Skip to main content

LangChain.dart 学习笔记

最新版本: langchain: ^0.8.0+1
发布时间: 52天前(截至2025年12月8日)
官方文档: https://langchaindart.dev/
仓库地址: https://github.com/davidmigloz/langchain_dart


📚 目录

  1. 简介
  2. 核心概念
  3. 包结构
  4. 支持的集成
  5. 快速开始
  6. 核心模块详解
  7. 实战示例
  8. 最佳实践
  9. 学习资源

🎯 简介

什么是 LangChain.dart?

LangChain.dart 是由 Harrison Chase 创建的流行 Python 框架 LangChain 的非官方 Dart 移植版本。它为开发者提供了一套开箱即用的组件,用于构建基于大语言模型(LLM)的应用程序。

核心优势

  • 🎯 统一接口: 提供统一的 API 与各种 LLM 提供商交互(OpenAI、Google、Mistral、Ollama 等)
  • 🔗 链式调用: 支持通过 LCEL(LangChain Expression Language)将组件链接在一起
  • 🚀 跨平台: 支持 Dart 和 Flutter,可运行在 Android、iOS、Linux、macOS、Web、Windows
  • 📦 模块化设计: 可按需导入所需组件
  • 🔧 丰富的集成: 支持主流 LLM 服务和工具

应用场景

  • 💬 聊天机器人(Chatbots)
  • ❓ 问答系统(Q&A with RAG)
  • 🤖 智能代理(Agents)
  • 📝 文本摘要(Summarization)
  • 🌐 翻译(Translation)
  • 🔍 信息提取(Extraction)
  • 🎯 推荐系统(Recommendation Systems)

🧩 核心概念

LangChain.dart 的组件可以分为三个核心模块:

1. 📃 Model I/O(模型输入输出)

  • 功能: 与各种 LLM 提供商交互的统一 API
  • 包含:
    • 提示模板(Prompt Templates)
    • 示例选择器(Example Selectors)
    • 输出解析器(Output Parsers)
  • 优势: 轻松切换不同的 LLM 提供商

2. 📚 Retrieval(检索)

  • 功能: 实现 RAG(检索增强生成)
  • 包含:
    • 文档加载器(Document Loaders)
    • 文本分割器(Text Splitters)
    • 嵌入模型(Embedding Models)
    • 向量存储(Vector Stores)
    • 检索器(Retrievers)

3. 🤖 Agents(代理)

  • 功能: 基于 LLM 的智能决策机器人
  • 能力: 可以使用工具(web 搜索、计算器、数据库查询等)来完成任务

4. 🔗 LCEL(LangChain Expression Language)

组件间的连接语言,使用管道(pipe)操作符将不同组件串联起来。


📦 包结构

LangChain.dart 采用模块化设计,由多个包组成:

核心包

1. langchain_core

  • 用途: 核心抽象和 LCEL
  • 适用: 构建框架或与 LangChain.dart 互操作
  • 依赖: langchain 已包含此包,无需显式依赖

2. langchain

  • 用途: 高级链、代理、检索算法
  • 适用: 构建 LLM 应用
  • 安装:
    dependencies:
    langchain: ^0.8.0+1

3. langchain_community

  • 用途: 第三方集成和社区贡献组件
  • 适用: 需要使用社区提供的集成时
  • 安装:
    dependencies:
    langchain_community: ^0.8.0+1

集成包

常用的第三方集成独立包:

包名用途
langchain_openaiOpenAI 集成(GPT-4o, o1, 嵌入, 工具, 视觉, DALL·E 3等)
langchain_googleGoogle 集成(Gemini, PaLM 2, 嵌入, 向量搜索等)
langchain_anthropicAnthropic 集成(Claude 3.5 Sonnet, Opus, Haiku等)
langchain_ollamaOllama 集成(Llama 3.2, Gemma 2, Phi-3.5等)
langchain_mistralaiMistral AI 集成
langchain_firebaseFirebase 集成(VertexAI for Firebase)
langchain_chromaChroma 向量数据库集成
langchain_pineconePinecone 向量数据库集成
langchain_supabaseSupabase 向量数据库集成

