news 2026/9/26 4:04:45

LangChain 1.x 实战笔记(一):接入模型 —— 一个 base_url 打通所有大模型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangChain 1.x 实战笔记(一):接入模型 —— 一个 base_url 打通所有大模型

📌《LangChain + RAG 全链路学习笔记》系列 · 第 1 篇(共 13 篇)

作者:AvA
环境:Python 3.11 +LangChain 1.x

⚠️看之前先注意一件事:网上大量 LangChain 教程还是 0.3.x 版本,导入路径已经变了,照抄会直接ModuleNotFoundError: No module named 'langchain'。本系列每一处都标注了新旧路径差异,代码全部本机实测跑通。

这一章解决什么问题

不解决任何业务问题,只回答一件事:

怎么用一行invoke把一句话发给大模型,并把回答拿出来。

听起来简单,但这里有一个国内开发者绕不开的问题:模型厂商这么多,难道每换一家就要换一套 SDK、改一遍代码?

这一章给出了答案。

核心结论:OpenAI 兼容协议

国内主流厂商——DeepSeek、通义、月之暗面、智谱——都提供了「OpenAI 兼容接口」:它们的 API 形态和 OpenAI 一模一样,只是域名不同。

所以只要改一个base_url,同一个ChatOpenAI类就能调所有厂商,不需要为每家装一个专用包。

