Freddolin commited on
Commit
b7bf79a
·
verified ·
1 Parent(s): 4d007ed

Update agent.py

Browse files
Files changed (1) hide show
  1. agent.py +79 -147
agent.py CHANGED
@@ -1,159 +1,91 @@
1
  import os
2
- from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM
3
- import torch # För att kontrollera enheter
4
 
5
- # Importera ditt nya sökverktyg
6
- from tools.tavily_search import search_tavily
 
 
 
 
 
 
 
7
 
8
  class GaiaAgent:
9
  def __init__(self, model_id: str = "google/gemma-2b-it"):
10
- # Ladda tokenizer och modell manuellt. Detta ger mer kontroll.
11
- try:
12
- print(f"Laddar tokenizer för {model_id}...")
13
- self.tokenizer = AutoTokenizer.from_pretrained(model_id, token=os.getenv("HF_TOKEN"))
14
- print(f"Laddar modell för {model_id}...")
15
-
16
- # Kontrollera om GPU är tillgänglig
17
- device = "cuda" if torch.cuda.is_available() else "cpu"
18
- print(f"Använder enhet: {device}")
19
-
20
- self.model = AutoModelForCausalLM.from_pretrained(
21
- model_id,
22
- torch_dtype=torch.bfloat16, # Använd bfloat16 för minskat minne
23
- device_map="auto", # Accelerate hanterar detta över CPU/GPU
24
- token=os.getenv("HF_TOKEN")
25
  )
26
- print("Modell laddad framgångsrikt.")
27
 
28
- # Skapa en pipeline för textgenerering
29
- self.text_generator = pipeline(
30
- "text-generation",
31
- model=self.model,
32
- tokenizer=self.tokenizer,
33
- # device=0 if device == "cuda" else -1 # 0 för första GPU, -1 för CPU
34
  )
35
- print("Textgenereringspipeline skapad.")
36
-
37
  except Exception as e:
38
- print(f"Fel vid initiering av agent: {e}")
39
- raise RuntimeError(f"Fel vid laddning av modell eller tokenizer: {e}")
 
 
40
 
41
- # --- THIS IS THE MISSING __CALL__ METHOD ---
42
- def __call__(self, question: str) -> str:
43
- """
44
- Denna metod gör att en instans av GaiaAgent kan kallas som en funktion.
45
- Den kommer att anropa din process_task metod för att generera svaret.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  """
47
- print(f"Agent received question (first 50 chars): {question[:50]}...")
48
- result = self.process_task(question)
49
- print(f"Agent returning answer: {result[:100]}...") # För att inte fylla loggarna med för långa svar
50
- return result
51
- # --- END OF MISSING METHOD ---
52
-
53
- def process_task(self, task_description: str) -> str:
54
- # Instruction to the LLM to perform the task and use tools.
55
- # We need to build a prompt that instructs the model to use tools.
56
-
57
- prompt = f"""
58
- You are a helpful and expert AI assistant with access to a search tool.
59
- Your task is to carefully and accurately answer questions by using the search tool when necessary.
60
- Always provide a complete and correct answer based on the information you find.
61
-
62
- You must follow a Thought, Tool, Observation, Answer (TTOA) pattern.
63
-
64
- **Thought:** First, carefully consider the task. What information do you need to answer the question? Do you need to use a tool?
65
- **Tool:** If you need to search, use the search_tavily tool. The format is: <TOOL_CODE>search_tavily("your search query")</TOOL_CODE>
66
- **Observation:** After a tool call, you will receive an observation (the tool's output). This is factual information.
67
- **Answer:** Once you have gathered all necessary information, provide your final, concise answer directly.
68
-
69
- Your available tools:
70
- 1. search_tavily(query: str): Searches on Tavily and returns relevant results.
71
-
72
- Example Interaction:
73
- Task: What is the capital of France?
74
- Thought: I need to find the capital of France. I should use the search_tavily tool.
75
- Tool: <TOOL_CODE>search_tavily("capital of France")</TOOL_CODE>
76
- Observation: The capital of France is Paris.
77
- Answer: The capital of France is Paris.
78
-
79
- Now, let's start.
80
-
81
- Task: {task_description}
82
  """