API 客户端包

可独立使用的 API 客户端:

包名用途
openai_dartOpenAI API 客户端
googleai_dartGoogle AI API 客户端
anthropic_sdk_dartAnthropic API 客户端
ollama_dartOllama API 客户端
mistralai_dartMistral AI API 客户端
vertex_aiGCP Vertex AI API 客户端
chromadbChroma DB API 客户端
tavily_dartTavily API 客户端
openai_realtime_dartOpenAI Realtime API 客户端

🔌 支持的集成

Chat Models(聊天模型)

模型流式工具视觉说明
ChatOpenAIlangchain_openaiOpenAI Chat API 及兼容服务
ChatGoogleGenerativeAIlangchain_googleGoogle AI (Gemini API)
ChatAnthropiclangchain_anthropicAnthropic Messages API (Claude)
ChatOllamalangchain_ollamaOllama Chat API
ChatFirebaseVertexAIlangchain_firebaseVertex AI for Firebase
ChatMistralAIlangchain_mistralai--Mistral Chat API
ChatVertexAIlangchain_google---GCP Vertex AI Chat API

LLMs(传统语言模型)

注意: 优先使用 Chat Models,因为许多提供商已弃用 LLMs

模型流式说明
Ollamalangchain_ollamaOllama Completions API
OpenAIlangchain_openaiOpenAI Completions API
VertexAIlangchain_google-GCP Vertex AI Text API

Embedding Models(嵌入模型)

模型说明
OpenAIEmbeddingslangchain_openaiOpenAI 嵌入 API
GoogleGenerativeAIEmbeddingslangchain_googleGoogle AI 嵌入 API
VertexAIEmbeddingslangchain_googleGCP Vertex AI 嵌入 API
OllamaEmbeddingslangchain_ollamaOllama 嵌入 API
MistralAIEmbeddingslangchain_mistralaiMistral 嵌入 API

Vector Stores(向量存储)

存储说明
MemoryVectorStorelangchain内存向量存储(原型和测试)
Chromalangchain_chromaChroma 集成
Pineconelangchain_pineconePinecone 集成
Supabaselangchain_supabaseSupabase Vector 集成
ObjectBoxVectorStorelangchain_communityObjectBox 集成
VertexAIMatchingEnginelangchain_googleVertex AI Vector Search

Tools(工具)

工具说明
CalculatorToollangchain_community计算数学表达式
TavilySearchResultsToollangchain_communityTavily 搜索引擎查询
TavilyAnswerToollangchain_communityTavily 搜索引擎答案
OpenAIDallEToollangchain_openaiOpenAI DALL-E 图像生成

🚀 快速开始

1. 安装依赖

pubspec.yaml 中添加依赖:

dependencies:
langchain: ^0.8.0+1
langchain_openai: ^0.8.0+1 # 如果使用 OpenAI
langchain_google: ^0.8.0+1 # 如果使用 Google
langchain_community: ^0.8.0+1 # 如果需要社区组件

2. 基础示例:调用 LLM

import 'package:langchain_google/langchain_google.dart';

void main() async {
// 创建模型实例
final model = ChatGoogleGenerativeAI(
apiKey: 'YOUR_GOOGLE_API_KEY',
);

// 创建提示
final prompt = PromptValue.string('Hello world!');

// 调用模型
final result = await model.invoke(prompt);

print(result);
// 输出: Hello everyone! I'm new here and excited to be part of this community.
}

3. 简单链式调用

import 'package:langchain/langchain.dart';
import 'package:langchain_openai/langchain_openai.dart';

void main() async {
// 创建提示模板
final promptTemplate = ChatPromptTemplate.fromTemplate(
'讲一个关于{topic}的笑话',
);

// 创建模型
final model = ChatOpenAI(
apiKey: 'YOUR_OPENAI_API_KEY',
defaultOptions: ChatOpenAIOptions(
model: 'gpt-4',
temperature: 0.8,
),
);

// 创建输出解析器
const outputParser = StringOutputParser<ChatResult>();

// 构建链:提示模板 -> 模型 -> 输出解析器
final chain = promptTemplate.pipe(model).pipe(outputParser);

// 执行链
final result = await chain.invoke({'topic': '程序员'});

print(result);
}

