LangChainPatterns LangChainPatterns

LangChain是一个用于构建由大型语言模型(LLM)驱动的应用程序的框架,它通过简化提示链、内存管理、检索、代理和工具使用等复杂性,加速AI应用的开发过程。

AI应用 0 次安装 0 次浏览 更新于 3/5/2026

name: LangChain Patterns description: 构建由LLM驱动的应用程序的LangChain - 链、代理、RAG、内存和生产模式,用于AI驱动的应用程序。

LangChain Patterns

概览

LangChain 是一个用于构建由LLM驱动的应用程序的框架。它帮助管理提示链、内存、检索、代理和工具使用的复杂性,使得构建AI应用程序更加快速。

为什么这很重要

  • 抽象: 为各种LLM提供商提供统一的接口
  • 可组合性: 轻松地将组件链式组合在一起
  • RAG就绪: 内置的检索和向量存储集成
  • 生产: LangSmith用于监控和调试

核心概念

1. 基本设置

// lib/langchain.ts
import { ChatOpenAI } from '@langchain/openai';
import { ChatAnthropic } from '@langchain/anthropic';
import { StringOutputParser } from '@langchain/core/output_parsers';
import { ChatPromptTemplate } from '@langchain/core/prompts';

// 初始化模型
export const openai = new ChatOpenAI({
  modelName: 'gpt-4-turbo-preview',
  temperature: 0,
  openAIApiKey: process.env.OPENAI_API_KEY,
});

export const claude = new ChatAnthropic({
  modelName: 'claude-3-opus-20240229',
  temperature: 0,
  anthropicApiKey: process.env.ANTHROPIC_API_KEY,
});

// 简单链
const prompt = ChatPromptTemplate.fromMessages([
  ['system', '你是一个帮助助手,将{input_language}翻译成{output_language}。'],
  ['human', '{text}'],
]);

const chain = prompt.pipe(openai).pipe(new StringOutputParser());

// 使用方法
const result = await chain.invoke({
  input_language: 'English',
  output_language: 'Thai',
  text: 'Hello, how are you?',
});

2. 结构化输出

import { z } from 'zod';
import { StructuredOutputParser } from 'langchain/output_parsers';
import { ChatPromptTemplate } from '@langchain/core/prompts';

// 定义模式
const productSchema = z.object({
  name: z.string().describe('产品名称'),
  description: z.string().describe('产品描述'),
  price: z.number().describe('美元价格'),
  category: z.enum(['electronics', 'clothing', 'food', 'other']),
  tags: z.array(z.string()).describe('产品标签'),
});

const parser = StructuredOutputParser.fromZodSchema(productSchema);

const prompt = ChatPromptTemplate.fromMessages([
  ['system', `从文本中提取产品信息。
{format_instructions}`],
  ['human', '{text}'],
]);

const chain = prompt.pipe(openai).pipe(parser);

const result = await chain.invoke({
  text: 'New iPhone 15 Pro, amazing camera, $999, perfect for photography enthusiasts',
  format_instructions: parser.getFormatInstructions(),
});

// result: { name: 'iPhone 15 Pro', description: '...', price: 999, category: 'electronics', tags: ['photography', 'camera'] }

3. RAG (检索增强生成)

import { OpenAIEmbeddings } from '@langchain/openai';
import { SupabaseVectorStore } from '@langchain/community/vectorstores/supabase';
import { createClient } from '@supabase/supabase-js';
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
import { createRetrievalChain } from 'langchain/chains/retrieval';
import { createStuffDocumentsChain } from 'langchain/chains/combine_documents';

// 设置向量存储
const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_KEY!
);

const embeddings = new OpenAIEmbeddings({
  openAIApiKey: process.env.OPENAI_API_KEY,
});

const vectorStore = new SupabaseVectorStore(embeddings, {
  client: supabase,
  tableName: 'documents',
  queryName: 'match_documents',
});

// 索引文档
async function indexDocuments(documents: string[]) {
  const splitter = new RecursiveCharacterTextSplitter({
    chunkSize: 1000,
    chunkOverlap: 200,
  });

  const docs = await splitter.createDocuments(documents);
  await vectorStore.addDocuments(docs);
}

// 创建RAG链
const retriever = vectorStore.asRetriever({
  k: 5,
  searchType: 'similarity',
});

const qaPrompt = ChatPromptTemplate.fromMessages([
  ['system', `基于以下上下文回答问题:

{context}

如果你不知道答案,请说“我没有足够的信息来回答这个问题。”`],
  ['human', '{input}'],
]);

