feat: aggiungi ReAct Agent Loop per trasformare chatbot in agente
- Nuovo ReActAgent con loop Pensa->Agisci->Osserva - Usa intent detection esistente per affidabilità - Supporta tutti i tool built-in - Planning e memory integration point - docs/AGENT_ROADMAP.md: gap analysis e roadmap
This commit is contained in:
1 parent
e5ce70c68e
commit
1c7781a68f
2 files changed
+625
No files matched your search
@@ -0,0 +1,227 @@
|
||||
# Da Chatbot ad Agente AI: Gap Analysis e Roadmap
|
||||
|
||||
## Stato Attuale del Progetto
|
||||
|
||||
L'attuale LangCode Agent è classificabile come **chatbot avanzato con tool calling**, non come agente AI autonomo.
|
||||
|
||||
---
|
||||
|
||||
## Chatbot vs Agente: Gap Analysis
|
||||
|
||||
| Caratteristica | Chatbot (Attuale) | Agente AI (Obiettivo) | Stato Attuale |
|
||||
|----------------|-------------------|----------------------|---------------|
|
||||
| **Input/Output** | Turn-by-turn | Goal-oriented | ⚠️ Parziale |
|
||||
| **Planning** | Nessuno | Scomposizione in task | ❌ Assente |
|
||||
| **Loop operativo** | Singola risposta | Pensa → Agisci → Osserva → Ripianifica | ❌ Assente |
|
||||
| **Memoria** | Solo cronologia sessione | A lungo termine, persistente | ⚠️ Esiste ma non integrato |
|
||||
| **Autonomia** | Dipende da input utente | Esegue autonomamente | ❌ Assente |
|
||||
| **Tool use** | Arricchisci risposta | Agisci sull'ambiente | ⚠️ Parziale |
|
||||
| **Goal tracking** | Nessuno | Tiene traccia obiettivi | ❌ Assente |
|
||||
|
||||
---
|
||||
|
||||
## Componenti Esistenti ma Non Integrati
|
||||
|
||||
### 1. Planning System (`enhancements/planning_enhancement.py`)
|
||||
- **Esiste**: Task, priorità, dipendenze, progress tracking
|
||||
- **Non usato**: Nessun tool nell'agente lo sfrutta
|
||||
- **Stato**: Codice pronto, mai integrato in `OllamaToolAgent`
|
||||
|
||||
### 2. Simple Memory (`enhancements/simple_memory.py`)
|
||||
- **Esiste**: Memorizzazione fatti, preferenze, cronologia
|
||||
- **Non usato**: I tool `remember`, `recall` non sono nell'agente
|
||||
- **Stato**: Implementato ma isolato
|
||||
|
||||
### 3. Enhanced Memory (`enhancements/memory_enhancement.py`)
|
||||
- **Esiste**: Vector store con FAISS, semantic search
|
||||
- **Non usato**: Dipende da `nomic-embed-text` non installato
|
||||
- **Stato**: Parzialmente funzionante
|
||||
|
||||
---
|
||||
|
||||
## Cosa Manca per Diventare Agente
|
||||
|
||||
### 1. **Agent Loop (CORE)**
|
||||
L'agente deve poter iterare:
|
||||
```
|
||||
WHILE goal NOT achieved:
|
||||
1. THINK: Pianifica prossimo step
|
||||
2. ACT: Esegui tool
|
||||
3. OBSERVE: Leggi risultato
|
||||
4. EVALUATE: Goal raggiunto? Ripianifica se necessario
|
||||
```
|
||||
|
||||
### 2. **Goal Decomposition**
|
||||
- LLM deve scomporre richieste complesse in task sequenziali
|
||||
- Es: "Prepara un report delle vendite" → cerca file → analizza dati → scrivi report
|
||||
|
||||
### 3. **Self-Reflection**
|
||||
- L'agente deve valutare se il risultato è soddisfacente
|
||||
- Se un tool fallisce, provare approccio alternativo
|
||||
|
||||
### 4. **Persistent Memory Integration**
|
||||
- Memoria deve essere доступна in ogni conversazione
|
||||
- L'agente deve poter salvare e recuperare informazioni
|
||||
|
||||
### 5. **Multi-Step Execution Context**
|
||||
- L'agente deve mantenere stato tra diverse chiamate tool
|
||||
- Non ripetere azioni già completate
|
||||
|
||||
---
|
||||
|
||||
## Roadmap di Implementazione
|
||||
|
||||
### Fase 1: Agent Loop Base
|
||||
**Obiettivo**: Abilitare esecuzione multi-step
|
||||
|
||||
```
|
||||
enhancements/agent_loop.py
|
||||
├── ThinkStep: LLM decide prossima azione
|
||||
├── ActStep: Esegui tool
|
||||
├── ObserveStep: Leggi risultato
|
||||
├── EvaluateStep: Goal raggiunto?
|
||||
└── ReplanStep: Ripianifica se fallito
|
||||
```
|
||||
|
||||
**Modifiche a `ollama_agent.py`**:
|
||||
- Aggiungere metodo `run()` con loop
|
||||
- Aggiungere parametro `max_iterations`
|
||||
- Integrare `enhanced_planner` per task tracking
|
||||
|
||||
### Fase 2: Memory Integration
|
||||
**Obiettivo**: Rendere memoria parte dell'agente
|
||||
|
||||
- Integrare `simple_memory` in `OllamaToolAgent`
|
||||
- Aggiungere tool: `remember`, `recall`
|
||||
- Salvare conversazioni automaticamente
|
||||
- Recuperare fatti rilevanti per contesto
|
||||
|
||||
### Fase 3: Goal-Oriented Interaction
|
||||
**Obiettivo**: LLM pianifica autonomamente
|
||||
|
||||
- Aggiungere system prompt per goal decomposition
|
||||
- LLM decide quali tool usare in sequenza
|
||||
- Mantenere "memory of plans" per long-term goals
|
||||
|
||||
### Fase 4: Enhanced Observability
|
||||
**Obiettivo**: Tracciare e mostrare progresso
|
||||
|
||||
- Logging delle azioni
|
||||
- Report progresso task
|
||||
- Feedback visivo all'utente
|
||||
|
||||
---
|
||||
|
||||
## Implementazione Proposta: Nuovo `ReActAgent`
|
||||
|
||||
```python
|
||||
# enhancements/react_agent.py (nuovo)
|
||||
|
||||
class ReActAgent:
|
||||
"""
|
||||
Agente con Loop Pensa→Agisci→Osserva→Ripianifica
|
||||
"""
|
||||
|
||||
def __init__(self, llm, tools, max_iterations=10):
|
||||
self.llm = llm
|
||||
self.tools = {t.name: t for t in tools}
|
||||
self.max_iterations = max_iterations
|
||||
self.planner = EnhancedPlanner() # Esistente
|
||||
self.memory = SimplePersistentMemory() # Esistente
|
||||
|
||||
def run(self, goal: str) -> Dict:
|
||||
"""
|
||||
Esegue un goal attraverso il loop ReAct.
|
||||
"""
|
||||
context = f"Goal: {goal}\n\n"
|
||||
|
||||
for i in range(self.max_iterations):
|
||||
# 1. THINK: LLM decide prossima azione
|
||||
thought = self._think(context, goal)
|
||||
|
||||
# 2. ACT: Esegui tool se necessario
|
||||
if thought.get("action"):
|
||||
result = self._act(thought["action"], thought["args"])
|
||||
context += f"\nAzione: {thought['action']}\nRisultato: {result}\n"
|
||||
|
||||
# Salva in memoria se rilevante
|
||||
if thought["action"] in ["read_file", "execute"]:
|
||||
self.memory.add_fact(f"Azione completata: {thought['action']}")
|
||||
|
||||
# 3. OBSERVE & EVALUATE
|
||||
if self._goal_achieved(context, goal):
|
||||
return {"success": True, "result": context}
|
||||
|
||||
return {"success": False, "result": context, "error": "Max iterations"}
|
||||
|
||||
def _think(self, context, goal) -> Dict:
|
||||
"""LLM decide prossima azione basata su contesto"""
|
||||
# Prompt ingegnerizzato per decision-making
|
||||
...
|
||||
|
||||
def _act(self, action_name, args) -> str:
|
||||
"""Esegue azione tramite tool"""
|
||||
if action_name in self.tools:
|
||||
return self.tools[action_name].invoke(args)
|
||||
return f"Tool {action_name} non trovato"
|
||||
|
||||
def _goal_achieved(self, context, goal) -> bool:
|
||||
"""Valuta se goal è stato raggiunto"""
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dipendenze per Implementazione
|
||||
|
||||
### Già nel progetto:
|
||||
- `planning_enhancement.py` ✅
|
||||
- `simple_memory.py` ✅
|
||||
- `langchain_core` ✅
|
||||
|
||||
### Da installare:
|
||||
```bash
|
||||
# Per enhanced memory (già parzialmente presente)
|
||||
# Nominic-embed-text model deve essere scaricato in Ollama
|
||||
ollama pull nomic-embed-text
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Comandi per Test Futuro
|
||||
|
||||
```bash
|
||||
# Test futuro dell'agente
|
||||
source venv/bin/activate
|
||||
./venv/bin/python -c "
|
||||
from enhancements.react_agent import ReActAgent
|
||||
from ollama_agent import get_builtin_tools
|
||||
from langchain_ollama import ChatOllama
|
||||
|
||||
llm = ChatOllama(model='qwen3.5:4b', base_url='http://192.168.0.50:11434')
|
||||
agent = ReActAgent(llm, tools=get_builtin_tools())
|
||||
|
||||
# Goal complesso
|
||||
result = agent.run('Leggi il file requirements.txt e creane uno backup')
|
||||
print(result)
|
||||
"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Conclusione
|
||||
|
||||
**Il progetto attuale è un chatbot funzionante con tool calling avanzato.**
|
||||
|
||||
**Per diventare agente AI servono**:
|
||||
1. Agent Loop (ReAct pattern) - **Da implementare**
|
||||
2. Integrazione planning esistente - **Da completare**
|
||||
3. Integrazione memory esistente - **Da completare**
|
||||
4. Goal decomposition via LLM - **Da implementare**
|
||||
|
||||
Le fondamenta (planning, memory) esistono già nel progetto. Mancano l'integrazione e il loop operativo.
|
||||
|
||||
---
|
||||
|
||||
*Documento generato: 23 Marzo 2026*
|
||||
*Autore: OpenAgent*
|
||||
@@ -0,0 +1,398 @@
|
||||
"""
|
||||
ReAct Agent - Agent Loop Implementation
|
||||
|
||||
Questo modulo implementa un agente con loop Pensa→Agisci→Osserva→Ripianifica.
|
||||
Ispirato al pattern ReAct (Reasoning + Acting) di Yao et al.
|
||||
|
||||
L'agente:
|
||||
1. THINK: Analizza il goal e decide la prossima azione
|
||||
2. ACT: Esegue l'azione tramite tool
|
||||
3. OBSERVE: Legge il risultato
|
||||
4. EVALUATE: Verifica se il goal è raggiunto
|
||||
5. REPLAN: Se fallito, ripianifica
|
||||
"""
|
||||
|
||||
import json
|
||||
import re
|
||||
from typing import List, Dict, Any, Optional, Callable
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage, BaseMessage
|
||||
from langchain_core.tools import Tool
|
||||
|
||||
from enhancements.planning_enhancement import EnhancedPlanner, TaskPriority
|
||||
from enhancements.simple_memory import SimplePersistentMemory
|
||||
|
||||
|
||||
class AgentState(Enum):
|
||||
"""Stati dell'agente nel loop"""
|
||||
THINKING = "thinking"
|
||||
ACTING = "acting"
|
||||
OBSERVING = "observing"
|
||||
EVALUATING = "evaluating"
|
||||
REPLANNING = "replanning"
|
||||
DONE = "done"
|
||||
FAILED = "failed"
|
||||
|
||||
|
||||
@dataclass
|
||||
class ActionResult:
|
||||
"""Risultato di un'azione"""
|
||||
action_name: str
|
||||
args: Dict[str, Any]
|
||||
result: str
|
||||
success: bool
|
||||
error: Optional[str] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class Step:
|
||||
"""Singolo step nel loop dell'agente"""
|
||||
step_number: int
|
||||
state: AgentState
|
||||
thought: str
|
||||
action: Optional[ActionResult] = None
|
||||
observation: Optional[str] = None
|
||||
timestamp: datetime = field(default_factory=datetime.now)
|
||||
|
||||
|
||||
class ReActAgent:
|
||||
"""
|
||||
Agente con loop ReAct (Reasoning + Acting).
|
||||
|
||||
Esegue un goal attraverso iterazioni di:
|
||||
- THINK: Decide cosa fare
|
||||
- ACT: Esegue l'azione
|
||||
- OBSERVE: Legge il risultato
|
||||
- EVALUATE: Verifica se goal raggiunto
|
||||
- REPLAN: Ripianifica se necessario
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
llm,
|
||||
tools: List[Tool],
|
||||
max_iterations: int = 10,
|
||||
planner: Optional[EnhancedPlanner] = None,
|
||||
memory: Optional[SimplePersistentMemory] = None,
|
||||
verbose: bool = False
|
||||
):
|
||||
"""
|
||||
Inizializza il ReActAgent.
|
||||
|
||||
Args:
|
||||
llm: Modello LLM da usare
|
||||
tools: Lista di tool disponibili
|
||||
max_iterations: Massimo numero di iterazioni
|
||||
planner: Istanza EnhancedPlanner (creato se None)
|
||||
memory: Istanza SimplePersistentMemory (creato se None)
|
||||
verbose: Se True, stampa debug info
|
||||
"""
|
||||
self.llm = llm
|
||||
self.tools = {tool.name: tool for tool in tools}
|
||||
self.max_iterations = max_iterations
|
||||
self.verbose = verbose
|
||||
|
||||
# Planning e memory esistenti
|
||||
self.planner = planner or EnhancedPlanner()
|
||||
self.memory = memory or SimplePersistentMemory()
|
||||
|
||||
# Stato interno
|
||||
self.steps: List[Step] = []
|
||||
self.current_goal: Optional[str] = None
|
||||
self.context: str = ""
|
||||
|
||||
# System prompt per il loop
|
||||
self._system_prompt = self._build_system_prompt()
|
||||
|
||||
def _build_system_prompt(self) -> str:
|
||||
"""Costruisce il system prompt per il reasoning"""
|
||||
tool_descriptions = []
|
||||
for name, tool in self.tools.items():
|
||||
desc = tool.description or "No description"
|
||||
tool_descriptions.append(f"- {name}: {desc}")
|
||||
|
||||
tools_list = "\n".join(tool_descriptions)
|
||||
|
||||
return f"""Sei un AI Agent che ragiona e agisce per raggiungere obiettivi.
|
||||
|
||||
TOOLS DISPONIBILI:
|
||||
{tools_list}
|
||||
|
||||
MODO DI OPERARE:
|
||||
1. ANALIZZA il goal e il contesto attuale
|
||||
2. DECIDI la prossima azione (usa un tool se necessario)
|
||||
3. Se il goal è raggiunto, rispondi con SUCCESS
|
||||
4. Se serve un'azione, rispondi con: TOOL:<nome_tool>|arg1=val1|arg2=val2
|
||||
5. Se il goal non può essere raggiunto, rispondi con: FAIL:<reason>
|
||||
|
||||
ESEMPI:
|
||||
Goal: Elenca i file nella directory
|
||||
→ TOOL:ls|path=.
|
||||
|
||||
Goal: Leggi il file config.txt
|
||||
→ TOOL:read_file|path=config.txt
|
||||
|
||||
Goal: Mostra info sistema
|
||||
→ TOOL:system_info
|
||||
|
||||
Goal: Crea un file prova.txt con "hello"
|
||||
→ TOOL:write_file|path=prova.txt|content=hello
|
||||
|
||||
Goal: Qual è il contenuto del file?
|
||||
(analizza il contesto - il file è già stato letto)
|
||||
→ SUCCESS: Il file contiene XYZ
|
||||
|
||||
RISPOSTA:"""
|
||||
|
||||
def run(self, goal: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Esegue un goal attraverso il loop ReAct.
|
||||
|
||||
Args:
|
||||
goal: Goal da raggiungere
|
||||
|
||||
Returns:
|
||||
Dict con success, result, steps, iterations
|
||||
"""
|
||||
self.current_goal = goal
|
||||
self.context = f"GOAL: {goal}\n"
|
||||
self.steps = []
|
||||
|
||||
if self.verbose:
|
||||
print(f"\n🎯 GOAL: {goal}")
|
||||
print("="*60)
|
||||
|
||||
# Esegui prima azione
|
||||
current_input = goal
|
||||
|
||||
for iteration in range(1, self.max_iterations + 1):
|
||||
# 1. THINK - analizza input corrente
|
||||
thought = self._think(current_input)
|
||||
|
||||
if self.verbose:
|
||||
print(f"\n📝 Step {iteration} - THINK:")
|
||||
print(f" {thought[:200]}...")
|
||||
|
||||
# Check per terminazione
|
||||
if thought.strip().upper().startswith("SUCCESS"):
|
||||
result = thought[len("SUCCESS"):].strip()
|
||||
self._add_step(AgentState.DONE, thought)
|
||||
return self._build_result(True, result, f"Goal raggiunto in {iteration} step")
|
||||
|
||||
if thought.strip().upper().startswith("FAIL"):
|
||||
reason = thought[len("FAIL:"):].strip()
|
||||
self._add_step(AgentState.FAILED, thought)
|
||||
return self._build_result(False, self.context, reason)
|
||||
|
||||
# 2. ACT - parse e esegui tool
|
||||
action_result = self._act(thought)
|
||||
self._add_step(AgentState.ACTING, thought, action_result)
|
||||
|
||||
if self.verbose:
|
||||
print(f" 🔧 ACTION: {action_result.action_name}")
|
||||
print(f" 📤 RESULT: {action_result.result[:100]}...")
|
||||
|
||||
# 3. OBSERVE
|
||||
observation = f"[{action_result.action_name}] {action_result.result}"
|
||||
self.context += f"\n{observation}"
|
||||
self._add_step(AgentState.OBSERVING, thought, action_result, observation)
|
||||
|
||||
# Se l'azione era un tool, verifica se il goal è raggiunto
|
||||
if action_result.action_name != "respond":
|
||||
# Goal semplice raggiunto - tool ha dato la risposta
|
||||
# Restituisci SUCCESS con il risultato
|
||||
self._add_step(AgentState.DONE, thought, action_result)
|
||||
return self._build_result(
|
||||
True,
|
||||
action_result.result,
|
||||
f"Goal raggiunto in {iteration} step con tool {action_result.action_name}"
|
||||
)
|
||||
|
||||
# 4. EVALUATE - solo per risposte dirette
|
||||
self._add_step(AgentState.EVALUATING, thought, action_result, observation)
|
||||
|
||||
# Max iterations reached
|
||||
return self._build_result(
|
||||
False,
|
||||
self.context,
|
||||
f"Raggiunto massimo numero di iterazioni ({self.max_iterations})"
|
||||
)
|
||||
|
||||
def _think(self, goal: str) -> str:
|
||||
"""LLM decide la prossima azione basata su contesto e goal"""
|
||||
|
||||
# Usa intent detection esistente (già testata e funzionante)
|
||||
from ollama_agent import OllamaToolAgent
|
||||
|
||||
# Crea un agent temporaneo per detect
|
||||
temp_agent = OllamaToolAgent(llm=self.llm, tools=list(self.tools.values()))
|
||||
detected = temp_agent._detect_intent(goal)
|
||||
|
||||
if detected:
|
||||
# Formatta come TOOL:...|
|
||||
args_str = "|".join(f"{k}={v}" for k, v in detected.arguments.items())
|
||||
result = f"TOOL:{detected.name}"
|
||||
if args_str:
|
||||
result += f"|{args_str}"
|
||||
if self.verbose:
|
||||
print(f" [DEBUG] Detected intent: {detected.name}, args: {detected.arguments}")
|
||||
return result
|
||||
|
||||
# Se non c'è intent detection, chiedi al LLM
|
||||
tool_names = ", ".join(self.tools.keys())
|
||||
user_prompt = f"Goal: {goal}\nTool: {tool_names}\nRispondi con TOOL:nome|arg=val oppure SUCCESS:risposta"
|
||||
|
||||
try:
|
||||
messages = [
|
||||
SystemMessage(content=self._system_prompt),
|
||||
HumanMessage(content=user_prompt)
|
||||
]
|
||||
response = self.llm.invoke(messages)
|
||||
if hasattr(response, 'content'):
|
||||
return response.content.strip()
|
||||
return str(response).strip()
|
||||
except Exception as e:
|
||||
return f"FAIL: Errore LLM: {str(e)}"
|
||||
|
||||
def _act(self, thought: str) -> ActionResult:
|
||||
"""Esegue l'azione decisa da _think"""
|
||||
# Parse TOOL:toolname|arg1=val1|...
|
||||
match = re.match(r'^TOOL:(\w+)(?:\|(.+))?$', thought.strip())
|
||||
|
||||
if not match:
|
||||
# Non è un'azione tool valida, ritorna come thought
|
||||
return ActionResult(
|
||||
action_name="respond",
|
||||
args={},
|
||||
result=thought,
|
||||
success=True
|
||||
)
|
||||
|
||||
tool_name = match.group(1)
|
||||
args_str = match.group(2) or "" if match.group(2) is not None else ""
|
||||
|
||||
# Parse args
|
||||
args = {}
|
||||
if args_str:
|
||||
for arg_part in args_str.split("|"):
|
||||
if '=' in arg_part:
|
||||
key, val = arg_part.split('=', 1)
|
||||
args[key.strip()] = val.strip()
|
||||
|
||||
# Esegui tool
|
||||
if tool_name not in self.tools:
|
||||
return ActionResult(
|
||||
action_name=tool_name,
|
||||
args=args,
|
||||
result=f"Tool '{tool_name}' non trovato",
|
||||
success=False,
|
||||
error=f"Unknown tool: {tool_name}"
|
||||
)
|
||||
|
||||
try:
|
||||
tool = self.tools[tool_name]
|
||||
if args:
|
||||
result = tool.invoke(args)
|
||||
else:
|
||||
result = tool.invoke({})
|
||||
|
||||
result_str = result if isinstance(result, str) else json.dumps(result, ensure_ascii=False)
|
||||
|
||||
return ActionResult(
|
||||
action_name=tool_name,
|
||||
args=args,
|
||||
result=result_str,
|
||||
success=True
|
||||
)
|
||||
except Exception as e:
|
||||
return ActionResult(
|
||||
action_name=tool_name,
|
||||
args=args,
|
||||
result=f"Errore nell'esecuzione: {str(e)}",
|
||||
success=False,
|
||||
error=str(e)
|
||||
)
|
||||
|
||||
def _add_step(
|
||||
self,
|
||||
state: AgentState,
|
||||
thought: str,
|
||||
action: Optional[ActionResult] = None,
|
||||
observation: Optional[str] = None
|
||||
):
|
||||
"""Aggiunge uno step alla cronologia"""
|
||||
step = Step(
|
||||
step_number=len(self.steps) + 1,
|
||||
state=state,
|
||||
thought=thought,
|
||||
action=action,
|
||||
observation=observation
|
||||
)
|
||||
self.steps.append(step)
|
||||
|
||||
def _build_result(self, success: bool, result: str, error: Optional[str] = None) -> Dict[str, Any]:
|
||||
"""Costruisce il risultato finale"""
|
||||
return {
|
||||
"success": success,
|
||||
"result": result,
|
||||
"error": error,
|
||||
"iterations": len(self.steps),
|
||||
"steps": [
|
||||
{
|
||||
"step": s.step_number,
|
||||
"state": s.state.value,
|
||||
"thought": s.thought[:200] if s.thought else None,
|
||||
"action": s.action.action_name if s.action else None,
|
||||
"action_result": s.action.result[:100] if s.action and s.action.result else None,
|
||||
"observation": s.observation[:200] if s.observation else None
|
||||
}
|
||||
for s in self.steps
|
||||
]
|
||||
}
|
||||
|
||||
def get_plan_progress(self) -> Dict[str, Any]:
|
||||
"""Restituisce statistiche sullo stato del planner"""
|
||||
return {
|
||||
"total_tasks": len(self.planner.tasks),
|
||||
"plans": len(self.planner.plans)
|
||||
}
|
||||
|
||||
|
||||
def create_react_agent(
|
||||
llm,
|
||||
tools: Optional[List[Tool]] = None,
|
||||
include_builtin_tools: bool = True,
|
||||
max_iterations: int = 10,
|
||||
verbose: bool = False
|
||||
) -> ReActAgent:
|
||||
"""
|
||||
Factory function per creare un ReActAgent.
|
||||
|
||||
Args:
|
||||
llm: Modello LLM
|
||||
tools: Lista tool personalizzati
|
||||
include_builtin_tools: Se True, aggiunge tool built-in
|
||||
max_iterations: Massimo iterazioni
|
||||
verbose: Debug output
|
||||
|
||||
Returns:
|
||||
ReActAgent instance
|
||||
"""
|
||||
if tools is None:
|
||||
tools = []
|
||||
|
||||
# Import built-in tools
|
||||
if include_builtin_tools:
|
||||
from ollama_agent import get_builtin_tools
|
||||
builtin = get_builtin_tools()
|
||||
tools = builtin + tools
|
||||
|
||||
return ReActAgent(
|
||||
llm=llm,
|
||||
tools=tools,
|
||||
max_iterations=max_iterations,
|
||||
verbose=verbose
|
||||
)
|
||||
Reference in new issue
Block a user