Alwrity version 0.5.4

This commit is contained in:
ajaysi
2025-08-12 22:35:21 +05:30
parent 39b96c44da
commit 66ece49705
44 changed files with 9577 additions and 2112 deletions

View File

@@ -1,232 +0,0 @@
import re
import os
import PyPDF2
import openai
import streamlit as st
import tempfile
from loguru import logger
from lib.ai_writers.ai_news_article_writer import ai_news_generation
from lib.ai_writers.ai_finance_report_generator.ai_financial_dashboard import get_dashboard
from lib.ai_writers.ai_facebook_writer.facebook_ai_writer import facebook_main_menu
from lib.ai_writers.linkedin_writer.linkedin_ai_writer import linkedin_main_menu
from lib.ai_writers.twitter_writers.twitter_dashboard import run_dashboard
from lib.ai_writers.insta_ai_writer import insta_writer
from lib.ai_writers.youtube_writers.youtube_ai_writer import youtube_main_menu
from lib.ai_writers.ai_essay_writer import ai_essay_generator
from lib.gpt_providers.text_to_image_generation.main_generate_image_from_prompt import generate_image
#from lib.content_planning_calender.content_planning_agents_alwrity_crew import ai_agents_content_planner
from lib.gpt_providers.text_generation.main_text_generation import llm_text_gen
def ai_agents_team():
# Define options for AI Content Teams
st.title("🐲 Your AI Agents Teams")
st.markdown("""Alwrity offers AI agents team for content creators to easily modify them for their needs.
Abstracting tech & plumbing, easily define role, goal, task. Use different AI agents framework.""")
options = [
"AI Planning Team",
"AI Content Creation Team"
]
# Radio button for choosing an AI Content Team
selected_team = st.radio("**Choose AI Agents Team:**", options)
if selected_team == "AI Planning Team":
st.title("AI Agents for Content Ideation")
plan_keywords = st.text_input(
"Enter Keywords to get 2 months content calendar:",
placeholder="Enter keywords to generate AI content calendar:",
help="Enter at least two words for better results."
)
if st.button("Get calendar"):
if plan_keywords and len(plan_keywords.split()) >= 2:
with st.spinner("Get Content Plan..."):
try:
#plan_content = ai_agents_content_planner(plan_keywords)
st.success(f"Coming soon: Content plan for: {plan_keywords}")
#st.markdown(plan_content)
except Exception as err:
st.error(f"Failed to generate content plan: {err}")
else:
st.error("🚫 Single keywords are just too vague. Try again.")
elif selected_team == "AI Content Creation Team":
content_agents()
def content_agents():
st.markdown("AI Agents Team for Content Writing")
content_keywords = st.text_input(
"Enter Main Domain Keywords of your business:",
placeholder="Better keywords, Better content. Get keywords from Google search",
help="These keywords define your main business sector, blogging niche, Industry, domain etc"
)
if st.button("Start Writing"):
if content_keywords and len(content_keywords.split()) >= 2:
with st.spinner("Generating Content..."):
try:
#calendar_content = ai_agents_writers(content_keywords)
st.success(f"🚫 Not implemented yet: {content_keywords}")
#st.markdown(calendar_content)
except Exception as err:
st.error(f"🚫 Failed to generate content with AI Agents: {err}")
else:
st.error("🚫 Single keywords are just too vague. Try again.")
def essay_writer():
st.title("AI Essay Writer 📝")
st.write("Select your essay type, education level, and desired length, then let AI generate an essay for you. ✨")
# Define essay types and education levels
essay_types = [
"📖 Argumentative - Forming an opinion via research. Building an evidence-based argument.",
"📚 Expository - Knowledge of a topic. Communicating information clearly.",
"✒️ Narrative - Creative language use. Presenting a compelling narrative.",
"🎨 Descriptive - Creative language use. Describing sensory details."
]
education_levels = [
"🏫 Primary School",
"🏫 High School",
"🎓 College",
"🎓 Graduate School"
]
# Define the options for number of pages
num_pages_options = [
"📄 Short Form (1-2 pages)",
"📄📄 Medium Form (3-5 pages)",
"📄📄📄 Long Form (6+ pages)"
]
# Create columns for input fields
col1, col2 = st.columns(2)
with col1:
# Ask the user for the title of the essay
essay_title = st.text_input("📝 Essay Title", placeholder="Enter the title of your essay", help="Provide a clear and concise title for your essay.")
# Ask the user for type of essay
selected_essay_type = st.selectbox("📚 Type of Essay", options=essay_types, help="Choose the type of essay you want to write.")
with col2:
# Ask the user for level of education
selected_education_level = st.selectbox("🎓 Level of Education", options=education_levels, help="Choose your level of education.")
# Ask the user for number of pages
selected_num_pages = st.selectbox("📄 Number of Pages", options=num_pages_options, help="Select the length of your essay.")
if st.button("🚀 Generate Essay"):
if essay_title:
st.success("Generating your essay... ✨")
ai_essay_generator(essay_title, selected_essay_type, selected_education_level, selected_num_pages)
else:
st.error("Please enter a valid title for your essay. 🚫")
def ai_news_writer():
""" AI News Writer """
st.markdown("<h1>📰 AI News Writer 🗞️ </h1>", unsafe_allow_html=True)
# Input for news keywords
news_keywords = st.text_input(
"**🔑 Enter Keywords from News Headlines:**",
placeholder="Describe the News article in 3-5 words. Enter main keywords describing the News Event:",
help="Enter at least two words for better results."
)
if news_keywords and len(news_keywords.split()) < 2:
st.error("🚫 News keywords should be at least two words long. Least, you can do..")
# Selectbox for country and language
countries = [
("es", "Spain"),
("vn", "Vietnam"),
("pk", "Pakistan"),
("in", "India"),
("de", "Germany"),
("cn", "China")
]
languages = [
("en", "English"),
("es", "Spanish"),
("vi", "Vietnamese"),
("ar", "Arabic"),
("hi", "Hindi"),
("de", "German"),
("zh-cn", "Chinese")
]
col1, col2 = st.columns(2)
with col1:
news_country = st.selectbox("**🌍 Select Origin Country of News Event:**",
countries, format_func=lambda x: x[1], help="Which country did the NEWS originate from ?")
with col2:
news_language = st.selectbox("**🗣️ Select News Article Language to Search For:**",
languages, format_func=lambda x: x[1], help="Language to output News Article in ?")
if st.button("📰 Generate News Report"):
if news_keywords and len(news_keywords.split()) >= 2:
with st.spinner("Generating News Report... ⏳"):
try:
news_report = ai_news_generation(news_keywords, news_country, news_language)
st.success(f"Successfully generated news report on: {news_keywords} 🎉")
st.markdown(news_report)
except Exception as err:
st.error(f"Failed to generate news report: {err}")
else:
st.error("Please enter valid keywords for the news report. 🚫")
def ai_finance_ta_writer():
st.markdown("<div class='sub-header'>AI Financial Technical Analysis Writer</div>", unsafe_allow_html=True)
ticker_symbol = st.text_input(
"Enter Ticker Symbol for TA:",
placeholder="Enter a valid Ticker Symbol (Examples: IBM, BABA, HDFCBANK.NS, TATAMOTORS.NS etc)",
help="Be sure of the ticker symbol. Double-check it! Examples: IBM, BABA, HDFCBANK.NS, TATAMOTORS.NS"
)
if st.button("Generate TA Report"):
if ticker_symbol:
with st.spinner("Generating TA Report..."):
try:
# Get dashboard instance and generate technical analysis
dashboard = get_dashboard()
ta_report = dashboard.generate_technical_analysis(ticker_symbol)
st.success(f"Successfully generated TA report for: {ticker_symbol}")
st.markdown(ta_report)
except Exception as err:
st.error(f"🚫 Check ticker symbol: Failed to write Financial Technical Analysis. Error: {err}")
else:
st.error("🚫 Provide a valid Ticker Symbol. Don't waste my time.")
def ai_social_writer():
# Define social media platforms as radio buttons
social_media_options = [
("facebook", "Facebook"),
("linkedin", "LinkedIn"),
("twitter", "Twitter"),
("instagram", "Instagram"),
("youtube", "YouTube")
]
# Selectbox for choosing a platform
selected_platform = st.radio("Choose a Social Media Platform:", social_media_options, format_func=lambda x: x[1])
if "facebook" in selected_platform:
facebook_main_menu()
elif "linkedin" in selected_platform:
linkedin_main_menu()
elif "twitter" in selected_platform:
run_dashboard()
elif "instagram" in selected_platform:
insta_writer()
elif "youtube" in selected_platform:
youtube_main_menu()

