> ## Documentation Index
> Fetch the complete documentation index at: https://www.yuan111.asia/doc/llms.txt
> Use this file to discover all available pages before exploring further.

# 16 · langchain_core 全地图：那个"地基包"里到底装了什么

> langchain_core 全地图：29 个模块、5 大家族，哪些天天用、哪些知道即可。

# 16 · langchain\_core 全地图：那个"地基包"里到底装了什么

## 开头的现象

老王问小林："你能一口气说出 langchain\_core 里有哪些模块吗？" 小林掰着手指头数："messages、prompts、runnables……呃，还有……" 数到第五个就卡住了。

他打开 `D:\lib\miniconda3\envs\learn-langchain\Lib\site-packages\langchain_core\` 目录，数了数——**29 个模块。** 小林倒吸一口凉气："我学了两个月，只用了里面的五六个。"

他决定用一天时间把整个包翻一遍，搞清楚：**每个模块是干嘛的？哪些我天天用？哪些我这辈子可能都用不上？用不上的，为什么用不上？**

## 第一幕：小林先搞懂了 langchain\_core 的"地位"——它是协议层

小林翻到 `langchain_core/__init__.py`，看到版本号 `1.5.1`。他又看了看自己装的包，恍然大悟：

```text theme={null}
你 import 的包                    里面的东西
├── langchain_core        ← 抽象基类 + 统一协议（29 个模块）
├── langchain-anthropic   ← ChatAnthropic（智谱/Claude 的实现）
├── langchain-openai      ← ChatOpenAI（DeepSeek/通义的实现）
├── langchain-chroma      ← Chroma（向量库的实现）
└── langgraph             ← 编排框架（状态图、checkpointer）
```

他明白了：**langchain\_core 是"地基"——定义"接口长什么样"；各集成包是"砖头"——实现"怎么连到具体服务"。** 他用的 `ChatAnthropic` 住在 `langchain_anthropic`，但它的"爹" `BaseChatModel` 住在 `langchain_core.language_models`。**他天天 import 的是砖头，但砖头长什么样，是地基说了算。**

他还把 29 个模块分成了 5 大家族，画了一张图：

```text theme={null}
① 消息与提示（对话的"信"）    messages, prompts, prompt_values
② 模型与解析（对话的"脑子"）  language_models, output_parsers, embeddings
③ 数据与检索（对话的"资料"）  documents, document_loaders, retrievers, vectorstores, cross_encoders
④ 组合与编排（对话的"流水线"）runnables, outputs, load, tools, agents
⑤ 基础设施（对话的"后勤"）    callbacks, tracers, utils, chat_history, stores,
                              caches, example_selectors, indexing, rate_limiters,
                              chat_loaders, chat_sessions, structured_query, exceptions
