The Blog Writing Agent analyzes your existing articles to learn your unique writing style, then generates new blog posts that sound exactly like you. Built with Digital Ocean AI and GibsonAI Memori, this agent provides persistent style memory across sessions.
import pypdffrom docx import Documentdef extract_text_from_pdf(pdf_file) -> str: """Extract text from PDF file.""" pdf_reader = pypdf.PdfReader(pdf_file) text = "" for page in pdf_reader.pages: text += page.extract_text() + "\n" return textdef extract_text_from_docx(docx_file) -> str: """Extract text from DOCX file.""" doc = Document(docx_file) text = "" for paragraph in doc.paragraphs: text += paragraph.text + "\n" return textdef extract_text_from_txt(txt_file) -> str: """Extract text from TXT file.""" return txt_file.read().decode("utf-8")
from openai import OpenAIimport json# Initialize Digital Ocean AI clientclient = OpenAI( base_url=f"{DIGITAL_OCEAN_ENDPOINT}/api/v1/", api_key=DIGITAL_OCEAN_AGENT_ACCESS_KEY,)def analyze_writing_style(text: str) -> dict: """Analyze writing style using Digital Ocean AI.""" prompt = f""" Analyze the following text and extract the author's writing style characteristics. Focus on: 1. Tone (formal, casual, professional, friendly, etc.) 2. Writing structure (how paragraphs are organized, transitions, etc.) 3. Vocabulary level and complexity 4. Sentence structure patterns 5. Use of examples, analogies, or storytelling 6. Overall voice and personality Text to analyze: {text[:3000]} # Limit to first 3000 characters Provide your analysis in JSON format with these keys: - tone: string describing the tone - structure: string describing paragraph and content structure - vocabulary: string describing vocabulary level and style - sentence_patterns: string describing sentence structure - examples_style: string describing how examples/analogies are used - voice: string describing overall voice/personality - writing_habits: list of specific writing habits or patterns """ response = client.chat.completions.create( model="n/a", # Digital Ocean agent endpoint messages=[ { "role": "system", "content": "You are an expert writing analyst." }, {"role": "user", "content": prompt} ], temperature=0.3, ) # Extract JSON from response analysis_text = response.choices[0].message.content if "```json" in analysis_text: json_start = analysis_text.find("```json") + 7 json_end = analysis_text.find("```", json_start) json_content = analysis_text[json_start:json_end].strip() else: json_start = analysis_text.find("{") json_end = analysis_text.rfind("}") + 1 json_content = analysis_text[json_start:json_end] return json.loads(json_content)
def store_writing_style_in_memori( memory_system, style_analysis: dict, original_text: str): """Store writing style analysis in Memori as a conversation.""" # Create a conversation about the writing style user_input = f""" Hi AI, here is my writing style: {style_analysis.get('tone', 'N/A')} tone, {style_analysis.get('voice', 'N/A')} voice, {style_analysis.get('structure', 'N/A')} structure, {style_analysis.get('vocabulary', 'N/A')} vocabulary, and {len(style_analysis.get('writing_habits', []))} writing habits. """ ai_response = f""" I understand your writing style! You write with a {style_analysis.get('tone', 'N/A')} tone and {style_analysis.get('voice', 'N/A')} voice. Your structure is {style_analysis.get('structure', 'N/A')} and you use {style_analysis.get('vocabulary', 'N/A')} vocabulary. I'll use this to write content that sounds exactly like you. """ # Record in Memori memory_system.record_conversation( user_input=user_input, ai_output=ai_response, model="n/a", metadata={ "type": "writing_style_profile", "style_data": style_analysis, "text_length": len(original_text), "analysis_timestamp": "now", }, ) return ai_response
def generate_blog_with_style(memory_tool, topic: str) -> str: """Generate blog content using stored writing style.""" # Retrieve writing style from memory writing_style_context = "" try: context_result = memory_tool.execute(query="writing style") if context_result and "No relevant memories found" not in str(context_result): writing_style_context = str(context_result)[:300] except Exception: pass # Create prompt with style context if writing_style_context: prompt = f"Write a blog post about {topic}. Use this writing style: {writing_style_context}" else: prompt = f"Write a professional and engaging blog post about {topic}." response = client.chat.completions.create( model="n/a", messages=[{"role": "user", "content": prompt}], temperature=0.7, max_tokens=2000, ) return response.choices[0].message.content
import streamlit as stst.title("AI Blog Writing Agent")# Sidebar: Knowledge Agent for style analysiswith st.sidebar: st.header("π Knowledge Agent") uploaded_file = st.file_uploader( "Upload your article (PDF, DOCX, TXT)", type=["pdf", "docx", "txt"] ) if uploaded_file and st.button("π Analyze Writing Style"): # Extract text based on file type if uploaded_file.type == "application/pdf": text = extract_text_from_pdf(uploaded_file) elif uploaded_file.type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document": text = extract_text_from_docx(uploaded_file) else: text = extract_text_from_txt(uploaded_file) # Analyze style with st.spinner("Analyzing your writing style..."): style_analysis = analyze_writing_style(text) # Store in Memori memory_system = initialize_memori() store_writing_style_in_memori(memory_system, style_analysis, text) st.success("β Writing style analyzed and stored!") st.json(style_analysis)# Main area: Writing Agentst.header("βοΈ Writing Agent")topic = st.chat_input("What would you like to write about?")if topic: with st.spinner("Generating blog post..."): memory_system = initialize_memori() memory_tool = create_memory_tool(memory_system) # Generate content blog_content = generate_blog_with_style(memory_tool, topic) st.markdown(blog_content) # Download button st.download_button( "Download Blog Post", blog_content, file_name="blog_post.md", mime="text/markdown" )