Update tools/tools_on_modal_labs.py
Browse files- tools/tools_on_modal_labs.py +14 -35
tools/tools_on_modal_labs.py
CHANGED
@@ -17,8 +17,7 @@ image = modal.Image.debian_slim().pip_install(
|
|
17 |
"groundx",
|
18 |
"llama-index",
|
19 |
"llama-index-llms-nebius",
|
20 |
-
"
|
21 |
-
"langchain-community")
|
22 |
|
23 |
app = modal.App(name="hackathon-mcp-tools", image=image)
|
24 |
|
@@ -45,7 +44,7 @@ def search_rag_context(queryInput: QueryInput) -> str:
|
|
45 |
print(f"RAG Search Result: {result}")
|
46 |
print("=============================\n")
|
47 |
|
48 |
-
return
|
49 |
|
50 |
def search_groundx_for_rag_context(query) -> str:
|
51 |
from groundx import GroundX
|
@@ -71,7 +70,7 @@ from llama_index.core.agent.workflow import (
|
|
71 |
ToolCallResult,
|
72 |
)
|
73 |
|
74 |
-
from
|
75 |
|
76 |
@app.function(secrets=[
|
77 |
modal.Secret.from_name("hackathon-secret", required_keys=["NEBIUS_API_KEY", "AGENT_MODEL"])
|
@@ -92,33 +91,13 @@ llm = NebiusLLM(
|
|
92 |
is_function_calling_model=True
|
93 |
)
|
94 |
|
95 |
-
|
96 |
-
duckduckgo = DuckDuckGoSearchAPIWrapper()
|
97 |
-
|
98 |
-
MAX_SEARCH_CALLS = 2 # Limit the number of searches to 2
|
99 |
-
search_call_count = 0
|
100 |
-
past_queries = set()
|
101 |
-
|
102 |
-
async def duckduckgo_search(query: str) -> str:
|
103 |
-
"""
|
104 |
-
A DuckDuckGo-based search limiting number of searches and avoiding duplicates.
|
105 |
-
"""
|
106 |
-
global search_call_count, past_queries
|
107 |
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
if search_call_count >= MAX_SEARCH_CALLS:
|
114 |
-
return "Search limit reached."
|
115 |
-
|
116 |
-
# Otherwise, perform the search
|
117 |
-
search_call_count += 1
|
118 |
-
past_queries.add(query)
|
119 |
-
|
120 |
-
result = duckduckgo.run(query)
|
121 |
-
return str(result)
|
122 |
|
123 |
# Research tools
|
124 |
async def save_research(ctx: Context, notes: str, notes_title: str) -> str:
|
@@ -166,8 +145,8 @@ async def review_report(ctx: Context, review: str) -> str:
|
|
166 |
research_agent = FunctionAgent(
|
167 |
name="ResearchAgent",
|
168 |
description=(
|
169 |
-
"A research agent that searches the web using
|
170 |
-
"It must not exceed
|
171 |
"Once sufficient information is collected, it should hand off to the WriteAgent."
|
172 |
),
|
173 |
system_prompt=(
|
@@ -178,10 +157,10 @@ research_agent = FunctionAgent(
|
|
178 |
),
|
179 |
llm=llm,
|
180 |
tools=[
|
181 |
-
|
182 |
save_research
|
183 |
],
|
184 |
-
max_iterations=
|
185 |
cooldown=5, # Cooldown to prevent rapid re-querying
|
186 |
can_handoff_to=["WriteAgent"]
|
187 |
)
|
@@ -230,7 +209,7 @@ agent_workflow = AgentWorkflow(
|
|
230 |
root_agent=research_agent.name, # Start with the ResearchAgent
|
231 |
initial_state={
|
232 |
"research_notes": {},
|
233 |
-
"report_content": "
|
234 |
"review": "Review required.",
|
235 |
},
|
236 |
)
|
|
|
17 |
"groundx",
|
18 |
"llama-index",
|
19 |
"llama-index-llms-nebius",
|
20 |
+
"tavily-python")
|
|
|
21 |
|
22 |
app = modal.App(name="hackathon-mcp-tools", image=image)
|
23 |
|
|
|
44 |
print(f"RAG Search Result: {result}")
|
45 |
print("=============================\n")
|
46 |
|
47 |
+
return result
|
48 |
|
49 |
def search_groundx_for_rag_context(query) -> str:
|
50 |
from groundx import GroundX
|
|
|
70 |
ToolCallResult,
|
71 |
)
|
72 |
|
73 |
+
from tavily import AsyncTavilyClient
|
74 |
|
75 |
@app.function(secrets=[
|
76 |
modal.Secret.from_name("hackathon-secret", required_keys=["NEBIUS_API_KEY", "AGENT_MODEL"])
|
|
|
91 |
is_function_calling_model=True
|
92 |
)
|
93 |
|
94 |
+
TAVILY_API_KEY = os.getenv("TAVILY_API_KEY")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
|
96 |
+
# Search tools using Tavily
|
97 |
+
async def search_web(query: str) -> str:
|
98 |
+
"""Useful for using the web to answer questions."""
|
99 |
+
client = AsyncTavilyClient(api_key=TAVILY_API_KEY)
|
100 |
+
return str(await client.search(query))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
|
102 |
# Research tools
|
103 |
async def save_research(ctx: Context, notes: str, notes_title: str) -> str:
|
|
|
145 |
research_agent = FunctionAgent(
|
146 |
name="ResearchAgent",
|
147 |
description=(
|
148 |
+
"A research agent that searches the web using TavilyClient Search."
|
149 |
+
"It must not exceed 3 searches total, and must avoid repeating the same query. "
|
150 |
"Once sufficient information is collected, it should hand off to the WriteAgent."
|
151 |
),
|
152 |
system_prompt=(
|
|
|
157 |
),
|
158 |
llm=llm,
|
159 |
tools=[
|
160 |
+
search_web,
|
161 |
save_research
|
162 |
],
|
163 |
+
max_iterations=3, # Limit to 2 iterations to prevent infinite loops
|
164 |
cooldown=5, # Cooldown to prevent rapid re-querying
|
165 |
can_handoff_to=["WriteAgent"]
|
166 |
)
|
|
|
209 |
root_agent=research_agent.name, # Start with the ResearchAgent
|
210 |
initial_state={
|
211 |
"research_notes": {},
|
212 |
+
"report_content": "No report has been generated after the search.",
|
213 |
"review": "Review required.",
|
214 |
},
|
215 |
)
|