2.2 Components d'un Agent en Detall¶
Objectiu
Analitzar en profunditat cada component d'un agent: el LLM com a motor de raonament, el sistema de prompts, la integració d'eines, i l'executor que ho coordina tot.
🧠 Component 1: El Motor de Raonament (LLM)¶
El System Prompt¶
El system prompt defineix la "personalitat" i capacitats de l'agent:
SYSTEM_PROMPT = """
Ets un assistent tècnic expert en administració de sistemes (ASIX).
CAPACITATS:
- Pots buscar informació tècnica actualitzada a internet
- Pots executar comandes de diagnòstic
- Pots llegir i analitzar fitxers de log
LIMITACIONS:
- No executes mai comandes destructives sense confirmació
- Si no tens certesa, dius "No ho sé" en lloc d'inventar
FORMAT: Respostes en català. Scripts en blocs de codi.
"""
from langchain.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", SYSTEM_PROMPT),
("placeholder", "{chat_history}"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
Temperatura i Paràmetres¶
from langchain_openai import ChatOpenAI
# Agents → temperatura 0 (determinista, segueix instruccions de format)
llm_agent = ChatOpenAI(model="gpt-4o", temperature=0, max_tokens=2000)
# Generació creativa → temperatura alta
llm_creatiu = ChatOpenAI(model="gpt-4o", temperature=0.8)
🔧 Component 2: Les Eines (Tools)¶
Definir Eines amb Pydantic (recomanat)¶
from langchain.tools import BaseTool
from pydantic import BaseModel, Field
from typing import Optional, Type
class ConsultaBDInput(BaseModel):
taula: str = Field(description="Taula: alumnes, notes, assignatures, grups")
condicio: Optional[str] = Field(default=None, description="Condició WHERE SQL")
limit: int = Field(default=10, ge=1, le=100)
class ConsultaBDTool(BaseTool):
name: str = "consulta_bd_alumnes"
description: str = (
"Consulta la base de dades d'alumnes. "
"ÚNICAMENT per a lectura, mai per a modificar dades."
)
args_schema: Type[BaseModel] = ConsultaBDInput
def _run(self, taula: str, condicio: Optional[str] = None, limit: int = 10) -> str:
import sqlite3
taules_permeses = {"alumnes", "notes", "assignatures", "grups"}
if taula not in taules_permeses:
return f"Error: taula '{taula}' no accessible."
try:
conn = sqlite3.connect("institut.db")
cursor = conn.cursor()
query = f"SELECT * FROM {taula}"
if condicio:
query += f" WHERE {condicio}"
query += f" LIMIT {limit}"
cursor.execute(query)
rows = cursor.fetchall()
if not rows:
return "No s'han trobat resultats."
columns = [d[0] for d in cursor.description]
lines = [", ".join(columns)] + [", ".join(str(v) for v in r) for r in rows]
return f"{len(rows)} files:\n" + "\n".join(lines)
except sqlite3.Error as e:
return f"Error BD: {e}"
finally:
conn.close()
async def _arun(self, *args, **kwargs):
raise NotImplementedError
Eines Pre-construïdes de LangChain¶
# pip install langchain-community
from langchain_community.tools import DuckDuckGoSearchResults, WikipediaQueryRun
from langchain_community.agent_toolkits import FileManagementToolkit
# Eines de fitxers (confinades a un directori segur)
file_tools = FileManagementToolkit(
root_dir="/tmp/agent_workspace",
selected_tools=["read_file", "write_file", "list_directory"]
).get_tools()
🔄 Component 3: L'Executor¶
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o", temperature=0)
agent = create_tool_calling_agent(llm, tools, prompt)
executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True,
max_iterations=10,
max_execution_time=60,
handle_parsing_errors=True,
return_intermediate_steps=True,
)
# Conversa multi-torn
from langchain_core.messages import HumanMessage, AIMessage
chat_history = []
def chat(message: str) -> str:
result = executor.invoke({"input": message, "chat_history": chat_history})
chat_history.extend([
HumanMessage(content=message),
AIMessage(content=result["output"])
])
return result["output"]
print(chat("Quin és el port per defecte de SSH?"))
print(chat("I com el canviaria a 2222?")) # Recorda el context!
📊 El Context en Cada Iteració¶
┌──────────────────────────────────────────┐
│ [SYSTEM PROMPT] ~500-2000 tokens │
│ [HISTORIAL] creix amb el temps │
│ [SCRATCHPAD] Thought/Action/Obs │
│ [MISSATGE ACTUAL] la pregunta nova │
└──────────────────────────────────────────┘
✅ Activitats¶
Exercici 2.2.1 — System Prompt per ASIX
Crea un system prompt per a un agent d'administració de xarxa. Ha d'incloure: rol, capacitats, limitacions de seguretat, format de resposta, i instruccions per quan no sap la resposta.
Exercici 2.2.2 — Eina ping_host
Implementa una eina que executi ping real a un host, retorni el temps de resposta, i gestioni errors (host inexistent, timeout). Integra-la en un agent.
Exercici 2.2.3 — Anàlisi del Context
Amb return_intermediate_steps=True, per a una tasca de 5+ iteracions, calcula quants tokens consumeix cada part del context per iteració.