4.1 Patrons de Planificació d'Agents¶
Per Què Planificació?
Un LLM sense planificació és com un programador que escriu tot el codi en una sola funció. La planificació permet descompondre tasques complexes, adaptar-se als resultats, i detectar errors en el flux d'execució.
📋 El Problema de la Planificació¶
Per a tasques simples, un agent pot respondre directament. Però per a tasques complexes cal descompondre:
Tasca complexa: "Analitza la seguretat del servidor web de l'empresa
i genera un informe amb recomanacions"
Sense planificació:
→ L'agent intenta fer-ho tot d'una sola vegada → resposta vaga i incompleta
Amb planificació:
1. Identificar el servidor web (IP, domini)
2. Escanejar ports oberts (nmap conceptual)
3. Comprovar versions de serveis (Apache, Nginx, PHP...)
4. Cercar CVEs per les versions trobades
5. Analitzar configuració SSL/TLS
6. Generar recomanacions per gravetat
7. Redactar informe final
🔄 Patró 1: ReAct (Reason + Act) — Planificació Iterativa¶
Ja vist a la Unitat 4.2. El patró més usat. L'agent planifica un pas cada vegada, observa el resultat, i decideix el pròxim pas.
Quan usar-lo: Tasques on no es pot saber tota la seqüència d'accions a priori.
📋 Patró 2: Plan-and-Execute — Planificació Explícita¶
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
# Fase 1: PLANIFICACIÓ (genera tot el pla primer)
PLANNING_PROMPT = PromptTemplate(
template="""Ets un expert planificador. Per a la tasca donada,
genera un pla detallat d'accions a executar.
Tasca: {task}
Eines disponibles: {tools}
Genera un pla pas a pas en format JSON:
[
{{"pas": 1, "accio": "...", "eina": "...", "input": "..."}},
{{"pas": 2, "accio": "...", "eina": "...", "input": "..."}}
]
Pla:""",
input_variables=["task", "tools"]
)
llm = ChatOpenAI(model="gpt-4o", temperature=0)
planner = LLMChain(llm=llm, prompt=PLANNING_PROMPT)
# Exemple d'ús
tools_desc = "cerca_web, calculadora, ping_host, comprovar_port"
pla = planner.invoke({
"task": "Verifica que el servidor web de sapalomera.cat funciona correctament",
"tools": tools_desc
})
# Pla generat (exemple):
# [
# {"pas": 1, "accio": "Resoldre IP", "eina": "cerca_web", "input": "sapalomera.cat IP address"},
# {"pas": 2, "accio": "Ping al servidor", "eina": "ping_host", "input": "sapalomera.cat"},
# {"pas": 3, "accio": "Comprovar port 80", "eina": "comprovar_port", "input": "sapalomera.cat:80"},
# {"pas": 4, "accio": "Comprovar port 443", "eina": "comprovar_port", "input": "sapalomera.cat:443"}
# ]
# Fase 2: EXECUCIÓ (executa el pla)
import json
pla_parsed = json.loads(pla["text"])
for step in pla_parsed:
print(f"\nPas {step['pas']}: {step['accio']}")
# Executar l'eina corresponent...
Quan usar-lo: Tasques estructurades on el pla és predictible i les eines sempre les mateixes.
🌳 Patró 3: Tree of Thoughts (ToT) — Explorar Múltiples Camins¶
Extensió de CoT que explora múltiples raonaments en paral·lel i selecciona el millor.
┌─── Enfocament A ──► Resultat A (avaluat: 7/10)
Problema ─┤
├─── Enfocament B ──► Resultat B (avaluat: 9/10) ← SELECCIONAT
│
└─── Enfocament C ──► Resultat C (avaluat: 5/10)
Quan usar-lo: Problemes de disseny, decisions estratègiques, problemes matemàtics complexos.
🔁 Patró 4: Reflexion — Aprendre dels Errors¶
# L'agent genera una resposta → la critica → la millora iterativament
ACTOR_PROMPT = "Respon la pregunta: {question}"
CRITIC_PROMPT = """Critica la resposta següent.
Identifica: errors factuals, mancances, millores possibles.
Resposta: {response}
Crítica:"""
REFINE_PROMPT = """Millora la resposta original basant-te en la crítica.
Resposta original: {response}
Crítica: {critique}
Resposta millorada:"""
def reflexion_agent(question: str, iterations: int = 2) -> str:
"""Genera, critica i millora iterativament una resposta."""
response = llm.invoke(ACTOR_PROMPT.format(question=question)).content
for i in range(iterations):
critique = llm.invoke(CRITIC_PROMPT.format(response=response)).content
response = llm.invoke(REFINE_PROMPT.format(
response=response, critique=critique
)).content
print(f"Iteració {i+1}: resposta millorada")
return response
# Exemple
answer = reflexion_agent(
"Explica els avantatges i desavantatges d'usar Docker en producció",
iterations=2
)
📊 Comparativa de Patrons¶
| Patró | Complexitat | Cost Tokens | Millor Per a |
|---|---|---|---|
| ReAct | Baixa | Mig | Tasques generals amb eines |
| Plan-and-Execute | Mitja | Mig-Alt | Tasques estructurades predictibles |
| Tree of Thoughts | Alta | Alt | Decisions complexes, múltiples opcions |
| Reflexion | Mitja | Alt | Quan la qualitat és crítica |
| Multi-Agent | Alta | Molt Alt | Tasques que requereixen especialització |
✅ Activitats¶
Exercici 4.1.1 — Implementar Plan-and-Execute
Implementa un agent Plan-and-Execute per a la tasca: "Comprova que tots els serveis crítics d'un servidor estan actius i genera un report." El pla ha d'adaptar-se als resultats intermedis.
Exercici 4.1.2 — Reflexion per a Documentació
Implementa un agent Reflexion que generi documentació tècnica per a una funció Python. Executa 3 iteracions i compara la qualitat entre la versió inicial i la final.
Exercici 4.1.3 — Comparativa Empírica
Per a la mateixa tasca complexa (p.ex. "Dissenya l'arquitectura de xarxa per a un aula informàtica de 30 equips"), compara la qualitat de les respostes amb: (a) LLM directe, (b) ReAct, (c) Reflexion. Quines diferències observes?