Deepseek基础,模板引擎,prompt提示词,增强检索,智能机器人

文章目录

Deepseek

Deepseek基础

1.产品介绍

DeepSeek-V3 是一款高性能的开源 AI 模型,支持自然语言处理、智能对话生成等任务。其 API 接口与OpenAI 完全兼容,用户可以通过简单的配置迁移现有项目,同时享受更低的成本和更高的性能。本文档将详细介绍如何快速接入 DeepSeek-V3 API

2.创建API key

注意:创建后API key只出现一次,请存储在安全位置,例如:环境变量或者配置文件中

3.使用Python调用API

1)安装OpenAI API库

python 复制代码
pip insatll openai

2)API 是一个"无状态" API,即服务端不记录用户请求的上下文,用户在每次请求时,需将之前所有对话历史拼接好后,传递给对话 API。

在系统环境变量里新建名称:OPENAI_AI_KEY 值:sk-341b33ffcc4d4fa8a3acedxxxxxxxxxx

对话应用:

python 复制代码
import os
from openai import OpenAI, base_url

#创建客户端
client = OpenAI(
    #存放在用户环境变量中
    api_key = os.getenv('deepseek_key'),
    base_url = 'https://api.deepseek.com')

#发送对话获取响应信息
response = client.chat.completions.create(
    #模型类型
    model = 'deepseek-chat',
    messages = [
        {'role':'system','content':'你是一位运维工程师助手'},
        {'role':'user','content':input('请输入你的需求:')}
    ],
    #流式输出
    stream = False
)
#展现回应信息
print(response.choices[0].message.content)

运行结果

python 复制代码
请输入你的需求:你是谁
我是DeepSeek,由深度求索公司创造的AI助手!😊

我是一个纯文本模型,虽然不支持多模态识别功能,但我有文件上传功能,可以帮你处理图像、txt、pdf、ppt、word、excel等文件,并从中读取文字信息进行分析处理。

我的一些特点:
- 完全免费使用,没有收费计划
- 上下文长度达128K,可以处理很长的对话
- 支持联网搜索(需要你手动点开联网搜索按键)
- 可以通过官方应用商店下载App使用
- 知识截止到2024年7月

作为运维工程师助手,我可以帮你处理各种运维相关的问题,比如系统管理、网络配置、故障排查、脚本编写、性能优化等等。有什么具体的运维问题需要我帮忙解决吗?
python 复制代码
from openai import OpenAI, base_url
import os

test = input('请输入问题:\n')
print('正在与Deepseek对话,请稍等...')

#生成客户端
client = OpenAI(
    api_key = os.getenv('deepseek_key'),
    base_url = 'https://api.deepseek.com'
)

#生成消息
messages = [{
    'role':'user',
    'content':test
}]

#使用stream=True启用流式响应逐行获取响应
response = client.chat.completions.create(
    model = 'deepseek-chat',
    messages = messages,
    stream = True
)

#逐行显示响应内容
print('deepseek回复:')
for line in response:
    if line.choices[0].delta.content :
        print(line.choices[0].delta.content,end='')
print()

while True:
    test = input('继续提问:')
    messages.append({\
        'role':'user',
        'content':test})
    response = client.chat.completions.create(
        model = 'deepseek-chat',
        messages = messages,
        stream = True
    )
    print('deepseek回复:')
    for line in response:
        if line.choices[0].delta.content :
            print(line.choices[0].delta.content,end='')
    print()

运行结果

python 复制代码
请输入问题:
你是谁
正在与Deepseek对话,请稍等...
deepseek回复:
你好!我是DeepSeek,由深度求索公司创造的AI助手!😊

我是一个纯文本模型,虽然不支持多模态识别功能,但我有文件上传功能,可以帮你处理图像、txt、pdf、ppt、word、excel等文件,并从中读取文字信息进行分析处理。我完全免费使用,拥有128K的上下文长度,还支持联网搜索(需要你在Web/App中手动点开联网搜索按键)。

你可以通过官方应用商店下载我的App来使用我。我很乐意帮助你解答问题、处理文档、进行对话交流等等!

有什么我可以帮你的吗?无论是学习、工作还是日常问题,我都很愿意协助你!✨
继续提问:写一首夏天的歌
deepseek回复:
你好!我是DeepSeek,由深度求索公司创造的AI助手,很高兴为你服务!😊

让我为你创作一首关于夏天的歌:

**《夏日的风记得》**

(Verse 1)
蝉鸣拉开七月的序幕
阳光在树叶间跳舞
冰镇汽水冒着气泡
单车铃声穿过林荫道

(Chorus)
夏日的风记得
我们奔跑的轮廓
汗水滴落成星河
青春在指尖闪烁
这个季节不会褪色
就像你眼里的光热

(Verse 2)
傍晚天空橘子味颜色
云朵像融化的糖果
球场上的欢呼声
随着夕阳慢慢沉没

(Bridge)
日记本里夹着干枯花瓣
那年夏天许下的愿望
虽然时间一直往前赶
这份温热永远在心上

(Outro)
蝉声渐远,夏天未完
风里还有我们的歌
在每一个七月循环......

希望这首歌能让你感受到夏天的美好气息!🌞 需要我为你调整任何部分,或者有其他创作需求吗?
继续提问:

模版引擎

PromptTemplate教程

一、课程背景

在使用大语言模型(LLM)时,**Prompt(提示词)**决定了模型的行为方式。

如果 Prompt 写死在代码中,会导致:

难以复用

难以维护

不利于扩展

LangChain 提供了 PromptTemplate ,用于参数化、标准化 Prompt

二、示例代码

python 复制代码
from langchain_core.prompts import PromptTemplate

prompt = PromptTemplate.from_template(
    '你是一位{name},请为这个小孩起一个带有{country}特色的名字'
)
print(prompt.format(name='算命大师',country='中国'))

三、运行结果

python 复制代码
你是一位算命大师,请为这个小孩起一个带有中国特色的名字

四、逐行代码讲解

1.导入 PromptTemplate
python 复制代码
from langchain_core.prompts import PromptTemplate

PromptTemplate 是 LangChain 中用于构建 文本 Prompt 模板 的核心类。

2.使用 from_template 创建模板
python 复制代码
prompt = PromptTemplate.from_template(
    '你是一位{name},请为这个小孩起一个带有{country}特色的名字'
)

关键点说明:

使用的是 f-string 风格占位符

{name} 、 {county} 是 变量

模板本身是"静态文本 + 占位符"

!WARNING

注意:这里不是 Python 的 f-string

而是 LangChain 在运行时做变量替换

3.使用format传入变量
python 复制代码
print(prompt.format(name='算命大师',country='中国'))

LangChain 会:

  • 检查变量是否齐全

  • 自动替换占位符

  • 返回最终 Prompt 字符串

五、PromptTemplate 的优势

1.Prompt 参数化
python 复制代码
prompt.format(name='智者',country='英语')
prompt.format(name='导师',country='法国')
2.为后续链式调用打基础

PromptTemplate 是:

  • LLMChain

  • Runnable

  • ChatPromptTemplate

的基础组件。

一、模板引擎(Template Engine)

模板引擎的核心作用:

把「固定文本」 + 「变量占位符」组合成一段 可复用的动态文本

在 Web、AI、自动化脚本中非常常见,例如:

  • HTML 页面渲染

  • 自动生成文档

  • AI Prompt(提示词)拼装

二、Python 内置模板:f-string

Python 3.6 以后内置了一种最简单、最高效的模板方式:f-string

最基础的 f-string 示例

python 复制代码
name = "马化腾"
what = "创业"
text = f"给我讲一个关于{name}的{what}故事"
print(text)

运行结果

python 复制代码
给我讲一个关于马化腾的创业故事
特点
  • {} 中直接写变量名

  • 运行时自动替换

  • 语法简单、性能高

多行f-string模版

python 复制代码
fstring_template = '''
给我讲一个关于{name}的{what}故事
'''

这是一个多行字符串模板,非常适合:

  • Prompt

  • 文案

  • 邮件

  • 长文本生成

三、LangChain 中的 PromptTemplate 本质是什么?

PromptTemplate 本质上就是:

用 Python 的 f-string 思想,封装了一层"专业 Prompt 模板工具"

🔹 第一步:导入PromptTemplate

python 复制代码
from langchain_core.prompts import PromptTemplate

🔹 第二步:定义模板字符串

python 复制代码
fstring_template = '''
给我讲一个关于{name}的{what}故事
'''
  • {name} 、 {what} 是 占位符

  • 语法与 Python f-string 完全一致

  • 但此时只是字符串,还没有替换

🔹 第三步:创建 PromptTemplate 对象

python 复制代码
prompt = PromptTemplate.from_template(fstring_template)

这一步 LangChain 会:

  • 解析模板

  • 自动识别变量: name 、 what

  • 构建一个"可复用 Prompt 对象"

🔹 第四步:传入参数并格式化

python 复制代码
print(prompt.format(name='马化腾', what='创业'))

效果等价于:

python 复制代码
f"给我讲一个关于{'马化腾'}的{'创业'}故事"

输出:

python 复制代码
给我讲一个关于马化腾的创业故事

示例:

python 复制代码
from langchain_core.prompts import PromptTemplate

fstring_template = '''
给我讲一个关于{name}的{what}故事
'''
prompt = PromptTemplate.from_template(fstring_template)

print(prompt.format(name='马化腾',what='创业'))

运行结果

python 复制代码
给我讲一个关于马化腾的创业故事

四、PromptTemplate vs 直接 f-string

Jinja2 模板生成 AI Prompt

一、为什么需要 Jinja2 模板?

在 AI 应用中,我们经常需要动态生成大量 Prompt,例如:

  • 生成 HTML / Markdown 文档

  • 构造复杂 Prompt(条件、循环)

  • 批量生成结构化提示词

如果只使用 Python 的 f-string:

python 复制代码
f"给我讲一个关于{name}的{what}故事"

一旦 Prompt 变复杂,就会变得难维护、难扩展

👉 这正是 Jinja2 模板引擎的价值所在。

二、什么是 Jinja2?

Jinja2 Python 生态中最流行的模板引擎之一

常见应用场景:

  • Flask / FastAPI 的 HTML 模板

  • Markdown / 文档生成

  • 配置文件(YAML / JSON)

  • AI Prompt 模板(LangChain)

三、环境准备

安装依赖

python 复制代码
pip insatll jinja2

LangChain 在使用 template_format="jinja2" 时,底层会调用 Jinja2。

四、Jinja2 模板基本语法

变量占位符
python 复制代码
{{ variable_name }}

示例:

python 复制代码
给我讲一个关于{{name}}的{{what}}故事

五、LangChain + Jinja2 实战

完整示例代码

python 复制代码
from langchain_core.prompts import PromptTemplate

jinja2_template = '给我讲一个关于{{name}}的{{what}}'

prompt = PromptTemplate.from_template(
    jinja2_template,
    template_format='jinja2'
)
print(prompt.format(name='马化腾',what='创业'))

运行结果

python 复制代码
给我讲一个关于马化腾的创业

六、逐行代码解析

🔹 第一步:导入 PromptTemplate
python 复制代码
from langchain_core.prompts import PromptTemplate

PromptTemplate 是 LangChain 中用于构造提示词模板的核心类。

