Trae-Agent中的llm核心交互逻辑

LLM交互逻辑全面解析

概述

Trae Agent通过模块化的LLM客户端架构与多种大语言模型进行交互。本文档详细解析LLM交互的完整流程和架构设计。


LLM架构概览

scss 复制代码
┌─────────────────────────────────────────────────────────────────────────────┐
│                           LLM交互架构                                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌─────────────────┐                                                        │
│  │   BaseAgent     │  调用 LLMClient.chat()                                │
│  │  (agent层)      │                                                        │
│  └────────┬────────┘                                                        │
│           │                                                                 │
│           ▼                                                                 │
│  ┌─────────────────┐     ┌─────────────────┐                               │
│  │   LLMClient     │────▶│  LLMProvider    │  工厂模式创建具体客户端       │
│  │  (工厂类)       │     │   (Enum)        │                               │
│  └────────┬────────┘     └─────────────────┘                               │
│           │                                                                 │
│           ▼                                                                 │
│  ┌─────────────────┐                                                        │
│  │ BaseLLMClient   │  抽象基类,定义统一接口                                │
│  │   (ABC)         │                                                        │
│  └────────┬────────┘                                                        │
│           │                                                                 │
│     ┌─────┼─────┬─────────┬─────────┐                                      │
│     │     │     │         │         │                                      │
│     ▼     ▼     ▼         ▼         ▼                                      │
│  ┌────┐┌────┐┌────┐   ┌────┐   ┌────┐                                     │
│  │Anth││Open││Azur│   │Olla│   │Goog│  具体实现类                          │
│  │ropic││AI ││e   │   │ma  │   │le  │                                     │
│  └────┘└────┘└────┘   └────┘   └────┘                                     │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

核心组件

1. 数据模型

文件 : trae_agent/utils/llm_clients/llm_basics.py

LLMMessage - 消息格式
python 复制代码
@dataclass
class LLMMessage:
    """标准消息格式"""
    role: str                          # 角色: system, user, assistant
    content: str | None = None         # 消息内容
    tool_call: ToolCall | None = None  # 工具调用
    tool_result: ToolResult | None = None  # 工具执行结果
LLMResponse - 响应格式
python 复制代码
@dataclass
class LLMResponse:
    """标准LLM响应格式"""
    content: str                       # 响应内容
    usage: LLMUsage | None = None      # Token使用情况
    model: str | None = None           # 模型名称
    finish_reason: str | None = None   # 完成原因
    tool_calls: list[ToolCall] | None = None  # 工具调用列表
LLMUsage - Token使用统计
python 复制代码
@dataclass
class LLMUsage:
    """LLM使用统计"""
    input_tokens: int                  # 输入token数
    output_tokens: int                 # 输出token数
    cache_creation_input_tokens: int = 0   # 缓存创建token
    cache_read_input_tokens: int = 0       # 缓存读取token
    reasoning_tokens: int = 0          # 推理token

2. LLMClient - 工厂类

文件 : trae_agent/utils/llm_clients/llm_client.py

python 复制代码
class LLMProvider(Enum):
    """支持的LLM提供商"""
    OPENAI = "openai"
    ANTHROPIC = "anthropic"
    AZURE = "azure"
    OLLAMA = "ollama"
    OPENROUTER = "openrouter"
    DOUBAO = "doubao"
    GOOGLE = "google"


class LLMClient:
    """主LLM客户端,支持多提供商"""
    
    def __init__(self, model_config: ModelConfig):
        self.provider = LLMProvider(model_config.model_provider.provider)
        
        # 工厂模式:根据提供商创建对应客户端
        match self.provider:
            case LLMProvider.OPENAI:
                from .openai_client import OpenAIClient
                self.client = OpenAIClient(model_config)
            case LLMProvider.ANTHROPIC:
                from .anthropic_client import AnthropicClient
                self.client = AnthropicClient(model_config)
            case LLMProvider.AZURE:
                from .azure_client import AzureClient
                self.client = AzureClient(model_config)
            # ... 其他提供商
    
    def chat(
        self,
        messages: list[LLMMessage],
        model_config: ModelConfig,
        tools: list[Tool] | None = None,
        reuse_history: bool = True,
    ) -> LLMResponse:
        """发送聊天消息到LLM"""
        return self.client.chat(messages, model_config, tools, reuse_history)