83
-
84
- max_iterations = 3
85
- current_response_history = "" # Ny variabel för att bygga upp historiken
86
-
87
- for i in range(max_iterations):
88
- # Lägg till "Thought:" här för att uppmuntra modellen att starta sin tankeprocess
89
- full_prompt = prompt + current_response_history + "\n\nThought:"
90
-
91
- print(f"[{i+1}/{max_iterations}] Generating response with prompt length: {len(full_prompt)}")
92
-
93
- generated_text = self.text_generator(
94
- full_prompt,
95
- max_new_tokens=1024, # Fortsätt med 1024 eller öka till 2048
96
- num_return_sequences=1,
97
- pad_token_id=self.tokenizer.eos_token_id,
98
- do_sample=True,
99
- top_k=50, top_p=0.95,
100
- temperature=0.7
101
- )[0]['generated_text']
102
-
103
- # Extrahera endast den nya delen av texten (modellens respons efter den sista "Thought:")
104
- new_content = generated_text[len(full_prompt):].strip()
105
- print(f"DEBUG - Full generated_text: \n---START---\n{generated_text}\n---END---")
106
- print(f"DEBUG - Extracted new_content: '{new_content}'")
107
-
108
- # Kontrollera om modellen genererade ett svar som en 'Answer:'
109
- if "Answer:" in new_content:
110
- final_answer = new_content.split("Answer:", 1)[1].strip()
111
- print(f"Final answer from model:\n{final_answer}")
112
- return final_answer # Returnera det slutgiltiga svaret
113
-
114
- elif "<TOOL_CODE>" in new_content and "</TOOL_CODE>" in new_content:
115
- # Modellen genererade ett verktygskall.
116
- # Vi vill inte inkludera modellens egna "Observation:" eller "Tool:"-text i historiken
117
- # innan verktyget faktiskt körts. Vi tar bara själva tool_code strängen.
118
-
119
- tool_call_start = new_content.find("<TOOL_CODE>")
120
- tool_call_end = new_content.find("</TOOL_CODE>") + len("</TOOL_CODE>")
121
-
122
- # Försök att extrahera tanken som ledde till verktygskallet
123
- thought_part = ""
124
- if "Thought:" in new_content[:tool_call_start]:
125
- thought_part = new_content.split("Thought:", 1)[1].split("Tool:", 1)[0].strip()
126
- elif tool_call_start > 0: # Om det finns text före tool code
127
- thought_part = new_content[:tool_call_start].strip()
128
-
129
- tool_code_section = new_content[tool_call_start:tool_call_end]
130
- tool_call_str = tool_code_section.replace("<TOOL_CODE>", "").replace("</TOOL_CODE>", "").strip()
131
-
132
- print(f"Tool call detected: {tool_call_str}")
133
-
134
- try:
135
- if tool_call_str.startswith("search_tavily("):
136
- query = tool_call_str[len("search_tavily("):-1].strip().strip('"').strip("'")
137
- tool_output = search_tavily(query)
138
- print(f"Tool result: {tool_output[:200]}...")
139
-
140
- # Lägg till tanken, verktygskallet och det FAKTISKA observationen till historiken
141
- current_response_history += f"\n\nThought: {thought_part}\nTool: {tool_code_section}\nObservation: {tool_output}\n"
142
- else:
143
- tool_output = f"Unknown tool: {tool_call_str}"
144
- print(f"Error: {tool_output}")
145
- current_response_history += f"\n\nThought: {thought_part}\nTool: {tool_code_section}\nObservation: {tool_output}\n"
146
- except Exception as tool_e:
147
- tool_output = f"Error running tool {tool_call_str}: {tool_e}"
148
- print(f"Error: {tool_output}")
149
- current_response_history += f"\n\nThought: {thought_part}\nTool: {tool_code_section}\nObservation: {tool_output}\n"
150
- else:
151
- # Modellen genererade varken ett verktygskall eller ett slutgiltigt svar.
152
- # Lägg till det den faktiskt genererade till historiken så den kan fortsätta sin tanke.
153
- current_response_history += f"\n\nThought: {new_content}\n"
154
- print(f"Model generated non-tool/non-answer content. Appending: {new_content[:100]}...")
155
-
156
- # Om max_iterations nås utan slutgiltigt svar
157
- return "Agent could not complete the task within the allowed iterations. Latest relevant content: " + \
158
- (current_response_history[-500:] if current_response_history else "No meaningful content generated.")
159
-
 
1
  import os
2
+ import torch
3
+ from huggingface_hub import InferenceClient
4
 
5
+ # Importera smolagents komponenter
6
+ from smolagents import ToolCallingAgent, Tool, InferenceClientModel
7
+
8
+ # Importera dina befintliga, anpassade verktygsfunktioner
9
+ # Se till att dessa filer (tavily_search.py, asr_tool.py, etc.) finns i samma katalog eller är korrekt importerbara.
10
+ from tavily_search import search_tavily
11
+ from asr_tool import transcribe_audio
12
+ from excel_tool import analyze_excel
13
+ from math_tool import calculate_math
14
 
