尼恩:LLM大模型学习圣经PDF的起源
《LLM大模型学习圣经:从0到1吃透Transformer技术底座》 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》 《LLM大模型学习圣经:从0到1精通RAG架构,基于LLM+RAG构建生产级企业知识库》 《SpringCloud + Python 混合微服务架构,打造AI分布式业务应用的技术底层》 《LLM大模型学习圣经:从0到1吃透大模型的顶级架构》
本文目录
- 尼恩:LLM大模型学习圣经PDF的起源
- 本文目录
- LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架
- 1. LangChain 简介
- 1.1. LangChain 发展史
- 1.2. LangChain 为什么这么火
- 1.3. LangChain 核心概念
- 1.4. LangChain 如何工作?
- 1.5. LangChain 应用场景
- 2. LangChain 应用架构 和核心组件
- LangChain 应用架构
- LangChain 的核心组件
- 2.1. Models(模型)
- 2.1.1. Chat Models 聊天模型
- Chat Models 聊天模型使用场景
- Chat Models 聊天模型使用例子
- Chat Models 聊天模型的上下文缓存
- 流式响应在 LangChain 中的应用
- 2.1.2. 嵌入 模型(embeddings model)
- 通过OpenAIEmbeddings 使用 嵌入模型(Embedding Model)
- 2.1.3. LLMS 大语言模型
- 嵌入 模型 和 大模型的区别
- 2.2. Prompts(提示词)
- 2.2.1. Prompt Templates
- 2.2.2. PipelinePrompt 提示词模版组合
- 2.2.3. Few-shot Example(小样本提示)
- 2.2.4. Example Selector
- 2.2.5. 聊天提示模板
- 2.3. Indexes (RAG 索引)
- 2.3.1. Document Loaders
- 2.3.2. Document Transformers
- 2.3.3. Embedding Models
- 2.3.4. VectorStores
- 2.3.5. Retrievers
- 2.4. Chains(链)
- 2.4.1. 简单的链 LLMChain
- 使用ChainVS不使用Chain的代码对比
- 2.4.2 LLMChain 的调用方法
- 1. 直接调用链对象
- 2. 通过run方法
- 3. 通过invoke方法
- 4. 通过predict方法
- 5. 通过apply方法
- 6. 通过generate方法
- 2.4.3. 简单顺序链 SimpleSequentialChain
- 2.4.4.通用顺序链 SequentialChain
- 2.4.5. 转换链TransformChain
- 2.4.6. LangChain表达式语言 (LCEL)
-LCEL 语法样例
-管道运算符的工作原理
- 2.4.7 LangChain预置链
-LCEL Chains:链构造器
-Legacy Chains:遗留链
- 2.5. LangChain Memory(记忆)
- 上下文管理能力 如何实现?
- 2.5.1. 简单实现对话 ConversationBufferMemory
- 2.5.2. 时间窗口记忆ConversationBufferWindowMemory
- 2.5.3. ConversationSummaryMemory
- 2.5.4. ConversationSummaryBufferMemory
- 2.5.5. ConversationTokenBufferMemory
- 2.5.6. 对话知识图谱记忆ConversationKGMemory
- 2.5.7. 基于向量存储记忆 VectorStoreRetrieverMemory
- 2.6. Agents(代理)
- 2.6.1. Action agents
- 2.6.2. Plan-and-execute agents
- 3. LangChain 实战
- 3.1. 案例1:完成一次问答
- 3.2. 案例二:通过谷歌搜索并返回答案
- 3.3. 案例三:对超长文本进行总结
- 3.4. 构建本地知识库问答机器人
- 3.5. 构建本地Chroma向量索引数据库
- 3.6. 实战: 基于 Langchain+私有模型,构建一个生成级RAG 聊天机器人
- 3.7. 实战: 基于 Langchain+公有模型,构建一个生成级RAG 聊天机器人
- 3.8. 基于 LangChain 构建的开源应用
- 说在最后:有问题找老架构取经
LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架
1. LangChain 简介
首先是 Compents“组件”,为LLMs提供接口封装、模板提示和信息检索索引; 其次是 Chains“链”,它将不同的组件组合起来解决特定的任务,比如在大量文本中查找信息; 最后是 Agents“代理”,它们使得LLMs能够与外部环境进行交互,例如通过API请求执行操作。
可以连接多种数据源,比如网页链接、本地PDF文件、向量数据库等 允许语言模型与其环境交互 封装了Model I/O(输入/输出)、Retrieval(检索器)、Memory(记忆)、Agents(决策和调度)等核心组件 可以使用链的方式组装这些组件,以便最好地完成特定用例。
1.1. LangChain 发展史
1.2. LangChain 为什么这么火
1.3. Langchain 核心概念
LLM Wrappers:这些包装器允许你连接到大型语言模型,如 GPT-4 或 Hugging Face 提供的模型。 Prompt Templates:这些模板让你避免硬编码文本输入。你可以动态地将用户输入插入到模板中,并发送给语言模型。 Indexes:索引帮助你从语言模型中提取相关信息。 Chains:链允许你将多个组件组合在一起,解决特定的任务,并构建完整的语言模型应用程序。 Agents:代理允许语言模型与外部API交互。
模型 Models 负责理解和生成语言, 提示Prompts 用于引导模型输出; 链条 Chains 代表将多个步骤串联起来完成复杂任务的过程; 代理 Agents 则用于让模型与外部环境互动,比如执行API调用。 Embedding 嵌入与向量存储 VectorStore 是数据表示和检索的手段,为模型提供必要的语言理解基础。
1.4. LangChain 如何工作?
提问:用户提出问题。 向语言模型查询:问题被转换成向量表示,用于在向量数据库中进行相似性搜索。 获取相关信息:从向量数据库中提取相关信息块,并将其输入给语言模型。 生成答案或执行操作:语言模型现在拥有了初始问题和相关信息,能够提供答案或执行操作。
1.5. LangChain 应用场景
个人助手:可以帮助预订航班、转账、缴税等。 数据分析和数据科学:连接到公司的客户数据或市场数据,极大地促进数据分析的进展。 数据连接:Langchain 允许你将大型语言模型连接到你自己的数据源,比如数据库、PDF文件或其他文档。这意味着你可以使模型从你的私有数据中提取信息。 行动执行:不仅可以提取信息,Langchain 还可以帮助你根据这些信息执行特定操作,如发送邮件。无需硬编码:它提供了灵活的方式来动态生成查询,避免了硬编码的需求。
2. LangChain 应用架构 和核心组件
LangChain 应用架构
LangChain 的核心组件
2.1. Models(模型)
2.1.1. Chat Models 聊天模型
AIMessage、 HumanMessage、 SystemMessage hatMessage,
用途:用于记录和传输由用户输入的消息内容。 例子: {
"type": "HumanMessage",
"content": "请问今天的天气如何?"
}
用途:用于记录和传输由 AI 生成的回复内容。 例子: {
"type": "AIMessage",
"content": "你好,有什么我可以帮你的吗?"
}
用途:用于系统状态更新、环境设置或元信息传递。 例子: {
"type": "SystemMessage",
"content": "对话已经开始。"
}
用途:用于记录和传输对话中的任何消息,无论其来源。 例子: json复制代码{
"type": "ChatMessage",
"role": "human",
"content": "我想了解一下最新的新闻。"
},
{
"type": "ChatMessage",
"role": "ai",
"content": "当然,以下是最新的新闻摘要。"
},
{
"type": "ChatMessage",
"role": "system",
"content": "会话已重置。"
}
Chat Models 聊天模型使用场景
AIMessage 和 HumanMessage:
在对话中区分用户输入和 AI 响应。 帮助追踪对话的来回交流,便于分析和改进对话系统的性能。
用于管理对话的状态和控制信息流。 可以包含会话开始、结束、重置等系统事件的信息。
提供一种统一的方式来存储和传输各种类型的消息。 适用于需要处理多种消息类型的复杂对话场景。
Chat Models 聊天模型使用例子
# 导入OpenAI的聊天模型,及消息类型
from langchain.chat_models import ChatOpenAI
from langchain.schema import (
AIMessage,
HumanMessage,
SystemMessage
)
# 初始化聊天对象
chat = ChatOpenAI(openai_api_key="...")
# 向聊天模型发问
chat([HumanMessage(content="Translate this sentence from English to French: I love programming.")])
messages = [
SystemMessage(content="You are a helpful assistant that translates English to French."),
HumanMessage(content="I love programming.")
]
chat(messages)
batch_messages = [
[
SystemMessage(content="You are a helpful assistant that translates English to French."),
HumanMessage(content="I love programming.")
],
[
SystemMessage(content="You are a helpful assistant that translates English to French."),
HumanMessage(content="I love artificial intelligence.")
],
]
result = chat.generate(batch_messages)
result
Chat Models 聊天模型的上下文缓存
# 导入聊天模型,SQLiteCache模块
import os
os.environ["OPENAI_API_KEY"] = 'your apikey'
import langchain
from langchain.chat_models import ChatOpenAI
from langchain.cache import SQLiteCache
# 设置语言模型的缓存数据存储的地址
langchain.llm_cache = SQLiteCache(database_path=".langchain.db")
# 加载 llm 模型
llm = ChatOpenAI()
# 第一次向模型提问
result = llm.predict('tell me a joke')
print(result)
# 第二次向模型提问同样的问题
result2 = llm.predict('tell me a joke')
print(result2)
流式响应在 LangChain 中的应用
设置 流式生成器: LangChain 提供了生成器函数的支持,可以逐步生成响应内容。这些生成器函数可以在生成部分响应时立即返回给用户,而不是等待完整响应生成完毕。 配置流式响应: 使用 LangChain 的流媒体功能时,需要配置相应的接口,使得系统可以处理和返回流式响应。
StreamingResponse
返回流式响应。from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import time
from langchain.chains import ConversationalRetrievalChain
from langchain.llms import OpenAI
app = FastAPI()
# 初始化 Langchain 模型
llm = OpenAI(api_key='your-api-key')
chain = ConversationalRetrievalChain(llm)
def generate_stream_response(prompt):
# 使用 Langchain 生成响应
responses = chain.generate_responses(prompt)
for response in responses:
yield response
time.sleep(1) # 模拟生成过程中的延迟
@app.post("/chat")
async def chat(prompt: str):
return StreamingResponse(generate_stream_response(prompt), media_type="text/plain")
# 运行应用程序:uvicorn example:app --reload
LangChain 模型初始化: 首先初始化一个 Langchain 模型,这里使用的是 OpenAI 的 GPT 模型。可以根据需要替换成其他支持的模型。 生成器函数: generate_stream_response
函数是接收流式数据的方法 ,这个方法使用 Langchain 的ConversationalRetrievalChain
来逐步生成响应内容。每次生成一部分响应后,通过yield
返回给调用方。FastAPI 的 StreamingResponse: def chat 是接口,前端可访问。暴露在 FastAPI 的 /chat
地址,前端可访问。我们使用StreamingResponse
将生成器函数返回的内容逐步发送给客户端。先利用 langchain 框架调用 openai 接口进行对话,最后使用 StreamingResponse 流式响应类返回,里面传入流式处理的过程,也就是上面的generate_stream_response类。
即时反馈:用户不需要等待完整的响应生成完毕即可看到部分内容,从而提高响应速度和用户体验。 资源优化:逐步生成和返回内容可以更好地利用计算和带宽资源,避免一次性处理大量数据带来的压力。 改进互动体验:在长时间生成内容的情况下,用户可以逐步看到生成的结果,减少等待的焦虑。
2.1.2. 嵌入 模型(embeddings model)
低维表示:嵌入模型将高维、稀疏的离散数据转换为低维、密集的向量表示。 语义信息:嵌入向量捕捉了输入数据的语义或特征信息,向量之间的距离反映了输入数据之间的相似性。 效率高:嵌入模型通常计算高效,适合用于大规模数据的相似性搜索和分类任务。
Word2Vec:通过Skip-Gram或CBOW方法训练,生成单词的嵌入向量。 GloVe:基于全局词共现矩阵训练,生成单词嵌入。 FastText:扩展了Word2Vec,能够处理未见过的词汇。
文本相似度计算:比较两个文本的嵌入向量,计算相似度。 信息检索:通过嵌入向量进行高效的相似性搜索。 分类和聚类:使用嵌入向量进行文本或图像的分类和聚类。
通过OpenAIEmbeddings 使用 嵌入模型(Embedding Model)
# 导入os, 设置环境变量,导入OpenAI的嵌入模型
import os
from langchain.embeddings.openai import OpenAIEmbeddings
os.environ["OPENAI_API_KEY"] = 'your apikey'
# 初始化嵌入模型
embeddings = OpenAIEmbeddings()
# 把文本通过嵌入模型向量化
res = embeddings.embed_query('hello world')
/*
[
-0.004845875, 0.004899438, -0.016358767, -0.024475135, -0.017341806,
0.012571548, -0.019156644, 0.009036391, -0.010227379, -0.026945334,
0.022861943, 0.010321903, -0.023479493, -0.0066544134, 0.007977734,
0.0026371893, 0.025206111, -0.012048521, 0.012943339, 0.013094575,
-0.010580265, -0.003509951, 0.004070787, 0.008639394, -0.020631202,
-0.0019203906, 0.012161949, -0.019194454, 0.030373365, -0.031028723,
0.0036170771, -0.007813894, -0.0060778237, -0.017820721, 0.0048647798,
-0.015640393, 0.001373733, -0.015552171, 0.019534737, -0.016169721,
0.007316074, 0.008273906, 0.011418369, -0.01390117, -0.033347685,
0.011248227, 0.0042503807, -0.012792102, -0.0014595914, 0.028356876,
0.025407761, 0.00076445413, -0.016308354, 0.017455231, -0.016396577,
0.008557475, -0.03312083, 0.031104341, 0.032389853, -0.02132437,
0.003324056, 0.0055610985, -0.0078012915, 0.006090427, 0.0062038545,
... 1466 more items
]
*/
2.1.3. LLMS 大语言模型
大规模:大语言模型拥有大量参数和复杂的网络结构,能够捕捉丰富的语言信息。 生成能力:能够生成高质量的自然语言文本,进行对话、写作等任务。 多任务处理:能够处理多种NLP任务,如翻译、总结、问答等。
GPT-3:由OpenAI开发的生成型预训练模型,具有1750亿参数。 BERT:由Google开发的双向编码器表示模型,适用于文本分类、命名实体识别等任务。 T5:由Google开发的文本到文本转换模型,能够处理多种文本生成任务。
对话系统:用于构建智能对话助手,如ChatGPT。 文本生成:自动写作、内容创作、翻译等。 问答系统:回答用户的问题,提供信息检索和知识问答服务。
集成和扩展: LangChain 提供了一个框架,使开发者可以轻松地集成和扩展大型语言模型。通过 LangChain,开发者可以将 LLM 的强大能力与其他工具和数据源结合,创建更复杂和强大的 NLP 应用。例如,可以将 LLM 与向量数据库、API 接口、外部计算资源等结合,增强其功能和应用场景。 组件化设计: LangChain 提供了各种组件,使开发者能够模块化地构建应用。这些组件包括模型管理、数据处理、任务调度、交互界面等。开发者可以根据需要选择和组合这些组件,以实现特定的应用需求。 增强的交互性: 通过 LangChain,开发者可以实现更复杂的用户交互。例如,可以设计多轮对话系统、复杂的问答系统,或者根据用户输入动态调用外部 API 进行信息查询和处理。这使得基于 LLM 的应用不仅限于单一的任务处理,而是能够实现更复杂的交互逻辑。 提升性能和效率: LangChain 通过优化模型调用、缓存机制、并行处理等技术手段,提升了 LLM 的性能和效率。尤其是在处理高并发请求或大规模数据时,LangChain 的设计能够显著降低延迟,提高响应速度。
import { OpenAI } from "langchain/llms/openai";
// 实例化一个模型
const model = new OpenAI({
// OpenAI内置参数
openAIApiKey: "YOUR_KEY_HERE",
modelName: "text-davinci-002", //gpt-4、gpt-3.5-turbo
maxTokens: 25,
temperature: 1, //发散度
// LangChain自定义参数
maxRetries: 10, //发生错误后重试次数
maxConcurrency: 5, //最大并发请求次数
cache: true //开启缓存
});
// 使用模型
const res = await model.predict("Tell me a joke");
import { OpenAI } from "langchain/llms/openai";
const model = new OpenAI({ temperature: 1 });
const controller = new AbortController();
const res = await model.call(
"What would be a good name for a company that makes colorful socks?",
{
signal: controller.signal, //调用controller.abort()即可取消请求
timeout: 1000 //超时时间设置
}
);
import { OpenAI } from "langchain/llms/openai";
const model = new OpenAI({
maxTokens: 25,
});
const stream = await model.stream("Tell me a joke.");
for await (const chunk of stream) {
console.log(chunk);
}
/*
Q
:
What
did
the
fish
say
when
it
hit
the
wall
?
A
:
Dam
!
*/
invoke
,batch
,stream
,map
等方法, 提供了对调用、流式传输、批处理和映射请求的基本支持嵌入 模型 和 大模型的区别
特性 | 嵌入模型 | 大语言模型 |
Basic Language Model基础语言模型有哪些?
当前绝大部分的大语言模型都是 Decoder-only 的模型结构,; 大部分大语言模型都不开源,而 OPT、BLOOM、LLaMA 三个模型是主要面向开源促进研究和应用的,中文开源可用的是 GLM,后续很多工作都是在这些开源的基础模型上进行微调优化的。
2.2. Prompts(提示词)
提示词模板(Prompt templates): 为模型输入添加参数 示例选择器(Example selectors): 动态选择在提示中包含的示例
2.2.1. Prompt Templates
固定文本部分:这是提示词模板中的静态部分,用于提供上下文或引导语言模型的生成方向。 变量部分:这是提示词模板中的动态部分,可以根据具体输入进行替换。这些变量通常用占位符表示。
PromptTemplate
类创建一个简单的硬编码提示。from langchain import PromptTemplate
# An example prompt with no input variables
no_input_prompt = PromptTemplate(input_variables=[], template="Tell me a joke.")
no_input_prompt.format()
# -> "Tell me a joke."
# An example prompt with one input variable
one_input_prompt = PromptTemplate(input_variables=["adjective"], template="Tell me a {adjective} joke.")
one_input_prompt.format(adjective="funny")
# -> "Tell me a funny joke."
# An example prompt with multiple input variables
multiple_input_prompt = PromptTemplate(
input_variables=["adjective", "content"],
template="Tell me a {adjective} joke about {content}."
)
multiple_input_prompt.format(adjective="funny", content="chickens")
# -> "Tell me a funny joke about chickens."
input_variables
,也可以使用 from_template
类方法创建 PromptTemplate
。LangChain
将根据传递的 template
自动推断 input_variables
。template = "Tell me a {adjective} joke about {content}."
prompt_template = PromptTemplate.from_template(template)
prompt_template.input_variables
# -> ['adjective', 'content']
prompt_template.format(adjective="funny", content="chickens")
# -> Tell me a funny joke about chickens.
2.2.2. PipelinePrompt 提示词模版组合
import { PromptTemplate, PipelinePromptTemplate } from "langchain/prompts";
const fullPrompt = PromptTemplate.fromTemplate(`{introduction}
{example}
{start}`);
const introductionPrompt = PromptTemplate.fromTemplate(
`You are impersonating {person}.`
);
const examplePrompt =
PromptTemplate.fromTemplate(`Here's an example of an interaction:
Q: {example_q}
A: {example_a}`);
const startPrompt = PromptTemplate.fromTemplate(`Now, do this for real!
Q: {input}
A:`);
const composedPrompt = new PipelinePromptTemplate({
pipelinePrompts: [
{
name: "introduction",
prompt: introductionPrompt,
},
{
name: "example",
prompt: examplePrompt,
},
{
name: "start",
prompt: startPrompt,
},
],
finalPrompt: fullPrompt,
});
const formattedPrompt = await composedPrompt.format({
person: "Elon Musk",
example_q: `What's your favorite car?`,
example_a: "Telsa",
input: `What's your favorite social media site?`,
});
console.log(formattedPrompt);
/*
You are impersonating Elon Musk.
Here's an example of an interaction:
Q: What's your favorite car?
A: Telsa
Now, do this for real!
Q: What's your favorite social media site?
A:
*/
2.2.3. Few-shot example(小样本提示)
import os
os.environ["OPENAI_API_KEY"] = 'your apikey'
from langchain import PromptTemplate, FewShotPromptTemplate
from langchain.llms import OpenAI
examples = [
{"word": "黑", "antonym": "白"},
{"word": "伤心", "antonym": "开心"},
]
example_template = """
单词: {word}
反义词: {antonym}\\n
"""
# 创建提示词模版
example_prompt = PromptTemplate(
input_variables=["word", "antonym"],
template=example_template,
)
# 创建小样本提示词模版
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
prefix="给出每个单词的反义词",
suffix="单词: {input}\\n反义词:",
input_variables=["input"],
example_separator="\\n",
)
# 格式化小样本提示词
prompt_text = few_shot_prompt.format(input="粗")
# 调用OpenAI
llm = OpenAI(temperature=0.9)
print(llm(prompt_text))
2.2.4. Example Selector
按长度选择:对于较长的输入,它将选择较少的示例来;而对于较短的输入,它将选择更多的示例。 按相似度选择:查找与输入具有最大余弦相似度的嵌入示例
import os
os.environ["OPENAI_API_KEY"] = 'your apikey'
from langchain.prompts import PromptTemplate, FewShotPromptTemplate
from langchain.prompts.example_selector import LengthBasedExampleSelector
from langchain.prompts.example_selector import LengthBasedExampleSelector
# These are a lot of examples of a pretend task of creating antonyms.
examples = [
{"word": "happy", "antonym": "sad"},
{"word": "tall", "antonym": "short"},
{"word": "energetic", "antonym": "lethargic"},
{"word": "sunny", "antonym": "gloomy"},
{"word": "windy", "antonym": "calm"},
]
# 例子格式化模版
example_formatter_template = """
Word: {word}
Antonym: {antonym}\n
"""
example_prompt = PromptTemplate(
input_variables=["word", "antonym"],
template=example_formatter_template,
)
# 使用 LengthBasedExampleSelector来选择例子
example_selector = LengthBasedExampleSelector(
examples=examples,
example_prompt=example_prompt,
# 最大长度
max_length=25,
)
# 使用'example_selector'创建小样本提示词模版
dynamic_prompt = FewShotPromptTemplate(
example_selector=example_selector,
example_prompt=example_prompt,
prefix="Give the antonym of every input",
suffix="Word: {input}\nAntonym:",
input_variables=["input"],
example_separator="\n\n",
)
longString = "big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else"
print(dynamic_prompt.format(input=longString))
...
// 定义相似度选择器
const exampleSelector = await SemanticSimilarityExampleSelector.fromExamples(
[
{ input: "happy", output: "sad" },
{ input: "tall", output: "short" },
{ input: "energetic", output: "lethargic" },
{ input: "sunny", output: "gloomy" },
{ input: "windy", output: "calm" },
],
new OpenAIEmbeddings(),
HNSWLib,
{ k: 1 }
);
...
// 跟天气类相关的示例
console.log(await dynamicPrompt.format({ adjective: "rainy" }));
/*
Give the antonym of every input
Input: sunny
Output: gloomy
Input: rainy
Output:
*/
// 跟尺寸相关的示例
console.log(await dynamicPrompt.format({ adjective: "large" }));
/*
Give the antonym of every input
Input: tall
Output: short
Input: large
Output:
*/
2.2.5. 聊天提示模板
AIMessage、 HumanMessage、 SystemMessage hatMessage,
role
相关联。from langchain.prompts import (
ChatPromptTemplate,
PromptTemplate,
SystemMessagePromptTemplate,
AIMessagePromptTemplate,
HumanMessagePromptTemplate,
)
from langchain.schema import (
AIMessage,
HumanMessage,
SystemMessage
)
MessagePromptTemplate
。from_template
方法。template="You are a helpful assistant that translates {input_language} to {output_language}."
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
human_template="{text}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
MessagePromptTemplate
,您可以在外部创建一个 PromptTemplate,然后将其传递进去,例如:prompt=PromptTemplate(
template="You are a helpful assistant that translates {input_language} to {output_language}.",
input_variables=["input_language", "output_language"],
)
system_message_prompt_2 = SystemMessagePromptTemplate(prompt=prompt)
assert system_message_prompt == system_message_prompt_2
MessagePromptTemplates
构建一个 ChatPromptTemplate
。ChatPromptTemplate
的 format_prompt
方法 - 这将返回一个 PromptValue
,您可以将其转换为字符串或 Message 对象,具体取决于您是否希望将格式化的值用作 llm 或 chat 模型的输入。chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
# get a chat completion from the formatted messages
chat_prompt.format_prompt(input_language="English", output_language="French", text="I love programming.").to_messages()
2.3. Indexes (RAG 索引)
Document Loaders(文档加载器)、 Text Splitters(文本拆分器)、 VectorStores(向量存储器) Retrievers(检索器)。
2.3.1. Document Loaders
interface Document {
pageContent: string;
metadata: Record<string, any>;
}
2.3.2. Document Transformers
CharacterTextSplitter 它按照指定的分隔符(默认“\n\n”)进行分割,并且考虑文本片段的最大长度。当处理大量任意文档集合时,简单的文本分割可能会出现重叠文本的文档,CharacterTextSplitter可以用元数据标记文档,从而解决矛盾来源的信息等问题。 RecursiveCharacterTextSplitter 除了可以按指定分隔符进行分割外,还支持根据特定于语言的语法分割文本,比如:JavaScript、Python、Solidity 和 Rust 等流行语言,以及 Latex、HTML 和 Markdown。 当提取 HTML 文档以供以后检索时,我们通常只对网页的实际内容而不是语义感兴趣。HtmlToTextTransformer和MozillaReadabilityTransformer都可以从文档中剥离HTML标签,从而使检索更加有效 MetadataTagger转换器可以自动从文档中提取元数据,以便以后进行更有针对性的相似性搜索。
from langchain.text_splitter import CharacterTextSplitter
# 初始字符串
state_of_the_union = "..."
text_splitter = CharacterTextSplitter(
separator = "\\n\\n",
chunk_size = 1000,
chunk_overlap = 200,
length_function = len,
)
texts = text_splitter.create_documents([state_of_the_union])
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
const text = `Hi.\n\nI'm Harrison.\n\nHow? Are? You?\nOkay then f f f f.
This is a weird text to write, but gotta test the splittingggg some how.\n\n
Bye!\n\n-H.`;
const splitter = new RecursiveCharacterTextSplitter({
separators: ["\n\n", "\n", " ", ""], //默认分隔符
chunkSize: 1000, //最终文档的最大大小(以字符数计),默认1000
chunkOverlap: 200, //块之间应该有多少重叠,默认200
});
const output = await splitter.createDocuments([text]);
2.3.3. Embedding Models
import { OpenAIEmbeddings } from "langchain/embeddings/openai";
/* Create instance */
const embeddings = new OpenAIEmbeddings();
/* Embed queries */
const res = await embeddings.embedQuery("Hello world");
/*
[
-0.004845875, 0.004899438, -0.016358767, -0.024475135, -0.017341806,
0.012571548, -0.019156644, 0.009036391, -0.010227379, -0.026945334,
0.022861943, 0.010321903, -0.023479493, -0.0066544134, 0.007977734,
... 1436 more items
]
*/
/* Embed documents */
const documentRes = await embeddings.embedDocuments(["Hello world", "Bye bye"]);
/*
[
[
-0.0047852774, 0.0048640342, -0.01645707, -0.024395779, -0.017263541,
0.012512918, -0.019191515, 0.009053908, -0.010213212, -0.026890801,
0.022883644, 0.010251015, -0.023589306, -0.006584088, 0.007989113,
... 1436 more items
],
[
-0.009446913, -0.013253193, 0.013174579, 0.0057552797, -0.038993083,
0.0077763423, -0.0260478, -0.0114384955, -0.0022683728, -0.016509168,
0.041797023, 0.01787183, 0.00552271, -0.0049789557, 0.018146982,
... 1436 more items
]
]
*/
2.3.4. VectorStores
import { MemoryVectorStore } from "langchain/vectorstores/memory";
import { OpenAIEmbeddings } from "langchain/embeddings/openai";
import { TextLoader } from "langchain/document_loaders/fs/text";
// Create docs with a loader
const loader = new TextLoader("src/document_loaders/example_data/example.txt");
const docs = await loader.load();
// Load the docs into the vector store
const vectorStore = await MemoryVectorStore.fromDocuments(
docs,
new OpenAIEmbeddings()
);
// Search for the most similar document
const resultOne = await vectorStore.similaritySearch("hello world", 1);
console.log(resultOne);
/*
[
Document {
pageContent: "Hello world",
metadata: { id: 2 }
}
]
*/
2.3.5. Retrievers
父文档检索器(Parent Document Retriever):允许为每个父文档创建多个嵌入,从而允许查找较小的块但返回更大的上下文 自查询检索器(Self Query Retriever):用户问题通常包含对某些内容的引用,这些内容不仅是语义的,而且表达了一些可以最好地表示为元数据过滤器的逻辑。自查询允许从查询中存在的其他元数据过滤器解析出查询的语义部分。 Ensemble Retriever:可以更容易的从多个不同的来源检索文档或使用多种不同的算法。
...
retriever = vectorStore.asRetriever()
ContextualCompressionRetriever:用给定查询的上下文来压缩它们,以便只返回相关信息,而不是立即按原样返回检索到的文档,同时还可以减少token数量。 MultiQueryRetriever:从不同角度为给定的用户输入查询生成多个查询。 ParentDocumentRetriever:在检索过程中,它首先获取小块,然后查找这些块的父 ID,并返回那些较大的文档。 SelfQueryRetriever:一种能够查询自身的检索器。 VespaRetriever:从Vespa.ai数据存储中检索文档。
import { MemoryVectorStore } from "langchain/vectorstores/memory";
import { OpenAIEmbeddings } from "langchain/embeddings/openai";
import { ScoreThresholdRetriever } from "langchain/retrievers/score_threshold";
const vectorStore = await MemoryVectorStore.fromTexts(
[
"Buildings are made out of brick",
"Buildings are made out of wood",
"Buildings are made out of stone",
"Buildings are made out of atoms",
"Buildings are made out of building materials",
"Cars are made out of metal",
"Cars are made out of plastic",
],
[{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }],
new OpenAIEmbeddings()
);
const retriever = ScoreThresholdRetriever.fromVectorStore(vectorStore, {
minSimilarityScore: 0.9, // Finds results with at least this similarity score
maxK: 100, // The maximum K value to use. Use it based to your chunk size to make sure you don't run out of tokens
kIncrement: 2, // How much to increase K by each time. It'll fetch N results, then N + kIncrement, then N + kIncrement * 2, etc.
});
const result = await retriever.getRelevantDocuments(
"What are buildings made out of?"
);
console.log(result);
/*
[
Document {
pageContent: 'Buildings are made out of building materials',
metadata: { id: 5 }
},
Document {
pageContent: 'Buildings are made out of wood',
metadata: { id: 2 }
},
Document {
pageContent: 'Buildings are made out of brick',
metadata: { id: 1 }
},
Document {
pageContent: 'Buildings are made out of stone',
metadata: { id: 3 }
},
Document {
pageContent: 'Buildings are made out of atoms',
metadata: { id: 4 }
}
]
*/
2.4. Chains(链)
任务(Tasks): 每个任务是链中的一个独立步骤,可以是数据预处理、模型推理、结果生成等。 连接器(Connectors): 用于将任务串联起来,使得每个任务的输出可以作为下一个任务的输入。 控制流(Control Flow): 决定任务的执行顺序和条件,包括分支、循环等控制结构。
模块化: 每个任务应该是独立的模块,便于复用和维护。 灵活性: 设计链时应考虑到不同应用场景的需求,确保可以灵活调整任务顺序和内容。 扩展性: 链应能够轻松扩展,以添加新的任务或修改现有任务。 可维护性: 通过清晰的接口和文档,确保链的维护和更新过程简便。
2.4.1. 简单的链 LLMChain
from langchain import PromptTemplate, OpenAI, LLMChain
prompt_template = "What is a good name for a company that makes {product}?"
llm = OpenAI(temperature=0)
llm_chain = LLMChain(
llm=llm,
prompt=PromptTemplate.from_template(prompt_template)
)
llm_chain("colorful socks")
使用ChainVS不使用Chain的代码对比
提示模板的构建 模型的调用
# 导入LangChain中的提示模板
from langchain_core.prompts import PromptTemplate
# 原始字符串模板
template = "猪八戒吃{fruit}?"
# 创建LangChain模板
prompt_temp = PromptTemplate.from_template(template)
# 根据模板创建提示
prompt = prompt_temp.format(fruit='人参果')
# 导入LangChain中的OpenAI模型接口
from langchain_openai import OpenAI
# 创建模型实例
model = OpenAI(temperature=0)
# 传入提示,调用模型返回结果
result = model.invoke(prompt)
print(result)
猪八戒是《西游记》中的一个角色,他是一只贪吃懒惰的猪妖,平时喜欢吃各种美食。在《西游记》中,猪八戒曾经吃过人参果,但并不是真的吃了人参果,而是被唐僧误认为是人参果而被骗吃了。事实上,人参果是一种神奇的果实,可以让人长生不老,但是只有在特定的条件下才能生长,非常稀少。因此,猪八戒并没有真的吃到人参果。
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
# 原始字符串模板
template = "猪八戒吃{fruit}?"
# 创建模型实例
llm = OpenAI(temperature=0)
# 创建LLMChain
llm_chain = LLMChain(
llm=llm,
prompt=PromptTemplate.from_template(template))
# 调用LLMChain,返回结果
result = llm_chain.invoke({"fruit": "人参果"})
print(result)
{'fruit': '人参果', 'text': '\n\n猪八戒是《西游记》中的一个角色,他是一只贪吃懒惰的猪妖,平时喜欢吃各种美食。在《西游记》中,猪八戒曾经吃过人参果,但并不是真的吃了人参果,而是被唐僧误认为是人参果而被骗吃了。事实上,人参果是一种神奇的果实,可以让人长生不老,但是只有在特定的条件下才能生长,非常稀少。因此,猪八戒并没有真的吃到人参果。'}
2.4.2. LLMChain 的调用方法
1. 直接调用链对象
__call__
方法。__call__
方法。# 创建LLMChain
llm_chain = LLMChain(llm=llm, prompt=template)
# 调用LLMChain,返回结果
result = llm_chain({"role": "猪八戒", "fruit": "人参果"})
print(result)
2. 通过run方法
_call_
函数。# 创建LLMChain
llm_chain = LLMChain(llm=llm, prompt=template)
# 调用LLMChain,返回结果
result = llm_chain.run({"role": "猪八戒", "fruit": "人参果"})
print(result)
3. 通过invoke方法
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
# 创建模型实例
template = PromptTemplate(
input_variables=["role", "fruit"],
template="{role}喜欢吃{fruit}?",
)
# 创建LLM
llm = OpenAI(temperature=0)
# 创建LLMChain
llm_chain = LLMChain(llm=llm, prompt=template)
# 调用LLMChain,返回结果
# 如果提示模板中包含多个变量,在调用链的时候,可以使用字典一次性输入它们。
result = llm_chain.invoke({"role": "猪八戒", "fruit": "人参果"})
print(result)
{'role': '猪八戒', 'fruit': '人参果', 'text': '\n\n猪八戒是一只贪吃懒惰的猪妖,他最喜欢吃的是猪食。人参果是唐僧师徒在取经途中遇到的一种神奇的水果,具有延年益寿的功效,但并非猪八戒的最爱。'}
4. 通过predict方法
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
# 创建模型实例
template = PromptTemplate(
input_variables=["role", "fruit"],
template="{role}喜欢吃{fruit}?",
)
# 创建LLM
llm = OpenAI(temperature=0)
# 创建LLMChain
llm_chain = LLMChain(llm=llm, prompt=template)
# 调用LLMChain,返回结果
result = llm_chain.predict(role="猪八戒", fruit="人参果")
print(result)
5. 通过apply方法
input_list = [
{"product": "socks"},
{"product": "computer"},
{"product": "shoes"}
]
llm_chain.apply(input_list)
[{'text': '\n\nSocktastic!'},
{'text': '\n\nTechCore Solutions.'},
{'text': '\n\nFootwear Factory.'}]
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
# 创建模型实例
template = PromptTemplate(
input_variables=["role", "fruit"],
template="{role}喜欢吃{fruit}?",
)
# 创建LLM
llm = OpenAI(temperature=0)
# 创建LLMChain
llm_chain = LLMChain(llm=llm, prompt=template)
# 输入列表
input_list = [
{"role": "猪八戒", "fruit": "人参果"}, {"role": "孙悟空", "fruit": "仙桃"}
]
# 调用LLMChain,返回结果
result = llm_chain.apply(input_list)
print(result)
[{'text': '\n\n猪八戒是一个贪吃的角色,他喜欢吃各种美味的食物,包括人参果。在《西游记》中,猪八戒曾经在取经路上遇到过人参果树,他非常贪婪地摘下来吃,结果被孙悟空和唐僧发现并教训。虽然人参果具有补气养血的功效,但是对于猪八戒来说,它更像是一种美味的水果,他并不在意它的药用价值。因此,可以说猪八戒是喜欢吃人参果的。'}, {'text': '\n\n是的,孙悟空非常喜欢吃仙桃。在《西游记》中,他经常会偷吃仙桃,甚至为了吃仙桃而闹出许多笑话和故事。仙桃也是孙悟空的最爱,因为它们具有神奇的功效,可以让他长生不老。'}]
6. 通过generate方法
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
# 创建模型实例
template = PromptTemplate(
input_variables=["role", "fruit"],
template="{role}喜欢吃{fruit}?",
)
# 创建LLM
llm = OpenAI(temperature=0)
# 创建LLMChain
llm_chain = LLMChain(llm=llm, prompt=template)
input_list = [
{"role": "猪八戒", "fruit": "人参果"}, {"role": "孙悟空", "fruit": "仙桃"}
]
# 调用LLMChain,返回结果
result = llm_chain.generate(input_list)
print(result)
generations=[[Generation(text='\n\n猪八戒是一个贪吃的角色,他喜欢吃各种美味的食物,包括人参果。在《西游记》中,猪八戒曾经在取经路上遇到过人参果树,他非常贪婪地摘下来吃,结果被孙悟空和唐僧发现并责备他。虽然人参果具有补气养血的功效,但是对于猪八戒来说,它更像是一种美味的水果,他并不在意它的药用价值。因此可以说,猪八戒确实喜欢吃人参果。', generation_info={'finish_reason': 'stop', 'logprobs': None})], [Generation(text='\n\n是的,孙悟空非常喜欢吃仙桃。在《西游记》中,他经常会偷吃仙桃,甚至为了吃仙桃而闹出许多笑话和故事。仙桃也是孙悟空的最爱,因为它们具有神奇的功效,可以让他长生不老。', generation_info={'finish_reason': 'stop', 'logprobs': None})]] llm_output={'token_usage': {'completion_tokens': 309, 'total_tokens': 343, 'prompt_tokens': 34}, 'model_name': 'gpt-3.5-turbo-instruct'} run=[RunInfo(run_id=UUID('1354a070-6820-4005-9436-af859e65ebc3')), RunInfo(run_id=UUID('7d5d6633-b569-487f-ae18-24a3f4ac21db'))]
2.4.3. 简单顺序链 SimpleSequentialChain
from langchain.llms import OpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.chains import SimpleSequentialChain
# 定义第一个chain
llm = OpenAI(temperature=.7)
template = """You are a playwright. Given the title of play, it is your job to write a synopsis for that title.
Title: {title}
Playwright: This is a synopsis for the above play:"""
prompt_template = PromptTemplate(input_variables=["title"], template=template)
synopsis_chain = LLMChain(llm=llm, prompt=prompt_template)
# 定义第二个chain
llm = OpenAI(temperature=.7)
template = """You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.
Play Synopsis:
{synopsis}
Review from a New York Times play critic of the above play:"""
prompt_template = PromptTemplate(input_variables=["synopsis"], template=template)
review_chain = LLMChain(llm=llm, prompt=prompt_template)
# 通过简单顺序链组合两个LLMChain
overall_chain = SimpleSequentialChain(chains=[synopsis_chain, review_chain], verbose=True)
# 执行顺序链
review = overall_chain.run("Tragedy at sunset on the beach")
2.4.4. 通用顺序链 SequentialChain
# 这是一个 LLMChain,根据戏剧的标题和设定的时代,生成一个简介。
llm = OpenAI(temperature=.7)
template = """You are a playwright. Given the title of play and the era it is set in, it is your job to write a synopsis for that title.
# 这里定义了两个输入变量title和era,并定义一个输出变量:synopsis
Title: {title}
Era: {era}
Playwright: This is a synopsis for the above play:"""
prompt_template = PromptTemplate(input_variables=["title", "era"], template=template)
synopsis_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="synopsis")
# 这是一个 LLMChain,根据剧情简介撰写一篇戏剧评论。
llm = OpenAI(temperature=.7)
template = """You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.
# 定义了一个输入变量:synopsis,输出变量:review
Play Synopsis:
{synopsis}
Review from a New York Times play critic of the above play:"""
prompt_template = PromptTemplate(input_variables=["synopsis"], template=template)
review_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="review")
overall_chain({"title":"Tragedy at sunset on the beach", "era": "Victorian England"})
> Entering new SequentialChain chain...
> Finished chain.
{'title': 'Tragedy at sunset on the beach',
'era': 'Victorian England',
'synopsis': "xxxxxx",
'review': "xxxxxxx"}
2.4.5. 转换链TransformChain
from langchain.chains import TransformChain, LLMChain, SimpleSequentialChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
# 模拟超长文本
with open("../../state_of_the_union.txt") as f:
state_of_the_union = f.read()
# 定义转换方法,入参和出参都是字典,取前三段
def transform_func(inputs: dict) -> dict:
text = inputs["text"]
shortened_text = "\n\n".join(text.split("\n\n")[:3])
return {"output_text": shortened_text}
# 转换链:输入变量:text,输出变量:output_text
transform_chain = TransformChain(
input_variables=["text"], output_variables=["output_text"], transform=transform_func
)
# prompt模板描述
template = """Summarize this text:
{output_text}
Summary:"""
# prompt模板
prompt = PromptTemplate(input_variables=["output_text"], template=template)
# llm链
llm_chain = LLMChain(llm=OpenAI(), prompt=prompt)
# 使用顺序链
sequential_chain = SimpleSequentialChain(chains=[transform_chain, llm_chain])
# 开始执行
sequential_chain.run(state_of_the_union)
# 结果
"""
' The speaker addresses the nation, noting that while last year they were kept apart due to COVID-19, this year they are together again.
They are reminded that regardless of their political affiliations, they are all Americans.'
"""
2.4.6. LangChain表达式语言 (LCEL)
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
# 原始字符串模板
template = "猪八戒吃{fruit}?"
prompt = PromptTemplate.from_template(template)
# 创建模型实例
llm = OpenAI(temperature=0)
# 创建Chain
chain = prompt | llm
# 调用Chain,返回结果
result = chain.invoke({"fruit": "人参果"})
print(result)
超快速开发链。 高级特性,如流式处理、异步、并行执行等。 与 LangSmith 和 LangServe 等工具集成。
LCEL 语法样例
为了理解 LCEL 语法,让我们首先使用传统的 LangChain 语法构建一个简单的链。
# 导入所需的模块和类
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.chains import LLMChain
# 创建聊天提示模板,指定要获取关于的主题
prompt = ChatPromptTemplate.from_template(
"给我一个关于{topic}的一句话介绍"
)
# 创建ChatOpenAI模型实例
model = ChatOpenAI(temperature=0)
# 创建输出解析器实例
output_parser = StrOutputParser()
# 创建LLMChain链,将聊天提示、模型和输出解析器组合在一起
chain = LLMChain(
prompt=prompt,
llm=model,
output_parser=output_parser
)
# 运行链,并指定主题为"大语言模型"
out = chain.run(topic="大语言模型")
print(out)
# -> 大语言模型是一种基于深度学习的人工智能技术,能够自动学习和生成自然语言文本,具有广泛的应用领域,如机器翻译、文本生成和对话系统等
而通过 LCEL 语法,我们使用管道操作符( |
)而不是LLMChain
来创建我们的链。
# 使用 LangChain Expression Language(LCEL)创建链
lcel_chain = prompt | model | output_parser
# 运行链,并通过字典传递主题为"大语言模型"
out = lcel_chain.invoke({"topic": "大语言模型"})
print(out)
# -> 大语言模型是一种基于深度学习的人工智能技术,能够自动学习和生成自然语言文本,具有广泛的应用领域,如机器翻译、文本生成和对话系统等
|
操作符简单地将左侧的输出传递给右侧的函数。管道运算符的工作原理
|
运算符(如 a
|
b
)时,它会尝试将对象 a
传递给对象 b
的 __or__
方法。# 对象方法
chain = a.__or__(b)
chain("一些输入")
# 管道方法
chain = a | b
chain("一些输入")
Runnable
类,它接受一个函数并将其转换为可以使用管道运算符 |
与其他函数链接的函数。class Runnable:
def __init__(self, func):
self.func = func
def __or__(self, other):
def chained_func(*args, **kwargs):
# 其他函数使用这个函数的结果
return other(self.func(*args, **kwargs))
return Runnable(chained_func)
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
def add_five(x):
return x + 5
def multiply_by_two(x):
return x * 2
# 使用 Runnable 包装这些函数
add_five = Runnable(add_five)
multiply_by_two = Runnable(multiply_by_two)
# 使用对象方法运行它们
chain = add_five.__or__(multiply_by_two)
print(chain(3)) # (3 + 5) * 2 = 16
# -> 16
__or__
我们会得到正确答案,让我们尝试使用管道操作符 |
将它们链接在一起:# 将可运行的函数链接在一起
chain = add_five | multiply_by_two
# 调用链
print(chain(3)) # (3 + 5) * 2 = 16
# -> 16
RunnableLambda
是一个 LangChain 抽象,它允许我们将 Python 函数转换为与管道兼容的函数,类似于我们在之前介绍的 Runnable
类。 让我们尝试一下我们之前的 add_five
和 multiply_by_two
函数。from langchain_core.runnables import RunnableLambda
# 使用 RunnableLambda 包装这些函数
add_five = RunnableLambda(add_five)
multiply_by_two = RunnableLambda(multiply_by_two)
Runnable
抽象类似,我们可以使用 |
运算符将 RunnableLambda
抽象连接在一起:# 将可运行的函数链接在一起
chain = add_five | multiply_by_two
Runnable
抽象不同,我们不能通过直接调用它来运行 RunnableLambda
链,而是必须调用 chain.invoke
:# 调用链
print(chain.invoke(3))
# -> 16
RunnableLambda
获得了和 Runnable
类似的结果。2.4.7. LangChain预置链
LangChain中提供了很多种类型的预置链,目的是使各种各样的任务实现起来更加方便、规范。
1.使用LCEL构建的链,LangChain提供了一个更高级别的构造方法,实际上所有工作都是使用LCEL构建链。
2.[遗留]通过从继承自遗留Chain类构建的链,这些链独立于LCEL而存在。
访问LangChain文档,搜索链名称,查看具体用法。
LCEL Chains:链构造器
链构造器:这是链的构造函数,返回 LCEL 可运行对象的方法。可查看API文档了解更多信息。
函数调用:确定是否需要调用OpenAI函数。
其他工具:在链中使用了哪些其他工具(如果有的话)。
链构造器 | 函数调用 | 其他工具 | 使用场景 |
Legacy Chains:遗留链
链:链的名称,或构造方法的名称。如果是构造方法,这将返回一个Chain子类。
函数调用:是否需要OpenAI函数调用。
其他工具:链中使用的其他工具。
链 | 函数调用 | 其他工具 | 使用场景 |
2.5. LangChain Memory(记忆)
通过 Memory ,实现 上下文管理能力。 Token的消费控制 , 通过Memory ,减少Token使用, 降低 成本。
上下文管理能力 如何实现?
import openai
openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello"},
]
)
import openai
openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hello, how can I help you?"},
{"role": "user", "content": "who is more stylish Pikachu or Neo"},
]
)
2.5.1. 简单实现对话 ConversationBufferMemory
# 导入所需的库
from langchain.llms import OpenAI
from langchain.chains import ConversationChain
from langchain.chains.conversation.memory import ConversationBufferMemory
# 初始化大语言模型
# 大模型定义
api_key = ""
api_url = ""
modal= "baichuan"
llm = OpenAI(model_name=modal,openai_api_key=api_key,openai_api_base=api_url,temperature=0.0)
# 初始化对话链
conversation = ConversationChain(
llm=llm,
memory=ConversationBufferMemory()
)
# 第一天的对话
# 回合1
conversation("我姐姐明天要过生日,我需要一束生日花束。")
print("第一次对话后的记忆:", conversation.memory.buffer)
# 回合2
conversation("她喜欢粉色玫瑰,颜色是粉色的。")
print("第二次对话后的记忆:", conversation.memory.buffer)
# 回合3 (第二天的对话)
conversation("我又来了,还记得我昨天为什么要来买花吗?")
print("/n第三次对话后时提示:/n",conversation.prompt.template)
print("/n第三次对话后的记忆:/n", conversation.memory.buffer)
记忆容量有限,长对话下容易撑爆内存 对话噪声也全部记住,降低有效信息密度
2.5.2. 时间窗口记忆ConversationBufferWindowMemory
# 导入所需的库
from langchain.llms import OpenAI
from langchain.chains import ConversationChain
from langchain.chains.conversation.memory import ConversationBufferWindowMemory
# 初始化大语言模型
# 大模型定义
api_key = ""
api_url = ""
modal= "baichuan"
llm = OpenAI(model_name=modal,openai_api_key=api_key,openai_api_base=api_url,temperature=0.0)
# 初始化对话链
conversation = ConversationChain(
llm=llm,
memory=ConversationBufferWindowMemory(k=1)
)
# 第一天的对话
# 回合1
result = conversation("我姐姐明天要过生日,我需要一束生日花束。")
print(result)
# 回合2
result = conversation("她喜欢粉色玫瑰,颜色是粉色的。")
print("\n第二次对话后的记忆:\n", conversation.memory.buffer)
print(result)
# 第二天的对话
# 回合3
result = conversation("我又来了,还记得我昨天为什么要来买花吗?")
print(result)
窗口越大,记住的内容越多 窗口越小,记忆更加重点和精炼
2.5.3. ConversationSummaryMemory
文档太长,超过了 平台限制........ 这部分详细内容略,请参见 技术自由圈 PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
2.5.4.ConversationSummaryBufferMemory
文档太长,超过了 平台限制........ 这部分详细内容略,请参见 技术自由圈 PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
2.5.5. ConversationTokenBufferMemory
文档太长,超过了 平台限制........ 这部分详细内容略,请参见 技术自由圈 PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
2.5.6. 对话知识图谱记忆ConversationKGMemory
文档太长,超过了 平台限制........ 这部分详细内容略,请参见 技术自由圈 PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
2.5.7. 基于向量存储记忆 VectorStoreRetrieverMemory
文档太长,超过了 平台限制........ 这部分详细内容略,请参见 技术自由圈 PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
2.6. Agents(代理)
文档太长,超过了 平台限制........ 这部分详细内容略,请参见 技术自由圈 PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
2.6.1. Action agents
文档太长,超过了 平台限制........ 这部分详细内容略,请参见 技术自由圈 PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
2.6.2. Plan-and-execute agents
文档太长,超过了 平台限制........ 这部分详细内容略,请参见 技术自由圈 PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
3. LangChain 实战
3.1. 案例1:完成一次问答
文档太长,超过了 平台限制........ 这部分详细内容略,请参见 技术自由圈 PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
3.2. 案例二:通过谷歌搜索并返回答案
文档太长,超过了 平台限制........ 这部分详细内容略,请参见 技术自由圈 PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
3.3. 案例三:对超长文本进行总结
文档太长,超过了 平台限制........ 这部分详细内容略,请参见 技术自由圈 PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
3.4. 构建本地知识库问答机器人
文档太长,超过了 平台限制........ 这部分详细内容略,请参见 技术自由圈 PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
3.5.构建本地Chroma向量索引数据库
文档太长,超过了 平台限制........ 这部分详细内容略,请参见 技术自由圈 PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
3.6. 实战: 基于 Langchain+私有模型,构建一个生成级RAG 聊天机器人
3.7. 实战: 基于 Langchain+公有模型,构建一个生成级RAG 聊天机器人
3.8. 基于 LangChain 构建的开源应用
文档太长,超过了 平台限制........ 这部分详细内容略,请参见PDF 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》
说在最后:有问题找老架构取经
《LLM大模型学习圣经:从0到1吃透Transformer技术底座》 《LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架》 《LLM大模型学习圣经:从0到1精通RAG架构,基于LLM+RAG构建生产级企业知识库》 《SpringCloud + Python 混合微服务架构,打造AI分布式业务应用的技术底层》 《LLM大模型学习圣经:从0到1吃透大模型的顶级架构》
Netty 学习圣经:穿透Netty的内存池和对象池(那个超级难,很多人穷其一生都搞不懂), DDD学习圣经: 穿透 DDD的建模和落地, Caffeine学习圣经:比如Caffeine的底层架构, 比如高性能葵花宝典 Thread Local 学习圣经 等等等等。
部分历史案例
实现职业转型,极速上岸
关注职业救助站公众号,获取每天职业干货
助您实现职业转型、职业升级、极速上岸
---------------------------------
实现架构转型,再无中年危机
关注技术自由圈公众号,获取每天技术千货
一起成为牛逼的未来超级架构师
几十篇架构笔记、5000页面试宝典、20个技术圣经
请加尼恩个人微信 免费拿走
暗号,请在 公众号后台 发送消息:领电子书
如有收获,请点击底部的"在看"和"赞",谢谢