用LangChain工程化调用通义千问:密钥封装与流式输出

文章配图

原生 API 调通模型只是第一步,真要在项目里长期跑,绕不开三件事:密钥怎么放、调用怎么分层、提示词怎么复用。这篇以通义千问为例,把 LangChain 的工程化接法过一遍,顺带修正两处教程里高频出现的坑。

先把依赖收干净

对接千问的 OpenAI 兼容接口,两个包就够:

uv pip install langchain-openai pydantic

langchain-openai 是官方集成库,走兼容模式;pydantic 负责数据校验和密钥封装。项目结构上建议按平台分目录——百炼一个目录、其他平台一个目录,后续换模型不动老代码。

坑一:密钥类型写错,SecretString 并不存在

不少教程里会写 from pydantic import SecretString,在 pydantic v2 下这行直接报 ImportError。正确类型名是 SecretStr:

from langchain_openai import ChatOpenAI
from pydantic import SecretStr

API_KEY = SecretStr("你的百炼平台API密钥")

llm = ChatOpenAI(
    model="qwen-max-latest",
    api_key=API_KEY,
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    streaming=True,
    temperature=0.7,
)

SecretStr 的价值在日志安全:print(API_KEY) 输出的是 **********,不会把明文泄到控制台或日志文件里。校验一下:

print(API_KEY)            # **********
print(API_KEY.get_secret_value())  # 真实值,仅在发请求时用

坑二:base_url 少了 compatible-mode 路径

这是新手最高频的报错来源。百炼的 OpenAI 兼容端点必须带 /compatible-mode/v1 后缀,直接写根域名会得到 404 或 Model not exist。报错时的三步定位:

# 1. 先用 curl 验证密钥和端点本身通不通
curl -s https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"qwen-max-latest","messages":[{"role":"user","content":"hi"}]}'

# 2. 返回 401 Invalid API-key -> 密钥错了或没开通模型
# 3. 返回 404 / model not exist -> 检查模型名拼写与账号是否有该模型权限

判定标准:curl 能拿到 choices 字段,说明端点、密钥、模型名三者都对,问题一定在你的应用代码;curl 都不通,别急着改代码,先解决账号问题。

两种调用模式,按场景选

同步调用适合批处理,一次拿全量结果:

resp = llm.invoke("用一句话说明LangChain的核心价值")
print(resp.content)

流式调用适合对话界面,逐 token 刷新:

for chunk in llm.stream("用一句话说明LangChain的核心价值"):
    print(chunk.content, end="", flush=True)

流式有个排版细节:end="" 必须带上,否则 print 默认换行,输出会变成一行一个字。

提示词复用:模板固化 + 变量替换

相似场景反复手写提示词是维护灾难。用 PromptTemplate 把固定骨架沉淀下来,只留变量槽:

from langchain_core.prompts import PromptTemplate

tpl = PromptTemplate(
    input_variables=["user_query", "task_type"],
    template="""
    你是一名专业的AI技术助手,擅长{task_type}。
    请根据用户问题作答,回答简洁、给出可执行步骤:
    用户问题:{user_query}
    """
)

final_prompt = tpl.format(
    task_type="大模型框架开发",
    user_query="如何排查模型连接超时?",
)
print(llm.invoke(final_prompt).content)

注意 import 路径:老教程常见的 from langchain.prompts import ... 在 langchain 0.2+ 已建议迁移到 langchain_core.prompts,旧路径能跑但会有弃用警告,新项目直接用新路径省得后面重构。

工程收益有三条:改提示词只动模板一处;多场景风格统一;变量有 input_variables 声明,漏传参数会在 format 阶段立刻报错,而不是把 {xxx} 原样发给模型。

temperature 的取舍

代码生成、事实问答设 0——随机性越低越好复现;文案、创意类给 0.7 到 1。调试报错排查类问题时建议固定 0,否则同一个 bug 两次回答思路不同,会干扰你定位是代码问题还是模型波动。

小结

密钥用 SecretStr 封装、端点带全 compatible-mode 路径、curl 先行验证、模板复用提示词——四件事做完,千问的调用层就算工程化落地了。下一步接自定义工具和 Agent 编排时,这层地基越稳,上层越省心。

0

评论0

请先
显示验证码
没有账号?注册  忘记密码?