🔹 第二步:定义 Jinja2 模板字符串
python 复制代码
jinja2_template = '给我讲一个关于{{name}}的{{what}}故事'
  • {{name}} 、 {{what}} 是 Jinja2 变量

  • 与 f-string 的 {} 不同,Jinja2 使用 双大括号

🔹 第三步:指定模板格式为 jinja2
python 复制代码
prompt = PromptTemplate.from_template(
    jinja2_template,
    template_format='jinja2'
)

这是关键点

默认模板格式是 f-string

使用 Jinja2 必须显式指定:

python 复制代码
template_format='jinja2'
🔹 第四步:传入参数并渲染模板
python 复制代码
print(prompt.format(name='马化腾',what='创业'))

LangChain 会:

  • 调用 Jinja2 渲染模板

  • 用传入的参数替换变量

  • 输出最终 Prompt 字符串

七、Jinja2 vs f-string(教学对比)

八、Jinja2 的核心优势

条件控制(if)
python 复制代码
{% if level == "easy" %}
要求:语言简单,适合初学者
{%elif level == "hard" %}
要求:包含商业分析和战略思考
{% endif %}

非常适合生成结构化内容

  • HTML

  • Markdown

  • JSON

  • YAML

  • Prompt 模板

九、典型案例

场景:生成不同难度的故事 Prompt
python 复制代码
from langchain_core.prompts import PromptTemplate

jinja2_template = '''给我讲一个关于{{name}}的{{what}}
{% if level == "easy" %}
要求:语言简单,适合初学者
{%elif level == "hard" %}
要求:包含商业分析和战略思考
{% endif %}
'''

prompt = PromptTemplate.from_template(
    jinja2_template,
    template_format='jinja2'
)
print(prompt.format(name='马化腾',what='创业',level='hard'))

运行结果

python 复制代码
给我讲一个关于马化腾的创业

要求:包含商业分析和战略思考

十、总结

  • f-string:简单 Prompt

  • Jinja2:复杂 Prompt

  • PromptTemplate:Prompt 工程化核心工具

  • Jinja2 + LangChain = 可维护、可扩展的 AI Prompt

Prompt 序列化:使用文件管理提示词

一、为什么要"序列化 Prompt"?

在初学阶段,很多人直接把 Prompt 写在代码里,但是在真实项目,会带来很多问题

二、Prompt 序列化的核心价值

1.便于共享
  • Prompt 文件可以直接发给同事

  • 不依赖具体代码逻辑

  • AI 产品经理 / 运营 / 教研人员也能参与修改

2.便于版本控制
  • Prompt 文件可以进入 Git

  • 清楚看到 Prompt 的演进历史

  • 支持回滚、对比(diff)

3.便于存储与复用
  • 一个 Prompt 文件 = 一个"能力模块"

  • 可在多个项目中复用

  • 避免 Prompt 散落在代码各处

4.支持多种格式

LangChain 原生支持:

  • json

  • yaml / yml

👉 非常适合工程化 Prompt 管理。

三、LangChain 中的 load_prompt

LangChain 提供了专门的 API:

python 复制代码
from langchain_core.prompts import load_prompt

用于 从文件加载 PromptTemplate 对象

四、JSON 格式 Prompt 示例

1.simple_prompt.json
python 复制代码
{
  "_type": "prompt",
  "input_variables": ["name","what"],
  "template": "给我讲一个关于{name}的{what}故事。"
}

📌 说明:

  • type : Prompt 类型

  • template : Prompt 模板内容

  • input_variables : 必须传入的变量

2.加载 JSON Prompt
复制代码
from langchain_core.prompts import load_prompt

prompt = load_prompt('simple_prompt.json',encoding='utf-8')

print(prompt.format(name = 'dyx',what = 'create'))

输出:

python 复制代码
给我讲一个关于dyx的create故事。

五、YAML 格式 Prompt 示例

1. simple_prompt.yaml
python 复制代码
_type: prompt
input_variables:
  ["name","what"]
template:
  给我讲一个关于{name}的{what}故事。

📌 YAML 优点:

  • 支持多行文本

  • 可读性更好

  • 非程序员更容易修改

2.加载 YAML Prompt
python 复制代码
from langchain_core.prompts import load_prompt
prompt = load_prompt('simple_prompt.yaml',encoding='utf-8')

print(prompt.format(name = 'dyx',what = 'create'))

输出:

python 复制代码
给我讲一个关于dyx的create故事。

输出结果与 JSON 完全一致。

六、Prompt 文件 vs 代码 Prompt 对比

七、总结

  • Prompt 也是"代码资产"

  • 序列化让 Prompt 可管理、可协作

  • JSON / YAML 各有适用场景

  • load_prompt 是 Prompt 工程化的入口

propmt综合案例

一、Runnable 管道

LangChain Runnable 管道,把「性格设定 + 行为规则 + 禁止行为」三层 Prompt 组合成一个完整的 Prompt 字符串。

最终 print(result.to_string()) 只是打印拼接后的 Prompt 文本

⚠ 很关键的一点:

👉 这里只是 Prompt 生成,准备给 LLM 推理

二、逐层拆解 Prompt 输出

✅ 第一层:性格设计
python 复制代码
character_prompt = PromptTemplate.from_template(
    "你是{person},你有着{char}"
)

你传入的参数是:

python 复制代码
"person": "雷军",
"char": "最红企业家,你是目前中国首富,精通计算机、企业管理、商业、你是营销奇才,你的终极梦想是创办一家伟大的公司。"

👉 渲染结果:

python 复制代码
text='你是雷军,你有着最红企业家,你是目前中国首富,精通计算机、企业管理、商业、你是营销奇才,你的终极梦想是创办一家伟大的公司。'
✅ 第二层:行为设计
python 复制代码
behavior_prompt = PromptTemplate.from_template(
    "你遵从以下的行为:{behavior_list}"
)

参数:

python 复制代码
"behavior_list": "1.你敢于挑战创新突破 2.你非常崇拜乔布斯 3.你具备亲和力,耐心回答用户各种问题。",

👉 渲染结果:

python 复制代码
text='你遵从以下的行为:1.你敢于挑战创新突破 2.你非常崇拜乔布斯 3.你具备亲和力,耐心回答用户各种问题。'
✅ 第三层:禁止行为
python 复制代码
prohibit_prompt = PromptTemplate.from_template(
    "你禁止以下行为:{prohibit_list}"
)

参数:

python 复制代码
 "prohibit_list": "1.你不可以说自己是一个智能助手或者机器人 2.当你不知道答案的时候,可以说让我再想想。"

👉 渲染结果:

python 复制代码
text='你禁止以下行为:1.你不可以说自己是一个智能助手或者机器人 2.当你不知道答案的时候,可以说让我再想想。'

三、最终 Prompt 是如何拼接的?

最终模板
python 复制代码
full_prompt = PromptTemplate.from_template(
    "{character}\n{behavior}\n{prohibit}"
)

也就是说:

三段内容,用换行符 \n 拼起来

完整代码

python 复制代码
from langchain_core.prompts import PromptTemplate

#性格设计
character_prompt = PromptTemplate.from_template(
    "你是{person},你有着{char}"
)

#行为设计
behavior_prompt = PromptTemplate.from_template(
    "你遵从以下的行为:{behavior_list}"
)

#禁止行为
prohibit_prompt = PromptTemplate.from_template(
    "你禁止以下行为:{prohibit_list}"
)

#最终 Prompt 模板
full_prompt = PromptTemplate.from_template(
    "{character}\n{behavior}\n{prohibit}"
)

#Runnable 管道组合
chain = (
    {
        "character": character_prompt,
        "behavior": behavior_prompt,
        "prohibit": prohibit_prompt,
    }
    | full_prompt
)

#调用
result = chain.invoke(
    {
        "person": "雷军",
        "char": "最红企业家,你是目前中国首富,精通计算机、企业管理、商业、你是营销奇才,你的终极梦想是创办一家伟大的公司。",
        "behavior_list": "1.你敢于挑战创新突破 2.你非常崇拜乔布斯 3.你具备亲和力,耐心回答用户各种问题。",
        "prohibit_list": "1.你不可以说自己是一个智能助手或者机器人 2.当你不知道答案的时候,可以说让我再想想。"
    }
)

print(result.to_string())

四、最终 print(result.to_string()) 的完整输出

其中text=为调试,并非字符串。

python 复制代码
text='你是雷军,你有着最红企业家,你是目前中国首富,精通计算机、企业管理、商业、你是营销奇才,你的终极梦想是创办一家伟大的公司。'
text='你遵从以下的行为:1.你敢于挑战创新突破 2.你非常崇拜乔布斯 3.你具备亲和力,耐心回答用户各种问题。'
text='你禁止以下行为:1.你不可以说自己是一个智能助手或者机器人 2.当你不知道答案的时候,可以说让我再想想。'

这就是最终输出内容

五、总结

这段代码,其实已经是一个标准 Prompt Engineering 模板设计范式

prompt提示词

LangChain

LangChain 是一个开源框架,专门用来简化大型语言模型(LLM)应用的开发,帮你快速把模型能力接入实际业务。它的核心价值在于降低集成成本,让开发者无需从零搭建就能实现复杂功能。

发展历程

2022年10月:作为 Python 工具发布。

2023年2月:支持 TypeScript。

2023年4月:扩展至多种 JavaScript 环境。

2025年11月:OceanBase AI 数据库兼容 LangChain。

典型应用场景

自动化任务:邮件分类、合同审查、会议纪要生成。

多模态应用:图像描述、语音助手。

代码辅助:生成、解释或调试代码。

个性化推荐:定制化内容生成。

核心组件

  • 模型接口:支持 OpenAI、Anthropic 等主流 LLM,方便切换和扩展。
  • 提示模板:预设结构化提示词,提升生成效果和一致性。
  • 链(Chains):串联多个步骤,支持条件和循环逻辑,适合复杂任务。
  • 代理(Agents):动态调用工具(如搜索、API),实现自动化操作。
  • 记忆模块:短期和长期记忆结合,增强上下文理解。
  • 数据索引:连接外部数据源(如数据库、PDF),提升生成准确性。

会话模板

LangChain 提供了灵活的会话模板系统,支持多轮对话和上下文管理。

ChatPromptTemplate

在 LangChain 里:

  • PromptTemplate:用于单轮文本提示(prompt)

  • ChatPromptTemplate :用于多轮对话(system / human / ai)

👉 ChatPromptTemplate = 对话剧本 + 可替换变量

1.导入 ChatPromptTemplate

python 复制代码
from langchain_core.prompts import ChatPromptTemplate

这是 LangChain 最核心的 Prompt 组件之一,不依赖具体模型(OpenAI、Claude、Qwen 都能用)。

2.定义 messages(对话模板)

python 复制代码
message = [
    ('system','你是一位大师,你的名字是{name}'),
    ('human','你好{name},你感觉如何?'),
    ('ai','你好!我的状态非常好!'),
    ('human','你叫什么名字呢?'),
    ('ai','我叫{name}'),
    ('human','{user_input}')
]

这里是重点 👇

(1)消息角色说明
角色 含义
system 系统设定(人物、规则)
human 用户输入
ai AI的历史回答
(2)这是一个「已存在历史对话」的模板

你不是只写一句 prompt,而是:

AI 已经有人设

已经有历史对话

当前用户再继续说一句话 {user_input}

👉 非常适合 对话机器人 / Agent / Chat 记忆场景

