Spaces:
Sleeping
Sleeping
Luis Vizcaya commited on
Commit ·
b95f82b
1
Parent(s): 27827fb
requirements.txt updated
Browse files- app.py +36 -29
- requirements.txt +160 -9
app.py
CHANGED
|
@@ -6,6 +6,15 @@ import time
|
|
| 6 |
from typing import List, Dict, Generator
|
| 7 |
from dotenv import load_dotenv
|
| 8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
# Import our agents from the src directory
|
| 10 |
from src.clarifier import Clarifier
|
| 11 |
from src.planner import Planner
|
|
@@ -18,7 +27,8 @@ load_dotenv()
|
|
| 18 |
|
| 19 |
def get_secret(key):
|
| 20 |
val = os.getenv(key)
|
| 21 |
-
|
|
|
|
| 22 |
|
| 23 |
HF_KEY = get_secret("HF_KEY")
|
| 24 |
TAVILY_API_KEY = get_secret("TAVILY_API_KEY")
|
|
@@ -28,8 +38,8 @@ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(
|
|
| 28 |
logger = logging.getLogger(__name__)
|
| 29 |
|
| 30 |
# --- MODELS ---
|
| 31 |
-
# Using
|
| 32 |
-
CLARIFIER_MODEL = '
|
| 33 |
PLANNER_MODEL = 'Qwen/Qwen2.5-7B-Instruct'
|
| 34 |
SPLITTER_MODEL = 'Qwen/Qwen2.5-7B-Instruct'
|
| 35 |
COORDINATOR_MODEL = 'Qwen/Qwen2.5-7B-Instruct'
|
|
@@ -47,17 +57,19 @@ theme = gr.themes.Soft(
|
|
| 47 |
def start_clarification(topic, hf_key, state):
|
| 48 |
if not topic:
|
| 49 |
return gr.update(), "### ⚠️ Warning\nPlease enter a topic.", state, gr.update()
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
| 52 |
|
| 53 |
state["initial_topic"] = topic
|
| 54 |
-
clarifier = Clarifier(model_name=CLARIFIER_MODEL, hf_key=
|
| 55 |
try:
|
| 56 |
suggestions = clarifier.get_suggestions(topic)
|
| 57 |
state["suggestions"] = suggestions
|
| 58 |
|
| 59 |
if not suggestions:
|
| 60 |
-
return gr.update(), "### ❌ Error\nNo suggestions received.
|
| 61 |
|
| 62 |
suggestion_md = "### 💡 Refine Your Topic\n\nChoose one of the suggested directions or enter a custom one below:\n\n"
|
| 63 |
for i, s in enumerate(suggestions):
|
|
@@ -67,7 +79,7 @@ def start_clarification(topic, hf_key, state):
|
|
| 67 |
except Exception as e:
|
| 68 |
error_msg = str(e)
|
| 69 |
if "401" in error_msg:
|
| 70 |
-
error_msg = "401 Unauthorized: Your Hugging Face Token is invalid
|
| 71 |
return gr.update(), f"### ❌ Error\n{error_msg}", state, gr.update()
|
| 72 |
|
| 73 |
def select_suggestion(index, custom_topic, state):
|
|
@@ -77,17 +89,16 @@ def select_suggestion(index, custom_topic, state):
|
|
| 77 |
sug = state["suggestions"][int(index)-1]
|
| 78 |
state["final_topic"] = f"{sug['title']}: {sug['description']}"
|
| 79 |
else:
|
| 80 |
-
# ENSURE 4 ITEMS ARE RETURNED
|
| 81 |
return gr.update(), "### ⚠️ Warning\nPlease select an option or enter a custom topic.", state, gr.update()
|
| 82 |
|
| 83 |
return gr.update(visible=True), f"### 🎯 Target Topic\n**{state['final_topic']}**", state, gr.update(visible=False)
|
| 84 |
|
| 85 |
def generate_strategy(hf_key, state):
|
| 86 |
-
|
| 87 |
-
if not
|
| 88 |
return "### ⚠️ Warning\nHF Key missing.", state, gr.update()
|
| 89 |
|
| 90 |
-
planner = Planner(model_name=PLANNER_MODEL, hf_key=
|
| 91 |
try:
|
| 92 |
plan = planner.plan(state["final_topic"])
|
| 93 |
state["research_plan"] = plan
|
|
@@ -96,11 +107,11 @@ def generate_strategy(hf_key, state):
|
|
| 96 |
return f"### ❌ Error\n{str(e)}", state, gr.update()
|
| 97 |
|
| 98 |
def decompose_tasks(hf_key, state):
|
| 99 |
-
|
| 100 |
-
if not
|
| 101 |
return "### ⚠️ Warning\nHF Key missing.", state, gr.update()
|
| 102 |
|
| 103 |
-
splitter = Splitter(model_name=SPLITTER_MODEL, hf_key=
|
| 104 |
try:
|
| 105 |
subtasks = splitter.split(state["research_plan"])
|
| 106 |
state["subtasks"] = subtasks
|
|
@@ -118,23 +129,22 @@ def run_research(hf_key, tavily_key, state):
|
|
| 118 |
from src.prompts import SUBAGENT_DIRECTION, COORDINATOR_DIRECTION
|
| 119 |
from tavily import TavilyClient
|
| 120 |
|
| 121 |
-
|
| 122 |
-
|
| 123 |
|
| 124 |
-
if not
|
| 125 |
yield "### ❌ Error\nHF Token missing.", state, gr.update(), ""
|
| 126 |
return
|
| 127 |
-
if not
|
| 128 |
yield "### ❌ Error\nTavily API Key missing.", state, gr.update(), ""
|
| 129 |
return
|
| 130 |
|
| 131 |
-
tavily_client = TavilyClient(api_key=
|
| 132 |
|
| 133 |
@tool
|
| 134 |
def web_search(query: str) -> str:
|
| 135 |
"""
|
| 136 |
Search the web for real-time information using Tavily.
|
| 137 |
-
|
| 138 |
Args:
|
| 139 |
query: The search query to look up.
|
| 140 |
"""
|
|
@@ -146,8 +156,8 @@ def run_research(hf_key, tavily_key, state):
|
|
| 146 |
except Exception as e:
|
| 147 |
return f"Search failed: {e}"
|
| 148 |
|
| 149 |
-
coordinator_model = InferenceClientModel(model_id=COORDINATOR_MODEL, api_key=
|
| 150 |
-
subagent_model = InferenceClientModel(model_id=SUBAGENT_MODEL, api_key=
|
| 151 |
|
| 152 |
current_findings = []
|
| 153 |
log_content = "### 🔍 Agentic Research Progress\n\n"
|
|
@@ -162,7 +172,7 @@ def run_research(hf_key, tavily_key, state):
|
|
| 162 |
t_title = task['title']
|
| 163 |
t_desc = task['description']
|
| 164 |
|
| 165 |
-
log_content += f"**Agent working on:** {t_title}...\n"
|
| 166 |
yield log_content, state, gr.update(), ""
|
| 167 |
|
| 168 |
subagent = CodeAgent(
|
|
@@ -206,14 +216,11 @@ def run_research(hf_key, tavily_key, state):
|
|
| 206 |
final_report = response.content
|
| 207 |
if "<think>" in final_report and "</think>" in final_report:
|
| 208 |
final_report = final_report.split("</think>")[-1].strip()
|
| 209 |
-
elif "<think>" in final_report:
|
| 210 |
-
final_report = final_report.split("<think>")[-1].strip()
|
| 211 |
-
if "\n\n" in final_report: final_report = final_report.split("\n\n", 1)[-1]
|
| 212 |
|
| 213 |
log_content += "### 🖋️ Review: Polishing and Finalizing...\n"
|
| 214 |
yield log_content, state, gr.update(), ""
|
| 215 |
|
| 216 |
-
reviewer = Reviewer(model_name=REVIEWER_MODEL, hf_key=
|
| 217 |
polished_report = reviewer.review(final_report)
|
| 218 |
state["final_report"] = polished_report
|
| 219 |
|
|
@@ -265,7 +272,7 @@ with gr.Blocks(theme=theme, title="Deep Research Agent") as demo:
|
|
| 265 |
# STEP 1: Introduction
|
| 266 |
with gr.Column(visible=True) as step1_col:
|
| 267 |
gr.Markdown("## 1️⃣ What are you researching?")
|
| 268 |
-
topic_input = gr.Textbox(label="Enter a broad topic or research question:", placeholder="e.g.,
|
| 269 |
start_btn = gr.Button("Clarify Topic ➡️", variant="primary")
|
| 270 |
|
| 271 |
# STEP 2: Refinement
|
|
|
|
| 6 |
from typing import List, Dict, Generator
|
| 7 |
from dotenv import load_dotenv
|
| 8 |
|
| 9 |
+
# Try to use truststore for corporate network compatibility (local only)
|
| 10 |
+
if not os.getenv("SPACE_ID"):
|
| 11 |
+
try:
|
| 12 |
+
import truststore
|
| 13 |
+
truststore.inject_into_ssl()
|
| 14 |
+
print("💡 Truststore injected (Corporate SSL mode)")
|
| 15 |
+
except ImportError:
|
| 16 |
+
pass
|
| 17 |
+
|
| 18 |
# Import our agents from the src directory
|
| 19 |
from src.clarifier import Clarifier
|
| 20 |
from src.planner import Planner
|
|
|
|
| 27 |
|
| 28 |
def get_secret(key):
|
| 29 |
val = os.getenv(key)
|
| 30 |
+
# Strip spaces in case the .env has "KEY = VALUE"
|
| 31 |
+
return val.strip() if val is not None else ""
|
| 32 |
|
| 33 |
HF_KEY = get_secret("HF_KEY")
|
| 34 |
TAVILY_API_KEY = get_secret("TAVILY_API_KEY")
|
|
|
|
| 38 |
logger = logging.getLogger(__name__)
|
| 39 |
|
| 40 |
# --- MODELS ---
|
| 41 |
+
# Using highly stable serverless models
|
| 42 |
+
CLARIFIER_MODEL = 'HuggingFaceH4/zephyr-7b-beta'
|
| 43 |
PLANNER_MODEL = 'Qwen/Qwen2.5-7B-Instruct'
|
| 44 |
SPLITTER_MODEL = 'Qwen/Qwen2.5-7B-Instruct'
|
| 45 |
COORDINATOR_MODEL = 'Qwen/Qwen2.5-7B-Instruct'
|
|
|
|
| 57 |
def start_clarification(topic, hf_key, state):
|
| 58 |
if not topic:
|
| 59 |
return gr.update(), "### ⚠️ Warning\nPlease enter a topic.", state, gr.update()
|
| 60 |
+
|
| 61 |
+
clean_key = hf_key.strip() if hf_key else ""
|
| 62 |
+
if not clean_key:
|
| 63 |
+
return gr.update(), "### ⚠️ Warning\nPlease provide a valid Hugging Face Token.", state, gr.update()
|
| 64 |
|
| 65 |
state["initial_topic"] = topic
|
| 66 |
+
clarifier = Clarifier(model_name=CLARIFIER_MODEL, hf_key=clean_key)
|
| 67 |
try:
|
| 68 |
suggestions = clarifier.get_suggestions(topic)
|
| 69 |
state["suggestions"] = suggestions
|
| 70 |
|
| 71 |
if not suggestions:
|
| 72 |
+
return gr.update(), "### ❌ Error\nNo suggestions received. This usually means the HF Token is invalid or the model is overloaded.", state, gr.update()
|
| 73 |
|
| 74 |
suggestion_md = "### 💡 Refine Your Topic\n\nChoose one of the suggested directions or enter a custom one below:\n\n"
|
| 75 |
for i, s in enumerate(suggestions):
|
|
|
|
| 79 |
except Exception as e:
|
| 80 |
error_msg = str(e)
|
| 81 |
if "401" in error_msg:
|
| 82 |
+
error_msg = "401 Unauthorized: Your Hugging Face Token is invalid for the Inference API. Please generate a new 'Write' token at hf.co/settings/tokens"
|
| 83 |
return gr.update(), f"### ❌ Error\n{error_msg}", state, gr.update()
|
| 84 |
|
| 85 |
def select_suggestion(index, custom_topic, state):
|
|
|
|
| 89 |
sug = state["suggestions"][int(index)-1]
|
| 90 |
state["final_topic"] = f"{sug['title']}: {sug['description']}"
|
| 91 |
else:
|
|
|
|
| 92 |
return gr.update(), "### ⚠️ Warning\nPlease select an option or enter a custom topic.", state, gr.update()
|
| 93 |
|
| 94 |
return gr.update(visible=True), f"### 🎯 Target Topic\n**{state['final_topic']}**", state, gr.update(visible=False)
|
| 95 |
|
| 96 |
def generate_strategy(hf_key, state):
|
| 97 |
+
clean_key = hf_key.strip() if hf_key else ""
|
| 98 |
+
if not clean_key:
|
| 99 |
return "### ⚠️ Warning\nHF Key missing.", state, gr.update()
|
| 100 |
|
| 101 |
+
planner = Planner(model_name=PLANNER_MODEL, hf_key=clean_key)
|
| 102 |
try:
|
| 103 |
plan = planner.plan(state["final_topic"])
|
| 104 |
state["research_plan"] = plan
|
|
|
|
| 107 |
return f"### ❌ Error\n{str(e)}", state, gr.update()
|
| 108 |
|
| 109 |
def decompose_tasks(hf_key, state):
|
| 110 |
+
clean_key = hf_key.strip() if hf_key else ""
|
| 111 |
+
if not clean_key:
|
| 112 |
return "### ⚠️ Warning\nHF Key missing.", state, gr.update()
|
| 113 |
|
| 114 |
+
splitter = Splitter(model_name=SPLITTER_MODEL, hf_key=clean_key)
|
| 115 |
try:
|
| 116 |
subtasks = splitter.split(state["research_plan"])
|
| 117 |
state["subtasks"] = subtasks
|
|
|
|
| 129 |
from src.prompts import SUBAGENT_DIRECTION, COORDINATOR_DIRECTION
|
| 130 |
from tavily import TavilyClient
|
| 131 |
|
| 132 |
+
clean_hf = hf_key.strip() if hf_key else ""
|
| 133 |
+
clean_tavily = tavily_key.strip() if tavily_key else ""
|
| 134 |
|
| 135 |
+
if not clean_hf:
|
| 136 |
yield "### ❌ Error\nHF Token missing.", state, gr.update(), ""
|
| 137 |
return
|
| 138 |
+
if not clean_tavily:
|
| 139 |
yield "### ❌ Error\nTavily API Key missing.", state, gr.update(), ""
|
| 140 |
return
|
| 141 |
|
| 142 |
+
tavily_client = TavilyClient(api_key=clean_tavily)
|
| 143 |
|
| 144 |
@tool
|
| 145 |
def web_search(query: str) -> str:
|
| 146 |
"""
|
| 147 |
Search the web for real-time information using Tavily.
|
|
|
|
| 148 |
Args:
|
| 149 |
query: The search query to look up.
|
| 150 |
"""
|
|
|
|
| 156 |
except Exception as e:
|
| 157 |
return f"Search failed: {e}"
|
| 158 |
|
| 159 |
+
coordinator_model = InferenceClientModel(model_id=COORDINATOR_MODEL, api_key=clean_hf)
|
| 160 |
+
subagent_model = InferenceClientModel(model_id=SUBAGENT_MODEL, api_key=clean_hf)
|
| 161 |
|
| 162 |
current_findings = []
|
| 163 |
log_content = "### 🔍 Agentic Research Progress\n\n"
|
|
|
|
| 172 |
t_title = task['title']
|
| 173 |
t_desc = task['description']
|
| 174 |
|
| 175 |
+
log_content += f"**Agent {i+1} working on:** {t_title}...\n"
|
| 176 |
yield log_content, state, gr.update(), ""
|
| 177 |
|
| 178 |
subagent = CodeAgent(
|
|
|
|
| 216 |
final_report = response.content
|
| 217 |
if "<think>" in final_report and "</think>" in final_report:
|
| 218 |
final_report = final_report.split("</think>")[-1].strip()
|
|
|
|
|
|
|
|
|
|
| 219 |
|
| 220 |
log_content += "### 🖋️ Review: Polishing and Finalizing...\n"
|
| 221 |
yield log_content, state, gr.update(), ""
|
| 222 |
|
| 223 |
+
reviewer = Reviewer(model_name=REVIEWER_MODEL, hf_key=clean_hf)
|
| 224 |
polished_report = reviewer.review(final_report)
|
| 225 |
state["final_report"] = polished_report
|
| 226 |
|
|
|
|
| 272 |
# STEP 1: Introduction
|
| 273 |
with gr.Column(visible=True) as step1_col:
|
| 274 |
gr.Markdown("## 1️⃣ What are you researching?")
|
| 275 |
+
topic_input = gr.Textbox(label="Enter a broad topic or research question:", placeholder="e.g., Target market for sustainable polymers in Europe")
|
| 276 |
start_btn = gr.Button("Clarify Topic ➡️", variant="primary")
|
| 277 |
|
| 278 |
# STEP 2: Refinement
|
requirements.txt
CHANGED
|
@@ -1,9 +1,160 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
aiofiles==24.1.0
|
| 2 |
+
altair==5.5.0
|
| 3 |
+
altgraph==0.17.5
|
| 4 |
+
annotated-doc==0.0.4
|
| 5 |
+
annotated-types==0.7.0
|
| 6 |
+
anyio==4.9.0
|
| 7 |
+
asttokens==3.0.0
|
| 8 |
+
attrs==25.3.0
|
| 9 |
+
audioop-lts==0.2.2
|
| 10 |
+
azure-core==1.35.0
|
| 11 |
+
azure-identity==1.23.0
|
| 12 |
+
blinker==1.9.0
|
| 13 |
+
brotli==1.2.0
|
| 14 |
+
cachetools==6.1.0
|
| 15 |
+
certifi==2025.8.3
|
| 16 |
+
cffi==1.17.1
|
| 17 |
+
charset-normalizer==3.4.2
|
| 18 |
+
click==8.2.1
|
| 19 |
+
cloudpickle==3.1.1
|
| 20 |
+
colorama==0.4.6
|
| 21 |
+
comm==0.2.3
|
| 22 |
+
contourpy==1.3.2
|
| 23 |
+
cryptography==45.0.5
|
| 24 |
+
cycler==0.12.1
|
| 25 |
+
debugpy==1.8.16
|
| 26 |
+
decorator==5.2.1
|
| 27 |
+
distlib==0.4.0
|
| 28 |
+
distro==1.9.0
|
| 29 |
+
exceptiongroup==1.3.0
|
| 30 |
+
executing==2.2.0
|
| 31 |
+
Farama-Notifications==0.0.4
|
| 32 |
+
fastapi==0.128.0
|
| 33 |
+
fastjsonschema==2.21.2
|
| 34 |
+
ffmpy==1.0.0
|
| 35 |
+
filelock==3.19.1
|
| 36 |
+
fonttools==4.59.0
|
| 37 |
+
fsspec==2025.12.0
|
| 38 |
+
gitdb==4.0.12
|
| 39 |
+
GitPython==3.1.44
|
| 40 |
+
gradio==6.2.0
|
| 41 |
+
gradio_client==2.0.2
|
| 42 |
+
greenlet==3.3.0
|
| 43 |
+
groovy==0.1.2
|
| 44 |
+
gymnasium==1.1.1
|
| 45 |
+
h11==0.16.0
|
| 46 |
+
hf-xet==1.2.0
|
| 47 |
+
holidays==0.78
|
| 48 |
+
httpcore==1.0.9
|
| 49 |
+
httpx==0.28.1
|
| 50 |
+
httpx-sse==0.4.1
|
| 51 |
+
huggingface_hub==1.2.3
|
| 52 |
+
idna==3.10
|
| 53 |
+
ipykernel==6.30.1
|
| 54 |
+
ipython==8.37.0
|
| 55 |
+
ipython_pygments_lexers==1.1.1
|
| 56 |
+
jedi==0.19.2
|
| 57 |
+
Jinja2==3.1.6
|
| 58 |
+
jiter==0.10.0
|
| 59 |
+
joblib==1.5.1
|
| 60 |
+
jsonschema==4.25.1
|
| 61 |
+
jsonschema-specifications==2025.9.1
|
| 62 |
+
jupyter_client==8.6.3
|
| 63 |
+
jupyter_core==5.8.1
|
| 64 |
+
kiwisolver==1.4.8
|
| 65 |
+
llvmlite==0.44.0
|
| 66 |
+
logging==0.4.9.6
|
| 67 |
+
markdown-it-py==3.0.0
|
| 68 |
+
MarkupSafe==3.0.2
|
| 69 |
+
matplotlib==3.10.5
|
| 70 |
+
matplotlib-inline==0.1.7
|
| 71 |
+
mcp==1.11.0
|
| 72 |
+
mdurl==0.1.2
|
| 73 |
+
msal==1.32.3
|
| 74 |
+
msal-extensions==1.3.1
|
| 75 |
+
narwhals==2.4.0
|
| 76 |
+
nbformat==5.10.4
|
| 77 |
+
nest-asyncio==1.6.0
|
| 78 |
+
networkx==3.4.2
|
| 79 |
+
numba==0.61.2
|
| 80 |
+
numpy==2.2.6
|
| 81 |
+
openai==1.90.0
|
| 82 |
+
orjson==3.11.5
|
| 83 |
+
packaging==25.0
|
| 84 |
+
pandas==2.3.1
|
| 85 |
+
parso==0.8.5
|
| 86 |
+
patsy==1.0.1
|
| 87 |
+
pefile==2024.8.26
|
| 88 |
+
pillow==11.3.0
|
| 89 |
+
platformdirs==4.3.8
|
| 90 |
+
plotly==6.3.0
|
| 91 |
+
prompt_toolkit==3.0.51
|
| 92 |
+
protobuf==6.31.1
|
| 93 |
+
psutil==7.0.0
|
| 94 |
+
PuLP==3.2.2
|
| 95 |
+
pure_eval==0.2.3
|
| 96 |
+
pyarrow==20.0.0
|
| 97 |
+
pycparser==2.22
|
| 98 |
+
pydantic==2.11.7
|
| 99 |
+
pydantic-settings==2.10.1
|
| 100 |
+
pydantic_core==2.33.2
|
| 101 |
+
pydeck==0.9.1
|
| 102 |
+
pydub==0.25.1
|
| 103 |
+
pyenv-win==3.1.1
|
| 104 |
+
Pygments==2.19.2
|
| 105 |
+
pyinstaller==6.17.0
|
| 106 |
+
pyinstaller-hooks-contrib==2025.11
|
| 107 |
+
PyJWT==2.10.1
|
| 108 |
+
pyodbc==5.2.0
|
| 109 |
+
pyparsing==3.2.3
|
| 110 |
+
python-dateutil==2.9.0.post0
|
| 111 |
+
python-dotenv==1.1.1
|
| 112 |
+
python-multipart==0.0.20
|
| 113 |
+
pytz==2025.2
|
| 114 |
+
pywin32==311
|
| 115 |
+
pywin32-ctypes==0.2.3
|
| 116 |
+
PyYAML==6.0.3
|
| 117 |
+
pyzmq==27.0.2
|
| 118 |
+
referencing==0.36.2
|
| 119 |
+
requests==2.32.4
|
| 120 |
+
rich==14.1.0
|
| 121 |
+
rpds-py==0.27.1
|
| 122 |
+
safehttpx==0.1.7
|
| 123 |
+
scikit-learn==1.7.1
|
| 124 |
+
scipy==1.15.3
|
| 125 |
+
semantic-version==2.10.0
|
| 126 |
+
setuptools==80.9.0
|
| 127 |
+
shap==0.48.0
|
| 128 |
+
shellingham==1.5.4
|
| 129 |
+
six==1.17.0
|
| 130 |
+
slicer==0.0.8
|
| 131 |
+
smmap==5.0.2
|
| 132 |
+
sniffio==1.3.1
|
| 133 |
+
SQLAlchemy==2.0.45
|
| 134 |
+
sse-starlette==2.4.1
|
| 135 |
+
stack-data==0.6.3
|
| 136 |
+
starlette==0.47.1
|
| 137 |
+
statsmodels==0.14.5
|
| 138 |
+
streamlit==1.46.0
|
| 139 |
+
tabulate==0.9.0
|
| 140 |
+
tenacity==9.1.2
|
| 141 |
+
termcolor==3.1.0
|
| 142 |
+
threadpoolctl==3.6.0
|
| 143 |
+
toml==0.10.2
|
| 144 |
+
tomlkit==0.13.3
|
| 145 |
+
tornado==6.5.2
|
| 146 |
+
tqdm==4.67.1
|
| 147 |
+
traitlets==5.14.3
|
| 148 |
+
truststore==0.10.4
|
| 149 |
+
typer==0.21.0
|
| 150 |
+
typer-slim==0.21.0
|
| 151 |
+
typing-inspection==0.4.1
|
| 152 |
+
typing_extensions==4.14.1
|
| 153 |
+
tzdata==2025.2
|
| 154 |
+
urllib3==2.5.0
|
| 155 |
+
uv==0.7.20
|
| 156 |
+
uvicorn==0.35.0
|
| 157 |
+
virtualenv==20.34.0
|
| 158 |
+
watchdog==6.0.0
|
| 159 |
+
wcwidth==0.2.13
|
| 160 |
+
xgboost==3.0.4
|