const documentChain = await createStuffDocumentsChain({
  llm: openai,
  prompt: qaPrompt,
});

const ragChain = await createRetrievalChain({
  combineDocsChain: documentChain,
  retriever,
});

// 使用方法
const response = await ragChain.invoke({
  input: '我们的退款政策是什么?',
});

console.log(response.answer);
console.log(response.context); // 源文档

4. 对话内存

import { BufferMemory, ConversationSummaryMemory } from 'langchain/memory';
import { ConversationChain } from 'langchain/chains';
import { UpstashRedisChatMessageHistory } from '@langchain/community/stores/message/upstash_redis';

// 简单的缓冲内存
const bufferMemory = new BufferMemory({
  returnMessages: true,
  memoryKey: 'history',
});

// Redis支持的内存(生产用)
const redisMemory = new BufferMemory({
  chatHistory: new UpstashRedisChatMessageHistory({
    sessionId: `user-${userId}-session-${sessionId}`,
    config: {
      url: process.env.UPSTASH_REDIS_URL!,
      token: process.env.UPSTASH_REDIS_TOKEN!,
    },
  }),
  returnMessages: true,
  memoryKey: 'history',
});

// 摘要内存(长对话用)
const summaryMemory = new ConversationSummaryMemory({
  llm: openai,
  returnMessages: true,
});

// 带内存的对话链
const conversationChain = new ConversationChain({
  llm: openai,
  memory: redisMemory,
  verbose: true,
});

// 多轮对话
await conversationChain.call({ input: '我的名字叫John' });
await conversationChain.call({ input: '我的名字是什么?' }); // 记住“John”

5. 带有工具的代理

import { ChatOpenAI } from '@langchain/openai';
import { createOpenAIFunctionsAgent, AgentExecutor } from 'langchain/agents';
import { DynamicTool, DynamicStructuredTool } from '@langchain/core/tools';
import { pull } from 'langchain/hub';
import { z } from 'zod';

// 定义工具
const searchTool = new DynamicTool({
  name: 'search',
  description: '搜索网络以获取当前信息',
  func: async (query: string) => {
    // 实现搜索逻辑
    const results = await searchWeb(query);
    return JSON.stringify(results);
  },
});

const calculatorTool = new DynamicStructuredTool({
  name: 'calculator',
  description: '执行数学计算',
  schema: z.object({
    expression: z.string().describe('要评估的数学表达式'),
  }),
  func: async ({ expression }) => {
    try {
      const result = eval(expression); // 在生产中使用安全的数学解析器
      return `结果: ${result}`;
    } catch (error) {
      return `错误: 无效的表达式`;
    }
  },
});

const databaseTool = new DynamicStructuredTool({
  name: 'query_database',
  description: '查询产品数据库',
  schema: z.object({
    query: z.string().describe('产品搜索查询'),
    category: z.string().optional().describe('按类别过滤'),
    maxPrice: z.number().optional().describe('最高价格过滤'),
  }),
  func: async ({ query, category, maxPrice }) => {
    const products = await prisma.product.findMany({
      where: {
        name: { contains: query, mode: 'insensitive' },
        ...(category && { category }),
        ...(maxPrice && { price: { lte: maxPrice } }),
      },
      take: 5,
    });
    return JSON.stringify(products);
  },
});

// 创建代理
const tools = [searchTool, calculatorTool, databaseTool];
const prompt = await pull<ChatPromptTemplate>('hwchase17/openai-functions-agent');

const agent = await createOpenAIFunctionsAgent({
  llm: openai,
  tools,
  prompt,
});

const agentExecutor = new AgentExecutor({
  agent,
  tools,
  verbose: true,
  maxIterations: 5,
});

// 使用方法
const result = await agentExecutor.invoke({
  input: '在1000美元以下找到一台笔记本电脑并计算加上10%的税的价格',
});

6. 流式传输

import { ChatOpenAI } from '@langchain/openai';
import { StringOutputParser } from '@langchain/core/output_parsers';

const model = new ChatOpenAI({
  modelName: 'gpt-4-turbo-preview',
  streaming: true,
});

// 带回调的流
const stream = await model.stream('写一个关于机器人的故事');

for await (const chunk of stream) {
  process.stdout.write(chunk.content);
}

// 在Next.js API路由中的流
// app/api/chat/route.ts
import { StreamingTextResponse, LangChainStream } from 'ai';

