Commit
·
ff0eb39
1
Parent(s):
1a5faa6
feat: 50%
Browse files- .gitignore +6 -1
- agent.py +161 -0
- app.py +29 -27
- requirements.txt +3 -1
- utils.py +10 -0
.gitignore
CHANGED
@@ -1,2 +1,7 @@
|
|
1 |
venv/
|
2 |
-
.env
|
|
|
|
|
|
|
|
|
|
|
|
1 |
venv/
|
2 |
+
.env
|
3 |
+
test.ipynb
|
4 |
+
__pycache__/
|
5 |
+
*.png
|
6 |
+
*.mp3
|
7 |
+
*.xlsx
|
agent.py
ADDED
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from huggingface_hub import InferenceClient
|
2 |
+
|
3 |
+
# from langchain_together import Together
|
4 |
+
from smolagents import (
|
5 |
+
CodeAgent,
|
6 |
+
DuckDuckGoSearchTool,
|
7 |
+
WikipediaSearchTool,
|
8 |
+
VisitWebpageTool,
|
9 |
+
HfApiModel,
|
10 |
+
LiteLLMModel,
|
11 |
+
ApiModel,
|
12 |
+
PythonInterpreterTool,
|
13 |
+
)
|
14 |
+
from smolagents.tools import Tool
|
15 |
+
import yaml
|
16 |
+
import os
|
17 |
+
import requests
|
18 |
+
from urllib.parse import urlencode
|
19 |
+
from gradio_client import Client, handle_file
|
20 |
+
|
21 |
+
|
22 |
+
class ReadFileTool(Tool):
|
23 |
+
name = "read_file"
|
24 |
+
description = "Reads the content of a file."
|
25 |
+
inputs = {
|
26 |
+
"file_path": {"type": "string", "description": "The path to the file to read"}
|
27 |
+
}
|
28 |
+
output_type = "string"
|
29 |
+
|
30 |
+
def forward(self, file_path: str) -> str:
|
31 |
+
with open(file_path, "r", encoding="utf-8") as file:
|
32 |
+
return file.read()
|
33 |
+
|
34 |
+
def __init__(self, *args, **kwargs):
|
35 |
+
self.is_initialized = False
|
36 |
+
|
37 |
+
|
38 |
+
class TranscribeTool(Tool):
|
39 |
+
name = "transcribe"
|
40 |
+
description = "Transcribes audio files to text."
|
41 |
+
inputs = {
|
42 |
+
"audio_file_path": {
|
43 |
+
"type": "string",
|
44 |
+
"description": "The path to the audio file to transcribe",
|
45 |
+
}
|
46 |
+
}
|
47 |
+
output_type = "string"
|
48 |
+
|
49 |
+
def forward(self, audio_file_path: str) -> str:
|
50 |
+
# Placeholder for transcription logic
|
51 |
+
client = Client("viktor-hu/parakeet-asr-mcp-server")
|
52 |
+
result = client.predict(
|
53 |
+
audio_file=handle_file(audio_file_path), api_name="/transcribe_to_text"
|
54 |
+
)
|
55 |
+
return result
|
56 |
+
|
57 |
+
|
58 |
+
class GetChessBestMoveTool(Tool):
|
59 |
+
name = "get_chess_best_move"
|
60 |
+
description = "Gets the best move for a given chess position."
|
61 |
+
inputs = {
|
62 |
+
"fen_position": {
|
63 |
+
"type": "string",
|
64 |
+
"description": "The FEN string representing the chess position",
|
65 |
+
}
|
66 |
+
}
|
67 |
+
output_type = "string"
|
68 |
+
|
69 |
+
def forward(self, fen_position: str) -> str:
|
70 |
+
url = "https://stockfish.online/api/s/v2.php"
|
71 |
+
params = {"fen": fen_position, "depth": 5}
|
72 |
+
result = requests.get(url, params=urlencode(params), timeout=60)
|
73 |
+
return result.json()
|
74 |
+
|
75 |
+
|
76 |
+
class ImageAnalysisTool(Tool):
|
77 |
+
name = "image_analysis"
|
78 |
+
description = "Analyzes an image and answers questions about it."
|
79 |
+
inputs = {
|
80 |
+
"image_path": {
|
81 |
+
"type": "string",
|
82 |
+
"description": "The path to the image file to analyze",
|
83 |
+
},
|
84 |
+
"query": {
|
85 |
+
"type": "string",
|
86 |
+
"description": "The question to ask about the image. For example, 'Perform OCR on the text in the image.'",
|
87 |
+
},
|
88 |
+
}
|
89 |
+
output_type = "string"
|
90 |
+
|
91 |
+
def forward(self, image_path: str, query: str) -> str:
|
92 |
+
# Placeholder for image analysis logic
|
93 |
+
client = Client("prithivMLmods/DocScope-R1")
|
94 |
+
result = client.predict(
|
95 |
+
model_name="Cosmos-Reason1-7B",
|
96 |
+
text=query,
|
97 |
+
image=handle_file(image_path),
|
98 |
+
max_new_tokens=1024,
|
99 |
+
temperature=0.6,
|
100 |
+
top_p=0.9,
|
101 |
+
top_k=50,
|
102 |
+
repetition_penalty=1.2,
|
103 |
+
api_name="/generate_image",
|
104 |
+
)
|
105 |
+
return result
|
106 |
+
|
107 |
+
def __init__(self, *args, **kwargs):
|
108 |
+
self.is_initialized = False
|
109 |
+
|
110 |
+
|
111 |
+
class BasicAgent:
|
112 |
+
def __init__(
|
113 |
+
self, model_id: str = "meta-llama/Llama-3.3-70B-Instruct-Turbo-Free"
|
114 |
+
) -> None:
|
115 |
+
with open("prompts.yaml", "r", encoding="utf-8") as stream:
|
116 |
+
prompt_templates = yaml.safe_load(stream)
|
117 |
+
self.agent = CodeAgent(
|
118 |
+
tools=[
|
119 |
+
DuckDuckGoSearchTool(max_results=2),
|
120 |
+
WikipediaSearchTool(),
|
121 |
+
VisitWebpageTool(),
|
122 |
+
PythonInterpreterTool(),
|
123 |
+
ReadFileTool(),
|
124 |
+
TranscribeTool(),
|
125 |
+
ImageAnalysisTool(),
|
126 |
+
GetChessBestMoveTool(),
|
127 |
+
],
|
128 |
+
# model=HfApiModel(
|
129 |
+
# model_id=model_id,
|
130 |
+
# provider="together",
|
131 |
+
# token=os.getenv("TOGETHER_API_KEY"),
|
132 |
+
# ),
|
133 |
+
# model=ApiModel(
|
134 |
+
# model=model_id,
|
135 |
+
# # temperature=0.7,
|
136 |
+
# max_tokens=1500,
|
137 |
+
# api_key=os.getenv("TOGETHER_API_KEY")
|
138 |
+
# ),
|
139 |
+
# model=HfApiModel(),
|
140 |
+
model=LiteLLMModel(
|
141 |
+
# model_id="huggingface/together/Llama-3.3-70B-Instruct-Free",
|
142 |
+
model_id=f"together_ai/{model_id}",
|
143 |
+
# api_base="https://api.together.xyz/v1/chat/completions",
|
144 |
+
# custom_llm_provider="together",
|
145 |
+
api_key=os.getenv("TOGETHER_API_KEY"),
|
146 |
+
temperature=0.0,
|
147 |
+
),
|
148 |
+
prompt_templates=prompt_templates,
|
149 |
+
additional_authorized_imports=["pandas", "numpy", "re", "requests", "bs4"],
|
150 |
+
)
|
151 |
+
self.prompt_templates = prompt_templates
|
152 |
+
|
153 |
+
def __call__(self, question: str) -> str:
|
154 |
+
return self.agent.run(
|
155 |
+
# self.prompt_templates["system_prompt"]+ "\n\n" +
|
156 |
+
"You are a general AI assistant. I will ask you a question. Report your thoughts, and finish your answer with the following template: final_answer(YOUR FINAL ANSWER). YOUR FINAL ANSWER should be a number (python int of float, not numpy) OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities write Mount instead of Mt., Saint instead of St., etc), and write the digits in plain text unless specified otherwise, floats are shortened to one decimal if they are 0 so write the number as a string to avoid this (return '10.00' instead of 10.00). If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string. Put spaces between elements in the list such as 'a, b, c'. Divide the task in smaller tasks so thay you do every step correctly. Check if the answer you are going to submit follows all the rules before submitting it. If you are not sure about the answer, ask for more information or clarification. If you are asked to write a code, write the code in a single code block, and make sure that it is correct and that it follows exactly what has been asked. If you are asked to write a function, write the function in a single code block, and make sure that it is correct and that it follows exactly what has been asked."
|
157 |
+
# + "Before submitting your final answer, make sure to check that it is correct and that follows exactly what has been asked and it is represented in the asked format. it is very IMPORTANT that you give the answer exactly as asked by the user."
|
158 |
+
+ "\n\n"
|
159 |
+
+ question
|
160 |
+
# + "\n\n" + ,
|
161 |
+
)
|
app.py
CHANGED
@@ -1,42 +1,32 @@
|
|
1 |
import os
|
2 |
-
import yaml
|
3 |
import gradio as gr
|
4 |
import requests
|
5 |
-
import inspect
|
6 |
import pandas as pd
|
7 |
-
|
8 |
-
import
|
9 |
-
from
|
10 |
|
11 |
# (Keep Constants as is)
|
12 |
# --- Constants ---
|
13 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
14 |
|
|
|
15 |
|
16 |
-
|
17 |
-
#
|
18 |
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
self.agent = CodeAgent(
|
25 |
-
tools=[DuckDuckGoSearchTool()],
|
26 |
-
model=HfApiModel(
|
27 |
-
model_id=model_id,
|
28 |
-
provider="together",
|
29 |
-
token=os.getenv("TOGETHER_API_KEY"),
|
30 |
-
),
|
31 |
-
prompt_templates=prompt_templates,
|
32 |
-
)
|
33 |
-
self.executor = ThreadPoolExecutor()
|
34 |
|
35 |
-
|
36 |
-
return self.agent.run(
|
37 |
-
"You are a general AI assistant. I will ask you a question. Report your thoughts, and finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string."
|
38 |
-
+ question
|
39 |
-
)
|
40 |
|
41 |
|
42 |
def run_and_submit_all(profile: gr.OAuthProfile | None):
|
@@ -60,7 +50,9 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
|
|
60 |
|
61 |
# 1. Instantiate Agent ( modify this part to create your agent)
|
62 |
try:
|
63 |
-
agent =
|
|
|
|
|
64 |
except Exception as e:
|
65 |
print(f"Error instantiating agent: {e}")
|
66 |
return f"Error initializing agent: {e}", None
|
@@ -100,6 +92,12 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
|
|
100 |
print(f"Skipping item with missing task_id or question: {item}")
|
101 |
continue
|
102 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
submitted_answer = agent(question_text)
|
104 |
answers_payload.append(
|
105 |
{"task_id": task_id, "submitted_answer": submitted_answer}
|
@@ -136,6 +134,8 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
|
|
136 |
|
137 |
# 5. Submit
|
138 |
print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
|
|
|
|
|
139 |
try:
|
140 |
response = requests.post(submit_url, json=submission_data, timeout=60)
|
141 |
response.raise_for_status()
|
@@ -176,6 +176,8 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
|
|
176 |
print(status_message)
|
177 |
results_df = pd.DataFrame(results_log)
|
178 |
return status_message, results_df
|
|
|
|
|
179 |
|
180 |
|
181 |
# --- Build Gradio Interface using Blocks ---
|
|
|
1 |
import os
|
|
|
2 |
import gradio as gr
|
3 |
import requests
|
|
|
4 |
import pandas as pd
|
5 |
+
import json
|
6 |
+
from agent import BasicAgent # Import your agent class from agent.py
|
7 |
+
from utils import download_file
|
8 |
|
9 |
# (Keep Constants as is)
|
10 |
# --- Constants ---
|
11 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
12 |
|
13 |
+
from dotenv import load_dotenv
|
14 |
|
15 |
+
load_dotenv()
|
16 |
+
# Initialize the InferenceClient with together as the provider
|
17 |
|
18 |
+
# client = InferenceClient(
|
19 |
+
# "meta-llama/Llama-3.3-70B-Instruct-Free",
|
20 |
+
# provider="together",
|
21 |
+
# api_key=os.getenv("TOGETHER_API_KEY") # Replace with your API key (HF or custom)
|
22 |
+
# )
|
23 |
|
24 |
+
# --- Basic Agent Definition ---
|
25 |
+
# ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
|
26 |
+
# from huggingface_hub import login
|
27 |
+
# import os
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
29 |
+
# login(token=os.getenv("HUGGINGFACE_TOKEN"))
|
|
|
|
|
|
|
|
|
30 |
|
31 |
|
32 |
def run_and_submit_all(profile: gr.OAuthProfile | None):
|
|
|
50 |
|
51 |
# 1. Instantiate Agent ( modify this part to create your agent)
|
52 |
try:
|
53 |
+
agent = (
|
54 |
+
BasicAgent()
|
55 |
+
) # (model_id="deepseek-ai/DeepSeek-R1-Distill-Llama-70B-free")
|
56 |
except Exception as e:
|
57 |
print(f"Error instantiating agent: {e}")
|
58 |
return f"Error initializing agent: {e}", None
|
|
|
92 |
print(f"Skipping item with missing task_id or question: {item}")
|
93 |
continue
|
94 |
try:
|
95 |
+
if item["file_name"]:
|
96 |
+
file_path = item["file_name"]
|
97 |
+
download_path = download_file(
|
98 |
+
f"{api_url}/files/{item['task_id']}", file_path
|
99 |
+
)
|
100 |
+
question_text += f"\n\nThe file is available locally at {download_path}. Please use it to answer the question."
|
101 |
submitted_answer = agent(question_text)
|
102 |
answers_payload.append(
|
103 |
{"task_id": task_id, "submitted_answer": submitted_answer}
|
|
|
134 |
|
135 |
# 5. Submit
|
136 |
print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
|
137 |
+
json.dump(submission_data, open("submission_data.json", "w"), indent=2)
|
138 |
+
print("Submission data saved to submission_data.json for debugging.")
|
139 |
try:
|
140 |
response = requests.post(submit_url, json=submission_data, timeout=60)
|
141 |
response.raise_for_status()
|
|
|
176 |
print(status_message)
|
177 |
results_df = pd.DataFrame(results_log)
|
178 |
return status_message, results_df
|
179 |
+
finally:
|
180 |
+
print(submission_data) # Log the submission data for debugging
|
181 |
|
182 |
|
183 |
# --- Build Gradio Interface using Blocks ---
|
requirements.txt
CHANGED
@@ -1,3 +1,5 @@
|
|
1 |
gradio
|
2 |
requests
|
3 |
-
smolagents
|
|
|
|
|
|
1 |
gradio
|
2 |
requests
|
3 |
+
smolagents==1.13.0
|
4 |
+
smolagents[litellm]
|
5 |
+
wikipedia-api
|
utils.py
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import shutil
|
2 |
+
import requests
|
3 |
+
|
4 |
+
|
5 |
+
def download_file(url, local_filename):
|
6 |
+
with requests.get(url, stream=True) as r:
|
7 |
+
with open(local_filename, "wb") as f:
|
8 |
+
shutil.copyfileobj(r.raw, f)
|
9 |
+
|
10 |
+
return local_filename
|