惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V2EX - 技术
V2EX - 技术
P
Privacy International News Feed
Security Latest
Security Latest
H
Hacker News: Front Page
T
Tenable Blog
The Hacker News
The Hacker News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
Security @ Cisco Blogs
Project Zero
Project Zero
O
OpenAI News
AI
AI
Spread Privacy
Spread Privacy
C
CERT Recently Published Vulnerability Notes
The Last Watchdog
The Last Watchdog
G
GRAHAM CLULEY
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Scott Helme
Scott Helme
Application and Cybersecurity Blog
Application and Cybersecurity Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
CXSECURITY Database RSS Feed - CXSecurity.com
NISL@THU
NISL@THU
A
Arctic Wolf
T
Threat Research - Cisco Blogs
PCI Perspectives
PCI Perspectives
N
News and Events Feed by Topic
C
Cyber Attacks, Cyber Crime and Cyber Security
C
Cybersecurity and Infrastructure Security Agency CISA
Simon Willison's Weblog
Simon Willison's Weblog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Know Your Adversary
Know Your Adversary
Google Online Security Blog
Google Online Security Blog
罗磊的独立博客
L
LINUX DO - 最新话题
U
Unit 42
S
Security Affairs
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
博客园 - 【当耐特】
T
The Exploit Database - CXSecurity.com
S
Schneier on Security
月光博客
月光博客
Engineering at Meta
Engineering at Meta
腾讯CDC
F
Full Disclosure
Cyberwarzone
Cyberwarzone
S
SegmentFault 最新的问题
Recorded Future
Recorded Future
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 司徒正美
The Cloudflare Blog

Liu Zijian's Blog | 一个技术博客

使用Certbot自动续签HTTPS证书 使用Filebeat采集Nginx日志到ES Python的协程 Python中的异常 Python中的类和对象 Python的函数 Python的数据结构,推导式、迭代器和生成器 Spring AI集成多模态模型 LangChain4j多模态 LangChain Tools工具使用 Python中的模块和包 Python全局环境和虚拟环境(venv) LangChain4j Tools工具使用 基于Dify搭建AI智能体应用 LangChain4j RAG检索增强生成 Spring AI实现MCP Server Spring AI集成MCP Client LangChain4j Prompt提示词工程 Spring AI使用知识库增强对话功能 Spring AI实现一个智能客服 Spring AI实现一个简单的对话机器人 实现MinIO数据的每日备份 自己实现一个DNS服务 简单理解AI智能体 大模型和大模型应用 LangChain开篇 LangChain4j开篇 一个解析Excel2007的POI工具类 DataPermissionInterceptor源码解读 TenantLineInnerInterceptor源码解读 BaseMultiTableInnerInterceptor源码解读 Spring AI开篇 SQL解析工具JSQLParser 芋道源码解读之多租户 芋道源码解读之数据权限 芋道源码解读开篇 Java实现将数据导出为Word文档 OA系统的天数该怎样计算 安装MySQL8 安装MySQL5.7 RockyLinux9环境下编译MySQL8 MySQL字符集及底层原理 Java实现LDAP登录 Docker Compose IPv4和IPv6 使用虚拟机安装一个K8s集群 使用GraalVM原生编译打包SpringBoot工程 Nginx防止目录穿越 Java线程的状态 Nginx防盗链设置 使用python将excel表格转换为SQL INSERT Redis的公共操作命令 Redis数据结构之Bitfleid Redis数据结构之Bitmap Redis数据结构之GEO Redis数据结构之Hash Redis数据结构之HyperLogLog Redis数据结构之List Redis数据结构之Set Redis数据结构之Stream Redis数据结构之String Redis数据结构之ZSet 使用python压缩图片 利用Python实现Hexo站点的持续集成 Nginx设置HTTPS监听 firewalld防火墙工具的使用 Linux信号(signal)机制 MySQL5.7x 主从复制 用IP自签发一个HTTPS证书 基于Hexo实现一个静态的个人博客 RockyLinux9环境下编译MySQL5.7 Docker离线安装 MySQL数据定义语言 Docker与联合文件系统 Docker的网络 Docker的镜像操作 MySQL存储过程 MyBatis-Plus开篇 MySQL变量 MySQL视图 MySQL事务 MySQL插入修改和删除 MySQL查询 MySQL系统命令 Docker的容器操作 Docker的安装和配置 Docker容器数据卷 浅谈OAuth2.0授权原理 JVM开篇 浅谈Linux(Unix)的I/O模型 一个通用的CloseableHttpClient工厂类 JUC可重入锁ReentrantLock JUC读写锁ReadWriteLock Java的单例 Java泛型 Java8的新特性 最近最少使用算法(LRU) MySQL函数 SpringBoot配置和启动 volatile作用分析
LangChain Prompt提示词工程
Liu Zijian · 2025-12-12 · via Liu Zijian's Blog | 一个技术博客

