Spaces:
Runtime error
Runtime error
Upload folder using huggingface_hub
Browse files- Dockerfile +2 -2
- common/utility/autogen_model_factory.py +25 -1
- pyproject.toml +6 -0
- run.py +156 -15
- src/chatbot_v1/Dockerfile +35 -0
- src/chatbot_v1/README.md +223 -0
- src/chatbot_v1/aagents/__init__.py +0 -0
- src/chatbot_v1/aagents/input_validation_agent.py +58 -0
- src/chatbot_v1/aagents/orchestrator_agent.py +96 -0
- src/chatbot_v1/app.py +317 -0
- src/chatbot_v1/prompts/economic_news.txt +27 -0
- src/chatbot_v1/prompts/entertainment_updates.txt +26 -0
- src/chatbot_v1/prompts/india_news.txt +26 -0
- src/chatbot_v1/prompts/market_sentiment.txt +34 -0
- src/chatbot_v1/prompts/news_headlines.txt +28 -0
- src/chatbot_v1/prompts/odia_news.txt +26 -0
- src/chatbot_v1/prompts/trade_recommendation.txt +40 -0
- src/chatbot_v1/prompts/upcoming_earnings.txt +27 -0
- src/chatbot_v1/trace_config.py +37 -0
- uv.lock +179 -0
Dockerfile
CHANGED
|
@@ -21,7 +21,7 @@ COPY uv.lock .
|
|
| 21 |
|
| 22 |
# Copy required folders
|
| 23 |
COPY common/ ./common/
|
| 24 |
-
COPY src/
|
| 25 |
|
| 26 |
# Install dependencies using uv, then export and install with pip to system
|
| 27 |
RUN uv sync --frozen --no-dev && \
|
|
@@ -32,4 +32,4 @@ COPY run.py .
|
|
| 32 |
|
| 33 |
EXPOSE 7860
|
| 34 |
|
| 35 |
-
CMD ["python", "run.py", "
|
|
|
|
| 21 |
|
| 22 |
# Copy required folders
|
| 23 |
COPY common/ ./common/
|
| 24 |
+
COPY src/chatbot/ ./src/chatbot/
|
| 25 |
|
| 26 |
# Install dependencies using uv, then export and install with pip to system
|
| 27 |
RUN uv sync --frozen --no-dev && \
|
|
|
|
| 32 |
|
| 33 |
EXPOSE 7860
|
| 34 |
|
| 35 |
+
CMD ["python", "run.py", "chatbot", "--port", "7860"]
|
common/utility/autogen_model_factory.py
CHANGED
|
@@ -51,23 +51,47 @@ class AutoGenModelFactory:
|
|
| 51 |
# GOOGLE (GEMINI) via OpenAI Compat
|
| 52 |
# ----------------------------------------------------------------------
|
| 53 |
elif provider.lower() == "google" or provider.lower() == "gemini":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
return OpenAIChatCompletionClient(
|
| 55 |
model=model_name,
|
| 56 |
base_url="https://generativelanguage.googleapis.com/v1beta/openai/",
|
| 57 |
api_key=os.environ["GOOGLE_API_KEY"],
|
| 58 |
-
model_info=model_info,
|
| 59 |
temperature=temperature,
|
|
|
|
|
|
|
|
|
|
| 60 |
)
|
| 61 |
|
| 62 |
# ----------------------------------------------------------------------
|
| 63 |
# GROQ
|
| 64 |
# ----------------------------------------------------------------------
|
| 65 |
elif provider.lower() == "groq":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
return OpenAIChatCompletionClient(
|
| 67 |
model=model_name,
|
| 68 |
base_url="https://api.groq.com/openai/v1",
|
| 69 |
api_key=os.environ["GROQ_API_KEY"],
|
|
|
|
| 70 |
temperature=temperature,
|
|
|
|
|
|
|
| 71 |
)
|
| 72 |
|
| 73 |
# ----------------------------------------------------------------------
|
|
|
|
| 51 |
# GOOGLE (GEMINI) via OpenAI Compat
|
| 52 |
# ----------------------------------------------------------------------
|
| 53 |
elif provider.lower() == "google" or provider.lower() == "gemini":
|
| 54 |
+
if model_info is None:
|
| 55 |
+
model_info = {
|
| 56 |
+
"family": "gemini",
|
| 57 |
+
"vision": False,
|
| 58 |
+
"function_calling": True,
|
| 59 |
+
"json_output": True,
|
| 60 |
+
"structured_output": False
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
return OpenAIChatCompletionClient(
|
| 64 |
model=model_name,
|
| 65 |
base_url="https://generativelanguage.googleapis.com/v1beta/openai/",
|
| 66 |
api_key=os.environ["GOOGLE_API_KEY"],
|
| 67 |
+
model_info=model_info,
|
| 68 |
temperature=temperature,
|
| 69 |
+
max_tokens=2048,
|
| 70 |
+
structured_output=False, # Disable for Gemini compatibility
|
| 71 |
+
extra_headers={"x-goog-api-key": os.environ["GOOGLE_API_KEY"]}
|
| 72 |
)
|
| 73 |
|
| 74 |
# ----------------------------------------------------------------------
|
| 75 |
# GROQ
|
| 76 |
# ----------------------------------------------------------------------
|
| 77 |
elif provider.lower() == "groq":
|
| 78 |
+
if model_info is None:
|
| 79 |
+
model_info = {
|
| 80 |
+
"family": "llama", # Use llama family for Groq
|
| 81 |
+
"vision": False,
|
| 82 |
+
"function_calling": True,
|
| 83 |
+
"json_output": True,
|
| 84 |
+
"structured_output": False
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
return OpenAIChatCompletionClient(
|
| 88 |
model=model_name,
|
| 89 |
base_url="https://api.groq.com/openai/v1",
|
| 90 |
api_key=os.environ["GROQ_API_KEY"],
|
| 91 |
+
model_info=model_info,
|
| 92 |
temperature=temperature,
|
| 93 |
+
structured_output=False, # Disable for Groq compatibility
|
| 94 |
+
max_tokens=2048
|
| 95 |
)
|
| 96 |
|
| 97 |
# ----------------------------------------------------------------------
|
pyproject.toml
CHANGED
|
@@ -61,6 +61,7 @@ dependencies = [
|
|
| 61 |
"autogen-agentchat==0.4.7",
|
| 62 |
"autogen-ext[grpc,mcp,ollama,openai]==0.4.7",
|
| 63 |
"asyncio",
|
|
|
|
| 64 |
|
| 65 |
# =======================
|
| 66 |
# MCP
|
|
@@ -136,6 +137,11 @@ dependencies = [
|
|
| 136 |
"ddgs>=9.9.2",
|
| 137 |
"duckduckgo_search",
|
| 138 |
"azure-identity>=1.25.1",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
|
| 140 |
# =======================
|
| 141 |
# OBSERVABILITY
|
|
|
|
| 61 |
"autogen-agentchat==0.4.7",
|
| 62 |
"autogen-ext[grpc,mcp,ollama,openai]==0.4.7",
|
| 63 |
"asyncio",
|
| 64 |
+
"phidata>=2.0.0",
|
| 65 |
|
| 66 |
# =======================
|
| 67 |
# MCP
|
|
|
|
| 137 |
"ddgs>=9.9.2",
|
| 138 |
"duckduckgo_search",
|
| 139 |
"azure-identity>=1.25.1",
|
| 140 |
+
"azure-mgmt-resource>=23.0.1",
|
| 141 |
+
"azure-mgmt-compute>=30.3.0",
|
| 142 |
+
"azure-mgmt-monitor>=6.0.2",
|
| 143 |
+
"azure-monitor-query>=1.2.0",
|
| 144 |
+
"PyGithub>=2.1.1",
|
| 145 |
|
| 146 |
# =======================
|
| 147 |
# OBSERVABILITY
|
run.py
CHANGED
|
@@ -18,7 +18,7 @@ import subprocess
|
|
| 18 |
import argparse
|
| 19 |
from pathlib import Path
|
| 20 |
from typing import Dict, Optional
|
| 21 |
-
from agents import Runner, SQLiteSession
|
| 22 |
# from agents import set_trace_processors
|
| 23 |
# from langsmith.wrappers import OpenAIAgentsTracingProcessor
|
| 24 |
|
|
@@ -56,6 +56,7 @@ APP_REGISTRY: Dict[str, Dict[str, str]] = {
|
|
| 56 |
"trip-planner": {
|
| 57 |
"path": "src/trip-planner",
|
| 58 |
"entry": "main.py",
|
|
|
|
| 59 |
"description": "Trip Planner - Detailed trip itinerary planning"
|
| 60 |
},
|
| 61 |
"chatbot_v1": {
|
|
@@ -85,8 +86,9 @@ APP_REGISTRY: Dict[str, Dict[str, str]] = {
|
|
| 85 |
},
|
| 86 |
"market-analyst": {
|
| 87 |
"path": "src/market-analyst",
|
| 88 |
-
"entry": "
|
| 89 |
-
"
|
|
|
|
| 90 |
},
|
| 91 |
"image": {
|
| 92 |
"path": "src/image-generator",
|
|
@@ -98,10 +100,88 @@ APP_REGISTRY: Dict[str, Dict[str, str]] = {
|
|
| 98 |
"entry": "app.py",
|
| 99 |
"description": "Interview Assistant - Multi-agent interview tool"
|
| 100 |
},
|
| 101 |
-
"finadvisor": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
"path": "src/finadvisor",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
"entry": "app.py",
|
| 104 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
}
|
| 106 |
}
|
| 107 |
|
|
@@ -177,15 +257,63 @@ def launch_app(app_name: str, port: Optional[int] = None):
|
|
| 177 |
print(f"📂 Location: {config['path']}")
|
| 178 |
print(f"🌐 Entry Point: {app_file}")
|
| 179 |
|
| 180 |
-
|
| 181 |
-
cmd = ["streamlit", "run", app_file]
|
| 182 |
|
| 183 |
-
#
|
| 184 |
-
if
|
| 185 |
-
|
| 186 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
else:
|
| 188 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 189 |
|
| 190 |
print("\n" + "=" * 70)
|
| 191 |
print("\n🎯 Starting application...\n")
|
|
@@ -198,12 +326,25 @@ def launch_app(app_name: str, port: Optional[int] = None):
|
|
| 198 |
try:
|
| 199 |
# Change to app directory and run
|
| 200 |
os.chdir(app_dir)
|
| 201 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
except KeyboardInterrupt:
|
| 203 |
print("\n\n👋 Application stopped by user")
|
| 204 |
except FileNotFoundError:
|
| 205 |
-
|
| 206 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 207 |
sys.exit(1)
|
| 208 |
except Exception as e:
|
| 209 |
print(f"\n❌ Error launching app: {e}")
|
|
|
|
| 18 |
import argparse
|
| 19 |
from pathlib import Path
|
| 20 |
from typing import Dict, Optional
|
| 21 |
+
# from agents import Runner, SQLiteSession
|
| 22 |
# from agents import set_trace_processors
|
| 23 |
# from langsmith.wrappers import OpenAIAgentsTracingProcessor
|
| 24 |
|
|
|
|
| 56 |
"trip-planner": {
|
| 57 |
"path": "src/trip-planner",
|
| 58 |
"entry": "main.py",
|
| 59 |
+
"type": "fastapi",
|
| 60 |
"description": "Trip Planner - Detailed trip itinerary planning"
|
| 61 |
},
|
| 62 |
"chatbot_v1": {
|
|
|
|
| 86 |
},
|
| 87 |
"market-analyst": {
|
| 88 |
"path": "src/market-analyst",
|
| 89 |
+
"entry": "backend/main.py",
|
| 90 |
+
"type": "fastapi",
|
| 91 |
+
"description": "Market Analyst - Decoupled Multi-agent market analysis (Vue.js + FastAPI)"
|
| 92 |
},
|
| 93 |
"image": {
|
| 94 |
"path": "src/image-generator",
|
|
|
|
| 100 |
"entry": "app.py",
|
| 101 |
"description": "Interview Assistant - Multi-agent interview tool"
|
| 102 |
},
|
| 103 |
+
"finadvisor-lg": {
|
| 104 |
+
"path": "src/finadvisor",
|
| 105 |
+
"entry": "app-lg.py",
|
| 106 |
+
"description": "Financial Advisor - Multi-agent financial advisor tool using LangGraph"
|
| 107 |
+
}
|
| 108 |
+
,
|
| 109 |
+
"finadvisor-oai": {
|
| 110 |
+
"path": "src/finadvisor",
|
| 111 |
+
"entry": "app-oai.py",
|
| 112 |
+
"description": "Financial Advisor - Multi-agent financial advisor tool using OpenAI"
|
| 113 |
+
}
|
| 114 |
+
,
|
| 115 |
+
"finadvisor-phi": {
|
| 116 |
+
"path": "src/finadvisor",
|
| 117 |
+
"entry": "app-phi.py",
|
| 118 |
+
"description": "Financial Advisor - Multi-agent financial advisor tool using Phidata"
|
| 119 |
+
}
|
| 120 |
+
,
|
| 121 |
+
"finadvisor-ag": {
|
| 122 |
"path": "src/finadvisor",
|
| 123 |
+
"entry": "app-ag.py",
|
| 124 |
+
"description": "Financial Advisor - Multi-agent financial advisor tool using Autogen"
|
| 125 |
+
},
|
| 126 |
+
"mcp-trader": {
|
| 127 |
+
"path": "src/mcp-trader",
|
| 128 |
+
"entry": "server.py",
|
| 129 |
+
"type": "script",
|
| 130 |
+
"description": "Strategies MCP Server - FastMCP server for trading strategies"
|
| 131 |
+
},
|
| 132 |
+
"mcp-web": {
|
| 133 |
+
"path": "src/mcp-web",
|
| 134 |
+
"entry": "server.py",
|
| 135 |
+
"type": "script",
|
| 136 |
+
"description": "Web MCP Server - Search, Extract, Wikipedia, Arxiv"
|
| 137 |
+
},
|
| 138 |
+
"mcp-azure-sre": {
|
| 139 |
+
"path": "src/mcp-azure-sre",
|
| 140 |
+
"entry": "server.py",
|
| 141 |
+
"type": "script",
|
| 142 |
+
"description": "Azure SRE MCP Server - Manage Azure Resources & Monitoring"
|
| 143 |
+
},
|
| 144 |
+
"mcp-rag-secure": {
|
| 145 |
+
"path": "src/mcp-rag-secure",
|
| 146 |
+
"entry": "server.py",
|
| 147 |
+
"type": "script",
|
| 148 |
+
"description": "Secure RAG MCP Server - Multi-tenant knowledge base"
|
| 149 |
+
},
|
| 150 |
+
"mcp-trading-research": {
|
| 151 |
+
"path": "src/mcp-trading-research",
|
| 152 |
+
"entry": "server.py",
|
| 153 |
+
"type": "script",
|
| 154 |
+
"description": "Trading Research MCP Server - News, Insider, Analysts"
|
| 155 |
+
},
|
| 156 |
+
"mcp-github": {
|
| 157 |
+
"path": "src/mcp-github",
|
| 158 |
+
"entry": "server.py",
|
| 159 |
+
"type": "script",
|
| 160 |
+
"description": "GitHub MCP Server - Issues, PRs, Alerts"
|
| 161 |
+
},
|
| 162 |
+
"mcp-seo": {
|
| 163 |
+
"path": "src/mcp-seo",
|
| 164 |
+
"entry": "server.py",
|
| 165 |
+
"type": "script",
|
| 166 |
+
"description": "SEO & ADA MCP Server - Website Audits"
|
| 167 |
+
},
|
| 168 |
+
"github-portal": {
|
| 169 |
+
"path": "src/github-portal",
|
| 170 |
"entry": "app.py",
|
| 171 |
+
"type": "streamlit",
|
| 172 |
+
"description": "GitHub Portal - Repository health dashboard for issues, security, and pipelines"
|
| 173 |
+
},
|
| 174 |
+
"mcp-hub": {
|
| 175 |
+
"path": "src/mcp-hub",
|
| 176 |
+
"entry": "package.json",
|
| 177 |
+
"type": "npm",
|
| 178 |
+
"description": "MCP Hub - Discovery and monitoring portal (Vue.js)"
|
| 179 |
+
},
|
| 180 |
+
"test": {
|
| 181 |
+
"path": ".",
|
| 182 |
+
"entry": "tests",
|
| 183 |
+
"type": "test",
|
| 184 |
+
"description": "Run Project Tests - Executes pytest suite"
|
| 185 |
}
|
| 186 |
}
|
| 187 |
|
|
|
|
| 257 |
print(f"📂 Location: {config['path']}")
|
| 258 |
print(f"🌐 Entry Point: {app_file}")
|
| 259 |
|
| 260 |
+
app_type = config.get("type", "streamlit")
|
|
|
|
| 261 |
|
| 262 |
+
# Decoupled App Logic: Build frontend if needed
|
| 263 |
+
if app_name == "market-analyst":
|
| 264 |
+
frontend_dir = project_root / "src/market-analyst/frontend"
|
| 265 |
+
dist_dir = frontend_dir / "dist"
|
| 266 |
+
if not dist_dir.exists():
|
| 267 |
+
print("\n🛠️ Frontend build missing. Building now...")
|
| 268 |
+
subprocess.run(["npm", "run", "build"], cwd=frontend_dir, shell=True)
|
| 269 |
+
print("✅ Frontend built.\n")
|
| 270 |
+
|
| 271 |
+
python_exe = sys.executable
|
| 272 |
+
|
| 273 |
+
# Build command based on app type
|
| 274 |
+
if app_type == "fastapi":
|
| 275 |
+
# Extract module name from entry point (e.g. backend/main.py -> backend.main)
|
| 276 |
+
module_path = app_file.replace(".py", "").replace("/", ".").replace("\\", ".")
|
| 277 |
+
cmd = [python_exe, "-m", "uvicorn", f"{module_path}:app", "--host", "0.0.0.0"]
|
| 278 |
+
default_port = 8000
|
| 279 |
+
elif app_type == "script":
|
| 280 |
+
cmd = [python_exe, app_file]
|
| 281 |
+
default_port = None
|
| 282 |
+
elif app_type == "test":
|
| 283 |
+
cmd = [python_exe, "-m", "pytest", app_file, "-v"]
|
| 284 |
+
default_port = None
|
| 285 |
+
elif app_type == "npm":
|
| 286 |
+
cmd = ["npm", "run", "dev"]
|
| 287 |
+
default_port = 5173
|
| 288 |
else:
|
| 289 |
+
cmd = [python_exe, "-m", "streamlit", "run", app_file]
|
| 290 |
+
default_port = 8501
|
| 291 |
+
|
| 292 |
+
# Add port if specified
|
| 293 |
+
actual_port = port if port else default_port
|
| 294 |
+
|
| 295 |
+
if app_type in ["streamlit", "fastapi", "npm"]:
|
| 296 |
+
if port:
|
| 297 |
+
if app_type == "fastapi":
|
| 298 |
+
cmd.extend(["--port", str(port)])
|
| 299 |
+
elif app_type == "npm":
|
| 300 |
+
cmd.extend(["--", "--port", str(port)])
|
| 301 |
+
else:
|
| 302 |
+
cmd.extend(["--server.port", str(port)])
|
| 303 |
+
print(f"🔌 Port: {port}")
|
| 304 |
+
else:
|
| 305 |
+
print(f"🔌 Port: {default_port} (default)")
|
| 306 |
+
|
| 307 |
+
# Kill any process using the target port (Port is only relevant for web apps)
|
| 308 |
+
try:
|
| 309 |
+
import platform
|
| 310 |
+
if platform.system() != "Windows":
|
| 311 |
+
# Use fuser on Linux/Mac to kill processes on the port
|
| 312 |
+
kill_cmd = ["fuser", "-k", f"{actual_port}/tcp"]
|
| 313 |
+
subprocess.run(kill_cmd, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
|
| 314 |
+
print(f"🧹 Cleaned up port {actual_port}")
|
| 315 |
+
except Exception:
|
| 316 |
+
pass # Silently continue if cleanup fails
|
| 317 |
|
| 318 |
print("\n" + "=" * 70)
|
| 319 |
print("\n🎯 Starting application...\n")
|
|
|
|
| 326 |
try:
|
| 327 |
# Change to app directory and run
|
| 328 |
os.chdir(app_dir)
|
| 329 |
+
is_windows = sys.platform == "win32"
|
| 330 |
+
|
| 331 |
+
# Special case for mcp-hub: launch backend API first
|
| 332 |
+
if app_name == "mcp-hub":
|
| 333 |
+
print("🚀 Starting MCP Hub Backend API on port 8001...")
|
| 334 |
+
api_cmd = [python_exe, "api.py"]
|
| 335 |
+
subprocess.Popen(api_cmd, env=env, shell=is_windows)
|
| 336 |
+
|
| 337 |
+
subprocess.run(cmd, env=env, shell=is_windows)
|
| 338 |
except KeyboardInterrupt:
|
| 339 |
print("\n\n👋 Application stopped by user")
|
| 340 |
except FileNotFoundError:
|
| 341 |
+
binary = "command"
|
| 342 |
+
if app_type == "fastapi": binary = "uvicorn"
|
| 343 |
+
elif app_type == "streamlit": binary = "streamlit"
|
| 344 |
+
elif app_type == "test": binary = "pytest"
|
| 345 |
+
|
| 346 |
+
print(f"\n❌ Error: {binary} not found in the current environment.")
|
| 347 |
+
print(f" Please install it: pip install {binary}")
|
| 348 |
sys.exit(1)
|
| 349 |
except Exception as e:
|
| 350 |
print(f"\n❌ Error launching app: {e}")
|
src/chatbot_v1/Dockerfile
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.12-slim
|
| 2 |
+
|
| 3 |
+
ENV PYTHONUNBUFFERED=1 \
|
| 4 |
+
DEBIAN_FRONTEND=noninteractive \
|
| 5 |
+
PYTHONPATH=/app:/app/common:$PYTHONPATH
|
| 6 |
+
|
| 7 |
+
WORKDIR /app
|
| 8 |
+
|
| 9 |
+
# System deps
|
| 10 |
+
RUN apt-get update && apt-get install -y \
|
| 11 |
+
git build-essential curl \
|
| 12 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 13 |
+
|
| 14 |
+
# Install uv
|
| 15 |
+
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 16 |
+
ENV PATH="/root/.local/bin:$PATH"
|
| 17 |
+
|
| 18 |
+
# Copy project metadata
|
| 19 |
+
COPY pyproject.toml .
|
| 20 |
+
COPY uv.lock .
|
| 21 |
+
|
| 22 |
+
# Copy required folders
|
| 23 |
+
COPY common/ ./common/
|
| 24 |
+
COPY src/chatbot/ ./src/chatbot/
|
| 25 |
+
|
| 26 |
+
# Install dependencies using uv, then export and install with pip to system
|
| 27 |
+
RUN uv sync --frozen --no-dev && \
|
| 28 |
+
uv pip install -e . --system
|
| 29 |
+
|
| 30 |
+
# Copy entry point
|
| 31 |
+
COPY run.py .
|
| 32 |
+
|
| 33 |
+
EXPOSE 7860
|
| 34 |
+
|
| 35 |
+
CMD ["python", "run.py", "chatbot", "--port", "7860"]
|
src/chatbot_v1/README.md
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: AI Chatbot
|
| 3 |
+
emoji: 🤖
|
| 4 |
+
colorFrom: pink
|
| 5 |
+
colorTo: yellow
|
| 6 |
+
sdk: docker
|
| 7 |
+
sdk_version: "0.0.1"
|
| 8 |
+
app_file: app.py
|
| 9 |
+
pinned: false
|
| 10 |
+
license: mit
|
| 11 |
+
tags:
|
| 12 |
+
- text-generation
|
| 13 |
+
- agentic-ai
|
| 14 |
+
- openai-sdk
|
| 15 |
+
short_description: An Experimental Agentic Chatbot (uses OpenAI Agent SDK)
|
| 16 |
+
---
|
| 17 |
+
|
| 18 |
+
# AI Chatbot
|
| 19 |
+
|
| 20 |
+
This is an experimental chatbot for chatting with AI. It is equipped with agents & tools to give you realtime data from the web. It uses **OpenAI - SDK** and **OpenAI - Agents**...
|
| 21 |
+
|
| 22 |
+
## Features
|
| 23 |
+
- Predefined prompts for quick analysis
|
| 24 |
+
- Chat interface with AI responses
|
| 25 |
+
- Enter key support and responsive design
|
| 26 |
+
- Latest messages appear on top
|
| 27 |
+
|
| 28 |
+
## Usage
|
| 29 |
+
1. Type a message or select a predefined prompt
|
| 30 |
+
2. Press **Enter** or click **Send**
|
| 31 |
+
3. AI responses appear instantly in the chat interface
|
| 32 |
+
|
| 33 |
+
## Supported APIs
|
| 34 |
+
- OpenAI
|
| 35 |
+
- Google
|
| 36 |
+
- GROQ
|
| 37 |
+
- SERPER
|
| 38 |
+
- News API
|
| 39 |
+
|
| 40 |
+
## Notes
|
| 41 |
+
- Make sure your API keys are configured in the Space secrets
|
| 42 |
+
- Built using Streamlit and deployed as a Docker Space
|
| 43 |
+
|
| 44 |
+
## References
|
| 45 |
+
|
| 46 |
+
https://openai.github.io/openai-agents-python/
|
| 47 |
+
|
| 48 |
+
https://github.com/openai/openai-agents-python/tree/main/examples/mcp
|
| 49 |
+
|
| 50 |
+
## Project Folder Structure
|
| 51 |
+
|
| 52 |
+
```
|
| 53 |
+
chatbot/
|
| 54 |
+
├── app.py # Main Streamlit chatbot interface
|
| 55 |
+
├── appagents/
|
| 56 |
+
│ ├── __init__.py # Package initialization
|
| 57 |
+
│ ├── OrchestratorAgent.py # Main orchestrator - coordinates all agents
|
| 58 |
+
│ ├── FinancialAgent.py # Financial data and analysis agent
|
| 59 |
+
│ ├── NewsAgent.py # News retrieval and summarization agent
|
| 60 |
+
│ ├── SearchAgent.py # General web search agent
|
| 61 |
+
│ └── InputValidationAgent.py # Input validation and sanitization agent
|
| 62 |
+
├── core/
|
| 63 |
+
│ ├── __init__.py # Package initialization
|
| 64 |
+
│ └── logger.py # Centralized logging configuration
|
| 65 |
+
├── tools/
|
| 66 |
+
│ ├── __init__.py # Package initialization
|
| 67 |
+
│ ├── google_tools.py # Google search API wrapper
|
| 68 |
+
│ ├── yahoo_tools.py # Yahoo Finance API wrapper
|
| 69 |
+
│ ├── news_tools.py # News API wrapper
|
| 70 |
+
│ └── time_tools.py # Time-related utility functions
|
| 71 |
+
├── prompts/
|
| 72 |
+
│ ├── economic_news.txt # Prompt for economic news analysis
|
| 73 |
+
│ ├── market_sentiment.txt # Prompt for market sentiment analysis
|
| 74 |
+
│ ├── news_headlines.txt # Prompt for news headline summarization
|
| 75 |
+
│ ├── trade_recommendation.txt # Prompt for trade recommendations
|
| 76 |
+
│ └── upcoming_earnings.txt # Prompt for upcoming earnings alerts
|
| 77 |
+
├── Dockerfile # Docker configuration for container deployment
|
| 78 |
+
├── pyproject.toml # Project metadata and dependencies (copied from root)
|
| 79 |
+
├── uv.lock # Locked dependency versions (copied from root)
|
| 80 |
+
├── README.md # Project documentation
|
| 81 |
+
└── run.py # Script to run the application locally
|
| 82 |
+
```
|
| 83 |
+
|
| 84 |
+
## File Descriptions
|
| 85 |
+
|
| 86 |
+
### UI Layer
|
| 87 |
+
- **app.py** - Main Streamlit chatbot interface that provides:
|
| 88 |
+
- Chat message display with user and AI messages
|
| 89 |
+
- Text input for user queries
|
| 90 |
+
- Predefined prompt buttons for quick analysis
|
| 91 |
+
- Real-time AI responses
|
| 92 |
+
- Support for Enter key submission
|
| 93 |
+
- Responsive design with latest messages appearing first
|
| 94 |
+
|
| 95 |
+
### Agents (`appagents/`)
|
| 96 |
+
- **OrchestratorAgent.py** - Main orchestrator that:
|
| 97 |
+
- Coordinates communication between all specialized agents
|
| 98 |
+
- Routes user queries to appropriate agents
|
| 99 |
+
- Manages conversation flow and context
|
| 100 |
+
- Integrates tool responses
|
| 101 |
+
|
| 102 |
+
- **FinancialAgent.py** - Financial data and analysis:
|
| 103 |
+
- Retrieves stock prices and financial metrics
|
| 104 |
+
- Performs financial analysis using Yahoo Finance API
|
| 105 |
+
- Provides market insights and recommendations
|
| 106 |
+
- Integrates with yahoo_tools for data fetching
|
| 107 |
+
|
| 108 |
+
- **NewsAgent.py** - News retrieval and summarization:
|
| 109 |
+
- Fetches latest news articles
|
| 110 |
+
- Summarizes news content
|
| 111 |
+
- Integrates with News API for real-time updates
|
| 112 |
+
- Provides news-based market insights
|
| 113 |
+
|
| 114 |
+
- **SearchAgent.py** - General web search:
|
| 115 |
+
- Performs web searches for general queries
|
| 116 |
+
- Integrates with Google Search / Serper API
|
| 117 |
+
- Returns relevant search results
|
| 118 |
+
- Supports multi-source data gathering
|
| 119 |
+
|
| 120 |
+
- **InputValidationAgent.py** - Input validation:
|
| 121 |
+
- Sanitizes user input
|
| 122 |
+
- Validates query format and content
|
| 123 |
+
- Prevents malicious inputs
|
| 124 |
+
- Ensures appropriate content
|
| 125 |
+
|
| 126 |
+
### Core Utilities (`core/`)
|
| 127 |
+
- **logger.py** - Centralized logging configuration:
|
| 128 |
+
- Provides consistent logging across agents
|
| 129 |
+
- Handles different log levels
|
| 130 |
+
- Formats log messages for clarity
|
| 131 |
+
|
| 132 |
+
### Tools (`tools/`)
|
| 133 |
+
- **google_tools.py** - Google Search API wrapper:
|
| 134 |
+
- Executes web searches via Google Search / Serper API
|
| 135 |
+
- Parses and returns search results
|
| 136 |
+
- Handles API authentication
|
| 137 |
+
|
| 138 |
+
- **yahoo_tools.py** - Yahoo Finance API integration:
|
| 139 |
+
- Retrieves stock price data
|
| 140 |
+
- Fetches financial metrics and indicators
|
| 141 |
+
- Provides historical price data
|
| 142 |
+
- Returns earnings information
|
| 143 |
+
|
| 144 |
+
- **news_tools.py** - News API integration:
|
| 145 |
+
- Fetches latest news articles
|
| 146 |
+
- Filters news by category and keywords
|
| 147 |
+
- Returns news headlines and summaries
|
| 148 |
+
- Provides market-related news feeds
|
| 149 |
+
|
| 150 |
+
- **time_tools.py** - Time utility functions:
|
| 151 |
+
- Provides current time information
|
| 152 |
+
- Formats timestamps
|
| 153 |
+
- Handles timezone conversions
|
| 154 |
+
|
| 155 |
+
### Prompts (`prompts/`)
|
| 156 |
+
Predefined prompts for specialized analysis:
|
| 157 |
+
- **economic_news.txt** - Analyzes economic news and implications
|
| 158 |
+
- **market_sentiment.txt** - Analyzes market sentiment trends
|
| 159 |
+
- **news_headlines.txt** - Summarizes and explains news headlines
|
| 160 |
+
- **trade_recommendation.txt** - Provides trading recommendations
|
| 161 |
+
- **upcoming_earnings.txt** - Alerts about upcoming earnings reports
|
| 162 |
+
|
| 163 |
+
### Configuration Files
|
| 164 |
+
- **Dockerfile** - Container deployment:
|
| 165 |
+
- Builds Docker image with Python 3.12
|
| 166 |
+
- Installs dependencies using `uv`
|
| 167 |
+
- Sets up Streamlit server on port 8501
|
| 168 |
+
- Configures PYTHONPATH for module imports
|
| 169 |
+
|
| 170 |
+
- **pyproject.toml** - Project metadata:
|
| 171 |
+
- Package name: "agents"
|
| 172 |
+
- Python version requirement: 3.12
|
| 173 |
+
- Lists all dependencies (OpenAI, LangChain, Streamlit, etc.)
|
| 174 |
+
|
| 175 |
+
- **uv.lock** - Dependency lock file:
|
| 176 |
+
- Ensures reproducible builds
|
| 177 |
+
- Pins exact versions of all dependencies
|
| 178 |
+
|
| 179 |
+
## Key Technologies
|
| 180 |
+
|
| 181 |
+
| Component | Technology | Purpose |
|
| 182 |
+
|-----------|-----------|---------|
|
| 183 |
+
| LLM Framework | OpenAI Agents | Multi-agent orchestration |
|
| 184 |
+
| Chat Interface | Streamlit | User interaction and display |
|
| 185 |
+
| Web Search | Google Search / Serper API | Web search results |
|
| 186 |
+
| Financial Data | Yahoo Finance API | Stock prices and metrics |
|
| 187 |
+
| News Data | News API | Latest news articles |
|
| 188 |
+
| Async Operations | AsyncIO | Parallel agent execution |
|
| 189 |
+
| Dependencies | UV | Fast Python package management |
|
| 190 |
+
| Containerization | Docker | Cloud deployment |
|
| 191 |
+
|
| 192 |
+
## Predefined Prompts
|
| 193 |
+
|
| 194 |
+
The chatbot includes quick-access buttons for common analysis:
|
| 195 |
+
|
| 196 |
+
1. **Economic News** - Analyzes current economic trends and news
|
| 197 |
+
2. **Market Sentiment** - Provides market sentiment analysis
|
| 198 |
+
3. **News Headlines** - Summarizes latest news headlines
|
| 199 |
+
4. **Trade Recommendation** - Suggests trading strategies
|
| 200 |
+
5. **Upcoming Earnings** - Lists upcoming company earnings
|
| 201 |
+
|
| 202 |
+
## Running Locally
|
| 203 |
+
|
| 204 |
+
```bash
|
| 205 |
+
# Install dependencies
|
| 206 |
+
uv sync
|
| 207 |
+
|
| 208 |
+
# Set environment variables defined in .env.name file
|
| 209 |
+
export OPENAI_API_KEY="your-key"
|
| 210 |
+
export SERPER_API_KEY="your-key"
|
| 211 |
+
export NEWS_API_KEY="your-key"
|
| 212 |
+
|
| 213 |
+
# Run the Streamlit app (from the root)
|
| 214 |
+
python run.py chatbot
|
| 215 |
+
```
|
| 216 |
+
|
| 217 |
+
## Deployment
|
| 218 |
+
|
| 219 |
+
The project is deployed on Hugging Face Spaces as a Docker container:
|
| 220 |
+
- **Space**: https://huggingface.co/spaces/mishrabp/chatbot-app
|
| 221 |
+
- **URL**: https://mishrabp-chatbot-app.hf.space
|
| 222 |
+
- **Trigger**: Automatic deployment on push to `main` branch
|
| 223 |
+
- **Configuration**: `.github/workflows/chatbot-app-hf.yml`
|
src/chatbot_v1/aagents/__init__.py
ADDED
|
File without changes
|
src/chatbot_v1/aagents/input_validation_agent.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import os
|
| 3 |
+
import json
|
| 4 |
+
from agents import Agent, OpenAIChatCompletionsModel, Runner, GuardrailFunctionOutput
|
| 5 |
+
from pydantic import BaseModel
|
| 6 |
+
from openai import AsyncOpenAI
|
| 7 |
+
from core.model import get_model_client
|
| 8 |
+
|
| 9 |
+
class ValidatedOutput(BaseModel):
|
| 10 |
+
is_valid: bool
|
| 11 |
+
reasoning: str
|
| 12 |
+
|
| 13 |
+
input_validation_agent = Agent(
|
| 14 |
+
name="Guardrail Input Validation Agent",
|
| 15 |
+
instructions="""
|
| 16 |
+
You are a highly efficient and specialized **Agent** 🌐. Your sole function is to validate the user inputs.
|
| 17 |
+
|
| 18 |
+
## Core Directives & Priorities
|
| 19 |
+
1. You should flag if the user uses unparaliamentary language ONLY.
|
| 20 |
+
2. You MUST give reasoning for the same.
|
| 21 |
+
|
| 22 |
+
## Rules
|
| 23 |
+
- If it contains any of these, mark `"is_valid": false` and explain **why** in `"reasoning"`.
|
| 24 |
+
- Otherwise, mark `"is_valid": true` with reasoning like "The input follows respectful communication guidelines."
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
## Output Format (MANDATORY)
|
| 28 |
+
* Return a JSON object with the following structure:
|
| 29 |
+
{
|
| 30 |
+
"is_valid": <boolean>,
|
| 31 |
+
"reasoning": <string>
|
| 32 |
+
}
|
| 33 |
+
""",
|
| 34 |
+
model=get_model_client(),
|
| 35 |
+
output_type=ValidatedOutput,
|
| 36 |
+
)
|
| 37 |
+
input_validation_agent.description = "A guardrail agent that validates user input for unparliamentary language."
|
| 38 |
+
|
| 39 |
+
async def input_validation_guardrail(ctx, agent, input_data):
|
| 40 |
+
result = await Runner.run(input_validation_agent, input_data, context=ctx.context)
|
| 41 |
+
raw_output = result.final_output
|
| 42 |
+
|
| 43 |
+
# Handle different return shapes gracefully
|
| 44 |
+
if isinstance(raw_output, ValidatedOutput):
|
| 45 |
+
final_output = raw_output
|
| 46 |
+
print("Parsed ValidatedOutput:", final_output)
|
| 47 |
+
else:
|
| 48 |
+
final_output = ValidatedOutput(
|
| 49 |
+
is_valid=False,
|
| 50 |
+
reasoning=f"Unexpected output type: {type(raw_output)}"
|
| 51 |
+
)
|
| 52 |
+
|
| 53 |
+
return GuardrailFunctionOutput(
|
| 54 |
+
output_info=final_output,
|
| 55 |
+
tripwire_triggered=not final_output.is_valid,
|
| 56 |
+
)
|
| 57 |
+
|
| 58 |
+
__all__ = ["input_validation_agent", "input_validation_guardrail", "ValidatedOutput"]
|
src/chatbot_v1/aagents/orchestrator_agent.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import os
|
| 3 |
+
import asyncio
|
| 4 |
+
from common.aagents.search_agent import search_agent
|
| 5 |
+
from common.aagents.news_agent import news_agent
|
| 6 |
+
from common.aagents.yf_agent import yf_agent
|
| 7 |
+
from aagents.input_validation_agent import input_validation_guardrail
|
| 8 |
+
from agents import Agent, OpenAIChatCompletionsModel, Runner, function_tool
|
| 9 |
+
from openai import AsyncOpenAI
|
| 10 |
+
from core.model import get_model_client
|
| 11 |
+
|
| 12 |
+
# ----------------------------------------------------------
|
| 13 |
+
# PARALLEL EXECUTION TOOL
|
| 14 |
+
# ----------------------------------------------------------
|
| 15 |
+
@function_tool
|
| 16 |
+
async def prompt_broadcaster(query: str, include_finance: bool = True, include_news: bool = True, include_search: bool = True) -> str:
|
| 17 |
+
"""
|
| 18 |
+
Broadcasts the search query to selected specialized agents in parallel and aggregates their responses.
|
| 19 |
+
|
| 20 |
+
Args:
|
| 21 |
+
query: The user's question or topic to research.
|
| 22 |
+
include_finance: Whether to include the Yahoo Finance agent (default: True).
|
| 23 |
+
include_news: Whether to include the News agent (default: True).
|
| 24 |
+
include_search: Whether to include the Web Search agent (default: True).
|
| 25 |
+
|
| 26 |
+
Returns:
|
| 27 |
+
Combined reports from the selected agents.
|
| 28 |
+
"""
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
# A better approach for variable tasks is to map them.
|
| 32 |
+
active_agents = []
|
| 33 |
+
if include_finance: active_agents.append(("YahooFinanceAgent", Runner.run(yf_agent, query)))
|
| 34 |
+
if include_news: active_agents.append(("NewsAgent", Runner.run(news_agent, query)))
|
| 35 |
+
if include_search: active_agents.append(("WebSearchAgent", Runner.run(search_agent, query)))
|
| 36 |
+
|
| 37 |
+
if not active_agents:
|
| 38 |
+
return "No agents were selected for this query."
|
| 39 |
+
|
| 40 |
+
# Run in parallel
|
| 41 |
+
agent_names = [name for name, _ in active_agents]
|
| 42 |
+
coroutines = [coro for _, coro in active_agents]
|
| 43 |
+
|
| 44 |
+
results = await asyncio.gather(*coroutines, return_exceptions=True)
|
| 45 |
+
|
| 46 |
+
outputs = []
|
| 47 |
+
for name, res in zip(agent_names, results):
|
| 48 |
+
if isinstance(res, Exception):
|
| 49 |
+
outputs.append(f"❌ {name} Error: {str(res)}")
|
| 50 |
+
else:
|
| 51 |
+
outputs.append(f"✅ {name} Report:\n{res.final_output}")
|
| 52 |
+
|
| 53 |
+
combined_response = "\n--- START OF AGENT REPORTS ---\n\n" + "\n\n-----------------------------------\n\n".join(outputs) + "\n\n--- END OF AGENT REPORTS ---"
|
| 54 |
+
|
| 55 |
+
return combined_response
|
| 56 |
+
|
| 57 |
+
orchestrator_agent = Agent(
|
| 58 |
+
name="AI Chat Orchestrator",
|
| 59 |
+
tools=[prompt_broadcaster],
|
| 60 |
+
instructions="""
|
| 61 |
+
You are the **AI Chat Orchestrator**.
|
| 62 |
+
Your goal is to provide a comprehensive, multi-perspective answer by synthesizing data from specialized sub-agents.
|
| 63 |
+
|
| 64 |
+
**Workflow**:
|
| 65 |
+
1. **Analyze Request**: Understand the user's question.
|
| 66 |
+
2. **Determine Needs**: Decide which specialized agents are required.
|
| 67 |
+
* **Finance**: For stock prices, market trends, company financials, or analyst ratings.
|
| 68 |
+
* **News**: For recent events, headlines, or breaking news.
|
| 69 |
+
* **Web Search**: For general knowledge, history, facts, or broad research.
|
| 70 |
+
3. **Broadcast Query**: Call the `prompt_broadcaster` tool with the `query` and set the `include_*` flags to True/False accordingly.
|
| 71 |
+
* *Optimization Tip*: efficiently select ONLY the necessary agents to reduce latency.
|
| 72 |
+
4. **Synthesize Results**: Read the returned "Agent Reports".
|
| 73 |
+
* Combine the financial data (prices, sentiment), news headlines, and general search context.
|
| 74 |
+
* Compare and contrast findings if necessary.
|
| 75 |
+
* Resolve conflicts by prioritizing specific data (e.g., Yahoo Finance for prices) over general text.
|
| 76 |
+
5. **Final Response**: Generate a clear, professional, and well-structured summary for the user. Do not simply paste the individual reports.
|
| 77 |
+
|
| 78 |
+
**Final Response Structure**:
|
| 79 |
+
You should adapt the response structure based on the user's query type:
|
| 80 |
+
|
| 81 |
+
* **For Market/Finance Queries**: Use the "Market Analysis" style with a Financial Snapshot (Price, Sentinel, Ratings), Key Developments, and Synthesis.
|
| 82 |
+
* **For News/Research**: Use a clear "Executive Summary" followed by "Key Findings" and "Details".
|
| 83 |
+
* **For General Chat**: Maintain a conversational but professional tone. Use markdown for clarity (bullet points, bold text).
|
| 84 |
+
* **For Coding Requests**: Provide clear code blocks and explanations.
|
| 85 |
+
|
| 86 |
+
**Constraint**:
|
| 87 |
+
* Do NOT try to answer based on your own knowledge if live data is needed/requested.
|
| 88 |
+
* Use `prompt_broadcaster` when the query implies a need for external information.
|
| 89 |
+
* If agents return "No data", explicitly state that in the relevant section.
|
| 90 |
+
""",
|
| 91 |
+
model=get_model_client(),
|
| 92 |
+
)
|
| 93 |
+
orchestrator_agent.description = "An intelligent orchestrator that queries Finance, News, and Search agents in parallel and synthesizes a comprehensive response."
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
__all__ = ["orchestrator_agent"]
|
src/chatbot_v1/app.py
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import glob
|
| 3 |
+
import uuid
|
| 4 |
+
import asyncio
|
| 5 |
+
# import trace_config
|
| 6 |
+
import logging
|
| 7 |
+
import streamlit as st
|
| 8 |
+
from aagents.orchestrator_agent import orchestrator_agent
|
| 9 |
+
from agents import Runner, trace, SQLiteSession
|
| 10 |
+
from agents.exceptions import InputGuardrailTripwireTriggered
|
| 11 |
+
# from langsmith import traceable
|
| 12 |
+
|
| 13 |
+
from traceloop.sdk import Traceloop
|
| 14 |
+
from opentelemetry.sdk.trace import Span
|
| 15 |
+
|
| 16 |
+
# --- Monkeypatch to fix "Invalid type Omit" errors ---
|
| 17 |
+
# This filters out 'NotGiven'/'Omit' values from OpenAI that crash the OTel exporter
|
| 18 |
+
_original_set_attribute = Span.set_attribute
|
| 19 |
+
|
| 20 |
+
def _safe_set_attribute(self, key, value):
|
| 21 |
+
# Check string representation of type to avoid importing specific internal types
|
| 22 |
+
type_str = str(type(value))
|
| 23 |
+
if "Omit" in type_str or "NotGiven" in type_str:
|
| 24 |
+
return self
|
| 25 |
+
return _original_set_attribute(self, key, value)
|
| 26 |
+
|
| 27 |
+
Span.set_attribute = _safe_set_attribute
|
| 28 |
+
# -----------------------------------------------------
|
| 29 |
+
|
| 30 |
+
Traceloop.init(
|
| 31 |
+
disable_batch=True,
|
| 32 |
+
api_key="tl_1c19b8e8fcfd411fb9fcdb02d381faef"
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
# -----------------------------
|
| 36 |
+
# Configuration & Utils
|
| 37 |
+
# -----------------------------
|
| 38 |
+
st.set_page_config(
|
| 39 |
+
page_title="AI Assistant",
|
| 40 |
+
layout="wide",
|
| 41 |
+
page_icon="🤖"
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
def load_prompts(folder="prompts"):
|
| 45 |
+
prompts = []
|
| 46 |
+
prompt_labels = []
|
| 47 |
+
if os.path.exists(folder):
|
| 48 |
+
for file_path in glob.glob(os.path.join(folder, "*.txt")):
|
| 49 |
+
with open(file_path, "r", encoding="utf-8") as f:
|
| 50 |
+
content = f.read().strip()
|
| 51 |
+
if content:
|
| 52 |
+
prompts.append(content)
|
| 53 |
+
|
| 54 |
+
prompt_labels.append(os.path.basename(file_path).replace("_", " ").replace(".txt", "").title())
|
| 55 |
+
return prompts, prompt_labels
|
| 56 |
+
|
| 57 |
+
prompts, prompt_labels = load_prompts()
|
| 58 |
+
|
| 59 |
+
# -----------------------------
|
| 60 |
+
# Session State
|
| 61 |
+
# -----------------------------
|
| 62 |
+
if "messages" not in st.session_state:
|
| 63 |
+
st.session_state.messages = []
|
| 64 |
+
|
| 65 |
+
if "ai_session_id" not in st.session_state:
|
| 66 |
+
st.session_state.ai_session_id = str(uuid.uuid4())
|
| 67 |
+
|
| 68 |
+
# Persistent SQLite session
|
| 69 |
+
if "ai_session" not in st.session_state:
|
| 70 |
+
st.session_state.ai_session = SQLiteSession(f"conversation_{st.session_state.ai_session_id}.db")
|
| 71 |
+
|
| 72 |
+
session = st.session_state.ai_session
|
| 73 |
+
|
| 74 |
+
# -----------------------------
|
| 75 |
+
# Premium Styling
|
| 76 |
+
# -----------------------------
|
| 77 |
+
st.markdown("""
|
| 78 |
+
<style>
|
| 79 |
+
/* ---------------------------------------------------------------------
|
| 80 |
+
1. GLOBAL & RESET
|
| 81 |
+
--------------------------------------------------------------------- */
|
| 82 |
+
* {
|
| 83 |
+
box-sizing: border-box;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
.stApp, [data-testid="stAppViewContainer"] {
|
| 87 |
+
/* Standard Streamlit background */
|
| 88 |
+
background-color: #f8f9fa;
|
| 89 |
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
html {
|
| 93 |
+
-webkit-text-size-adjust: 100%; /* Prevent iOS font boosting */
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
/* ---------------------------------------------------------------------
|
| 97 |
+
2. LAYOUT & HERO BANNER
|
| 98 |
+
--------------------------------------------------------------------- */
|
| 99 |
+
|
| 100 |
+
/* Mobile font optimization */
|
| 101 |
+
@media (max-width: 768px) {
|
| 102 |
+
/* Target all markdown text specifically */
|
| 103 |
+
.stMarkdown p, .stMarkdown li, .stChatMessage p, .message-content, .stDataFrame, .stTable {
|
| 104 |
+
font-size: 16px !important;
|
| 105 |
+
line-height: 1.6 !important;
|
| 106 |
+
color: #1a1a1a !important;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
h1, h2, h3, h4, h5, h6 {
|
| 110 |
+
color: #1a1a1a !important;
|
| 111 |
+
}
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
/* Desktop Layout */
|
| 115 |
+
@media (min-width: 769px) {
|
| 116 |
+
.block-container {
|
| 117 |
+
padding-top: 0 !important;
|
| 118 |
+
padding-bottom: 2rem !important;
|
| 119 |
+
padding-left: 5rem !important;
|
| 120 |
+
padding-right: 5rem !important;
|
| 121 |
+
max-width: 100% !important;
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
.hero-container {
|
| 125 |
+
margin-top: -3rem;
|
| 126 |
+
margin-left: -5rem;
|
| 127 |
+
margin-right: -5rem;
|
| 128 |
+
/* Simple negative margins to pull edge-to-edge */
|
| 129 |
+
padding: 2.5rem 1rem 2rem 1rem; /* Compact desktop padding */
|
| 130 |
+
}
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
/* Mobile Layout */
|
| 134 |
+
@media (max-width: 768px) {
|
| 135 |
+
.block-container {
|
| 136 |
+
padding-left: 1rem !important;
|
| 137 |
+
padding-right: 1rem !important;
|
| 138 |
+
padding-top: 0 !important;
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
.hero-container {
|
| 142 |
+
margin-top: -2rem;
|
| 143 |
+
margin-left: -1rem;
|
| 144 |
+
margin-right: -1rem;
|
| 145 |
+
/* Break out of the 1rem padding */
|
| 146 |
+
padding: 2rem 1rem 1.5rem 1rem; /* Compact mobile padding */
|
| 147 |
+
border-radius: 0 0 12px 12px;
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
/* Ensure font sizes are standard (Streamlit defaults is ~16px) */
|
| 151 |
+
/* We DO NOT override them to 17px/fixed, allowing system zoom to work. */
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
/* Hero Styling */
|
| 155 |
+
.hero-container {
|
| 156 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 157 |
+
color: white;
|
| 158 |
+
text-align: center;
|
| 159 |
+
border-radius: 0 0 16px 16px;
|
| 160 |
+
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
|
| 161 |
+
margin-bottom: 2rem;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
.hero-title {
|
| 165 |
+
font-size: 2rem; /* Slightly smaller */
|
| 166 |
+
font-weight: 700;
|
| 167 |
+
margin-bottom: 0.25rem;
|
| 168 |
+
color: white !important;
|
| 169 |
+
}
|
| 170 |
+
.hero-subtitle {
|
| 171 |
+
font-size: 1rem;
|
| 172 |
+
opacity: 0.95;
|
| 173 |
+
font-weight: 400;
|
| 174 |
+
color: rgba(255,255,255,0.95) !important;
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
/* Remove Header Decoration */
|
| 178 |
+
header[data-testid="stHeader"] {
|
| 179 |
+
background-color: transparent !important;
|
| 180 |
+
height: 0 !important;
|
| 181 |
+
z-index: 100;
|
| 182 |
+
}
|
| 183 |
+
div[data-testid="stDecoration"] { display: none; }
|
| 184 |
+
|
| 185 |
+
/* ---------------------------------------------------------------------
|
| 186 |
+
3. COMPONENT STYLING (Healthcare-like)
|
| 187 |
+
--------------------------------------------------------------------- */
|
| 188 |
+
|
| 189 |
+
/* Chat Bubbles - Clean & Readable */
|
| 190 |
+
.stChatMessage {
|
| 191 |
+
background-color: white;
|
| 192 |
+
border-radius: 12px;
|
| 193 |
+
border: 1px solid #e5e5e5;
|
| 194 |
+
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
|
| 195 |
+
padding: 1rem;
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
.stChatMessage[data-testid="stChatMessage"]:nth-of-type(odd) {
|
| 199 |
+
background-color: #f8f9fa;
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
/* Input Fields */
|
| 203 |
+
.stTextInput input {
|
| 204 |
+
border-radius: 20px; /* Matching healthcare-assistant roundness */
|
| 205 |
+
border: 1px solid #ddd;
|
| 206 |
+
padding: 0.75rem 1rem;
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
/* Buttons */
|
| 210 |
+
.stButton button {
|
| 211 |
+
border-radius: 20px; /* Matching healthcare-assistant */
|
| 212 |
+
min-height: 48px;
|
| 213 |
+
font-weight: 500;
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
/* Sidebar */
|
| 217 |
+
section[data-testid="stSidebar"] {
|
| 218 |
+
background-color: #ffffff;
|
| 219 |
+
border-right: 1px solid #eaeaea;
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
/* Minimize Sidebar Top Padding */
|
| 223 |
+
section[data-testid="stSidebar"] .block-container {
|
| 224 |
+
padding-top: 0rem !important;
|
| 225 |
+
padding-bottom: 0rem !important;
|
| 226 |
+
}
|
| 227 |
+
</style>
|
| 228 |
+
""", unsafe_allow_html=True)
|
| 229 |
+
|
| 230 |
+
# -----------------------------
|
| 231 |
+
# Logic
|
| 232 |
+
# -----------------------------
|
| 233 |
+
# @traceable(name="chatbot")
|
| 234 |
+
async def get_ai_response(prompt: str) -> str:
|
| 235 |
+
try:
|
| 236 |
+
agent = orchestrator_agent
|
| 237 |
+
# Ensure session is valid
|
| 238 |
+
current_session = st.session_state.ai_session
|
| 239 |
+
current_session = st.session_state.ai_session
|
| 240 |
+
with trace("Chatbot Agent Run"): # Keep existing custom trace wrapper
|
| 241 |
+
# Run agent
|
| 242 |
+
result = await Runner.run(agent, prompt, session=current_session)
|
| 243 |
+
return result.final_output
|
| 244 |
+
except InputGuardrailTripwireTriggered as e:
|
| 245 |
+
reasoning = getattr(e, "reasoning", None) \
|
| 246 |
+
or getattr(getattr(e, "output", None), "reasoning", None) \
|
| 247 |
+
or getattr(getattr(e, "guardrail_output", None), "reasoning", None) \
|
| 248 |
+
or "Guardrail triggered, but no reasoning provided."
|
| 249 |
+
return f"⚠️ **Guardrail Blocked Input**\n\n{reasoning}"
|
| 250 |
+
except Exception as e:
|
| 251 |
+
return f"❌ **Error**: {str(e)}"
|
| 252 |
+
|
| 253 |
+
# -----------------------------
|
| 254 |
+
# Sidebar - Quick Actions
|
| 255 |
+
# -----------------------------
|
| 256 |
+
with st.sidebar:
|
| 257 |
+
st.markdown("### ⚡ Quick Starters")
|
| 258 |
+
st.markdown("Select a prompt to start:")
|
| 259 |
+
|
| 260 |
+
# We use a trick with st.button to act as input triggers
|
| 261 |
+
# If a button is clicked, we'll handle it in the main loop logic
|
| 262 |
+
selected_prompt = None
|
| 263 |
+
for idx, prompt_text in enumerate(prompts):
|
| 264 |
+
label = prompt_labels[idx] if idx < len(prompt_labels) else f"Prompt {idx+1}"
|
| 265 |
+
if st.button(label, key=f"sidebar_btn_{idx}", use_container_width=True):
|
| 266 |
+
# Reset conversation
|
| 267 |
+
st.session_state.messages = []
|
| 268 |
+
st.session_state.ai_session_id = str(uuid.uuid4())
|
| 269 |
+
# Recreate session object with new ID
|
| 270 |
+
st.session_state.ai_session = SQLiteSession(f"conversation_{st.session_state.ai_session_id}.db")
|
| 271 |
+
selected_prompt = prompt_text
|
| 272 |
+
|
| 273 |
+
st.markdown("---")
|
| 274 |
+
if st.button("🗑️ Clear Conversation", use_container_width=True):
|
| 275 |
+
st.session_state.messages = []
|
| 276 |
+
st.rerun()
|
| 277 |
+
|
| 278 |
+
# -----------------------------
|
| 279 |
+
# Main Content
|
| 280 |
+
# -----------------------------
|
| 281 |
+
|
| 282 |
+
# Hero Banner (Always visible & Sticky)
|
| 283 |
+
st.markdown("""
|
| 284 |
+
<div class="hero-container" role="banner">
|
| 285 |
+
<div class="hero-title">🤖 AI Companion</div>
|
| 286 |
+
<div class="hero-subtitle">Your intelligent partner for research, analysis, and more.</div>
|
| 287 |
+
</div>
|
| 288 |
+
""", unsafe_allow_html=True)
|
| 289 |
+
|
| 290 |
+
# Display Chat History
|
| 291 |
+
for message in st.session_state.messages:
|
| 292 |
+
with st.chat_message(message["role"]):
|
| 293 |
+
st.markdown(message["content"], unsafe_allow_html=True)
|
| 294 |
+
|
| 295 |
+
# Chat Input Handling
|
| 296 |
+
# We handle both the chat input widget and the sidebar selection here
|
| 297 |
+
if prompt := (st.chat_input("Type your message...") or selected_prompt):
|
| 298 |
+
# User Message
|
| 299 |
+
st.session_state.messages.append({"role": "user", "content": prompt})
|
| 300 |
+
with st.chat_message("user"):
|
| 301 |
+
st.markdown(prompt)
|
| 302 |
+
|
| 303 |
+
# Assistant Response
|
| 304 |
+
with st.chat_message("assistant"):
|
| 305 |
+
with st.spinner("Thinking..."):
|
| 306 |
+
response_text = asyncio.run(get_ai_response(prompt))
|
| 307 |
+
st.markdown(response_text, unsafe_allow_html=True)
|
| 308 |
+
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
st.session_state.messages.append({"role": "assistant", "content": response_text})
|
| 312 |
+
|
| 313 |
+
# If it was a sidebar click, we need to rerun to clear the selection state potentially,
|
| 314 |
+
# but st.chat_input usually handles focus. With buttons, a rerun happens automatically
|
| 315 |
+
# but we want to make sure the input box is cleared (which 'selected_prompt' doesn't use).
|
| 316 |
+
if selected_prompt:
|
| 317 |
+
st.rerun()
|
src/chatbot_v1/prompts/economic_news.txt
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
##### Task
|
| 2 |
+
Provide a concise update on **major economic indicators released recently** in USA.
|
| 3 |
+
|
| 4 |
+
###### Include
|
| 5 |
+
- **Interest Rates**: Latest central bank decisions, current policy rates, and forward guidance.
|
| 6 |
+
- **Labor Market**: Unemployment rate, job creation figures, and key labor metrics (if available).
|
| 7 |
+
- **Inflation**: CPI, PCE, or other inflation data with MoM and YoY changes.
|
| 8 |
+
- **Growth Indicators**: GDP, PMIs, or industrial production released recently.
|
| 9 |
+
- **Market Reaction**: Brief impact on equities, bonds, FX, and commodities.
|
| 10 |
+
|
| 11 |
+
###### Guidelines
|
| 12 |
+
- Compare results against forecasts and prior releases
|
| 13 |
+
- Highlight notable surprises and their implications
|
| 14 |
+
- Keep the summary brief, factual, and structured
|
| 15 |
+
- **Always retrieve numerical data from primary or authoritative sources**
|
| 16 |
+
|
| 17 |
+
###### Fallback
|
| 18 |
+
- If no relevant data was released recently, explicitly state **“No major economic indicators were released during this period.”**
|
| 19 |
+
- If data is partially unavailable, summarize what is available and clearly note missing indicators.
|
| 20 |
+
- Do not infer or fabricate numbers under any circumstance.
|
| 21 |
+
|
| 22 |
+
###### Output Style
|
| 23 |
+
- Concise, factual, and well-structured
|
| 24 |
+
- Use clear bullet points or short paragraphs
|
| 25 |
+
- Avoid speculation unless explicitly labeled as interpretation
|
| 26 |
+
- **Cite data sources clearly**
|
| 27 |
+
- Use color and emoji to make it more engaging.
|
src/chatbot_v1/prompts/entertainment_updates.txt
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
##### Task
|
| 2 |
+
Provide the **top 5 recent movie or series updates** that are trending or newly released in USA.
|
| 3 |
+
|
| 4 |
+
###### For each title, include:
|
| 5 |
+
- **Title in bold** and optionally use **color or emojis** to make it fun (e.g., 🎬, 🍿, 🌟)
|
| 6 |
+
- A **short, 2–3 line snippet** that generates excitement or humor about the plot, cast, or vibe
|
| 7 |
+
- **Platform or source** where it can be watched (Netflix, Prime, Disney+, etc.)
|
| 8 |
+
- **Release date or premiere date**
|
| 9 |
+
|
| 10 |
+
###### Requirements / Guidelines
|
| 11 |
+
- Focus on **recent releases** (last 2–4 weeks) or currently trending content
|
| 12 |
+
- Keep the tone **fun, witty, and engaging**, like a friend recommending a show
|
| 13 |
+
- Use **emojis liberally** to emphasize excitement, genre, or humor
|
| 14 |
+
- Call out the **main actors and actresses** to build the interest
|
| 15 |
+
- Where possible, add a **light humorous quip or pun** about the movie/series
|
| 16 |
+
- If color is supported, use HTML span tags, e.g., `<span style="color:orange">Title</span>` for emphasis
|
| 17 |
+
|
| 18 |
+
###### Fallback
|
| 19 |
+
- If fewer than 5 titles are available, provide what is available and indicate:
|
| 20 |
+
**“Only X recent releases found.”**
|
| 21 |
+
- Do not fabricate platforms or release dates — only use verified sources
|
| 22 |
+
|
| 23 |
+
###### Output Style
|
| 24 |
+
- List format (1–5) sorted by **popularity or release date**
|
| 25 |
+
- **Title + snippet + watch source + release date** per entry
|
| 26 |
+
- Use **color, emojis, and humor** to make the output visually appealing and fun to read
|
src/chatbot_v1/prompts/india_news.txt
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
##### Task
|
| 2 |
+
Tell me the **top 3 headlines from India**.
|
| 3 |
+
|
| 4 |
+
###### For each headline, provide:
|
| 5 |
+
- **Title in bold**
|
| 6 |
+
- A **3‑line summary**
|
| 7 |
+
- **Publish date and time**
|
| 8 |
+
- A **link to the exact source URL**
|
| 9 |
+
|
| 10 |
+
###### Requirements
|
| 11 |
+
- Use authoritative news sources (e.g., major national/regional news outlets)
|
| 12 |
+
- Headlines should be **recent (last 24 hours)**
|
| 13 |
+
- Provide timestamps in **UTC**
|
| 14 |
+
- If publish date/time is not available, indicate “Date/Time not provided”
|
| 15 |
+
|
| 16 |
+
###### Fallback
|
| 17 |
+
- If fewer than 3 headlines are found, provide what is available and state:
|
| 18 |
+
**“Only X recent headlines found for India.”**
|
| 19 |
+
- Do not fabricate headlines, dates, or URLs
|
| 20 |
+
|
| 21 |
+
###### Output Style
|
| 22 |
+
- Structured list sorted by **most recent first**
|
| 23 |
+
- Clear and concise formatting as requested
|
| 24 |
+
- Use color and emoji to make it more engaging.
|
| 25 |
+
- Use `<span style="color:...">` for coloring the title if the renderer supports it
|
| 26 |
+
- Keep the output **concise, factual, and visually engaging**
|
src/chatbot_v1/prompts/market_sentiment.txt
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
##### Task
|
| 2 |
+
Act as a **Senior Market Analyst** and provide a concise market sentiment update for the **US Stock Market / S&P 500**.
|
| 3 |
+
|
| 4 |
+
###### Steps
|
| 5 |
+
1. **Data Gathering**: Search for the **top 5 financial news headlines** from the last 24 hours related to the [US Stock Market / S&P 500].
|
| 6 |
+
2. **Market Check**: Retrieve the **current value** and **today’s percentage change** for:
|
| 7 |
+
- **S&P 500 (SPX)**
|
| 8 |
+
- **VIX (Volatility Index)**
|
| 9 |
+
3. **Synthesis**: Based on the **tone of the news headlines** and the **index performance**, determine whether the **current market sentiment** is:
|
| 10 |
+
- **Bullish**
|
| 11 |
+
- **Bearish**
|
| 12 |
+
- **Neutral**
|
| 13 |
+
4. **Output**: Provide a:
|
| 14 |
+
- **Sentiment Score (1–10)**
|
| 15 |
+
- **Top 3 key drivers** influencing this sentiment
|
| 16 |
+
|
| 17 |
+
###### Guidelines
|
| 18 |
+
- Prioritize **reliable financial news sources** (e.g., Bloomberg, Reuters, WSJ, CNBC)
|
| 19 |
+
- Use **accurate, real-time market data** for indices
|
| 20 |
+
- Base sentiment on both **news tone** and **market movement**
|
| 21 |
+
- Avoid subjective or unsupported judgments
|
| 22 |
+
|
| 23 |
+
###### Fallback
|
| 24 |
+
- If no relevant financial headlines are found in the last 24 hours, clearly state:
|
| 25 |
+
**“No significant market news available in the last 24 hours.”**
|
| 26 |
+
- If either index value or change is unavailable, report available data and note missing values explicitly
|
| 27 |
+
- Do not invent or estimate values — only use verified data
|
| 28 |
+
|
| 29 |
+
###### Output Style
|
| 30 |
+
- Concise, factual, and structured
|
| 31 |
+
- Use clear bullet points or short paragraphs
|
| 32 |
+
- Include numerical values and data timestamps
|
| 33 |
+
- Provide **sources for headlines and index data**
|
| 34 |
+
- Use color and emoji to make it more engaging.
|
src/chatbot_v1/prompts/news_headlines.txt
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
##### Task
|
| 2 |
+
Tell me the **top 3 USA headlines**. Use **emojis** and, where supported, **HTML color tags** to make the output engaging.
|
| 3 |
+
|
| 4 |
+
###### For each headline, provide:
|
| 5 |
+
- **Title in bold** and optionally in color, e.g., `<span style="color:blue">Title</span>`
|
| 6 |
+
- A **3-line summary** with an emoji indicating the type of news:
|
| 7 |
+
- 📰 Politics
|
| 8 |
+
- 💼 Business
|
| 9 |
+
- 🌎 World
|
| 10 |
+
- ⚡ Breaking news
|
| 11 |
+
- **Publish date and time** (UTC)
|
| 12 |
+
- A **link to the exact source URL**
|
| 13 |
+
|
| 14 |
+
###### Requirements
|
| 15 |
+
- Use **credible news sources** (Reuters, AP, BBC, Guardian, etc.)
|
| 16 |
+
- Headlines should be **recent (last 24 hours)**
|
| 17 |
+
- If publish time is unavailable, indicate **“Time not provided”**
|
| 18 |
+
|
| 19 |
+
###### Fallback
|
| 20 |
+
- If fewer than 3 headlines are found, state:
|
| 21 |
+
**“Only X recent headlines found for the USA.”**
|
| 22 |
+
- Do not fabricate headlines, dates, or URLs
|
| 23 |
+
|
| 24 |
+
###### Output Style
|
| 25 |
+
- Structured list sorted by **most recent first**
|
| 26 |
+
- Use emojis consistently to indicate news type
|
| 27 |
+
- Use `<span style="color:...">` for coloring the title if the renderer supports it
|
| 28 |
+
- Keep the output **concise, factual, and visually engaging**
|
src/chatbot_v1/prompts/odia_news.txt
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
##### Task
|
| 2 |
+
Tell me the **top 3 headlines from Odisha**.
|
| 3 |
+
|
| 4 |
+
###### For each headline, provide:
|
| 5 |
+
- **Title in bold**
|
| 6 |
+
- A **3‑line summary**
|
| 7 |
+
- **Publish date and time**
|
| 8 |
+
- A **link to the exact source URL**
|
| 9 |
+
|
| 10 |
+
###### Requirements
|
| 11 |
+
- Use authoritative news sources (e.g., major national/regional news outlets)
|
| 12 |
+
- Headlines should be **recent (last 24 hours)**
|
| 13 |
+
- Provide timestamps in **UTC**
|
| 14 |
+
- If publish date/time is not available, indicate “Date/Time not provided”
|
| 15 |
+
|
| 16 |
+
###### Fallback
|
| 17 |
+
- If fewer than 3 headlines are found, provide what is available and state:
|
| 18 |
+
**“Only X recent headlines found for Odisha.”**
|
| 19 |
+
- Do not fabricate headlines, dates, or URLs
|
| 20 |
+
|
| 21 |
+
###### Output Style
|
| 22 |
+
- Structured list sorted by **most recent first**
|
| 23 |
+
- Clear and concise formatting as requested
|
| 24 |
+
- Use color and emoji to make it more engaging.
|
| 25 |
+
- Use `<span style="color:...">` for coloring the title if the renderer supports it
|
| 26 |
+
- Keep the output **concise, factual, and visually engaging**
|
src/chatbot_v1/prompts/trade_recommendation.txt
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
##### Task
|
| 2 |
+
Recommend **three option spreads** with **>80% probability of profit**. Perform a thorough analysis of each underlying’s **3-month price trend** and current **market sentiment** before selecting spreads.
|
| 3 |
+
|
| 4 |
+
###### Steps
|
| 5 |
+
1. **Stock selection & analysis**
|
| 6 |
+
- Analyze the **last 3 months** of price action (trend, volatility, support/resistance).
|
| 7 |
+
- Assess market sentiment from the **last 7 days** of headlines and social/analyst tone.
|
| 8 |
+
2. **Spread construction**
|
| 9 |
+
- For each of the **3 recommended spreads**, specify:
|
| 10 |
+
- **Underlying ticker**
|
| 11 |
+
- **Spread type** (e.g., bull put, bear call, iron condor)
|
| 12 |
+
- **Exact expiry date** (YYYY-MM-DD)
|
| 13 |
+
- **Each leg**: side (sell/buy), option type (put/call), **strike price**
|
| 14 |
+
- **Premium entry**: exact net credit/debit per share (use live bid/ask midpoint)
|
| 15 |
+
- **Position size guidance** (risk per trade as % of portfolio) — optional
|
| 16 |
+
3. **Probability & rationale**
|
| 17 |
+
- Provide a **quantitative probability of profit (%)** (clearly state model/method used).
|
| 18 |
+
- Give a concise **rationale** linking 3-month trend, implied volatility, and sentiment to the spread choice.
|
| 19 |
+
- Show key supporting numbers: current spot, IV30, recent volatility, and relevant news headlines (with timestamps).
|
| 20 |
+
|
| 21 |
+
###### Requirements / Guidelines
|
| 22 |
+
- Target **>80% probability of profit** for each spread. Explain how the probability was computed (IV-based log-normal, normal approximation, or risk-neutral model).
|
| 23 |
+
- **Always** use live option-chain quotes (bid/ask midpoint) and authoritative sources for prices/IV (e.g., exchange data, major market data providers).
|
| 24 |
+
- Compare outcomes **vs. forecasts / recent range** and note any idiosyncratic risk (earnings, events).
|
| 25 |
+
- Include **exact timestamps** (UTC) for all quoted prices.
|
| 26 |
+
- Provide **sources** for price, IV, and headlines.
|
| 27 |
+
|
| 28 |
+
###### Fallback
|
| 29 |
+
- If live option-chain or price data is unavailable, state: **“Live market data unavailable — cannot generate exact strike/premium. Provide analysis based on most recent available snapshot.”**
|
| 30 |
+
- If sentiment or 3-month history is incomplete, present what is available and **explicitly list missing items**.
|
| 31 |
+
- **Do not fabricate** strikes, premiums, probabilities, or news — only use verified data.
|
| 32 |
+
|
| 33 |
+
###### Output Style
|
| 34 |
+
- For each spread, use a compact block with:
|
| 35 |
+
- Ticker — Spread type — Expiry (YYYY-MM-DD) — Net premium — PO P (%)
|
| 36 |
+
- Legs: bullet list of exact leg details (sell/buy, put/call, strike, premium)
|
| 37 |
+
- Rationale: 2–3 short sentences linking trend & sentiment to the trade
|
| 38 |
+
- Sources & timestamps
|
| 39 |
+
- Keep language concise, factual, and machine/agent friendly for downstream parsing.
|
| 40 |
+
- Use color and emoji to make it more engaging.
|
src/chatbot_v1/prompts/upcoming_earnings.txt
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
##### Task
|
| 2 |
+
Search for **upcoming critical earnings announcements** in the stock market.
|
| 3 |
+
|
| 4 |
+
###### Include
|
| 5 |
+
- **Ticker**
|
| 6 |
+
- **Company name**
|
| 7 |
+
- **Earnings date & time**
|
| 8 |
+
- **Expected EPS & revenue consensus**
|
| 9 |
+
- **Last quarter’s actual EPS & revenue**
|
| 10 |
+
- **Implied volatility trend ahead of earnings**
|
| 11 |
+
|
| 12 |
+
###### Requirements / Guidelines
|
| 13 |
+
- Focus on **high‑impact names** (large cap, high volume, sector leaders)
|
| 14 |
+
- Include **earnings expected within the next 7 calendar days**
|
| 15 |
+
- Use **primary/authoritative sources** for earnings dates and estimates (e.g., exchange calendars, Bloomberg/Refinitiv/Estimize)
|
| 16 |
+
- Show **timestamped data** (UTC)
|
| 17 |
+
|
| 18 |
+
###### Fallback
|
| 19 |
+
- If no critical earnings are found in the next 7 days, state:
|
| 20 |
+
**“No upcoming critical earnings announcements found within the specified period.”**
|
| 21 |
+
- If consensus estimates are unavailable, list the earnings date/time and note missing metrics.
|
| 22 |
+
|
| 23 |
+
###### Output Style
|
| 24 |
+
- Structured list sorted by **earnings date**
|
| 25 |
+
- Use clear bullet points or short paragraphs
|
| 26 |
+
- Provide **sources** for each item
|
| 27 |
+
- Use color and emoji to make it more engaging.
|
src/chatbot_v1/trace_config.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# trace_config.py
|
| 2 |
+
import openai
|
| 3 |
+
from langsmith.wrappers import wrap_openai
|
| 4 |
+
import os
|
| 5 |
+
|
| 6 |
+
print("🔌 APPLYING LANGSMITH TRACE PATCH...")
|
| 7 |
+
|
| 8 |
+
# 1. Save original classes
|
| 9 |
+
_OriginalOpenAI = openai.OpenAI
|
| 10 |
+
_OriginalAsyncOpenAI = openai.AsyncOpenAI
|
| 11 |
+
|
| 12 |
+
# 2. Define the shim
|
| 13 |
+
def PatchedOpenAI(*args, **kwargs):
|
| 14 |
+
print("✨ Creating Wrapped OpenAI Client (Sync)") # Debug print
|
| 15 |
+
client = _OriginalOpenAI(*args, **kwargs)
|
| 16 |
+
return wrap_openai(client)
|
| 17 |
+
|
| 18 |
+
def PatchedAsyncOpenAI(*args, **kwargs):
|
| 19 |
+
print("✨ Creating Wrapped OpenAI Client (Async)") # Debug print
|
| 20 |
+
client = _OriginalAsyncOpenAI(*args, **kwargs)
|
| 21 |
+
return wrap_openai(client)
|
| 22 |
+
|
| 23 |
+
# 3. Apply patch
|
| 24 |
+
openai.OpenAI = PatchedOpenAI
|
| 25 |
+
openai.AsyncOpenAI = PatchedAsyncOpenAI
|
| 26 |
+
|
| 27 |
+
from langsmith import traceable
|
| 28 |
+
|
| 29 |
+
# You can't decorate the class directly with @traceable,
|
| 30 |
+
# but you can use this helper to wrap all methods:
|
| 31 |
+
|
| 32 |
+
def instrument_class(cls):
|
| 33 |
+
for attr_name, attr_value in cls.__dict__.items():
|
| 34 |
+
if callable(attr_value) and not attr_name.startswith("__"):
|
| 35 |
+
setattr(cls, attr_name, traceable(attr_value, run_type="tool"))
|
| 36 |
+
return cls
|
| 37 |
+
|
uv.lock
CHANGED
|
@@ -15,6 +15,10 @@ dependencies = [
|
|
| 15 |
{ name = "autogen-agentchat" },
|
| 16 |
{ name = "autogen-ext", extra = ["grpc", "mcp", "openai"] },
|
| 17 |
{ name = "azure-identity" },
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
{ name = "beautifulsoup4" },
|
| 19 |
{ name = "chromadb" },
|
| 20 |
{ name = "datasets" },
|
|
@@ -61,11 +65,13 @@ dependencies = [
|
|
| 61 |
{ name = "opentelemetry-api" },
|
| 62 |
{ name = "opentelemetry-exporter-otlp" },
|
| 63 |
{ name = "opentelemetry-sdk" },
|
|
|
|
| 64 |
{ name = "pillow" },
|
| 65 |
{ name = "playwright" },
|
| 66 |
{ name = "plotly" },
|
| 67 |
{ name = "polygon-api-client" },
|
| 68 |
{ name = "psutil" },
|
|
|
|
| 69 |
{ name = "pymupdf" },
|
| 70 |
{ name = "pypdf" },
|
| 71 |
{ name = "pypdf2" },
|
|
@@ -103,6 +109,10 @@ requires-dist = [
|
|
| 103 |
{ name = "autogen-agentchat", specifier = "==0.4.7" },
|
| 104 |
{ name = "autogen-ext", extras = ["grpc", "mcp", "ollama", "openai"], specifier = "==0.4.7" },
|
| 105 |
{ name = "azure-identity", specifier = ">=1.25.1" },
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
{ name = "beautifulsoup4", specifier = ">=4.12.3" },
|
| 107 |
{ name = "chromadb", specifier = ">=0.4.0" },
|
| 108 |
{ name = "datasets", specifier = ">=4.4.1" },
|
|
@@ -149,11 +159,13 @@ requires-dist = [
|
|
| 149 |
{ name = "opentelemetry-api", specifier = ">=1.20.0" },
|
| 150 |
{ name = "opentelemetry-exporter-otlp", specifier = ">=1.20.0" },
|
| 151 |
{ name = "opentelemetry-sdk", specifier = ">=1.20.0" },
|
|
|
|
| 152 |
{ name = "pillow" },
|
| 153 |
{ name = "playwright", specifier = ">=1.51.0" },
|
| 154 |
{ name = "plotly", specifier = ">=6.5.0" },
|
| 155 |
{ name = "polygon-api-client", specifier = ">=1.16.3" },
|
| 156 |
{ name = "psutil", specifier = ">=7.0.0" },
|
|
|
|
| 157 |
{ name = "pymupdf" },
|
| 158 |
{ name = "pypdf", specifier = ">=6.3.0" },
|
| 159 |
{ name = "pypdf2", specifier = ">=3.0.1" },
|
|
@@ -446,6 +458,15 @@ openai = [
|
|
| 446 |
{ name = "tiktoken" },
|
| 447 |
]
|
| 448 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 449 |
[[package]]
|
| 450 |
name = "azure-core"
|
| 451 |
version = "1.38.0"
|
|
@@ -475,6 +496,75 @@ wheels = [
|
|
| 475 |
{ url = "https://files.pythonhosted.org/packages/83/7b/5652771e24fff12da9dde4c20ecf4682e606b104f26419d139758cc935a6/azure_identity-1.25.1-py3-none-any.whl", hash = "sha256:e9edd720af03dff020223cd269fa3a61e8f345ea75443858273bcb44844ab651", size = 191317, upload-time = "2025-10-06T20:30:04.251Z" },
|
| 476 |
]
|
| 477 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 478 |
[[package]]
|
| 479 |
name = "backoff"
|
| 480 |
version = "2.2.1"
|
|
@@ -1632,6 +1722,15 @@ wheels = [
|
|
| 1632 |
{ url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" },
|
| 1633 |
]
|
| 1634 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1635 |
[[package]]
|
| 1636 |
name = "jedi"
|
| 1637 |
version = "0.19.2"
|
|
@@ -3594,6 +3693,28 @@ wheels = [
|
|
| 3594 |
{ url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" },
|
| 3595 |
]
|
| 3596 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3597 |
[[package]]
|
| 3598 |
name = "pillow"
|
| 3599 |
version = "12.1.0"
|
|
@@ -3971,6 +4092,22 @@ wheels = [
|
|
| 3971 |
{ url = "https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f", size = 63551, upload-time = "2025-06-20T18:45:26.937Z" },
|
| 3972 |
]
|
| 3973 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3974 |
[[package]]
|
| 3975 |
name = "pygments"
|
| 3976 |
version = "2.19.2"
|
|
@@ -4009,6 +4146,29 @@ wheels = [
|
|
| 4009 |
{ url = "https://files.pythonhosted.org/packages/dd/c3/d0047678146c294469c33bae167c8ace337deafb736b0bf97b9bc481aa65/pymupdf-1.26.7-cp310-abi3-win_amd64.whl", hash = "sha256:425b1befe40d41b72eb0fe211711c7ae334db5eb60307e9dd09066ed060cceba", size = 18405952, upload-time = "2025-12-11T21:48:02.947Z" },
|
| 4010 |
]
|
| 4011 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4012 |
[[package]]
|
| 4013 |
name = "pyparsing"
|
| 4014 |
version = "3.3.2"
|
|
@@ -4744,6 +4904,24 @@ wheels = [
|
|
| 4744 |
{ url = "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", size = 16588, upload-time = "2020-11-01T01:40:20.672Z" },
|
| 4745 |
]
|
| 4746 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4747 |
[[package]]
|
| 4748 |
name = "torch"
|
| 4749 |
version = "2.10.0"
|
|
@@ -4775,6 +4953,7 @@ dependencies = [
|
|
| 4775 |
{ name = "typing-extensions" },
|
| 4776 |
]
|
| 4777 |
wheels = [
|
|
|
|
| 4778 |
{ url = "https://files.pythonhosted.org/packages/cc/af/758e242e9102e9988969b5e621d41f36b8f258bb4a099109b7a4b4b50ea4/torch-2.10.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:5fd4117d89ffd47e3dcc71e71a22efac24828ad781c7e46aaaf56bf7f2796acf", size = 145996088, upload-time = "2026-01-21T16:24:44.171Z" },
|
| 4779 |
{ url = "https://files.pythonhosted.org/packages/23/8e/3c74db5e53bff7ed9e34c8123e6a8bfef718b2450c35eefab85bb4a7e270/torch-2.10.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:787124e7db3b379d4f1ed54dd12ae7c741c16a4d29b49c0226a89bea50923ffb", size = 915711952, upload-time = "2026-01-21T16:23:53.503Z" },
|
| 4780 |
{ url = "https://files.pythonhosted.org/packages/6e/01/624c4324ca01f66ae4c7cd1b74eb16fb52596dce66dbe51eff95ef9e7a4c/torch-2.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:2c66c61f44c5f903046cc696d088e21062644cbe541c7f1c4eaae88b2ad23547", size = 113757972, upload-time = "2026-01-21T16:24:39.516Z" },
|
|
|
|
| 15 |
{ name = "autogen-agentchat" },
|
| 16 |
{ name = "autogen-ext", extra = ["grpc", "mcp", "openai"] },
|
| 17 |
{ name = "azure-identity" },
|
| 18 |
+
{ name = "azure-mgmt-compute" },
|
| 19 |
+
{ name = "azure-mgmt-monitor" },
|
| 20 |
+
{ name = "azure-mgmt-resource" },
|
| 21 |
+
{ name = "azure-monitor-query" },
|
| 22 |
{ name = "beautifulsoup4" },
|
| 23 |
{ name = "chromadb" },
|
| 24 |
{ name = "datasets" },
|
|
|
|
| 65 |
{ name = "opentelemetry-api" },
|
| 66 |
{ name = "opentelemetry-exporter-otlp" },
|
| 67 |
{ name = "opentelemetry-sdk" },
|
| 68 |
+
{ name = "phidata" },
|
| 69 |
{ name = "pillow" },
|
| 70 |
{ name = "playwright" },
|
| 71 |
{ name = "plotly" },
|
| 72 |
{ name = "polygon-api-client" },
|
| 73 |
{ name = "psutil" },
|
| 74 |
+
{ name = "pygithub" },
|
| 75 |
{ name = "pymupdf" },
|
| 76 |
{ name = "pypdf" },
|
| 77 |
{ name = "pypdf2" },
|
|
|
|
| 109 |
{ name = "autogen-agentchat", specifier = "==0.4.7" },
|
| 110 |
{ name = "autogen-ext", extras = ["grpc", "mcp", "ollama", "openai"], specifier = "==0.4.7" },
|
| 111 |
{ name = "azure-identity", specifier = ">=1.25.1" },
|
| 112 |
+
{ name = "azure-mgmt-compute", specifier = ">=30.3.0" },
|
| 113 |
+
{ name = "azure-mgmt-monitor", specifier = ">=6.0.2" },
|
| 114 |
+
{ name = "azure-mgmt-resource", specifier = ">=23.0.1" },
|
| 115 |
+
{ name = "azure-monitor-query", specifier = ">=1.2.0" },
|
| 116 |
{ name = "beautifulsoup4", specifier = ">=4.12.3" },
|
| 117 |
{ name = "chromadb", specifier = ">=0.4.0" },
|
| 118 |
{ name = "datasets", specifier = ">=4.4.1" },
|
|
|
|
| 159 |
{ name = "opentelemetry-api", specifier = ">=1.20.0" },
|
| 160 |
{ name = "opentelemetry-exporter-otlp", specifier = ">=1.20.0" },
|
| 161 |
{ name = "opentelemetry-sdk", specifier = ">=1.20.0" },
|
| 162 |
+
{ name = "phidata", specifier = ">=2.0.0" },
|
| 163 |
{ name = "pillow" },
|
| 164 |
{ name = "playwright", specifier = ">=1.51.0" },
|
| 165 |
{ name = "plotly", specifier = ">=6.5.0" },
|
| 166 |
{ name = "polygon-api-client", specifier = ">=1.16.3" },
|
| 167 |
{ name = "psutil", specifier = ">=7.0.0" },
|
| 168 |
+
{ name = "pygithub", specifier = ">=2.1.1" },
|
| 169 |
{ name = "pymupdf" },
|
| 170 |
{ name = "pypdf", specifier = ">=6.3.0" },
|
| 171 |
{ name = "pypdf2", specifier = ">=3.0.1" },
|
|
|
|
| 458 |
{ name = "tiktoken" },
|
| 459 |
]
|
| 460 |
|
| 461 |
+
[[package]]
|
| 462 |
+
name = "azure-common"
|
| 463 |
+
version = "1.1.28"
|
| 464 |
+
source = { registry = "https://pypi.org/simple" }
|
| 465 |
+
sdist = { url = "https://files.pythonhosted.org/packages/3e/71/f6f71a276e2e69264a97ad39ef850dca0a04fce67b12570730cb38d0ccac/azure-common-1.1.28.zip", hash = "sha256:4ac0cd3214e36b6a1b6a442686722a5d8cc449603aa833f3f0f40bda836704a3", size = 20914, upload-time = "2022-02-03T19:39:44.373Z" }
|
| 466 |
+
wheels = [
|
| 467 |
+
{ url = "https://files.pythonhosted.org/packages/62/55/7f118b9c1b23ec15ca05d15a578d8207aa1706bc6f7c87218efffbbf875d/azure_common-1.1.28-py2.py3-none-any.whl", hash = "sha256:5c12d3dcf4ec20599ca6b0d3e09e86e146353d443e7fcc050c9a19c1f9df20ad", size = 14462, upload-time = "2022-02-03T19:39:42.417Z" },
|
| 468 |
+
]
|
| 469 |
+
|
| 470 |
[[package]]
|
| 471 |
name = "azure-core"
|
| 472 |
version = "1.38.0"
|
|
|
|
| 496 |
{ url = "https://files.pythonhosted.org/packages/83/7b/5652771e24fff12da9dde4c20ecf4682e606b104f26419d139758cc935a6/azure_identity-1.25.1-py3-none-any.whl", hash = "sha256:e9edd720af03dff020223cd269fa3a61e8f345ea75443858273bcb44844ab651", size = 191317, upload-time = "2025-10-06T20:30:04.251Z" },
|
| 497 |
]
|
| 498 |
|
| 499 |
+
[[package]]
|
| 500 |
+
name = "azure-mgmt-compute"
|
| 501 |
+
version = "37.2.0"
|
| 502 |
+
source = { registry = "https://pypi.org/simple" }
|
| 503 |
+
dependencies = [
|
| 504 |
+
{ name = "azure-mgmt-core" },
|
| 505 |
+
{ name = "isodate" },
|
| 506 |
+
{ name = "typing-extensions" },
|
| 507 |
+
]
|
| 508 |
+
sdist = { url = "https://files.pythonhosted.org/packages/e2/e3/c887e27260754014dc63fc33bf612f1c7f1751f74e80d1aaa32491af3ffa/azure_mgmt_compute-37.2.0.tar.gz", hash = "sha256:23499d4d5ad2b2bf40a4c59df2684cc4c9cef0f9672a4e842bb9a1cf6b62f628", size = 534068, upload-time = "2026-01-27T06:39:05.39Z" }
|
| 509 |
+
wheels = [
|
| 510 |
+
{ url = "https://files.pythonhosted.org/packages/be/78/8dcdb92dd9f716d08a3ac6b31c31a12cfcf8c430b2c312cbf9cc6e4695e8/azure_mgmt_compute-37.2.0-py3-none-any.whl", hash = "sha256:70741c26ac94c30408a3b20f4fdfe93e6481e308b3c14a6dbefdfd4794028616", size = 686212, upload-time = "2026-01-27T06:39:07.016Z" },
|
| 511 |
+
]
|
| 512 |
+
|
| 513 |
+
[[package]]
|
| 514 |
+
name = "azure-mgmt-core"
|
| 515 |
+
version = "1.6.0"
|
| 516 |
+
source = { registry = "https://pypi.org/simple" }
|
| 517 |
+
dependencies = [
|
| 518 |
+
{ name = "azure-core" },
|
| 519 |
+
]
|
| 520 |
+
sdist = { url = "https://files.pythonhosted.org/packages/3e/99/fa9e7551313d8c7099c89ebf3b03cd31beb12e1b498d575aa19bb59a5d04/azure_mgmt_core-1.6.0.tar.gz", hash = "sha256:b26232af857b021e61d813d9f4ae530465255cb10b3dde945ad3743f7a58e79c", size = 30818, upload-time = "2025-07-03T02:02:24.093Z" }
|
| 521 |
+
wheels = [
|
| 522 |
+
{ url = "https://files.pythonhosted.org/packages/a0/26/c79f962fd3172b577b6f38685724de58b6b4337a51d3aad316a43a4558c6/azure_mgmt_core-1.6.0-py3-none-any.whl", hash = "sha256:0460d11e85c408b71c727ee1981f74432bc641bb25dfcf1bb4e90a49e776dbc4", size = 29310, upload-time = "2025-07-03T02:02:25.203Z" },
|
| 523 |
+
]
|
| 524 |
+
|
| 525 |
+
[[package]]
|
| 526 |
+
name = "azure-mgmt-monitor"
|
| 527 |
+
version = "7.0.0"
|
| 528 |
+
source = { registry = "https://pypi.org/simple" }
|
| 529 |
+
dependencies = [
|
| 530 |
+
{ name = "azure-common" },
|
| 531 |
+
{ name = "azure-mgmt-core" },
|
| 532 |
+
{ name = "isodate" },
|
| 533 |
+
{ name = "typing-extensions" },
|
| 534 |
+
]
|
| 535 |
+
sdist = { url = "https://files.pythonhosted.org/packages/0e/12/25874f6b894e972646244f570a23298969b58f57cfb7a188e2740017b43a/azure_mgmt_monitor-7.0.0.tar.gz", hash = "sha256:b75f536441d430f69ff873a1646e5f5dbcb3080a10768a59d0adc01541623816", size = 195496, upload-time = "2025-07-28T07:46:17.031Z" }
|
| 536 |
+
wheels = [
|
| 537 |
+
{ url = "https://files.pythonhosted.org/packages/c6/d1/f6ea4731edfa02c14756770d7c3d5202b40c5c72744f15142c0d89b6d957/azure_mgmt_monitor-7.0.0-py3-none-any.whl", hash = "sha256:ad63b5d187e21d2d34366271ade6abbeea1fcf76e313ff0f83d394d9c124aa1b", size = 245243, upload-time = "2025-07-28T07:46:18.594Z" },
|
| 538 |
+
]
|
| 539 |
+
|
| 540 |
+
[[package]]
|
| 541 |
+
name = "azure-mgmt-resource"
|
| 542 |
+
version = "25.0.0"
|
| 543 |
+
source = { registry = "https://pypi.org/simple" }
|
| 544 |
+
dependencies = [
|
| 545 |
+
{ name = "azure-mgmt-core" },
|
| 546 |
+
{ name = "isodate" },
|
| 547 |
+
{ name = "typing-extensions" },
|
| 548 |
+
]
|
| 549 |
+
sdist = { url = "https://files.pythonhosted.org/packages/d7/7e/b3f9d544a94782be9c5ab8123d2fa7fb20cbdf3f5a16b883f308865e1406/azure_mgmt_resource-25.0.0.tar.gz", hash = "sha256:dc123a9f6509c37299d7716c9090cff0a9d73309b228cc094ea950ce3cca3603", size = 92837, upload-time = "2026-02-06T06:00:39.699Z" }
|
| 550 |
+
wheels = [
|
| 551 |
+
{ url = "https://files.pythonhosted.org/packages/92/41/ce12546aa2a20c4f37d061bfa7df3bf8fa72ff01e7557ec330929c72ec7d/azure_mgmt_resource-25.0.0-py3-none-any.whl", hash = "sha256:f6f17b2305abe9bf6ec6c92a9410af21a2b0d805cc98e94d80c07220924a045b", size = 83670, upload-time = "2026-02-06T06:00:41.317Z" },
|
| 552 |
+
]
|
| 553 |
+
|
| 554 |
+
[[package]]
|
| 555 |
+
name = "azure-monitor-query"
|
| 556 |
+
version = "2.0.0"
|
| 557 |
+
source = { registry = "https://pypi.org/simple" }
|
| 558 |
+
dependencies = [
|
| 559 |
+
{ name = "azure-core" },
|
| 560 |
+
{ name = "isodate" },
|
| 561 |
+
{ name = "typing-extensions" },
|
| 562 |
+
]
|
| 563 |
+
sdist = { url = "https://files.pythonhosted.org/packages/04/c0/e5c760f38224575f1eba35c319842f2be30fab599854ba9bd0b19d39c261/azure_monitor_query-2.0.0.tar.gz", hash = "sha256:7b05f2fcac4fb67fc9f77a7d4c5d98a0f3099fb73b57c69ec1b080773994671b", size = 86658, upload-time = "2025-07-30T22:23:41.534Z" }
|
| 564 |
+
wheels = [
|
| 565 |
+
{ url = "https://files.pythonhosted.org/packages/52/0c/6b08a5a1e5f0bd97cefa13c53bf47f281a9a11732d19a94a86709acbc6bd/azure_monitor_query-2.0.0-py3-none-any.whl", hash = "sha256:8f52d581271d785e12f49cd5aaa144b8910fb843db2373855a7ef94c7fc462ea", size = 71102, upload-time = "2025-07-30T22:23:43.056Z" },
|
| 566 |
+
]
|
| 567 |
+
|
| 568 |
[[package]]
|
| 569 |
name = "backoff"
|
| 570 |
version = "2.2.1"
|
|
|
|
| 1722 |
{ url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" },
|
| 1723 |
]
|
| 1724 |
|
| 1725 |
+
[[package]]
|
| 1726 |
+
name = "isodate"
|
| 1727 |
+
version = "0.7.2"
|
| 1728 |
+
source = { registry = "https://pypi.org/simple" }
|
| 1729 |
+
sdist = { url = "https://files.pythonhosted.org/packages/54/4d/e940025e2ce31a8ce1202635910747e5a87cc3a6a6bb2d00973375014749/isodate-0.7.2.tar.gz", hash = "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6", size = 29705, upload-time = "2024-10-08T23:04:11.5Z" }
|
| 1730 |
+
wheels = [
|
| 1731 |
+
{ url = "https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", size = 22320, upload-time = "2024-10-08T23:04:09.501Z" },
|
| 1732 |
+
]
|
| 1733 |
+
|
| 1734 |
[[package]]
|
| 1735 |
name = "jedi"
|
| 1736 |
version = "0.19.2"
|
|
|
|
| 3693 |
{ url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" },
|
| 3694 |
]
|
| 3695 |
|
| 3696 |
+
[[package]]
|
| 3697 |
+
name = "phidata"
|
| 3698 |
+
version = "2.7.10"
|
| 3699 |
+
source = { registry = "https://pypi.org/simple" }
|
| 3700 |
+
dependencies = [
|
| 3701 |
+
{ name = "docstring-parser" },
|
| 3702 |
+
{ name = "gitpython" },
|
| 3703 |
+
{ name = "httpx" },
|
| 3704 |
+
{ name = "pydantic" },
|
| 3705 |
+
{ name = "pydantic-settings" },
|
| 3706 |
+
{ name = "python-dotenv" },
|
| 3707 |
+
{ name = "pyyaml" },
|
| 3708 |
+
{ name = "rich" },
|
| 3709 |
+
{ name = "tomli" },
|
| 3710 |
+
{ name = "typer" },
|
| 3711 |
+
{ name = "typing-extensions" },
|
| 3712 |
+
]
|
| 3713 |
+
sdist = { url = "https://files.pythonhosted.org/packages/5c/bc/808d8f82c1be723d51c945bbedca62c68950b3cb294716f309428a9d3be7/phidata-2.7.10.tar.gz", hash = "sha256:d8d01e5e3841bf0df659f57d84a5eb5a8e5271fdf2f2899f6037f54839463482", size = 500479, upload-time = "2025-01-27T14:27:54.142Z" }
|
| 3714 |
+
wheels = [
|
| 3715 |
+
{ url = "https://files.pythonhosted.org/packages/90/de/814e0bc3532a9a0ad45c7164ac3a43abfcaac1253e61ad852ae344badc55/phidata-2.7.10-py3-none-any.whl", hash = "sha256:9cb3b2bf790440d644c5443cd20e0ab27dea98e5b7cfed4676a615e1583e2501", size = 716942, upload-time = "2025-01-27T14:27:50.415Z" },
|
| 3716 |
+
]
|
| 3717 |
+
|
| 3718 |
[[package]]
|
| 3719 |
name = "pillow"
|
| 3720 |
version = "12.1.0"
|
|
|
|
| 4092 |
{ url = "https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f", size = 63551, upload-time = "2025-06-20T18:45:26.937Z" },
|
| 4093 |
]
|
| 4094 |
|
| 4095 |
+
[[package]]
|
| 4096 |
+
name = "pygithub"
|
| 4097 |
+
version = "2.8.1"
|
| 4098 |
+
source = { registry = "https://pypi.org/simple" }
|
| 4099 |
+
dependencies = [
|
| 4100 |
+
{ name = "pyjwt", extra = ["crypto"] },
|
| 4101 |
+
{ name = "pynacl" },
|
| 4102 |
+
{ name = "requests" },
|
| 4103 |
+
{ name = "typing-extensions" },
|
| 4104 |
+
{ name = "urllib3" },
|
| 4105 |
+
]
|
| 4106 |
+
sdist = { url = "https://files.pythonhosted.org/packages/c1/74/e560bdeffea72ecb26cff27f0fad548bbff5ecc51d6a155311ea7f9e4c4c/pygithub-2.8.1.tar.gz", hash = "sha256:341b7c78521cb07324ff670afd1baa2bf5c286f8d9fd302c1798ba594a5400c9", size = 2246994, upload-time = "2025-09-02T17:41:54.674Z" }
|
| 4107 |
+
wheels = [
|
| 4108 |
+
{ url = "https://files.pythonhosted.org/packages/07/ba/7049ce39f653f6140aac4beb53a5aaf08b4407b6a3019aae394c1c5244ff/pygithub-2.8.1-py3-none-any.whl", hash = "sha256:23a0a5bca93baef082e03411bf0ce27204c32be8bfa7abc92fe4a3e132936df0", size = 432709, upload-time = "2025-09-02T17:41:52.947Z" },
|
| 4109 |
+
]
|
| 4110 |
+
|
| 4111 |
[[package]]
|
| 4112 |
name = "pygments"
|
| 4113 |
version = "2.19.2"
|
|
|
|
| 4146 |
{ url = "https://files.pythonhosted.org/packages/dd/c3/d0047678146c294469c33bae167c8ace337deafb736b0bf97b9bc481aa65/pymupdf-1.26.7-cp310-abi3-win_amd64.whl", hash = "sha256:425b1befe40d41b72eb0fe211711c7ae334db5eb60307e9dd09066ed060cceba", size = 18405952, upload-time = "2025-12-11T21:48:02.947Z" },
|
| 4147 |
]
|
| 4148 |
|
| 4149 |
+
[[package]]
|
| 4150 |
+
name = "pynacl"
|
| 4151 |
+
version = "1.6.2"
|
| 4152 |
+
source = { registry = "https://pypi.org/simple" }
|
| 4153 |
+
dependencies = [
|
| 4154 |
+
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
| 4155 |
+
]
|
| 4156 |
+
sdist = { url = "https://files.pythonhosted.org/packages/d9/9a/4019b524b03a13438637b11538c82781a5eda427394380381af8f04f467a/pynacl-1.6.2.tar.gz", hash = "sha256:018494d6d696ae03c7e656e5e74cdfd8ea1326962cc401bcf018f1ed8436811c", size = 3511692, upload-time = "2026-01-01T17:48:10.851Z" }
|
| 4157 |
+
wheels = [
|
| 4158 |
+
{ url = "https://files.pythonhosted.org/packages/be/7b/4845bbf88e94586ec47a432da4e9107e3fc3ce37eb412b1398630a37f7dd/pynacl-1.6.2-cp38-abi3-macosx_10_10_universal2.whl", hash = "sha256:c949ea47e4206af7c8f604b8278093b674f7c79ed0d4719cc836902bf4517465", size = 388458, upload-time = "2026-01-01T17:32:16.829Z" },
|
| 4159 |
+
{ url = "https://files.pythonhosted.org/packages/1e/b4/e927e0653ba63b02a4ca5b4d852a8d1d678afbf69b3dbf9c4d0785ac905c/pynacl-1.6.2-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8845c0631c0be43abdd865511c41eab235e0be69c81dc66a50911594198679b0", size = 800020, upload-time = "2026-01-01T17:32:18.34Z" },
|
| 4160 |
+
{ url = "https://files.pythonhosted.org/packages/7f/81/d60984052df5c97b1d24365bc1e30024379b42c4edcd79d2436b1b9806f2/pynacl-1.6.2-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:22de65bb9010a725b0dac248f353bb072969c94fa8d6b1f34b87d7953cf7bbe4", size = 1399174, upload-time = "2026-01-01T17:32:20.239Z" },
|
| 4161 |
+
{ url = "https://files.pythonhosted.org/packages/68/f7/322f2f9915c4ef27d140101dd0ed26b479f7e6f5f183590fd32dfc48c4d3/pynacl-1.6.2-cp38-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:46065496ab748469cdd999246d17e301b2c24ae2fdf739132e580a0e94c94a87", size = 835085, upload-time = "2026-01-01T17:32:22.24Z" },
|
| 4162 |
+
{ url = "https://files.pythonhosted.org/packages/3e/d0/f301f83ac8dbe53442c5a43f6a39016f94f754d7a9815a875b65e218a307/pynacl-1.6.2-cp38-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a66d6fb6ae7661c58995f9c6435bda2b1e68b54b598a6a10247bfcdadac996c", size = 1437614, upload-time = "2026-01-01T17:32:23.766Z" },
|
| 4163 |
+
{ url = "https://files.pythonhosted.org/packages/c4/58/fc6e649762b029315325ace1a8c6be66125e42f67416d3dbd47b69563d61/pynacl-1.6.2-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:26bfcd00dcf2cf160f122186af731ae30ab120c18e8375684ec2670dccd28130", size = 818251, upload-time = "2026-01-01T17:32:25.69Z" },
|
| 4164 |
+
{ url = "https://files.pythonhosted.org/packages/c9/a8/b917096b1accc9acd878819a49d3d84875731a41eb665f6ebc826b1af99e/pynacl-1.6.2-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c8a231e36ec2cab018c4ad4358c386e36eede0319a0c41fed24f840b1dac59f6", size = 1402859, upload-time = "2026-01-01T17:32:27.215Z" },
|
| 4165 |
+
{ url = "https://files.pythonhosted.org/packages/85/42/fe60b5f4473e12c72f977548e4028156f4d340b884c635ec6b063fe7e9a5/pynacl-1.6.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:68be3a09455743ff9505491220b64440ced8973fe930f270c8e07ccfa25b1f9e", size = 791926, upload-time = "2026-01-01T17:32:29.314Z" },
|
| 4166 |
+
{ url = "https://files.pythonhosted.org/packages/fa/f9/e40e318c604259301cc091a2a63f237d9e7b424c4851cafaea4ea7c4834e/pynacl-1.6.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:8b097553b380236d51ed11356c953bf8ce36a29a3e596e934ecabe76c985a577", size = 1363101, upload-time = "2026-01-01T17:32:31.263Z" },
|
| 4167 |
+
{ url = "https://files.pythonhosted.org/packages/48/47/e761c254f410c023a469284a9bc210933e18588ca87706ae93002c05114c/pynacl-1.6.2-cp38-abi3-win32.whl", hash = "sha256:5811c72b473b2f38f7e2a3dc4f8642e3a3e9b5e7317266e4ced1fba85cae41aa", size = 227421, upload-time = "2026-01-01T17:32:33.076Z" },
|
| 4168 |
+
{ url = "https://files.pythonhosted.org/packages/41/ad/334600e8cacc7d86587fe5f565480fde569dfb487389c8e1be56ac21d8ac/pynacl-1.6.2-cp38-abi3-win_amd64.whl", hash = "sha256:62985f233210dee6548c223301b6c25440852e13d59a8b81490203c3227c5ba0", size = 239754, upload-time = "2026-01-01T17:32:34.557Z" },
|
| 4169 |
+
{ url = "https://files.pythonhosted.org/packages/29/7d/5945b5af29534641820d3bd7b00962abbbdfee84ec7e19f0d5b3175f9a31/pynacl-1.6.2-cp38-abi3-win_arm64.whl", hash = "sha256:834a43af110f743a754448463e8fd61259cd4ab5bbedcf70f9dabad1d28a394c", size = 184801, upload-time = "2026-01-01T17:32:36.309Z" },
|
| 4170 |
+
]
|
| 4171 |
+
|
| 4172 |
[[package]]
|
| 4173 |
name = "pyparsing"
|
| 4174 |
version = "3.3.2"
|
|
|
|
| 4904 |
{ url = "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", size = 16588, upload-time = "2020-11-01T01:40:20.672Z" },
|
| 4905 |
]
|
| 4906 |
|
| 4907 |
+
[[package]]
|
| 4908 |
+
name = "tomli"
|
| 4909 |
+
version = "2.4.0"
|
| 4910 |
+
source = { registry = "https://pypi.org/simple" }
|
| 4911 |
+
sdist = { url = "https://files.pythonhosted.org/packages/82/30/31573e9457673ab10aa432461bee537ce6cef177667deca369efb79df071/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", size = 17477, upload-time = "2026-01-11T11:22:38.165Z" }
|
| 4912 |
+
wheels = [
|
| 4913 |
+
{ url = "https://files.pythonhosted.org/packages/3c/43/7389a1869f2f26dba52404e1ef13b4784b6b37dac93bac53457e3ff24ca3/tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1", size = 154894, upload-time = "2026-01-11T11:21:56.07Z" },
|
| 4914 |
+
{ url = "https://files.pythonhosted.org/packages/e9/05/2f9bf110b5294132b2edf13fe6ca6ae456204f3d749f623307cbb7a946f2/tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8", size = 149053, upload-time = "2026-01-11T11:21:57.467Z" },
|
| 4915 |
+
{ url = "https://files.pythonhosted.org/packages/e8/41/1eda3ca1abc6f6154a8db4d714a4d35c4ad90adc0bcf700657291593fbf3/tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a", size = 243481, upload-time = "2026-01-11T11:21:58.661Z" },
|
| 4916 |
+
{ url = "https://files.pythonhosted.org/packages/d2/6d/02ff5ab6c8868b41e7d4b987ce2b5f6a51d3335a70aa144edd999e055a01/tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1", size = 251720, upload-time = "2026-01-11T11:22:00.178Z" },
|
| 4917 |
+
{ url = "https://files.pythonhosted.org/packages/7b/57/0405c59a909c45d5b6f146107c6d997825aa87568b042042f7a9c0afed34/tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b", size = 247014, upload-time = "2026-01-11T11:22:01.238Z" },
|
| 4918 |
+
{ url = "https://files.pythonhosted.org/packages/2c/0e/2e37568edd944b4165735687cbaf2fe3648129e440c26d02223672ee0630/tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51", size = 251820, upload-time = "2026-01-11T11:22:02.727Z" },
|
| 4919 |
+
{ url = "https://files.pythonhosted.org/packages/5a/1c/ee3b707fdac82aeeb92d1a113f803cf6d0f37bdca0849cb489553e1f417a/tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729", size = 97712, upload-time = "2026-01-11T11:22:03.777Z" },
|
| 4920 |
+
{ url = "https://files.pythonhosted.org/packages/69/13/c07a9177d0b3bab7913299b9278845fc6eaaca14a02667c6be0b0a2270c8/tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da", size = 108296, upload-time = "2026-01-11T11:22:04.86Z" },
|
| 4921 |
+
{ url = "https://files.pythonhosted.org/packages/18/27/e267a60bbeeee343bcc279bb9e8fbed0cbe224bc7b2a3dc2975f22809a09/tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3", size = 94553, upload-time = "2026-01-11T11:22:05.854Z" },
|
| 4922 |
+
{ url = "https://files.pythonhosted.org/packages/23/d1/136eb2cb77520a31e1f64cbae9d33ec6df0d78bdf4160398e86eec8a8754/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", size = 14477, upload-time = "2026-01-11T11:22:37.446Z" },
|
| 4923 |
+
]
|
| 4924 |
+
|
| 4925 |
[[package]]
|
| 4926 |
name = "torch"
|
| 4927 |
version = "2.10.0"
|
|
|
|
| 4953 |
{ name = "typing-extensions" },
|
| 4954 |
]
|
| 4955 |
wheels = [
|
| 4956 |
+
{ url = "https://files.pythonhosted.org/packages/c9/2f/0b295dd8d199ef71e6f176f576473d645d41357b7b8aa978cc6b042575df/torch-2.10.0-1-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:6abb224c2b6e9e27b592a1c0015c33a504b00a0e0938f1499f7f514e9b7bfb5c", size = 79498197, upload-time = "2026-02-06T17:37:27.627Z" },
|
| 4957 |
{ url = "https://files.pythonhosted.org/packages/cc/af/758e242e9102e9988969b5e621d41f36b8f258bb4a099109b7a4b4b50ea4/torch-2.10.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:5fd4117d89ffd47e3dcc71e71a22efac24828ad781c7e46aaaf56bf7f2796acf", size = 145996088, upload-time = "2026-01-21T16:24:44.171Z" },
|
| 4958 |
{ url = "https://files.pythonhosted.org/packages/23/8e/3c74db5e53bff7ed9e34c8123e6a8bfef718b2450c35eefab85bb4a7e270/torch-2.10.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:787124e7db3b379d4f1ed54dd12ae7c741c16a4d29b49c0226a89bea50923ffb", size = 915711952, upload-time = "2026-01-21T16:23:53.503Z" },
|
| 4959 |
{ url = "https://files.pythonhosted.org/packages/6e/01/624c4324ca01f66ae4c7cd1b74eb16fb52596dce66dbe51eff95ef9e7a4c/torch-2.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:2c66c61f44c5f903046cc696d088e21062644cbe541c7f1c4eaae88b2ad23547", size = 113757972, upload-time = "2026-01-21T16:24:39.516Z" },
|