Akemi

langchain模块介绍与简单案例

2025/11/25

langchain是一个框架,用以

  • 集成大语言模型、其他数据源(文档、数据库、应用库等)
  • 让不同来源的数据进行交互
  • 支持链,一连串的动作

langchain的基础数据类型

  • texts 自然语言交互
  • chat messages 特定消息分类
  • system:提供背景信息,告诉AI需要做什么
  • human:用户信息
  • AI:AI给出的回应
  • documents 文本和元数据
  • examples 例子(代表了函数的输入以及预期输出

langchain的组件

  • 模型-IO输入输出
  • 数据连接
  • 文档加载器:加载不同来源的文档
  • 文档转换器:拆分文档,将文档转换为QA格式等
  • 文本嵌入模型:将非结构化的文档转换为浮点数列表
  • 向量存储:存储和检索嵌入数据
  • 检索器:查询数据
  • 链:将chain定义为对组件的一系列的调用
  • 记忆:记忆上下文,如聊天机器人
  • 代理:使用多种工具,比如API

windows配置环境

  • 下载anaconda与navigator,打开vscode
  • 在anaconda prompt中创建虚拟环境
1
2
3
4
5
6
7
8
# 创建虚拟环境
conda create -n deepseek python=3.13

# 切换虚拟环境
conda activate deepseek

# 安装langchain与deepseek相关组件
pip install langchain==0.3.17 langchain-community==0.3.16 langchain-core==0.3.34 langchain-deepseek==0.1.1 langchain-openai==0.3.3 faiss-cpu==1.10.0 rich==13.9.4
  • 创建项目目录
  • vscode或pycharm切换解释器为虚拟环境
  • 写入.env与python文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from langchain_core.prompts import ChatMessagePromptTemplate
from langchain_deepseek import ChatDeepSeek
from rich import print
from dotenv import load_dotenv

load_dotenv()

# 用类实例化一个模型,可选deepseek-chat和deepseek-reasoner
llm = ChatDeepSeek(model="deepseek-chat")

# 提示语模板
prompt = "我可以解决{subject}的问题"

# 给提示语模板创建一个角色
chat_message_prompt = ChatMessagePromptTemplate.from_template(role="销售顾问",template=prompt)

# 填写模板内容
formatted_prompt = chat_message_prompt.format(subject="产品咨询")

# 生成最终提示语
prompts = [str(formatted_prompt)]

# 让大模型针对prompts进行回答
response = llm.generate(prompts)

print(response)

linux配置环境

使用python直接创建虚拟环境

1
2
3
4
python3 -m venv ~/venv/lanchain/
source ~/venv/lanchain/bin/activate

# 这种创建出来的版本和python命令本身有关

使用miniconda创建虚拟环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cd ~
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
chmod +x Miniconda3-latest-Linux-x86_64.sh
./Miniconda3-latest-Linux-x86_64.sh

# 同意条款
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r

#
conda create -n langchain python=3.12 -y
conda activate langchain

#
pip3 install langchain-huggingface langchain==0.3.17 langchain-community==0.3.16 langchain-core==0.3.34 langchain-deepseek==0.1.1 faiss-cpu==1.10.0 rich==13.9.4 sentence-transformers chromadb

--upgrade-strategy only-if-needed
--force-reinstall

pip freeze > requirements.txt

词向量嵌入embedding与简单案例

embedding:将词语、短语、句子转换为数值向量的过程,这个是计算机可以识别的

最终会变成一个向量数据库

词向量嵌入的最终目的是让机器能理解文本

embedding的过程

  • 初始化:每个词分配一个随机的向量
  • 上下文学习:相似的向量靠近
  • 优化:梯度下降的方式调整向量

embedding的作用

  • 文本分类:将一段文本的词向量相加或平均,从而判断文本的分类,例如情感分析积极/消极
  • 文本相似度:两段文本的相似度
  • 消除文本歧义:确定一个词在上下文中的含义
  • 机器翻译:源语言的词会与目标语言的词向量相似

之后就可以使用数学方法,对其进行比较、运算,从而知道词与词、句子与句子之间的关系

嵌入向量数据库

将词向量保存到一个库中,就是嵌入向量数据库,用以节省算力与时间

生成向量数据库的步骤

首先需要一些数据,可以是文本或大量文件

文本→文本切割:大语言模型通常有一个固定的输入长度限制,将文本分割得更小,可以确保模型能够处理所有输入

选择嵌入模型:使用一个向量模型,用来将词转换成向量

将文本保存到向量数据库中:指定向量模型、文本、存储路径等参数

1
2
3
4
5
6
7
8
9
10
# 向量数据库初始化,使用免费的本地嵌入模型embeddings
from langchain_community.vectorstores import Chroma
from langchain_huggingface import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-MiniLM-L6-v2",
# sentence-transformers/all-mpnet-base-v2 或 sentence-transformers/all-MiniLM-L6-v2
model_kwargs={'device': 'cpu'}
)
db = Chroma.from_documents(texts, embeddings,persist_directory="./chroma_db")
print("向量数据库创建完成!")

使用向量数据库

使用向量数据库需要使用retirever,,将它们插入到一个提示中

然后再将该提示传递给LLM

1
2
3
4
5
6
7
8
9
10
11
12
# 创建检索器
retirever = docsearch.as_retirever()
chain = RetrievalQAWithSourcesChain.from_chain_type(
llm=llm,
# stuff是一种文档链,可以接收一系列文档
chain_type = "stuff",
retriever = retriever,
return_source_document = True
)