本文未完待续

引言

本文基于Python 1.13.x和LangChain 1.1.2,并采用DeekSeep大模型,介绍LangChain提示词工程的实现。

pip install langchain==1.1.2
pip install langchain-openai

langchain-openai底层也是对openai官方OpenAI Python API的封装,也可以直接用官方OpenAI Python,但是没有必要

类似的其他语言和框架的提示词工程实现案例,可以移步:

1.对话

一个基于init_chat_model的简单的对话实现

  • model 大模型名称
  • model_provider 采用协议
  • api_key API_KEY
  • base_url 接口地址
  • temperature 温度,越高内容越随机,越低,内容越确定
  • max_tokens 生成内容的最大token数
  • timeout 请求超时时间
  • max_retries 最大重试次数

上述这些参数,可能对某些大语言模型无效,仅对于langchain官方提供的集成包例如langchain-openai,langchain-anthropic等有效,对于langchain-community下定义的第三方模型可能无效

from langchain.chat_models import init_chat_model
import os

llm = init_chat_model(
    model = 'deepseek-chat',
    model_provider = 'openai',
    api_key = os.getenv('DSKEY'),
    base_url = 'https://api.deepseek.com'
)

msg = llm.invoke('你是谁')
print(msg)

model.invoke()返回的是一个AIMessage对象,包括以下常见内容

  • type 描述是哪个类型的消息:user/ai/system/tool
  • content 大模型的输出,一般是字符串,多模态模型可能是其他内容
  • name 当消息类型相同,对消息进行区分,不是所有模型都支持
  • response_metadata ai消息才会包含的属性,附加元数据,不同模型内容也是不一样的
  • tool_calls ai消息才会包含的属性,当大模型决定调用某个工具时,就会包含,每个元素是一个字典,包含工具名name,参数args,工具唯一标识id等

可以通过llm.stream返回的迭代器对象Iterator[AIMessageChunk],得到实时流式返回的输出,打印追加


from langchain.chat_models import init_chat_model
import os

llm = init_chat_model(
    model = 'deepseek-chat',
    model_provider = 'openai',
    api_key = os.getenv('DSKEY'),
    base_url = 'https://api.deepseek.com'
)

for trunk in llm.stream('你是谁'):
    print(trunk.content, end='')

print('结束')

还可以每次返回和之前的返回拼接在一起

无数trunk对象通过+加在一起,底层是用重写__add__()方法运算符重载实现

from langchain.chat_models import init_chat_model
import os

llm = init_chat_model(
    model = 'deepseek-chat',
    model_provider = 'openai',
    api_key = os.getenv('DSKEY'),
    base_url = 'https://api.deepseek.com'
)

full = None
for trunk in llm.stream('用一句话介绍自己'):
    full = trunk if full is None else full + trunk
    print(full.text)
    print(full.content_blocks)

print('结束')
print(full.content_blocks)

运行结果:

[]
你好
[{'type': 'text', 'text': '你好'}]
你好,
[{'type': 'text', 'text': '你好,'}]
你好,我是
[{'type': 'text', 'text': '你好,我是'}]
你好,我是Deep
[{'type': 'text', 'text': '你好,我是Deep'}]
你好,我是DeepSe
[{'type': 'text', 'text': '你好,我是DeepSe'}]
你好,我是DeepSeek
[{'type': 'text', 'text': '你好,我是DeepSeek'}]
你好,我是DeepSeek,
[{'type': 'text', 'text': '你好,我是DeepSeek,'}]
你好,我是DeepSeek,一个
[{'type': 'text', 'text': '你好,我是DeepSeek,一个'}]
你好,我是DeepSeek,一个由
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由'}]
你好,我是DeepSeek,一个由深度
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度'}]
你好,我是DeepSeek,一个由深度求
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求'}]
你好,我是DeepSeek,一个由深度求索
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索'}]
你好,我是DeepSeek,一个由深度求索公司
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司'}]
你好,我是DeepSeek,一个由深度求索公司创造的
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊'}]
你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊'}]
结束
[{'type': 'text', 'text': '你好,我是DeepSeek,一个由深度求索公司创造的AI助手,乐于用热情细腻的方式为你提供帮助!😊'}]