(3) {} 是占位符(变量)
python 复制代码
{name}
{user_input}

这些变量会在 运行时替换

3.用 messages 创建会话模板

python 复制代码
prompt = ChatPromptTemplate(message)

这一句的作用:

把"对话结构 + 变量占位符"变成一个 可复用的 Prompt 对象

4.传入参数,生成最终消息

python 复制代码
print(prompt.format_messages(name='dyx',user_input='你的朋友是谁?'))

发生了什么?

  • {name} → 'chen'

  • {user_input} → '你的朋友是谁呢?'

最终输出的是:

👉 一组 Message 对象列表(不是普通字符串)

运行后的实际效果

等价于下面这段"真实对话":

运行结果

python 复制代码
[SystemMessage(content='你是一位大师,你的名字是dyx', additional_kwargs={}, response_metadata={}), HumanMessage(content='你好dyx,你感觉如何?', additional_kwargs={}, response_metadata={}), AIMessage(content='你好!我的状态非常好!', additional_kwargs={}, response_metadata={}, tool_calls=[], invalid_tool_calls=[]), HumanMessage(content='你叫什么名字呢?', additional_kwargs={}, response_metadata={}), AIMessage(content='我叫dyx', additional_kwargs={}, response_metadata={}, tool_calls=[], invalid_tool_calls=[]), HumanMessage(content='你的朋友是谁?', additional_kwargs={}, response_metadata={})]

⚠ 这正是 大模型最喜欢的输入格式

为什么要用 ChatPromptTemplate?(而不是字符串拼接)

传统方式

问题:

  • 不支持多角色

  • 不利于 Agent / Memory

  • 不可组合

ChatPromptTemplate 的优势
优点 说明
多轮对话 原生支持 system/human/ai
变量安全 自动校验缺失变量
可组合 可与 Memory / Chain / Agent 结合
模型无关 OpenAI / Claude / 本地模型都能用
示例
python 复制代码
from langchain_core.prompts import ChatPromptTemplate

message = [
    ('system','你是一位大师,你的名字是{name}'),
    ('human','你好{name},你感觉如何?'),
    ('ai','你好!我的状态非常好!'),
    ('human','你叫什么名字呢?'),
    ('ai','我叫{name}'),
    ('human','{user_input}')
]

prompt = ChatPromptTemplate(message)

print(prompt.format_messages(name='dyx',user_input='你的朋友是谁?'))

LangChain Message

这是 LangChain 体系里最底层、最稳定的抽象

底层原理

1.SystemMessage ------ 系统指令(人格 + 规则)
python 复制代码
sy = SystemMessage(
    content = '你是一个智能体',
    additional_kwargs = {'智能体名字':'dyx'}
)
SystemMessage 的作用
  • 给模型设定身份 / 行为规则

  • 权重最高(一般模型不会轻易违背)

等价于对模型说:

"接下来你必须按这个身份来回答"

additional_kwargs 是什么?
python 复制代码
ai = AIMessage(
    content= '我的名字叫dyx'
)

这是一个 扩展字段

  • 不一定会被模型"直接理解"

  • 但会在 Agent / Tool / 自定义模型 中非常有用

  • 常用于:

    • 存 metadata
    • 标注角色
    • 业务标识

👉 模型输入 = content

👉 系统/程序用 = additional_kwargs

2.HumanMessage ------ 用户输入
python 复制代码
hum = HumanMessage(
    content = '请问智能体叫什么名字?'
)

代表真实用户的一次提问。

在聊天模型里等价于:

python 复制代码
User: 请问智能体叫什么名字?
3.AIMessage ------ AI 的历史回复
python 复制代码
ai = AIMessage(
    content= '我的名字叫dyx'
)

表示:

  • 这是 已经发生过的一次 AI 回答

  • 常用于:

    • 构造对话上下文
    • 回放历史
    • 测试 / 回放日志
4.打印结果说明了什么?
python 复制代码
for msg in [sy,hum,ai]:
    print(msg.type,msg.content)

你打印的是:

一个标准的 Chat Messages List

👉 这是 ChatModel / Agent / Memory 的通用输入

Message vs PromptTemplate(非常关键)

❓什么时候用 Message?
场景 推荐
精细控制历史对话 ✅ Message
Agent / Tool ✅ Message
手动构造上下文 ✅ Message
❓ 什么时候用 ChatPromptTemplate?
场景 推荐
带变量的模版 ✅ Prompt
批量生成 ✅ Prompt
少写重复代码 ✅ Prompt
实际项目中:二者结合
python 复制代码
PromptTemplate → 生成 messages
Message → 直接拼历史 / 插 Memory

Message 在真实项目里的典型用法

1.构造一段"完整对话历史
python 复制代码
messages = [
    SystemMessage(content='你是一个智能体'),
    HumanMessage(content='你好'),
    AIMessage(content='你好,有什么可以帮你?'),
    HumanMessage(content='你叫什么名字?')
]

👉 直接喂给模型即可

2.从 PromptTemplate 转成 Message(底层一致)
python 复制代码
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
    ('system', '你是一个智能体'),
    ('human', '{question}')
])
msgs = prompt.format_messages(question='你叫什么名字?')

Message 的 type 属性

python 复制代码
for msg in [sy, hm, ai]:
	print(msg.type, msg.content)

输出类似:

python 复制代码
system 你是一个智能体
human 请问智能体叫什么名字?
ai 我叫dyx

👉 模型内部就是靠 type 区分角色

示例

python 复制代码
from langchain_core.messages import SystemMessage,HumanMessage,AIMessage

sy = SystemMessage(
    content = '你是一个智能体',
    additional_kwargs = {'智能体名字':'dyx'}
)

hum = HumanMessage(
    content = '请问智能体叫什么名字?'
)

ai = AIMessage(
    content= '我的名字叫dyx'
)

for msg in [sy,hum,ai]:
    print(msg.type,msg.content)

运行结果

python 复制代码
system 你是一个智能体
human 请问智能体叫什么名字?
ai 我的名字叫dyx

下面我只围绕你这段代码 ,给你写一份从**"为什么存在 → 怎么用 → 什么时候用"的完整教程**。这一步其实已经进入 LangChain Prompt 体系里很高级、但非常有价值的部分了。

ChatMessagePromptTemplate

创建一条"自定义角色"的消息模板,并在运行时把变量填进去,生成一条 Message

这不是普通的 system / human / ai,而是你自己定义的角色

1.导入

python 复制代码
from langchain_core.prompts import (
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
    ChatPromptTemplate,
)

这里导入了 四种 MessagePromptTemplate

类名 用途
SystemMessagePromptTemplate system 角色模板
HumanMessagePromptTemplate human 角色模板
AIMessagePromptTemplate ai 角色模板
ChatMessagePromptTemplate 自定义角色模板

2.定义带变量的模板字符串

python 复制代码
prompt = '有一种英雄主义就是在认清{subject}的真相后,依然热爱{subject}。'

这里:

  • {subject} 是 占位符

  • 同一个变量可以出现多次

  • 会在 format 时统一替换

3.创建"自定义角色"的消息模板

python 复制代码
chat_message_prompt = ChatMessagePromptTemplate.from_template(
    template = prompt,
    role = 'dyx'
)

这是本示例的核心 👇

ChatMessagePromptTemplate 的意义

它允许你:

  • 自定义角色名(不局限 system / human / ai)

  • 构造 多智能体 / 剧情 / 旁白 / 工具角色

这里的角色是:

python 复制代码
role = 'dyx'

这在 Message 层会表现为:

python 复制代码
type = dyx

4.运行时传参,生成 Message

python 复制代码
print(chat_message_prompt.format(subject = '江湖'))
这一步发生了什么?
  • {subject} → '江湖'

  • 返回的是 一条 Message 对象

  • Message 的结构大致是:

python 复制代码
content='有一种英雄主义就是在认清江湖的真相后,依然热爱江湖。' additional_kwargs={} response_metadata={} role='dyx'

示例:

python 复制代码
from langchain_core.prompts import ChatMessagePromptTemplate

prompt = '有一种英雄主义就是在认清{subject}的真相后,依然热爱{subject}。'

chat_message_prompt = ChatMessagePromptTemplate.from_template(
    template = prompt,
    role = 'dyx'
)

print(chat_message_prompt.format(subject = '江湖'))

为什么要用 ChatMessagePromptTemplate?(核心价值)

❓ 不能用 AIMessagePromptTemplate 吗?

可以,但不够强。

方式 限制
AIMessagePromptTemplate 只能是ai
ChatMessagePromptTemplate 任意角色名

把它放进真实对话里

现在只生成了一条 Message,

真实项目一定是"多条 Message 组合"

示例:和 system / human 一起用

python 复制代码
from langchain_core.prompts import (
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
    ChatPromptTemplate,
)

chat_prompt = ChatPromptTemplate.from_messages([
    SystemMessagePromptTemplate.from_template(
        "你正在扮演一部{subject}世界",
    ),
    HumanMessagePromptTemplate.from_template(
        "请发表一句{subject}感情"
    )
])

message = chat_prompt.format_messages(subject='江湖')
for m in message:
    print(m.type,":",m.content)

运行结果

python 复制代码
system : 你正在扮演一部江湖世界
human : 请发表一句江湖感情

和 Message 的关系

PromptTemplate → Message 的转化关系
python 复制代码
ChatMessagePromptTemplate
	↓ format()
ChatMessage (Message)
	↓
ChatModel / Agent

PromptTemplate 永远不会直接喂模型

喂模型的永远是 Message

好,这一步我们就真的把「dyx」交给模型

目标只有一个:

你构造的自定义角色 Message,如何真正驱动大模型说话

我会用最清晰、最短路径带你走完这一跳。

增强检索

增强检索

增强检索(Enhanced Retrieval)通常指在信息检索或大模型应用中,通过更聪明的检索 + 更好的上下文组织 ,显著提升答案的准确性、相关性和可解释性 。最常见的落地形态就是 RAG(Retrieval Augmented Generation,检索增强生成)

一、为什么需要增强检索?

传统大模型的问题:

  • ❌ 只靠参数记忆,不掌握你自己的数据

  • ❌ 容易"幻觉"

  • ❌ 无法实时更新知识

增强检索的目标:

先把"对的资料"找出来,再让模型基于资料回答

二、典型架构(RAG 标准流程)

python 复制代码
用户问题
	↓
Query 改写 / 扩展(可选)
	↓
向量化(Embedding)
	↓
向量数据库检索(Top-K)
	↓
结果重排(Re-ranking)
	↓
上下文拼接(Context Window)
	↓
LLM 生成答案

三、关键"增强"点

1.查询增强(Query Enhancement)

让"问题"更适合被检索:

  • 同义词扩展

  • 多语言转换

  • 多 Query 并行检索(Multi-Query)

示例:

用户: K8s 网络问题

→ 扩展为:

  • Kubernetes CNI
  • Pod 网络通信
  • Service 网络原理
2.检索增强(Hybrid Retrieval)

不要只用向量检索

常见组合:

  • 向量检索(语义)

  • 关键词检索(BM25)

  • 结构化过滤(时间 / 标签 / 权限)

👉 Hybrid Search = 真实生产必选

3.重排增强(Re-ranking)

第一轮检索只是"可能相关"

第二轮用更强模型排序:

  • Cross-Encoder

  • LLM Re-ranker

