Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- appagents/FinancialAgent.py +56 -0
- appagents/NewsAgent.py +66 -0
- appagents/OrchestratorAgent.py +68 -0
- appagents/SearchAgent.py +58 -0
- tools/news_tools.py +1 -1
- ui/app.py +29 -6
appagents/FinancialAgent.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from tools.yahoo_tools import FinanceTools
|
| 2 |
+
from tools.time_tools import TimeTools
|
| 3 |
+
from tools.google_tools import GoogleTools
|
| 4 |
+
import os
|
| 5 |
+
from agents import Agent, OpenAIChatCompletionsModel
|
| 6 |
+
from openai import AsyncOpenAI
|
| 7 |
+
|
| 8 |
+
class FinancialAgent:
|
| 9 |
+
"""
|
| 10 |
+
Encapsulates the AI agent definition for financial analysis and market research.
|
| 11 |
+
"""
|
| 12 |
+
|
| 13 |
+
@staticmethod
|
| 14 |
+
def create():
|
| 15 |
+
"""
|
| 16 |
+
Returns a configured Agent instance ready for use.
|
| 17 |
+
"""
|
| 18 |
+
# Included all relevant tools
|
| 19 |
+
tools = [
|
| 20 |
+
TimeTools.current_datetime,
|
| 21 |
+
FinanceTools.get_market_sentiment,
|
| 22 |
+
FinanceTools.get_history,
|
| 23 |
+
GoogleTools.search
|
| 24 |
+
]
|
| 25 |
+
|
| 26 |
+
instructions = """
|
| 27 |
+
You are a specialized **Financial Analysis Agent** 💰, expert in market research, financial data retrieval, and news correlation. Your primary role is to provide *actionable*, *data-driven*, and *concise* financial reports based on the tools and current time.
|
| 28 |
+
|
| 29 |
+
## Core Directives & Priorities
|
| 30 |
+
1. **Time Sensitivity (TimeTools):** Always use the **TimeTools.current_datetime** to ensure all analysis is contextually relevant to the current date and time. Financial data is extremely time-sensitive.
|
| 31 |
+
2. **Financial Data Integrity (FinanceTools):** Use **FinanceTools** (get_history, get_market_sentiment) for specific stock/index data, historical trends, and current market sentiment. Be precise about the date range and data source.
|
| 32 |
+
3. **Market Catalysts (NewsTools/WebSearch):** Utilize **NewsTools** and **WebSearchTool** to identify and incorporate recent news, earnings announcements, economic reports, or significant events that are *catalysts* for the requested financial query.
|
| 33 |
+
4. **Synthesis and Analysis:** Do not just list data. You must **synthesize** financial data (prices, volume, sentiment) with relevant news to provide a complete analytical perspective (e.g., "Stock X is up 5% today (get_history) driven by a positive Q3 earnings surprise (get_news_by_topic)").
|
| 34 |
+
5. **Professional Clarity:** Present information in a clear, professional, and structured format. Use numerical data and financial terminology correctly.
|
| 35 |
+
6. **No Financial Advice:** Explicitly state that your analysis is for informational purposes only and is **not financial advice**.
|
| 36 |
+
7. **Tool Mandatory:** For any request involving a stock, index, or current market conditions, you **must** use the appropriate tool(s) to verify data. **Strictly avoid speculation or using internal knowledge for data points.**
|
| 37 |
+
|
| 38 |
+
## Output Format Guidelines
|
| 39 |
+
* Use **bold** for key financial metrics (e.g., Stock Symbol, Price, Volume).
|
| 40 |
+
* Cite the tools used to obtain the data (e.g., Data sourced from FinanceTools (Yahoo) as of [Date]).
|
| 41 |
+
* If a symbol or data point cannot be found, clearly state "Data for [X] is unavailable or invalid."
|
| 42 |
+
"""
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/"
|
| 46 |
+
google_api_key = os.getenv('GOOGLE_API_KEY')
|
| 47 |
+
gemini_client = AsyncOpenAI(base_url=GEMINI_BASE_URL, api_key=google_api_key)
|
| 48 |
+
gemini_model = OpenAIChatCompletionsModel(model="gemini-2.0-flash", openai_client=gemini_client)
|
| 49 |
+
|
| 50 |
+
agent = Agent(
|
| 51 |
+
name="Financial Analysis Agent",
|
| 52 |
+
tools=tools,
|
| 53 |
+
instructions=instructions,
|
| 54 |
+
model=gemini_model
|
| 55 |
+
)
|
| 56 |
+
return agent
|
appagents/NewsAgent.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from tools.news_tools import NewsTools
|
| 2 |
+
from tools.time_tools import TimeTools
|
| 3 |
+
from tools.google_tools import GoogleTools
|
| 4 |
+
# from tools.yahoo_tools import FinanceTools # Removed: Not needed for a pure News Agent
|
| 5 |
+
import os
|
| 6 |
+
from agents import Agent, OpenAIChatCompletionsModel
|
| 7 |
+
from openai import AsyncOpenAI
|
| 8 |
+
|
| 9 |
+
class NewsAgent:
|
| 10 |
+
"""
|
| 11 |
+
Encapsulates the AI agent definition for real-time news gathering, summarization, and reporting.
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
@staticmethod
|
| 15 |
+
def create():
|
| 16 |
+
"""
|
| 17 |
+
Returns a configured Agent instance ready for use.
|
| 18 |
+
"""
|
| 19 |
+
# Corrected tool list: removed FinanceTools, added WebSearchTool
|
| 20 |
+
tools = [
|
| 21 |
+
TimeTools.current_datetime,
|
| 22 |
+
NewsTools.top_headlines,
|
| 23 |
+
NewsTools.search_news,
|
| 24 |
+
GoogleTools.search
|
| 25 |
+
]
|
| 26 |
+
|
| 27 |
+
instructions = """
|
| 28 |
+
You are a specialized **News Reporting Agent** 📰, expert in retrieving, summarizing, and synthesizing current events and information from various sources. Your primary role is to deliver a concise, objective, and timely news digest or report.
|
| 29 |
+
|
| 30 |
+
## Core Directives & Priorities
|
| 31 |
+
1. **Immediacy and Context (TimeTools):** Always use **TimeTools.current_datetime** to contextualize all reports. Clearly indicate when the information was retrieved (e.g., "As of [Date/Time]").
|
| 32 |
+
2. **News Retrieval (NewsTools):**
|
| 33 |
+
* For general awareness, use **NewsTools.top_headlines**.
|
| 34 |
+
* For specific topics, use **NewsTools.search_news**.
|
| 35 |
+
* Prioritize the most recent articles.
|
| 36 |
+
3. **Comprehensive Search (WebSearchTool):** Use the **WebSearchTool (Google Search)** for:
|
| 37 |
+
* Verifying facts or statistics found in news articles.
|
| 38 |
+
* Gathering background context on a complex story.
|
| 39 |
+
* Finding information not covered by the dedicated news API.
|
| 40 |
+
4. **Objective Synthesis:** Do not express opinions or speculate. You must **synthesize** information from multiple articles or tools to provide a **balanced and neutral summary**. Avoid sensationalism.
|
| 41 |
+
5. **Attribution and Transparency:** Every piece of reported information must be sourced. Cite the original publication or the tool used (e.g., "The New York Times reported...", "According to data found via WebSearch..."). Provide links where available.
|
| 42 |
+
6. **Structured Reporting:** Present the information clearly. For complex topics, use bullet points, subheadings, and a brief introductory summary.
|
| 43 |
+
7. **Data Gaps:** If a requested topic yields no recent or verifiable information, explicitly state: **"No verifiable recent news could be found on [Topic]."**
|
| 44 |
+
|
| 45 |
+
## Output Format Guidelines
|
| 46 |
+
* Start with a brief, high-level summary of the answer.
|
| 47 |
+
* Use **bold** for key names, dates, and locations.
|
| 48 |
+
* List news sources clearly with the article title and, if possible, the link/publication name.
|
| 49 |
+
* Maintain a professional, journalistic tone.
|
| 50 |
+
|
| 51 |
+
**Strictly adhere to verifiable facts and avoid making up any information.**
|
| 52 |
+
"""
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/"
|
| 56 |
+
google_api_key = os.getenv('GOOGLE_API_KEY')
|
| 57 |
+
gemini_client = AsyncOpenAI(base_url=GEMINI_BASE_URL, api_key=google_api_key)
|
| 58 |
+
gemini_model = OpenAIChatCompletionsModel(model="gemini-2.0-flash", openai_client=gemini_client)
|
| 59 |
+
|
| 60 |
+
agent = Agent(
|
| 61 |
+
name="News Reporting Agent",
|
| 62 |
+
tools=tools,
|
| 63 |
+
instructions=instructions,
|
| 64 |
+
model=gemini_model #"gpt-4o-mini"
|
| 65 |
+
)
|
| 66 |
+
return agent
|
appagents/OrchestratorAgent.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from appagents.FinancialAgent import FinancialAgent
|
| 2 |
+
from appagents.NewsAgent import NewsAgent
|
| 3 |
+
from appagents.SearchAgent import SearchAgent
|
| 4 |
+
import os
|
| 5 |
+
from agents import Agent, OpenAIChatCompletionsModel
|
| 6 |
+
from openai import AsyncOpenAI
|
| 7 |
+
|
| 8 |
+
class OrchestratorAgent:
|
| 9 |
+
"""
|
| 10 |
+
The OrchestratorAgent coordinates multiple specialized agents
|
| 11 |
+
(financial, news, and search) to provide accurate and up-to-date
|
| 12 |
+
market research insights.
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
@staticmethod
|
| 16 |
+
def create(model: str = "gpt-4o-mini"):
|
| 17 |
+
"""
|
| 18 |
+
Creates and returns a configured Agent instance with
|
| 19 |
+
predefined instructions and connected sub-agents.
|
| 20 |
+
"""
|
| 21 |
+
|
| 22 |
+
# Define sub-agents for specialized handoffs
|
| 23 |
+
handoffs = [
|
| 24 |
+
FinancialAgent.create(),
|
| 25 |
+
NewsAgent.create(),
|
| 26 |
+
SearchAgent.create()
|
| 27 |
+
]
|
| 28 |
+
|
| 29 |
+
# Core behavioral and ethical instructions
|
| 30 |
+
instructions = """
|
| 31 |
+
You are an AI research assistant designed to deliver accurate,
|
| 32 |
+
concise, and verifiable answers.
|
| 33 |
+
|
| 34 |
+
**Your Core Priorities**
|
| 35 |
+
1. **Current Awareness:** Always use the Time Tool to maintain awareness
|
| 36 |
+
of the current date and time for contextual accuracy.
|
| 37 |
+
2. **Accuracy and Recency:** Base all responses on the latest and most
|
| 38 |
+
reliable data available.
|
| 39 |
+
3. **Tool Usage:** For questions involving current events, statistics,
|
| 40 |
+
or factual updates, invoke the appropriate tools (Search, News, APIs)
|
| 41 |
+
to confirm or refresh information before responding.
|
| 42 |
+
4. **Synthesis:** When using multiple data sources, integrate findings
|
| 43 |
+
into a coherent, factual, and reader-friendly summary.
|
| 44 |
+
5. **Source Transparency:** Always cite your sources clearly (e.g., URLs,
|
| 45 |
+
named publications, or APIs).
|
| 46 |
+
6. **Clarity and Brevity:** Use professional, direct language. Avoid
|
| 47 |
+
speculation, filler text, or redundancy.
|
| 48 |
+
7. **Simplification:** Present complex topics in simple, accessible terms
|
| 49 |
+
suitable for a general audience.
|
| 50 |
+
8. **Verification:** If information cannot be confirmed, explicitly state
|
| 51 |
+
that the data could not be verified or is unavailable.
|
| 52 |
+
|
| 53 |
+
⚠️ Do **not fabricate** or infer details without verifiable evidence.
|
| 54 |
+
"""
|
| 55 |
+
|
| 56 |
+
GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/"
|
| 57 |
+
google_api_key = os.getenv('GOOGLE_API_KEY')
|
| 58 |
+
gemini_client = AsyncOpenAI(base_url=GEMINI_BASE_URL, api_key=google_api_key)
|
| 59 |
+
gemini_model = OpenAIChatCompletionsModel(model="gemini-2.0-flash", openai_client=gemini_client)
|
| 60 |
+
|
| 61 |
+
# Create and return the configured agent
|
| 62 |
+
agent = Agent(
|
| 63 |
+
name="AI Market Research Assistant",
|
| 64 |
+
handoffs=handoffs,
|
| 65 |
+
instructions=instructions.strip(),
|
| 66 |
+
model=gemini_model
|
| 67 |
+
)
|
| 68 |
+
return agent
|
appagents/SearchAgent.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from tools.google_tools import GoogleTools
|
| 2 |
+
from tools.time_tools import TimeTools
|
| 3 |
+
from agents import Agent, WebSearchTool # Assuming WebSearchTool is the same as GoogleTools
|
| 4 |
+
import os
|
| 5 |
+
from agents import Agent, OpenAIChatCompletionsModel
|
| 6 |
+
from openai import AsyncOpenAI
|
| 7 |
+
|
| 8 |
+
class SearchAgent:
|
| 9 |
+
"""
|
| 10 |
+
Encapsulates the AI agent definition for conducting comprehensive web searches and synthesizing information.
|
| 11 |
+
"""
|
| 12 |
+
|
| 13 |
+
@staticmethod
|
| 14 |
+
def create():
|
| 15 |
+
"""
|
| 16 |
+
Returns a configured Agent instance ready for use.
|
| 17 |
+
"""
|
| 18 |
+
# The tool list is correct for a pure search agent
|
| 19 |
+
tools = [
|
| 20 |
+
TimeTools.current_datetime,
|
| 21 |
+
GoogleTools.search,
|
| 22 |
+
]
|
| 23 |
+
|
| 24 |
+
instructions = """
|
| 25 |
+
You are a highly efficient and specialized **Web Search Agent** 🌐. Your sole function is to retrieve and analyze information from the internet using the **GoogleTools.search** function. You must act as a digital librarian and researcher, providing synthesized, cited, and up-to-date answers.
|
| 26 |
+
|
| 27 |
+
## Core Directives & Priorities
|
| 28 |
+
1. **Search First:** For virtually *every* factual query, you must invoke **GoogleTools.search** before responding. Your primary source of truth is the current web search results.
|
| 29 |
+
2. **Query Optimization:** Before calling the tool, analyze the user's request and construct the most effective, concise, and targeted search queries (1-3 queries max). Use specific keywords, dates, or phrases to ensure relevant results.
|
| 30 |
+
3. **Time Sensitivity (TimeTools):** Use **TimeTools.current_datetime** to contextualize time-sensitive queries. Results must reflect the current state of information.
|
| 31 |
+
4. **Verification and Synthesis:**
|
| 32 |
+
* **Verification:** Corroborate facts by checking multiple search results if necessary. If results conflict, report the disagreement and the most common or reputable finding.
|
| 33 |
+
* **Synthesis:** Aggregate the key findings from the search snippets into a single, comprehensive, and easy-to-read answer. Do not simply list the search results.
|
| 34 |
+
5. **Source Transparency (Citation Mandatory):** You **must** provide clear citation for all facts. At the end of your response, list the source titles and URLs from the Google Search results used to construct the answer.
|
| 35 |
+
6. **Clarity and Brevity:** Use professional, plain language. Structure the response using headings and bullet points for complex topics. Avoid filler text or unnecessary detail.
|
| 36 |
+
7. **Data Gaps:** If no relevant or conclusive information is found via the search tool, explicitly state: **"A conclusive answer could not be verified by current web search results."**
|
| 37 |
+
|
| 38 |
+
## Output Format Guidelines
|
| 39 |
+
* Begin with a direct answer to the user's question.
|
| 40 |
+
* Use **bold** for key facts, names, dates, or statistics.
|
| 41 |
+
* Conclude the response with a separate "Sources" section citing the search results.
|
| 42 |
+
|
| 43 |
+
**Crucially, never fabricate information or provide an answer without grounding it in the search results.**
|
| 44 |
+
"""
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/"
|
| 48 |
+
google_api_key = os.getenv('GOOGLE_API_KEY')
|
| 49 |
+
gemini_client = AsyncOpenAI(base_url=GEMINI_BASE_URL, api_key=google_api_key)
|
| 50 |
+
gemini_model = OpenAIChatCompletionsModel(model="gemini-2.0-flash", openai_client=gemini_client)
|
| 51 |
+
|
| 52 |
+
agent = Agent(
|
| 53 |
+
name="Web Search Agent",
|
| 54 |
+
tools=tools,
|
| 55 |
+
instructions=instructions,
|
| 56 |
+
model=gemini_model
|
| 57 |
+
)
|
| 58 |
+
return agent
|
tools/news_tools.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
| 1 |
import os
|
| 2 |
import requests
|
| 3 |
-
import yfinance as yf
|
| 4 |
from dotenv import load_dotenv
|
| 5 |
from agents import function_tool
|
| 6 |
from core.logger import log_call
|
|
|
|
| 7 |
|
| 8 |
# Load environment variables once
|
| 9 |
load_dotenv()
|
|
|
|
| 1 |
import os
|
| 2 |
import requests
|
|
|
|
| 3 |
from dotenv import load_dotenv
|
| 4 |
from agents import function_tool
|
| 5 |
from core.logger import log_call
|
| 6 |
+
import datetime
|
| 7 |
|
| 8 |
# Load environment variables once
|
| 9 |
load_dotenv()
|
ui/app.py
CHANGED
|
@@ -7,7 +7,7 @@ import sys
|
|
| 7 |
# Add project root
|
| 8 |
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
| 9 |
|
| 10 |
-
from appagents.
|
| 11 |
from agents import Runner, trace
|
| 12 |
|
| 13 |
# -----------------------------
|
|
@@ -124,6 +124,25 @@ section[data-testid="stSidebar"] {padding-top: 0.5rem !important;}
|
|
| 124 |
.mobile-prompts { display: none; }
|
| 125 |
.desktop-sidebar { display: block; }
|
| 126 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
</style>
|
| 128 |
""", unsafe_allow_html=True)
|
| 129 |
|
|
@@ -149,8 +168,8 @@ if "auto_send_prompt" not in st.session_state:
|
|
| 149 |
# Async AI response
|
| 150 |
# -----------------------------
|
| 151 |
async def get_ai_response(prompt: str) -> str:
|
| 152 |
-
agent =
|
| 153 |
-
with trace("
|
| 154 |
result = await Runner.run(agent, prompt)
|
| 155 |
return result.final_output
|
| 156 |
|
|
@@ -159,12 +178,16 @@ async def get_ai_response(prompt: str) -> str:
|
|
| 159 |
# -----------------------------
|
| 160 |
with st.sidebar.container() if st.config.get_option("server.headless") is False else st.container() as container:
|
| 161 |
st.markdown('<div class="desktop-sidebar">', unsafe_allow_html=True)
|
|
|
|
| 162 |
st.sidebar.title("💡 Quick Prompts")
|
|
|
|
| 163 |
for idx, prompt_text in enumerate(prompts):
|
| 164 |
label = prompt_labels[idx] if idx < len(prompt_labels) else f"Prompt {idx+1}"
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
st.markdown(
|
|
|
|
|
|
|
| 168 |
|
| 169 |
# -----------------------------
|
| 170 |
# Mobile Quick Prompts
|
|
|
|
| 7 |
# Add project root
|
| 8 |
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
| 9 |
|
| 10 |
+
from appagents.OrchestratorAgent import OrchestratorAgent
|
| 11 |
from agents import Runner, trace
|
| 12 |
|
| 13 |
# -----------------------------
|
|
|
|
| 124 |
.mobile-prompts { display: none; }
|
| 125 |
.desktop-sidebar { display: block; }
|
| 126 |
}
|
| 127 |
+
|
| 128 |
+
.quick-prompts-grid {
|
| 129 |
+
display: flex;
|
| 130 |
+
flex-wrap: wrap;
|
| 131 |
+
gap: 0.5rem;
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
.quick-prompts-grid button {
|
| 135 |
+
flex: 1 1 45%; /* two buttons per row approx */
|
| 136 |
+
min-width: 120px;
|
| 137 |
+
max-width: 250px;
|
| 138 |
+
padding: 0.5rem 1rem;
|
| 139 |
+
border-radius: 8px;
|
| 140 |
+
border: 1px solid #ccc;
|
| 141 |
+
background-color: #f5f5f5;
|
| 142 |
+
cursor: pointer;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
|
| 146 |
</style>
|
| 147 |
""", unsafe_allow_html=True)
|
| 148 |
|
|
|
|
| 168 |
# Async AI response
|
| 169 |
# -----------------------------
|
| 170 |
async def get_ai_response(prompt: str) -> str:
|
| 171 |
+
agent = OrchestratorAgent.create()
|
| 172 |
+
with trace("Chatbot Search Agent Run"):
|
| 173 |
result = await Runner.run(agent, prompt)
|
| 174 |
return result.final_output
|
| 175 |
|
|
|
|
| 178 |
# -----------------------------
|
| 179 |
with st.sidebar.container() if st.config.get_option("server.headless") is False else st.container() as container:
|
| 180 |
st.markdown('<div class="desktop-sidebar">', unsafe_allow_html=True)
|
| 181 |
+
# Desktop Quick Prompts
|
| 182 |
st.sidebar.title("💡 Quick Prompts")
|
| 183 |
+
buttons_html = '<div class="quick-prompts-grid">'
|
| 184 |
for idx, prompt_text in enumerate(prompts):
|
| 185 |
label = prompt_labels[idx] if idx < len(prompt_labels) else f"Prompt {idx+1}"
|
| 186 |
+
buttons_html += f'<button onclick="window.location.href=\'#\'" id="prompt_{idx}">{label}</button>'
|
| 187 |
+
buttons_html += '</div>'
|
| 188 |
+
st.sidebar.markdown(buttons_html, unsafe_allow_html=True)
|
| 189 |
+
|
| 190 |
+
|
| 191 |
|
| 192 |
# -----------------------------
|
| 193 |
# Mobile Quick Prompts
|