importosfromlangchain_openaiimportChatOpenAI llm=ChatOpenAI(model="deepseek-chat",base_url="https://api.deepseek.com/v1",# ← 精髓就这一行api_key=os.environ.get("DEEPSEEK_API_KEY"),temperature=0,)

课程里演示了四种接法,结论如下:

接法写法评价
直连 OpenAIChatOpenAI(model=...)最标准
厂商专用包langchain_deepseek.ChatDeepSeek要额外装包,且只认一家
社区包langchain_community的ChatTongyi需要dashscope依赖
兼容协议ChatOpenAI+base_url⭐推荐,一个类通吃

最小可运行代码

importosfromdotenvimportload_dotenvfromlangchain_openaiimportChatOpenAI load_dotenv()# ① 必须在创建客户端之前llm=ChatOpenAI(model="deepseek-chat",base_url="https://api.deepseek.com/v1",api_key=os.environ["DEEPSEEK_API_KEY"],# 用中括号:拼错会当场 KeyErrortemperature=0,)response=llm.invoke("你是谁?")# ② 返回 AIMessage 对象print(response.content)# ③ 要 .content 才是正文

两个必须记住的约定:

  1. load_dotenv()必须在创建客户端之前调用—— 客户端在构造的那一刻就去读环境变量。
  2. 拿到的是AIMessage对象,不是字符串—— 要.content取正文。

⚠️ 我踩到的坑

1.load_dotenv()放错位置,报错却和.env无关

放到ChatOpenAI(...)后面 → key 读不到 → 报鉴权错误(AuthenticationError),而不是「找不到 .env 文件」。报错信息会把你往错误的方向带。

2.os.environ.get("XXX")拼错变量名不报错

它会静默返回None,一路传到 API 那里才炸,表现为鉴权失败。

想立刻发现,用方括号:os.environ["DEEPSEEK_API_KEY"]—— 键不存在直接KeyError,当场暴露。

3.import成功 ≠ 能用

ChatTongyi的dashscope是在构造时才 import 的。所以:

fromlangchain_community.chat_modelsimportChatTongyi# ✅ 成功llm=ChatTongyi(...)# ❌ 这里才 ImportError

这是个思维陷阱:别人说「装了这个包」,不代表你 import 一下就能用。

4.model=还是model_name=?

ChatOpenAI两个都能用(字段真名是model_name,model是别名),但ChatDeepSeek/ChatTongyi只认model。

👉统一写model=最安全。

5. 忘了.content

直接print(response)会打出一坨:

content='...' additional_kwargs={} response_metadata={} ...

⚠️ 1.x 和 0.3.x 的导入路径差异

这条是本篇相对网上教程最大的不同:

# 网上 0.3.x 教程:fromlangchain.chat_modelsimportChatOpenAI# 本机 1.x 实际:fromlangchain_openaiimportChatOpenAI# ⭐ 单独成包了

照抄老教程会直接ModuleNotFoundError: No module named 'langchain'。


补充 ①:我为什么选了 DeepSeek

主要还是控制成本。我平时用的 Claude Code,里面接的就是我自己配的deepseek-v4-flash,加上最近 DeepSeek 出了 v4.1,价格也往下调了(截至 2026 年 9 月)。


补充 ②:我实际遇到的第一个报错

第一个错误就是这个ModuleNotFoundError: No module named 'langchain',这个是因为课程使用的是老的版本,他和新版本之间的导入不同。

第二个错误是我导入的时候,包的大小写错了一处。这个错误其实会报错,但从报错信息里看不出是大小写的问题 —— 我盯着代码看了半天就是没发现,最后问 AI 才找出来。人眼对大小写是真的不敏感。


补充 ③:为什么改一个base_url就能调所有厂商

我个人觉得这个东西可能和我现在使用的这个 Claude 比较像,就是这个 openai 设置的是一个通用接口,所以只需要提供模型商的网址,就是 base_url 就可以了,然后每个模型商会给自己的模型提供专用的接口,这个可能是比这个统一的接口更加适配,包括速度快,损耗少啥的。


✅ 自测三问

  1. ChatOpenAI(...).invoke("你好")返回什么类型?要打印纯文本该怎么写?

    AIMessage是一个消息对象,不是字符串。正文在它的.content里,所以打印纯文本要写print(response.content)。

    我一开始以为print(response)会报错,其实不会—— 它会把content、response_metadata、usage_metadata等 9 个字段一股脑全打出来。不报错反而更坑:报错你会去查,不报错你只会纳闷「这什么玩意儿」。

    顺带一提,那一坨不是 JSON,是 Python 对象的 repr —— 看引号就能分:单引号'...'是 Python,双引号"..."才是 JSON。真要存它或者传给前端,才需要json.dumps(response.model_dump())。

  2. 想用ChatOpenAI调 DeepSeek,最少传哪几个参数?

    model、base_url、api_key。

  3. 把load_dotenv()挪到ChatOpenAI(...)后面,报错信息为什么看起来跟.env无关?

    因为那时候环境变量还没来得及加载,key 读到的是None,一路传到 API 那里才以「鉴权失败」的形式炸出来。


📖本系列共 13 篇,下一篇:02 模型与消息 ——LLM和ChatModel到底差在哪

笔记同步更新在 GitHub:github.com/MaDai66/langchain-rag-notes
代码基于 LangChain 1.x 实测,有问题欢迎评论区交流。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/26 4:04:25

拿下开源生图第一,千问Qwen-Image-2.1把生图卷出新高度

视觉生成模块仅7B,生图、改图、透明素材装进了同一个模型。 AI 写代码的能力经常能让开发者「双手离开键盘」,但对于设计师而言,AI 生成的图片距离能交稿总是差了好几步。 在图像设计的工作流中,人物需要抠图、素材需要改字、各…

作者头像 李华
网站建设 2026/9/26 4:03:44

C语言学习--回顾(05)

(第五篇) 目录 (第五篇) 2.6while循环 {1}补充内容 2.7 for循环 2.8 do while循环 2.9 break与continue​编辑 2.10嵌套循环 2.11 goto语句 2.12 随机数生成 2.6while循环 (a)while与if 的差别在于…

作者头像 李华
网站建设 2026/9/26 4:03:17

Python 自制文件下载器

1. 项目概述当你文件下载很慢时,如何不用别的工具,自己用趁手的工具自行搭建一个用 Python 编写一个功能完整的文件下载器。2. 环境准备本项目基于 Python 3.8 及以上版本开发,无需安装任何第三方依赖。建议使用虚拟环境隔离项目,…

作者头像 李华
网站建设 2026/9/26 4:02:58

一人公司如何用WorkBuddy搭建自动化工作流:Skill与Agent实战指南

1. 一人公司的效率困局与 WorkBuddy 的破局思路一个人干一家公司的活,最怕的不是没活干,而是活太杂。早上写文案,中午剪视频,下午回客户消息,晚上还要整理数据报表,中间穿插着发票、合同、选题、排期。每切…

作者头像 李华
网站建设 2026/9/26 4:02:48

Spring Boot避坑指南:版本兼容、配置与Bean注入排查全解析

Spring Boot这套东西,上手是真的快,十分钟就能跑起来一个接口,但真要说把它用顺了,坑是一点儿都不少。我这些年帮人排查问题,发现十个报错里至少有六个是版本不匹配、配置缩进错误、Bean注入失败这类基础问题&#xff…

作者头像 李华