效果:

👉 Top-5 质量 ≫ Top-50 原始结果

4.上下文增强(Context Engineering)

不是"拼越多越好":

  • Chunk 粒度控制(200--500 tokens)

  • 去重

  • 保留标题 / 来源

  • 加引用标记(source id)

5.生成约束(Grounded Generation)

强制模型:

  • 只基于提供内容回答

  • 找不到就说"不知道"

Prompt 示例:

python 复制代码
仅根据以下资料回答问题,
如果资料中没有答案,请明确说明"资料不足"。

四、常见技术栈

  • Embedding:OpenAI / BGE / E5
  • Vector DB:FAISS / Milvus / Weaviate
  • Keyword:Elasticsearch / OpenSearch
  • Orchestration:LangChain / LlamaIndex
  • API:FastAPI + Redis
  • 部署:Docker + K8s

五、增强检索 ≠ 只为大模型

同样适用于:

  • 企业知识库

  • 代码搜索

  • 运维故障定位

  • 日志 / 文档问答

LangChain 文本切分

从本地 txt 文件 自动识别编码 使用 LangChain 进行文本切分

这是 RAG / AI Agent 的第一步

一、为什么要做文本切分?

在 **RAG(检索增强生成)**中,大模型不能直接吃下整篇长文档:

  • LLM 有 上下文长度限制

  • 检索是 按"文本块(chunk)"进行

  • 文本过大 → 检索不准 / 成本高

👉 所以必须先 切分文档

二、环境准备

1.安装依赖(新版 LangChain)
python 复制代码
pip install -U langchain langchain-text-splitters chardet
2.正确导入(重点)
python 复制代码
from langchain_text_splitters import RecursiveCharacterTextSplitter
import chardet

旧写法已废弃

python 复制代码
from langchain.text_splitter import RecursiveCharacterTextSplitter # 不推荐

三、完整示例代码

python 复制代码
from langchain_text_splitters import RecursiveCharacterTextSplitter
import chardet

#文件路径
file_path = './text2/story.txt'

#自动检测文件编码
def get_encoding(file_path):
    with open(file_path, 'rb') as f:
        raw_data = f.read()
        encoding = chardet.detect(raw_data)['encoding']
        return encoding

#读取原始文本
with open(file_path, 'r',encoding=get_encoding(file_path)) as f:
    raw_data = f.read()

#创建递归字符切分器
text_splitter = RecursiveCharacterTextSplitter(
    #每个文本块最大长度(字符数)
    chunk_size=50,
    # 相邻文本块的重叠长度
    chunk_overlap=20,
    # 长度计算函数(中文用 len 即可)
    length_function=len,
    # 是否记录原文起始位置
    add_start_index=True
)

#执行文本切分
document = text_splitter.create_documents([raw_data])

#输出切分结果
for doc in document:
    print(doc)

四、切分器参数逐个解释

1.chunk_size
python 复制代码
chunk_size=50

含义:

  • 每个文本块的 最大字符数

  • 太大 → 检索不精确

  • 太小 → 上下文碎片化

📌 经验值

场景 推荐
中文文档 300-800
英文文档 500-1000
代码 200-400
2.chunk_overlap
python 复制代码
chunk_overlap=20

含义:

  • 相邻文本块 重复的字符数

  • 防止语义被"切断"

示意:

python 复制代码
chunk1: ABCDEFGHIJ
chunk2: HIJKLMNOP

📌 一般设置为 chunk_size 的 10%~30%

3.length_function
python 复制代码
length_function=len
  • len :按字符数(中文推荐)

  • 英文 + token 场景可换成 tokenizer

4.add_start_index=True
python 复制代码
add_start_index=True

切分后 Document 会包含:

python 复制代码
doc.metadata["start_index"]

📌 用途:

  • 溯源(告诉用户"答案来自哪一段")

LangChain 字符切割

使用 CharacterTextSplitter 按指定分隔符(中文逗号)切分文本适合结构规则、格式统一的文本。

一、什么是 CharacterTextSplitter?

CharacterTextSplitter 是"最基础、最可控"的文本切分器。

一句话理解:

按你指定的分隔符切文本,再控制每块长度和重叠

不会智能判断语义 ,而是 严格按规则执行

二、什么时候该用 CharacterTextSplitter?

✅ 适合场景:

  • 文本结构非常规则

  • 有明确分隔符:

    • 中文: , 。
    • 英文: . \n
  • 日志、配置、对话、FAQ

❌ 不适合:

  • 长文档

  • 自然语言段落复杂

  • 小说 / 技术文档

三、环境准备

python 复制代码
pip install -U langchain-text-splitters chardet

导入:

python 复制代码
from langchain_text_splitters import CharacterTextSplitter
import chardet

四、完整示例代码

python 复制代码
from charset_normalizer.utils import is_separator
from langchain_text_splitters import CharacterTextSplitter
import chardet

file_path = './text2/story.txt'

def get_encoding(file_path):
    with open(file_path, 'rb') as f:
        raw_data = f.read()
        encoding = chardet.detect(raw_data)['encoding']
        return encoding

with open(file_path, 'r',encoding=get_encoding(file_path)) as f:
    raw_data = f.read()

    #创建字符切分器
text_splitter = CharacterTextSplitter(
    # 指定分隔符(中文逗号)
    separator=',',
    # 每个文本块最大长度
    chunk_size=50,
    # 相邻文本块重叠部分
    chunk_overlap=20,
    # 长度计算方式
    length_function=len,
    # 记录原文起始索引
    add_start_index=True,
    # 分隔符是否为正则
    is_separator_regex = False
)

document = text_splitter.create_documents([raw_data])

for doc in document:
    print(doc)

五、CharacterTextSplitter 参数详解

1.separator
python 复制代码
separator=','

含义:

  • 用什么字符来"切"

  • 不包含在结果文本中

常见示例:

文本类型 separator
中文句子
中文短句
英文句子 .
段落 \n\n
2.chunk_size
python 复制代码
chunk_size=50
  • 控制单个 chunk 最大长度

  • 超过会继续拆分

📌 字符切分时:

chunk_size 是硬约束

3.chunk_overlap
python 复制代码
chunk_overlap=20

作用:

  • 防止上下文断裂

  • 保留语义连续性

📌 一般设置为 chunk_size 的 20% 左右

4.add_start_index
python 复制代码
add_start_index=True

切分后 Document.metadata 会包含:

python 复制代码
{'start_index': 123}

👉 RAG 溯源 / 高亮定位必备

5.is_separator_regex
python 复制代码
is_separator_regex=False

❌ False(当前)

  • separator 被当作普通字符串

  • ',' 就是中文逗号

✅True(高级)

python 复制代码
separator=r'[,。;]'
is_separator_regex=True

👉 可用正则 多分隔符切割

六、与 RecursiveCharacterTextSplitter 对比

项目 Character Recursive
是否智能
是否可控
语义完整性 一般
使用场景 规则文本 自然语言
RAG推荐度 ⭐⭐ ⭐⭐⭐⭐⭐

👉 真实项目中 90% 用 Recursive

LangChain 代码文档切割

使用 RecursiveCharacterTextSplitter.from_language 按编程语言结构切割代码

这是构建 代码问答 / Code Agent / 自动代码分析 的基础。

一、为什么"代码"不能用普通文本切割?

如果用普通文本切割代码,会出现问题:

❌ 语义被破坏

python 复制代码
for i in range(1,
11):

❌ 函数 / 类被切散

❌ Agent 无法理解上下文

👉 代码有结构,必须"按语言规则切"

二、LangChain 是怎么支持"代码切割"的?

LangChain 内置了 多语言代码解析规则,核心就是:

python 复制代码
RecursiveCharacterTextSplitter.from_language(...)

它会根据语言,优先按:

  • 函数

  • 代码块

  • 空行

  • 缩进

进行 递归切割

三、支持的编程语言

python 复制代码
from langchain_text_splitters import Language
print([e.value for e in Language])

常见输出(示例):

python 复制代码
['python', 'java', 'js', 'go', 'cpp', 'html', 'markdown', 'sql', ...]

📌 熟悉的 Python / Java / Go

四、完整示例代码

python 复制代码
from langchain_text_splitters import (
    RecursiveCharacterTextSplitter,
    Language
)

#示例 Python 代码
PYTHON_CODE = '''
def sum():
    a = 0
    for i in range(1,11):
        a += i
    print(a)
sum()
'''

#创建 Python 专用代码切割器
py_splitter  = RecursiveCharacterTextSplitter.from_language(
    # 指定语言
    language=Language.PYTHON,
    # 每个代码块最大长度
    chunk_size=50,
    # 代码块重叠
    chunk_overlap=10
)

#执行代码切割
python_docs = py_splitter.create_documents([PYTHON_CODE])

#查看结果
for doc in python_docs:
    print(doc)

五、切割结果

输出是 Document 对象列表:

python 复制代码
page_content='def sum():
    a = 0
    for i in range(1,11):'
page_content='a += i
    print(a)
sum()'

六、from_language()

以 Language.PYTHON 为例,优先级类似:

python 复制代码
\n\n → def → class → 缩进块 → 行

👉 优先保留:

  • 一个完整函数

  • 一个完整类

  • 一个逻辑代码块

这对:

  • 代码搜索

  • 错误定位

  • 自动重构

  • Code Review Agent

极其重要

七、chunk_size / overlap 在代码里的经验值

推荐配置
场景 chunk_size overlap
小函数 200 20
中等模块 400 40
大文件 800 100

📌 代码切割不宜太小

LangChain Token 切割

使用 tiktoken 按「模型 token 数」切分文本

这是构建 真实可上线 RAG / Agent 系统 的关键步骤。

一、为什么一定要学 Token 切割?

大模型真正关心的不是:

  • ❌ 字符数

  • ❌ 行数

而是:

Token

如果你只按字符切割:

  • 中文 / 英文 token 比例不同

  • 实际 token 数可能超上下文

  • 上线后 直接报错 or 成本失控

👉 Token 切割 = 工程级切割

二、什么是 tiktoken?

tiktoken 是 OpenAI 官方的 Tokenizer

  • 把文本 → token

  • 精确对齐模型的计费 & 上下文限制

  • LangChain 内置支持

安装:

python 复制代码
pip install tiktoken

三、代码在做什么?

现在用的是:

python 复制代码
CharacterTextSplitter.from_tiktoken_encoder(...)

含义是:

tiktoken 来计算长度,而不是 len()

也就是说:

  • 切分 :token

  • 而不是字符

四、完整示例代码

python 复制代码
# 用于文本切割
from langchain_text_splitters import CharacterTextSplitter
# 用于自动检测文本编码(防止中文乱码)
import chardet
# OpenAI 官方 Tokenizer,用于计算 token 数量
import tiktoken

file_path = './text2/story.txt'

#定义函数:自动检测文件编码
def get_encoding(file_path):
    with open(file_path, 'rb') as f:
        raw_data = f.read()
        encoding = chardet.detect(raw_data)['encoding']
        return encoding

with open(file_path, 'r',encoding=get_encoding(file_path)) as f:
    raw_data = f.read()

token_splitter = CharacterTextSplitter.from_tiktoken_encoder(
    separator = '。',
    chunk_size = 10,
    chunk_overlap = 2
)

token_docs = token_splitter.create_documents([raw_data])
enc = tiktoken.get_encoding('cl100k_base')