export async function POST(req: Request) {
  const { messages } = await req.json();

  const { stream, handlers } = LangChainStream();

  const chain = prompt.pipe(model).pipe(new StringOutputParser());

  chain.invoke(
    { messages },
    { callbacks: [handlers] }
  );

  return new StreamingTextResponse(stream);
}

7. 文档加载器

import { PDFLoader } from 'langchain/document_loaders/fs/pdf';
import { CSVLoader } from 'langchain/document_loaders/fs/csv';
import { WebBaseLoader } from 'langchain/document_loaders/web/web_base';
import { NotionAPILoader } from 'langchain/document_loaders/web/notionapi';
import { GithubRepoLoader } from 'langchain/document_loaders/web/github';

// 加载PDF
const pdfLoader = new PDFLoader('path/to/document.pdf', {
  splitPages: true,
});
const pdfDocs = await pdfLoader.load();

// 加载CSV
const csvLoader = new CSVLoader('path/to/data.csv', {
  column: 'text', // 用作页面内容的列
});
const csvDocs = await csvLoader.load();

// 从网络加载
const webLoader = new WebBaseLoader('https://example.com/article');
const webDocs = await webLoader.load();

// 从Notion加载
const notionLoader = new NotionAPILoader({
  clientOptions: {
    auth: process.env.NOTION_API_KEY,
  },
  id: 'page-or-database-id',
  type: 'page',
});
const notionDocs = await notionLoader.load();

// 从GitHub仓库加载
const githubLoader = new GithubRepoLoader(
  'https://github.com/username/repo',
  {
    branch: 'main',
    recursive: true,
    unknown: 'warn',
    accessToken: process.env.GITHUB_TOKEN,
  }
);
const repoDocs = await githubLoader.load();

8. LangSmith集成(生产监控)

// 启用跟踪
process.env.LANGCHAIN_TRACING_V2 = 'true';
process.env.LANGCHAIN_API_KEY = 'your-langsmith-api-key';
process.env.LANGCHAIN_PROJECT = 'my-project';

// 或者以编程方式配置
import { Client } from 'langsmith';
import { LangChainTracer } from 'langchain/callbacks';

const client = new Client({
  apiKey: process.env.LANGSMITH_API_KEY,
});

const tracer = new LangChainTracer({
  projectName: 'my-project',
  client,
});

// 与任何链一起使用
const result = await chain.invoke(
  { input: 'Hello' },
  { callbacks: [tracer] }
);

// 评估运行
import { evaluate } from 'langsmith/evaluation';

await evaluate(
  (input) => chain.invoke(input),
  {
    data: 'my-dataset-name',
    evaluators: [
      // 自定义评估器
      async ({ run, example }) => {
        const score = calculateScore(run.outputs, example.outputs);
        return { key: 'accuracy', score };
      },
    ],
  }
);

快速开始

  1. 安装包:

    npm install langchain @langchain/openai @langchain/community
    
  2. 设置环境变量:

    OPENAI_API_KEY=sk-...
    LANGCHAIN_TRACING_V2=true
    LANGCHAIN_API_KEY=ls-...
    
  3. 创建一个简单的链:

    import { ChatOpenAI } from '@langchain/openai';
    import { ChatPromptTemplate } from '@langchain/core/prompts';
    
    const chain = ChatPromptTemplate
      .fromTemplate('告诉我一个关于{topic}的笑话')
      .pipe(new ChatOpenAI())
      .pipe(new StringOutputParser());
    
    const joke = await chain.invoke({ topic: '编程' });
    

生产检查清单

  • [ ] 启用LangSmith跟踪
  • [ ] 配置错误处理和重试
  • [ ] 实施速率限制
  • [ ] 缓存层嵌入
  • [ ] 监控令牌使用情况
  • [ ] 配置备用模型
  • [ ] 输入验证
  • [ ] 输出验证/防护栏

反模式

  1. 长响应无流式传输: 总是流式传输以获得更好的用户体验
  2. 忽略令牌限制: 监控并处理上下文长度
  3. 无错误处理: LLM调用可能会失败 - 优雅地处理
  4. 硬编码提示: 使用提示模板和版本控制

集成点

  • 向量存储: Pinecone, Supabase, Chroma, Weaviate
  • LLMs: OpenAI, Anthropic, Google, Cohere, 本地模型
  • 内存: Redis, PostgreSQL, 内存中
  • 工具: 自定义APIs, 数据库, 搜索引擎

进一步阅读