update agent
Browse files- __pycache__/agent.cpython-312.pyc +0 -0
- agent.py +58 -70
__pycache__/agent.cpython-312.pyc
CHANGED
|
Binary files a/__pycache__/agent.cpython-312.pyc and b/__pycache__/agent.cpython-312.pyc differ
|
|
|
agent.py
CHANGED
|
@@ -47,81 +47,79 @@ load_dotenv()
|
|
| 47 |
# huggingfacehub_api_token=os.getenv("HUGGINGFACEHUB_API_TOKEN"),
|
| 48 |
# )
|
| 49 |
|
| 50 |
-
#
|
| 51 |
-
model = ChatGroq(
|
| 52 |
-
model="meta-llama/llama-4-scout-17b-16e-instruct",
|
| 53 |
-
temperature=0,
|
| 54 |
-
max_tokens=None,
|
| 55 |
-
timeout=None,
|
| 56 |
-
max_retries=2,
|
| 57 |
-
)
|
| 58 |
-
|
| 59 |
-
# OpenRouter Model (Primary Fallback)
|
| 60 |
-
openrouter_model = ChatOpenAI(
|
| 61 |
-
model="meta-llama/llama-3.3-70b-instruct",
|
| 62 |
-
openai_api_key=os.getenv("OPENROUTER_API_KEY"),
|
| 63 |
-
openai_api_base="https://openrouter.ai/api/v1",
|
| 64 |
-
temperature=0,
|
| 65 |
-
)
|
| 66 |
-
|
| 67 |
-
# Google AI Studio Fallback Model (Gemini)
|
| 68 |
-
gemini_model = ChatGoogleGenerativeAI(
|
| 69 |
-
model="gemini-2.5-flash",
|
| 70 |
-
# google_api_key is automatically picked up from GOOGLE_API_KEY environment variable
|
| 71 |
-
temperature=0,
|
| 72 |
-
)
|
| 73 |
-
|
| 74 |
-
# NVIDIA Model (Secondary Fallback)
|
| 75 |
-
nvidia_model = ChatOpenAI(
|
| 76 |
-
model="meta/llama-3.1-405b-instruct",
|
| 77 |
-
openai_api_key=os.getenv("NVIDIA_API_KEY"),
|
| 78 |
-
openai_api_base="https://integrate.api.nvidia.com/v1",
|
| 79 |
-
temperature=0,
|
| 80 |
-
)
|
| 81 |
-
|
| 82 |
-
# Vercel Model (Tertiary Fallback)
|
| 83 |
-
# Note: Adjust model and base_url if using a specific Vercel AI Gateway setup
|
| 84 |
-
vercel_model = ChatOpenAI(
|
| 85 |
-
model="meta-llama/llama-3.3-70b-instruct",
|
| 86 |
-
openai_api_key=os.getenv("VERCEL_API_KEY"),
|
| 87 |
-
openai_api_base="https://gateway.ai.vercel.com/v1",
|
| 88 |
-
temperature=0,
|
| 89 |
-
)
|
| 90 |
|
| 91 |
def smart_invoke(msgs, use_tools=False, start_tier=0):
|
| 92 |
"""
|
| 93 |
-
Tiered fallback: OpenRouter -> Gemini -> Groq.
|
| 94 |
Retries next tier if a 429 (rate limit), 402 (credits), or 404 (model found) error occurs.
|
| 95 |
"""
|
| 96 |
-
primary = model_with_tools if use_tools else model
|
| 97 |
-
secondary = openrouter_with_tools if use_tools else openrouter_model
|
| 98 |
-
tertiary = gemini_with_tools if use_tools else gemini_model
|
| 99 |
-
quaternary = nvidia_with_tools if use_tools else nvidia_model
|
| 100 |
-
quinary = vercel_with_tools if use_tools else vercel_model
|
| 101 |
|
| 102 |
# Adaptive Gemini names to try if 1.5 flash is 404
|
| 103 |
gemini_alternatives = ["gemini-2.5-flash-lite", "gemma-3-1b", "gemini-3-flash", "gemini-3.1-flash-lite"]
|
| 104 |
|
| 105 |
-
|
| 106 |
-
{"name": "OpenRouter", "
|
| 107 |
-
{"name": "Gemini", "
|
| 108 |
-
{"name": "Groq", "
|
| 109 |
-
{"name": "NVIDIA", "
|
| 110 |
-
{"name": "Vercel", "
|
| 111 |
]
|
| 112 |
|
| 113 |
last_exception = None
|
| 114 |
-
for i in range(start_tier, len(
|
| 115 |
-
tier =
|
| 116 |
-
|
|
|
|
| 117 |
continue
|
| 118 |
|
| 119 |
-
|
| 120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
if "alternatives" in tier:
|
| 122 |
for alt_name in tier["alternatives"]:
|
| 123 |
-
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
models_to_try.append(alt_model)
|
| 126 |
|
| 127 |
for current_model in models_to_try:
|
|
@@ -150,11 +148,6 @@ def smart_invoke(msgs, use_tools=False, start_tier=0):
|
|
| 150 |
print("CRITICAL: All fallback tiers failed.")
|
| 151 |
raise last_exception
|
| 152 |
return None, 0
|
| 153 |
-
|
| 154 |
-
if last_exception:
|
| 155 |
-
print("CRITICAL: All fallback tiers failed.")
|
| 156 |
-
raise last_exception
|
| 157 |
-
return None, 0
|
| 158 |
|
| 159 |
@tool
|
| 160 |
def web_search(keywords: str) -> str:
|
|
@@ -400,7 +393,6 @@ Your answer should only start with "FINAL ANSWER: ", then follows with the answe
|
|
| 400 |
class AgentState(TypedDict):
|
| 401 |
messages: List[Union[HumanMessage, AIMessage, SystemMessage]]
|
| 402 |
|
| 403 |
-
|
| 404 |
def read_message(state: AgentState) -> AgentState:
|
| 405 |
messages = state["messages"]
|
| 406 |
print(f"Processing question: {messages[-1].content if messages else ''}")
|
|
@@ -432,11 +424,7 @@ def restart_required(state: AgentState) -> AgentState:
|
|
| 432 |
# Augment the LLM with tools
|
| 433 |
tools = [web_search, wiki_search, analyze_image, analyze_audio, analyze_video, read_url, run_python_script, read_document]
|
| 434 |
tools_by_name = {tool.name: tool for tool in tools}
|
| 435 |
-
model_with_tools
|
| 436 |
-
openrouter_with_tools = openrouter_model.bind_tools(tools)
|
| 437 |
-
gemini_with_tools = gemini_model.bind_tools(tools)
|
| 438 |
-
nvidia_with_tools = nvidia_model.bind_tools(tools)
|
| 439 |
-
vercel_with_tools = vercel_model.bind_tools(tools)
|
| 440 |
|
| 441 |
def answer_message(state: AgentState) -> AgentState:
|
| 442 |
messages = state["messages"]
|
|
|
|
| 47 |
# huggingfacehub_api_token=os.getenv("HUGGINGFACEHUB_API_TOKEN"),
|
| 48 |
# )
|
| 49 |
|
| 50 |
+
# Model initializations moved to smart_invoke for lazy loading to prevent import errors if keys are missing.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
|
| 52 |
def smart_invoke(msgs, use_tools=False, start_tier=0):
|
| 53 |
"""
|
| 54 |
+
Tiered fallback: OpenRouter -> Gemini -> Groq -> NVIDIA -> Vercel.
|
| 55 |
Retries next tier if a 429 (rate limit), 402 (credits), or 404 (model found) error occurs.
|
| 56 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
|
| 58 |
# Adaptive Gemini names to try if 1.5 flash is 404
|
| 59 |
gemini_alternatives = ["gemini-2.5-flash-lite", "gemma-3-1b", "gemini-3-flash", "gemini-3.1-flash-lite"]
|
| 60 |
|
| 61 |
+
tiers_config = [
|
| 62 |
+
{"name": "OpenRouter", "key": "OPENROUTER_API_KEY", "provider": "openai", "model_name": "meta-llama/llama-3.3-70b-instruct", "base_url": "https://openrouter.ai/api/v1"},
|
| 63 |
+
{"name": "Gemini", "key": "GOOGLE_API_KEY", "provider": "google", "model_name": "gemini-2.5-flash", "alternatives": gemini_alternatives},
|
| 64 |
+
{"name": "Groq", "key": "GROQ_API_KEY", "provider": "groq", "model_name": "meta-llama/llama-4-scout-17b-16e-instruct"},
|
| 65 |
+
{"name": "NVIDIA", "key": "NVIDIA_API_KEY", "provider": "openai", "model_name": "meta/llama-3.1-405b-instruct", "base_url": "https://integrate.api.nvidia.com/v1"},
|
| 66 |
+
{"name": "Vercel", "key": "VERCEL_API_KEY", "provider": "openai", "model_name": "meta-llama/llama-3.3-70b-instruct", "base_url": "https://gateway.ai.vercel.com/v1"},
|
| 67 |
]
|
| 68 |
|
| 69 |
last_exception = None
|
| 70 |
+
for i in range(start_tier, len(tiers_config)):
|
| 71 |
+
tier = tiers_config[i]
|
| 72 |
+
api_key = os.getenv(tier["key"])
|
| 73 |
+
if not api_key:
|
| 74 |
continue
|
| 75 |
|
| 76 |
+
def create_model_instance(m_name, provider, b_url=None):
|
| 77 |
+
if provider == "openai":
|
| 78 |
+
return ChatOpenAI(model=m_name, openai_api_key=api_key, openai_api_base=b_url, temperature=0)
|
| 79 |
+
elif provider == "google":
|
| 80 |
+
return ChatGoogleGenerativeAI(model=m_name, temperature=0)
|
| 81 |
+
elif provider == "groq":
|
| 82 |
+
return ChatGroq(model=m_name, temperature=0, max_retries=2)
|
| 83 |
+
return None
|
| 84 |
+
|
| 85 |
+
primary_model = create_model_instance(tier["model_name"], tier["provider"], tier.get("base_url"))
|
| 86 |
+
if use_tools:
|
| 87 |
+
primary_model = primary_model.bind_tools(tools)
|
| 88 |
+
|
| 89 |
+
models_to_try = [primary_model]
|
| 90 |
if "alternatives" in tier:
|
| 91 |
for alt_name in tier["alternatives"]:
|
| 92 |
+
alt_model = create_model_instance(alt_name, tier["provider"], tier.get("base_url"))
|
| 93 |
+
if use_tools:
|
| 94 |
+
alt_model = alt_model.bind_tools(tools)
|
| 95 |
+
models_to_try.append(alt_model)
|
| 96 |
+
|
| 97 |
+
last_exception = None
|
| 98 |
+
for i in range(start_tier, len(tiers_config)):
|
| 99 |
+
tier = tiers_config[i]
|
| 100 |
+
api_key = os.getenv(tier["key"])
|
| 101 |
+
if not api_key:
|
| 102 |
+
continue
|
| 103 |
+
|
| 104 |
+
def create_model_instance(m_name, provider, b_url=None):
|
| 105 |
+
if provider == "openai":
|
| 106 |
+
return ChatOpenAI(model=m_name, openai_api_key=api_key, openai_api_base=b_url, temperature=0)
|
| 107 |
+
elif provider == "google":
|
| 108 |
+
return ChatGoogleGenerativeAI(model=m_name, temperature=0)
|
| 109 |
+
elif provider == "groq":
|
| 110 |
+
return ChatGroq(model=m_name, temperature=0, max_retries=2)
|
| 111 |
+
return None
|
| 112 |
+
|
| 113 |
+
primary_model = create_model_instance(tier["model_name"], tier["provider"], tier.get("base_url"))
|
| 114 |
+
if use_tools:
|
| 115 |
+
primary_model = primary_model.bind_tools(tools)
|
| 116 |
+
|
| 117 |
+
models_to_try = [primary_model]
|
| 118 |
+
if "alternatives" in tier:
|
| 119 |
+
for alt_name in tier["alternatives"]:
|
| 120 |
+
alt_model = create_model_instance(alt_name, tier["provider"], tier.get("base_url"))
|
| 121 |
+
if use_tools:
|
| 122 |
+
alt_model = alt_model.bind_tools(tools)
|
| 123 |
models_to_try.append(alt_model)
|
| 124 |
|
| 125 |
for current_model in models_to_try:
|
|
|
|
| 148 |
print("CRITICAL: All fallback tiers failed.")
|
| 149 |
raise last_exception
|
| 150 |
return None, 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
|
| 152 |
@tool
|
| 153 |
def web_search(keywords: str) -> str:
|
|
|
|
| 393 |
class AgentState(TypedDict):
|
| 394 |
messages: List[Union[HumanMessage, AIMessage, SystemMessage]]
|
| 395 |
|
|
|
|
| 396 |
def read_message(state: AgentState) -> AgentState:
|
| 397 |
messages = state["messages"]
|
| 398 |
print(f"Processing question: {messages[-1].content if messages else ''}")
|
|
|
|
| 424 |
# Augment the LLM with tools
|
| 425 |
tools = [web_search, wiki_search, analyze_image, analyze_audio, analyze_video, read_url, run_python_script, read_document]
|
| 426 |
tools_by_name = {tool.name: tool for tool in tools}
|
| 427 |
+
# model_with_tools etc. removed, replaced by lazy initialization in smart_invoke
|
|
|
|
|
|
|
|
|
|
|
|
|
| 428 |
|
| 429 |
def answer_message(state: AgentState) -> AgentState:
|
| 430 |
messages = state["messages"]
|