← 人工智能返回顶部

Application Engineering:Agent、RAG 与 Memory

LLM 应用开发不仅包括调用模型 API,还涉及工具调用、任务编排、知识检索、记忆管理、评测、安全和可靠性。

1. 核心架构

LLM Application
│
├── Tool Calling
│   ├── Tool Schema / Arguments
│   ├── Validation / Authorization
│   ├── Parallel / Sequential Calls
│   └── Error Handling / Idempotency
│
├── Agent / Workflow
│   ├── ReAct / Plan-and-Execute
│   ├── Router / State Machine
│   ├── State / Checkpointing
│   └── Human-in-the-loop
│
├── RAG
│   ├── Parsing / Chunking / Embedding
│   ├── Hybrid Retrieval / Reranking
│   └── Context Assembly / Citation
│
├── Vector Database
│   ├── Similarity / ANN
│   ├── HNSW / IVF
│   └── Metadata Filtering
│
├── Memory
│   ├── Short-term / Long-term
│   ├── Retrieval / Updating
│   └── Invalidation
│
├── Evaluation / Observability
│   ├── Task Success / Groundedness
│   └── Trace / Logging / Metrics
│
└── Security / Reliability
    ├── Prompt Injection
    ├── Authorization / Sandboxing
    └── Retry / Rate Limit / Audit

2. Tool Calling / Function Calling

模型不直接执行外部操作,而是生成工具名称和结构化参数,真正执行由应用后端完成。

User
  ↓
LLM
  ↓
Tool Name + Arguments
  ↓
Validate / Authorize
  ↓
Backend Executes Tool
  ↓
Tool Result
  ↓
LLM Continues

Tool Schema / JSON Schema

工具描述通常包含名称、说明以及参数 Schema。

{
  "name": "get_weather",
  "description": "Get weather for a city",
  "parameters": {
    "type": "object",
    "properties": {
      "city": {
        "type": "string"
      },
      "unit": {
        "type": "string",
        "enum": ["celsius", "fahrenheit"]
      }
    },
    "required": ["city"],
    "additionalProperties": false
  }
}

JSON Schema 描述参数的形状,但不能代替后端业务验证。

Tool Choice

控制模型是否调用工具以及调用哪个工具。

常见策略:

策略含义
Auto模型决定是否调用
None禁止调用
Required要求调用工具
Specific Tool指定必须调用某个工具

具体参数名称和支持程度取决于模型 API。

多工具调用

Parallel Tool Calling:多个工具互相独立,可以并发执行。

                 ┌── get_weather()
LLM Tool Calls ──┤
                 └── get_exchange_rate()
                         ↓
                  Aggregate Results

Sequential Tool Calling:后续工具依赖前一个工具的返回值。

search_flight()
      ↓
get_flight_details()
      ↓
check_availability()
      ↓
book_flight()

注意:模型一次生成多个 Tool Call,并不意味着后端必须并行执行。涉及资源依赖或副作用时,程序应控制执行顺序。

Tool Validation / Authorization

模型生成的参数属于不可信输入。

后端至少检查:

  1. JSON 结构与字段类型是否正确。
  2. 参数是否满足业务约束。
  3. 当前用户是否拥有调用权限。
  4. 用户是否有权操作指定资源。
  5. 高风险操作是否经过明确确认。

例如:

def delete_document(user, document_id):
    document = get_document(document_id)

    if document.owner_id != user.id:
        raise PermissionError("Forbidden")

    document.delete()

不能因为模型调用了 delete_document,就默认它有权限删除文档。

Timeout / Retry / Idempotency

外部工具可能超时或失败。

  • Timeout:限制等待时间。
  • Retry:对可恢复错误重试。
  • Fallback:主要方案失败后切换备选方案。
  • Idempotency:同一个逻辑操作重复提交,不会重复产生预期之外的副作用。