🔍 核心模块详解

Model I/O(模型输入输出)

1. Prompt Templates(提示模板)

提示模板用于格式化输入,支持变量替换:

// 简单字符串模板
final promptTemplate = ChatPromptTemplate.fromTemplate(
'Tell me a joke about {topic}',
);

// 多消息模板
final promptTemplate = ChatPromptTemplate.fromTemplates([
(ChatMessageType.system, 'You are a helpful assistant'),
(ChatMessageType.human, '{input}'),
]);

// 使用模板
final formattedPrompt = promptTemplate.format({'topic': 'cats'});

2. Output Parsers(输出解析器)

解析模型输出为结构化数据:

// 字符串输出解析器
const stringParser = StringOutputParser<ChatResult>();
final result = await model.pipe(stringParser).invoke(prompt);

// JSON 输出解析器
// 自定义解析器可以将输出解析为特定数据结构

3. Chat Models 使用

final model = ChatOpenAI(
apiKey: apiKey,
defaultOptions: ChatOpenAIOptions(
model: 'gpt-4o',
temperature: 0.7,
maxTokens: 1000,
),
);

// 单次调用
final response = await model.invoke(
PromptValue.string('你好'),
);

// 流式调用
final stream = model.stream(
PromptValue.string('写一首诗'),
);
await for (final chunk in stream) {
print(chunk);
}

Retrieval(检索 - RAG)

完整的 RAG 流程

import 'package:langchain/langchain.dart';
import 'package:langchain_openai/langchain_openai.dart';

Future<void> ragExample() async {
// 1. 创建向量存储并添加文档
final vectorStore = MemoryVectorStore(
embeddings: OpenAIEmbeddings(apiKey: openaiApiKey),
);

await vectorStore.addDocuments(
documents: [
Document(pageContent: 'LangChain was created by Harrison'),
Document(pageContent: 'David ported LangChain to Dart in LangChain.dart'),
],
);

// 2. 定义检索链
final retriever = vectorStore.asRetriever();
final setupAndRetrieval = Runnable.fromMap<String>({
'context': retriever.pipe(
Runnable.mapInput(
(docs) => docs.map((d) => d.pageContent).join('\n'),
),
),
'question': Runnable.passthrough(),
});

// 3. 构建 RAG 提示模板
final promptTemplate = ChatPromptTemplate.fromTemplates([
(
ChatMessageType.system,
'Answer the question based on only the following context:\n{context}'
),
(ChatMessageType.human, '{question}'),
]);

// 4. 定义最终链
final model = ChatOpenAI(apiKey: openaiApiKey);
const outputParser = StringOutputParser<ChatResult>();

final chain = setupAndRetrieval
.pipe(promptTemplate)
.pipe(model)
.pipe(outputParser);

// 5. 运行管道
final res = await chain.invoke('Who created LangChain.dart?');
print(res);
// 输出: David created LangChain.dart
}

Document Loaders(文档加载器)

// 加载文本文件
final loader = TextLoader('path/to/file.txt');
final documents = await loader.load();

// 加载 JSON 文件
final jsonLoader = JsonLoader('path/to/data.json');
final jsonDocs = await jsonLoader.load();

Text Splitters(文本分割器)

// 按字符分割
final splitter = CharacterTextSplitter(
chunkSize: 1000,
chunkOverlap: 200,
);
final chunks = await splitter.splitDocuments(documents);

// 递归分割
final recursiveSplitter = RecursiveCharacterTextSplitter(
chunkSize: 1000,
chunkOverlap: 200,
);

Embeddings(嵌入)

// OpenAI 嵌入
final embeddings = OpenAIEmbeddings(
apiKey: apiKey,
model: 'text-embedding-3-small',
);