View File

@@ -1,310 +0,0 @@
"""Test configuration settings page for ALwrity."""
import streamlit as st
from loguru import logger
import asyncio
from lib.web_crawlers.async_web_crawler import AsyncWebCrawlerService
from pages.style_utils import (
get_test_config_styles,
get_glass_container,
get_info_section,
get_example_box,
get_analysis_section,
get_style_guide_html
)
import sys
from lib.personalization.style_analyzer import StyleAnalyzer
# Set page config - must be the first Streamlit command
st.set_page_config(
layout="wide",
initial_sidebar_state="collapsed",
menu_items={
'Get Help': None,
'Report a bug': None,
'About': None
}
)
import yaml
from pathlib import Path
import os
from loguru import logger
from lib.utils.read_main_config_params import get_personalization_settings
from lib.web_crawlers.crawl4ai_web_crawler import analyze_style
# Configure logger
logger.remove() # Remove default handler
logger.add(
"logs/test_config_settings.log",
rotation="500 MB",
retention="10 days",
level="DEBUG",
format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}",
backtrace=True,
diagnose=True
)
logger.add(
sys.stdout,
level="INFO",
format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{message}</cyan>"
)
# Apply CSS styles
st.markdown(get_test_config_styles(), unsafe_allow_html=True)
def load_website_url():
"""Load website URL from config file."""
try:
logger.debug("Loading website URL from config file")
config_path = Path(os.environ["ALWRITY_CONFIG"])
config = yaml.safe_load(config_path.read_text())
url = config.get('website', {}).get('url', '')
logger.info(f"Loaded website URL: {url}")
return url
except Exception as e:
logger.error(f"Error loading website URL: {str(e)}", exc_info=True)
return ''
def display_style_analysis(analysis_results: dict):
"""Display the style analysis results in a structured format."""
try:
# Writing Style Section
st.markdown("### 🎨 Writing Style Analysis")
writing_style = analysis_results.get("writing_style", {})
writing_style_content = f"""
<ul>
<li><strong>Tone:</strong> {writing_style.get("tone", "N/A")}</li>
<li><strong>Voice:</strong> {writing_style.get("voice", "N/A")}</li>
<li><strong>Complexity:</strong> {writing_style.get("complexity", "N/A")}</li>
<li><strong>Engagement Level:</strong> {writing_style.get("engagement_level", "N/A")}</li>
</ul>
"""
st.markdown(get_analysis_section("Writing Style", writing_style_content), unsafe_allow_html=True)
# Content Characteristics Section
content_chars = analysis_results.get("content_characteristics", {})
content_chars_content = f"""
<ul>
<li><strong>Sentence Structure:</strong> {content_chars.get("sentence_structure", "N/A")}</li>
<li><strong>Vocabulary Level:</strong> {content_chars.get("vocabulary_level", "N/A")}</li>
<li><strong>Paragraph Organization:</strong> {content_chars.get("paragraph_organization", "N/A")}</li>
<li><strong>Content Flow:</strong> {content_chars.get("content_flow", "N/A")}</li>
</ul>
"""
st.markdown(get_analysis_section("Content Characteristics", content_chars_content), unsafe_allow_html=True)
# Target Audience Section
target_audience = analysis_results.get("target_audience", {})
target_audience_content = f"""
<ul>
<li><strong>Demographics:</strong> {', '.join(target_audience.get("demographics", ["N/A"]))}</li>
<li><strong>Expertise Level:</strong> {target_audience.get("expertise_level", "N/A")}</li>
<li><strong>Industry Focus:</strong> {target_audience.get("industry_focus", "N/A")}</li>
<li><strong>Geographic Focus:</strong> {target_audience.get("geographic_focus", "N/A")}</li>
</ul>
"""
st.markdown(get_analysis_section("Target Audience", target_audience_content), unsafe_allow_html=True)
# Content Type Section
content_type = analysis_results.get("content_type", {})
content_type_content = f"""
<ul>
<li><strong>Primary Type:</strong> {content_type.get("primary_type", "N/A")}</li>
<li><strong>Secondary Types:</strong> {', '.join(content_type.get("secondary_types", ["N/A"]))}</li>
<li><strong>Purpose:</strong> {content_type.get("purpose", "N/A")}</li>
<li><strong>Call to Action:</strong> {content_type.get("call_to_action", "N/A")}</li>
</ul>
"""
st.markdown(get_analysis_section("Content Type", content_type_content), unsafe_allow_html=True)
# Recommended Settings Section
recommended = analysis_results.get("recommended_settings", {})
recommended_content = f"""
<ul>
<li><strong>Writing Tone:</strong> {recommended.get("writing_tone", "N/A")}</li>
<li><strong>Target Audience:</strong> {recommended.get("target_audience", "N/A")}</li>
<li><strong>Content Type:</strong> {recommended.get("content_type", "N/A")}</li>
<li><strong>Creativity Level:</strong> {recommended.get("creativity_level", "N/A")}</li>
<li><strong>Geographic Location:</strong> {recommended.get("geographic_location", "N/A")}</li>
</ul>
"""
st.markdown(get_analysis_section("Recommended Settings", recommended_content), unsafe_allow_html=True)
except Exception as e:
logger.error(f"Error displaying style analysis: {str(e)}")
st.error(f"Error displaying analysis results: {str(e)}")
def render_test_config_settings():
"""Render the test configuration settings page."""
try:
logger.info("Starting to render test configuration settings")
# Add back button at the top
col1, col2 = st.columns([1, 3])
with col1:
if st.button("← Back to Personalization Setup"):
logger.info("User clicked back to personalization setup")
# Set session state for navigation
st.session_state.current_step = 4
st.session_state.next_step = "personalization_setup"
# Navigate back to the main page where personalization setup is rendered
st.switch_page("alwrity.py")
# Title and description
st.title("🎨 Find Your Style with ALwrity")
st.markdown(get_glass_container(
"<p>Enter a website URL or provide content samples to analyze your writing style and get personalized recommendations.</p>"
), unsafe_allow_html=True)
# Create two columns for the layout
col1, col2 = st.columns([2, 1])
with col1:
# Website URL input
st.markdown("### Website URL")
url = st.text_input(
"Enter your website URL",
placeholder="https://example.com",
help="Provide your website URL to analyze your content style. Leave empty if you want to provide written samples instead."
)
logger.debug(f"Website URL input value: {url}")
# Alternative: Written samples
if not url:
st.markdown("### Written Samples")
st.markdown(get_info_section("""
<p>No website URL? No problem! You can provide written samples of your content instead.</p>
<p>Share your best articles, blog posts, or any content that represents your writing style.</p>
"""), unsafe_allow_html=True)
samples = st.text_area(
"Paste your content samples here",
help="Paste 2-3 samples of your best content. This helps ALwrity understand your writing style."
)
logger.debug(f"Sample text length: {len(samples) if samples else 0}")
st.markdown('</div>', unsafe_allow_html=True)
# ALwrity Style button
st.markdown("<div style='height: 20px'></div>", unsafe_allow_html=True)
if st.button("🎨 ALwrity Style", use_container_width=True):
if url:
with st.status("Starting style analysis...", expanded=True) as status:
try:
logger.info(f"Starting style analysis for URL: {url}")
# Step 1: Initialize crawler
status.update(label="Step 1/4: Initializing web crawler...", state="running")
crawler_service = AsyncWebCrawlerService()
# Step 2: Crawl website
status.update(label="Step 2/4: Crawling website content...", state="running")
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
result = loop.run_until_complete(crawler_service.crawl_website(url))
loop.close()
if result.get('success', False):
content = result.get('content', {})
# Step 3: Initialize style analyzer
status.update(label="Step 3/4: Analyzing content style...", state="running")
style_analyzer = StyleAnalyzer()
# Step 4: Perform style analysis
status.update(label="Step 4/4: Generating style recommendations...", state="running")
style_analysis = style_analyzer.analyze_content_style(content)
if style_analysis.get('error'):
status.update(label="Analysis failed", state="error")
st.error(f"Style analysis failed: {style_analysis['error']}")
else:
status.update(label="Analysis complete!", state="complete")
# Display style analysis results
display_style_analysis(style_analysis)
# Display original content in tabs
tab1, tab2, tab3 = st.tabs(["Content", "Metadata", "Links"])
with tab1:
st.markdown("### Main Content")
st.markdown(content.get('main_content', 'No content found'))
with tab2:
st.markdown("### Metadata")
st.markdown(f"""
**Title:** {content.get('title', 'No title found')}
**Description:** {content.get('description', 'No description found')}
**Meta Tags:**
{content.get('meta_tags', {})}
""")
with tab3:
st.markdown("### Links")
for link in content.get('links', []):
st.markdown(f"- [{link.get('text', '')}]({link.get('href', '')})")
else:
status.update(label="Crawling failed", state="error")
st.error(f"Failed to analyze website: {result.get('error', 'Unknown error')}")
except Exception as e:
logger.error(f"Error during style analysis: {str(e)}")
st.error(f"Analysis failed: {str(e)}")
elif samples:
with st.spinner("Analyzing content samples..."):
try:
# TODO: Implement sample text analysis
st.info("Sample text analysis coming soon!")
except Exception as e:
logger.error(f"Error analyzing samples: {str(e)}")
st.error(f"Analysis failed: {str(e)}")
else:
st.warning("Please provide either a website URL or content samples")
with col2:
st.markdown("""
### How ALwrity Discovers Your Style
**AI-Powered Style Analysis**
ALwrity AI analyzes your existing content to understand your unique writing style and preferences. This helps us generate content that matches your voice perfectly.
**Step 1: Content Analysis**
We'll analyze your website content or written samples to understand:
- Writing tone and voice
- Vocabulary and language style
- Content structure and formatting
- Target audience and engagement style
**Step 2: Style Recommendations**
Based on the analysis, we'll provide:
- Personalized writing guidelines
- Content structure templates
- Tone and voice recommendations
- Audience engagement strategies
**Step 3: Content Generation**
Finally, we'll use these insights to:
- Generate content that matches your style
- Maintain consistency across all content
- Optimize for your target audience
- Ensure brand voice alignment
""")
except Exception as e:
logger.error(f"Error in render_test_config_settings: {str(e)}")
st.error(f"An error occurred: {str(e)}")
if __name__ == "__main__":
logger.info("Starting test config settings page")
render_test_config_settings()
logger.info("Test config settings page rendered successfully")

