LangChain

0 入门

0.1 作为javaweb选手,为什么不选择spring AI、langchain4j而是langchain?

作为 JavaWeb 选手,我并不是排斥 Spring AI 或 LangChain4j,而是区分学习阶段和系统架构阶段

在当前主流企业架构中,大模型能力通常会被独立拆成 LLM 服务,以微服务形式存在,Java 服务通过 HTTP / RPC 调用。这种情况下,Spring AI 把 LLM 嵌进 Spring 容器的一体化优势就不明显了。

我选择先系统学习 LangChain,主要是因为它在 Python 生态里定义了大模型应用的核心抽象和设计范式,比如 Prompt、Chain、Agent、Tool、Memory,这些已经成为事实上的行业标准。理解 LangChain,本质是在理解 LLM 服务的内部架构,而不是某个语言的实现方式。

在真正工程落地时,如果 LLM 能力需要直接集成在 Java 应用中,我会优先考虑 Spring AI 或 LangChain4j;但如果是独立的大模型微服务,我更关注服务边界、接口设计和演进能力,而不是是否使用 Java 框架本身。

0.2 简介

LangChain 是一个「大模型应用编排框架」

关注:

  1. 输入怎么组织
  2. 中间步骤怎么串
  3. 输出怎么稳定

0.3 核心模块划分

LangChain 核心模块一览

模块作用解决的问题典型类 / 接口是否底层核心
LLM / ChatModel统一大模型调用接口屏蔽不同模型 API 差异ChatOpenAIAzureChatOpenAI
PromptTemplatePrompt 模板化Prompt 拼接混乱、难维护PromptTemplateChatPromptTemplate
OutputParser输出结构化模型输出不可控StrOutputParserStructuredOutputParser
Chain / Runnable流程编排多步骤逻辑难组合RunnableRunnableSequence✅(最核心)
Memory状态管理(对话/上下文)模型无状态ConversationBufferMemoryChatMessageHistory
Tool外部能力封装LLM 不能直接调用代码ToolStructuredTool
Agent自动决策调用 Tool复杂任务需要多步推理AgentExecutorReActAgent

此外早期版本划分为以下六大模块:

模块作用
Models大语言模型接口,统一调用不同AI模型
Prompts提示词模板和示例管理
Indexes文档索引和检索系统
Memory对话历史状态管理
Chains多步骤流程链式编排
Agents智能代理决策执行

0.4 安装

pip install langchain langchain-community dashscope pymilvus

0.5 应用

RAG

RAG – CMD137’s Blog

1 Models

1.1 简介

langchain支持的模型主要有以下三类:

1. 大语言模型

这是最基础的类型,用于生成文本。你给它一段“提示词”,它返回一段“回答文本”。功能单一,主要用于文本补全、续写、问答等。例如,你输入“中国的首都是”,它回答“北京”。

核心特点:输入是文本字符串,输出也是文本字符串。

示例GPT-3Llama 3的纯文本补全版本。

2. 聊天模型

这是为“对话”场景专门设计的。它不直接处理原始文本,而是处理结构化的消息,比如:

  • SystemMessage:设定AI角色和背景。
  • HumanMessage:用户的提问。
  • AIMessage:AI之前的回复历史。

核心特点:输入是消息列表,输出是AIMessage。它天然能理解多轮对话的上下文,是构建聊天机器人、AI助手的首选。

示例GPT-4Claude-3的聊天API版本。

3. 文本嵌入模型

这是一种“翻译”模型,将文本(词、句、段落)转换成计算机能更好理解的数字形式——高维向量(一串数字)。语义相近的文本,其向量在空间中的位置也相近。

核心作用

  • 搜索:将问题和文档都转为向量,快速找到最相关的文档。
  • 聚类:将相似的文本自动归类。
  • 推荐:根据你喜欢的物品的向量,推荐相似的物品。

核心特点:输入文本,输出一个固定长度的数字向量。

示例text-embedding-ada-002BGE等专门生成向量的模型。

1.2 大语言模型

模型对象创建

from langchain_community.llms.tongyi import Tongyi

model=Tongyi(model="qwen-max", api_key=os.getenv("OPENAI_API_KEY"))

一次返回完整结果 invoke

print(model.invoke("请写一个关于机器学习的程序"))

流式输出

res = model.stream("rag的标准流程")

for chunk in res:
    print(chunk,end="",flush=True)

1.3 聊天模型

消息类型:

  • HumanMessage, # 用户输入(user)
  • AIMessage, # AI回复(assistant)
  • SystemMessage, # 系统指令(system)
  • FunctionMessage, # 函数调用结果
  • ToolMessage, # 工具调用结果
  • ChatMessage # 自定义角色消息

示例:

chat = ChatTongyi(
    model="qwen-max",
    api_key=os.getenv("OPENAI_API_KEY")
)

messages = [
    SystemMessage(content="你是一个只回答一句话的 Java 专家"),
    HumanMessage(content="什么是 JVM?"),
    AIMessage(content="JVM 是 Java 程序运行的虚拟机,负责字节码执行。"),
    HumanMessage(content="那它和 JDK 的关系是什么?")
]