15
  class GaiaAgent:
16
  def __init__(self, model_id: str = "google/gemma-2b-it"):
17
+ """
18
+ Initialiserar GaiaAgent, som nu använder smolagents.ToolCallingAgent internt.
19
+ """
20
+ print(f"Initialiserar GaiaAgent med modell: {model_id}")
21
+
22
+ # Säkerställ att Hugging Face token är tillgänglig från miljön
23
+ hf_token = os.getenv("HF_TOKEN") or os.getenv("HUGGING_FACE_HUB_TOKEN")
24
+ if not hf_token:
25
+ raise ValueError(
26
+ "Hugging Face token (HF_TOKEN eller HUGGING_FACE_HUB_TOKEN) är inte konfigurerad i miljövariabler."
27
+ "Vänligen lägg till din token som en 'Repository secret' i dina Space-inställningar."
 
 
 
 
28
  )
 
29
 
30
+ # Initialisera InferenceClientModel för att kommunicera med Hugging Face Inference API
31
+ try:
32
+ # InferenceClientModel ansluter till en fjärrmodell, så lokal laddning av tokenizer/modell tas bort.
33
+ self.llm_model = InferenceClientModel(
34
+ model=InferenceClient(model=model_id, token=hf_token)
 
35
  )
36
+ print("InferenceClientModel laddad framgångsrikt.")
 
37
  except Exception as e:
38
+ raise RuntimeError(
39
+ f"Misslyckades att initialisera InferenceClientModel: {e}."
40
+ "Vänligen kontrollera din HF token och att modellen är tillgänglig/laddningsbar."
41
+ )
42
 
43
+ # Definiera dina anpassade verktyg som smolagents.Tool objekt
44
+ # Detta gör dem kompatibla med ToolCallingAgent.
45
+ tools_list = [
46
+ Tool(
47
+ name="search_tavily",
48
+ description="Användbart för att söka information online med Tavily Search. Returnerar en sammanfattning av de mest relevanta resultaten från webben. Kräver en fråga som input.",
49
+ function=search_tavily
50
+ ),
51
+ Tool(
52
+ name="transcribe_audio",
53
+ description="Transkriberar ljudfil till text. Användbart för att omvandla tal till text från en angiven ljudfilsväg. Kräver en filsökväg till ljudfilen som input.",
54
+ function=transcribe_audio
55
+ ),
56
+ Tool(
57
+ name="analyze_excel",
58
+ description="Analysera Excel-filer och returnera detaljerad information om rader, kolumner, datatyper och statistik (summa, medelvärde, max, min för numeriska kolumner). Kan ta både en lokal filväg eller en URL till Excel-filen som input.",
59
+ function=analyze_excel
60
+ ),
61
+ Tool(
62
+ name="calculate_math",
63
+ description="Beräkna matematiska uttryck. Användbart för att utföra aritmetiska operationer som addition, subtraktion, multiplikation, division och potenser. Tar ett matematiskt uttryck som en sträng som input.",
64
+ function=calculate_math
65
+ )
66
+ ]
67
+ print(f"Laddade {len(tools_list)} anpassade verktyg.")
68
+
69
+ # Initialisera ToolCallingAgent med dina verktyg och din modell
70
+ self.agent = ToolCallingAgent(
71
+ tools=tools_list,
72
+ model=self.llm_model,
73
+ verbosity_level=2 # Ställ in detaljnivå för att se agentens tankeprocess
74
+ )
75
+ print("ToolCallingAgent initialiserad.")
76
+
77
+ def process_task(self, task_prompt: str) -> str:
78
  """
79
+ Bearbetar en uppgift med den interna ToolCallingAgent.
80
+ Denna metod ersätter den tidigare manuella verktygsexekveringsloopen.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  """
82
+ print(f"\nBearbetar uppgift med ToolCallingAgent: '{task_prompt}'")
83
+ try:
84
+ final_answer = self.agent.run(task_prompt)
85
+ print(f"\nToolCallingAgent avslutad. Slutgiltigt svar: {final_answer}")
86
+ return final_answer
87
+ except Exception as e:
88
+ error_message = f"Ett fel uppstod under agentens bearbetning: {e}"
89
+ print(error_message)
90
+ return f"Agenten kunde inte slutföra uppgiften på grund av ett fel: {error_message}"
91
+