API Setup Updates and Tweaks
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
"""API key manager components package."""
|
"""API key manager components package."""
|
||||||
|
|
||||||
from .ai_research_setup import render_ai_research_setup
|
from .ai_research_setup import render_ai_research_setup
|
||||||
|
from .ai_research import render_ai_research
|
||||||
from .ai_providers import render_ai_providers
|
from .ai_providers import render_ai_providers
|
||||||
from .final_setup import render_final_setup
|
from .final_setup import render_final_setup
|
||||||
from .personalization_setup import render_personalization_setup
|
from .personalization_setup import render_personalization_setup
|
||||||
@@ -10,6 +11,7 @@ from .website_setup import render_website_setup
|
|||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'render_ai_research_setup',
|
'render_ai_research_setup',
|
||||||
|
'render_ai_research',
|
||||||
'render_ai_providers',
|
'render_ai_providers',
|
||||||
'render_final_setup',
|
'render_final_setup',
|
||||||
'render_personalization_setup',
|
'render_personalization_setup',
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ from ..manager import APIKeyManager
|
|||||||
from .base import render_navigation_buttons, render_step_indicator, render_tab_style
|
from .base import render_navigation_buttons, render_step_indicator, render_tab_style
|
||||||
from ..wizard_state import next_step, update_progress
|
from ..wizard_state import next_step, update_progress
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
import os
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
def validate_api_key(key: str) -> bool:
|
def validate_api_key(key: str) -> bool:
|
||||||
"""Validate if an API key is properly formatted."""
|
"""Validate if an API key is properly formatted."""
|
||||||
@@ -15,10 +17,53 @@ def validate_api_key(key: str) -> bool:
|
|||||||
# Basic validation - check if key is not empty and has minimum length
|
# Basic validation - check if key is not empty and has minimum length
|
||||||
return len(key.strip()) > 0
|
return len(key.strip()) > 0
|
||||||
|
|
||||||
|
def save_to_env_file(key_name: str, key_value: str) -> bool:
|
||||||
|
"""Save API key to .env file."""
|
||||||
|
try:
|
||||||
|
env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))), '.env')
|
||||||
|
|
||||||
|
# Read existing .env file
|
||||||
|
env_contents = []
|
||||||
|
if os.path.exists(env_path):
|
||||||
|
with open(env_path, 'r') as f:
|
||||||
|
env_contents = f.readlines()
|
||||||
|
|
||||||
|
# Check if key already exists
|
||||||
|
key_exists = False
|
||||||
|
for i, line in enumerate(env_contents):
|
||||||
|
if line.startswith(f"{key_name}="):
|
||||||
|
env_contents[i] = f"{key_name}={key_value}\n"
|
||||||
|
key_exists = True
|
||||||
|
break
|
||||||
|
|
||||||
|
# Add new key if it doesn't exist
|
||||||
|
if not key_exists:
|
||||||
|
env_contents.append(f"{key_name}={key_value}\n")
|
||||||
|
|
||||||
|
# Write back to .env file
|
||||||
|
with open(env_path, 'w') as f:
|
||||||
|
f.writelines(env_contents)
|
||||||
|
|
||||||
|
# Reload environment variables to ensure consistency
|
||||||
|
load_dotenv(override=True)
|
||||||
|
|
||||||
|
logger.info(f"[save_to_env_file] Successfully saved {key_name} to .env file")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[save_to_env_file] Error saving to .env file: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
def render_ai_providers(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
def render_ai_providers(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
||||||
"""Render the AI providers setup step."""
|
"""Render the AI providers setup step."""
|
||||||
logger.info("[render_ai_providers] Starting AI providers setup")
|
logger.info("[render_ai_providers] Starting AI providers setup")
|
||||||
try:
|
try:
|
||||||
|
# Load environment variables
|
||||||
|
load_dotenv(override=True)
|
||||||
|
|
||||||
|
# Get existing API keys from .env
|
||||||
|
openai_key = os.getenv('OPENAI_API_KEY', '')
|
||||||
|
gemini_key = os.getenv('GEMINI_API_KEY', '')
|
||||||
|
|
||||||
# Initialize wizard state if not already initialized
|
# Initialize wizard state if not already initialized
|
||||||
if 'wizard_state' not in st.session_state:
|
if 'wizard_state' not in st.session_state:
|
||||||
st.session_state.wizard_state = {
|
st.session_state.wizard_state = {
|
||||||
@@ -35,10 +80,7 @@ def render_ai_providers(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
|
|
||||||
# Main content
|
# Main content
|
||||||
st.markdown("""
|
st.markdown("""
|
||||||
<div class='setup-header'>
|
<div class='setup-header'><h2>🤖 AI LLM Providers Setup</h2></div>
|
||||||
<h2>🤖 AI Providers Setup</h2>
|
|
||||||
<p>Configure your AI service providers for content generation</p>
|
|
||||||
</div>
|
|
||||||
""", unsafe_allow_html=True)
|
""", unsafe_allow_html=True)
|
||||||
|
|
||||||
# Create tabs for different AI providers
|
# Create tabs for different AI providers
|
||||||
@@ -51,7 +93,6 @@ def render_ai_providers(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
|
|
||||||
with tabs[0]:
|
with tabs[0]:
|
||||||
st.markdown("### Primary AI Providers")
|
st.markdown("### Primary AI Providers")
|
||||||
st.markdown("Configure the main AI providers for content creation")
|
|
||||||
|
|
||||||
# Create a grid layout for AI provider cards
|
# Create a grid layout for AI provider cards
|
||||||
col1, col2 = st.columns(2)
|
col1, col2 = st.columns(2)
|
||||||
@@ -59,26 +100,19 @@ def render_ai_providers(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
with col1:
|
with col1:
|
||||||
# OpenAI Card
|
# OpenAI Card
|
||||||
with st.container():
|
with st.container():
|
||||||
st.markdown("""
|
openai_input = st.text_input(
|
||||||
<div class="ai-provider-card">
|
|
||||||
<div class="ai-provider-header">
|
|
||||||
<div class="ai-provider-icon">🤖</div>
|
|
||||||
<div class="ai-provider-title">OpenAI</div>
|
|
||||||
</div>
|
|
||||||
<div class="ai-provider-content">
|
|
||||||
<p>Power your content with GPT-4 and GPT-3.5 models</p>
|
|
||||||
<div class="ai-provider-input">
|
|
||||||
""", unsafe_allow_html=True)
|
|
||||||
|
|
||||||
openai_key = st.text_input(
|
|
||||||
"OpenAI API Key",
|
"OpenAI API Key",
|
||||||
|
value=openai_key,
|
||||||
type="password",
|
type="password",
|
||||||
key="openai_key",
|
key="openai_key",
|
||||||
help="Enter your OpenAI API key"
|
help="Enter your OpenAI API key",
|
||||||
|
placeholder="Power your content generation with GPT-4 AI models"
|
||||||
)
|
)
|
||||||
|
|
||||||
if openai_key:
|
if openai_key:
|
||||||
if validate_api_key(openai_key):
|
st.success("✅ OpenAI API key found in environment")
|
||||||
|
elif openai_input:
|
||||||
|
if validate_api_key(openai_input):
|
||||||
st.markdown("""
|
st.markdown("""
|
||||||
<div class="ai-provider-status status-valid">
|
<div class="ai-provider-status status-valid">
|
||||||
✓ API key configured
|
✓ API key configured
|
||||||
@@ -103,31 +137,22 @@ def render_ai_providers(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
**Note:** Keep your API key secure and never share it publicly.
|
**Note:** Keep your API key secure and never share it publicly.
|
||||||
""")
|
""")
|
||||||
|
|
||||||
st.markdown("</div></div></div>", unsafe_allow_html=True)
|
|
||||||
|
|
||||||
with col2:
|
with col2:
|
||||||
# Google Card
|
# Google Card
|
||||||
with st.container():
|
with st.container():
|
||||||
st.markdown("""
|
gemini_input = st.text_input(
|
||||||
<div class="ai-provider-card">
|
"Google Gemini API Key",
|
||||||
<div class="ai-provider-header">
|
value=gemini_key,
|
||||||
<div class="ai-provider-icon">🔍</div>
|
|
||||||
<div class="ai-provider-title">Google Gemini</div>
|
|
||||||
</div>
|
|
||||||
<div class="ai-provider-content">
|
|
||||||
<p>Leverage Google's powerful Gemini models</p>
|
|
||||||
<div class="ai-provider-input">
|
|
||||||
""", unsafe_allow_html=True)
|
|
||||||
|
|
||||||
google_key = st.text_input(
|
|
||||||
"Google API Key",
|
|
||||||
type="password",
|
type="password",
|
||||||
key="google_key",
|
key="google_key",
|
||||||
help="Enter your Google API key"
|
help="Enter your Google API key",
|
||||||
|
placeholder="Power your content generation with Gemini AI models"
|
||||||
)
|
)
|
||||||
|
|
||||||
if google_key:
|
if gemini_key:
|
||||||
if validate_api_key(google_key):
|
st.success("✅ Gemini API key found in environment")
|
||||||
|
elif gemini_input:
|
||||||
|
if validate_api_key(gemini_input):
|
||||||
st.markdown("""
|
st.markdown("""
|
||||||
<div class="ai-provider-status status-valid">
|
<div class="ai-provider-status status-valid">
|
||||||
✓ API key configured
|
✓ API key configured
|
||||||
@@ -151,8 +176,6 @@ def render_ai_providers(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
**Note:** Make sure to enable the Gemini API in your Google Cloud Console.
|
**Note:** Make sure to enable the Gemini API in your Google Cloud Console.
|
||||||
""")
|
""")
|
||||||
|
|
||||||
st.markdown("</div></div></div>", unsafe_allow_html=True)
|
|
||||||
|
|
||||||
with tabs[1]:
|
with tabs[1]:
|
||||||
st.markdown("### Additional AI Providers")
|
st.markdown("### Additional AI Providers")
|
||||||
st.markdown("Configure additional AI providers for enhanced capabilities")
|
st.markdown("Configure additional AI providers for enhanced capabilities")
|
||||||
@@ -193,10 +216,10 @@ def render_ai_providers(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
st.info("Mistral integration will be available in the next update")
|
st.info("Mistral integration will be available in the next update")
|
||||||
|
|
||||||
# Track changes and validate keys
|
# Track changes and validate keys
|
||||||
if any([openai_key, google_key]):
|
if any([openai_input, gemini_input]):
|
||||||
changes_made = True
|
changes_made = True
|
||||||
# Check if at least one valid API key is provided
|
# Check if at least one valid API key is provided
|
||||||
if validate_api_key(openai_key) or validate_api_key(google_key):
|
if validate_api_key(openai_input) or validate_api_key(gemini_input):
|
||||||
has_valid_key = True
|
has_valid_key = True
|
||||||
validation_message = "✅ At least one AI provider configured successfully"
|
validation_message = "✅ At least one AI provider configured successfully"
|
||||||
else:
|
else:
|
||||||
@@ -214,20 +237,33 @@ def render_ai_providers(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
# Navigation buttons
|
# Navigation buttons
|
||||||
if render_navigation_buttons(1, 6, changes_made):
|
if render_navigation_buttons(1, 6, changes_made):
|
||||||
if has_valid_key:
|
if has_valid_key:
|
||||||
# Store the API keys in a separate session state key
|
|
||||||
st.session_state['api_keys'] = {
|
|
||||||
'openai': openai_key if validate_api_key(openai_key) else None,
|
|
||||||
'google': google_key if validate_api_key(google_key) else None
|
|
||||||
}
|
|
||||||
|
|
||||||
# Save API keys to .env file
|
# Save API keys to .env file
|
||||||
if validate_api_key(openai_key):
|
if validate_api_key(openai_input):
|
||||||
api_key_manager.save_api_key("openai", openai_key)
|
if save_to_env_file("OPENAI_API_KEY", openai_input):
|
||||||
logger.info("[render_ai_providers] OpenAI API key saved to .env file")
|
logger.info("[render_ai_providers] OpenAI API key saved to .env file")
|
||||||
|
else:
|
||||||
|
st.error("Failed to save OpenAI API key to .env file")
|
||||||
|
return {"current_step": 1, "error": "Failed to save OpenAI API key"}
|
||||||
|
|
||||||
if validate_api_key(google_key):
|
if validate_api_key(gemini_input):
|
||||||
api_key_manager.save_api_key("gemini", google_key)
|
if save_to_env_file("GEMINI_API_KEY", gemini_input):
|
||||||
logger.info("[render_ai_providers] Google Gemini API key saved to .env file")
|
logger.info("[render_ai_providers] Google Gemini API key saved to .env file")
|
||||||
|
else:
|
||||||
|
st.error("Failed to save Gemini API key to .env file")
|
||||||
|
return {"current_step": 1, "error": "Failed to save Gemini API key"}
|
||||||
|
|
||||||
|
# Reload environment variables to ensure consistency
|
||||||
|
load_dotenv(override=True)
|
||||||
|
|
||||||
|
# Get updated API keys from environment
|
||||||
|
updated_openai_key = os.getenv('OPENAI_API_KEY', '')
|
||||||
|
updated_gemini_key = os.getenv('GEMINI_API_KEY', '')
|
||||||
|
|
||||||
|
# Store the API keys in session state
|
||||||
|
st.session_state['api_keys'] = {
|
||||||
|
'openai': updated_openai_key,
|
||||||
|
'google': updated_gemini_key
|
||||||
|
}
|
||||||
|
|
||||||
# Update progress and move to next step
|
# Update progress and move to next step
|
||||||
st.session_state['current_step'] = 2 # Set the next step explicitly
|
st.session_state['current_step'] = 2 # Set the next step explicitly
|
||||||
|
|||||||
@@ -1,114 +0,0 @@
|
|||||||
"""AI providers setup component for API key manager."""
|
|
||||||
|
|
||||||
from typing import Dict, Any
|
|
||||||
from loguru import logger
|
|
||||||
import streamlit as st
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
def render_ai_providers_setup(api_key_manager) -> Dict[str, Any]:
|
|
||||||
"""
|
|
||||||
Render the AI providers setup component.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
api_key_manager: API key manager instance
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Dict[str, Any]: Component state
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
logger.info("[render_ai_providers_setup] Rendering AI providers setup")
|
|
||||||
|
|
||||||
# Display section header
|
|
||||||
st.header("Step 1: Select AI Providers")
|
|
||||||
st.markdown("""
|
|
||||||
Configure your AI providers to enable advanced content generation capabilities.
|
|
||||||
Choose and set up the AI services you want to use.
|
|
||||||
""")
|
|
||||||
|
|
||||||
# Create columns for different providers
|
|
||||||
col1, col2 = st.columns(2)
|
|
||||||
|
|
||||||
with col1:
|
|
||||||
st.subheader("OpenAI")
|
|
||||||
st.markdown("""
|
|
||||||
OpenAI's GPT models provide powerful natural language processing capabilities.
|
|
||||||
|
|
||||||
Get your API key from: [OpenAI Dashboard](https://platform.openai.com/account/api-keys)
|
|
||||||
""")
|
|
||||||
|
|
||||||
openai_key = api_key_manager.get_api_key("openai")
|
|
||||||
openai_input = st.text_input(
|
|
||||||
"OpenAI API Key",
|
|
||||||
value=openai_key if openai_key else "",
|
|
||||||
type="password",
|
|
||||||
key="openai_key_input"
|
|
||||||
)
|
|
||||||
|
|
||||||
with col2:
|
|
||||||
st.subheader("Google Gemini")
|
|
||||||
st.markdown("""
|
|
||||||
Google's Gemini models offer advanced AI capabilities.
|
|
||||||
|
|
||||||
Get your API key from: [Google AI Studio](https://makersuite.google.com/app/apikey)
|
|
||||||
""")
|
|
||||||
|
|
||||||
gemini_key = api_key_manager.get_api_key("gemini")
|
|
||||||
gemini_input = st.text_input(
|
|
||||||
"Gemini API Key",
|
|
||||||
value=gemini_key if gemini_key else "",
|
|
||||||
type="password",
|
|
||||||
key="gemini_key_input"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Optional AI Provider
|
|
||||||
st.subheader("Additional AI Provider (Optional)")
|
|
||||||
col1, col2 = st.columns(2)
|
|
||||||
|
|
||||||
with col1:
|
|
||||||
st.markdown("""
|
|
||||||
Mistral AI provides an alternative model for content generation.
|
|
||||||
|
|
||||||
Get your API key from: [Mistral Platform](https://console.mistral.ai/api-keys/)
|
|
||||||
""")
|
|
||||||
|
|
||||||
mistral_key = api_key_manager.get_api_key("mistral")
|
|
||||||
mistral_input = st.text_input(
|
|
||||||
"Mistral API Key (Optional)",
|
|
||||||
value=mistral_key if mistral_key else "",
|
|
||||||
type="password",
|
|
||||||
key="mistral_key_input"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Add a note about saving
|
|
||||||
st.info("""
|
|
||||||
Note: At least one AI provider (OpenAI or Google Gemini) is required.
|
|
||||||
Click Continue to save your keys and proceed.
|
|
||||||
""")
|
|
||||||
|
|
||||||
# Save keys if they've changed when proceeding to next step
|
|
||||||
if st.session_state.get('wizard_current_step', 1) > 1:
|
|
||||||
if openai_input != openai_key:
|
|
||||||
api_key_manager.save_api_key("openai", openai_input)
|
|
||||||
logger.info("[render_ai_providers_setup] OpenAI API key saved")
|
|
||||||
|
|
||||||
if gemini_input != gemini_key:
|
|
||||||
api_key_manager.save_api_key("gemini", gemini_input)
|
|
||||||
logger.info("[render_ai_providers_setup] Gemini API key saved")
|
|
||||||
|
|
||||||
if mistral_input != mistral_key:
|
|
||||||
api_key_manager.save_api_key("mistral", mistral_input)
|
|
||||||
logger.info("[render_ai_providers_setup] Mistral API key saved")
|
|
||||||
|
|
||||||
# Validate that at least one required provider is configured
|
|
||||||
if not (openai_input or gemini_input):
|
|
||||||
st.error("Please configure at least one AI provider (OpenAI or Google Gemini) to proceed.")
|
|
||||||
return {"current_step": 1, "can_proceed": False}
|
|
||||||
|
|
||||||
return {"current_step": 1, "can_proceed": bool(openai_input or gemini_input)}
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
error_msg = f"Error in AI providers setup: {str(e)}"
|
|
||||||
logger.error(f"[render_ai_providers_setup] {error_msg}")
|
|
||||||
st.error(error_msg)
|
|
||||||
return {"current_step": 1, "error": error_msg}
|
|
||||||
@@ -29,10 +29,7 @@ def render_ai_research_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
logger.info("[render_ai_research_setup] Rendering AI research setup component")
|
logger.info("[render_ai_research_setup] Rendering AI research setup component")
|
||||||
|
|
||||||
st.markdown("""
|
st.markdown("""
|
||||||
<div class='setup-header'>
|
<div class='setup-header'><h2>🔍 AI Web Research API Setup</h2></div>
|
||||||
<h2>🔍 AI Research Setup</h2>
|
|
||||||
<p>Configure your AI research providers for content analysis and research</p>
|
|
||||||
</div>
|
|
||||||
""", unsafe_allow_html=True)
|
""", unsafe_allow_html=True)
|
||||||
|
|
||||||
# Create two columns for different search types
|
# Create two columns for different search types
|
||||||
@@ -188,19 +185,7 @@ def render_ai_research_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
|
|
||||||
st.markdown("</div></div>", unsafe_allow_html=True)
|
st.markdown("</div></div>", unsafe_allow_html=True)
|
||||||
|
|
||||||
# Disabled Options Expander
|
|
||||||
with st.expander("🔜 Coming Soon - More Search Options", expanded=False):
|
|
||||||
st.markdown("""
|
|
||||||
<div style='opacity: 0.7;'>
|
|
||||||
<h4>Bing Search API</h4>
|
|
||||||
<p>Microsoft's powerful search API with web, news, and image search capabilities.</p>
|
|
||||||
|
|
||||||
<h4>Google Search API</h4>
|
|
||||||
<p>Google's programmable search engine with customizable search parameters.</p>
|
|
||||||
|
|
||||||
<p><em>These integrations are under development and will be available soon!</em></p>
|
|
||||||
</div>
|
|
||||||
""", unsafe_allow_html=True)
|
|
||||||
|
|
||||||
# Track changes
|
# Track changes
|
||||||
changes_made = bool(serpapi_key or tavily_key or metaphor_key or firecrawl_key)
|
changes_made = bool(serpapi_key or tavily_key or metaphor_key or firecrawl_key)
|
||||||
@@ -246,11 +231,16 @@ def render_ai_research_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
st.error("Please configure at least one research provider to continue")
|
st.error("Please configure at least one research provider to continue")
|
||||||
|
|
||||||
# Detailed Information Section
|
# Detailed Information Section
|
||||||
st.markdown("""
|
st.markdown("---")
|
||||||
---
|
st.markdown("### Understanding Your Research Options")
|
||||||
### Understanding Your Research Options
|
|
||||||
|
|
||||||
#### The Usual: Traditional Search
|
# Create four columns for the information popovers
|
||||||
|
info_col1, info_col2, info_col3, info_col4 = st.columns(4)
|
||||||
|
|
||||||
|
# The Usual: Traditional Search Popover
|
||||||
|
with info_col1:
|
||||||
|
with st.popover("#### The Usual: Traditional Search"):
|
||||||
|
st.markdown("""
|
||||||
**SerpAPI**
|
**SerpAPI**
|
||||||
- Real-time search results from multiple search engines
|
- Real-time search results from multiple search engines
|
||||||
- Access to structured data from search results
|
- Access to structured data from search results
|
||||||
@@ -260,9 +250,12 @@ def render_ai_research_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
- News articles
|
- News articles
|
||||||
- Knowledge graphs
|
- Knowledge graphs
|
||||||
- Related questions
|
- Related questions
|
||||||
|
""")
|
||||||
|
|
||||||
#### AI Deep Research: Advanced Search Capabilities
|
# AI Deep Research Popover
|
||||||
|
with info_col2:
|
||||||
|
with st.popover("#### AI Deep Research: Advanced Search Capabilities"):
|
||||||
|
st.markdown("""
|
||||||
**Tavily AI**
|
**Tavily AI**
|
||||||
- AI-powered search with semantic understanding
|
- AI-powered search with semantic understanding
|
||||||
- Automatically summarizes and analyzes search results
|
- Automatically summarizes and analyzes search results
|
||||||
@@ -280,9 +273,12 @@ def render_ai_research_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
- Finding similar content
|
- Finding similar content
|
||||||
- Discovering patterns in research
|
- Discovering patterns in research
|
||||||
- Understanding topic landscapes
|
- Understanding topic landscapes
|
||||||
|
""")
|
||||||
|
|
||||||
#### Choosing the Right Tool
|
# Choosing the Right Tool Popover
|
||||||
|
with info_col3:
|
||||||
|
with st.popover("#### Choosing the Right Tool"):
|
||||||
|
st.markdown("""
|
||||||
1. **For General Research:**
|
1. **For General Research:**
|
||||||
- Start with SerpAPI for broad coverage and structured data
|
- Start with SerpAPI for broad coverage and structured data
|
||||||
|
|
||||||
@@ -298,4 +294,34 @@ def render_ai_research_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
> **Pro Tip:** Configure multiple providers to ensure you have backup options and can cross-reference results for better accuracy.
|
> **Pro Tip:** Configure multiple providers to ensure you have backup options and can cross-reference results for better accuracy.
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
# Coming Soon Popover
|
||||||
|
with info_col4:
|
||||||
|
with st.popover("#### 🔜 Coming Soon - More Search Options"):
|
||||||
|
st.markdown("""
|
||||||
|
**Bing Search API**
|
||||||
|
- Microsoft's powerful search API with comprehensive capabilities
|
||||||
|
- Features include:
|
||||||
|
- Web search with advanced filtering
|
||||||
|
- News articles with sentiment analysis
|
||||||
|
- Image search with visual recognition
|
||||||
|
- Video search with content understanding
|
||||||
|
- Custom search parameters for targeted results
|
||||||
|
|
||||||
|
**Google Search API**
|
||||||
|
- Google's programmable search engine with extensive features
|
||||||
|
- Capabilities include:
|
||||||
|
- Custom search engine creation
|
||||||
|
- Site-specific search
|
||||||
|
- Image and video search
|
||||||
|
- News search with time-based filtering
|
||||||
|
- Knowledge graph integration
|
||||||
|
|
||||||
|
**Additional Planned Integrations:**
|
||||||
|
- **DuckDuckGo API**: Privacy-focused search with no tracking
|
||||||
|
- **Brave Search API**: Independent search engine with unique features
|
||||||
|
- **Perplexity API**: AI-powered research assistant with real-time data
|
||||||
|
|
||||||
|
> **Note:** These integrations are under active development and will be available in future updates.
|
||||||
|
""")
|
||||||
|
|
||||||
return {"current_step": 3, "changes_made": changes_made}
|
return {"current_step": 3, "changes_made": changes_made}
|
||||||
|
|||||||
@@ -4,12 +4,6 @@ import streamlit as st
|
|||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from ..styles import API_KEY_MANAGER_STYLES
|
from ..styles import API_KEY_MANAGER_STYLES
|
||||||
from ..wizard_state import (
|
|
||||||
get_current_step,
|
|
||||||
next_step,
|
|
||||||
previous_step,
|
|
||||||
can_proceed_to_next_step
|
|
||||||
)
|
|
||||||
|
|
||||||
def render_step_indicator(current_step: int, total_steps: int) -> None:
|
def render_step_indicator(current_step: int, total_steps: int) -> None:
|
||||||
"""Render the step indicator."""
|
"""Render the step indicator."""
|
||||||
|
|||||||
@@ -36,19 +36,20 @@ def render_website_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
"""
|
"""
|
||||||
logger.info("[render_website_setup] Rendering website setup component")
|
logger.info("[render_website_setup] Rendering website setup component")
|
||||||
|
|
||||||
st.markdown("### Step 2: Website Setup")
|
st.markdown("### Step 2: Enter Your Website URL for Analysis (Optional)")
|
||||||
|
|
||||||
# Create two columns for input and results
|
# Create two columns for input and results
|
||||||
col1, col2 = st.columns([1, 1])
|
col1, col2 = st.columns([1, 1])
|
||||||
|
|
||||||
with col1:
|
with col1:
|
||||||
st.markdown("#### Enter Website URL")
|
url = st.text_input("Enter your website URL, if you own one", placeholder="https://example.com")
|
||||||
url = st.text_input("Website URL", placeholder="https://example.com")
|
logger.info(f"[render_website_setup] URL input value: {url}")
|
||||||
logger.debug(f"[render_website_setup] URL input value: {url}")
|
|
||||||
|
|
||||||
analyze_type = st.radio(
|
analyze_type = st.radio(
|
||||||
"Analysis Type",
|
"Analysis Type",
|
||||||
["Basic Analysis", "Full Analysis with SEO"],
|
["Basic Website Analysis", "Full Website Analysis with SEO"],
|
||||||
|
horizontal=True,
|
||||||
|
label_visibility="hidden",
|
||||||
help="Choose between basic website analysis or comprehensive SEO analysis"
|
help="Choose between basic website analysis or comprehensive SEO analysis"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -115,8 +116,6 @@ def render_website_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
st.warning("Please enter a valid URL")
|
st.warning("Please enter a valid URL")
|
||||||
|
|
||||||
with col2:
|
with col2:
|
||||||
st.markdown("#### Analysis Results")
|
|
||||||
|
|
||||||
# Check if we have analysis results
|
# Check if we have analysis results
|
||||||
if 'website_analysis' in st.session_state:
|
if 'website_analysis' in st.session_state:
|
||||||
results = st.session_state.website_analysis
|
results = st.session_state.website_analysis
|
||||||
@@ -126,7 +125,7 @@ def render_website_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
analysis = data.get('analysis', {})
|
analysis = data.get('analysis', {})
|
||||||
|
|
||||||
# Create tabs for different sections
|
# Create tabs for different sections
|
||||||
if analyze_type == "Full Analysis with SEO":
|
if analyze_type == "Full Website Analysis with SEO":
|
||||||
tab1, tab2, tab3, tab4, tab5 = st.tabs([
|
tab1, tab2, tab3, tab4, tab5 = st.tabs([
|
||||||
"Basic Metrics",
|
"Basic Metrics",
|
||||||
"Content Analysis",
|
"Content Analysis",
|
||||||
@@ -237,7 +236,7 @@ def render_website_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
|
|||||||
for issue in issues:
|
for issue in issues:
|
||||||
st.write(f"• {issue}")
|
st.write(f"• {issue}")
|
||||||
|
|
||||||
with tab4 if analyze_type == "Basic Analysis" else tab5:
|
with tab4 if analyze_type == "Basic Website Analysis" else tab5:
|
||||||
st.markdown("##### Strategy Recommendations")
|
st.markdown("##### Strategy Recommendations")
|
||||||
strategy_info = analysis.get('strategy', {})
|
strategy_info = analysis.get('strategy', {})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user