mishrabp commited on
Commit
8153ec2
·
verified ·
1 Parent(s): 9e09672

Upload folder using huggingface_hub

Browse files
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.research_agent import MarketResearchAgent
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 = MarketResearchAgent.create()
153
- with trace("Chatting with AI"):
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
- if st.sidebar.button(label, key=f"prompt_{idx}"):
166
- st.session_state.auto_send_prompt = prompt_text
167
- st.markdown('</div>', unsafe_allow_html=True)
 
 
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