tet-ana commited on
Commit
bf5412e
·
verified ·
1 Parent(s): 76a1a6d

Upload 3 files

Browse files
Files changed (3) hide show
  1. analytics_agent_new.py +155 -0
  2. coordinator_agent.py +59 -0
  3. rag_agent.py +72 -0
analytics_agent_new.py ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # ✅ Import Libraries
3
+ import os
4
+ import pandas as pd
5
+ import numpy as np
6
+ import matplotlib.pyplot as plt
7
+ from prophet import Prophet
8
+ from statsmodels.tsa.arima.model import ARIMA
9
+ import gradio as gr
10
+ import re
11
+ from dotenv import load_dotenv
12
+ from langchain_google_genai import ChatGoogleGenerativeAI
13
+ from langchain.agents import Tool, initialize_agent
14
+ from langchain.agents.agent_types import AgentType
15
+ import zipfile
16
+ import chromadb
17
+ from langchain.vectorstores import Chroma
18
+ from langchain.embeddings import HuggingFaceEmbeddings
19
+ from langgraph.prebuilt import create_react_agent
20
+
21
+ # ✅ Load Environment Variables from .env or set securely
22
+ load_dotenv()
23
+
24
+ # ✅ Setup Gemini Model
25
+ llm = ChatGoogleGenerativeAI(model="models/gemini-1.5-flash", google_api_key=os.getenv("GOOGLE_API_KEY"))
26
+
27
+ # ✅ Upload and Load Chroma Vector Store
28
+ # uploaded = files.upload()
29
+ # for filename in uploaded.keys():
30
+ # if filename.endswith(".zip"):
31
+ # with zipfile.ZipFile(filename, 'r') as zip_ref:
32
+ # zip_ref.extractall("/content/chroma_db")
33
+ # print(f"✅ Extracted: {filename} to /content/chroma_db")
34
+
35
+ persistent_client = chromadb.PersistentClient(path="chroma/")
36
+ vectorstore = Chroma(
37
+ client=persistent_client,
38
+ collection_name="financial_reports",
39
+ embedding_function=HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
40
+ )
41
+
42
+ # ✅ Forecasting utility functions
43
+ def parse_yearly_data(text):
44
+ pattern = r"(\d{4})[^0-9]{1,10}?([\d.,]+)[\s]?[BbMm]?"
45
+ matches = re.findall(pattern, text)
46
+ data = {}
47
+ for year, value in matches:
48
+ try:
49
+ value = float(value.replace(',', ''))
50
+ data[int(year)] = value
51
+ except ValueError:
52
+ continue
53
+ return dict(sorted(data.items()))
54
+
55
+ def forecast_next_value(data: dict):
56
+ years = list(data.keys())
57
+ values = list(data.values())
58
+ if len(years) < 2:
59
+ raise ValueError("❌ Error: Need at least 2 years of numerical data in your query to generate a forecast.\n\n👉 Try rephrasing and include examples like 'Revenue was 100B in 2022 and 120B in 2023'.")
60
+ delta = values[-1] - values[-2]
61
+ next_year = years[-1] + 1
62
+ next_value = values[-1] + delta
63
+ data[next_year] = next_value
64
+ return data
65
+
66
+ def forecast_with_prophet(data):
67
+ try:
68
+ df = pd.DataFrame({"ds": pd.to_datetime([f"{year}-01-01" for year in data.keys()], errors='coerce'), "y": list(data.values())})
69
+ df = df.dropna()
70
+ if len(df) < 2:
71
+ return "⚠️ Not enough valid data for Prophet."
72
+ model = Prophet()
73
+ model.fit(df)
74
+ future = model.make_future_dataframe(periods=1, freq='Y')
75
+ forecast = model.predict(future)
76
+ return forecast.iloc[-1]['yhat']
77
+ except Exception as e:
78
+ return f"⚠️ Prophet forecast failed: {str(e)}"
79
+
80
+ def forecast_with_arima(data):
81
+ try:
82
+ values = list(data.values())
83
+ if len(values) < 3:
84
+ return "⚠️ Not enough data for ARIMA."
85
+ model = ARIMA(values, order=(1, 1, 1))
86
+ model_fit = model.fit()
87
+ return model_fit.forecast()[0]
88
+ except Exception as e:
89
+ return f"⚠️ ARIMA forecast failed: {str(e)}"
90
+
91
+ def plot_forecast(data: dict, title="Financial Forecast"):
92
+ years = list(data.keys())
93
+ values = list(data.values())
94
+ plt.figure(figsize=(8, 5))
95
+ plt.plot(years, values, marker='o', linestyle='-')
96
+ plt.title(title)
97
+ plt.xlabel("Year")
98
+ plt.ylabel("Value")
99
+ plt.grid(True)
100
+ plt.tight_layout()
101
+ plt.savefig("forecast.png")
102
+ plt.close()
103
+
104
+ # ✅ Forecasting Tool Function
105
+ last_data_source = ""
106
+
107
+ def forecast_tool_func(query: str) -> str:
108
+ global last_data_source
109
+ data = parse_yearly_data(query)
110
+ if not data or len(data) < 2:
111
+ raise ValueError("❌ Error: Need at least 2 years of numerical data in your query to generate a forecast.\n\n👉 Try rephrasing and include examples like 'Revenue was 100B in 2022 and 120B in 2023'.")
112
+
113
+ extrapolated = forecast_next_value(data.copy())
114
+ prophet_result = forecast_with_prophet(data)
115
+ arima_result = forecast_with_arima(data)
116
+ plot_forecast(extrapolated, title="Forecast based on financial data")
117
+ last_data_source = query
118
+
119
+ result_text = (
120
+ f"📈 Forecast complete using Prophet and ARIMA.\n"
121
+ f"🔮 Prophet prediction for {max(data.keys()) + 1}: {prophet_result}\n"
122
+ f"📊 ARIMA prediction for {max(data.keys()) + 1}: {arima_result}\n"
123
+ f"🖼️ Plot saved as forecast.png.\n"
124
+ f"\n📌 Source data extracted from your query: '{query}'"
125
+ f"\n🔢 Parsed numeric data: {data}"
126
+ )
127
+ return result_text
128
+
129
+ # ✅ LangChain Tool and Agent
130
+ forecast_tool = Tool(
131
+ name="FinancialForecaster",
132
+ func=forecast_tool_func,
133
+ description="Use this tool to forecast financial metrics based on yearly values given in the user's query. It parses numerical data and extrapolates one year forward using Prophet and ARIMA, also saving a plot."
134
+ )
135
+
136
+ # analytics_agent = initialize_agent(
137
+ # tools=[forecast_tool],
138
+ # llm=llm,
139
+ # agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
140
+ # verbose=True
141
+ # )
142
+
143
+ analytics_agent = create_react_agent(
144
+ model=llm,
145
+ tools=[forecast_tool],
146
+ name="analytics_agent",
147
+ prompt=(
148
+ "You are a financial forecasting assistant. Based on the user's query, "
149
+ "extract yearly data and forecast the next year's value using Prophet and ARIMA.\n"
150
+ "Your job is to answer user questions involving trends, predictions, market dynamics, and revenue projections.\n"
151
+ "Respond clearly with citations where appropriate.\n"
152
+ "If you cannot find any relevant data in the user's query, respond with 'No relevant data found.'\n"
153
+ "If you find relevant data but cannot make a prediction, respond with 'Prediction not possible.'\n"
154
+ )
155
+ )
coordinator_agent.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # agents/coordinator_agent.py
2
+ # coordinator_agent.py
3
+
4
+ from langchain.chat_models import init_chat_model
5
+ from langgraph_supervisor import create_supervisor
6
+ from web_agent import web_agent # <-- импортируй deinen Web-Agent mit Tool
7
+ import os
8
+ from langchain_core.tools import Tool
9
+ from langgraph.prebuilt import create_react_agent
10
+ from rag_agent import financial_rag_agent
11
+ from analytics_agent_new import analytics_agent
12
+
13
+
14
+ gemini_model = init_chat_model("gemini-2.0-flash", model_provider="google_genai")
15
+ # 🧠 Koordinator-Agent mit Gemini 2.0 Flash
16
+ coordinator_agent = create_supervisor(
17
+ agents=[web_agent, analytics_agent, financial_rag_agent],
18
+ model=gemini_model,
19
+ prompt=(
20
+ # "Du bist ein Koordinator-Agent, der zwei spezialisierte Agenten verwaltet:\n"
21
+ # "- web_agent für Nachrichten und aktuelle Informationen und stock prices and financial news, schlusskurs\n"
22
+ # "- analytics_agent für Analyse, Prognosen und Finanzbewertung\n"
23
+ # "\n"
24
+ # "Wähle den passenden Agenten basierend auf der Nutzerfrage.\n"
25
+ # "Gib die Antworten und Ergebnisse von Agenten zurück und zeight mir die Antworten."
26
+ # "Du bist ein intelligenter Koordinator-Agent, der drei spezialisierte Agenten verwaltet:\n"
27
+ # "1. 📰 web_agent\n"
28
+ # " - Recherchiert aktuelle Nachrichten, Aktienkurse, Schlusskurse und wirtschaftliche Entwicklungen im Internet.\n"
29
+ # " - Verwenden, wenn die Nutzerfrage aktuelle Daten oder Marktgeschehen betrifft.\n\n"
30
+ # "2. 📊 analytics_agent\n"
31
+ # " - Führt Marktanalysen, statistische Bewertungen, Prognosen oder Wirtschaftstrend-Analysen durch.\n"
32
+ # " - Verwenden, wenn analytische oder bewertende Aufgaben verlangt sind.\n\n"
33
+ # "3. 📁 financial_rag_agent\n"
34
+ # " - Beantwortet Fragen zu historischen Finanzberichten (10-K, 10-Q, Annual Reports) der Unternehmen Apple, Microsoft, Google, NVIDIA und Meta aus den letzten fünf Jahren.\n"
35
+ # " - Gibt präzise Antworten mit Angabe der Quelle (Firma, Jahr, Dokumenttyp, Dateiname).\n"
36
+ # " - Verwenden, wenn es um offizielle Unternehmensberichte oder dokumentierte Geschäftszahlen geht.\n\n"
37
+ # "🔍 Deine Aufgabe:\n"
38
+ # #"Analysiere die Benutzeranfrage sorgfältig und leite sie ausschließlich an den passenden Agenten weiter.\n\n"
39
+ # "Assign work to one agent at a time, do not call agents in parallel.\n\n"
40
+ # "🔒 Du darfst nicht selbst antworten. Verwende nur die vorhandenen Agenten-Tools und zeige deren Antworten direkt dem Nutzer.\n\n"
41
+ # "Beispiele:\n"
42
+ # "- \"Was war NVIDIAs Umsatz im Jahr 2022?\" → 📁 financial_rag_agent\n"
43
+ # "- \"Wie sieht die Prognose für den Halbleitermarkt aus?\" → 📊 analytics_agent\n"
44
+ # "- \"Was sind die aktuellen Nachrichten zu Apple?\" → 📰 web_agent\n"
45
+ "Du bist ein intelligenter Koordinator-Agent, der drei spezialisierte Agenten verwaltet:\n\n"
46
+ "1. 📰 web_agent – für aktuelle Nachrichten, Aktienkurse und wirtschaftliche Entwicklungen.\n"
47
+ "2. 📊 analytics_agent – für Marktanalysen, Prognosen und statistische Bewertungen.\n"
48
+ "3. 📁 financial_rag_agent – für historische Finanzberichte (10-K, 10-Q, Annual Reports) von Apple, Microsoft, Google, NVIDIA und Meta.\n\n"
49
+ "🔍 Deine Aufgabe:\n"
50
+ "Führe bei jeder Nutzeranfrage alle drei Agenten nacheinander aus, in folgender Reihenfolge:\n\n"
51
+ "1. 📁 financial_rag_agent\n"
52
+ "2. 📊 analytics_agent\n"
53
+ "3. 📰 web_agent\n\n"
54
+ "Übergebe die ursprüngliche Frage und ggf. Zwischenergebnisse als Kontext weiter.\n\n"
55
+ "🔒 Antworte niemals selbst. Gib nur die Antworten der Agenten weiter.\n"
56
+ ),
57
+ add_handoff_back_messages=True,
58
+ output_mode="full_history",
59
+ ).compile()
rag_agent.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.documents import Document
2
+ from langchain_core.messages import HumanMessage, AIMessage
3
+ from typing import Dict, List
4
+ from langchain_chroma import Chroma
5
+ from langchain_google_genai import GoogleGenerativeAIEmbeddings
6
+ import chromadb
7
+ import os
8
+ from langchain.tools import Tool
9
+ from langgraph.prebuilt import create_react_agent
10
+ from langchain.chat_models import init_chat_model
11
+
12
+ # 🤖 Web-Agent mit Gemini 2.0 Flash
13
+ gemini_model = init_chat_model("gemini-2.0-flash", model_provider="google_genai")
14
+
15
+ persistent_client = chromadb.PersistentClient(path="chroma/")
16
+ embeddings = GoogleGenerativeAIEmbeddings(model="models/text-embedding-004", google_api_key=os.getenv("GOOGLE_API_KEY"))
17
+
18
+ vector_store = Chroma(
19
+ client=persistent_client,
20
+ collection_name="big_tech_financial_reports",
21
+ embedding_function=embeddings,
22
+ )
23
+
24
+ # Функция: отвечает на финансовый запрос с цитированием источников
25
+ def answer_financial_query(query: str) -> str:
26
+ # Используем глобальные vector_store и llm
27
+ global vector_store, gemini_model
28
+
29
+ query_embedding = embeddings.embed_query(query)
30
+ retrieved_docs = vector_store.similarity_search_by_vector(query_embedding, k=5)
31
+
32
+ context = "\n\n".join([
33
+ f"[{doc.metadata['company']}, {doc.metadata['year']}, {doc.metadata['type']}, {doc.metadata['source']}]:\n{doc.page_content}"
34
+ for doc in retrieved_docs
35
+ ])
36
+
37
+ prompt = f"""
38
+ You are a financial assistant. Based only on the following financial report excerpts, answer the user's query.
39
+ Use a clear and concise tone and cite the company, year, document type, and source for any fact.
40
+
41
+ User Query: {query}
42
+
43
+ Documents:
44
+ {context}
45
+
46
+ Answer:
47
+ """
48
+
49
+ response = gemini_model([HumanMessage(content=prompt)])
50
+ return response.content
51
+
52
+ financial_rag_tool = Tool(
53
+ name="analyze_financial_report",
54
+ func=answer_financial_query,
55
+ description=(
56
+ "Beantworte Fragen zu Finanzberichten, Bilanzen, Quartalszahlen und Jahresabschlüssen "
57
+ "von Apple, Microsoft, Google, NVIDIA und Meta in den letzten fünf Jahren. "
58
+ "Die Antworten enthalten genaue Quellenangaben zum Bericht."
59
+ )
60
+ )
61
+
62
+ financial_rag_agent = create_react_agent(
63
+ model=gemini_model,
64
+ tools=[financial_rag_tool],
65
+ name="financial_rag_agent",
66
+ prompt=(
67
+ "Du bist ein spezialisierter Finanzassistent.\n"
68
+ "Du beantwortest ausschließlich Fragen zu den Finanzberichten von Apple, Microsoft, Google, NVIDIA und Meta.\n"
69
+ "Nutze ausschließlich das Tool 'analyze_financial_report', um Informationen aus diesen Quellen zu beziehen.\n"
70
+ "Gib stets eine präzise Antwort mit Angabe der Quelle (Unternehmen, Jahr, Berichtstyp, Dateiname)."
71
+ )
72
+ )