dawid-lorek commited on
Commit
02c61e8
·
verified ·
1 Parent(s): 608b200

Update agent.py

Browse files
Files changed (1) hide show
  1. agent.py +64 -71
agent.py CHANGED
@@ -1,76 +1,37 @@
1
  import os
2
- import requests
3
  import base64
4
- from langchain_openai import ChatOpenAI
5
- from langchain_community.tools import DuckDuckGoSearchRun
6
- from langchain.agents import initialize_agent, Tool
7
- from langchain.agents.agent_types import AgentType
8
- from langchain.memory import ConversationBufferMemory
9
- from langchain_core.messages import HumanMessage
10
 
11
- DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
12
 
13
  class BasicAgent:
14
  def __init__(self):
 
15
  print("BasicAgent initialized.")
16
- # Use DuckDuckGo Search only
17
- tools = [
18
- Tool(
19
- name="DuckDuckGo Search",
20
- func=DuckDuckGoSearchRun().run,
21
- description="Use this tool to find factual information or recent events."
22
- ),
23
- Tool(
24
- name="Image Analyzer",
25
- func=self.describe_image,
26
- description="Analyzes and describes what's in an image. Input is an image path."
27
- )
28
- ]
29
 
30
- memory = ConversationBufferMemory(memory_key="chat_history")
31
- self.model = ChatOpenAI(model="gpt-4.1-mini", temperature=0)
32
-
33
- self.agent = initialize_agent(
34
- tools=tools,
35
- llm=self.model,
36
- agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
37
- verbose=True,
38
- memory=memory
39
- )
40
-
41
- def describe_image(self, img_path: str) -> str:
42
- all_text = ""
43
  try:
44
- r = requests.get(img_path, timeout=10)
45
- image_bytes = r.content
46
- image_base64 = base64.b64encode(image_bytes).decode("utf-8")
47
- message = [
48
- HumanMessage(
49
- content=[
50
- {
51
- "type": "text",
52
- "text": (
53
- "You're a chess assistant. Answer only with the best move in algebraic notation (e.g., Qd1#)."
54
- ),
55
- },
56
- {
57
- "type": "image_url",
58
- "image_url": {
59
- "url": f"data:image/png;base64,{image_base64}"
60
- },
61
- },
62
- ]
63
- )
64
- ]
65
- response = self.model.invoke(message)
66
- all_text += response.content + "\n\n"
67
- return all_text.strip()
68
  except Exception as e:
69
- error_msg = f"Error extracting text: {str(e)}"
70
- print(error_msg)
71
- return ""
72
 
73
  def fetch_file(self, task_id):
 
74
  try:
75
  url = f"{DEFAULT_API_URL}/files/{task_id}"
76
  r = requests.get(url, timeout=10)
@@ -78,13 +39,45 @@ class BasicAgent:
78
  return url, r.content, r.headers.get("Content-Type", "")
79
  except:
80
  return None, None, None
81
-
82
- def __call__(self, question: str, task_id: str) -> str:
83
- print(f"Agent received question (first 50 chars) {task_id}: {question[:50]}...")
84
- file_url, file_content, file_type = self.fetch_file(task_id)
85
- print(f"Fetched file {file_type}")
86
- if file_url is not None:
87
- question = f"{question} This task has assigned file with URL: {file_url}"
88
- fixed_answer = self.agent.run(question)
89
- print(f"Agent returning fixed answer: {fixed_answer}")
90
- return fixed_answer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
 
2
  import base64
3
+ import requests
4
+ from openai import OpenAI
5
+ from duckduckgo_search import DDGS
 
 
 
6
 
7
+ # You can expand with image/audio/etc tools as needed
8
 
9
  class BasicAgent:
10
  def __init__(self):
11
+ self.llm = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
12
  print("BasicAgent initialized.")
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
+ def web_search(self, query: str, max_results: int = 5) -> str:
15
+ """Search the web using DuckDuckGo for current information."""
 
 
 
 
 
 
 
 
 
 
 
16
  try:
17
+ with DDGS() as ddgs:
18
+ results = list(ddgs.text(query, max_results=max_results))
19
+ if not results:
20
+ return f"No results found for query: {query}"
21
+ formatted_results = f"Web search results for '{query}':\n\n"
22
+ for i, result in enumerate(results, 1):
23
+ title = result.get('title', 'No title')
24
+ body = result.get('body', 'No description')
25
+ href = result.get('href', 'No URL')
26
+ formatted_results += f"{i}. {title}\n"
27
+ formatted_results += f" URL: {href}\n"
28
+ formatted_results += f" Description: {body}\n\n"
29
+ return formatted_results
 
 
 
 
 
 
 
 
 
 
 
30
  except Exception as e:
31
+ return f"Error performing web search: {str(e)}"
 
 
32
 
33
  def fetch_file(self, task_id):
34
+ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
35
  try:
36
  url = f"{DEFAULT_API_URL}/files/{task_id}"
37
  r = requests.get(url, timeout=10)
 
39
  return url, r.content, r.headers.get("Content-Type", "")
40
  except:
41
  return None, None, None
42
+
43
+ def describe_image(self, img_path: str) -> str:
44
+ # This is optional: image-based chess move recognition
45
+ try:
46
+ r = requests.get(img_path, timeout=10)
47
+ image_bytes = r.content
48
+ image_base64 = base64.b64encode(image_bytes).decode("utf-8")
49
+ prompt = (
50
+ "You're a chess assistant. Answer only with the best move in algebraic notation (e.g., Qd1#)."
51
+ )
52
+ # In this template, you'd need your LLM to accept vision input.
53
+ # If not, just return an error or a stub.
54
+ return "[Image analysis not implemented in this agent.]"
55
+ except Exception as e:
56
+ return f"Error extracting text: {str(e)}"
57
+
58
+ def __call__(self, question: str, task_id: str = None) -> str:
59
+ # Step 1: Always web search and build prompt
60
+ search_snippet = self.web_search(question)
61
+ # Step 2: Compose the mandated prompt exactly as specified
62
+ full_prompt = (
63
+ "You are a general AI assistant. I will ask you a question. "
64
+ "Report your thoughts, and finish your answer with the following template: "
65
+ "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. "
66
+ "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. "
67
+ "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. "
68
+ "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.\n\n"
69
+ f"Here are web search results and the question:\n{search_snippet}\n\nQuestion: {question}"
70
+ )
71
+
72
+ # Step 3: Get answer from OpenAI, temperature 0 for max determinism
73
+ response = self.llm.chat.completions.create(
74
+ model="gpt-4o",
75
+ messages=[
76
+ {"role": "system", "content": full_prompt},
77
+ ],
78
+ temperature=0.0,
79
+ max_tokens=512,
80
+ )
81
+ answer = response.choices[0].message.content.strip()
82
+ # You may want to extract just the "FINAL ANSWER: ..." line, or you can return as is
83
+ return answer