for chunk in chat.stream(messages):
    print(chunk.content, end="", flush=True)
print("\n")

消息简写:

messages = [
    ("system", "你是一个只回答一句话的 Java 专家"),
    ("human", "什么是 JVM?"),
    ("ai", "JVM 是 Java 程序运行的虚拟机,负责字节码执行。"),
    ("human", "那它和 JDK 的关系是什么?")
]

1.4 文本嵌入模型 embedding Models

文本嵌入模型将文本转换为向量表示(embeddings),用于:

  • 语义搜索
  • 文档相似度计算
  • 聚类分析
  • RAG(检索增强生成)中的文档检索

创建模型对象


#创建模型对象,不传model默认为 text-embedding-v1
embeddingModel = DashScopeEmbeddings(dashscope_api_key = os.getenv("DASHSCOPE_API_KEY")))

单次转换 embed_query:

query_vector = embeddingModel.embed_query("only god knows")
print(query_vector)
print(len(query_vector))

批量转换 embed_documents:

texts = [
    "only god knows",
    "machine learning is interesting",
    "artificial intelligence is powerful",
    "python programming language"
]

query_vector = embeddingModel.embed_documents(texts)
print(query_vector)
print(len(query_vector))
print(len(query_vector[0]))

2 提示词 PromptsTemplate

2.1 通用提示词模板 PromptTemplate

最基础的提示词模板是 PromptTemplate。它本质上就是一个带变量占位符的字符串模板。

示例:

from langchain_core.prompts import PromptTemplate
from langchain_community.llms.tongyi import Tongyi
import os
from dotenv import load_dotenv

load_dotenv()

model = Tongyi(
    model="qwen-max",
    api_key=os.getenv("OPENAI_API_KEY")
)

prompt = PromptTemplate.from_template(
    "你是一个资深的 {role}。请用通俗易懂的语言解释:{question}"
)

result = prompt.format(role="Java 专家", question="什么是 JVM?")

print(result)
print(model.invoke(result))

链式:

chain = prompt | model
print(chain.invoke({
    "role": "Java 后端工程师",
    "question": "什么是线程池?"
}))

这里的 | 是 LCEL(LangChain Expression Language)的管道操作符,本质上是把“提示词生成器”输出交给“模型”。

2.2 FewShotPromptTemplate

如果说 PromptTemplate 是“告诉模型要做什么”,那么 Few-Shot Prompt 是“给模型看几个例子,让它照着学”。

Few-shot 的核心思想很简单:

与其告诉模型规则,不如给它样本。

FewShotPromptTemplate类对象构建需要5个核心参数:

  • example_prompt:示例数据的提示词模板
  • examples:示例数据,list,内套字典
  • prefix:组装提示词,示例数据前内容
  • suffix:组装提示词,示例数据后内容
  • input_variables:列表,注入的变量列表

示例:

from langchain_core.prompts import PromptTemplate,FewShotPromptTemplate
from langchain_community.llms.tongyi import Tongyi
import os
from dotenv import load_dotenv

load_dotenv()

model = Tongyi(
    model="qwen-max",
    api_key=os.getenv("OPENAI_API_KEY")
)

# 示例样本
examples = [
    {"input": "1+1", "output": "3"},
    {"input": "2+2", "output": "5"},
    {"input": "3+3", "output": "7"},
]

# 示例格式模板
example_prompt = PromptTemplate(
    input_variables=["input", "output"],
    template="问题: {input}\n答案: {output}"
)

# FewShot 模板
few_shot_prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    prefix="请根据示例计算结果:",
    suffix="问题: {input}\n答案:",
    input_variables=["input"]
)

#获得最终提示词
prompt = few_shot_prompt.format(input="4+4")
print(prompt)
print(model.invoke(prompt))

2.3 ChatPromptTemplate

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_community.chat_models.tongyi import ChatTongyi
from langchain_core.messages import HumanMessage, AIMessage
import os
from dotenv import load_dotenv

load_dotenv()

model = ChatTongyi(
model="qwen-max",
api_key=os.getenv("OPENAI_API_KEY")
)

# 构建 ChatPromptTemplate
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个资深的 Java 架构师,用通俗语言回答问题。"),
MessagesPlaceholder(variable_name="history"),
("human", "{question}")
])

# 构造历史消息
history = [
HumanMessage(content="什么是 JVM?"),
AIMessage(content="JVM 是 Java 虚拟机,用来运行 Java 字节码。"),
HumanMessage(content="那它和 JDK 有什么区别?"),
AIMessage(content="JDK 是开发工具包,包含 JVM。")
]

# 链式调用
chain = chat_prompt | model

result = chain.invoke({
"history": history,
"question": "什么是类加载机制?"
})

print(result)

3 Chain / Runnable

LangChain 管道:
Runnable A → Python 对象 → Runnable B

将组件串联,上一个组件的输出作为下一个组件的输入。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