2.异步

langchain支持异步任务调用大模型,将invoke()换成ainvoke()即可

langchain中异步方法一般就是同步方法的方法名加一个’a’

import asyncio

from langchain.chat_models import init_chat_model
import os

llm = init_chat_model(
    model = 'deepseek-chat',
    model_provider = 'openai',
    api_key = os.getenv('DSKEY'),
    base_url = 'https://api.deepseek.com'
)

async def main():
    task1 = llm.ainvoke('你是谁')
    task2 = llm.ainvoke('你能做什么')
    v1 = await task1
    v2 = await task2
    print('v1', v1)
    print('v2', v2)

if __name__ == '__main__':
    asyncio.run(main())

异步流式,可实现两路请求同时实时返回大模型回答到程序中,出现两路控制台打印,可以提升吞吐量,异步流式返回异步生成器,遍历生成器时,要用异步for循环async for

flush=True 刷新缓冲区,实现流式打印


import asyncio

from langchain.chat_models import init_chat_model
import os

llm = init_chat_model(
    model = 'deepseek-chat',
    model_provider = 'openai',
    api_key = os.getenv('DSKEY'),
    base_url = 'https://api.deepseek.com'
)

async def main():

    async for trunk in llm.astream('你是谁'):
        print(trunk.content, end='', flush=True)

    async for trunk in llm.astream('你能做什么'):
        print(trunk.content, end='', flush=True)

if __name__ == '__main__':
    asyncio.run(main())

3.批处理

有时,需要向大模型发出不止一个问题,需要一次性回答完后一起得到结果,就用到了批处理batch()

from langchain.chat_models import init_chat_model
import os

from dotenv import load_dotenv

load_dotenv(encoding='utf-8')

llm = init_chat_model(
    model = 'deepseek-chat',
    model_provider = 'openai',
    api_key = os.getenv('DEEPSEEK_API_KEY'),
    base_url = 'https://api.deepseek.com'
)


questions = [
    '你是谁',
    '一句话介绍什么是neo4j',
    '一句话介绍什么是php'
]

lst = llm.batch(questions)

for q, a in zip(questions, lst):
    print(f'问题:{q},回答:{a.content}')
问题:你是谁,回答:你好!我是DeepSeek,由深度求索公司创造的AI助手。我是最新版本的DeepSeek模型,专门设计来帮助你解答问题、提供信息和进行对话。

我的一些特点包括:
- **免费使用**:完全免费,没有任何收费计划
- **强大的处理能力**:支持100万token的上下文,可以一次性处理像《三体》三部曲这样的大部头书籍
- **文件处理**:可以上传并读取图片、PDF、Word、Excel、PPT等文件中的文字信息
- **联网搜索**:支持联网查询最新信息(需要手动开启)
- **多平台支持**:提供Web端和App端,App还支持语音输入

有什么我可以帮你的吗?无论是学习、工作还是日常生活中的问题,我都很乐意为你提供帮助!😊
问题:一句话介绍什么是neo4j,回答:Neo4j 是一个高性能的图数据库,它以节点、关系和属性的图形结构来存储和查询高度关联的数据。
问题:一句话介绍什么是php,回答:PHP是一种主要用于Web开发的服务器端脚本语言,能嵌入HTML中动态生成网页内容。

异步批处理

import asyncio

from langchain.chat_models import init_chat_model
import os

from dotenv import load_dotenv

load_dotenv(encoding='utf-8')

llm = init_chat_model(
    model = 'deepseek-chat',
    model_provider = 'openai',
    api_key = os.getenv('DEEPSEEK_API_KEY'),
    base_url = 'https://api.deepseek.com'
)

questions = [
    '你是谁',
    '一句话介绍什么是neo4j',
    '一句话介绍什么是php'
]

async def main():
    lst = await llm.abatch(questions)

    for q, a in zip(questions, lst):
        print(f'问题:{q},回答:{a.content}')

if __name__ == '__main__':
    asyncio.run(main())

4.提示词模板

提示词经历了从简单的纯字符串提问,到占位符动态问题,再到多角色消息的历程,在和大语言模型交互时,通常不会原样将用户输入传递给大模型,而是进行相应的包装,组织和格式化,便于更清晰的表达意图,更好的利用模型能力。

常用提示词模板有PromptTemplate,ChatPromptTemplate,PipelinePrompt等。

4.1 PromptTemplate

