Streamlit Reddit Integration
2025-02-037 turns41,333 charsgpt-4o
Summary
Debugging Streamlit app integration with Reddit API that throws uncaught exceptions during execution.
Messages
--- /Users/danielkliewer/RedToBlog01/requirements.txt ---
networkx
requests
praw
python-dotenv
streamlit==1.25.0
--- /Users/danielkliewer/RedToBlog01/.gitattributes ---
# Auto detect text files and perform LF normalization
* text=auto
--- /Users/danielkliewer/RedToBlog01/.gitattributes copy ---
# Auto detect text files and perform LF normalization
* text=auto
--- /Users/danielkliewer/RedToBlog01/main.py ---
import os
import requests
import json
from datetime import datetime
import networkx as nx
from dotenv import load_dotenv
from utils.base_agent import BaseAgent
from agents.final_agent import FinalAgent
from agents.analyze import AnalyzeAgent
from agents.expand import ExpandAgent
from utils.reddit_fetch import RedditMonitor
from agents.metric_generate import MetricAgent
def write_to_file(prompt, filename='output.txt'):
with open(filename, 'a') as f:
f.write("=== Iteration Output ===\n")
f.write("Message:\n")
f.write(prompt.get('message', '') + "\n\n")
def main():
load_dotenv()
# Initialize Reddit monitor
reddit_monitor = RedditMonitor()
if not reddit_monitor.username:
logging.error("Reddit authentication failed. Exiting application.")
return
reddit_content = reddit_monitor.fetch_all_recent_activity(limit=4)
print(f"Fetched {len(reddit_content)} recent posts and comments.")
# Initialize agents
agents = {
'Expand': ExpandAgent(),
'Analyze': AnalyzeAgent(),
'Metric': MetricAgent(),
'Final': FinalAgent()
}
# Create a directed graph to model the flow of data between agents
G = nx.DiGraph()
# Add nodes
G.add_nodes_from(agents.keys())
# Define edges to represent the flow between agents
G.add_edges_from([
('Expand', 'Analyze'),
('Analyze', 'Metric'),
('Metric', 'Final'),
('Expand', 'Final'),
('Analyze', 'Final'),
('Metric', 'Final')
])
# Initial prompt
prompt = {'message': reddit_content}
iteration = 0
max_iterations = 1 # Safety limit to prevent infinite loops
is_complete = False
while iteration < max_iterations and not is_complete:
iteration += 1
print(f"--- Iteration {iteration} ---")
# Process the prompt through the agents according to the graph
for node in nx.topological_sort(G):
if node != 'Final':
agent = agents[node]
try:
print(f"Processing with {node}Agent")
prompt = agent.process(prompt)
write_to_file(prompt)
except Exception as e:
logging.error(f"An error occurred in {node}Agent: {e}")
return
else:
# Check completion with the FinalAgent
is_complete = agents['Final'].process(prompt)
print("Process is complete." if is_complete else "Continuing to next iteration.")
if not is_complete:
print("Reached maximum iterations without completion. Saving current progress.")
# Save the final output
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"final_output_{timestamp}.txt"
with open(filename, 'w') as f:
f.write(f"Final Output ({timestamp}):\n\n")
f.write("Message:\n")
f.write(prompt.get('message', '') + "\n\n")
print(f"Final progress has been saved to {filename}.")
if __name__ == "__main__":
main()
--- /Users/danielkliewer/RedToBlog01/agents/metric_generate.py ---
import os
import re
from datetime import datetime
import requests
import json
from utils.base_agent import BaseAgent
class MetricAgent(BaseAgent):
def __init__(self):
super().__init__()
self.endpoint = "http://localhost:11434/api/generate"
def process(self, message, code="", readme=""):
# Ensure `message` is a string
message_str = message if isinstance(message, str) else str(message)
# Prepare the payload
data = {
"model": self.model,
"prompt": f"""Using this analysis: {message_str} Analyze the previous content and create a JSON object that contains the following structured data:
{{
"psychological_profile": {{
"emotional_tone": {{
"description": "Analyzed sentiment of the text.",
"type": "string",
"values": ["Positive", "Neutral", "Negative"]
}},
"dominant_emotion": {{
"description": "Primary emotion conveyed in the text.",
"type": "string",
"values": ["Joy", "Anger", "Sadness", "Fear", "Surprise", "Disgust", "Neutral"]
}},
"cognitive_complexity": {{
"description": "Measures depth of thought and abstraction in the writing.",
"type": "integer",
"range": [1, 10]
}},
"openness_to_experience": {{
"description": "Determines the level of curiosity, creativity, and intellectual engagement.",
"type": "integer",
"range": [1, 10]
}},
"conscientiousness": {{
"description": "Assesses organization, discipline, and thoroughness in writing.",
"type": "integer",
"range": [1, 10]
}},
"extraversion": {{
"description": "Measures social engagement, enthusiasm, and talkativeness.",
"type": "integer",
"range": [1, 10]
}},
"agreeableness": {{
"description": "Evaluates friendliness, cooperativeness, and empathy.",
"type": "integer",
"range": [1, 10]
}},
"neuroticism": {{
"description": "Measures emotional stability and tendency toward negative emotions.",
"type": "integer",
"range": [1, 10]
}},
"confidence_level": {{
"description": "Indicates certainty vs. doubt in statements.",
"type": "integer",
"range": [1, 10]
}},
"formality_of_writing": {{
"description": "Measures the degree of structured and professional tone.",
"type": "integer",
"range": [1, 10]
}},
"self_reference_frequency": {{
"description": "Percentage of words that are self-referential (e.g., 'I', 'me', 'my').",
"type": "float",
"unit": "percentage"
}},
"use_of_technical_jargon": {{
"description": "Percentage of words that are domain-specific technical terms.",
"type": "float",
"unit": "percentage"
}},
"hedging_language": {{
"description": "Percentage of words or phrases that indicate uncertainty (e.g., 'might', 'perhaps').",
"type": "float",
"unit": "percentage"
}},
"persuasive_language": {{
"description": "Measures the use of rhetorical devices and argumentation strategies.",
"type": "integer",
"range": [1, 10]
}},
"optimism_vs_pessimism": {{
"description": "Determines the outlook on future events.",
"type": "string",
"values": ["Optimistic", "Neutral", "Pessimistic"]
}},
"problem_solving_orientation": {{
"description": "Identifies structured attempts to resolve issues.",
"type": "integer",
"range": [1, 10]
}},
"ambiguity_vs_specificity": {{
"description": "Measures precision and clarity of language.",
"type": "integer",
"range": [1, 10]
}},
"use_of_metaphors_analogies": {{
"description": "Percentage of words that are metaphors or analogies.",
"type": "float",
"unit": "percentage"
}},
"intensity_of_emotion": {{
"description": "Measures the expressiveness and strength of emotions conveyed.",
"type": "integer",
"range": [1, 10]
}},
"frequency_of_humor_or_sarcasm": {{
"description": "Measures humor or sarcasm usage.",
"type": "integer",
"range": [1, 10]
}},
"use_of_imperatives": {{
"description": "Percentage of sentences that contain commands or directives.",
"type": "float",
"unit": "percentage"
}},
"introspective_vs_external_focus": {{
"description": "Classifies whether the writing is focused on personal experience or external topics.",
"type": "string",
"values": ["Introspective", "Balanced", "External"]
}},
"risk_aversion": {{
"description": "Measures cautious vs. risk-taking tendencies.",
"type": "integer",
"range": [1, 10]
}},
"resilience_language": {{
"description": "Detects expressions of perseverance and adaptability.",
"type": "integer",
"range": [1, 10]
}},
"use_of_collective_language": {{
"description": "Percentage of words indicating group affiliation (e.g., 'we', 'us').",
"type": "float",
"unit": "percentage"
}}
}},
"programming_metrics": {{
"main_programming_topic": {{
"description": "Primary area of discussion in programming content.",
"type": "string"
}},
"programming_languages_mentioned": {{
"description": "List of programming languages referenced.",
"type": "array",
"items": "string"
}},
"frameworks_and_libraries_mentioned": {{
"description": "List of frameworks and libraries referenced.",
"type": "array",
"items": "string"
}},
"problem_statement": {{
"description": "Brief description of the technical issue being discussed.",
"type": "string"
}},
"proposed_solution_complexity": {{
"description": "Evaluates depth of proposed solutions.",
"type": "integer",
"range": [1, 10]
}},
"use_of_design_patterns": {{
"description": "List of software design patterns mentioned.",
"type": "array",
"items": "string"
}},
"algorithmic_complexity_discussion": {{
"description": "Measures depth of algorithm-related discussion.",
"type": "integer",
"range": [1, 10]
}},
"performance_optimization_concerns": {{
"description": "Evaluates concerns about code performance.",
"type": "integer",
"range": [1, 10]
}},
"security_considerations": {{
"description": "Evaluates references to security best practices.",
"type": "integer",
"range": [1, 10]
}},
"scalability_discussion": {{
"description": "Measures discussion on handling large-scale applications.",
"type": "integer",
"range": [1, 10]
}},
"code_readability_consideration": {{
"description": "Evaluates emphasis on clean and readable code.",
"type": "integer",
"range": [1, 10]
}},
"testing_and_debugging_approaches": {{
"description": "List of mentioned testing and debugging techniques.",
"type": "array",
"items": "string"
}},
"tooling_and_environment_mentions": {{
"description": "List of development tools and environments mentioned.",
"type": "array",
"items": "string"
}},
"dependency_management_discussion": {{
"description": "List of dependency/package management tools mentioned.",
"type": "array",
"items": "string"
}},
"database_discussion": {{
"description": "Mentions of database technologies.",
"type": "string"
}},
"error_handling_strategies": {{
"description": "List of error-handling techniques discussed.",
"type": "array",
"items": "string"
}},
"ui_ux_considerations": {{
"description": "Measures emphasis on user experience and interface design.",
"type": "integer",
"range": [1, 10]
}},
"ethical_considerations_in_programming": {{
"description": "Evaluates discussions about ethical programming topics.",
"type": "integer",
"range": [1, 10]
}}
}}
}}
Return only the JSON object containing the psychological profile and programming metrics.
""",
"stream": False
}
try:
# Make the API request
response = requests.post(self.endpoint, json=data)
json_response = response.json()
# Extract the response content
design_spec = json_response.get('response', 'No response key in API result')
enhanced_message = f"{message_str}\n\n{design_spec}"
# Create simplified output with just the response
output_data = {
'response': design_spec
}
# Save just the response to a JSON file
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"metric_output_{timestamp}.json"
with open(filename, 'w') as json_file:
json.dump(output_data, json_file, indent=4)
return {
'message': enhanced_message
}
except requests.exceptions.RequestException as req_err:
print(f"Request error in MetricAgent: {str(req_err)}")
except Exception as e:
print(f"General error in MetricAgent: {str(e)}")
# Return the original message if an error occurs
return {
'message': message_str
}
--- /Users/danielkliewer/RedToBlog01/agents/process.py ---
import os
import re
from datetime import datetime
import requests
import json
from utils.base_agent import BaseAgent
class ProcessAgent(BaseAgent):
def __init__(self):
super().__init__()
self.endpoint = "http://localhost:11434/api/generate"
def _extract_json(self, text):
# Find JSON-like structure between curly braces
pattern = r'\{(?:[^{}]|(?R))*\}'
matches = re.findall(pattern, text, re.DOTALL)
if not matches:
return None
# Try each match until we find valid JSON
for match in matches:
try:
# Parse to validate and return first valid JSON
parsed = json.loads(match)
return match
except json.JSONDecodeError:
continue
return None
def process(self, message, code="", readme=""):
# Ensure `message` is a string
message_str = message if isinstance(message, str) else str(message)
# Prepare the payload
data = {
"model": self.model,
"prompt": f"""Using this analysis: ({message_str})""",
"stream": False
}
# Make the API request
response = requests.post(self.endpoint, json=data)
json_response = response.json()
json_result = self._extract_json(json_response)
if json_result:
return json_result
# Return the original message if an error occurs
return {'message': message_str}
--- /Users/danielkliewer/RedToBlog01/agents/final_agent.py ---
import os
import requests
import json
from utils.base_agent import BaseAgent
class FinalAgent(BaseAgent):
def __init__(self, model="default-model"):
super().__init__()
self.endpoint = "http://localhost:11434/api/generate"
self.model = model
def process(self, prompt):
message = prompt.get('message', '')
message_str = message if isinstance(message, str) else json.dumps(message, indent=2)
data = {
"model": self.model,
"prompt": f"""Using these metrics ({message_str}) generate a final report that combines the psychological profile and programming project outline into a single markdown document. The report should provide a comprehensive analysis of the Reddit user's psychological characteristics and propose a technical project inspired by the extracted programming ideas. The report should be well-structured, detailed, and insightful, combining both psychological and technical aspects into a coherent narrative.""",
"stream": False,
}
response = requests.post(self.endpoint, json=data)
json_response = response.json() # Parse JSON response
# Get the result from the response
result = json_response.get('response', 'No response from API')
enhanced_message = f"{message_str}\n\n{result}"
return {
'message': enhanced_message,
}
--- /Users/danielkliewer/RedToBlog01/agents/expand.py ---
import os
import requests
from utils.base_agent import BaseAgent
class ExpandAgent(BaseAgent):
def __init__(self):
super().__init__()
self.endpoint = "http://localhost:11434/api/generate"
def process(self, message, code="", readme=""):
# Convert message to string if it's a dict
message_str = message if isinstance(message, str) else str(message)
data = {
"model": self.model,
"prompt": f"""{message_str} Analyze the following content and extract the following values from the following keys:
Psychological Profile Extraction (Keys and Value Descriptions)
1. Emotional Tone – Analyzed sentiment of the text (positive, neutral, negative). (String: “Positive”, “Neutral”, “Negative”)
2. Dominant Emotion – Primary emotion conveyed (joy, anger, sadness, etc.). (String: “Joy”, “Anger”, “Sadness”, etc.)
3. Cognitive Complexity – Measures depth of thought and abstraction. (Number: Scale of 1-10, where 1 is simple and 10 is highly complex)
4. Openness to Experience – Determines level of curiosity and exploration. (Number: Scale of 1-10)
5. Conscientiousness – Assesses organization and discipline in the text. (Number: Scale of 1-10)
6. Extraversion – Measures social engagement or withdrawal. (Number: Scale of 1-10)
7. Agreeableness – Evaluates friendliness and cooperativeness. (Number: Scale of 1-10)
8. Neuroticism – Measures emotional stability. (Number: Scale of 1-10)
9. Confidence Level – Extracts indicators of certainty vs. doubt. (Number: Scale of 1-10)
10. Formality of Writing – Measures casual vs. structured writing. (Number: Scale of 1-10, where 1 is informal and 10 is highly formal)
11. Self-Reference Frequency – Counts first-person pronouns (I, me, my). (Number: Percentage of self-references per total words)
12. Use of Technical Jargon – Measures complexity of vocabulary. (Number: Percentage of technical terms per total words)
13. Hedging Language – Identifies uncertainty (e.g., “might,” “perhaps”). (Number: Percentage of hedging words per total words)
14. Persuasive Language – Detects argumentation strategies. (Number: Scale of 1-10, where 1 is neutral and 10 is highly persuasive)
15. Optimism vs. Pessimism – Determines future outlook in statements. (String: “Optimistic”, “Neutral”, “Pessimistic”)
16. Problem-Solving Orientation – Identifies structured problem resolution attempts. (Number: Scale of 1-10)
17. Ambiguity vs. Specificity – Measures how precise the language is. (Number: Scale of 1-10)
18. Use of Metaphors & Analogies – Detects abstract explanatory patterns. (Number: Percentage of metaphors per total words)
19. Intensity of Emotion – Measures emotional expressiveness. (Number: Scale of 1-10)
20. Frequency of Humor or Sarcasm – Identifies humorous intent. (Number: Scale of 1-10)
21. Use of Imperatives – Detects commands or direct instructions. (Number: Percentage of imperative sentences per total words)
22. Introspective vs. External Focus – Identifies whether the user talks about personal experience or external topics. (String: “Introspective”, “Balanced”, “External”)
23. Risk Aversion – Evaluates cautious vs. risk-taking tendencies. (Number: Scale of 1-10)
24. Resilience Language – Detects expressions of perseverance and adaptability. (Number: Scale of 1-10)
25. Use of Collective Language – Measures group affiliation (“we,” “us”). (Number: Percentage of collective pronouns per total words)
Programming Idea Extraction (Keys and Value Descriptions)
26. Main Programming Topic – Extracts the primary area of discussion. (String: “Web Development”, “Machine Learning”, “Databases”, etc.)
27. Programming Language Mentioned – Identifies the programming languages in use. (List of strings: [“Python”, “JavaScript”, etc.])
28. Frameworks and Libraries Mentioned – Extracts names of technologies used. (List of strings: [“React”, “Django”, etc.])
29. Problem Statement – Extracts the core technical issue being discussed. (String: Brief problem description)
30. Proposed Solution Complexity – Evaluates depth of proposed solutions. (Number: Scale of 1-10)
31. Use of Design Patterns – Identifies named software patterns. (List of strings: [“Singleton”, “Factory”, etc.])
32. Algorithmic Complexity Discussion – Measures technical depth of algorithm talk. (Number: Scale of 1-10)
33. Performance Optimization Concerns – Detects efficiency discussions. (Number: Scale of 1-10)
34. Security Considerations – Extracts references to security best practices. (Number: Scale of 1-10)
35. Scalability Discussion – Identifies concerns about large-scale applications. (Number: Scale of 1-10)
36. Code Readability Consideration – Extracts whether clarity is a focus. (Number: Scale of 1-10)
37. Testing and Debugging Approaches – Identifies methodologies used. (List of strings: [“Unit Tests”, “Debugging”, “CI/CD”])
38. Tooling and Environment Mentions – Extracts references to IDEs, linters, etc. (List of strings: [“VS Code”, “Docker”, etc.])
39. Dependency Management Discussion – Identifies package management strategies. (List of strings: [“pip”, “npm”, etc.])
40. Database Discussion – Extracts database-related topics. (String: “SQL”, “NoSQL”, “Graph Databases”)
41. Data Structure Mentions – Identifies key structures being discussed. (List of strings: [“Array”, “HashMap”, etc.])
42. Concurrency and Parallelism Concerns – Detects threading or async talk. (Number: Scale of 1-10)
43. API Design Discussion – Evaluates REST, GraphQL, or microservices mentions. (String: “REST”, “GraphQL”, “Microservices”)
44. Error Handling Strategies – Extracts how errors are managed. (List of strings: [“Try-Catch”, “Logging”, etc.])
45. Automated Deployment Mention – Identifies CI/CD pipeline discussions. (String: “Jenkins”, “GitHub Actions”, etc.)
46. UI/UX Considerations – Detects front-end usability discussions. (Number: Scale of 1-10)
47. Code Reusability Mentions – Extracts whether modularity is discussed. (Number: Scale of 1-10)
48. Project Management Methodologies – Identifies Agile, Scrum, etc. (List of strings: [“Agile”, “Scrum”, “Kanban”])
49. Collaboration and Open Source Involvement – Detects teamwork discussions. (Number: Scale of 1-10)
50. Ethical Considerations in Programming – Identifies discussions about responsible AI, privacy, etc. (Number: Scale of 1-10)""",
"stream": False
}
try:
response = requests.post(self.endpoint, json=data).json()
design_spec = response.get('response', '')
enhanced_message = f"{message_str}\n\n{design_spec}"
return {
'message': enhanced_message,
}
except Exception as e:
print(f"Error in ExpandAgent: {str(e)}")
return {
'message': message_str,
}
--- /Users/danielkliewer/RedToBlog01/agents/analyze.py ---
import os
import requests
from utils.base_agent import BaseAgent
class AnalyzeAgent(BaseAgent):
def __init__(self):
super().__init__()
self.endpoint = "http://localhost:11434/api/generate"
def process(self, message, code="", readme=""):
# Convert message to string if it's a dict
message_str = message if isinstance(message, str) else str(message)
data = {
"model": self.model,
"prompt": f"""({message_str}) You will receive structured Reddit content analysis data based on two main categories: **Psychological Profile Extraction** and **Programming Metrics Extraction**. Your task is to analyze the provided data according to the outlined metrics and generate two distinct markdown-formatted outputs:
6. **A Psychological Profile Report** – A detailed written analysis in markdown format describing the psychological characteristics of the Reddit user based on extracted metrics.
7. **A Programming Project Outline** – A structured markdown document detailing the technical discussion, extracted programming ideas, and an architecture overview of a potential project inspired by the extracted insights.
**Input Structure:**
The structured input data will contain two sections:
**1. Psychological Profile Extraction**
For each metric, the data will contain either a categorical label (e.g., "Positive", "Joy"), a numerical scale (1-10), or a percentage-based metric. These values should be used to construct a meaningful psychological analysis. The key attributes include:
• **Emotional Tone** (Positive, Neutral, Negative)
• **Dominant Emotion** (Joy, Anger, Sadness, etc.)
• **Cognitive Complexity** (1-10)
• **Openness to Experience** (1-10)
• **Conscientiousness** (1-10)
• **Extraversion** (1-10)
• **Agreeableness** (1-10)
• **Neuroticism** (1-10)
• **Confidence Level** (1-10)
• **Formality of Writing** (1-10)
• **Self-Reference Frequency** (Percentage)
• **Use of Technical Jargon** (Percentage)
• **Hedging Language** (Percentage)
• **Persuasive Language** (1-10)
• **Optimism vs. Pessimism** (Optimistic, Neutral, Pessimistic)
• **Problem-Solving Orientation** (1-10)
• **Ambiguity vs. Specificity** (1-10)
• **Use of Metaphors & Analogies** (Percentage)
• **Intensity of Emotion** (1-10)
• **Frequency of Humor or Sarcasm** (1-10)
• **Use of Imperatives** (Percentage)
• **Introspective vs. External Focus** (Introspective, Balanced, External)
• **Risk Aversion** (1-10)
• **Resilience Language** (1-10)
• **Use of Collective Language** (Percentage)
**2. Programming Metrics Extraction**
This section will contain structured data extracted from the programming-related discussion. Your task is to use these extracted elements to construct a markdown-formatted programming guide that outlines the technical topic, programming challenges, and a structured plan for a potential application. The extracted metrics include:
• **Main Programming Topic** (Web Development, Machine Learning, etc.)
• **Programming Language Mentioned** (List: Python, JavaScript, etc.)
• **Frameworks and Libraries Mentioned** (List: React, Django, etc.)
• **Problem Statement** (Brief description)
• **Proposed Solution Complexity** (1-10)
• **Use of Design Patterns** (List: Singleton, Factory, etc.)
• **Algorithmic Complexity Discussion** (1-10)
• **Performance Optimization Concerns** (1-10)
• **Security Considerations** (1-10)
• **Scalability Discussion** (1-10)
• **Code Readability Consideration** (1-10)
• **Testing and Debugging Approaches** (List: Unit Tests, Debugging, CI/CD)
• **Tooling and Environment Mentions** (List: VS Code, Docker, etc.)
• **Dependency Management Discussion** (List: pip, npm, etc.)
• **Database Discussion** (SQL, NoSQL, Graph Databases)
• **Data Structure Mentions** (List: Array, HashMap, etc.)
• **Concurrency and Parallelism Concerns** (1-10)
• **API Design Discussion** (REST, GraphQL, Microservices)
• **Error Handling Strategies** (List: Try-Catch, Logging, etc.)
• **Automated Deployment Mention** (Jenkins, GitHub Actions, etc.)
• **UI/UX Considerations** (1-10)
• **Code Reusability Mentions** (1-10)
• **Project Management Methodologies** (List: Agile, Scrum, Kanban)
• **Collaboration and Open Source Involvement** (1-10)
• **Ethical Considerations in Programming** (1-10)
**Expected Output Format:**
**1. Markdown-Formatted Psychological Profile Analysis**
Using the structured psychological metrics, generate a **detailed written analysis** in markdown format. This analysis should explain the psychological characteristics inferred from the data, provide insights into the author’s personality, and discuss key trends in their writing.
**2. Markdown-Formatted Programming Guide and Project Architecture**
Using the extracted programming metrics, generate a **structured markdown document** that contains:
• A high-level summary of the technical discussion.
• An identified **problem statement** based on the extracted programming concerns.
• A detailed **architecture overview** of a new project that could be developed based on the discussed ideas.
• Relevant **frameworks, libraries, and best practices** to be used.
• Considerations regarding **performance, security, scalability, and testing**.
**Guidelines for Generating the Output:**
• Ensure the **Psychological Profile Analysis** reads as a natural, well-structured assessment, using the extracted numerical and categorical data to describe key traits.
• The **Programming Guide** should be formatted with clear sections (e.g., Problem Statement, Proposed Solution, Architecture, Tools, Best Practices).
• Use appropriate **markdown formatting** with headings (#), subheadings (##), lists (-), and code blocks where necessary.
• The generated text should be structured as **a blog post** suitable for publication.""",
"stream": False
}
try:
response = requests.post(self.endpoint, json=data).json()
design_spec = response.get('response', '')
enhanced_message = f"{message_str}\n\n{design_spec}"
return {
'message': enhanced_message,
}
except Exception as e:
print(f"Error in AnalyzeAgent: {str(e)}")
return {
'message': message_str,
}
--- /Users/danielkliewer/RedToBlog01/utils/config.py ---
class ModelConfig:
# Change this variable to switch models
DEFAULT_MODEL = "gemma2:27b"
--- /Users/danielkliewer/RedToBlog01/utils/base_agent.py ---
from .config import ModelConfig
class BaseAgent:
def __init__(self):
self.endpoint = "http://localhost:11434/api/generate"
self.model = ModelConfig.DEFAULT_MODEL
--- /Users/danielkliewer/RedToBlog01/utils/reddit_fetch.py ---
import praw
import os
from dotenv import load_dotenv
# Configure logging
load_dotenv()
class RedditMonitor:
def __init__(self):
try:
self.reddit = praw.Reddit(
client_id=os.getenv("REDDIT_CLIENT_ID"),
client_secret=os.getenv("REDDIT_CLIENT_SECRET"),
user_agent=os.getenv("REDDIT_USER_AGENT"),
username=os.getenv("REDDIT_USERNAME"),
password=os.getenv("REDDIT_PASSWORD")
)
user = self.reddit.user.me()
if user is None:
raise ValueError("Authentication failed. Check your Reddit credentials.")
self.username = user.name
print(f"Authenticated as: {self.username}")
except Exception as e:
print(f"Error during Reddit authentication: {e}")
self.username = None
def fetch_recent_posts(self, limit=10):
if not self.username:
print("Cannot fetch posts: User is not authenticated.")
return []
user = self.reddit.redditor(self.username)
posts = []
try:
for submission in user.submissions.new(limit=limit):
posts.append({
"type": "post",
"title": submission.title,
"selftext": submission.selftext,
"created_utc": submission.created_utc,
"url": submission.url
})
except Exception as e:
print(f"Error fetching posts: {e}")
return posts
def fetch_recent_comments(self, limit=10):
if not self.username:
print("Cannot fetch comments: User is not authenticated.")
return []
user = self.reddit.redditor(self.username)
comments = []
try:
for comment in user.comments.new(limit=limit):
comments.append({
"type": "comment",
"body": comment.body,
"created_utc": comment.created_utc,
"link_id": comment.link_id
})
except Exception as e:
print(f"Error fetching comments: {e}")
return comments
def fetch_all_recent_activity(self, limit=20):
posts = self.fetch_recent_posts(limit)
comments = self.fetch_recent_comments(limit)
total = posts + comments
return total
--------Write a prompt which will instruct an LLM to do the following and then execute that prompt:
Add the following functionality to this program ----
Streamlit frontend that takes the metrics generated as well as the final blog output and displays both as well as saving each generated output for future retrieval perhaps use a database instead of simply storing the metrics in JSON so they are easily altered and changed
Here's a prompt for the LLM to modify your program accordingly:
**Prompt:**
"Modify the existing Python program to add a Streamlit frontend that displays both the generated psychological metrics and the final blog output. Ensure that each generated output is stored in a database (e.g., SQLite or PostgreSQL) for future retrieval, instead of just saving metrics as JSON. The Streamlit app should have the following features:
1. **Input Section**: Allow the user to trigger content processing manually.
2. **Metrics Display**: Show the structured psychological and programming-related metrics in an easy-to-read format.
3. **Final Blog Display**: Render the blog-style report generated from the extracted data.
4. **History Retrieval**: Let users browse previous outputs stored in the database.
5. **Edit & Save Functionality**: Allow modification of stored metrics before finalizing the blog output.
6. **Database Integration**: Use SQLite or PostgreSQL to persist outputs, allowing them to be queried or updated later.
Implement the necessary changes in the backend to store and retrieve structured data, ensuring seamless integration between the agents and the frontend."
---
Now I'll generate the required modifications to your code to integrate this functionality.
gpt-4o
This code integrates a Streamlit frontend with a SQLite database, allowing users to trigger analysis, display metrics, save results, and browse historical outputs. Let me know if you need enhancements! 🚀
gpt-4o
Processing with ExpandAgent
Processing with AnalyzeAgent
Processing with MetricAgent
Process is complete.
Final progress has been saved to final_output_20250203_093352.txt.
2025-02-03 09:33:52.724 Uncaught app exception
Traceback (most recent call last):
File "/Users/danielkliewer/RedToBlog01/venv/lib/python3.10/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 552, in _run_script
exec(code, module.__dict__)
File "/Users/danielkliewer/RedToBlog01/frontend.py", line 43, in <module>
metrics = output.get("metrics", {})
AttributeError: 'NoneType' object has no attribute 'get'
The error is occurring because `main()` is returning `None`, causing `output.get("metrics", {})` to fail. This likely means `main()` is not returning a dictionary as expected.
### Fix:
Modify `main()` in **main.py** to ensure it returns the necessary data. Update the end of `main()` to something like this:
```python
def main():
load_dotenv()
reddit_monitor = RedditMonitor()
if not reddit_monitor.username:
logging.error("Reddit authentication failed. Exiting application.")
return None # Return None explicitly on failure
reddit_content = reddit_monitor.fetch_all_recent_activity(limit=4)
print(f"Fetched {len(reddit_content)} recent posts and comments.")
agents = {
'Expand': ExpandAgent(),
'Analyze': AnalyzeAgent(),
'Metric': MetricAgent(),
'Final': FinalAgent()
}
G = nx.DiGraph()
G.add_edges_from([
('Expand', 'Analyze'),
('Analyze', 'Metric'),
('Metric', 'Final'),
('Expand', 'Final'),
('Analyze', 'Final'),
('Metric', 'Final')
])
prompt = {'message': reddit_content}
iteration = 0
max_iterations = 1
is_complete = False
while iteration < max_iterations and not is_complete:
iteration += 1
for node in nx.topological_sort(G):
if node != 'Final':
agent = agents[node]
try:
prompt = agent.process(prompt)
except Exception as e:
logging.error(f"Error in {node}Agent: {e}")
return None # Handle errors safely
else:
is_complete = agents['Final'].process(prompt)
# Save output
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"final_output_{timestamp}.txt"
with open(filename, 'w') as f:
f.write(prompt.get('message', '') + "\n\n")
return { # Ensure it returns a dict
"metrics": prompt.get("metrics", {}),
"final_blog": prompt.get("message", "")
}
```
Now, `main()` always returns a dictionary, preventing the `AttributeError`. Restart the Streamlit app after making this change. 🚀
gpt-4o
2025-02-03 09:37:43.334 Uncaught app exception
Traceback (most recent call last):
File "/Users/danielkliewer/RedToBlog01/venv/lib/python3.10/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 552, in _run_script
exec(code, module.__dict__)
File "/Users/danielkliewer/RedToBlog01/frontend.py", line 50, in <module>
results = fetch_history()
File "/Users/danielkliewer/RedToBlog01/frontend.py", line 33, in fetch_history
cursor.execute("SELECT id, timestamp, metrics, final_blog FROM results ORDER BY id DESC")
sqlite3.OperationalError: no such table: results
Authenticated as: KonradFreeman
Fetched 8 recent posts and comments.
--- Iteration 1 ---
Processing with ExpandAgent
Processing with AnalyzeAgent
Processing with MetricAgent
Process is complete.
Final progress has been saved to final_output_20250203_094155.txt.
2025-02-03 09:41:55.467 Uncaught app exception
Traceback (most recent call last):
File "/Users/danielkliewer/RedToBlog01/venv/lib/python3.10/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 552, in _run_script
exec(code, module.__dict__)
File "/Users/danielkliewer/RedToBlog01/frontend.py", line 45, in <module>
save_to_db(metrics, final_blog)
File "/Users/danielkliewer/RedToBlog01/frontend.py", line 24, in save_to_db
cursor.execute("INSERT INTO results (timestamp, metrics, final_blog) VALUES (?, ?, ?)",
sqlite3.OperationalError: no such table: results
The error **"sqlite3.OperationalError: no such table: results"** suggests that the database table `results` does not exist.
### Fix:
Ensure the database and table are created before any queries are executed. Modify **frontend.py** to explicitly call `init_db()` at the start of the script:
#### **1. Ensure the Database Table Exists**
Modify `frontend.py`:
```python
import os
import streamlit as st
import sqlite3
import json
from main import main
from datetime import datetime
# Database setup
def init_db():
conn = sqlite3.connect("metrics.db")
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS results (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT,
metrics TEXT,
final_blog TEXT)''')
conn.commit()
conn.close()
# Initialize database
init_db() # Ensure table exists before running any queries
# Save output to database
def save_to_db(metrics, final_blog):
conn = sqlite3.connect("metrics.db")
cursor = conn.cursor()
cursor.execute("INSERT INTO results (timestamp, metrics, final_blog) VALUES (?, ?, ?)",
(datetime.now().strftime("%Y-%m-%d %H:%M:%S"), json.dumps(metrics), final_blog))
conn.commit()
conn.close()
# Fetch previous outputs
def fetch_history():
conn = sqlite3.connect("metrics.db")
cursor = conn.cursor()
cursor.execute("SELECT id, timestamp, metrics, final_blog FROM results ORDER BY id DESC")
data = cursor.fetchall()
conn.close()
return data
# Initialize Streamlit UI
st.title("Reddit Content Analysis and Blog Generator")
if st.button("Run Analysis"):
output = main()
if output: # Ensure main() returned valid output
metrics = output.get("metrics", {})
final_blog = output.get("final_blog", "")
save_to_db(metrics, final_blog)
st.success("Analysis complete! Results saved.")
else:
st.error("Failed to generate output. Please check logs.")
# Display stored results
st.subheader("Previous Outputs")
results = fetch_history()
for entry in results:
with st.expander(f"Output from {entry[1]}"):
st.json(json.loads(entry[2]))
st.markdown(entry[3])
```
---
### **Steps to Apply the Fix**
1. **Stop Streamlit (`Ctrl + C`) and restart it after making these changes.**
2. Ensure that `metrics.db` exists in your project directory (`/Users/danielkliewer/RedToBlog01/`).
3. Run your Streamlit app again:
```sh
streamlit run frontend.py
```
This should ensure the table is created before any database operations, preventing the `OperationalError`. 🚀
gpt-4o