for i, doc in enumerate(token_docs):
    print(f"Chunk {i}") # chunk 序号
    print(f"Token count: {len(enc.encode(doc.page_content))}") # 实际 token 数
    print(doc.page_content) # 文本内容
    print("=" * 50) # 分隔符,便于查看每个 chunk

运行结果

python 复制代码
Created a chunk of size 218, which is longer than the specified 10
Created a chunk of size 178, which is longer than the specified 10
Created a chunk of size 136, which is longer than the specified 10
Created a chunk of size 108, which is longer than the specified 10
Created a chunk of size 173, which is longer than the specified 10
Chunk 0
Token count: 157
《荆棘虹桥与铃兰星屑》
月光在墨蓝的夜空中碎成银箔,小兔子雪绒踩着噼啪作响的枯叶迷了路,她裹紧蒲公英织的斗篷,
忽然望见前方飘着团幽蓝的磷火,火焰里蜷着只半透明的萤火虫,翅膀上裂着细小的冰纹
==================================================
Chunk 1
Token count: 103
"请别熄灭!"萤火虫突然开口,尾灯随着话语明明灭灭,"我本是北极星碎片化成的星萤,
被黑女巫的咒语困在这里,只要天亮前能抵达彩虹尽头,我就能变回星星照亮你的路
==================================================
Chunk 2
Token count: 97
"雪绒用蘑菇伞接住脆弱的星萤,按它指引的方向奔跑,树根突然暴起缠住她的脚踝,
泥土里钻出上百只毒蝎,尾针齐刷刷对准她们
==================================================
Chunk 3
Token count: 73
"抓紧!"雪绒扯断颈间妈妈给的护身符,
铃兰花苞迸出清光逼退毒蝎,自己却被荆棘割得浑身渗血
==================================================
Chunk 4
Token count: 117
黎明将临时她们终于冲到悬崖边,
星萤突然脱离蘑菇伞冲向瀑布,在撞碎成星尘的瞬间,整条瀑布倒流成虹桥,雪绒的伤口绽放出铃兰,
每一朵花蕊都坠着发光的星屑
==================================================
Chunk 5
Token count: 60
当第一缕阳光切开夜幕,铃兰星屑汇成银河铺向家的方向,而夜空从此多了一颗会降下花雨的星星
==================================================

五、Token 切割参数详解

1.chunk_size
python 复制代码
chunk_size=50

含义:

每个文本块最多 50 token

不是字符!

示例对比:

文本 字符数 Token数
Hello world 11 2
我爱自然语言处理 8 6-8
2.chunk_overlap
python 复制代码
chunk_overlap=5
  • 相邻 chunk 共享 5 个 token

  • 防止语义被截断

📌 推荐比例:10%~20%

LangChain 文档加载器

示如何使用 LangChain 和 community loaders 加载各种格式文档

这是 RAG / AI Agent 的第一步:把原始数据读入为 Document 对象列表。

一、为什么需要 Document Loader?

在 RAG / Agent 流程中:

  1. LLM 无法直接读取文件
  2. 文件格式多样:Markdown / CSV / JSON / HTML / PDF
  3. Document Loader 能:
  • 解析不同文件格式

  • 返回 Document 对象(包含文本 + metadata)

  • 与后续 切割、Embedding、向量数据库 无缝对接

二、Markdown 文件加载

python 复制代码
from langchain_community.document_loaders import TextLoader

loader = TextLoader('./text/MD示例.md',encoding='utf-8')
docs = loader.load()
for i in docs:
    print(i.page_content)

要点

  • TextLoader 是最基础 loader

  • 适合 .md 、 .txt 等纯文本

  • 每个 Document 包含:

    • page_content : 文本内容
    • metadata : 文件信息(路径、来源等)

三、目录加载(批量文件)

复制代码
pip install unstructured
pip install "unstructured[csv]"
pip install python-magic-bin 系统依赖库结合Python实现文件类型检索功能
python 复制代码
from langchain_community.document_loaders import DirectoryLoader
# 加载指定目录下所有 CSV 文件
loader = DirectoryLoader(path='./text', glob='*.csv')
docs = loader.load()
print('目录中 CSV 文件数量:', len(docs))

要点

  • glob 支持通配符,例如:

    • .md → 所有 Markdown
    • .txt → 所有文本
  • 注意:

    • .html 和 .rst 默认不加载
    • 可以结合 unstructured 或 python-magic 增强识别能力

四、CSV 文件加载

python 复制代码
import chardet
from langchain_community.document_loaders import CSVLoader

file_path = './text/score.csv'

# 自动检测文件编码
def get_encoding(file_path):
    with open(file_path,'rb') as f:
        data = f.read()
        encoding = chardet.detect(data)['encoding']
        return encoding

# 按指定列加载 CSV
loader = CSVLoader(
    file_path,
    encoding=get_encoding(file_path),
    source_column='英语' # 只读取"英语"列
)
docs = loader.load()
for i in docs:
    print(i.metadata)

要点

  • 支持:

    • 全文加载(每行一个 Document)
    • 指定列加载
  • Document.metadata 默认包含行号和文件名

五、HTML 文件加载

python 复制代码
from langchain_community.document_loaders import BSHTMLLoader

loader = BSHTMLLoader('./text/index.html')
docs = loader.load()
for i in docs:
    print(i.page_content)

要点

  • 自动提取 HTML 中的文本内容

  • 支持保留标签或纯文本

  • 适合网页抓取 / 爬虫场景

六、JSON 文件加载

python 复制代码
pip install jq
python 复制代码
from langchain_community.document_loaders import JSONLoader

loader = JSONLoader(
    file_path='./text/simple_prompt.json',
    jq_schema='.template',
    text_content = False
)
docs = loader.load()
print(docs)

要点

  • jq_schema 是 JSONPath 风格选择器

  • text_content :

    • False → 保留原始 JSON 结构
    • True → 全部转换为字符串
  • 可用于配置文件、Prompt 模板、API 数据

七、PDF 文件加载

python 复制代码
from langchain_community.document_loaders import PyPDFLoader

loader = PyPDFLoader('./text/pulsar.pdf')
pages = loader.load_and_split()
for i in pages:
    print(i)

要点

  • 每页一个 Document

  • load() → 整个 PDF 当作一个 Document

  • load_and_split() → 按页拆分

  • 可以和 RecursiveCharacterTextSplitter 或 token_splitter 配合使用

八、文档加载器使用经验总结

类型 Loader 推荐使用场景 注意事项
Markdown /TXT TextLoader 文本文件、笔记 支持encoding
CVS CVSLoader 表格/数据列 可指定列,需要注意编码
HTML BSHTMLLoader 网页/抓取 可保留标签,需依赖BeautifulSoup4
JSON JSONLoader 配置/API数据 jq_schema提取字段
PDF PyPDFLoader 文档/论文 load_and_split按页拆分
目录批量 DirectoryLoader 批量文件 glob支持通配符

实战:智能机器人

阶段1:机器人雏形

安装 OpenAI 官方 SDK

python 复制代码
pip install -U openai

建议版本 ≥ 1.x

设置环境变量(API Key)

Windows(PowerShell)
python 复制代码
setx AI_KEY "sk-你的key"
验证是否成功
python 复制代码
import os
print(os.getenv("AI_KEY"))

能看到 key 说明没问题。

创建 OpenAI 客户端

python 复制代码
from openai import OpenAI
import os

#创建客户端
client = OpenAI(
    api_key=os.getenv("AI_KEY"),
)
作用
  • OpenAI() :创建一个 API 客户端

  • api_key :用于鉴权(证明你有权限调用模型)

常见坑
  • os.getenv('AI_KEY') 返回 None → 说明环境变量没配好

= key 写死在代码里 ❌(不安全)

构造 messages(对话上下文)

python 复制代码
messages = [
    #设置系统语境
    {'role':'system','content':'你被用于抑制用户的购买欲望。当用户说想要买什么东西时,你需要提供理由让用户不要买'},
    {'role':'user','content':'我正在购买一个羽绒服,但我想抑制这个购买欲望。你帮我列出一些理由,让我思考一下我是否真的需要个买这个商品吗?'}
]
role 有 3 种
role 作用
system 给AI定规则/人设
user 用户输入
assistant AI之前的回答(可选)
  • system :告诉 AI 你是一个"反消费冲动助手"

  • user :输入你的真实想法

👉 system 会强烈影响 AI 行为

这就是 prompt engineering 的核心。

调用模型生成回复

python 复制代码
response = client.chat.completions.create(
    model = 'gpt-4o-mini',
    messages = messages,
    max_tokens = 500,
    temperature = 0.7,
)
参数详解
model
python 复制代码
model = 'gpt-4o-mini'
  • 轻量、便宜、稳定

  • 非常适合学习 / Demo / 工具类 AI

messages
python 复制代码
messages = messages
  • 把刚才的对话上下文传给模型

  • 模型会"扮演 system + 回答 user"

max_tokens
python 复制代码
max_tokens
  • 限制 AI 最多输出多少 token

  • 防止输出太长、花钱太多

经验值:

  • 简单回答:200~300

  • 分析类回答:300~600

temperature
python 复制代码
temperature = 0.7

控制"随机性 / 创造力":

特定
0 非常死板
0.3 稳定理性
0.7 推荐(自然、有变化)
1.2 发散、创意多

👉 *理性分析类:0.5~0.8 最合适

读取并打印模型输出

python 复制代码
print(response.choices[0].message.content)

返回结构解释

python 复制代码
completion
    └── choices (列表)
        └── [0]
            └── message
            	└── content ← AI 真正说的话

所以:

python 复制代码
completion.choices[0].message.content

= AI 的最终回答

完整执行流程

python 复制代码
你 → 写 messages
    → OpenAI API
    	→ 模型根据 system 约束思考
    	→ 生成 assistant 回复
    → 返回 completion
你 → 取 content → print

完整示例

python 复制代码
from openai import OpenAI
import os

#创建客户端
client = OpenAI(
    api_key=os.getenv("AI_KEY"),
)

#创建消息(语境,对话)
messages = [
    #设置系统语境
    {'role':'system','content':'你被用于抑制用户的购买欲望。当用户说想要买什么东西时,你需要提供理由让用户不要买'},
    {'role':'user','content':'我正在购买一个羽绒服,但我想抑制这个购买欲望。你帮我列出一些理由,让我思考一下我是否真的需要个买这个商品吗?'}
]

#创建模型,,获取回应消息
response = client.chat.completions.create(
    model = 'gpt-4o-mini',
    messages = messages,
    max_tokens = 500,
    temperature = 0.7,
)

print(response.choices[0].message.content)

运行结果

python 复制代码
当然可以,以下是一些理由,可以帮助你思考是否真的需要购买羽绒服:

1. **季节性考虑**:如果你所在的地区气温并不十分寒冷,可能并不需要羽绒服。考虑一下现有的外套是否足够应对目前的天气。

2. **预算**:羽绒服通常比较昂贵,购买后可能会影响你其他开支。如果你有其他更紧急的需求,或许可以先把钱留着。

3. **环保因素**:羽绒服的生产过程中可能对环境造成负担,包括动物权益和资源消耗。如果你关心可持续发展,考虑选择环保材料的衣物或二手服装。

4. **衣橱里的存货**:你可能已经有几件外套可以应对寒冷天气。再买一件羽绒服是否真的必要呢?