View File

@@ -1,23 +0,0 @@
import streamlit as st
from streamlit_mic_recorder import speech_to_text
def record_voice(language="en"):
# https://github.com/B4PT0R/streamlit-mic-recorder?tab=readme-ov-file#example
state = st.session_state
if "text_received" not in state:
state.text_received = []
text = speech_to_text(
start_prompt="🎙Press & Speak🔊",
stop_prompt="🔇Stop Recording🚨",
language=language,
use_container_width=True,
just_once=False,
)
if text:
state.text_received.append(text)
result = ""
for text in state.text_received:
result += text
state.text_received = []
return result if result else None

View File

@@ -1,45 +0,0 @@
"""Data models for website analysis results."""
from dataclasses import dataclass
from typing import List, Dict, Optional
from datetime import datetime
@dataclass
class SEORecommendation:
"""A single SEO recommendation."""
priority: str # 'high', 'medium', 'low'
category: str # 'content', 'technical', 'meta', etc.
issue: str
recommendation: str
impact: str
@dataclass
class MetaTagAnalysis:
"""Analysis of meta tags."""
title: Dict[str, str] # {'status': 'good', 'value': 'actual title', 'recommendation': 'suggestion'}
description: Dict[str, str]
keywords: Dict[str, str]
has_robots: bool
has_sitemap: bool
@dataclass
class ContentAnalysis:
"""Analysis of page content."""
word_count: int
headings_structure: Dict[str, int] # {'h1': 1, 'h2': 3, etc}
keyword_density: Dict[str, float]
readability_score: float
content_quality_score: float
@dataclass
class SEOAnalysisResult:
"""Complete SEO analysis result."""
url: str
analyzed_at: datetime
overall_score: float # 0-100
meta_tags: MetaTagAnalysis
content: ContentAnalysis
recommendations: List[SEORecommendation]
errors: List[str]
warnings: List[str]
success: bool