在上一篇文章中,我们梳理了 Transformer、RAG、Function Calling 以及 MCP 的基础原理。如果说第一篇关注的是单点能力(如何调用模型、如何连接数据),那么这一篇我们将聚焦于工程架构

当前 AI 应用开发(如 Cursor、Windsurf、Devin 等)的核心挑战,在于如何将无状态的 LLM 转化为有状态、可执行复杂任务的系统。这涉及到三个核心概念的工程化落地:Skill(技能封装)Agent(智能体循环)Workflow(工作流编排)

本文将从代码实现与数据流转的角度,深入剖析这三者的实现原理。

Skill:从 Prompt 到可执行单元

在早期的 AI 开发中,Prompt 是零散的字符串。但在复杂的工程中,我们需要一种标准化的格式来封装“特定领域的解决能力”,这就是 Skill。

Skill 本质上是一个包含指令、上下文、工具和元数据的配置对象。 它是 Agent 在运行时动态挂载的“驱动程序”。

Skill 的数据结构

一个标准的 Skill 在 Node.js 环境下通常被定义为如下结构:

interface Skill {
  // 元数据:用于路由分发
  metadata: {
    id: string;
    name: string;
    version: string;
    description: string; // 用于 Semantic Router 匹配
  };

  // 核心指令:System Prompt 的片段
  instruction: string;

  // 上下文注入:动态或静态的知识
  context: {
    files?: string[];     // 静态文档路径
    dynamic?: () => Promise<string>; // 运行时获取的状态 (e.g. 当前用户ID、系统时间)
  };

  // 工具集:该技能可用的原子能力
  tools: ToolDefinition[]; 
}

// 示例:定义一个 SQL 查询技能
const sqlExpertSkill: Skill = {
  metadata: {
    id: 'sql-expert-v1',
    name: 'SQL Generator & Executor',
    description: 'When users need to query database or analyze data via SQL',
  },
  instruction: `
    You are a PostgreSQL expert. 
    1. Always explain the query plan before execution.
    2. Read-only queries allowed.
    3. Use ISO 8601 for dates.
  `,
  context: {
    files: ['./docs/db_schema.md'], // 注入表结构
  },
  tools: [runQueryTool, listTablesTool] // 挂载 MCP 工具或本地函数
};

Skill 的加载与执行流程

Skill 的核心价值在于按需加载。我们不需要将所有 Prompt 和 Tool 一次性塞入 Context Window,而是通过路由动态激活。

graph TD
    A[用户输入 User Input] --> B{Router 意图识别}
    
    subgraph "Skill Registry"
        C[Coding Skill]
        D[Data Analysis Skill]
        E[General Chat Skill]
    end
    
    B -->|Match: SQL| D
    B -->|Match: Bug fix| C
    
    D --> F[Context Assembler]
    
    subgraph "Runtime Context"
        G[System Prompt + Skill Instruction]
        H[Global Context + Skill Files]
        I[Registered Tools]
    end
    
    F --> G
    F --> H
    D --> I
    
    I --> J[LLM Inference]

Agent:从无状态推理到有状态循环

LLM 本身是无状态的(Stateless),输入什么输出什么。Agent 则是通过**循环(Loop)记忆(Memory)**机制,让 LLM 具备了连续执行任务的能力。

目前主流的 Agent 架构通常基于 ReAct (Reasoning + Acting) 模式。

ReAct 循环

Agent 的核心是一个 while 循环,直到 LLM 判定任务结束或达到最大迭代次数。伪代码如下:

async function runAgentLoop(userQuery, tools) {
  let messages = [
    { role: 'system', content: 'You are a helpful assistant...' },
    { role: 'user', content: userQuery }
  ];

  let iterations = 0;
  const MAX_ITERATIONS = 10;

  while (iterations < MAX_ITERATIONS) {
    // 1. 调用 LLM
    const response = await llm.chat({ messages, tools });
    const message = response.choices[0].message;

    // 2. 将 LLM 的回复加入历史
    messages.push(message);

    // 3. 判断是否需要停止(无工具调用则视为回答完毕)
    if (!message.tool_calls || message.tool_calls.length === 0) {
      return message.content;
    }

    // 4. 执行工具调用 (Action)
    for (const toolCall of message.tool_calls) {
      const toolName = toolCall.function.name;
      const args = JSON.parse(toolCall.function.arguments);
      
      // 执行具体函数
      const result = await executeTool(toolName, args);
      
      // 5. 将工具结果回填给 LLM (Observation)
      // 注意:这一步是为了让 LLM 在下一次循环中看到工具执行的结果,从而生成最终回答
      messages.push({
        role: 'tool',
        tool_call_id: toolCall.id,
        content: JSON.stringify(result)
      });
    }

    iterations++;
  }
}

Agent 状态流转图

sequenceDiagram
    participant Client
    participant AgentCore
    participant LLM
    participant ToolEnv as 工具环境(API/DB)

    Client->>AgentCore: 任务指令
    loop ReAct Loop
        AgentCore->>LLM: 当前消息历史 (History)
        LLM-->>AgentCore: 返回思考 (Thought) + 工具调用 (Call)
        
        opt 无工具调用
            AgentCore-->>Client: 返回最终结果
            Note right of AgentCore: 循环结束
        end
        
        AgentCore->>ToolEnv: 执行工具 (Action)
        ToolEnv-->>AgentCore: 返回执行结果 (Observation)
        AgentCore->>AgentCore: 更新消息历史 (Append History)
    end