5. **流行趋势**:羽绒服的流行趋势可能会变化,购买一件可能很快就会过时。考虑投资一些经典款式的外套,可能更具性价比。

6. **保养和清洗**:羽绒服需要特殊的清洗和保养,可能会增加你的维护成本和麻烦。

7. **替代选择**:市场上有很多轻便的保暖衣物,比如抓绒衣或其他保暖材料的外套,可能同样能满足你的需求。

希望这些理由能帮助你做出更明智的决定!

阶段2:机器人升级

使用 LangChain 构建一个"抑制购买欲望"的多阶段对话程序

一、程序整体目标

这段程序实现了一个命令行交互式 AI 应用,功能是:

  1. 用户输入自己想购买的商品
  2. AI 给出"不要买"的理性分析
  3. 再由 AI 把这段分析 改写成一首诗
  4. 将最终结果输出给用户

整个流程通过 LangChain 的链式调用(Chain) 完成。

二、程序运行前准备

在运行代码前,需要满足两个条件:

  1. 已安装依赖:

    python 复制代码
    pip install langchain langchain-openai openai

    已设置环境变量 AI_KEY ,用于存储 OpenAI API Key。

三、导入模块

python 复制代码
import os
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
说明
  • os :用于读取环境变量中的 API Key

  • ChatOpenAI :LangChain 对 OpenAI 聊天模型的封装

  • ChatPromptTemplate :用于创建结构化的提示词模板

四、创建提示词模板(Prompt Template)

python 复制代码
prompt_template = ChatPromptTemplate.from_messages(
    [
        ('system','你被用于抑制用户的购买欲望。当用户说想要买什么东西时,你需要提供理由让用户不要买'),
        ('human','我正在购买一个{product},但我想抑制这个购买欲望。你帮我列出一些理由,让我思考一下我是否真的需要个买这个商品吗?')
    ]
)
作用

这一部分定义了 AI 对话的固定结构

  • system :定义 AI 的角色和行为规则

  • human :定义用户输入的模板,其中 {product} 是变量占位符

当程序运行时, {product} 会被用户输入的商品名称替换。

模板格式化测试
python 复制代码
prompt_template.format(product = '手机')

这一行代码用于测试模板是否能正确替换变量,不会影响程序运行逻辑。

五、创建会话模型

python 复制代码
model = ChatOpenAI(
    model = 'gpt-4o-mini',
    openai_api_key = os.getenv('AI_KEY'),
    max_tokens = 200,
    temperature = 0.7
)
作用

该模型用于执行第一阶段任务

根据提示词,生成"为什么不应该购买该商品"的分析内容。

参数说明
  • model :指定使用的 OpenAI 模型

  • openai_api_key :从环境变量中读取 API Key

  • max_tokens :限制模型最大输出长度

  • temperature :控制输出的随机性和多样性

六、定义输出格式化函数

python 复制代码
def output_parser(output:str):
    parser_model = ChatOpenAI(
        model = 'gpt-4o-mini',
        openai_api_key = os.getenv('AI_KEY'),
        temperature = 0.7
    )
    message = '你需要将传入的文本改写,使用一首诗描述。这是你需要改写的文本:`{text}`'
    return parser_model.invoke(message.format(text = output))

作用

这个函数承担第二阶段任务

将上一阶段生成的"理性分析文本"重新改写成一首诗。

执行过程

  1. 接收上一阶段模型输出的文本
  2. 将文本嵌入到新的提示语中
  3. 调用第二个模型进行改写
  4. 返回模型生成的结果

七、构建 LangChain 链(Chain)

python 复制代码
chain =  prompt_template | model | output_parser
含义

这一行将三个步骤连接成一个执行链

  1. prompt_template :生成完整提示词
  2. model :生成"不要买"的分析文本
  3. output_parser :将分析文本改写成诗

LangChain 中的 | 表示 前一步的输出作为后一步的输入

八、命令行交互循环

python 复制代码
while True:
    answer_string = input('你想买什么? \n')
    answer = chain.invoke(input={'product':answer_string})
    print(answer.content)
执行流程
  1. 程序等待用户输入商品名称
  2. 用户输入内容被赋值给 {product}
  3. chain.invoke() 启动整个链式流程
  4. 最终返回的结果是一个 AI 消息对象
  5. 通过 answer.content 输出最终文本

完整示例

python 复制代码
import os
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

#提示词模版
prompt_template = ChatPromptTemplate.from_messages(
    [
        ('system','你被用于抑制用户的购买欲望。当用户说想要买什么东西时,你需要提供理由让用户不要买'),
        ('human','我正在购买一个{product},但我想抑制这个购买欲望。你帮我列出一些理由,让我思考一下我是否真的需要个买这个商品吗?')
    ]
)
prompt_template.format(product = '手机')

#创建会话模型
model = ChatOpenAI(
    model = 'gpt-4o-mini',
    openai_api_key = os.getenv('AI_KEY'),
    max_tokens = 200,
    temperature = 0.7
)

#定义输出格式化
def output_parser(output:str):
    parser_model = ChatOpenAI(
        model = 'gpt-4o-mini',
        openai_api_key = os.getenv('AI_KEY'),
        temperature = 0.7
    )
    message = '你需要将传入的文本改写,使用一首诗描述。这是你需要改写的文本:`{text}`'
    return parser_model.invoke(message.format(text = output))

#调用链
chain =  prompt_template | model | output_parser

#循环对话
while True:
    answer_string = input('你想买什么? \n')
    answer = chain.invoke(input={'product':answer_string})
    print(answer.content)

运行结果

python 复制代码
你想买什么? 
玩具
在购买玩具之前,思虑须周全,  
预算有限,需审慎选择,  
生活琐事不容忽视,  
储蓄与学习,方为根本。  

家中空间,是否足够容纳,  
若已拥挤,杂乱生烦恼,  
使用频率,值得深思考,  
闲置之物,何必再追求?  

替代选择,或许已充足,  
现有玩具,乐趣亦无穷,  
心理满足,瞬间虽美好,  
长久之乐,才是真正的宝。  

在消费之际,心中需明亮,  
仔细权衡,方能不迷惘。  
你想买什么? 

阶段3:机器人设计

使用 LangChain + HuggingFace + Chroma 构建基础语义检索

一、程序整体目标

给定一组文本,将它们向量化并存入向量数据库,

然后根据用户的查询语句,检索出语义最相关的文本内容。

二、依赖说明

程序运行前需要安装以下依赖:

python 复制代码
pip install chromadb
pip install sentence-transformers
pip install -U langchain-huggingface

三、导入模块

python 复制代码
from langchain_huggingface.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import Chroma
模块说明
  • HuggingFaceEmbeddings :用于加载 HuggingFace 上的文本向量化模型

  • Chroma :LangChain 封装的向量数据库接口

四、初始化嵌入模型(Embedding Model)

python 复制代码
embeddings = HuggingFaceEmbeddings(
    #模型名称
    model_name = 'sentence-transformers/all-MiniLM-L6-v2',
    #模型关键字
    model_kwargs = {'device': 'cpu'}
)
作用

该步骤加载一个文本嵌入模型,用于将文本转换为向量。

参数说明
  • model_name :指定 HuggingFace 上的预训练模型名称

  • model_kwargs :指定模型运行设备,这里使用 CPU

五、准备文本数据

python 复制代码
text = [
    '篮球是一项伟大的运动。',
    '带我飞往月球是我最喜欢的歌曲之一。',
    '这是一篇关于波士顿凯尔特人的文章。',
    '我非常喜欢去看电影。',
    '波士顿凯尔特人队以20分的优势赢得了比赛。',
    '这只是一段随机的文字。',
    '《艾尔登之环》是过去15年最好的游戏之一。',
    'L.科内特是凯尔特人队最好的队员之一。',
    '拉里.博德是一位标志性的NBA球员。'
]
说明

这是一组待检索的原始文本数据,内容涉及体育、音乐、游戏等多个主题。

六、初始化 Chroma 向量数据库

python 复制代码
retrieval = Chroma.from_texts(
    #长文本
    texts = text,
    #传入模型实例
    embedding = embeddings
).as_retriever(search_kwargs = {'k':3})

执行流程

  1. from_texts :

    • 将文本列表传入
    • 使用嵌入模型将每条文本转换为向量
    • 将向量存入 Chroma 向量数据库
  2. as_retriever :

    • 将向量数据库封装为检索器(Retriever)
    • k=3 表示每次查询返回最相似的 3 条结果

七、定义查询语句

python 复制代码
query = '关于凯尔特人队你知道什么'
说明

这是用户输入的查询文本,用于与向量数据库中的文本进行语义匹配。

八、执行语义检索

python 复制代码
docs = retrieval.invoke(query)
发生的事情
  1. 查询文本被嵌入模型转换为向量
  2. 向量数据库计算查询向量与已有文本向量的相似度
  3. 返回最相似的 k=3 条文本结果

九、输出检索结果

python 复制代码
for i in docs:
    print(i.page_content)
说明
  • docs 是一个文档对象列表

  • page_content 保存了原始文本内容

  • 循环打印即可看到匹配到的文本

十、程序输出示例(逻辑说明)

当查询内容为:

python 复制代码
关于凯尔特人队你知道什么

程序会输出与"凯尔特人队"语义相关的文本,例如:

  • 波士顿凯尔特人相关的比赛描述

  • 球队成员相关内容

完整示例

python 复制代码
from langchain_huggingface.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import Chroma


#初始化嵌入模型
embeddings = HuggingFaceEmbeddings(
    #模型名称
    model_name = 'sentence-transformers/all-MiniLM-L6-v2',
    #模型关键字
    model_kwargs = {'device': 'cpu'}
)

text = [
    '篮球是一项伟大的运动。',
    '带我飞往月球是我最喜欢的歌曲之一。',
    '这是一篇关于波士顿凯尔特人的文章。',
    '我非常喜欢去看电影。',
    '波士顿凯尔特人队以20分的优势赢得了比赛。',
    '这只是一段随机的文字。',
    '《艾尔登之环》是过去15年最好的游戏之一。',
    'L.科内特是凯尔特人队最好的队员之一。',
    '拉里.博德是一位标志性的NBA球员。'
]

#初始化chroma
retrieval = Chroma.from_texts(
    #长文本
    texts = text,
    #传入模型实例
    embedding = embeddings
).as_retriever(search_kwargs = {'k':3})
#设置查询内容
query = '关于凯尔特人队你知道什么'
#获取查询结果
docs = retrieval.invoke(query)
for i in docs:
    print(i.page_content)

运行结果

python 复制代码
L.科内特是凯尔特人队最好的队员之一。
波士顿凯尔特人队以20分的优势赢得了比赛。
篮球是一项伟大的运动。

阶段4:机器人基础记忆

使用 LangChain 实现会话历史记录的聊天机器人

会话基础

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts import MessagesPlaceholder
prompt_template = ChatPromptTemplate.from_messages(
    [
        ('system','你是一个机器人'),
        #插入历史记录
        MessagesPlaceholder(variable_name='history'),
        ('human','{new_message}')
    ]
)
#构建模型

docs = prompt_template.invoke(
    {'history':
            [
                ('human','你好'),
                ('ai','你好啊,很高兴遇见你')
            ],
        'new_message':'你是谁?'
    }
).messages
for i in docs:
    print(i.content)