3. BaseLLMClient - 抽象基类

文件 : trae_agent/utils/llm_clients/base_client.py

python 复制代码
class BaseLLMClient(ABC):
    """LLM客户端抽象基类"""
    
    def __init__(self, model_config: ModelConfig):
        self.api_key = model_config.model_provider.api_key
        self.base_url = model_config.model_provider.base_url
        self.api_version = model_config.model_provider.api_version
        self.trajectory_recorder = None
    
    @abstractmethod
    def chat(
        self,
        messages: list[LLMMessage],
        model_config: ModelConfig,
        tools: list[Tool] | None = None,
        reuse_history: bool = True,
    ) -> LLMResponse:
        """发送聊天消息到LLM"""
        pass
    
    def supports_tool_calling(self, model_config: ModelConfig) -> bool:
        """检查是否支持工具调用"""
        return model_config.supports_tool_calling

LLM交互流程

完整交互流程图

ini 复制代码
┌─────────────────────────────────────────────────────────────────────────────┐
│                        LLM交互完整流程                                       │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  1. Agent初始化                                                              │
│     ┌─────────────────────────────────────────────────────────────┐        │
│     │ BaseAgent.__init__()                                         │        │
│     │   self._llm_client = LLMClient(agent_config.model)          │        │
│     └─────────────────────────────────────────────────────────────┘        │
│                              │                                              │
│                              ▼                                              │
│  2. LLMClient创建(工厂模式)                                                │
│     ┌─────────────────────────────────────────────────────────────┐        │
│     │ LLMClient.__init__()                                         │        │
│     │   match provider:                                            │        │
│     │     case ANTHROPIC:                                          │        │
│     │       self.client = AnthropicClient(model_config)           │        │
│     │     case OPENAI:                                             │        │
│     │       self.client = OpenAIClient(model_config)              │        │
│     └─────────────────────────────────────────────────────────────┘        │
│                              │                                              │
│                              ▼                                              │
│  3. 执行步骤时调用LLM                                                         │
│     ┌─────────────────────────────────────────────────────────────┐        │
│     │ BaseAgent._run_llm_step()                                    │        │
│     │   llm_response = self._llm_client.chat(                     │        │
│     │       messages, model_config, tools                         │        │
│     │   )                                                          │        │
│     └─────────────────────────────────────────────────────────────┘        │
│                              │                                              │
│                              ▼                                              │
│  4. LLMClient转发调用                                                        │
│     ┌─────────────────────────────────────────────────────────────┐        │
│     │ LLMClient.chat()                                             │        │
│     │   return self.client.chat(messages, model_config, tools)    │        │
│     └─────────────────────────────────────────────────────────────┘        │
│                              │                                              │
│                              ▼                                              │
│  5. 具体客户端执行(以Anthropic为例)                                          │
│     ┌─────────────────────────────────────────────────────────────┐        │
│     │ AnthropicClient.chat()                                       │        │
│     │   # 1. 转换消息格式                                          │        │
│     │   anthropic_messages = self.parse_messages(messages)        │        │
│     │                                                              │        │
│     │   # 2. 转换工具格式                                          │        │
│     │   tool_schemas = self._convert_tools(tools)                 │        │
│     │                                                              │        │
│     │   # 3. 调用API(带重试)                                     │        │
│     │   response = self._create_anthropic_response(...)           │        │
│     │                                                              │        │
│     │   # 4. 转换响应格式                                          │        │
│     │   return self._convert_response(response)                   │        │
│     └─────────────────────────────────────────────────────────────┘        │
│                              │                                              │
│                              ▼                                              │
│  6. 返回LLMResponse                                                          │
│     ┌─────────────────────────────────────────────────────────────┐        │
│     │ LLMResponse(                                                 │        │
│     │   content="我来分析这个问题...",                             │        │
│     │   usage=LLMUsage(...),                                      │        │
│     │   tool_calls=[ToolCall(...)]  # 如果有工具调用              │        │
│     │ )                                                            │        │
│     └─────────────────────────────────────────────────────────────┘        │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

具体客户端实现

AnthropicClient

文件 : trae_agent/utils/llm_clients/anthropic_client.py