例如支付、预订、发送通知等操作,可以通过 Idempotency Key 识别重复请求。

Retry 必须考虑幂等性,否则网络超时后的重试可能导致重复执行。

Tool Result

工具结果同样属于不可信内容。

外部网页、文档和 API 响应中的文字可以作为数据,但不能自动升级为系统指令或用户授权。


3. Agent Loop / Workflow

ReAct

ReAct 采用循环式执行:

Reason
   ↓
Action
   ↓
Observation
   ↓
Reason
   ↓
Action
   ↓
...

模型根据工具返回结果不断调整下一步。

适合开放式、多步骤、事先难以完全确定执行路径的任务。

Plan-and-Execute

先制定整体计划,再执行各步骤。

User Task
    ↓
Planner
    ↓
Step 1 → Step 2 → Step 3
    ↓
Executor
    ↓
Result

执行中也可以重新规划,并不意味着计划永远不允许修改。

对比ReActPlan-and-Execute
决策方式逐步决定先规划整体步骤
灵活性高通常更有结构
适用场景探索性任务较复杂、可分解任务

Router

根据任务类型选择执行路径。

User
  ↓
Router
  ├── General QA → LLM
  ├── Document QA → RAG
  ├── Weather → Tool
  └── Data Analysis → Data Agent

Router 可以使用规则、分类模型或 LLM 实现。

State Machine / Workflow

State Machine 将流程限制在明确的状态转换中。

START
  ↓
SEARCH
  ↓
VALIDATE
  ↓
CONFIRM
  ↓
EXECUTE
  ↓
DONE

Workflow 将确定性代码、LLM 节点和工具节点组合在一起。

生产 Agent 不必让 LLM 决定所有步骤。

例如:

Upload Document
       ↓
Parse(确定性代码)
       ↓
Retrieve(检索)
       ↓
Summarize(LLM)
       ↓
Human Approval
       ↓
Save(确定性代码)

对于流程明确的业务任务,Workflow + 少量 Agent 决策通常比完全自由的 Agent Loop 更容易控制和测试。

Agent State / Checkpointing

这是 Agent 工程中非常重要的概念。

State 保存当前任务执行需要的信息。

例如:

{
    "messages": [...],
    "current_step": "validate",
    "tool_results": {...},
    "retry_count": 1,
    "approved": False
}

Checkpointing 将执行状态持久化,以便:

  • 出错后恢复。
  • 跨请求继续执行。
  • 暂停等待人工确认。
  • 检查历史执行状态。

LangGraph 的 Checkpointer 可保存 Graph State,而 Store 可用于跨 Thread 的长期数据。

需要注意:恢复执行不代表每行代码都只执行一次。某些节点可能重新运行,因此外部副作用仍然需要幂等性保护。

Loop Termination / Budget

Agent 必须有明确的停止条件。

Task Completed
Max Steps Reached
Timeout
Token / Cost Budget Exhausted
Unrecoverable Error
User Cancelled

除了 max_steps,建议同时限制:

  • 最大工具调用次数。
  • 最大总耗时。
  • 最大 Token 消耗。
  • 最大成本。
  • 单个工具的重试次数。

仅设置 Max Steps 不一定能防止单次工具调用长期阻塞。

Human-in-the-loop

高风险操作需要暂停执行,等待用户确认。

Agent Proposes Action
          ↓
     Pause / Checkpoint
          ↓
     Human Approval
       ├── Reject → Stop
       └── Approve → Execute

例如:

  • 删除数据。
  • 发送邮件。
  • 执行付款。
  • 修改生产配置。
  • 提交不可逆操作。

LangGraph 的 interrupt() 支持保存状态并等待外部输入后恢复。


4. RAG:Retrieval-Augmented Generation

RAG 通过检索外部知识,为 LLM 提供相关上下文。

Indexing Pipeline

Documents
    ↓
Parsing
    ↓
Chunking
    ↓
Embedding
    ↓
