Python-langchain对接LLM-2

虽然【阿里百炼(通义千问)】官网的示例是使用【openai】python框架,但是Langchain在行业中确实有着举足轻重的影响,在此记录使用langchain的学习过程


1-知识整理

1-Langchain的消息类型对比->langchain_core.messages

messages = [
    {"role": "system", "content": "You are a helpful assistant! Your name is Bob."},
    {"role": "user", "content": "你是谁?"},
]

from langchain_core.messages import SystemMessage, HumanMessage
messages = [
    SystemMessage(content="You are a helpful assistant! Your name is Bob."),
    HumanMessage(content="你是谁?"),
]

2-提取通用的提示词并支持参数注入->langchain_core.prompts

from langchain_core.prompts import ChatPromptTemplate, PromptTemplate

# 先准备一个字符串模板
system_tpl = PromptTemplate(
    input_variables=["field"],
    template="你是一位资深{field}专家,回答请严谨。"
)

# 再转成消息模板
chat_tpl = ChatPromptTemplate.from_messages([
    ("system", system_tpl.template),   # 注意这里还是字符串,变量会一起传
    ("human", "{question}")
])

prompt_value = chat_tpl.format_prompt(field="量子物理", question="什么是叠加态?")
print(llm.invoke(prompt_value.messages).content)

3-PromptTemplate vs Template

输入/输出 典型用途 能否直接给 Chat 模型
PromptTemplate 一个字符串模板 → 一个字符串 完形填空式 prompt,用于 Completion/LLMChain ❌ 需再包成 HumanMessage
ChatPromptTemplate 消息列表模板 → PromptValue.messages 多角色对话(system/human/ai/…) ✅ 直接喂给 ChatOpenAI 等
FewShotPromptTemplate 把“例子池”动态拼进 PromptTemplate 少样本学习 ❌ 本质还是字符串,需再转消息
PipelinePrompt / ConditionalPrompt … 组合/条件分支等高级玩法 复杂模板复用 视底层模板而定

一句话:
只要模型接口是 chat(.invoke([messages])),就用 ChatPromptTemplate;
如果模型接口是 completion(.invoke(string)),就用 PromptTemplate。



2-参考网址


3-动手实操

1-UV环境管理

# 1-查看并指定环境
uv python list
uv python pin 3.10

# 2-进行项目创建
uv init hello-langchain && cd hello-langchain

# 3-指定本地运行环境
uv venv && source .venv/bin/activate

# 4-本地环境安装依赖
uv pip install python-dotenv pydantic langchain-openai

2-LangChain-Invoke对话

from langchain_openai import ChatOpenAI
from pydantic import SecretStr

from settings import DASHSCOPE_API_KEY

# 1-定义客户端
llm = ChatOpenAI(
    model="qwen-max",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key=SecretStr(DASHSCOPE_API_KEY),
    streaming=True
)

# 2-定义对话上下文
messages = [
    {"role": "system", "content": "You are a helpful assistant! Your name is Bob."},
    {"role": "user", "content": "你是谁?"},
]

# 3-打印
response = llm.invoke(messages)
print("----llm:", llm)
print("----content:", response.content)
print("----model_dump_json:", response.model_dump_json())

3-LangChain-Stream对话

from langchain_core.messages import SystemMessage, HumanMessage
from langchain_openai import ChatOpenAI
from pydantic import SecretStr

from settings import DASHSCOPE_API_KEY

# 1-定义客户端
llm = ChatOpenAI(
    model="qwen-max",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key=SecretStr(DASHSCOPE_API_KEY),
    streaming=True
)

# 2-定义对话上下文
messages = [
    SystemMessage(content="You are a helpful assistant! Your name is Bob."),
    HumanMessage(content="你是谁?"),
]
# 3-打印
response = llm.stream(messages)
for chunk in response:
    # print("----chunk:", chunk)
    # print("----chunk:", chunk.content)
    # 打印不换行
    print(chunk.content, end="")


4-知识补充

1-PromptTemplate的对话示例

下面用一张“速览表”先把概念区分清楚,再给出 3 组可直接运行的对话示例,让你一眼看懂 PromptTemplate 到底该在哪用、不该在哪用。


一、速览:PromptTemplate vs 其它 Template

输入/输出 典型用途 能否直接给 Chat 模型
PromptTemplate 一个字符串模板 → 一个字符串 完形填空式 prompt,用于 Completion/LLMChain ❌ 需再包成 HumanMessage
ChatPromptTemplate 消息列表模板 → PromptValue.messages 多角色对话(system/human/ai/…) ✅ 直接喂给 ChatOpenAI 等
FewShotPromptTemplate 把“例子池”动态拼进 PromptTemplate 少样本学习 ❌ 本质还是字符串,需再转消息
PipelinePrompt / ConditionalPrompt … 组合/条件分支等高级玩法 复杂模板复用 视底层模板而定

一句话:
只要模型接口是 chat(.invoke([messages])),就用 ChatPromptTemplate;
如果接口是 completion(.invoke(string)),就用 PromptTemplate。


二、PromptTemplate 核心 API

from langchain_core.prompts import PromptTemplate

pt = PromptTemplate(
    input_variables=["topic", "n"],
    template="用{n}句话向小学生解释什么是{topic}。"
)