Workflow:确定性的编排

当单一 Agent 无法胜任复杂场景(如先写需求文档,再写代码,最后运行测试)时,我们需要引入 Workflow(工作流)

Agent 倾向于自主决策(Probabilistic),而 Workflow 强调确定性的流程控制(Deterministic)。在实际工程中,通常采用 DAG(有向无环图)State Graph(状态图) 来编排多个 Agent。

常见的 Workflow 模式

1. Planning Pattern (规划-执行模式)

将任务拆解为 Plan,然后逐一 Execute。

graph TD
    Start[用户需求] --> Planner[Planner Agent]
    Planner -->|生成 Plan List| Controller
    
    subgraph Execution Loop
        Controller -->|取下一个 Task| Worker[Worker Agent]
        Worker -->|执行结果| Reflector[Reflector Agent]
        Reflector -->|结果检查| Check{是否通过?}
        
        Check -->|是| Controller
        Check -->|否/重试| Worker
    end
    
    Controller -->|列表为空| Summarizer[总结输出]
    Summarizer --> End

2. Multi-Agent Handoff (多智能体协作)

类似工厂流水线,上游 Agent 的输出作为下游 Agent 的输入。

graph LR
    User --> A[Product Manager Agent]
    A -->|PRD文档| B[Developer Agent]
    B -->|源代码| C[Code Reviewer Agent]
    
    C -->|Review意见| D{通过?}
    D -->|否| B
    D -->|是| E[Deployer Agent]

伪代码:基于状态图的编排

使用类似 LangGraph 的逻辑来定义工作流:

// 定义状态
const State = {
  input: String,
  code: String,
  review_comments: String,
  status: 'planning' | 'coding' | 'reviewing' | 'finished'
};

// 定义节点(Node)
async function codingNode(state) {
  const code = await codingAgent.generate(state.input);
  return { ...state, code, status: 'reviewing' };
}

async function reviewNode(state) {
  const comments = await reviewAgent.check(state.code);
  if (comments.hasCriticalIssues) {
    return { ...state, review_comments: comments, status: 'coding' }; // 回退
  }
  return { ...state, status: 'finished' };
}

// 定义图(Graph)
const graph = new StateGraph();
graph.addNode('coder', codingNode);
graph.addNode('reviewer', reviewNode);

// 定义边(Edge)
graph.addEdge('coder', 'reviewer');
graph.addConditionalEdge('reviewer', (state) => {
  return state.status === 'coding' ? 'coder' : 'end';
});

// 执行
await graph.compile().invoke({ input: "Implement a login page" });

工程化挑战:结构化输出与评估

在企业级落地中,仅有架构是不够的,必须解决稳定性和可观测性问题。

结构化输出 (Structured Output)

LLM 默认输出非结构化文本。为了让 Workflow 中的节点能够通信,必须强制 LLM 输出严格的 JSON。

实现方案:

  1. Instruction Tuning:在 Prompt 中给出 JSON 示例(稳定性一般)。
  2. Function Calling Mode:利用 Tool Call 参数必须为 JSON 的特性(稳定性高)。
  3. Grammar Sampling:在推理引擎层(如 llama.cpp)使用 BNF 语法约束 Token 采样(稳定性最高)。
// 利用 Zod 定义输出 Schema
import { z } from 'zod';

const AnalysisSchema = z.object({
  sentiment: z.enum(['positive', 'neutral', 'negative']),
  key_points: z.array(z.string()),
  confidence_score: z.number().min(0).max(1)
});

// 大部分现代 SDK 支持直接传递 Schema
const result = await llm.generateObject({
  model: 'gpt-4',
  schema: AnalysisSchema,
  prompt: '分析这段客户反馈...'
});

自动化评估 (Evals)

Agent 系统是一个黑盒,必须建立评估流水线。

graph LR
    DS["测试数据集 (Dataset)"] --> Agent["Agent System"]
    Agent --> Output["实际输出"]
    
    DS --> GT["标准答案 (Ground Truth)"]
    
    Output --> Judge["Judge LLM (GPT-4)"]
    GT --> Judge
    
    Judge --> Metric1["准确性"]
    Judge --> Metric2["幻觉检测"]
    Judge --> Metric3["工具使用正确率"]

结语

从 Transformer 的底层原理,到 Skill、Agent、Workflow 的上层架构,我们已经完整梳理了构建现代 AI 应用的技术栈。

  • Skill 解决了“能力复用”与“上下文隔离”的问题。
  • Agent 解决了“复杂任务自动推演”的问题。
  • Workflow 解决了“多步骤协作”与“过程可控性”的问题。

未来的竞争焦点将不再局限于模型本身的参数量,而在于谁能构建出更高效的 Agent Runtime 和更丰富的 Skill 生态。希望这两篇文章能为你构建自己的 AI 应用提供扎实的工程参考。

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:alixiixcom@163.com