```

> 想验证"地位"吗？在 Python 里 `from langchain_core.language_models import BaseChatModel`，然后 `issubclass(ChatAnthropic, BaseChatModel)`——返回 True。你的 ChatAnthropic 就是 BaseChatModel 的孩子。

## 第二幕：小林逐个拜访——他标记了"天天用"的模块

小林从第①家族开始，一个一个拜访。他发现自己天天用的，集中在几个模块：

**messages（57 个导出）——他的老朋友。** 第 02、08、10 篇的 AIMessage、tool\_calls、usage\_metadata 全在这。他扫了一眼导出列表，看到了 `BaseMessage`（爹）、`HumanMessage`/`SystemMessage`/`AIMessage`/`ToolMessage`（四个孩子）、`ToolCall`（工具调用结构）、`trim_messages`（第 4 篇说的剪枝）。**"我天天用，不用复习。"**

**prompts（21 个导出）——刚吵完架的那个。** `ChatPromptTemplate`、`MessagesPlaceholder`、`PromptTemplate`——第 3 篇刚说过。

**language\_models（19 个导出）——爹在这。** `BaseChatModel`（invoke/stream/bind\_tools/with\_structured\_output 全定义在这）、`BaseLLM`（旧式文本模型）、还有一堆 `FakeListChatModel` 假模型。小林看到假模型，眼睛一亮：**"测试用！不用真调 API 就能模拟模型回复！"**

**embeddings（3 个导出）——第 8 篇的接口。** `Embeddings` 基类：`embed_query`/`embed_documents`。他的 HuggingFaceEmbeddings 就是实现这个接口的。

**documents（3 个导出）——第 7 篇的盒子。** `Document`（page\_content + metadata）、`BaseDocumentTransformer`（切分器的爹）、`BaseDocumentCompressor`（压缩器的爹）。

**retrievers（1 个类）——第 9 篇的检索器。** `BaseRetriever`，`invoke(query)` 返回 Document 列表。

**vectorstores（4 个导出）——第 8 篇的库。** `VectorStore`（add\_texts/similarity\_search/as\_retriever）、`VectorStoreRetriever`、还有 `InMemoryVectorStore`——小林看到这个乐了：**"内存版向量库？测试不用装 Chroma 了！"**

**runnables（29 个导出）——第 9 篇的流水线。** `Runnable`（invoke/stream/`|`/batch）、`RunnablePassthrough`、`RunnableLambda`、`RunnableWithMessageHistory`（**官方废弃，别学**——1.3.3 标记 deprecated，2.0 移除）。小林看到它旁边的 deprecated 标记，心里暗暗庆幸自己没在它身上浪费时间。

**tools（19 个导出）——第 10 篇的 @tool。** `BaseTool`、`tool` 装饰器、`ToolException`、`create_retriever_tool`。

小林画了张表，标出他的使用频率：

| 模块               | 小林的使用频率 | 一句话                                      |
| ---------------- | ------- | ---------------------------------------- |
| messages         | ⭐ 天天用   | 消息对象、tool\_calls、用量                      |
| prompts          | ⭐ 天天用   | ChatPromptTemplate、MessagesPlaceholder   |
| language\_models | ⭐ 天天用   | BaseChatModel（invoke/stream/bind\_tools） |
| output\_parsers  | ✅ 链尾必用  | StrOutputParser                          |
| embeddings       | ⭐ 天天用   | embed\_query/embed\_documents            |
| documents        | ⭐ 天天用   | Document                                 |
| retrievers       | ⭐ 天天用   | BaseRetriever                            |
| vectorstores     | ⭐ 天天用   | VectorStore + as\_retriever              |
| runnables        | ⭐ 天天用   | invoke/stream/\|/RunnablePassthrough     |
| tools            | ⭐ 天天用   | @tool/BaseTool                           |

> 想验证"天天用"吗？翻你自己的 `.py` 文件——`01_first_chat.py` 用了 language\_models（间接）、messages；`09_rag.py` 用了 prompts/runnables/output\_parsers/documents/retrievers/vectorstores。你早就在用了，只是没意识到它们住在哪个包里。

## 第三幕：小林拜访了"知道就行"的模块——以及为什么用不上

小林接着拜访剩下的模块，每个都问一句"我用得上吗"：

**callbacks（34 个导出）——"进阶才用，但很有用。"** 监听模型/链/工具的生命周期：`on_llm_start`、`on_llm_end`、`on_tool_start`……小林心想：**"做生产应用想'看到每次调用花了多少 token、耗时多久'，就写个 BaseCallbackHandler 子类。LangSmith 追踪底层就是它。"**

**chat\_history（普通模块）——"记忆的存储抽象。"** `BaseChatMessageHistory`、`InMemoryChatMessageHistory`。小林想起第 10 篇：**"这就是我手写 session 历史的'正规军'。LangGraph 的 checkpointer 是它的'进化版'。"**

**exceptions（7 个导出）——"报错时认类型用。"** `LangChainException`（所有异常的爹）、`OutputParserException`（解析失败）。小林点点头："报错先看异常类型，`LangChainException` 是总爹，catch 它不会漏。"

**outputs（7 个导出）——"内部结构，日常碰不到。"** `LLMResult`、`ChatResult`。小林解释给自己听：**"`model.invoke()` 直接给你 AIMessage，碰不到这些。它们是 `generate()` 批量接口和回调里的原始结构。"**

**load（6 个导出）——"序列化，配置管理才用。"** `dumps`/`loads`。小林心想：**"把 prompt 存成 JSON 文件，下次加载——生产配置管理才需要。"**

**stores（普通模块）——"通用 KV 存储。"** `BaseStore`、`InMemoryStore`。小林：**"比 chat\_history 更底层——存任何键值数据，跨会话共享。Agent 的记忆库用它。课程用不上。"**

**indexing（8 个导出）——"增量索引，生产文档更新才用。"** `index()`、`RecordManager`。小林：**"第 8 篇我每次 `shutil.rmtree` 重建库；生产环境文档会更新，才需要只处理新文档。课程用不上。"**

**rate\_limiters（2 个导出）——"API 限速，批量调用才用。"** `BaseRateLimiter`、`InMemoryRateLimiter`。小林：**"个人学习调 API 量小，用不上；生产批量调用才要防 429。"**

**example\_selectors（5 个导出）——"few-shot 选例子。"** `SemanticSimilarityExampleSelector`。小林：**"给模型几个例子再提问（few-shot）时，自动挑最相关的例子。做分类/抽取任务才有用。"**

**cross\_encoders（2 个导出）——"重排序，RAG 进阶才用。"** `BaseCrossEncoder`。小林：**"检索后再精排（Reranker），生产级 RAG 才用。我的 2-Step RAG 用向量相似度够了。"**

**caches（7 个导出）、chat\_loaders/chat\_sessions、structured\_query、agents、utils、prompt\_values、document\_loaders……** 小林一个个扫过，大多数是"知道存在即可"。

他特别注意到两个"容易踩雷"的：

**agents（普通模块）——"历史的包袱。"** 里面是 `AgentAction`/`AgentStep`/`AgentFinish`。小林查了查，发现这是 **LangChain 0.x 时代 AgentExecutor 的数据结构**，现在他用 create\_agent（走 LangGraph）根本不碰。**"看到旧教程里 AgentExecutor/AgentAction 就明白是历史包袱。"**

**还有——根本没有 `structured_output` 模块！** 小林之前找过，翻遍整个包都没有。他查了查，明白了：**"结构化输出不是独立模块，是 `BaseChatModel.with_structured_output()` 方法 + output\_parsers 里的 Pydantic 系列实现的。"** 他差点因为这个跑去装不存在的包。

> 想验证"没有 structured\_output 模块"吗？试试 `from langchain_core.structured_output import ...`——直接 ImportError。结构化输出在 `BaseChatModel.with_structured_output()` 里。

## 第四幕：小林给 29 个模块排了"优先级"

拜访完所有模块，小林画了一张"最终地图"：

```text theme={null}
⭐ 必须掌握（天天用）：
   messages / prompts / language_models / embeddings / documents /
   retrievers / vectorstores / runnables / tools / output_parsers