// 嵌入文档
final docEmbeddings = await embeddings.embedDocuments([
'This is a document',
'This is another document',
]);

// 嵌入查询
final queryEmbedding = await embeddings.embedQuery('search query');

Agents(代理)

代理可以根据用户输入自主决定使用哪些工具:

import 'package:langchain/langchain.dart';
import 'package:langchain_openai/langchain_openai.dart';
import 'package:langchain_community/langchain_community.dart';

Future<void> agentExample() async {
// 1. 定义工具
final tools = [
CalculatorTool(),
Tool(
name: 'search',
description: 'Useful for searching the web',
func: (input) async => 'Search results for: $input',
),
];

// 2. 创建代理
final llm = ChatOpenAI(
apiKey: apiKey,
defaultOptions: ChatOpenAIOptions(
model: 'gpt-4',
temperature: 0,
),
);

final agent = OpenAIFunctionsAgent.fromLLMAndTools(
llm: llm,
tools: tools,
);

// 3. 创建执行器
final executor = AgentExecutor(agent: agent);

// 4. 运行代理
final result = await executor.run(
'What is 25 * 4? Then search for information about that number.',
);

print(result);
}

💡 实战示例

示例 1: 简单问答

import 'package:langchain/langchain.dart';
import 'package:langchain_openai/langchain_openai.dart';

Future<void> simpleQA() async {
final model = ChatOpenAI(
apiKey: 'YOUR_API_KEY',
defaultOptions: ChatOpenAIOptions(model: 'gpt-4'),
);

final prompt = PromptValue.chat([
ChatMessage.system('You are a helpful assistant.'),
ChatMessage.humanText('What is the capital of France?'),
]);

final response = await model.invoke(prompt);
print(response.output.content);
}

示例 2: 流式聊天

Future<void> streamingChat() async {
final model = ChatOpenAI(
apiKey: 'YOUR_API_KEY',
defaultOptions: ChatOpenAIOptions(model: 'gpt-4'),
);

final prompt = PromptValue.string('Write a long story about a robot.');

final stream = model.stream(prompt);

await for (final chunk in stream) {
// 实时输出每个 token
stdout.write(chunk.output.content);
}
}

示例 3: 使用工具的聊天

Future<void> chatWithTools() async {
final model = ChatOpenAI(
apiKey: 'YOUR_API_KEY',
defaultOptions: ChatOpenAIOptions(
model: 'gpt-4',
tools: [
// 定义工具
ChatTool(
type: 'function',
function: {
'name': 'get_weather',
'description': 'Get the weather for a location',
'parameters': {
'type': 'object',
'properties': {
'location': {
'type': 'string',
'description': 'The city name',
},
},
'required': ['location'],
},
},
),
],
),
);

final response = await model.invoke(
PromptValue.string('What\'s the weather in Beijing?'),
);

// 处理工具调用
if (response.output.toolCalls.isNotEmpty) {
final toolCall = response.output.toolCalls.first;
print('Model wants to call: ${toolCall.name}');
print('With arguments: ${toolCall.arguments}');
}
}

示例 4: 多模态(视觉)

Future<void> visionExample() async {
final model = ChatOpenAI(
apiKey: 'YOUR_API_KEY',
defaultOptions: ChatOpenAIOptions(
model: 'gpt-4-vision-preview',
),
);

final prompt = PromptValue.chat([
ChatMessage.human(
ChatMessageContent.multiModal([
ChatMessageContent.text('What is in this image?'),
ChatMessageContent.image(
mimeType: 'image/jpeg',
data: base64Image, // base64 编码的图片
),
]),
),
]);

final response = await model.invoke(prompt);
print(response.output.content);
}

示例 5: 文档问答系统