question = '小明在哪'
result = chain({"question": question})

model IO-简单案例

通过提示语Prompt进行输入

Prompt可以附带Template模板

模板中可以自定义输入的内容与输出的格式,形成Prompt template

最普通的prompt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 最普通的prompt
from langchain_deepseek import ChatDeepSeek
from dotenv import load_dotenv

load_dotenv()

llm = ChatDeepSeek(model="deepseek-chat")

prompt = "今天11月12号,明天几号?"

response = llm.invoke(prompt)
print(response.content)

# 今天是 11 月 12 号,那么明天就是 **11 月 13 号**。

使用prompt模板

这种模板可以用变量(占位符)接受用户输入,然后转换为模板之后向llm提问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 添加可由用户添加变量
from langchain_deepseek import ChatDeepSeek
from langchain.prompts import PromptTemplate
from dotenv import load_dotenv

load_dotenv()

llm = ChatDeepSeek(model="deepseek-chat")

template = """
你是一个导游,帮我回答以下问题,每次回答不超过两句话。
我想去{location}旅游,有什么景点可以推荐?
"""

prompt = PromptTemplate(
input_variables=["location"],
template=template
)

# 最终输入
final_prompt = prompt.format(location='浙江绍兴越城区')
print(final_prompt)

response = llm.invoke(final_prompt)
print(response.content)

# 输出
你是一个导游,帮我回答以下问题,每次回答不超过两句话。
我想去浙江绍兴越城区旅游,有什么景点可以推荐?

我推荐您游览鲁迅故里和沈园,它们都位于绍兴越城区。鲁迅故里可以了解文学巨匠的成长足迹,沈园则以其古典园林和陆游诗词闻名。

格式化输出器,告诉llm用何种格式进行相应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 格式化输出器,告诉llm用何种格式进行相应
from langchain.output_parsers import StructuredOutputParser,ResponseSchema
from langchain.prompts import ChatMessagePromptTemplate,HumanMessagePromptTemplate
from langchain.prompts import PromptTemplate
from langchain_deepseek import ChatDeepSeek
from dotenv import load_dotenv

load_dotenv()

llm = ChatDeepSeek(model="deepseek-chat")

# 定义输出结构
response_schemas = [
ResponseSchema(name="错误的文字",description="这里输入错误的问题"),
ResponseSchema(name="正确的文字",description="纠正后正确的文字")
]

# 定义输出解析器
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)

# 获取输出指令
format_instrustions = output_parser.get_format_instructions()
print(format_instrustions)

tempalte = """你是一个语文老师,需要帮助用户修改错别字:识别并修改用户输入的语句中的错别字,并且确保输出的文字是正确的
用户输入:{user_input}
以{output_format}的格式输出"""

# 将输入格式加入到提示词模板中
prompt = PromptTemplate(
input_variables = ["user_input"],
partial_variables = {"output_format": format_instrustions},
template = tempalte
)

# 加入变量
final_prompt = prompt.format(user_input="今天天奇振豪啊")
print(final_prompt)

response = llm.invoke(final_prompt)
print(response.content)

# 输出
你是一个语文老师,需要帮助用户修改错别字:识别并修改用户输入的语句中的错别字,并且确保输出的文字是正确的
用户输入:今天天奇振豪啊
以The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":

"错误的文字": string // 这里输入错误的问题
"正确的文字": string // 纠正后正确的文字
的格式输出

"错误的文字": "今天天奇振豪啊",
"正确的文字": "今天天气真好啊"

链接数据-文件加载、分割简单案例

  • 文档加载器loader:通过网络、本地的方式将文件加载到加载器中,便于处理和传送给大模型
  • 文档分割器text splitters:大模型无法一次输入大量token,所以需要对文档进行分割,然后再传入向量数据库
  • 文本搜索器retriever:在向量数据库中进行搜索

从本地加载文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from langchain.output_parsers import StructuredOutputParser,ResponseSchema
from langchain.prompts import ChatMessagePromptTemplate,HumanMessagePromptTemplate
from langchain.prompts import PromptTemplate
from langchain_deepseek import ChatDeepSeek
from dotenv import load_dotenv
from transformers import AutoTokenizer
from langchain_community.document_loaders import WebBaseLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 加载一个本地文件test.txt
with open('./test.txt') as f:
doc = f.read()

# 计算使用tokens
tokenizer = AutoTokenizer.from_pretrained("deepseek-ai/deepseek-llm-7b-chat")
tokens = tokenizer.encode(doc)
token_count = len(tokens)
# print(f"文本: {doc}")
print(f"Token 数量: {token_count}")
# print(f"Tokens: {tokens}")

# 准备对文件进行切分
text_splitter = RecursiveCharacterTextSplitter(
chunk_size = 150,
chunk_overlap = 20
)

texts = text_splitter.create_documents([doc])
print(f"一共有{len(texts)}个小文档")
CATALOG
  1. 1. windows配置环境
  2. 2. linux配置环境
  3. 3. 词向量嵌入embedding与简单案例
    1. 3.1. 生成向量数据库的步骤
    2. 3.2. 使用向量数据库
  4. 4. model IO-简单案例
  5. 5. 链接数据-文件加载、分割简单案例