✅ 进阶必知（生产才用）：
   callbacks（观测）/ exceptions（排错）/ chat_history（记忆对照）

💡 知道即可（课程用不上，但要知道为什么）：
   outputs / load / stores / caches / indexing / rate_limiters /
   example_selectors / cross_encoders / document_loaders /
   chat_loaders / chat_sessions / structured_query / prompt_values / utils / env

🗗 历史包袱（别学，认识就行）：
   agents（0.x 时代残留，create_agent 不用它）
```

他写下了一句总结，贴在工位上：

> **你 7 章学的"组件"（ChatModel/Document/Embeddings/VectorStore/Retriever/Memory/Tools/Agent）——抽象基类全在 langchain\_core；具体实现在各集成包（ChatAnthropic/Chroma/HuggingFaceEmbeddings）；编排在 langgraph。langchain\_core = 协议层，集成包 = 实现层，langgraph = 编排层。三层各司其职。**

> 想验证"三层各司其职"吗？`from langchain_core.language_models import BaseChatModel`（协议层）→ `from langchain_anthropic import ChatAnthropic`（实现层）→ `from langgraph.graph import StateGraph`（编排层）。三个 import，三层架构。

### 🔧 技术细节：langchain\_core 关键类签名速查（本章全景）

小林把"天天用"的模块里的**核心类签名**整理成了一张速查表（实测签名）：

**① messages——消息与工具结构**

```python theme={null}
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage, ToolMessage, ToolCall

BaseMessage(content, additional_kwargs, response_metadata, type, name, id)  # 基类 6 字段
AIMessage(..., tool_calls, invalid_tool_calls, usage_metadata)              # 加 3 个 = 9 字段
ToolCall(name: str, args: dict, id: str | None, type="tool_call")           # 统一工具调用
```

**② prompts——模板**

```python theme={null}
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate, MessagesPlaceholder