Future<void> documentQA() async {
// 1. 加载文档
final loader = TextLoader('knowledge_base.txt');
final documents = await loader.load();

// 2. 分割文档
final splitter = RecursiveCharacterTextSplitter(
chunkSize: 500,
chunkOverlap: 50,
);
final chunks = await splitter.splitDocuments(documents);

// 3. 创建向量存储
final embeddings = OpenAIEmbeddings(apiKey: apiKey);
final vectorStore = MemoryVectorStore(embeddings: embeddings);
await vectorStore.addDocuments(documents: chunks);

// 4. 创建 QA 链
final retriever = vectorStore.asRetriever(
searchKwargs: {'k': 3}, // 检索前3个最相关的文档
);

final qaPrompt = ChatPromptTemplate.fromTemplates([
(
ChatMessageType.system,
'Use the following context to answer the question:\n\n{context}'
),
(ChatMessageType.human, '{question}'),
]);

final model = ChatOpenAI(apiKey: apiKey);
const parser = StringOutputParser<ChatResult>();

final qaChain = Runnable.fromMap({
'context': retriever.pipe(
Runnable.mapInput((docs) => docs.map((d) => d.pageContent).join('\n\n')),
),
'question': Runnable.passthrough(),
}).pipe(qaPrompt).pipe(model).pipe(parser);

// 5. 提问
final answer = await qaChain.invoke('What is LangChain?');
print(answer);
}

示例 6: 会话记忆

Future<void> conversationWithMemory() async {
final model = ChatOpenAI(apiKey: apiKey);

// 创建会话记忆
final memory = ConversationBufferMemory();

// 定义对话链
final prompt = ChatPromptTemplate.fromTemplates([
(ChatMessageType.system, 'You are a helpful assistant.'),
(ChatMessageType.human, '{history}\nHuman: {input}'),
]);

final chain = prompt.pipe(model);

// 多轮对话
final inputs = [
'My name is John',
'What is my name?',
'What is 2+2?',
];

for (final input in inputs) {
final history = await memory.loadMemoryVariables();
final result = await chain.invoke({
'input': input,
'history': history['history'] ?? '',
});

// 保存到记忆
await memory.saveContext(
inputValues: {'input': input},
outputValues: {'output': result.output.content},
);

print('Human: $input');
print('AI: ${result.output.content}\n');
}
}

🎯 最佳实践

1. API Key 管理

// ❌ 不要硬编码 API Key
final model = ChatOpenAI(apiKey: 'sk-...');

// ✅ 使用环境变量
final apiKey = Platform.environment['OPENAI_API_KEY']!;
final model = ChatOpenAI(apiKey: apiKey);

// ✅ 使用 flutter_dotenv
import 'package:flutter_dotenv/flutter_dotenv.dart';

await dotenv.load();
final apiKey = dotenv.env['OPENAI_API_KEY']!;

2. 错误处理

try {
final result = await model.invoke(prompt);
print(result);
} on LLMException catch (e) {
print('LLM Error: ${e.message}');
} on HttpException catch (e) {
print('Network Error: $e');
} catch (e) {
print('Unexpected Error: $e');
}

3. 选择合适的模型

// 对于简单任务,使用较小的模型
final simpleModel = ChatOpenAI(
apiKey: apiKey,
defaultOptions: ChatOpenAIOptions(model: 'gpt-3.5-turbo'),
);

// 对于复杂任务,使用更强大的模型
final advancedModel = ChatOpenAI(
apiKey: apiKey,
defaultOptions: ChatOpenAIOptions(model: 'gpt-4'),
);

4. 控制输出长度和随机性

final model = ChatOpenAI(
apiKey: apiKey,
defaultOptions: ChatOpenAIOptions(
model: 'gpt-4',
temperature: 0.0, // 0=确定性,1=更随机
maxTokens: 500, // 限制输出长度
topP: 0.95, // nucleus sampling
),
);

5. 向量存储选择

  • 开发/测试: 使用 MemoryVectorStore(内存存储)
  • 生产环境: 使用 ChromaPineconeSupabase(持久化存储)
// 开发环境
final devStore = MemoryVectorStore(embeddings: embeddings);

// 生产环境
final prodStore = Chroma(
embeddings: embeddings,
collectionName: 'my_collection',
);

6. 文本分割策略