pt.format(topic="光合作用", n=3)
# → '用3句话向小学生解释什么是光合作用。'


三、对话示例(3 个场景)

场景 1:字符串 → Completion 模型(OpenAI text-davinci-003 类)

from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI

tpl = PromptTemplate(
    input_variables=["topic"],
    template="列出关于{topic}的 5 个关键词,用逗号分隔:"
)

# 格式输入的消息内容
format_message = tpl.format(topic="量子计算")

# 模型对话
llm = OpenAI(temperature=0)          # 注意是 Completion 接口
llm_output = llm.invoke(format_message)
print(llm_output)
# 量子比特,叠加,纠缠,量子门,量子算法

场景 2:把 PromptTemplate 包成 HumanMessage,再交给 Chat 模型

from langchain_core.prompts import PromptTemplate
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI

tpl = PromptTemplate(
    input_variables=["lang", "code"],
    template="请把下面的 {lang} 代码加上行号:\n\n{code}"
)

# 格式输入的消息内容
format_message = tpl.format(lang="Python", code="print('hello')")
messages = [HumanMessage(content=format_message)]

# 模型对话
llm = ChatOpenAI(temperature=0)
llm_output = llm.invoke(messages)
print(llm_output.content)

输出:

1 print('hello')

场景 3:与 ChatPromptTemplate 混用——“动态 system + 动态 human”

from langchain_core.prompts import ChatPromptTemplate, PromptTemplate

# 先准备一个字符串模板
system_tpl = PromptTemplate(
    input_variables=["field"],
    template="你是一位资深{field}专家,回答请严谨。"
)

# 再转成消息模板
chat_tpl = ChatPromptTemplate.from_messages([
    ("system", system_tpl.template),   # 注意这里还是字符串,变量会一起传
    ("human", "{question}")
])

prompt_value = chat_tpl.format_prompt(field="量子物理", question="什么是叠加态?")
print(llm.invoke(prompt_value.messages).content)

输出:

叠加态是指一个量子系统可以同时处于多个本征态的线性组合,直到被测量才坍缩到某一确定态。

四、一句话总结

PromptTemplate 只管“字符串→字符串”;
ChatPromptTemplate 管“多角色消息→消息列表”。
模型接口决定用谁:completion 用前者,chat 用后者。


2-ChatPromptTemplate的对话示例

下面给出 3 个最常见的使用场景,每个场景都给出

  1. 模板定义(ChatPromptTemplate)
  2. 填充变量后的实际消息列表(prompt_value.messages)
  3. 用任意 LLM 跑一次对话的完整代码(可直接复制到 python 里跑通)。
    依赖:langchain-core ≥ 0.2,任何 chat 模型接口(这里用 ChatOpenAI 做示范)。

场景 1:单轮问答(System + Human)

from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

# 1. 定义模板
template = ChatPromptTemplate.from_messages([
    ("system", "你是{role},回答尽量简洁。"),
    ("human", "{question}")
])

# 2. 填充变量
prompt_value = template.format_prompt(role="法律顾问", question="租房合同没到期可以退押金吗?")

# 3. 查看实际发出去的消息
for m in prompt_value.messages:
    print(f"{m.type}: {m.content}")

# 4. 直接调用模型
llm = ChatOpenAI(temperature=0)
ai_msg = llm.invoke(prompt_value.messages)
print("AI:", ai_msg.content)

运行结果示例:

system: 你是法律顾问,回答尽量简洁。
human: 租房合同没到期可以退押金吗?
AI: 原则上不能单方要求退还;若房东违约或双方协商一致可退,具体看合同条款与地方规定。

场景 2:多轮对话(带上历史记录)

history = [
    ("human", "我叫小北。"),
    ("ai", "你好小北,很高兴认识你!"),
]

template = ChatPromptTemplate.from_messages([
    ("system", "你是{role},记住用户名字。"),
    *history,                       # 直接把历史解包进来
    ("human", "{input}")
])

prompt_value = template.format_prompt(role="聊天助手", input="你知道我叫什么吗?")
llm = ChatOpenAI(temperature=0)
print(llm.invoke(prompt_value.messages).content)

输出:

当然记得,你叫小北。

场景 3:Few-shot / 工具调用(带示例)

examples = [
    {"lang": "zh", "code": "print('你好')"},
    {"lang": "en", "code": "print('hello')"},
]

template = ChatPromptTemplate.from_messages([
    ("system", "根据自然语言描述生成对应语言的代码。"),
    *[("human", f"请写一段{ex['lang']}代码") for ex in examples],
    *[("ai", ex["code"]) for ex in examples],
    ("human", "{request}")
])

prompt_value = template.format_prompt(request="请写一段法语代码")
print(llm.invoke(prompt_value.messages).content)

输出:

print('Bonjour')

小结

ChatPromptTemplate.from_messages 接收一个「消息列表」,每条消息可以是

  • 元组形式 (role, template_str)
  • BaseMessage 的子类(SystemMessage, HumanMessage, AIMessage 等)。

模板字符串里用 {变量} 占位,调用 format_prompt(**kwargs) 即可得到 PromptValue,其 .messages 就是可直接喂给任何 LangChain chat 模型的标准消息列表。


Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