Vector Database / Search Index

Query Pipeline

User Query
     ↓
Query Processing
     ↓
Retrieval
     ↓
Reranking
     ↓
Context Assembly
     ↓
LLM
     ↓
Answer + Citation

Document Parsing

将 PDF、网页、Markdown、Office 文档等转换成可处理内容。

需要注意:

  • 标题层级。
  • 表格。
  • 页码。
  • 文档结构。
  • 图片和多模态内容。

如果解析时丢失表格结构,后续 Retrieval 质量也可能受到影响。

Chunking

将长文档分成较小的检索单元。

常见策略:

方式特点
Fixed-size固定 Token 长度
Recursive按段落、句子等递归切分
Semantic根据语义边界切分
Parent-child子 Chunk 用于检索,父 Chunk 提供上下文

Overlap 可以缓解边界信息丢失,但过大的 Overlap 会增加存储成本和重复检索结果。

Embedding 将文本表示成向量。

Query → Query Encoder → Query Vector
                              ↓
                          Similarity
                              ↑
Document → Document Encoder → Doc Vector

常见 Bi-Encoder 可以分别编码 Query 和 Document。

不要求两侧一定使用完全相同的编码流程,但必须使用彼此兼容、训练目标一致的向量空间。

BM25 根据关键词匹配、词频、逆文档频率和文档长度等计算相关性。

Semantic Search 更强调语义相似性。

Hybrid Search 将两者结合:

Query
  ├── BM25 Retrieval
  └── Vector Retrieval
          ↓
      Merge / Fusion
          ↓
        Rerank

RRF:Reciprocal Rank Fusion

RRF 是 Hybrid Search 中常见的排序融合方法。

其核心是根据不同检索列表中的排名给文档累计分数,而不是直接比较 BM25 与 Cosine Similarity 的原始分数。

对于结果 (d),常见形式为:

RRF(d)=∑i1k+rank⁡_i(d)RRF(d)=\sum_i\frac{1}{k+\operatorname{rank}\_i(d)}

其中 (k) 是排名平滑常数。

Reranking

第一阶段 Retrieval 重视速度和召回。

Reranking 使用更复杂的模型重新评估候选结果。

常见的 Cross-Encoder:

Query + Document
        ↓
Joint Encoding
        ↓
Relevance Score

与 Bi-Encoder 不同,Cross-Encoder 直接联合处理 Query 和 Document,通常更适合精细排序,但计算成本更高。

Query Rewriting / Multi-query Retrieval

Query Rewriting 改写不清晰或缺少上下文的用户问题。

Multi-query Retrieval 从不同角度生成多个查询,提高召回覆盖率。

但增加查询数量也会提高成本、延迟和噪声。

Context Assembly

将最终检索结果构造成 LLM 上下文。

需要考虑:

  • Token Budget。
  • 去重。
  • 来源和页码。
  • 相关性排序。
  • 上下文截断。
  • 检索内容权限。

Citation

Citation 让回答可以追溯到原始资料。

但生成了 Citation 不代表引用一定正确,还应验证引用资料是否真正支持对应陈述。

RAG 权限隔离

这是生产 RAG 中的重要安全问题。

例如不同用户或组织拥有不同的文档访问权限。

检索时必须由后端强制执行资源权限过滤:

filters = {
    "tenant_id": authenticated_user.tenant_id
}

其中 tenant_id 必须来自经过认证的身份,而不是直接信任 LLM 生成的值。

不能先检索所有用户资料,再让 LLM 自行判断哪些内容可以展示。


5. Vector Database

Vector Database 用于存储和检索 Embedding,通常支持 ANN Index 和 Metadata Filtering。

Embedding
    ↓
Vector Storage
    ↓
ANN Index
    ├── HNSW
    └── IVF
    ↓
Similarity Search
    ↓
Top-k

Similarity Metrics

