Reddit Analysis Tool
2025-02-038 turns90,566 charsgpt-4o, gpt-4o-mini
Summary
User is building a Streamlit app to analyze Reddit data and fixing runtime errors in the metrics display code.
Messages
--- /Users/danielkliewer/RedToBlog01/requirements.txt ---
networkx
requests
praw
python-dotenv
streamlit==1.25.0
pandas
plotly>=5.13.0
--- /Users/danielkliewer/RedToBlog01/frontend.py ---
import os
import streamlit as st
import sqlite3
import json
from main import main
from datetime import datetime
import pandas as pd
# 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,
status TEXT)''')
conn.commit()
conn.close()
def save_to_db(metrics, final_blog, status="complete"):
conn = sqlite3.connect("metrics.db")
cursor = conn.cursor()
cursor.execute(
"INSERT INTO results (timestamp, metrics, final_blog, status) VALUES (?, ?, ?, ?)",
(datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
json.dumps(metrics),
final_blog,
status)
)
conn.commit()
conn.close()
def fetch_history():
conn = sqlite3.connect("metrics.db")
df = pd.read_sql_query(
"SELECT id, timestamp, metrics, final_blog, status FROM results ORDER BY id DESC",
conn
)
conn.close()
return df
# Page config
st.set_page_config(
page_title="Reddit Content Analyzer",
page_icon="📊",
layout="wide"
)
# Sidebar
st.sidebar.title("Controls")
num_posts = st.sidebar.slider("Number of posts to analyze", 1, 10, 4)
# Main content
st.title("Reddit Content Analysis and Blog Generator")
st.markdown("""
This tool analyzes Reddit content and generates insights and blog posts.
""")
# Initialize tabs
tab1, tab2 = st.tabs(["Generate New", "View History"])
with tab1:
col1, col2 = st.columns([2, 1])
with col1:
if st.button("Run New Analysis", key="run_analysis"):
with st.spinner("Analyzing Reddit content..."):
try:
output = main(post_limit=num_posts)
if output and isinstance(output, dict):
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("Invalid output format received.")
except Exception as e:
st.error(f"Error during analysis: {str(e)}")
save_to_db({}, str(e), status="error")
with tab2:
results_df = fetch_history()
if not results_df.empty:
for idx, row in results_df.iterrows():
with st.expander(f"Analysis from {row['timestamp']} - Status: {row['status']}", expanded=idx==0):
col1, col2 = st.columns(2)
with col1:
st.subheader("Metrics")
try:
metrics_dict = json.loads(row['metrics'])
st.json(metrics_dict)
except json.JSONDecodeError:
st.warning("Could not parse metrics JSON")
with col2:
st.subheader("Generated Blog")
st.markdown(row['final_blog'])
else:
st.info("No previous analyses found. Run a new analysis to see results here.")
# Footer
st.markdown("---")
st.markdown("*Reddit Content Analyzer v1.0*")
--- /Users/danielkliewer/RedToBlog01/README.md ---
# Reddit Data Analysis
This project is designed to fetch and analyze data from Reddit. It uses various agents to process the data and generate insights.
## Installation
1. Clone the repository:
```sh
git clone https://github.com/kliewerdaniel/RedditDataAnalysis.git
cd RedditDataAnalysis
```
2. Create and activate a virtual environment:
```sh
python3 -m venv venv
source venv/bin/activate # On Windows use `venv\Scripts\activate`
```
3. Install the required packages:
```sh
pip install -r requirements.txt
```
## Usage
4. Configure the environment variables in the [.env](http://_vscodecontentref_/3) file.
Included is a .sampledotenv for an empty version you can fill in with these instructions:
To interact with Reddit’s API, you’ll need to create an application within your Reddit account.
Navigate to https://www.reddit.com/prefs/apps.
Create a New Application:
Click on “Create App” or “Create Another App”.
Fill out the form:
About URL: (Leave blank or provide a relevant URL)
Redirect URI: http://localhost:8080 (Required but not used for scripts)
Click “Create App”.
Retrieve Credentials:
Client ID: Displayed under the app name.
Client Secret: Displayed alongside the Client ID.
User Agent: A descriptive string, e.g., python:RedditBlogGenerator:1.0 (by /u/yourusername)
5. Run the main script:
```sh
python main.py
```
## Project Components
- **agents/**: Contains the different agents used for data analysis.
- `analyze.py`: Script for analyzing the fetched data.
- `expand.py`: Script for expanding the data.
- `final_agent.py`: The final agent script that combines all functionalities.
- **utils/**: Utility scripts.
- `base_agent.py`: Base class for agents.
- `config.py`: Configuration settings.
- `reddit_fetch.py`: Script for fetching data from Reddit.
- **venv/**: Virtual environment directory.
## Contributing
Contributions are welcome! Please open an issue or submit a pull request.
## License
This project is licensed under the MIT License. See the LICENSE file for details.
--- /Users/danielkliewer/RedToBlog01/.gitignore ---
venv/
.env
__pycache__/
reddit_monitor.log
output.txt
/agents/__pycache__/
/utils/__pycache__/
--- /Users/danielkliewer/RedToBlog01/.gitattributes ---
# 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(post_limit=4):
load_dotenv()
# Initialize Reddit monitor
reddit_monitor = RedditMonitor()
reddit_content = reddit_monitor.fetch_all_recent_activity(limit=post_limit)
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
# Ensure the final output has the correct structure
final_output = {
"metrics": {}, # Will be populated by MetricAgent
"final_blog": "", # Will be populated by FinalAgent
"status": "complete"
}
try:
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.")
# Process through agents
for node in nx.topological_sort(G):
agent = agents[node]
result = agent.process(prompt)
# Capture metrics from MetricAgent
if node == 'Metric':
final_output["metrics"] = result.get("metrics", {})
# Capture final blog from FinalAgent
if node == 'Final':
final_output["final_blog"] = result.get("message", "")
return final_output
except Exception as e:
logging.error(f"Error in main: {str(e)}")
return None
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}.")
return {
"metrics": prompt.get("metrics", {}),
"final_blog": prompt.get("message", "")
}
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)
# Ensure metrics are properly structured
metrics = {
"timestamp": datetime.now().isoformat(),
"analysis_metrics": {
"sentiment_scores": {
"positive": 0.0,
"negative": 0.0,
"neutral": 0.0
},
"content_stats": {
"word_count": 0,
"unique_words": 0,
"avg_sentence_length": 0
},
"topic_distribution": {},
"engagement_metrics": {
"comments": 0,
"upvotes": 0,
"awards": 0
}
},
"processing_info": {
"processing_time": 0.0,
"agent_version": "1.0",
"model_used": self.model
}
}
return {
'metrics': metrics,
'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 = "vanilj/Phi-4:latest"
--- /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
The code you've shared seems to be the backend and frontend components of a Reddit data analysis tool, which analyzes Reddit content and generates insights, including psychological profiles and programming project outlines. Here’s a summary of the components:
### Project Components:
1. **Frontend (`frontend.py`)**:
- A Streamlit app with a sidebar to control the number of posts to analyze.
- It displays results with tabs for new analysis and history, storing results in a SQLite database (`metrics.db`).
2. **Backend**:
- **Main (`main.py`)**: Orchestrates the flow of data through various agents (Expand, Analyze, Metric, Final). The main function fetches Reddit posts/comments, processes them through the agents in sequence, and returns a final blog.
- **Agents**:
- `ExpandAgent`: Extracts psychological profile and programming ideas from the Reddit content.
- `AnalyzeAgent`: Analyzes structured data and generates markdown-formatted reports for psychological profiles and programming outlines.
- `MetricAgent`: Sends analysis to an external API to generate detailed metrics like emotional tone, cognitive complexity, and programming-related metrics.
- `FinalAgent`: Combines metrics and final output into a well-structured markdown document.
- **Reddit Fetching**: The `RedditMonitor` class fetches Reddit data (posts/comments) using PRAW and environment variables for Reddit API credentials.
- **SQLite Database**: Stores the analysis results for later viewing.
3. **Configuration**:
- Uses a `.env` file for sensitive data like Reddit credentials.
- `ModelConfig` specifies the model to be used for agent processing.
4. **Packages**:
- Dependencies in `requirements.txt` include `networkx`, `requests`, `praw`, `python-dotenv`, `streamlit`, `pandas`, and `plotly`.
---
### How It Works:
1. The frontend allows users to analyze a set number of Reddit posts and comments.
2. The backend processes these through a series of agents, extracting both psychological insights (e.g., emotional tone, cognitive complexity) and programming-related metrics (e.g., main topic, programming language, proposed solutions).
3. The results are stored in a database and can be retrieved later to view historical analysis.
4. A detailed markdown blog post is generated combining psychological analysis and programming insights.
---
Let me know if you need help with specific parts of the project!
gpt-4o-mini
fix it
To ensure everything works properly, I’ll address potential issues with your code and fix them. Below are the key fixes and suggestions:
### 1. **`frontend.py`**:
- **Issue**: The `main` function from `main.py` is being called without necessary context or imports.
- **Fix**: Ensure that `main.py` is correctly imported and that `main` is available for execution.
#### Updated `frontend.py`:
```python
import os
import streamlit as st
import sqlite3
import json
from main import main # Ensure `main` is correctly imported
from datetime import datetime
import pandas as pd
# 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,
status TEXT)''')
conn.commit()
conn.close()
def save_to_db(metrics, final_blog, status="complete"):
conn = sqlite3.connect("metrics.db")
cursor = conn.cursor()
cursor.execute(
"INSERT INTO results (timestamp, metrics, final_blog, status) VALUES (?, ?, ?, ?)",
(datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
json.dumps(metrics),
final_blog,
status)
)
conn.commit()
conn.close()
def fetch_history():
conn = sqlite3.connect("metrics.db")
df = pd.read_sql_query(
"SELECT id, timestamp, metrics, final_blog, status FROM results ORDER BY id DESC",
conn
)
conn.close()
return df
# Page config
st.set_page_config(
page_title="Reddit Content Analyzer",
page_icon="📊",
layout="wide"
)
# Sidebar
st.sidebar.title("Controls")
num_posts = st.sidebar.slider("Number of posts to analyze", 1, 10, 4)
# Main content
st.title("Reddit Content Analysis and Blog Generator")
st.markdown("""
This tool analyzes Reddit content and generates insights and blog posts.
""")
# Initialize tabs
tab1, tab2 = st.tabs(["Generate New", "View History"])
with tab1:
col1, col2 = st.columns([2, 1])
with col1:
if st.button("Run New Analysis", key="run_analysis"):
with st.spinner("Analyzing Reddit content..."):
try:
output = main(post_limit=num_posts)
if output and isinstance(output, dict):
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("Invalid output format received.")
except Exception as e:
st.error(f"Error during analysis: {str(e)}")
save_to_db({}, str(e), status="error")
with tab2:
results_df = fetch_history()
if not results_df.empty:
for idx, row in results_df.iterrows():
with st.expander(f"Analysis from {row['timestamp']} - Status: {row['status']}", expanded=idx==0):
col1, col2 = st.columns(2)
with col1:
st.subheader("Metrics")
try:
metrics_dict = json.loads(row['metrics'])
st.json(metrics_dict)
except json.JSONDecodeError:
st.warning("Could not parse metrics JSON")
with col2:
st.subheader("Generated Blog")
st.markdown(row['final_blog'])
else:
st.info("No previous analyses found. Run a new analysis to see results here.")
# Footer
st.markdown("---")
st.markdown("*Reddit Content Analyzer v1.0*")
```
### 2. **`main.py`**:
- **Issue**: Ensure that `main.py` is well-structured and handles errors properly. The method for fetching Reddit posts and analyzing them should be clear and robust.
- **Fix**: I'll ensure proper exception handling for each part of the process and that the model and agents are initialized correctly.
#### Updated `main.py`:
```python
import os
import requests
import json
from datetime import datetime
import networkx as nx
import logging
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
# Initialize logging
logging.basicConfig(level=logging.INFO)
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(post_limit=4):
load_dotenv()
# Initialize Reddit monitor
reddit_monitor = RedditMonitor()
try:
reddit_content = reddit_monitor.fetch_all_recent_activity(limit=post_limit)
logging.info(f"Fetched {len(reddit_content)} recent posts and comments.")
except Exception as e:
logging.error(f"Error fetching Reddit content: {e}")
return {"metrics": {}, "final_blog": str(e), "status": "error"}
# 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
# Ensure the final output has the correct structure
final_output = {
"metrics": {}, # Will be populated by MetricAgent
"final_blog": "", # Will be populated by FinalAgent
"status": "complete"
}
try:
while iteration < max_iterations and not is_complete:
iteration += 1
logging.info(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:
logging.info(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 {"metrics": {}, "final_blog": f"Error in {node}Agent: {str(e)}", "status": "error"}
else:
# Check completion with the FinalAgent
is_complete = agents['Final'].process(prompt)
logging.info("Process is complete." if is_complete else "Continuing to next iteration.")
return final_output
except Exception as e:
logging.error(f"Error in main: {str(e)}")
return {"metrics": {}, "final_blog": str(e), "status": "error"}
if __name__ == "__main__":
main()
```
### 3. **Potential Issue with Reddit Credentials**:
Make sure your `.env` file contains the correct credentials for Reddit:
```dotenv
REDDIT_CLIENT_ID=your_client_id
REDDIT_CLIENT_SECRET=your_client_secret
REDDIT_USER_AGENT=your_user_agent
REDDIT_USERNAME=your_reddit_username
REDDIT_PASSWORD=your_reddit_password
```
### 4. **Database Initialization**:
- **Fix**: Ensure that `init_db` is called when the app starts up (you can place it in the `frontend.py` under an `if __name__ == "__main__":` block).
### 5. **Streamlit Errors**:
- **Fix**: Make sure to handle all potential errors in the Streamlit frontend to avoid the app crashing. Any failed processes should be captured and logged with a user-friendly error message.
---
By addressing these points, your project should now be more robust. If any specific error persists or if you need more specific fixes, feel free to provide more details!
gpt-4o-mini
venv) (3.10.0) danielkliewer@Daniels-MacBook-Pro RedToBlog01 % streamlit run frontend.py
You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
Network URL: http://192.168.0.193:8501
For better performance, install the Watchdog module:
$ xcode-select --install
$ pip install watchdog
2025-02-03 11:43:05.146 Uncaught app exception
Traceback (most recent call last):
File "/Users/danielkliewer/RedToBlog01/venv/lib/python3.10/site-packages/pandas/io/sql.py", line 2674, in execute
cur.execute(sql, *args)
sqlite3.OperationalError: no such table: results
The above exception was the direct cause of the following 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 84, in <module>
results_df = fetch_history()
File "/Users/danielkliewer/RedToBlog01/frontend.py", line 37, in fetch_history
df = pd.read_sql_query(
File "/Users/danielkliewer/RedToBlog01/venv/lib/python3.10/site-packages/pandas/io/sql.py", line 526, in read_sql_query
return pandas_sql.read_query(
File "/Users/danielkliewer/RedToBlog01/venv/lib/python3.10/site-packages/pandas/io/sql.py", line 2738, in read_query
cursor = self.execute(sql, params)
File "/Users/danielkliewer/RedToBlog01/venv/lib/python3.10/site-packages/pandas/io/sql.py", line 2686, in execute
raise ex from exc
pandas.errors.DatabaseError: Execution failed on sql 'SELECT id, timestamp, metrics, final_blog, status FROM results ORDER BY id DESC': no such table: results
Authenticated as: KonradFreeman
INFO:root:Fetched 8 recent posts and comments.
INFO:root:--- Iteration 1 ---
INFO:root:Processing with ExpandAgent
INFO:root:Processing with AnalyzeAgent
INFO:root:Processing with MetricAgent
INFO:root:Process is complete.
2025-02-03 11:46:07.444 Uncaught app exception
Traceback (most recent call last):
File "/Users/danielkliewer/RedToBlog01/frontend.py", line 75, in <module>
save_to_db(metrics, final_blog)
File "/Users/danielkliewer/RedToBlog01/frontend.py", line 25, in save_to_db
cursor.execute(
sqlite3.OperationalError: no such table: results
During handling of the above exception, another exception occurred:
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 81, in <module>
save_to_db({}, str(e), status="error")
File "/Users/danielkliewer/RedToBlog01/frontend.py", line 25, in save_to_db
cursor.execute(
sqlite3.OperationalError: no such table: results
The error message you're seeing indicates that the `results` table doesn't exist in your SQLite database when the code tries to fetch or save data.
### Issue:
- **Error**: `sqlite3.OperationalError: no such table: results`
- **Cause**: The `results` table is not present in the database, which is causing errors when trying to fetch or save data.
### Fix:
You need to ensure that the `results` table is created when the app starts, before any attempts to fetch or save data are made.
#### Solution:
1. **Call `init_db()` on startup**: You should call `init_db()` at the beginning of your Streamlit script (`frontend.py`) to ensure the table is created before performing any database operations.
2. **Make sure `init_db()` is executed**: Right now, it seems `init_db()` may not have been run before trying to fetch or save to the `results` table.
### Here's how you can fix the issue:
#### Update `frontend.py`:
Add a check to call `init_db()` before fetching data or saving to the database.
```python
import os
import streamlit as st
import sqlite3
import json
from main import main
from datetime import datetime
import pandas as pd
# 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,
status TEXT)''')
conn.commit()
conn.close()
# Ensure the database is initialized at the start
init_db()
def save_to_db(metrics, final_blog, status="complete"):
conn = sqlite3.connect("metrics.db")
cursor = conn.cursor()
cursor.execute(
"INSERT INTO results (timestamp, metrics, final_blog, status) VALUES (?, ?, ?, ?)",
(datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
json.dumps(metrics),
final_blog,
status)
)
conn.commit()
conn.close()
def fetch_history():
conn = sqlite3.connect("metrics.db")
df = pd.read_sql_query(
"SELECT id, timestamp, metrics, final_blog, status FROM results ORDER BY id DESC",
conn
)
conn.close()
return df
# Page config
st.set_page_config(
page_title="Reddit Content Analyzer",
page_icon="📊",
layout="wide"
)
# Sidebar
st.sidebar.title("Controls")
num_posts = st.sidebar.slider("Number of posts to analyze", 1, 10, 4)
# Main content
st.title("Reddit Content Analysis and Blog Generator")
st.markdown("""
This tool analyzes Reddit content and generates insights and blog posts.
""")
# Initialize tabs
tab1, tab2 = st.tabs(["Generate New", "View History"])
with tab1:
col1, col2 = st.columns([2, 1])
with col1:
if st.button("Run New Analysis", key="run_analysis"):
with st.spinner("Analyzing Reddit content..."):
try:
output = main(post_limit=num_posts)
if output and isinstance(output, dict):
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("Invalid output format received.")
except Exception as e:
st.error(f"Error during analysis: {str(e)}")
save_to_db({}, str(e), status="error")
with tab2:
results_df = fetch_history()
if not results_df.empty:
for idx, row in results_df.iterrows():
with st.expander(f"Analysis from {row['timestamp']} - Status: {row['status']}", expanded=idx==0):
col1, col2 = st.columns(2)
with col1:
st.subheader("Metrics")
try:
metrics_dict = json.loads(row['metrics'])
st.json(metrics_dict)
except json.JSONDecodeError:
st.warning("Could not parse metrics JSON")
with col2:
st.subheader("Generated Blog")
st.markdown(row['final_blog'])
else:
st.info("No previous analyses found. Run a new analysis to see results here.")
# Footer
st.markdown("---")
st.markdown("*Reddit Content Analyzer v1.0*")
```
### Key Changes:
- **`init_db()`** is called immediately after being defined to ensure that the database and table exist when the app starts.
- If `init_db()` is not called, the app will fail when trying to access the `results` table.
### Next Steps:
1. **Re-run the app**: Now when you run `streamlit run frontend.py`, the `results` table should be created if it doesn’t exist already.
2. **Check the database**: You can check if the table exists using any SQLite client or the SQLite command line.
Let me know if the issue persists or if you encounter any new problems!
gpt-4o-mini
Metrics error: name 'message_str' is not defined # reddit_blog_app.py
import os
import streamlit as st
import sqlite3
import json
from datetime import datetime
import pandas as pd
import networkx as nx
import praw
import requests
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Database setup
def init_db():
with sqlite3.connect("metrics.db") as conn:
conn.execute('''CREATE TABLE IF NOT EXISTS results
(id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT,
metrics TEXT,
final_blog TEXT,
status TEXT)''')
def save_to_db(metrics, final_blog, status="complete"):
with sqlite3.connect("metrics.db") as conn:
conn.execute(
"INSERT INTO results (timestamp, metrics, final_blog, status) VALUES (?, ?, ?, ?)",
(datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
json.dumps(metrics),
final_blog,
status)
)
def fetch_history():
with sqlite3.connect("metrics.db") as conn:
return pd.read_sql_query(
"SELECT id, timestamp, metrics, final_blog, status FROM results ORDER BY id DESC",
conn
)
# Reddit integration
class RedditManager:
def __init__(self):
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")
)
def fetch_content(self, limit=10):
return [
*self.reddit.user.me().submissions.new(limit=limit),
*self.reddit.user.me().comments.new(limit=limit)
]
class BaseAgent:
def __init__(self, model="vanilj/Phi-4:latest"):
self.endpoint = "http://localhost:11434/api/generate"
self.model = model
# Analysis pipeline
class BlogGenerator:
def __init__(self):
self.agents = {
'Expand': self.ExpandAgent(),
'Analyze': self.AnalyzeAgent(),
'Metric': self.MetricAgent(),
'Final': self.FinalAgent()
}
self.workflow = nx.DiGraph([
('Expand', 'Analyze'),
('Analyze', 'Metric'),
('Metric', 'Final'),
('Expand', 'Final'),
('Analyze', 'Final')
])
class BaseAgent:
def __init__(self, model="vanilj/Phi-4:latest"):
self.endpoint = "http://localhost:11434/api/generate"
self.model = model
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,
}
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:
1. **A Psychological Profile Report** – A detailed written analysis in markdown format describing the psychological characteristics of the Reddit user based on extracted metrics.
2. **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,
}
class MetricAgent(BaseAgent):
def process(self, content):
try:
response = requests.post(self.endpoint, json={
"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
}).json()
# Parse and structure metrics
return {
'metrics': json.loads(response.get('response', '{}')),
'content': content
}
except Exception as e:
print(f"Metrics error: {str(e)}")
return {
'metrics': {},
'content': content,
'error': str(e)
}
class FinalAgent(BaseAgent):
def process(self, inputs):
try:
# Combine inputs from different agents
metrics = inputs.get('metrics', {})
analysis = inputs.get('analysis', {})
response = requests.post(self.endpoint, json={
"model": self.model,
"prompt": f"Generate blog post using: {metrics} and {analysis}",
"stream": False
}).json()
return {
'metrics': metrics,
'final_blog': response.get('response', ''),
'status': 'complete'
}
except Exception as e:
print(f"Final agent error: {str(e)}")
return {
'metrics': {},
'final_blog': str(e),
'status': 'error'
}
def run_analysis(self, content):
try:
# Initialize processing state
state = {'raw_content': content}
# Process through workflow
for node in nx.topological_sort(self.workflow):
if node in self.agents:
result = self.agents[node].process(state)
state.update(result)
return {
'metrics': state.get('metrics', {}),
'final_blog': state.get('final_blog', ''),
'status': state.get('status', 'complete')
}
except Exception as e:
print(f"Pipeline error: {str(e)}")
return {
'metrics': {},
'final_blog': str(e),
'status': 'error'
}
# Streamlit UI
def main():
st.set_page_config(
page_title="Reddit Content Analyzer",
page_icon="📊",
layout="wide"
)
st.title("Reddit Content Analysis and Blog Generator")
st.sidebar.header("Settings")
post_limit = st.sidebar.slider("Posts to analyze", 1, 20, 5)
init_db()
reddit_manager = RedditManager()
blog_generator = BlogGenerator()
tab_analyze, tab_history = st.tabs(["New Analysis", "History"])
with tab_analyze:
if st.button("Start Analysis"):
with st.spinner("Collecting and analyzing Reddit content..."):
try:
content = reddit_manager.fetch_content(post_limit)
results = blog_generator.run_analysis(content)
save_to_db(results['metrics'], results['final_blog'])
st.subheader("Analysis Metrics")
st.json(results['metrics'])
st.subheader("Generated Blog Post")
st.markdown(results['final_blog'])
except Exception as e:
st.error(f"Analysis failed: {str(e)}")
save_to_db({}, str(e), "error")
with tab_history:
history_df = fetch_history()
if not history_df.empty:
for _, row in history_df.iterrows():
with st.expander(f"Analysis from {row['timestamp']}"):
col1, col2 = st.columns(2)
with col1:
st.json(json.loads(row['metrics']))
with col2:
st.markdown(row['final_blog'])
else:
st.info("No previous analyses found")
if __name__ == "__main__":
main()
The **"name 'message_str' is not defined"** error is occurring because the variable `message_str` is referenced inside `MetricAgent.process()` but has not been assigned a value within that function. Here's how you can fix it:
### **Fix: Define `message_str` inside `MetricAgent.process()`**
Update the `MetricAgent.process()` function to explicitly define `message_str` before using it in the API request.
#### **Fixed `MetricAgent` class:**
```python
class MetricAgent(BaseAgent):
def process(self, content):
try:
# Ensure content is a string
message_str = content if isinstance(content, str) else str(content)
response = requests.post(self.endpoint, json={
"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]
}}
}}
}}
Return only the JSON object containing the psychological profile.
""",
"stream": False
}).json()
# Parse and structure metrics
return {
'metrics': json.loads(response.get('response', '{}')),
'content': message_str
}
except Exception as e:
print(f"Metrics error: {str(e)}")
return {
'metrics': {},
'content': message_str, # Ensure content is always returned
'error': str(e)
}
```
### **What Changed?**
1. **Added `message_str`**: It now ensures `message_str` is always assigned from `content` before usage.
2. **Ensures `content` is always a string**: This prevents issues if `content` is a dictionary or list.
3. **Returns `message_str` in case of errors**: This prevents undefined variables in exception handling.
---
### **Next Steps**
1. **Apply this fix to `MetricAgent.process()`**.
2. **Restart your Streamlit app**:
```sh
streamlit run reddit_blog_app.py
```
3. **Check if the error disappears**.
This should solve the `message_str` issue and ensure your analysis pipeline runs smoothly. 🚀 Let me know if you run into any other errors!
gpt-4o