ChatPromptTemplate.from_messages(messages, template_format="f-string") -> ChatPromptTemplate
chat_prompt.invoke(input: dict, config=None) -> PromptValue    # .to_messages() → list[BaseMessage]
PromptTemplate.from_template(template: str, ...) -> PromptTemplate
MessagesPlaceholder(variable_name: str, optional=False, n_messages=None)
```

**③ language\_models——模型基类（最常用）**

```python theme={null}
from langchain_core.language_models import BaseChatModel

BaseChatModel.invoke(input) -> AIMessage
BaseChatModel.stream(input) -> Iterator[AIMessageChunk]
BaseChatModel.bind_tools(tools) -> self
BaseChatModel.with_structured_output(schema) -> Runnable
# ChatAnthropic / ChatDeepSeek / ChatOpenAI 都继承它
```

**④ output\_parsers / embeddings / documents / retrievers / vectorstores**

```python theme={null}
StrOutputParser().parse(text: str) -> str
Embeddings.embed_query(text: str) -> list[float]
Embeddings.embed_documents(texts: list[str]) -> list[list[float]]
Document(page_content: str, metadata: dict, id: str | None)
BaseRetriever.invoke(query: str) -> list[Document]
VectorStore.similarity_search(query, k=4) -> list[Document]
VectorStore.as_retriever(search_kwargs={"k": 3}) -> VectorStoreRetriever
```

**⑤ runnables——LCEL 引擎**

```python theme={null}
Runnable.invoke(input, config=None)      # 一切组件的统一调用入口
Runnable.stream(input)                   # 流式
a | b                                     # pipe：a 的输出接 b 的输入
RunnablePassthrough.assign(**kwargs)     # 输入 + 塞新键
RunnableLambda(func)                     # 普通函数 → Runnable
```

**⑥ tools / callbacks / exceptions**

```python theme={null}
@tool  # 函数 → BaseTool（自动推断 args schema）
BaseTool.invoke(input: str | dict | ToolCall) -> Any
BaseCallbackHandler.on_llm_start/on_llm_end/on_tool_start/...  # 生命周期监听
LangChainException    # 所有 LangChain 异常的父类（catch 它不漏）
```

> 想验证吗？`from langchain_core.language_models import BaseChatModel; isinstance(ChatAnthropic(...), BaseChatModel)` 返回 True——证明这些签名就是"统一插口"的物理定义。`help(ChatPromptTemplate.from_messages)` 能看到完整签名。

## 结论（小林用一天换来的）

**langchain\_core 是 LangChain 的协议层（地基）：29 个模块，5 大家族。** 你真正天天用的只有 10 个（messages/prompts/language\_models/embeddings/documents/retrievers/vectorstores/runnables/tools/output\_parsers），其余大多是"知道存在即可"——**用不上的原因是"你的场景没到那一步"**（生产要观测才用 callbacks、文档会更新才用 indexing、批量调用才用 rate\_limiters、RAG 进阶才用 cross\_encoders）。**没有 `structured_output` 模块**（结构化输出在方法里）。**agents 模块是 0.x 历史包袱。** 记住"协议层/实现层/编排层"三层架构，你就抓住了整个 LangChain 的骨架。

## 复现信号：什么时候你会想起这一章

1. **`from langchain_core.structured_output import ...` 报错**——没这个模块，用 `with_structured_output()`。
2. **`from langchain_core.agents import AgentExecutor` 报错**——agents 只有数据结构，AgentExecutor 是 langchain-classic 遗留。
3. **想给模型加"观测"**（token/耗时/日志）——写 `BaseCallbackHandler` 子类（callbacks 模块）。
4. **报错搞不清类型**——catch `LangChainException`（exceptions 模块的爹）。
5. **想知道"这个类是哪个包定义的"**——抽象在 langchain\_core，实现在集成包。

小林把整个"地基"翻完了。他觉得自己理论知识差不多了，但老王说："你学了一堆玩具（员工手册），能不能拿一份'真的'文件练练手？" 小林想起 data 目录里躺着两份真实的国家政策文件——十五五就业规划和十五五教育规划。他决定做一次"实战"：用真实文件，把学过的切块、向量化、检索全部走一遍——[翻到第 16 篇：给真实政策文件做问答](/doc/doc/narrative-course/17-十五五实战)。