指标特点
Cosine Similarity比较向量方向
Dot Product比较向量内积
Euclidean Distance比较几何距离

如果向量经过 L2 Normalization,Cosine Similarity、Dot Product 与 Euclidean Distance 的排序之间存在确定的对应关系。

如果没有归一化,它们的排序可能不同。

ANN

Approximate Nearest Neighbor 使用近似索引,以较低计算成本寻找高相似度向量。

它需要在检索速度、内存和 Recall 之间权衡。

HNSW

Hierarchical Navigable Small World 使用多层近邻图进行搜索。

常见参数:

  • M:控制图连接数量。
  • ef_construction:影响索引构建质量与成本。
  • ef_search:影响查询速度与 Recall。

IVF

Inverted File Index 将向量划分到不同的 Cluster。

查询时只搜索部分 Cluster,以减少计算。

常见参数:

  • nlist:Cluster 数量。
  • nprobe:查询时搜索的 Cluster 数量。

Vector Database 选型

不一定需要独立向量数据库。

如果应用已经使用 PostgreSQL,也可以使用 pgvector 实现向量存储和检索。

对于中小规模 RAG:

PostgreSQL + pgvector

通常是值得考虑的方案。

当向量规模、检索吞吐或分布式要求提高时,再评估专门的向量数据库。


6. Memory

Memory 让 Agent 可以利用当前上下文或长期保存的信息。

Short-term Memory

Conversation History
       ↓
Summarization
       ↓
Context Compression
       ↓
Current LLM Context

主要处理当前对话和任务执行状态。

Long-term Memory

类型作用
User Profile较稳定的用户信息
Episodic Memory过去发生过的事件
Semantic Memory从历史中提炼出的事实
Persistent Store跨会话保存信息

Episodic Memory

例如:

2026-10-01:
部署某个模型时遇到 CUDA OOM。

2026-10-03:
决定改用另一个推理引擎。

Semantic Memory

将历史事件提炼为更稳定的知识:

User frequently develops Django applications.

Episodic Memory 强调发生过什么,Semantic Memory 强调可以长期使用的事实或知识。

Memory Retrieval

长期记忆不能每次全部放入 Context。

可以基于:

  • Semantic Similarity。
  • Keywords。
  • Recency。
  • Importance。
  • User / Task Scope。

选择相关记忆。

Memory Updating / Invalidation

需要解决:

  • 用户信息发生变化怎么办?
  • 新记忆与旧记忆冲突怎么办?
  • 已失效的记忆何时删除?
  • 用户要求删除信息怎么办?
  • 记忆应该保存多久?

例如:

Old:
User prefers Framework A.

New:
User now prefers Framework B.

系统应更新当前有效事实,而不是永远同时保留两个互相冲突的偏好。

同时,不能把 Prompt Injection 内容或未经核实的工具返回值直接写入长期记忆。


7. Evaluation / Observability

Agent 应用需要同时观察最终结果和内部执行过程。

Evaluation

指标含义
Task Success Rate任务成功率
Tool-call Accuracy工具选择和参数正确率
Retrieval Recall正确资料召回率
Groundedness回答是否有来源支持
Hallucination Rate不受支持或错误内容比例,取决于定义
Latency端到端执行时间
Token UsageToken 消耗
Cost执行成本

Groundedness 不等于 Correctness。检索文档本身可能不准确,即使模型忠实引用它也可能产生错误答案。

Trace

Trace 记录一次任务中的完整调用路径。

Request
   ↓
LLM Call
   ↓
Tool Call
   ↓
Tool Result
   ↓
Retriever
   ↓
Reranker
   ↓
LLM Call
   ↓
Final Answer

通常每一步形成 Span,记录:

  • 开始与结束时间。
  • 输入输出摘要。
  • Token Usage。
  • Model Name。
  • Error。
  • Tool Name。
  • Parent / Child Relationship。

Logging 与 Metrics