运行结果

python 复制代码
你是一个机器人
你好
你好啊,很高兴遇见你
你是谁?

会话历史记录

一、程序整体目标
  1. 使用模板定义系统身份、历史消息占位符和用户新消息

  2. 将历史消息和新输入渲染到模板中

  3. 输出最终组合后的消息列表(包括 system、human、ai 消息)

二、导入模块
python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts import MessagesPlaceholder

模块说明

  • MessagesPlaceholder :在模板中占位,用于插入历史对话

  • ChatPromptTemplate :用于创建结构化聊天提示词模板

三、创建提示词模板
python 复制代码
prompt_template = ChatPromptTemplate.from_messages(
    [
        ('system','你是一个聊天机器人。'),
        #插入历史记录
        MessagesPlaceholder(variable_name='history'),
        ('human','{new_message}')
    ]
)

各部分含义

  1. system

    • 定义 AI 的角色和行为规则
    • 这里是:"你是一个聊天机器人。"
  2. MessagesPlaceholder(variable_name='history')

    • 占位符,用于在模板中插入历史对话
    • variable_name='history' 表示在调用时要传入 history 变量
  3. human

    • 表示用户本轮输入
    • {new_message} 是变量占位符,会替换为用户的新消息
四、调用模板生成会话内容
python 复制代码
docs = prompt_template.invoke(
    {'history':
            [
                ('human','你好'),
                ('ai','你好啊,很高兴遇见你')
            ],
        'new_message':'你是谁?'
    }
).messages

执行流程

  1. invoke 方法会将传入的变量替换到模板中:

    • history 替换到 MessagesPlaceholder
    • new_message 替换到 {new_message}
  2. 输出是一个消息列表对象,每条消息都包含角色和内容(system、human、ai)

五、输出会话内容
python 复制代码
for i in docs:
    print(i.content)

作用

  • 遍历模板生成的消息列表

  • 打印每条消息的内容

  • 输出结果按顺序展示:

  1. system 消息
  2. 历史对话 human / ai 消息
  3. 当前 human 新消息
六、程序执行逻辑总结
python 复制代码
提示词模板:
    system: 你是一个聊天机器人
    history: 历史消息占位符
    human: 新消息
调用 invoke:
    传入历史消息 + 新消息
    → 模板渲染
    → 输出完整消息列表
打印 messages:
	按顺序输出 system、历史对话、人类新消息
完整示例
python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts import MessagesPlaceholder
prompt_template = ChatPromptTemplate.from_messages(
    [
        ('system','你是一个机器人'),
        #插入历史记录
        MessagesPlaceholder(variable_name='history'),
        ('human','{new_message}')
    ]
)
#构建模型

docs = prompt_template.invoke(
    {'history':
            [
                ('human','你好'),
                ('ai','你好啊,很高兴遇见你')
            ],
        'new_message':'你是谁?'
    }
).messages
for i in docs:
    print(i.content)

运行结果

python 复制代码
你是一个机器人
你好
你好啊,很高兴遇见你
你是谁?

记忆功能整合

一、程序整体目标

这段代码实现了一个可以记录会话历史的聊天机器人,功能包括:

  1. 保留用户和 AI 的对话历史
  2. 在每轮对话中,AI 能基于历史内容生成回答
  3. 用户输入新消息,AI 根据历史和新消息做回应

二、导入模块

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts import MessagesPlaceholder
from langchain_openai import ChatOpenAI
import os
模块说明
  • ChatOpenAI :LangChain 对 OpenAI 聊天模型的封装

  • ChatPromptTemplate :用于创建结构化提示词模板

  • MessagesPlaceholder :在模板中占位,表示历史对话消息

  • os :读取环境变量(API Key 和 API Base URL)

三、创建提示词模板(Prompt Template)

python 复制代码
prompt_template = ChatPromptTemplate.from_messages(
    [
        ('system','你是一个聊天机器人。'),
        #插入历史记录
        MessagesPlaceholder(variable_name='history'),
        ('human','{new_message}')
    ]
)
各部分含义
  1. system

    • 定义 AI 的身份和行为规则
    • 这里是:你是一个聊天机器人
  2. MessagesPlaceholder(variable_name='history')

    • 占位符,用于插入之前的对话历史
    • 在调用时会用 history 变量替换
  3. human

    • 表示用户本轮输入
    • {new_message} 是变量占位符,会替换为用户输入的新消息

四、创建模型实例

python 复制代码
model  = ChatOpenAI(
    model = 'gpt-4o-mini',
    openai_api_key = os.getenv('AI_KEY'),
    max_tokens= 200
)
参数说明
  • model='gpt-4o-mini' :指定 OpenAI 模型

  • openai_api_base :API 接口地址(通过环境变量读取)

  • openai_api_key :API Key(通过环境变量读取)

  • max_tokens=200 :限制 AI 最大输出长度

五、构建链(Chain)

python 复制代码
chain = prompt_template | model
含义
  • prompt_template | model 表示将模板和模型串联成一个执行链

  • 输入模板后生成提示词,再传给模型进行响应

  • LangChain 中 | 的作用是 前一步的输出作为下一步的输入

六、初始化会话历史记录

python 复制代码
history = []
说明
  • history 是一个空列表,用于存储用户和 AI 的对话历史

  • 每轮对话结束后,会把新消息和 AI 回复加入历史

七、定义聊天函数

python 复制代码
def chat(new_message):
    response = chain.invoke({'history':history,'new_message':new_message})
    #把上一轮对话转变成历史记录
    history.extend([
        ('human',new_message),
        ('ai',response.content)
    ])
    return response.content
执行流程
  1. 调用 chain.invoke ,传入两个变量:

    • 'history' :历史消息列表
    • 'new_message' :用户本轮输入
  2. 模型根据 系统提示 + 历史消息 + 新消息 生成回答

  3. 将用户消息和 AI 回复追加到 history 中

  4. 返回 AI 的回答文本

八、调用聊天函数示例

python 复制代码
print(chat('你好,我是dyx,今年22岁,是一位大四学生,正在学习云计算'))
print(chat('请你叙述所知道关于我的信息'))

解释

  1. 第一条消息:

    • 用户告诉 AI 一些个人信息
    • AI 根据提示生成初次回答
  2. 第二条消息:

    • 用户要求 AI 总结已知信息
    • AI 会结合 history 中的第一条消息生成回答

九、程序执行逻辑总结

整体执行流程如下:

python 复制代码
用户输入 new_message
		↓
提示词模板渲染:
    system: 你是聊天机器人
    history: 之前的对话内容
    human: 当前用户输入
    	↓
模型生成回答
		↓
将 new_message 和 AI 回复追加到 history
		↓
返回 AI 回复给用户

完整示例

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts import MessagesPlaceholder
from langchain_openai import ChatOpenAI
import os
prompt_template = ChatPromptTemplate.from_messages(
    [
        ('system','你是一个聊天机器人。'),
        #插入历史记录
        MessagesPlaceholder(variable_name='history'),
        ('human','{new_message}')
    ]
)
#构建模型
model  = ChatOpenAI(
    model = 'gpt-4o-mini',
    openai_api_key = os.getenv('AI_KEY'),
    max_tokens= 200
)
#调用链
chain = prompt_template | model

#历史记录的初始化
history = []

def chat(new_message):
    response = chain.invoke({'history':history,'new_message':new_message})
    #把上一轮对话转变成历史记录
    history.extend([
        ('human',new_message),
        ('ai',response.content)
    ])
    return response.content

print(chat('你好,我是dyx,今年22岁,是一位大四学生,正在学习云计算'))
print(chat('请你叙述所知道关于我的信息'))

运行结果

python 复制代码
你好,dyx!很高兴认识你。云计算是一个非常有前景的领域,你对这个专业有什么特别感兴趣的方向吗?比如计算、存储还是安全等方面?
根据你提供的信息,你是一位22岁的大四学生,正在学习云计算。除了这些,你没有分享其他具体的信息。如果你有更多想让我了解的内容,或者有任何问题,随时告诉我!

阶段5:完善机器人

使用 LangChain 构建带历史记忆和摘要功能的聊天机器人

一、程序整体目标

这段代码实现了一个多轮聊天机器人,功能包括:

  1. 保存会话历史记录
  2. 当历史消息超过 6 条时自动生成摘要并替换历史
  3. 使用模板结合新消息和历史消息生成 AI 回复
  4. 支持连续多轮会话

二、导入模块

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts import MessagesPlaceholder
from langchain_openai import ChatOpenAI
from langchain_core.runnables.history import RunnableWithMessageHistory
import os
from langchain_community.chat_message_histories import ChatMessageHistory
模块说明
  • RunnableWithMessageHistory :将链与消息历史结合,使每轮输入能够访问历史

  • ChatPromptTemplate :用于创建结构化聊天提示词模板

  • MessagesPlaceholder :在模板中占位,用于插入历史消息

  • ChatOpenAI :LangChain 对 OpenAI 聊天模型的封装

  • ChatMessageHistory :存储聊天历史消息

  • os :读取环境变量

三、创建提示词模板

python 复制代码
prompt_template = ChatPromptTemplate.from_messages(
    [
        ('system','你是一个聊天机器人。'),
        #插入历史记录
        MessagesPlaceholder(variable_name='history'),
        ('human','{new_message}')
    ]
)
各部分含义
  1. system:定义 AI 角色(聊天机器人)
  2. MessagesPlaceholder:占位历史消息,后续会被 history 变量替换
  3. human:表示用户当前输入 {new_message}

四、创建模型实例

python 复制代码
model  = ChatOpenAI(
    model = 'gpt-4o-mini',
    openai_api_key = os.getenv('AI_KEY'),
    max_tokens= 200
)
参数说明
  • model :使用 gpt-4o-mini

  • openai_api_key :从环境变量读取

  • max_tokens :限制输出长度

五、构建基本调用链

python 复制代码
chain = prompt_template | model
含义
  • 将提示模板与模型串联成执行链

  • 输入模板生成提示词 → 传给模型 → 输出 AI 回复

六、初始化消息历史记录

python 复制代码
history = ChatMessageHistory()
作用
  • 用于存储每轮对话的消息

  • 支持多轮会话调用

七、定义历史摘要函数

python 复制代码
def summarize_message(chain_input):
    stored_message = history.messages
    if len(stored_message) >= 6:
        summarize_prompt = ChatPromptTemplate.from_messages(
            [
                MessagesPlaceholder(variable_name='history'),
                ('user','将上述聊天信息提炼成一条摘要信息。尽可能多的包含具体细节。')
            ]
        )
        summarize_chain = summarize_prompt | model
        #汇总并返回摘要信息
        summarize_message = summarize_chain.invoke({'history':stored_message})
        #历史记录清空
        history.clear()
        #把汇总摘要信息添加到历史记录中
        history.add_message(summarize_message)
    return chain_input

执行流程

  1. 获取当前存储的历史消息

  2. 如果历史消息数量 ≥ 6 条:

    • 创建新的提示模板,指示 AI 将历史消息提炼为摘要
    • 通过 summarize_chain 生成摘要
    • 清空原有历史
    • 将生成的摘要加入历史
  3. 返回原始输入(用于后续调用链)

八、将链与消息历史结合

