Agenți: FunctionAgent, ReActAgent și AgentWorkflow în LlamaIndex & Data RAG

Agenții din llama_index.core.agent.workflow: un LLM care primește unelte (funcții Python, motoare de interogare) și le apelează într-o buclă până poate răspunde; AgentWorkflow leagă mai mulți agenți care își predau controlul.

Sintaxă & invocare Python
import asyncio
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.openai import OpenAI

def inmulteste(a: float, b: float) -> float:
    """Înmulțește două numere."""
    return a * b

agent = FunctionAgent(
    tools=[inmulteste],
    llm=OpenAI(model="gpt-6-astra"),
    system_prompt="Ești un asistent care poate înmulți numere.",
)

async def main():
    raspuns = await agent.run(user_msg="Cât face 1234 * 4567?")
    print(str(raspuns))

asyncio.run(main())

Documentația definește agentul ca un sistem care folosește un LLM, memorie și unelte pentru a răspunde utilizatorului. FunctionAgent folosește apelarea de funcții (tool calling) a furnizorului. ReActAgent și CodeActAgent folosesc alte strategii de prompt, pentru modele fără tool calling sau pentru agenți care scriu cod. Bucla: agentul primește mesajul și istoricul, modelul răspunde direct sau cere apeluri de unelte, uneltele rulează, rezultatele intră în istoric și modelul e apelat din nou.

Uneltele pot fi funcții Python simple (numele funcției devine numele uneltei, docstring-ul devine descrierea), FunctionTool.from_defaults(...) sau QueryEngineTool.from_defaults(query_engine, name=..., description=...), care pune un query engine RAG la dispoziția agentului. Agenții sunt workflow-uri: agent.run(...) întoarce un handler pe care îl aștepți cu await sau din care citești evenimente cu stream_events() (AgentStream, ToolCall, ToolCallResult, AgentOutput).

Implicit, agentul nu ține minte nimic între două apeluri run(). Pentru o conversație creezi un Context(agent) și îl dai la fiecare apel; contextul se poate serializa cu to_dict() și reface cu Context.from_dict(). AgentWorkflow(agents=[...], root_agent=...) combină mai mulți agenți, fiecare cu name, description și can_handoff_to. Clasele vechi (AgentRunner, OpenAIAgent) nu mai există în llama-index-core 0.14, iar as_chat_engine(chat_mode="react") sau "openai" aruncă ValueError cu trimitere la acești agenți.

Concepte cheie și caracteristici

Concept / Parametru Descriere practică
tools Listă de funcții sau obiecte BaseTool (FunctionTool, QueryEngineTool, unelte din pachetele llama-index-tools-*).
llm Modelul agentului. FunctionAgent cere un model cu tool calling.
system_prompt Instrucțiunile de sistem ale agentului.
name / description / can_handoff_to Folosite în AgentWorkflow: cum se numește agentul, ce face și cui îi poate preda controlul.
output_cls Clasă Pydantic pentru un răspuns final structurat.
streaming Implicit activ; streaming=False pentru modelele care nu suportă streaming.
run(user_msg=..., ctx=..., memory=..., max_iterations=...) Pornește agentul și întoarce un WorkflowHandler.

Exemple practice și scenarii reale

Exemplul 1: Agent RAG peste un index

from llama_index.core.agent.workflow import FunctionAgent
from llama_index.core.tools import QueryEngineTool
from llama_index.llms.openai import OpenAI

tool_contracte = QueryEngineTool.from_defaults(
    index.as_query_engine(),
    name="contracte",
    description="Răspunde la întrebări despre contractele companiei.",
)
agent = FunctionAgent(tools=[tool_contracte], llm=OpenAI(model="gpt-6-astra"))
raspuns = await agent.run(user_msg="Ce termen de plată are contractul cu Alfa SRL?")

Exemplul 2: Conversație cu memorie și streaming

După ghidurile „Maintaining state” și „Streaming output and events”.

from llama_index.core.agent.workflow import AgentStream
from llama_index.core.workflow import Context

ctx = Context(agent)
await agent.run(user_msg="Mă numesc Ana.", ctx=ctx)

handler = agent.run(user_msg="Cum mă cheamă?", ctx=ctx)
async for ev in handler.stream_events():
    if isinstance(ev, AgentStream):
        print(ev.delta, end="", flush=True)
raspuns = await handler

Exemplul 3: Doi agenți care își predau controlul

from llama_index.core.agent.workflow import AgentWorkflow, FunctionAgent

cercetator = FunctionAgent(
    name="Cercetator", description="Caută informații în documente.",
    tools=[tool_contracte], llm=OpenAI(model="gpt-6-astra"),
    can_handoff_to=["Redactor"],
)
redactor = FunctionAgent(
    name="Redactor", description="Scrie rezumatul final.",
    tools=[], llm=OpenAI(model="gpt-6-luna"),
)
flux = AgentWorkflow(agents=[cercetator, redactor], root_agent="Cercetator")
raspuns = await flux.run(user_msg="Rezumă clauzele de penalitate.")

Greșeli frecvente și capcane

  • Cod vechi cu OpenAIAgent, AgentRunner sau ReActAgent.from_tools(...). În 0.14 agenții sunt în llama_index.core.agent.workflow și se construiesc direct, cu tools= și llm=.
  • Un agent fără Context refolosit, de la care aștepți să țină minte conversația. Fiecare run() fără ctx pornește de la zero.
  • Descrieri vagi pentru unelte. Modelul alege unealta și argumentele după nume și descriere; două unelte cu descrieri asemănătoare duc la alegeri greșite.

Noțiuni și module înrudite