personalised blog
Browse files- __pycache__/app.cpython-312.pyc +0 -0
- app.py +39 -7
- style_guide.yaml +36 -0
- test_research.py +11 -0
- tools/__pycache__/blog_tools.cpython-312.pyc +0 -0
- tools/blog_tools.py +44 -8
__pycache__/app.cpython-312.pyc
CHANGED
|
Binary files a/__pycache__/app.cpython-312.pyc and b/__pycache__/app.cpython-312.pyc differ
|
|
|
app.py
CHANGED
|
@@ -9,7 +9,7 @@ from Gradio_UI import GradioUI
|
|
| 9 |
|
| 10 |
@tool
|
| 11 |
def generate_blog_outline(topic: str) -> str:
|
| 12 |
-
"""Creates a structured outline for a blog post
|
| 13 |
Args:
|
| 14 |
topic: The main topic for the blog post
|
| 15 |
"""
|
|
@@ -17,7 +17,7 @@ def generate_blog_outline(topic: str) -> str:
|
|
| 17 |
|
| 18 |
@tool
|
| 19 |
def suggest_blog_topics(main_theme: str) -> str:
|
| 20 |
-
"""Suggests related blog topics based on a theme
|
| 21 |
Args:
|
| 22 |
main_theme: The primary theme or area of interest
|
| 23 |
"""
|
|
@@ -36,11 +36,34 @@ def get_current_time_in_timezone(timezone: str) -> str:
|
|
| 36 |
except Exception as e:
|
| 37 |
return f"Error fetching time for timezone '{timezone}': {str(e)}"
|
| 38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
final_answer = FinalAnswerTool()
|
| 40 |
|
| 41 |
model = HfApiModel(
|
| 42 |
max_tokens=2096,
|
| 43 |
-
temperature=0.
|
| 44 |
model_id='Qwen/Qwen2.5-Coder-32B-Instruct',
|
| 45 |
custom_role_conversions=None,
|
| 46 |
)
|
|
@@ -48,6 +71,9 @@ model = HfApiModel(
|
|
| 48 |
with open("prompts.yaml", 'r') as stream:
|
| 49 |
prompt_templates = yaml.safe_load(stream)
|
| 50 |
|
|
|
|
|
|
|
|
|
|
| 51 |
agent = CodeAgent(
|
| 52 |
model=model,
|
| 53 |
tools=[
|
|
@@ -58,14 +84,20 @@ agent = CodeAgent(
|
|
| 58 |
generate_blog_section,
|
| 59 |
improve_writing_style,
|
| 60 |
check_readability,
|
| 61 |
-
generate_seo_metadata
|
|
|
|
| 62 |
],
|
| 63 |
-
max_steps=
|
| 64 |
verbosity_level=1,
|
| 65 |
grammar=None,
|
| 66 |
planning_interval=None,
|
| 67 |
-
name="
|
| 68 |
-
description="An
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
)
|
| 70 |
|
| 71 |
GradioUI(agent).launch()
|
|
|
|
| 9 |
|
| 10 |
@tool
|
| 11 |
def generate_blog_outline(topic: str) -> str:
|
| 12 |
+
"""Creates a structured outline for a blog post with a direct, practical approach
|
| 13 |
Args:
|
| 14 |
topic: The main topic for the blog post
|
| 15 |
"""
|
|
|
|
| 17 |
|
| 18 |
@tool
|
| 19 |
def suggest_blog_topics(main_theme: str) -> str:
|
| 20 |
+
"""Suggests related blog topics based on a theme, drawing from AI product expertise
|
| 21 |
Args:
|
| 22 |
main_theme: The primary theme or area of interest
|
| 23 |
"""
|
|
|
|
| 36 |
except Exception as e:
|
| 37 |
return f"Error fetching time for timezone '{timezone}': {str(e)}"
|
| 38 |
|
| 39 |
+
@tool
|
| 40 |
+
def research_topic(query: str) -> str:
|
| 41 |
+
"""Searches the web for information about a specific topic and returns relevant sources
|
| 42 |
+
Args:
|
| 43 |
+
query: The topic to research
|
| 44 |
+
"""
|
| 45 |
+
try:
|
| 46 |
+
# Create a fresh instance for each search
|
| 47 |
+
search_tool = DuckDuckGoSearchTool(max_results=5)
|
| 48 |
+
|
| 49 |
+
# Add focus on tech and AI product development
|
| 50 |
+
enhanced_query = f"{query} AI product development tech industry"
|
| 51 |
+
results = search_tool.forward(enhanced_query)
|
| 52 |
+
|
| 53 |
+
# Format the results in your style
|
| 54 |
+
response = f"Here's what I found about {query}:\n\n"
|
| 55 |
+
response += results
|
| 56 |
+
response += "\n\nNote: These findings are current as of my research. Tech moves fast, so double-check anything critical."
|
| 57 |
+
|
| 58 |
+
return response
|
| 59 |
+
except Exception as e:
|
| 60 |
+
return f"Error performing research: {str(e)}"
|
| 61 |
+
|
| 62 |
final_answer = FinalAnswerTool()
|
| 63 |
|
| 64 |
model = HfApiModel(
|
| 65 |
max_tokens=2096,
|
| 66 |
+
temperature=0.7, # Slightly increased for more natural, conversational tone
|
| 67 |
model_id='Qwen/Qwen2.5-Coder-32B-Instruct',
|
| 68 |
custom_role_conversions=None,
|
| 69 |
)
|
|
|
|
| 71 |
with open("prompts.yaml", 'r') as stream:
|
| 72 |
prompt_templates = yaml.safe_load(stream)
|
| 73 |
|
| 74 |
+
with open("style_guide.yaml", 'r') as stream:
|
| 75 |
+
style_guide = yaml.safe_load(stream)
|
| 76 |
+
|
| 77 |
agent = CodeAgent(
|
| 78 |
model=model,
|
| 79 |
tools=[
|
|
|
|
| 84 |
generate_blog_section,
|
| 85 |
improve_writing_style,
|
| 86 |
check_readability,
|
| 87 |
+
generate_seo_metadata,
|
| 88 |
+
research_topic
|
| 89 |
],
|
| 90 |
+
max_steps=15,
|
| 91 |
verbosity_level=1,
|
| 92 |
grammar=None,
|
| 93 |
planning_interval=None,
|
| 94 |
+
name="Joséphine's Blog Assistant",
|
| 95 |
+
description="""An AI writing assistant that matches Joséphine's style:
|
| 96 |
+
- Direct and conversational tone
|
| 97 |
+
- Product and AI expertise focus
|
| 98 |
+
- Clear, practical insights
|
| 99 |
+
- Natural, professional voice
|
| 100 |
+
- Gets to the point quickly"""
|
| 101 |
)
|
| 102 |
|
| 103 |
GradioUI(agent).launch()
|
style_guide.yaml
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
writing_style:
|
| 2 |
+
tone:
|
| 3 |
+
- Direct and conversational
|
| 4 |
+
- Personal yet professional
|
| 5 |
+
- Authentic and genuine
|
| 6 |
+
- No AI clichés (avoid words like "effortlessly", "unleash", "power")
|
| 7 |
+
|
| 8 |
+
sentence_structure:
|
| 9 |
+
- Short, clear sentences
|
| 10 |
+
- Natural flow
|
| 11 |
+
- Light use of parentheticals for context
|
| 12 |
+
- Avoid overly formal language
|
| 13 |
+
|
| 14 |
+
content_approach:
|
| 15 |
+
- Get to the point quickly
|
| 16 |
+
- Focus on practical insights
|
| 17 |
+
- Draw from product and AI experience
|
| 18 |
+
- Include relevant tech context when helpful
|
| 19 |
+
|
| 20 |
+
author_profile:
|
| 21 |
+
name: "Joséphine"
|
| 22 |
+
expertise:
|
| 23 |
+
- Product leadership in AI
|
| 24 |
+
- Scaling AI products and platforms
|
| 25 |
+
- Image, 3D, and audio generation
|
| 26 |
+
- B2C applications and APIs
|
| 27 |
+
|
| 28 |
+
background:
|
| 29 |
+
- Business management
|
| 30 |
+
- 4+ years in tech
|
| 31 |
+
- Current: Stability AI product lead
|
| 32 |
+
|
| 33 |
+
interests:
|
| 34 |
+
- Building and testing new AI products
|
| 35 |
+
- Innovation in tech
|
| 36 |
+
- Meeting new people and exchanging ideas
|
test_research.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from app import agent
|
| 2 |
+
|
| 3 |
+
def test_research():
|
| 4 |
+
# Test the research capability
|
| 5 |
+
print("Researching AI in Healthcare...")
|
| 6 |
+
research_results = agent.run("Research recent developments in AI medical diagnosis and provide sources")
|
| 7 |
+
print("\nResearch Results:")
|
| 8 |
+
print(research_results)
|
| 9 |
+
|
| 10 |
+
if __name__ == "__main__":
|
| 11 |
+
test_research()
|
tools/__pycache__/blog_tools.cpython-312.pyc
CHANGED
|
Binary files a/tools/__pycache__/blog_tools.cpython-312.pyc and b/tools/__pycache__/blog_tools.cpython-312.pyc differ
|
|
|
tools/blog_tools.py
CHANGED
|
@@ -1,19 +1,50 @@
|
|
| 1 |
from smolagents import tool
|
| 2 |
from typing import List, Dict
|
| 3 |
import re
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
@tool
|
| 6 |
def generate_blog_section(topic: str, section_title: str) -> str:
|
| 7 |
-
"""Generates content for a specific section of the blog post
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
Args:
|
| 9 |
topic: The main topic of the blog post
|
| 10 |
section_title: The title of the section to generate
|
| 11 |
"""
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
@tool
|
| 15 |
def improve_writing_style(text: str, style: str = "professional") -> str:
|
| 16 |
-
"""Improves the writing style
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
Args:
|
| 18 |
text: The text to improve
|
| 19 |
style: The desired writing style (e.g., professional, casual, academic)
|
|
@@ -22,11 +53,15 @@ def improve_writing_style(text: str, style: str = "professional") -> str:
|
|
| 22 |
|
| 23 |
@tool
|
| 24 |
def check_readability(text: str) -> Dict:
|
| 25 |
-
"""Analyzes the readability of the text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
Args:
|
| 27 |
text: The text to analyze
|
| 28 |
"""
|
| 29 |
-
# Simple implementation - you can make this more sophisticated
|
| 30 |
words = len(text.split())
|
| 31 |
sentences = len(re.split(r'[.!?]+', text))
|
| 32 |
avg_words_per_sentence = words / max(sentences, 1)
|
|
@@ -35,18 +70,19 @@ def check_readability(text: str) -> Dict:
|
|
| 35 |
"word_count": words,
|
| 36 |
"sentence_count": sentences,
|
| 37 |
"avg_words_per_sentence": avg_words_per_sentence,
|
| 38 |
-
"readability_score": "Good" if avg_words_per_sentence <
|
|
|
|
| 39 |
}
|
| 40 |
|
| 41 |
@tool
|
| 42 |
def generate_seo_metadata(title: str, content: str) -> Dict:
|
| 43 |
-
"""Generates SEO metadata
|
| 44 |
Args:
|
| 45 |
title: The blog post title
|
| 46 |
content: The blog post content
|
| 47 |
"""
|
| 48 |
return {
|
| 49 |
-
"meta_description": f"
|
| 50 |
"keywords": [word.lower() for word in title.split()],
|
| 51 |
"suggested_title_tags": [f"<h1>{title}</h1>"]
|
| 52 |
}
|
|
|
|
| 1 |
from smolagents import tool
|
| 2 |
from typing import List, Dict
|
| 3 |
import re
|
| 4 |
+
import yaml
|
| 5 |
+
from app import DuckDuckGoSearchTool
|
| 6 |
+
|
| 7 |
+
# Load style guide
|
| 8 |
+
with open("style_guide.yaml", 'r') as f:
|
| 9 |
+
style_guide = yaml.safe_load(f)
|
| 10 |
|
| 11 |
@tool
|
| 12 |
def generate_blog_section(topic: str, section_title: str) -> str:
|
| 13 |
+
"""Generates content for a specific section of the blog post, following Joséphine's style:
|
| 14 |
+
- Direct and conversational tone
|
| 15 |
+
- Short, clear sentences
|
| 16 |
+
- Personal but professional
|
| 17 |
+
- Draws from AI product experience when relevant
|
| 18 |
+
|
| 19 |
Args:
|
| 20 |
topic: The main topic of the blog post
|
| 21 |
section_title: The title of the section to generate
|
| 22 |
"""
|
| 23 |
+
# First, get some background information
|
| 24 |
+
search_tool = DuckDuckGoSearchTool(max_results=3)
|
| 25 |
+
try:
|
| 26 |
+
search_query = f"{topic} {section_title}"
|
| 27 |
+
research = search_tool.forward(search_query)
|
| 28 |
+
|
| 29 |
+
# Format the content in your style
|
| 30 |
+
content = f"# {section_title}\n\n"
|
| 31 |
+
content += f"Let me share my perspective on {topic} (specifically {section_title}). "
|
| 32 |
+
content += f"Based on my experience in scaling AI products and recent developments:\n\n"
|
| 33 |
+
content += f"{research}\n\n"
|
| 34 |
+
content += "I'll keep updating this as I learn more. Let me know if you'd like to discuss any specific aspects."
|
| 35 |
+
|
| 36 |
+
return content
|
| 37 |
+
except Exception as e:
|
| 38 |
+
return f"Error generating content: {str(e)}"
|
| 39 |
|
| 40 |
@tool
|
| 41 |
def improve_writing_style(text: str, style: str = "professional") -> str:
|
| 42 |
+
"""Improves the writing style while maintaining Joséphine's voice:
|
| 43 |
+
- Keeps direct, conversational tone
|
| 44 |
+
- Removes AI clichés
|
| 45 |
+
- Ensures natural flow
|
| 46 |
+
- Maintains authenticity
|
| 47 |
+
|
| 48 |
Args:
|
| 49 |
text: The text to improve
|
| 50 |
style: The desired writing style (e.g., professional, casual, academic)
|
|
|
|
| 53 |
|
| 54 |
@tool
|
| 55 |
def check_readability(text: str) -> Dict:
|
| 56 |
+
"""Analyzes the readability of the text, focusing on:
|
| 57 |
+
- Sentence length and clarity
|
| 58 |
+
- Natural flow
|
| 59 |
+
- Direct communication
|
| 60 |
+
- Professional but personal tone
|
| 61 |
+
|
| 62 |
Args:
|
| 63 |
text: The text to analyze
|
| 64 |
"""
|
|
|
|
| 65 |
words = len(text.split())
|
| 66 |
sentences = len(re.split(r'[.!?]+', text))
|
| 67 |
avg_words_per_sentence = words / max(sentences, 1)
|
|
|
|
| 70 |
"word_count": words,
|
| 71 |
"sentence_count": sentences,
|
| 72 |
"avg_words_per_sentence": avg_words_per_sentence,
|
| 73 |
+
"readability_score": "Good" if avg_words_per_sentence < 15 else "Consider shorter sentences",
|
| 74 |
+
"style_notes": "Check for direct tone and clear communication"
|
| 75 |
}
|
| 76 |
|
| 77 |
@tool
|
| 78 |
def generate_seo_metadata(title: str, content: str) -> Dict:
|
| 79 |
+
"""Generates SEO metadata while maintaining authentic voice
|
| 80 |
Args:
|
| 81 |
title: The blog post title
|
| 82 |
content: The blog post content
|
| 83 |
"""
|
| 84 |
return {
|
| 85 |
+
"meta_description": f"A practical look at {title}",
|
| 86 |
"keywords": [word.lower() for word in title.split()],
|
| 87 |
"suggested_title_tags": [f"<h1>{title}</h1>"]
|
| 88 |
}
|