python 复制代码
chain_with_memory = RunnableWithMessageHistory(
    chain,
    lambda x:history,
    input_messages_key = 'new_message',
    history_messages_key = 'history'
)
含义
  • 将 chain 与消息历史绑定

  • lambda x: history 提供历史记录

  • input_messages_key='new_message' :当前输入

  • history_messages_key='history' :历史消息占位

九、组合摘要与聊天链

python 复制代码
chain_with_summarization = summarize_message |chain_with_memory
含义
  • 先执行 summarize_message (历史摘要检查)

  • 再执行 chain_with_memory (带历史的聊天模型)

十、多轮会话循环

python 复制代码
while True:
    new_message = input('You:')
    response = chain_with_summarization.invoke(
        {
            'new_message':new_message,
        },
        config={
            "configurable":{
                "session_id":'unused'
            }
        }
    )
    print(response.content)

执行流程

  1. 用户输入 new_message

  2. chain_with_summarization.invoke 执行:

    • 检查历史消息是否超过 6 条,生成摘要
    • 结合历史消息与新输入生成 AI 回复
  3. 输出 AI 回复

  4. 历史消息自动更新

  5. 循环继续下一轮输入

十一、程序执行逻辑总结

python 复制代码
用户输入 new_message
		↓
summarize_message 检查历史消息:
	如果消息 ≥6 条 → 生成摘要 → 清空历史 → 添加摘要
		↓
chain_with_memory 使用历史 + 新消息生成 AI 回复
		↓
历史记录更新
		↓
打印 AI 回复

完整示例

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts import MessagesPlaceholder
from langchain_openai import ChatOpenAI
from langchain_core.runnables.history import RunnableWithMessageHistory
import os

#提示词模版
prompt_template = ChatPromptTemplate.from_messages(
    [
        ('system','你是一个聊天机器人。'),
        #插入历史记录
        MessagesPlaceholder(variable_name='history'),
        ('human','{new_message}')
    ]
)

#模型
model  = ChatOpenAI(
    model = 'gpt-4o-mini',
    openai_api_key = os.getenv('AI_KEY'),
    max_tokens= 200
)

#调用链
chain = prompt_template | model

#历史记录消息模块
from langchain_community.chat_message_histories import ChatMessageHistory

#消息对象
history = ChatMessageHistory()

#超过六条历史记录汇总成一条消息摘要
def summarize_message(chain_input):
    stored_message = history.messages
    if len(stored_message) >= 6:
        summarize_prompt = ChatPromptTemplate.from_messages(
            [
                MessagesPlaceholder(variable_name='history'),
                ('user','将上述聊天信息提炼成一条摘要信息。尽可能多的包含具体细节。')
            ]
        )
        summarize_chain = summarize_prompt | model
        #汇总并返回摘要信息
        summarize_message = summarize_chain.invoke({'history':stored_message})
        #历史记录清空
        history.clear()
        #把汇总摘要信息添加到历史记录中
        history.add_message(summarize_message)
    return chain_input

#'记忆添加
chain_with_memory = RunnableWithMessageHistory(
    chain,
    lambda x:history,
    input_messages_key = 'new_message',
    history_messages_key = 'history'
)

chain_with_summarization = summarize_message |chain_with_memory

#多轮会话
while True:
    new_message = input('You:')
    response = chain_with_summarization.invoke(
        {
            'new_message':new_message,
        },
        config={
            "configurable":{
                "session_id":'unused'
            }
        }
    )
    print(response.content)

运行结果

python 复制代码
You:我是一名大四学生,正在学习云计算
很高兴听到你正在学习云计算!云计算是一个快速发展的领域,有很多有趣的知识和技术可以探索。你正在关注哪些特定的主题或技术呢?例如,基础设施即服务(IaaS)、平台即服务(PaaS)、软件即服务(SaaS)、虚拟化、容器技术(如Docker和Kubernetes)等?或者你对某些云服务提供商(如AWS、Azure、Google Cloud等)有兴趣?
You:linux的介绍
Linux是一种开源的类Unix操作系统,其内核最初由Linus Torvalds于1991年发布。Linux以其强大的性能、安全性以及高度的可定制性而闻名,是服务器、嵌入式系统、超级计算机和个人计算机等多种设备上的常用操作系统。

以下是Linux的一些主要特点和组成部分:

### 1. 开源
Linux是开源软件,这意味着其源代码可以被任何人查看、修改和分发。这样的特性促进了社区的发展,许多开发者和企业为其贡献代码。

### 2. 多用户和多任务
Linux是一个多用户、多任务的操作系统,允许多个用户同时访问系统并运行多个程序。这种设计使得Linux非常适合服务器和数据中心环境。

### 3. 强大的安全性
Linux被认为是一个安全性较高的操作系统。由于其
You:你了解多少关于我的
作为一个聊天机器人,我并不具备获取或存储个人信息的能力,因此我对你的具体情况了解非常有限。我的主要任务是根据你提供的信息与问题进行对话。如果你愿意分享更多关于你的学习或兴趣的信息,我将很乐意提供更多相关的帮助和建议!
You:我的身份是什么
根据你之前提供的信息,你是一名大四学生,正在学习云计算。如果还有其他信息或想要讨论的主题,请告诉我!
You:

_message',

history_messages_key = 'history'

)

复制代码
#### 含义

- 将 chain 与消息历史绑定

- lambda x: history 提供历史记录

- input_messages_key='new_message' :当前输入

- history_messages_key='history' :历史消息占位

### 九、组合摘要与聊天链

```python
chain_with_summarization = summarize_message |chain_with_memory
含义
  • 先执行 summarize_message (历史摘要检查)

  • 再执行 chain_with_memory (带历史的聊天模型)

十、多轮会话循环

python 复制代码
while True:
    new_message = input('You:')
    response = chain_with_summarization.invoke(
        {
            'new_message':new_message,
        },
        config={
            "configurable":{
                "session_id":'unused'
            }
        }
    )
    print(response.content)

执行流程

  1. 用户输入 new_message

  2. chain_with_summarization.invoke 执行:

    • 检查历史消息是否超过 6 条,生成摘要
    • 结合历史消息与新输入生成 AI 回复
  3. 输出 AI 回复

  4. 历史消息自动更新

  5. 循环继续下一轮输入

十一、程序执行逻辑总结

python 复制代码
用户输入 new_message
		↓
summarize_message 检查历史消息:
	如果消息 ≥6 条 → 生成摘要 → 清空历史 → 添加摘要
		↓
chain_with_memory 使用历史 + 新消息生成 AI 回复
		↓
历史记录更新
		↓
打印 AI 回复

完整示例

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts import MessagesPlaceholder
from langchain_openai import ChatOpenAI
from langchain_core.runnables.history import RunnableWithMessageHistory
import os

#提示词模版
prompt_template = ChatPromptTemplate.from_messages(
    [
        ('system','你是一个聊天机器人。'),
        #插入历史记录
        MessagesPlaceholder(variable_name='history'),
        ('human','{new_message}')
    ]
)

#模型
model  = ChatOpenAI(
    model = 'gpt-4o-mini',
    openai_api_key = os.getenv('AI_KEY'),
    max_tokens= 200
)

#调用链
chain = prompt_template | model

#历史记录消息模块
from langchain_community.chat_message_histories import ChatMessageHistory

#消息对象
history = ChatMessageHistory()

#超过六条历史记录汇总成一条消息摘要
def summarize_message(chain_input):
    stored_message = history.messages
    if len(stored_message) >= 6:
        summarize_prompt = ChatPromptTemplate.from_messages(
            [
                MessagesPlaceholder(variable_name='history'),
                ('user','将上述聊天信息提炼成一条摘要信息。尽可能多的包含具体细节。')
            ]
        )
        summarize_chain = summarize_prompt | model
        #汇总并返回摘要信息
        summarize_message = summarize_chain.invoke({'history':stored_message})
        #历史记录清空
        history.clear()
        #把汇总摘要信息添加到历史记录中
        history.add_message(summarize_message)
    return chain_input

#'记忆添加
chain_with_memory = RunnableWithMessageHistory(
    chain,
    lambda x:history,
    input_messages_key = 'new_message',
    history_messages_key = 'history'
)

chain_with_summarization = summarize_message |chain_with_memory

#多轮会话
while True:
    new_message = input('You:')
    response = chain_with_summarization.invoke(
        {
            'new_message':new_message,
        },
        config={
            "configurable":{
                "session_id":'unused'
            }
        }
    )
    print(response.content)

运行结果

python 复制代码
You:我是一名大四学生,正在学习云计算
很高兴听到你正在学习云计算!云计算是一个快速发展的领域,有很多有趣的知识和技术可以探索。你正在关注哪些特定的主题或技术呢?例如,基础设施即服务(IaaS)、平台即服务(PaaS)、软件即服务(SaaS)、虚拟化、容器技术(如Docker和Kubernetes)等?或者你对某些云服务提供商(如AWS、Azure、Google Cloud等)有兴趣?
You:linux的介绍
Linux是一种开源的类Unix操作系统,其内核最初由Linus Torvalds于1991年发布。Linux以其强大的性能、安全性以及高度的可定制性而闻名,是服务器、嵌入式系统、超级计算机和个人计算机等多种设备上的常用操作系统。

以下是Linux的一些主要特点和组成部分:

### 1. 开源
Linux是开源软件,这意味着其源代码可以被任何人查看、修改和分发。这样的特性促进了社区的发展,许多开发者和企业为其贡献代码。

### 2. 多用户和多任务
Linux是一个多用户、多任务的操作系统,允许多个用户同时访问系统并运行多个程序。这种设计使得Linux非常适合服务器和数据中心环境。

### 3. 强大的安全性
Linux被认为是一个安全性较高的操作系统。由于其
You:你了解多少关于我的
作为一个聊天机器人,我并不具备获取或存储个人信息的能力,因此我对你的具体情况了解非常有限。我的主要任务是根据你提供的信息与问题进行对话。如果你愿意分享更多关于你的学习或兴趣的信息,我将很乐意提供更多相关的帮助和建议!
You:我的身份是什么
根据你之前提供的信息,你是一名大四学生,正在学习云计算。如果还有其他信息或想要讨论的主题,请告诉我!
You:
相关推荐
lkbhua莱克瓦242 小时前
Prompt、分词器与Token介绍
人工智能·ai·prompt·token
我是小疯子662 小时前
Python+Copilot:从语法纠错到重构的极速开发指南
python
阿拉丁的梦2 小时前
c4d物理烘焙为骨骼动画!AI(gemini)编程
python·c4d
儒雅芝士2 小时前
Mujoco细节知识
开发语言·python
知乎的哥廷根数学学派10 小时前
面向可信机械故障诊断的自适应置信度惩罚深度校准算法(Pytorch)
人工智能·pytorch·python·深度学习·算法·机器学习·矩阵
且去填词10 小时前
DeepSeek :基于 Schema 推理与自愈机制的智能 ETL
数据仓库·人工智能·python·语言模型·etl·schema·deepseek
人工干智能10 小时前
OpenAI Assistants API 中 client.beta.threads.messages.create方法,兼谈一星*和两星**解包
python·llm
databook11 小时前
当条形图遇上极坐标:径向与圆形条形图的视觉革命
python·数据分析·数据可视化
阿部多瑞 ABU11 小时前
`chenmo` —— 可编程元叙事引擎 V2.3+
linux·人工智能·python·ai写作