Spaces:
Sleeping
Sleeping
smarter prompt approach
Browse files
app.py
CHANGED
|
@@ -8,7 +8,7 @@ from langchain_core.prompts import PromptTemplate
|
|
| 8 |
from langchain.agents import AgentExecutor, create_react_agent
|
| 9 |
from langchain import hub
|
| 10 |
from langchain.tools import Tool
|
| 11 |
-
from langchain_community.tools import
|
| 12 |
from langchain_community.utilities import WikipediaAPIWrapper
|
| 13 |
from youtube_transcript_api import YouTubeTranscriptApi
|
| 14 |
import io
|
|
@@ -24,6 +24,7 @@ import torchaudio
|
|
| 24 |
# --- Constants ---
|
| 25 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
| 26 |
|
|
|
|
| 27 |
def python_interpreter(code: str) -> str:
|
| 28 |
"""
|
| 29 |
Executes a string of Python code and returns the output.
|
|
@@ -35,7 +36,7 @@ def python_interpreter(code: str) -> str:
|
|
| 35 |
# Add numpy and sympy to the local scope of exec
|
| 36 |
local_scope = {}
|
| 37 |
exec("import numpy as np\nimport sympy", local_scope)
|
| 38 |
-
|
| 39 |
f = io.StringIO()
|
| 40 |
with redirect_stdout(f):
|
| 41 |
# Pass the local_scope to exec
|
|
@@ -44,6 +45,7 @@ def python_interpreter(code: str) -> str:
|
|
| 44 |
except Exception as e:
|
| 45 |
return str(e)
|
| 46 |
|
|
|
|
| 47 |
def file_reader_tool(url: str) -> str:
|
| 48 |
"""
|
| 49 |
Reads the content of a file from a URL and returns the first 5 rows as a string.
|
|
@@ -53,23 +55,28 @@ def file_reader_tool(url: str) -> str:
|
|
| 53 |
try:
|
| 54 |
# Download the file content
|
| 55 |
response = requests.get(url)
|
| 56 |
-
response.raise_for_status()
|
| 57 |
|
| 58 |
# Get the content type to guess the file type
|
| 59 |
-
content_type = response.headers.get(
|
| 60 |
-
|
| 61 |
# Use BytesIO for binary content like Excel files
|
| 62 |
file_content = io.BytesIO(response.content)
|
| 63 |
|
| 64 |
df = None
|
| 65 |
-
if
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
df = pd.read_excel(file_content)
|
| 67 |
-
elif
|
| 68 |
-
df = pd.read_csv(io.StringIO(response.content.decode(
|
| 69 |
else:
|
| 70 |
# Try reading as CSV as a fallback
|
| 71 |
try:
|
| 72 |
-
df = pd.read_csv(io.StringIO(response.content.decode(
|
| 73 |
except Exception:
|
| 74 |
return "Error: Could not determine file type. Supported types are Excel and CSV."
|
| 75 |
|
|
@@ -81,6 +88,7 @@ def file_reader_tool(url: str) -> str:
|
|
| 81 |
except Exception as e:
|
| 82 |
return f"Error: Could not read or process the file: {e}"
|
| 83 |
|
|
|
|
| 84 |
def youtube_transcript_tool(url: str) -> str:
|
| 85 |
"""
|
| 86 |
Fetches the transcript of a YouTube video from its URL.
|
|
@@ -89,16 +97,17 @@ def youtube_transcript_tool(url: str) -> str:
|
|
| 89 |
try:
|
| 90 |
video_id = url.split("v=")[1]
|
| 91 |
# Handle URLs with extra parameters
|
| 92 |
-
ampersand_position = video_id.find(
|
| 93 |
if ampersand_position != -1:
|
| 94 |
video_id = video_id[:ampersand_position]
|
| 95 |
-
|
| 96 |
transcript_list = YouTubeTranscriptApi.get_transcript(video_id)
|
| 97 |
-
transcript = " ".join([item[
|
| 98 |
return transcript
|
| 99 |
except Exception as e:
|
| 100 |
return f"Error: Could not fetch transcript. Make sure the URL is a valid YouTube video with available transcripts. Error: {e}"
|
| 101 |
|
|
|
|
| 102 |
def web_reader_tool(url: str) -> str:
|
| 103 |
"""
|
| 104 |
Reads the text content of a web page from a URL.
|
|
@@ -107,13 +116,14 @@ def web_reader_tool(url: str) -> str:
|
|
| 107 |
try:
|
| 108 |
response = requests.get(url)
|
| 109 |
response.raise_for_status()
|
| 110 |
-
soup = BeautifulSoup(response.content,
|
| 111 |
return soup.get_text()
|
| 112 |
except requests.exceptions.RequestException as e:
|
| 113 |
return f"Error: Could not download the file from the URL: {e}"
|
| 114 |
except Exception as e:
|
| 115 |
return f"Error: Could not read or process the file: {e}"
|
| 116 |
|
|
|
|
| 117 |
def audio_analyzer_tool(url: str) -> str:
|
| 118 |
"""
|
| 119 |
Analyzes audio content from a URL by transcribing it into text.
|
|
@@ -122,19 +132,22 @@ def audio_analyzer_tool(url: str) -> str:
|
|
| 122 |
try:
|
| 123 |
print(f"Analyzing audio from URL: {url}")
|
| 124 |
# Initialize the ASR pipeline
|
| 125 |
-
asr_pipeline = pipeline(
|
| 126 |
-
|
|
|
|
|
|
|
| 127 |
# Download the audio file
|
| 128 |
response = requests.get(url)
|
| 129 |
response.raise_for_status()
|
| 130 |
audio_data = response.content
|
| 131 |
-
|
| 132 |
# Transcribe the audio
|
| 133 |
transcription = asr_pipeline(audio_data)
|
| 134 |
-
return transcription[
|
| 135 |
except Exception as e:
|
| 136 |
return f"Error analyzing audio: {e}"
|
| 137 |
|
|
|
|
| 138 |
def video_analyzer_tool(url: str) -> str:
|
| 139 |
"""
|
| 140 |
Analyzes the audio track of a video from a URL by transcribing it into text.
|
|
@@ -143,35 +156,37 @@ def video_analyzer_tool(url: str) -> str:
|
|
| 143 |
try:
|
| 144 |
print(f"Analyzing video from URL: {url}")
|
| 145 |
# Initialize the ASR pipeline
|
| 146 |
-
asr_pipeline = pipeline(
|
| 147 |
-
|
|
|
|
|
|
|
| 148 |
# Open the video file from the URL
|
| 149 |
with av.open(url) as container:
|
| 150 |
audio_stream = container.streams.audio[0]
|
| 151 |
-
|
| 152 |
# Decode the audio stream
|
| 153 |
frames = []
|
| 154 |
for frame in container.decode(audio_stream):
|
| 155 |
frames.append(frame.to_ndarray())
|
| 156 |
-
|
| 157 |
if not frames:
|
| 158 |
return "Error: No audio frames found in the video."
|
| 159 |
|
| 160 |
# Concatenate frames and convert to a tensor
|
| 161 |
import numpy as np
|
|
|
|
| 162 |
audio_array = torch.from_numpy(np.concatenate(frames, axis=1))
|
| 163 |
-
|
| 164 |
# Resample if necessary
|
| 165 |
resampler = torchaudio.transforms.Resample(
|
| 166 |
-
orig_freq=audio_stream.sample_rate,
|
| 167 |
-
new_freq=16000
|
| 168 |
)
|
| 169 |
resampled_audio = resampler(audio_array)
|
| 170 |
-
|
| 171 |
# Transcribe the audio
|
| 172 |
transcription = asr_pipeline(resampled_audio.squeeze().numpy())
|
| 173 |
-
return transcription[
|
| 174 |
-
|
| 175 |
except Exception as e:
|
| 176 |
return f"Error analyzing video: {e}"
|
| 177 |
|
|
@@ -184,7 +199,9 @@ class BasicAgent:
|
|
| 184 |
# Get the token from environment variables (HF Spaces Secrets)
|
| 185 |
hf_token = os.getenv("HUGGING_FACE_HUB_TOKEN")
|
| 186 |
if not hf_token:
|
| 187 |
-
print(
|
|
|
|
|
|
|
| 188 |
|
| 189 |
# It's better to initialize the model here to avoid reloading it for every call.
|
| 190 |
# Using a smaller model for faster response times.
|
|
@@ -194,42 +211,46 @@ class BasicAgent:
|
|
| 194 |
model_kwargs={"dtype": "float32"},
|
| 195 |
pipeline_kwargs={"max_new_tokens": 256},
|
| 196 |
)
|
| 197 |
-
|
| 198 |
tools = [
|
| 199 |
Tool(
|
| 200 |
name="Python Interpreter",
|
| 201 |
func=python_interpreter,
|
| 202 |
-
description="A Python interpreter that can execute Python code. Use it for calculations, symbolic math (with sympy), and other tasks that can be solved with code. The code should use `print()` to output the result. Libraries like numpy (as np) and sympy are available."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 203 |
),
|
| 204 |
-
DuckDuckGoSearchRun(),
|
| 205 |
Tool(
|
| 206 |
name="File Reader from URL",
|
| 207 |
func=file_reader_tool,
|
| 208 |
-
description="Reads the content of a file from a URL and returns the first 5 rows as a string. It can handle Excel (.xlsx, .xls) and CSV (.csv) files. The URL must point directly to the file."
|
| 209 |
),
|
| 210 |
WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper()),
|
| 211 |
Tool(
|
| 212 |
name="YouTube Transcript Reader",
|
| 213 |
func=youtube_transcript_tool,
|
| 214 |
-
description="Fetches the full transcript of a YouTube video from its URL. Use this to answer questions about the content of a video."
|
| 215 |
),
|
| 216 |
Tool(
|
| 217 |
name="Web Page Reader",
|
| 218 |
func=web_reader_tool,
|
| 219 |
-
description="Reads the text content of a web page from a URL. Use this for any URL that doesn't point directly to a file like CSV or Excel."
|
| 220 |
),
|
| 221 |
Tool(
|
| 222 |
name="Audio Analyzer",
|
| 223 |
func=audio_analyzer_tool,
|
| 224 |
-
description="Analyzes audio content from a URL by transcribing it into text. The URL must point directly to an audio file (e.g., .wav, .mp3)."
|
| 225 |
),
|
| 226 |
Tool(
|
| 227 |
name="Video Analyzer",
|
| 228 |
func=video_analyzer_tool,
|
| 229 |
-
description="Analyzes the audio track of a video from a URL by transcribing it into text. The URL must point directly to a video file (e.g., .mp4)."
|
| 230 |
),
|
| 231 |
]
|
| 232 |
-
|
| 233 |
# A more direct, instruction-based prompt with high-quality examples.
|
| 234 |
gemma_react_prompt = '''<start_of_turn>user
|
| 235 |
You are a helpful agent. Your goal is to answer the user's question.
|
|
@@ -242,7 +263,7 @@ To answer the question, you MUST follow these steps:
|
|
| 242 |
2. **Action:** Choose one of the available tools for your 'Action'. Your 'Action' must be one of [{tool_names}].
|
| 243 |
3. **Action Input:** Provide the input for that tool. The input should be a simple string, not a Python expression.
|
| 244 |
4. **Observation:** Wait for the result of the tool.
|
| 245 |
-
5. **Thought:** Analyze the result and the current plan. If the plan needs to be revised, state the new plan. Then, proceed with the next step.
|
| 246 |
6. Repeat steps 2-5 until you have enough information to answer the question.
|
| 247 |
7. **Thought:** Once you have the final answer, you MUST use the following template: `FINAL ANSWER: [YOUR FINAL ANSWER]`.
|
| 248 |
|
|
@@ -255,7 +276,7 @@ To answer the question, you MUST follow these steps:
|
|
| 255 |
|
| 256 |
Do not make up observations.
|
| 257 |
|
| 258 |
-
Here
|
| 259 |
|
| 260 |
Question: In the YouTube video at `https://www.youtube.com/watch?v=example`, the speaker mentions a specific battle. Use the transcript to find the name of the battle, then find out which year it took place.
|
| 261 |
|
|
@@ -275,6 +296,25 @@ Observation: Page: Battle of Hastings. Summary: The Battle of Hastings was fough
|
|
| 275 |
Thought: I have found the year of the battle, 1066. I have completed all steps of my plan.
|
| 276 |
FINAL ANSWER: Battle of Hastings, 1066
|
| 277 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 278 |
Begin!
|
| 279 |
|
| 280 |
Question: {input}
|
|
@@ -282,10 +322,12 @@ Thought:{agent_scratchpad}<end_of_turn>
|
|
| 282 |
<start_of_turn>model
|
| 283 |
'''
|
| 284 |
prompt = PromptTemplate.from_template(gemma_react_prompt)
|
| 285 |
-
|
| 286 |
agent = create_react_agent(self.llm, tools, prompt)
|
| 287 |
-
|
| 288 |
-
self.agent_executor = AgentExecutor(
|
|
|
|
|
|
|
| 289 |
|
| 290 |
def __call__(self, question: str) -> str:
|
| 291 |
print(f"Agent received question (first 50 chars): {question[:50]}...")
|
|
|
|
| 8 |
from langchain.agents import AgentExecutor, create_react_agent
|
| 9 |
from langchain import hub
|
| 10 |
from langchain.tools import Tool
|
| 11 |
+
from langchain_community.tools import DuckDuckGoSearchResults, WikipediaQueryRun
|
| 12 |
from langchain_community.utilities import WikipediaAPIWrapper
|
| 13 |
from youtube_transcript_api import YouTubeTranscriptApi
|
| 14 |
import io
|
|
|
|
| 24 |
# --- Constants ---
|
| 25 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
| 26 |
|
| 27 |
+
|
| 28 |
def python_interpreter(code: str) -> str:
|
| 29 |
"""
|
| 30 |
Executes a string of Python code and returns the output.
|
|
|
|
| 36 |
# Add numpy and sympy to the local scope of exec
|
| 37 |
local_scope = {}
|
| 38 |
exec("import numpy as np\nimport sympy", local_scope)
|
| 39 |
+
|
| 40 |
f = io.StringIO()
|
| 41 |
with redirect_stdout(f):
|
| 42 |
# Pass the local_scope to exec
|
|
|
|
| 45 |
except Exception as e:
|
| 46 |
return str(e)
|
| 47 |
|
| 48 |
+
|
| 49 |
def file_reader_tool(url: str) -> str:
|
| 50 |
"""
|
| 51 |
Reads the content of a file from a URL and returns the first 5 rows as a string.
|
|
|
|
| 55 |
try:
|
| 56 |
# Download the file content
|
| 57 |
response = requests.get(url)
|
| 58 |
+
response.raise_for_status() # Raise an exception for bad status codes
|
| 59 |
|
| 60 |
# Get the content type to guess the file type
|
| 61 |
+
content_type = response.headers.get("content-type")
|
| 62 |
+
|
| 63 |
# Use BytesIO for binary content like Excel files
|
| 64 |
file_content = io.BytesIO(response.content)
|
| 65 |
|
| 66 |
df = None
|
| 67 |
+
if (
|
| 68 |
+
"excel" in content_type
|
| 69 |
+
or "spreadsheet" in content_type
|
| 70 |
+
or url.endswith(".xlsx")
|
| 71 |
+
or url.endswith(".xls")
|
| 72 |
+
):
|
| 73 |
df = pd.read_excel(file_content)
|
| 74 |
+
elif "csv" in content_type or url.endswith(".csv"):
|
| 75 |
+
df = pd.read_csv(io.StringIO(response.content.decode("utf-8")))
|
| 76 |
else:
|
| 77 |
# Try reading as CSV as a fallback
|
| 78 |
try:
|
| 79 |
+
df = pd.read_csv(io.StringIO(response.content.decode("utf-8")))
|
| 80 |
except Exception:
|
| 81 |
return "Error: Could not determine file type. Supported types are Excel and CSV."
|
| 82 |
|
|
|
|
| 88 |
except Exception as e:
|
| 89 |
return f"Error: Could not read or process the file: {e}"
|
| 90 |
|
| 91 |
+
|
| 92 |
def youtube_transcript_tool(url: str) -> str:
|
| 93 |
"""
|
| 94 |
Fetches the transcript of a YouTube video from its URL.
|
|
|
|
| 97 |
try:
|
| 98 |
video_id = url.split("v=")[1]
|
| 99 |
# Handle URLs with extra parameters
|
| 100 |
+
ampersand_position = video_id.find("&")
|
| 101 |
if ampersand_position != -1:
|
| 102 |
video_id = video_id[:ampersand_position]
|
| 103 |
+
|
| 104 |
transcript_list = YouTubeTranscriptApi.get_transcript(video_id)
|
| 105 |
+
transcript = " ".join([item["text"] for item in transcript_list])
|
| 106 |
return transcript
|
| 107 |
except Exception as e:
|
| 108 |
return f"Error: Could not fetch transcript. Make sure the URL is a valid YouTube video with available transcripts. Error: {e}"
|
| 109 |
|
| 110 |
+
|
| 111 |
def web_reader_tool(url: str) -> str:
|
| 112 |
"""
|
| 113 |
Reads the text content of a web page from a URL.
|
|
|
|
| 116 |
try:
|
| 117 |
response = requests.get(url)
|
| 118 |
response.raise_for_status()
|
| 119 |
+
soup = BeautifulSoup(response.content, "html.parser")
|
| 120 |
return soup.get_text()
|
| 121 |
except requests.exceptions.RequestException as e:
|
| 122 |
return f"Error: Could not download the file from the URL: {e}"
|
| 123 |
except Exception as e:
|
| 124 |
return f"Error: Could not read or process the file: {e}"
|
| 125 |
|
| 126 |
+
|
| 127 |
def audio_analyzer_tool(url: str) -> str:
|
| 128 |
"""
|
| 129 |
Analyzes audio content from a URL by transcribing it into text.
|
|
|
|
| 132 |
try:
|
| 133 |
print(f"Analyzing audio from URL: {url}")
|
| 134 |
# Initialize the ASR pipeline
|
| 135 |
+
asr_pipeline = pipeline(
|
| 136 |
+
"automatic-speech-recognition", model="openai/whisper-base"
|
| 137 |
+
)
|
| 138 |
+
|
| 139 |
# Download the audio file
|
| 140 |
response = requests.get(url)
|
| 141 |
response.raise_for_status()
|
| 142 |
audio_data = response.content
|
| 143 |
+
|
| 144 |
# Transcribe the audio
|
| 145 |
transcription = asr_pipeline(audio_data)
|
| 146 |
+
return transcription["text"]
|
| 147 |
except Exception as e:
|
| 148 |
return f"Error analyzing audio: {e}"
|
| 149 |
|
| 150 |
+
|
| 151 |
def video_analyzer_tool(url: str) -> str:
|
| 152 |
"""
|
| 153 |
Analyzes the audio track of a video from a URL by transcribing it into text.
|
|
|
|
| 156 |
try:
|
| 157 |
print(f"Analyzing video from URL: {url}")
|
| 158 |
# Initialize the ASR pipeline
|
| 159 |
+
asr_pipeline = pipeline(
|
| 160 |
+
"automatic-speech-recognition", model="openai/whisper-base"
|
| 161 |
+
)
|
| 162 |
+
|
| 163 |
# Open the video file from the URL
|
| 164 |
with av.open(url) as container:
|
| 165 |
audio_stream = container.streams.audio[0]
|
| 166 |
+
|
| 167 |
# Decode the audio stream
|
| 168 |
frames = []
|
| 169 |
for frame in container.decode(audio_stream):
|
| 170 |
frames.append(frame.to_ndarray())
|
| 171 |
+
|
| 172 |
if not frames:
|
| 173 |
return "Error: No audio frames found in the video."
|
| 174 |
|
| 175 |
# Concatenate frames and convert to a tensor
|
| 176 |
import numpy as np
|
| 177 |
+
|
| 178 |
audio_array = torch.from_numpy(np.concatenate(frames, axis=1))
|
| 179 |
+
|
| 180 |
# Resample if necessary
|
| 181 |
resampler = torchaudio.transforms.Resample(
|
| 182 |
+
orig_freq=audio_stream.sample_rate, new_freq=16000
|
|
|
|
| 183 |
)
|
| 184 |
resampled_audio = resampler(audio_array)
|
| 185 |
+
|
| 186 |
# Transcribe the audio
|
| 187 |
transcription = asr_pipeline(resampled_audio.squeeze().numpy())
|
| 188 |
+
return transcription["text"]
|
| 189 |
+
|
| 190 |
except Exception as e:
|
| 191 |
return f"Error analyzing video: {e}"
|
| 192 |
|
|
|
|
| 199 |
# Get the token from environment variables (HF Spaces Secrets)
|
| 200 |
hf_token = os.getenv("HUGGING_FACE_HUB_TOKEN")
|
| 201 |
if not hf_token:
|
| 202 |
+
print(
|
| 203 |
+
"Warning: HUGGING_FACE_HUB_TOKEN secret not found. This will fail for gated models."
|
| 204 |
+
)
|
| 205 |
|
| 206 |
# It's better to initialize the model here to avoid reloading it for every call.
|
| 207 |
# Using a smaller model for faster response times.
|
|
|
|
| 211 |
model_kwargs={"dtype": "float32"},
|
| 212 |
pipeline_kwargs={"max_new_tokens": 256},
|
| 213 |
)
|
| 214 |
+
|
| 215 |
tools = [
|
| 216 |
Tool(
|
| 217 |
name="Python Interpreter",
|
| 218 |
func=python_interpreter,
|
| 219 |
+
description="A Python interpreter that can execute Python code. Use it for calculations, symbolic math (with sympy), and other tasks that can be solved with code. The code should use `print()` to output the result. Libraries like numpy (as np) and sympy are available.",
|
| 220 |
+
),
|
| 221 |
+
Tool(
|
| 222 |
+
name="DuckDuckGo Search Results",
|
| 223 |
+
func=DuckDuckGoSearchResults(),
|
| 224 |
+
description="A wrapper around DuckDuckGo Search. Useful for when you need to answer questions about current events. Input should be a search query. Output is a list of results.",
|
| 225 |
),
|
|
|
|
| 226 |
Tool(
|
| 227 |
name="File Reader from URL",
|
| 228 |
func=file_reader_tool,
|
| 229 |
+
description="Reads the content of a file from a URL and returns the first 5 rows as a string. It can handle Excel (.xlsx, .xls) and CSV (.csv) files. The URL must point directly to the file.",
|
| 230 |
),
|
| 231 |
WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper()),
|
| 232 |
Tool(
|
| 233 |
name="YouTube Transcript Reader",
|
| 234 |
func=youtube_transcript_tool,
|
| 235 |
+
description="Fetches the full transcript of a YouTube video from its URL. Use this to answer questions about the content of a video.",
|
| 236 |
),
|
| 237 |
Tool(
|
| 238 |
name="Web Page Reader",
|
| 239 |
func=web_reader_tool,
|
| 240 |
+
description="Reads the text content of a web page from a URL. Use this for any URL that doesn't point directly to a file like CSV or Excel.",
|
| 241 |
),
|
| 242 |
Tool(
|
| 243 |
name="Audio Analyzer",
|
| 244 |
func=audio_analyzer_tool,
|
| 245 |
+
description="Analyzes audio content from a URL by transcribing it into text. The URL must point directly to an audio file (e.g., .wav, .mp3).",
|
| 246 |
),
|
| 247 |
Tool(
|
| 248 |
name="Video Analyzer",
|
| 249 |
func=video_analyzer_tool,
|
| 250 |
+
description="Analyzes the audio track of a video from a URL by transcribing it into text. The URL must point directly to a video file (e.g., .mp4).",
|
| 251 |
),
|
| 252 |
]
|
| 253 |
+
|
| 254 |
# A more direct, instruction-based prompt with high-quality examples.
|
| 255 |
gemma_react_prompt = '''<start_of_turn>user
|
| 256 |
You are a helpful agent. Your goal is to answer the user's question.
|
|
|
|
| 263 |
2. **Action:** Choose one of the available tools for your 'Action'. Your 'Action' must be one of [{tool_names}].
|
| 264 |
3. **Action Input:** Provide the input for that tool. The input should be a simple string, not a Python expression.
|
| 265 |
4. **Observation:** Wait for the result of the tool.
|
| 266 |
+
5. **Thought:** Analyze the result and the current plan. If a tool fails, you MUST try to recover by using a different tool or a different input. If you get stuck, you MUST try to search for the information using DuckDuckGo Search Results. If you find a relevant URL, you can use the Web Page Reader tool to read its content. If the plan needs to be revised, state the new plan. Then, proceed with the next step.
|
| 267 |
6. Repeat steps 2-5 until you have enough information to answer the question.
|
| 268 |
7. **Thought:** Once you have the final answer, you MUST use the following template: `FINAL ANSWER: [YOUR FINAL ANSWER]`.
|
| 269 |
|
|
|
|
| 276 |
|
| 277 |
Do not make up observations.
|
| 278 |
|
| 279 |
+
Here are some examples:
|
| 280 |
|
| 281 |
Question: In the YouTube video at `https://www.youtube.com/watch?v=example`, the speaker mentions a specific battle. Use the transcript to find the name of the battle, then find out which year it took place.
|
| 282 |
|
|
|
|
| 296 |
Thought: I have found the year of the battle, 1066. I have completed all steps of my plan.
|
| 297 |
FINAL ANSWER: Battle of Hastings, 1066
|
| 298 |
|
| 299 |
+
Question: How many studio albums did Mercedes Sosa release between 2000 and 2009?
|
| 300 |
+
|
| 301 |
+
Thought:
|
| 302 |
+
My plan is:
|
| 303 |
+
1. Search for Mercedes Sosa's discography.
|
| 304 |
+
2. From the search results, find a reliable source like Wikipedia or a music database.
|
| 305 |
+
3. Read the content of the source.
|
| 306 |
+
4. Count the number of studio albums released between 2000 and 2009.
|
| 307 |
+
I will now execute step 1.
|
| 308 |
+
Action: DuckDuckGo Search Results
|
| 309 |
+
Action Input: Mercedes Sosa discography
|
| 310 |
+
Observation: [snippet: Mercedes Sosa discography. Studio albums. Year, Album, Label. 1959, La voz de la zafra, RCA Victor. ... 2000, Acústico, ... 2005, Corazón libre, ... 2009, Cantora, ... link: https://en.wikipedia.org/wiki/Mercedes_Sosa_discography], ...
|
| 311 |
+
Thought: The search results show a Wikipedia page that seems to contain the discography. I will read the content of that page.
|
| 312 |
+
Action: Web Page Reader
|
| 313 |
+
Action Input: https://en.wikipedia.org/wiki/Mercedes_Sosa_discography
|
| 314 |
+
Observation: ...Studio albums... 2000 Acústico ... 2005 Corazón libre ... 2009 Cantora ...
|
| 315 |
+
Thought: I have the list of albums. Now I need to count the ones between 2000 and 2009. I see "Acústico" (2000), "Corazón libre" (2005), and "Cantora" (2009). That's 3 albums.
|
| 316 |
+
FINAL ANSWER: 3
|
| 317 |
+
|
| 318 |
Begin!
|
| 319 |
|
| 320 |
Question: {input}
|
|
|
|
| 322 |
<start_of_turn>model
|
| 323 |
'''
|
| 324 |
prompt = PromptTemplate.from_template(gemma_react_prompt)
|
| 325 |
+
|
| 326 |
agent = create_react_agent(self.llm, tools, prompt)
|
| 327 |
+
|
| 328 |
+
self.agent_executor = AgentExecutor(
|
| 329 |
+
agent=agent, tools=tools, verbose=True, handle_parsing_errors=True
|
| 330 |
+
)
|
| 331 |
|
| 332 |
def __call__(self, question: str) -> str:
|
| 333 |
print(f"Agent received question (first 50 chars): {question[:50]}...")
|