python 复制代码
class AnthropicClient(BaseLLMClient):
    """Anthropic客户端封装"""
    
    def __init__(self, model_config: ModelConfig):
        super().__init__(model_config)
        self.client = anthropic.Anthropic(
            api_key=self.api_key, 
            base_url=self.base_url
        )
        self.message_history = []
    
    def chat(self, messages, model_config, tools, reuse_history):
        """发送消息到Anthropic API"""
        
        # 1. 转换消息格式
        anthropic_messages = self.parse_messages(messages)
        
        # 2. 更新历史
        if reuse_history:
            self.message_history.extend(anthropic_messages)
        else:
            self.message_history = anthropic_messages
        
        # 3. 转换工具格式
        tool_schemas = []
        if tools:
            for tool in tools:
                if tool.name == "str_replace_based_edit_tool":
                    # Anthropic特殊工具
                    tool_schemas.append(
                        TextEditor20250429(...)
                    )
                else:
                    # 普通工具
                    tool_schemas.append(
                        anthropic.types.ToolParam(...)
                    )
        
        # 4. 调用API(带重试)
        response = self._create_anthropic_response(
            model_config, tool_schemas
        )
        
        # 5. 转换响应
        return self._convert_response(response)

OpenAICompatibleClient

文件 : trae_agent/utils/llm_clients/openai_compatible_base.py

python 复制代码
class OpenAICompatibleClient(BaseLLMClient):
    """OpenAI兼容客户端基类"""
    
    def __init__(self, model_config, provider_config):
        super().__init__(model_config)
        self.provider_config = provider_config
        self.client = provider_config.create_client(
            self.api_key, self.base_url, self.api_version
        )
    
    def chat(self, messages, model_config, tools, reuse_history):
        """发送消息到OpenAI兼容API"""
        
        # 1. 转换消息格式
        openai_messages = self.parse_messages(messages)
        self.message_history = openai_messages
        
        # 2. 转换工具格式
        tool_schemas = None
        if tools:
            tool_schemas = [
                ChatCompletionToolParam(
                    type="function",
                    function=FunctionDefinition(...)
                )
                for tool in tools
            ]
        
        # 3. 调用API
        response = self.client.chat.completions.create(
            model=model_config.model,
            messages=self.message_history,
            tools=tool_schemas,
            temperature=model_config.temperature,
            max_tokens=model_config.max_tokens,
        )
        
        # 4. 转换响应
        return self._convert_response(response)

继承OpenAICompatibleClient的客户端:

  • OpenAIClient - OpenAI官方
  • AzureClient - Azure OpenAI
  • OpenRouterClient - OpenRouter
  • DoubaoClient - 豆包

消息格式转换

消息转换流程

python 复制代码
# Trae Agent内部格式
llm_messages = [
    LLMMessage(role="system", content="You are..."),
    LLMMessage(role="user", content="修复这个bug..."),
    LLMMessage(role="user", tool_result=ToolResult(...)),
]

# 转换为Anthropic格式
anthropic_messages = [
    {"role": "user", "content": "修复这个bug..."},
    {"role": "user", "content": [{"type": "tool_result", ...}]},
]

# 转换为OpenAI格式
openai_messages = [
    {"role": "system", "content": "You are..."},
    {"role": "user", "content": "修复这个bug..."},
    {"role": "tool", "content": "...", "tool_call_id": "..."},
]

工具调用支持

工具格式转换

python 复制代码
# Trae Agent工具格式
class Tool:
    name: str
    description: str
    def get_parameters(self) -> list[ToolParameter]: ...

# Anthropic工具格式
anthropic.types.ToolParam(
    name=tool.name,
    description=tool.description,
    input_schema=tool.get_input_schema(),
)

# OpenAI工具格式
ChatCompletionToolParam(
    type="function",
    function=FunctionDefinition(
        name=tool.name,
        description=tool.description,
        parameters=tool.get_input_schema(),
    ),
)

重试机制

文件 : trae_agent/utils/llm_clients/retry_utils.py

python 复制代码
def retry_with(func, provider_name, max_retries):
    """为API调用添加重试逻辑"""
    
    @wraps(func)
    def wrapper(*args, **kwargs):
        for attempt in range(max_retries):
            try:
                return func(*args, **kwargs)
            except APIError as e:
                if attempt < max_retries - 1:
                    wait_time = 2 ** attempt  # 指数退避
                    time.sleep(wait_time)
                else:
                    raise
    return wrapper

Agent中的LLM调用

BaseAgent._run_llm_step

文件 : trae_agent/agent/base_agent.py (第210-236行)

