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 |
}
|