类型作用
Logs记录具体事件和错误
Metrics聚合成功率、延迟、成本等数值
Traces还原请求的完整执行链

生产环境通常需要三者结合。

特别注意避免在日志和 Trace 中无控制地记录用户隐私、工具凭据或敏感文件内容。


8. Security、Authorization & Reliability

Prompt Injection

Prompt Injection 是通过输入内容影响模型,使其偏离预期指令或安全边界。

Direct Prompt Injection:

攻击者直接输入恶意指令。

Indirect Prompt Injection:

恶意指令隐藏在外部网页、邮件、PDF、RAG 文档或工具返回结果中。

External Document
       ↓
RAG Retrieval
       ↓
LLM Reads Document
       ↓
Malicious Instruction
       ↓
Unauthorized Tool Call

RAG 和模型微调无法从根本上消除 Prompt Injection 风险。

Trust Boundary

必须区分:

Trusted:
Application Rules
Authorization Policy
Explicit User Approval

Untrusted:
User-controlled Data
Retrieved Documents
Web Pages
Tool Results
LLM-generated Arguments

LLM 不应成为最终的权限判断者。

OWASP 也建议将外部内容视为不可信,并在模型之外执行工具参数验证与访问控制。

Least Privilege

Agent 只应拥有完成当前任务所需的最小权限。

例如:

Read-only Research Agent
    ↓
Search / Read Permissions

Booking Agent
    ↓
Search Permissions
    ↓
Explicit Confirmation
    ↓
Booking Permission

Confirmation / Human Approval

以下操作通常需要额外确认或授权:

  • 删除重要资源。
  • 向外部发送敏感信息。
  • 支付或预订。
  • 修改生产环境。
  • 执行不可逆操作。

确认时应让用户看到实际操作对象和关键参数,而不是笼统地批准后续所有操作。

Input / Output Validation

输入验证:

Schema
Type
Range
Resource Existence
Business Rules
Authorization

输出验证:

Expected Format
Required Fields
Output Safety
Groundedness
Downstream Compatibility

例如模型生成 SQL 时,不能因为通过了 JSON Schema 验证,就直接允许在生产数据库执行。

Sandboxing

执行代码、Shell 或其他高风险工具时,应使用受限运行环境。

常见控制:

  • 文件系统访问范围。
  • 网络访问权限。
  • CPU / Memory 限额。
  • 执行超时。
  • 禁止不必要的特权。
  • 临时环境清理。

Reliability

除输入输出验证外,还需要:

  • Timeout。
  • Retry / Backoff。
  • Idempotency。
  • Circuit Breaker。
  • Rate Limiting。
  • Audit Logs。
  • Secrets Management。

Circuit Breaker 用于外部服务持续失败时暂时停止调用,避免重复请求不断消耗资源。

Audit Logs 应记录谁在什么时候发起了什么重要操作,以及授权和执行结果。

总结

模块最重要的知识
Tool CallingSchema、Validation、Authorization、Idempotency
Agent / WorkflowReAct、Router、State、Checkpointing、HITL
RAGChunking、Embedding、Hybrid Search、Reranking、Citation
Vector DatabaseSimilarity、ANN、HNSW、IVF、Filtering
MemoryShort-term、Long-term、Retrieval、Invalidation
EvaluationTask Success、Groundedness、Tracing
SecurityPrompt Injection、Trust Boundary、Least Privilege

最重要的工程原则:

  1. LLM 负责提出决策,后端负责验证和执行。
  2. 确定性的业务逻辑优先使用普通程序代码,不必全部交给 Agent。
  3. RAG 的检索质量和数据权限控制,与生成质量同样重要。
  4. Agent 必须有状态管理、停止条件和恢复机制。
  5. 外部内容、工具结果及模型输出都不能自动获得可信权限。
  6. 评价 Agent 应优先关注最终任务成功率,而不只是模型回答质量。

参考文档