PromptTemplate是最基础的提示词模板,通过格式化字符串生成提示词,常见参数:

  • template 字符串,包含占位符的模板({})的提示词
  • input_variables 列表,变量名称列表,传入时会进行替换
  • partial_variables 字典,提示词模板携带的部分变量字典,预先填充一些值,调用时无需再额外传入

通过format()方法格式化,一定要对input_variables中的变量赋值,否则会报错,如未设置则忽略,如果一个变量指定了默认值,也可以在调用时进行更换


例:使用构造方法构建PromptTemplate

from langchain_core.prompts import PromptTemplate

template = PromptTemplate(
    template='你是一个{role},请回答问题:{question}',
    input_variables=['role', 'question'],
    partial_variables={'role' : '教师'}
)

prompt = template.format(question='二次函数是什么')

print(prompt) #你是一个教师,请回答问题:二次函数是什么
from langchain_core.prompts import PromptTemplate

template = PromptTemplate(
    template='你是一个{role},请回答问题:{question}',
    input_variables=['role', 'question'],
    partial_variables={'role', '教师'}
)

prompt = template.format(question='二次函数是什么', role='高中数学教师')

print(prompt) #你是一个高中数学教师,请回答问题:二次函数是什么

例:使用from_template()方法来构建PromptTemplate

from langchain_core.prompts import PromptTemplate


template = PromptTemplate.from_template('你是一个{role},请回答问题:{question}')

prompt = template.format(question='二次函数是什么', role='高中数学教师')

print(prompt)

from langchain.chat_models import init_chat_model
import os
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableSequence
from langchain_core.prompts import PromptTemplate

llm = init_chat_model(
    model = 'deepseek-chat',
    model_provider = 'openai',
    api_key = os.getenv('DSKEY'),
    base_url = 'https://api.deepseek.com'
)

prompt_template = PromptTemplate(
    template='做一个关于{topic}的小诗',
    input_variables=['topic']
)

parser = StrOutputParser()

chain = RunnableSequence(prompt_template, llm, parser)


resp = chain.invoke({'topic': '霸道总裁爱上做保洁的我'})

print(resp)

提示词模板的调用如要想流式,只要改成chain.stream(...)即可

4.2 ChatPromptTemplate

ChatPromptTemplate是聊天模型提示词模板,包括SystemMessage,HumanMessage,AIMessage,ToolMessage几种

5.LCEL增强对话功能

要理解LCEL,首先要了解Runable,Runable(langchain_core.runnables.base.Runnable)是langchain中可以调用,批处理,流式输出,转换和组合的工作单元,是实现LCEL的基础,通过重写__or__()方法,实现了|运算符的重载,实现了Runable的类对象之间便可以进行一些类似linux命令中的管道(|)操作。

LCEL,全称LangChain Express Language,即LangChain表达式语言,也是LangChain官方推荐的写法,是一种从Runable而来的声明式方法,用于声明,组合和执行各种组件(模型,提示词,工具等),如果要使用LCEL,对应的组件必须实现Runable,使用LCEL创建的Runable称之为链。

例如,将刚刚提示词模板的例子用LCEL重写

import os

from langchain.chat_models import init_chat_model
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser

prompt_template = PromptTemplate(
    template='做一个关于{topic}的小诗',
    input_variables=['topic']
)

llm = init_chat_model(
    model = 'deepseek-chat',
    model_provider = 'openai',
    api_key = os.getenv('DSKEY'),
    base_url = 'https://api.deepseek.com'
)

parser = StrOutputParser()

# LCEL重写
chain = prompt_template | llm | parser

resp = chain.invoke({'topic': '霸道总裁爱上做保洁的我'})

print(resp)

还可以自定义一个word_count(text: str) -> int函数,通过langchain的RunnableLambda对象包装,使得函数变为获得链式的执行能力的Runable对象,拼入链中,统计大模型回复的字数


import os

from langchain.chat_models import init_chat_model
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableLambda

prompt_template = PromptTemplate(
    template='做一个关于{topic}的小诗',
    input_variables=['topic']
)

llm = init_chat_model(
    model = 'deepseek-chat',
    model_provider = 'openai',
    api_key = os.getenv('DSKEY'),
    base_url = 'https://api.deepseek.com'
)

parser = StrOutputParser()


def word_count(text: str) -> int:
    print('----------word_count---------')
    return len(text)

word_counter = RunnableLambda(word_count)

# LCEL重写
chain = prompt_template | llm | parser | word_counter

resp = chain.invoke({'topic': '霸道总裁爱上做保洁的我'})

print(resp)

运行:

----------word_count---------
232