两大应用范式

大语言模型有两种主要的应用范式:

  1. RAG(检索增强生成):让模型"查资料"后回答
  2. Agent 系统:让模型"使用工具"完成任务

RAG 架构

核心思想

传统 LLM:
用户问题 → 模型 → 回答 (可能过时/幻觉)

RAG:
用户问题 → 检索相关文档 → 模型 + 文档 → 回答 (准确/有据)

完整流程

RAG Pipeline:
┌─────────────────────────────────────┐
│           索引阶段                   │
│  文档 → 分块 → 向量化 → 存储        │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│           检索阶段                   │
│  问题 → 向量化 → 相似度搜索 → Top-K  │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│           生成阶段                   │
│  问题 + 检索结果 → LLM → 回答       │
└─────────────────────────────────────┘

文档分块策略

# 固定大小分块
def fixed_size_chunk(text, chunk_size=512, overlap=50):
    chunks = []
    for i in range(0, len(text), chunk_size - overlap):
        chunks.append(text[i:i + chunk_size])
    return chunks

# 语义分块
def semantic_chunk(text, model):
    sentences = split_sentences(text)
    embeddings = model.encode(sentences)
    
    # 基于语义相似度分块
    chunks = []
    current_chunk = [sentences[0]]
    
    for i in range(1, len(sentences)):
        similarity = cosine_similarity(
            embeddings[i], embeddings[i-1]
        )
        if similarity < 0.5:  # 阈值
            chunks.append(' '.join(current_chunk))
            current_chunk = [sentences[i]]
        else:
            current_chunk.append(sentences[i])
    
    return chunks

向量数据库

# Chroma (轻量级)
import chromadb

client = chromadb.Client()
collection = client.create_collection("docs")

# 添加文档
collection.add(
    documents=["doc1", "doc2"],
    ids=["id1", "id2"]
)

# 查询
results = collection.query(
    query_texts=["query"],
    n_results=5
)

# Pinecone (云服务)
import pinecone

pinecone.init(api_key="xxx")
index = pinecone.Index("my-index")

# 向量化并存储
vectors = model.encode(documents)
index.upsert(vectors)

# 查询
results = index.query(vector=query_embedding, top_k=5)

检索策略

1. 稠密检索 (Dense Retrieval):
   - 使用向量相似度(余弦、点积)
   - 捕捉语义相似性
   - 例: "猫" 和 "小猫" 相似度高

2. 稀疏检索 (Sparse Retrieval):
   - 使用 BM25 等关键词匹配
   - 精确匹配关键词
   - 例: 搜索 "Python" 精确匹配

3. 混合检索 (Hybrid Retrieval):
   - 结合稠密和稀疏检索
   - 取长补短,效果最好
   - 例: 语义搜索 + 关键词过滤

重排序

# 检索后重排序
def rerank(query, documents, model):
    # 计算 query-document 相关性分数
    scores = []
    for doc in documents:
        score = model.score(query, doc)
        scores.append(score)
    
    # 按分数排序
    ranked = sorted(
        zip(documents, scores),
        key=lambda x: x[1],
        reverse=True
    )
    return ranked

# 交叉编码器重排序
from sentence_transformers import CrossEncoder

reranker = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
scores = reranker.predict([(query, doc) for doc in documents])

Agent 系统

核心思想

Agent = LLM + 工具 + 记忆 + 规划

用户任务 → Agent 规划 → 选择工具 → 执行 → 观察 → 调整 → 完成

架构设计

Agent 系统架构:
┌─────────────────────────────────────┐
│           规划模块                   │
│  任务分解、策略选择、反思调整        │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│           执行模块                   │
│  工具调用、代码执行、API 调用        │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│           记忆模块                   │
│  短期记忆、长期记忆、工作记忆        │
└─────────────────────────────────────┘

ReAct 框架

ReAct (Reasoning + Acting):

思考 (Thought): 分析当前状态,决定下一步
行动 (Action): 选择并执行工具
观察 (Observation): 获取工具返回结果
循环直到完成

示例:
Thought: 我需要查找今天的天气
Action: search_weather("北京")
Observation: 北京今天晴,25°C
Thought: 我已经获取了天气信息,可以回答用户
Action: respond("北京今天晴,25°C")

工具调用

# LangChain Agent 示例
from langchain.agents import initialize_agent
from langchain.tools import Tool
from langchain.llms import OpenAI

# 定义工具
tools = [
    Tool(
        name="Search",
        func=search_web,
        description="搜索网页信息"
    ),
    Tool(
        name="Calculator",
        func=calculate,
        description="数学计算"
    )
]

# 创建 Agent
llm = OpenAI(temperature=0)
agent = initialize_agent(
    tools, llm, agent="react-docstore"
)

# 执行任务
result = agent.run("今天北京的天气怎么样?")

多 Agent 协作

# AutoGen 多 Agent 示例
from autogen import AssistantAgent, UserProxyAgent

# 创建 Agent
assistant = AssistantAgent(
    name="assistant",
    llm_config={"model": "gpt-4"}
)

user_proxy = UserProxyAgent(
    name="user_proxy",
    human_input_mode="NEVER"
)

# 注册工具
user_proxy.register_for_execution(
    name="search",
    func=search_web
)

# 对话
user_proxy.initiate_chat(
    assistant,
    message="帮我分析这个数据集的趋势"
)

RAG vs Agent 对比

特性RAGAgent
核心能力检索 + 生成规划 + 工具使用
数据来源预定义文档库实时工具调用
可控性高(基于文档)中(依赖工具)
延迟低(一次检索)高(多轮交互)
适用场景知识问答、文档检索复杂任务、动态决策

混合架构

RAG + Agent:

1. Agent 规划阶段:
   - 分析任务需要什么信息
   - 决定是否需要检索

2. RAG 检索阶段:
   - 检索相关文档
   - 返回给 Agent

3. Agent 执行阶段:
   - 基于检索结果决策
   - 可能调用其他工具

4. 迭代优化:
   - 如果信息不足,再次检索
   - 直到任务完成

面试常见问题

  1. RAG 如何处理幻觉问题?

    • 检索真实文档作为依据
    • 要求模型引用来源
    • 后处理验证事实性
  2. Agent 如何处理工具调用失败?

    • 重试机制
    • 备选工具
    • 反思和调整策略
  3. 如何评估 RAG 系统?

    • 检索指标: Recall@K, MRR
    • 生成指标: BLEU, ROUGE
    • 端到端: 人工评估
  4. 多 Agent 协作的挑战?

    • 通信开销
    • 决策一致性
    • 错误传播

实战: 搭建 RAG 系统

from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings

# 加载文档
loader = TextLoader("docs.txt")
documents = loader.load()

# 分块
splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50
)
chunks = splitter.split_documents(documents)

# 向量化存储
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(
    chunks, embeddings
)

# 检索
query = "什么是 Transformer?"
results = vectorstore.similarity_search(query, k=3)