suzannejin commited on
Commit
06cea18
·
1 Parent(s): 52a25ec

add modal.py

Browse files
Files changed (1) hide show
  1. modal.py +89 -0
modal.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from smolagents import CodeAgent, LiteLLMModel
2
+ from smolagents.tools import ToolCollection
3
+ import gradio as gr
4
+ import modal
5
+ import subprocess
6
+ import time
7
+
8
+ app = modal.App("agent-ontology")
9
+
10
+ OLLAMA_IMAGE = (
11
+ modal.Image.debian_slim()
12
+ # pkill/pgrep come from procps
13
+ .apt_install(
14
+ "curl", "gnupg", "software-properties-common",
15
+ "procps" # ← adds pkill, pgrep, ps …
16
+ )
17
+ # install Ollama
18
+ .run_commands("curl -fsSL https://ollama.com/install.sh | sh")
19
+ # spin up daemon, pull the model, shut daemon down
20
+ .run_commands(
21
+ "bash -c 'ollama serve >/dev/null 2>&1 & "
22
+ "PID=$!; "
23
+ "sleep 10 && "
24
+ "ollama pull devstral:latest && "
25
+ "kill $PID'"
26
+ )
27
+ # python deps
28
+ .pip_install(
29
+ "fastmcp>=2.6.1",
30
+ "gradio[mcp]>=5.0.0",
31
+ "huggingface_hub[mcp]>=0.32.2",
32
+ "mcp>=1.9.2",
33
+ "smolagents[litellm,mcp]>=1.17.0",
34
+ "textblob>=0.19.0",
35
+ )
36
+ )
37
+
38
+ # Specify the dependencies in the Modal function
39
+ @app.function(image=OLLAMA_IMAGE, gpu="A10G", timeout=2400)
40
+ def run_agent():
41
+
42
+ def chat_with_agent(message, history):
43
+ """Initialize MCP client for each request to avoid connection issues"""
44
+ try:
45
+ with ToolCollection.from_mcp(
46
+ {"url": "https://notredameslab-nf-ontology.hf.space/gradio_api/mcp/sse", "transport": "sse"},
47
+ trust_remote_code=True # Acknowledge that we trust this remote MCP server
48
+ ) as tool_collection:
49
+
50
+ model = LiteLLMModel(
51
+ model_id="ollama/devstral:latest",
52
+ api_base="http://localhost:11434",
53
+ )
54
+
55
+ agent = CodeAgent(
56
+ tools=tool_collection.tools,
57
+ model=model,
58
+ additional_authorized_imports=["inspect", "json"]
59
+ )
60
+
61
+ additional_instructions = """
62
+ ADDITIONAL IMPORTANT INSTRUCTIONS:
63
+ use the tool "final_answer" in the code block to provide the answer to the user. Prints are only for debugging purposes. So, to give your results concatenate everything you want to print in a single "final_answer" call as such : final_answer(f"your answer here").
64
+ """
65
+
66
+ agent.system_prompt += additional_instructions
67
+
68
+ result = agent.run(message)
69
+ return str(result)
70
+
71
+ except Exception as e:
72
+ return f"❌ Error: {e}\nType: {type(e).__name__}"
73
+
74
+ demo = gr.ChatInterface(
75
+ fn=chat_with_agent,
76
+ type="messages",
77
+ examples=["can you extract input/output metadata from fastqc nf-core module ?"],
78
+ title="Agent with MCP Tools (Per-Request Connection)",
79
+ description="This version creates a new MCP connection for each request."
80
+ )
81
+ demo.launch(share=True)
82
+
83
+ @app.local_entrypoint()
84
+ def main():
85
+ """Run the Modal app locally."""
86
+ run_agent.remote()
87
+
88
+ if __name__ == "__main__":
89
+ main()