python 复制代码
async def _run_llm_step(
    self, 
    step: AgentStep, 
    messages: list[LLMMessage], 
    execution: AgentExecution
) -> list[LLMMessage]:
    """执行一步LLM交互"""
    
    # 1. 设置状态为思考中
    step.state = AgentStepState.THINKING
    self._update_cli_console(step, execution)
    
    # 2. 调用LLM
    llm_response = self._llm_client.chat(
        messages, 
        self._model_config, 
        self._tools
    )
    step.llm_response = llm_response
    
    # 3. 更新显示
    self._update_cli_console(step, execution)
    
    # 4. 更新token使用统计
    self._update_llm_usage(llm_response, execution)
    
    # 5. 检查是否完成
    if self.llm_indicates_task_completed(llm_response):
        if self._is_task_completed(llm_response):
            execution.agent_state = AgentState.COMPLETED
            execution.final_result = llm_response.content
            execution.success = True
            return messages
    
    # 6. 处理工具调用
    tool_calls = llm_response.tool_calls
    return await self._tool_call_handler(tool_calls, step)

核心文件索引

文件 职责 重要性
llm_clients/llm_basics.py 数据模型定义 ⭐⭐⭐
llm_clients/llm_client.py 工厂类,创建客户端 ⭐⭐⭐
llm_clients/base_client.py 抽象基类 ⭐⭐⭐
llm_clients/anthropic_client.py Anthropic实现 ⭐⭐⭐
llm_clients/openai_compatible_base.py OpenAI兼容基类 ⭐⭐⭐
llm_clients/openai_client.py OpenAI实现 ⭐⭐
llm_clients/azure_client.py Azure实现 ⭐⭐
llm_clients/retry_utils.py 重试逻辑 ⭐⭐
agent/base_agent.py Agent调用LLM ⭐⭐⭐

设计模式总结

1. 工厂模式 (Factory Pattern)

python 复制代码
# LLMClient根据配置创建对应客户端
match self.provider:
    case LLMProvider.ANTHROPIC:
        self.client = AnthropicClient(model_config)
    case LLMProvider.OPENAI:
        self.client = OpenAIClient(model_config)

2. 策略模式 (Strategy Pattern)

python 复制代码
# 不同提供商实现相同的chat接口
class AnthropicClient(BaseLLMClient):
    def chat(self, ...): ...  # Anthropic实现

class OpenAIClient(BaseLLMClient):
    def chat(self, ...): ...  # OpenAI实现

3. 适配器模式 (Adapter Pattern)

python 复制代码
# 将内部LLMMessage转换为各提供商格式
anthropic_messages = self.parse_messages(messages)
openai_messages = self.parse_messages(messages)

总结

Trae Agent的LLM交互架构设计清晰:

  1. 统一接口 - BaseLLMClient定义统一接口
  2. 工厂创建 - LLMClient根据配置创建对应客户端
  3. 格式转换 - 自动转换消息和工具格式
  4. 重试机制 - 内置指数退避重试
  5. 多提供商支持 - 支持7+种LLM提供商

这种设计使得添加新的LLM提供商变得简单,只需实现BaseLLMClient接口即可。


最后更新: 2026-03-16

相关推荐
码路高手2 小时前
Trae-Agent中的记忆(Memory)机制实现
人工智能
赋创小助手2 小时前
AMD OpenClaw:本地 AI Agent 运行平台解析,RyzenClaw 与 RadeonClaw 两种架构方案意味着什么?
服务器·人工智能·深度学习·自然语言处理·架构·数据挖掘·openclaw
nonono3 小时前
深度学习——ViT(Vision Transformer)学习(2020.10)
人工智能·深度学习·transformer
Dxy12393102163 小时前
PyTorch的ReduceLROnPlateau详解:深度学习训练的“智能调速器”
人工智能·pytorch·深度学习
SomeOtherTime3 小时前
信号处理(AI回答)
人工智能·信号处理
视觉&物联智能3 小时前
【杂谈】-人工智能蓬勃演进背后的隐性支撑体系
人工智能·ai·aigc·算力·agi·deepseek
IT WorryFree3 小时前
openclaw飞书机器人权限管理
人工智能·机器人·飞书
吴佳浩3 小时前
OpenClaw、Claude Code 等 Agent 为什么都选择 Node.js?
前端·人工智能·langchain