| 63 | logger.info("✅ Ready!") |
| 64 | |
| 65 | async def run(self, user_txt_input: str) -> dict: |
| 66 | step = 0 |
| 67 | start_time = time.perf_counter() |
| 68 | tokens = Tokens(worker=LLMTokens(0, 0, 0)) |
| 69 | try: |
| 70 | while not self.agent_backend.is_finished(): |
| 71 | step += 1 |
| 72 | logger.info(f"Step {step} - Calling LLM...") |
| 73 | response = await self.openai.chat.completions.create( |
| 74 | model="gpt-4.1", |
| 75 | messages=self.agent_backend.messages, |
| 76 | tools=self.agent_backend.get_tools(), |
| 77 | tool_choice=self.agent_backend.tool_choice, |
| 78 | temperature=0, |
| 79 | ) |
| 80 | if hasattr(response, "usage"): |
| 81 | tokens.worker.prompt_tokens += response.usage.prompt_tokens |
| 82 | tokens.worker.completion_tokens += response.usage.completion_tokens |
| 83 | tokens.worker.total_tokens += response.usage.total_tokens |
| 84 | |
| 85 | self.agent_backend.add_messages(response.model_dump()) |
| 86 | self.agent_backend.report_execution_metrics(llm_tokens=tokens, ai_model="gpt-4.1") |
| 87 | tool_calls = self.agent_backend.extract_tool_calls(response.model_dump()) |
| 88 | |
| 89 | if tool_calls: |
| 90 | logger.info(f"Executing {len(tool_calls)} tools...") |
| 91 | tool_results = await asyncio.to_thread(self.agent_backend.run_tools, tool_calls) |
| 92 | for res in tool_results: |
| 93 | emoji = "✅" if res.is_success else "❌" |
| 94 | logger.info(f"Tool result: {emoji} {res.function_name}") |
| 95 | |
| 96 | duration = time.perf_counter() - start_time |
| 97 | logger.info(f"Done! Duration: {duration:.1f}s | Total tokens: {tokens.worker.total_tokens}") |
| 98 | result = self.agent_backend.retrieve_execution_result() |
| 99 | return {"result": result.result, "thread_id": result.memory_thread_id} |
| 100 | except Exception as e: |
| 101 | logger.error(f"Exception: {e}") |
| 102 | raise |
| 103 | |
| 104 | |
| 105 | # === Load Configuration === |