// 对于代码文档
final codeSplitter = RecursiveCharacterTextSplitter(
chunkSize: 1000,
chunkOverlap: 200,
separators: ['\n\n', '\n', ' ', ''],
);

// 对于普通文本
final textSplitter = CharacterTextSplitter(
chunkSize: 500,
chunkOverlap: 50,
);

7. 优化检索质量

// 增加检索的文档数量
final retriever = vectorStore.asRetriever(
searchKwargs: {
'k': 5, // 检索前5个最相关的文档
},
);

// 使用重排序提高准确性
// 或添加过滤条件
final retriever = vectorStore.asRetriever(
searchKwargs: {
'k': 10,
'filter': {'source': 'official_docs'},
},
);

8. 链式调用优化

// 使用 Runnable.fromMap 组织复杂的数据流
final complexChain = Runnable.fromMap({
'processed_input': Runnable.mapInput((input) => processInput(input)),
'context': retriever,
'original_query': Runnable.passthrough(),
})
.pipe(promptTemplate)
.pipe(model)
.pipe(outputParser);

📖 学习资源

官方资源

示例项目

相关项目

学习路径建议

  1. 入门阶段

    • 阅读官方文档的 "Getting Started" 部分
    • 运行简单的 LLM 调用示例
    • 了解基本的提示模板使用
  2. 进阶阶段

    • 学习 LCEL(链式表达语言)
    • 实践 RAG(检索增强生成)
    • 尝试构建简单的问答系统
  3. 高级阶段

    • 深入学习 Agents(代理)
    • 集成多个工具和数据源
    • 优化性能和成本
  4. 实战项目

    • 构建聊天机器人
    • 开发文档问答系统
    • 创建智能助手应用

🔧 常见问题

Q1: 如何选择合适的 LLM 提供商?

A: 根据需求选择:

  • OpenAI: 最强大,但成本较高
  • Google (Gemini): 性价比高,多模态能力强
  • Anthropic (Claude): 适合复杂推理和长文本
  • Ollama: 本地运行,隐私性好,免费

Q2: RAG 和直接调用 LLM 有什么区别?

A:

  • 直接调用: 依赖模型的预训练知识,可能有时效性问题
  • RAG: 从外部知识库检索相关信息,然后传给 LLM,更准确、更新

Q3: 如何降低 API 调用成本?

A:

  • 使用较小的模型(如 GPT-3.5 而非 GPT-4)
  • 减少 maxTokens 限制
  • 使用缓存避免重复调用
  • 批量处理请求
  • 考虑使用本地模型(Ollama)

Q4: 如何处理中文?

A: 所有主流模型都支持中文,但注意:

  • 中文 token 计数通常比英文多
  • 提示模板可以直接使用中文
  • 选择支持中文的嵌入模型

Q5: Flutter 应用中如何使用?

A:

// 在 Flutter 中使用与普通 Dart 项目相同
import 'package:langchain/langchain.dart';
import 'package:langchain_openai/langchain_openai.dart';

class ChatScreen extends StatefulWidget {
// ... Flutter UI 代码

Future<void> sendMessage(String message) async {
final model = ChatOpenAI(apiKey: apiKey);
final response = await model.invoke(PromptValue.string(message));
setState(() {
// 更新 UI
});
}
}

📊 版本信息

  • 当前版本: 0.8.0+1
  • 发布时间: 2024年10月17日
  • 许可证: MIT
  • 发布者: langchaindart.dev
  • 平台支持: Android, iOS, Linux, macOS, Web, Windows

🤝 贡献

LangChain.dart 欢迎贡献者!


📝 总结

LangChain.dart 是在 Dart/Flutter 生态系统中构建 LLM 应用的强大工具。它提供了:

✅ 统一的 API 接口
✅ 丰富的集成选项
✅ 强大的链式调用能力
✅ 完整的 RAG 支持
✅ 灵活的 Agent 系统
✅ 跨平台支持

通过学习和实践 LangChain.dart,你可以快速构建各种基于 LLM 的应用,如聊天机器人、问答系统、智能助手等。


最后更新: 2025年12月8日
笔记版本: v1.0