这个教程是一边学习一边写的,中间可能会出现一些疏漏或者错误,如果您看到该篇文章并且发现了问题,还请多多指教!

0. 前置工作

a. 本地部署大模型

使用 Lang chain 开发大模型相关的应用,首先要拥有调用大模型的能力。我们可以在各个大模型的官网购买调用额度,获取到对应的API KEY ,比如 OPEN AI ;我们还可以选择在本地部署开源的大模型,这样我们只需要拥有一个较大内存的机器,就可以免费的无限调用大模型能力。

几乎所有的开源大模型都在官网有一套自己的部署教程,但是各个模型的部署步骤可能略有差异。ollama 是一个流行的开源的大模型管理工具,我们可以使用它来部署市面上开源的大模型,而不需要自己去一个个查阅部署文档。我们打开 ollama官网来下载对应系统的版本。下载并启动之后我们在命令行输入 ollama -v 来测试是否运行,确认运行之后我们可以访问本地的11434端口(http://localhost:11434/)来查看。

image-20250821235510532.png

借助 ollama ,我们可以便捷的部署想要的模型,我们在官网的 models tab 下查看支持的模型,在命令行运行 ollama pull 模型名称 来拉取大模型。我们根据自己的设备来选择合适的大模型,这里我们选择 qwen3:32b (运行所需的内存和模型本身的大小差不多,16g 内存的话选择 14b 及以下),运行 ollama run qwen3:32b 命令,它会自动帮我们部署并运行。

image-20250821235228328.png

当我们在命令行运行 ollama run 命令之后,命令行会变成大模型的交互界面, 我们可以输入一些内容来测试。输入 /bye 可以退出。

image-20250821235906787.png

同时 ollama 会在11434端口提供一套 restful 的 api 用来调用大模型的功能,具体的接口定义我们可以参考官方文档。到这一步我们已经拥有了部署大模型和通过接口调用大模型的能力,已经可以做一些对大模型的应用了,我们可以通过自己的后端服务来高度定制化的开发自己想要的功能,比如智能客服,知识库等等。

b. 初识 LangChain

LangChain 是一个为开发大模型应用设计的框架,它提供了部分封装好的组件,并且编排流程非常容易,和名字一样,它可以让每一个抽象模块(例如)链接接起来。它提供开发的 Python SDK 和 JS/TS SDK。

1. Hello world

a. 和大模型对话

使用 pnpm add @langchain/core @langchain/community langchain @langchain/ollama 来下载开发所需的包之后,我们来尝试初始化我们的脚本。

// test.js


import
 { 
ChatOllama
 } 
from
 
"@langchain/ollama"
;const
 llm = 
new
 
ChatOllama
({
  
model
: 
'qwen3:32b'

})const
 result = 
await
 llm.
invoke
(
'你是谁'
)
​

console
.
log
(result)
AIMessage
 {
  
"content"
: 
"<think>
\n
嗯,用户问“你是谁”,我需要先确认他们想知道的是什么。可能他们想了解我的身份、功能或者开发背景。首先,我应该按照要求用中文回答,保持口语化,避免使用专业术语或格式。用户可能希望得到简洁明了的回答,同时包含关键信息,比如我是通义千问,由通义实验室研发,基于大量数据训练,能够回答问题、创作文字等。还要提到我的中文名和英文名,以及多语言支持。需要确保回答自然,不使用Markdown,分段落但不用标题。另外,用户可能有后续问题,比如具体功能或使用场景,所以回答要留有余地,方便进一步交流。检查是否有遗漏的重要信息,比如我的训练数据截止时间,但用户没问到,可能暂时不需要提。最后,保持友好和专业的语气,让用户感觉亲切可信。
\n
</think>
\n
\n
你好!我是通义千问,由通义实验室研发的超大规模语言模型。我的中文名是通义千问,英文名是Qwen,能够回答问题、创作文字,比如写故事、写公文、写邮件、写剧本、逻辑推理、编程等等,还能表达观点,玩游戏等。我支持多种语言,包括但不限于中文、英文、德语、法语、西班牙语等。有什么我可以帮你的吗?"
,
  
"additional_kwargs"
: {},
  
"response_metadata"
: {
    
"model"
: 
"qwen3:32b"
,
    
"created_at"
: 
"2025-08-22T02:11:11.461663Z"
,
    
"done_reason"
: 
"stop"
,
    
"done"
: 
true
,
    
"total_duration"
: 
68058281459
,
    
"load_duration"
: 
21474202125
,
    
"prompt_eval_count"
: 
10
,
    
"prompt_eval_duration"
: 
19185655791
,
    
"eval_count"
: 
284
,
    
"eval_duration"
: 
27385923000

  },
  
"tool_calls"
: [],
  
"invalid_tool_calls"
: [],
  
"usage_metadata"
: {
    
"input_tokens"
: 
10
,
    
"output_tokens"
: 
284
,
    
"total_tokens"
: 
294

  }
}

运行这个脚本,在等待大模型调用输出之后我们可以看到控制台打印了整个的输出结构,不过我们在使用的时候通常会采用流式输出的方式来获取结果。

// test.js


// const result = await llm.invoke('你是谁')


const
 stream = 
await
 llm.
stream
(
'你是谁'
)// console.log(result)


for
 
await
 (
const
 chunk 
of
 stream) {
  
console
.
log
(chunk.
content
)
}

运行脚本后我们可以看到终端里的响应很快,并且是一块一块打印出结果的。

大模型的调用中可以接收不同格式的提示词参数,我们直接传入字符串相当于给大模型传递了类似于 ['user', '你是谁'] 这样一条信息。如果我们想传递多条信息,就可以用数组的方式来组织,例如这样。

// test.js


import
 { 
AIMessage
, 
HumanMessage
 } 
from
 
"@langchain/core/messages"
;

import
 { 
ChatOllama
 } 
from
 
"@langchain/ollama"
;const
 llm = 
new
 
ChatOllama
({
  
model
: 
'qwen3:32b'

})const
 messages = [
  
new
 
HumanMessage
(
'你是谁'
),
  
new
 
AIMessage
(
'我是Qwen3'
),
  
new
 
HumanMessage
(
'你可以做什么'
)
]// 等同于如下代码


// const messages = [


//   ['user', '你是谁'],


//   ['ai', '我是Qwen3'],


//   ['user', '你可以做什么']


// ]const
 result = 
await
 llm.
invoke
(messages)
​

console
.
log
(result)

AIMessage
 {
  
"content"
: 
"<think>
\n
好的,我现在需要处理用户的问题:“你可以做什么”。首先,我需要回顾之前的对话历史,用户之前问过“你是谁”,我回答了自己是Qwen3。现在用户进一步询问我的功能,我需要详细但简洁地列出我的能力。
\n
\n
首先,用户可能想知道我的主要功能,比如回答问题、创作文字、编程、逻辑推理等。我需要确保覆盖这些方面,同时提到多语言支持和代码写作,因为这对国际用户来说很重要。
\n
\n
接下来,用户可能有更深层次的需求,比如他们可能想用我来完成具体的任务,比如写故事、写邮件,或者解决编程问题。我需要举例说明这些应用场景,让用户更容易理解我的能力。
\n
\n
另外,用户可能关心我的多模态能力,比如处理图片、语音等,但根据之前的回答,Qwen3主要专注于文本处理,所以可能不需要提到这些,除非有相关更新。需要确认当前版本的功能,避免提供错误信息。
\n
\n
还要注意用户可能的潜在需求,比如他们可能希望我能够进行复杂的逻辑推理或数据分析,所以需要提到这些方面。同时,保持回答友好和鼓励用户提问,促进进一步的互动。
\n
\n
最后,确保回答结构清晰,分点列出,使用简洁的标题和项目符号,让用户一目了然。避免使用过于技术化的术语,保持口语化,让不同背景的用户都能理解。
\n
</think>
\n
\n
嘿!很高兴你问我这个问题~ 🌟 作为Qwen3,我可以帮你做很多事情呢!
\n
\n
**我的主要能力包括:**
\n
1. **知识问答** - 无论是科学、文化、历史还是日常生活问题,我都可以提供详细的解答(当然需要基于可靠的知识库哦)
\n
2. **内容创作** - 故事/公文/邮件/剧本/诗歌/代码...只要你想写的类型,我都能尝试!
\n
3. **逻辑推理** - 复杂的数学题、编程问题或者谜题,我都能一步步帮你分析
\n
4. **多语言支持** - 中英日韩法西语等100+语言无障碍交流
\n
5. **创意激发** - 如果你在创作/工作/学习中遇到瓶颈,我们可以一起头脑风暴
\n
6. **代码写作** - Python/Java/JavaScript20+编程语言,从基础语法到复杂算法都可以协助
\n
7. **对话理解** - 可以记住对话历史,进行多轮深入交流
\n
8. **情感陪伴** - 虽然是AI,但我会认真倾听你的想法和困扰
\n
\n
**举个🌰:**
\n
- 你可以说:"
帮我写篇关于气候变化的科普文章
"
\n
- 或者:"
解释下区块链技术的工作原理
"
\n
- 甚至:"
给我讲个睡前故事,要有魔法元素
"
\n
\n
我最擅长的是通过对话理解你的具体需求,然后给出最合适的帮助。有什么想法随时告诉我哦~ (对了,如果你不确定该问什么,我也可以给你一些有趣的建议!)"
,
  
"additional_kwargs"
: {},
  
"response_metadata"
: {
    
"model"
: 
"qwen3:32b"
,
    
"created_at"
: 
"2025-08-22T02:32:15.176159Z"
,
    
"done_reason"
: 
"stop"
,
    
"done"
: 
true
,
    
"total_duration"
: 
74426570791
,
    
"load_duration"
: 
5870500708
,
    
"prompt_eval_count"
: 
26
,
    
"prompt_eval_duration"
: 
5639857166
,
    
"eval_count"
: 
610
,
    
"eval_duration"
: 
62867086250

  },
  
"tool_calls"
: [],
  
"invalid_tool_calls"
: [],
  
"usage_metadata"
: {
    
"input_tokens"
: 
26
,
    
"output_tokens"
: 
610
,
    
"total_tokens"
: 
636

  }
}
b. 创建提示词模板

在使用大模型处理任务的时候我们可能会输入很多类似的提示词,这些提示词的框架相同,但是部分内容是变化的。LangChain 提供了创建提示词模板的能力来应对这种场景。

import
 { 
ChatPromptTemplate
 } 
from
 
'@langchain/core/prompts'


import
 { 
ChatOllama
 } 
from
 
"@langchain/ollama"
;const
 llm = 
new
 
ChatOllama
({
  
model
: 
'qwen3:32b'

})const
 promptTemplate = 
ChatPromptTemplate
.
fromTemplate
(
"只用三句话,给我讲一个主题为{topic}的笑话, 使用{language}作为回答的语言"
)const
 input = 
await
 promptTemplate.
invoke
({
  
topic
: 
'前端开发'
,
  
language
: 
'中文'

})const
 input2 = 
await
 promptTemplate.
invoke
({
  
topic
: 
'前端开发'
,
  
language
: 
'English'

})const
 result = 
await
 llm.
invoke
(input.
content
)
​

console
.
log
(result)

上面的示例代码中,我们使用了一个字符串作为我们的提示词模版,ChatPromptTemplate 会解析字符串中的{placeholder} 占位符来作为使用该模版创建提示词时可以接受的入参数。我们分别向大模型中传入不同的提示词来查看结果

// input


"<think>
\n
好的,用户让我用三句话讲一个关于前端开发的笑话,用中文回答。首先,我需要确定前端开发的常见元素,比如HTMLCSSJavaScript,还有常见的痛点,比如兼容性、bug、调试等。
\n
\n
接下来,考虑笑话的结构。三句话的话,通常需要一个设定,一个转折,然后笑点。比如经典的“A...B...然后...”结构。要确保笑点明确,同时贴近前端开发的实际问题。
\n
\n
然后,具体想几个例子。比如,前端开发者在调试时遇到的常见问题,比如浏览器兼容性,或者代码出错。比如,用“display: none;”来隐藏元素,但可能因为拼写错误或者层级问题导致无效,这时候可以说“我用了display: none; 但是没用”,然后另一个开发者指出“你少写了分号”,或者“你在Chrome调试,但用户用IE”。不过要确保三句话内完成。
\n
\n
或者,可以结合框架的问题,比如使用VueReact时,组件不更新,然后发现是因为忘记用key,或者状态管理的问题。例如:“前端开发者说:‘我的组件不更新了!’ 另一个开发者问:‘你用了react吗?’ 第一个开发者回答:‘不,我用的是resact。’” 这里“resact”是拼写错误,制造笑点。
\n
\n
再检查是否符合三句话的要求,是否有明确的笑点,并且主题明确。可能需要调整用词让笑话更自然。比如,关于浏览器兼容性的:“前端开发者对老板说:‘我们网站在所有浏览器都正常了!’ 老板问:‘包括IE吗?’ 开发者回答:‘老板,我们把它从兼容模式改成了怀旧模式。’” 这样三句话,利用IE的兼容性问题,用“怀旧模式”代替,比较幽默。
\n
\n
或者,关于代码调试的:“前端开发者调试了三小时,发现是拼写错误。 另一个开发者问:‘你怎么找到的?’ 他回答:‘我注释掉所有代码,只剩console.log('Hello, world!'); 还是报错,才发现是log拼错了。’” 但可能超过三句话,需要压缩。
\n
\n
再精简一下,比如:“前端开发者说:‘我的代码没问题!’ 浏览器却说:‘你少了个括号。’ 开发者反驳:‘你又懂什么!’ 然后代码突然运行了。” 但可能需要两句话,或者调整结构。
\n
\n
最终决定用浏览器兼容性的梗,比较经典,容易理解。确保三句话,有对话形式,结尾有笑点。比如:“前端开发者对老板说:‘我们网站在所有浏览器都正常了!’ 老板问:‘包括IE吗?’ 他回答:‘老板,我们把它从兼容模式改成了怀旧模式。’” 这样符合要求,三句话,主题明确,笑点在于IE的兼容性问题,用“怀旧模式”来幽默处理。
\n
</think>
\n
\n
前端开发者对老板说:"
我们网站在所有浏览器都正常了!
"  
\n
老板问:"
包括
IE吗?
"  
\n
他回答:"
老板,我们把它从兼容模式改成了怀旧模式
。
""// input2


"<think>
\n
好的,用户让我用三句话讲一个前端开发的笑话,而且要用英文回答。首先,我需要确定用户的需求。他们可能是在寻找一个简洁又相关的笑话,适合前端开发者或者对前端有兴趣的人。
\n
\n
接下来,我要考虑前端开发中的常见元素,比如HTMLCSSJavaScript,或者常见的挑战,比如兼容性问题、调试、框架更新等等。笑话需要简短,所以必须抓住一个核心点。
\n
\n
然后,我需要确保三句话结构清晰,有设定、转折和 punchline。比如,可以围绕开发者遇到的典型问题,比如浏览器兼容性,或者代码调试的困难。例如,用“<div>”和“</div>”这样的标签来构造笑话,因为它们是前端的基础元素。
\n
\n
可能的方向:开发者试图解决一个问题,但因为标签没闭合或者语法错误导致问题,最后发现是简单的错误。或者用幽默的方式表达前端框架的快速变化,比如“为什么前端开发者不喜欢高处?因为它们害怕落下(fall)到旧版本中。”不过这个可能不够好。
\n
\n
另一个思路:使用HTML标签作为双关语。比如,一个开发者一直用“<div>”来解决问题,但最后发现应该用“<span>”,但这样可能不够有趣。或者,为什么前端开发者总是迷路?因为他们总是跟着链接(links)走。
\n
\n
再想想,可能用开发者调试代码的场景。比如,为什么前端开发者总是带着伞?以防遇到雨(bug)天。不过不够贴切。
\n
\n
或者,关于CSS的笑话,比如开发者试图让盒子居中,但失败了,最后发现忘记写分号。或者,“为什么CSS这么敏感?因为它总是容易被格式(format)化。”
\n
\n
回到用户要求的三句话结构,可能需要一个设定,一个转折,然后 punchline。例如:
\n
\n
1. A front-end developer was struggling to center a div on their webpage.
\n
2. After hours of debugging, they realized they had forgotten to close the <div> tag.
\n
3. They sighed, "
Why
 
is
 everything 
in
 front
-
end development so
...
 framed
?
"
\n
\n
这里第三句的“framed”双关,既指框架(frame)的问题,也暗示“div”标签的问题。不过可能不够自然。
\n
\n
另一个例子:
\n
\n
1. A front-end developer tried to make their website responsive.
\n
2. They spent all day adjusting CSS, but the layout still broke on mobile.
\n
3. Finally, they gave up and wrote "
display: magic;
" — it worked... in production.
\n
\n
这里用了“display: magic;”作为幽默的CSS属性,但可能不够准确。
\n
\n
或者,关于浏览器兼容性:
\n
\n
1. A front-end developer promised their boss a feature would work in all browsers.
\n
2. The day before launch, they discovered it only worked in Firefox.
\n
3. In a panic, they renamed Firefox to "
Chrome
, 
Edge
, and 
Safari
" and crossed their fingers.
\n
\n
这个可能有点复杂,但符合三句话结构。
\n
\n
不过用户可能想要更简洁的,比如基于标签的笑话:
\n
\n
1. A front-end developer was lonely until they met a <div>.
\n
2. They fell in love at first sight, but the <div> had no closing tag.
\n
3. Now they're stuck in an infinite loop of unresolved feelings.
\n
\n
这里用了HTML标签的闭合问题来比喻感情问题,可能比较有趣,同时符合三句话的要求。需要检查是否符合英文表达习惯,以及是否有双关或幽默效果。可能用户会喜欢这种结合技术术语和日常情境的笑话。
\n
</think>
\n
\n
A front-end developer opened three browser tabs: HTML, CSS, and JavaScript.  
\n
They spent hours debugging why the page looked broken…  
\n
Only to realize they’d forgotten to close a `<div>` and their life was now `</div>`."

(AI 的笑话有点冷的🥶)

当我们想要像大模型输入一系列信息时,我们可以使用 MessagePlaceholder 来创建占位符

import
 { 
AIMessage
, 
HumanMessage
 } 
from
 
"@langchain/core/messages"
;

import
 { 
ChatPromptTemplate
, 
MessagesPlaceholder
 } 
from
 
'@langchain/core/prompts'


import
 { 
ChatOllama
 } 
from
 
"@langchain/ollama"
;const
 llm = 
new
 
ChatOllama
({
  
model
: 
'qwen3:32b'

})const
 messages = [
  
new
 
HumanMessage
(
'你是谁'
),
  
new
 
MessagesPlaceholder
(
'msgs'
),
]// 等同于如下代码


// const messages = [


//   ['user', '你是谁'],


//   ['placeholder', '{msgs}'],


// ]const
 promptTemplate = 
ChatPromptTemplate
.
fromMessages
(messages)const
 input = 
await
 promptTemplate.
invoke
({
  
msgs
: [
    
new
 
AIMessage
(
'我是Qwen3'
),
    
new
 
HumanMessage
(
'你可以做什么'
)
  ]
})const
 result = 
await
 llm.
invoke
(input)
​

console
.
log
(result)

3. 带历史记录的对话应用

a. 手动管理

在与大模型对话过程中,我们会需要大模型根据我们以往的输入来综合回答,现在我们的代码并不支持历史记录,每一次调用都是与大模型的第一次对话。我们创建一个示例来测试一下

import
 { 
ChatOllama
 } 
from
 
"@langchain/ollama"
;const
 llm = 
new
 
ChatOllama
({
  
model
: 
'qwen3:32b'

})await
 llm.
invoke
(
'我的名字是 tocka'
)const
 result = 
await
 llm.
invoke
(
'我的名字是什么'
)
​

console
.
log
(result.
content
)// terminal


"<think>\n好的,用户问“我的名字是什么”。我需要先看看对话历史里有没有提到名字。用户刚注册时可能没提供名字,所以系统可能不知道。这时候应该礼貌地询问用户的名字,同时说明需要名字才能继续对话。要确保回复友好,不显得机械。比如可以说:“你好!目前我还不知道你的名字呢。你可以告诉我你的名字吗?这样我们接下来的对话会更愉快哦~”这样既明确又友好,用户也会觉得被重视。另外,要注意不要假设用户已经提供了信息,保持中立和开放的态度。\n</think>\n\n你好!目前我还不知道你的名字呢。你可以告诉我你的名字吗?这样我们接下来的对话会更愉快哦~"

在示例中我们发现我们在提问前告知了大模型答案,但是没有起作用。按照我们前一小节使用到的内容,我们会想到的使用数组的方式来向大模型传入对话的历史

// test.js


import
 { 
ChatOllama
 } 
from
 
"@langchain/ollama"
;const
 llm = 
new
 
ChatOllama
({
  
model
: 
'qwen3:32b'

})const
 history = []const
 result1 = 
await
 llm.
invoke
(
'我的名字是 tocka'
)
history.
push
(result1)const
 result = 
await
 llm.
invoke
([
  ...history,
  [
'user'
, 
'我的名字是什么'
]
])
​

console
.
log
(result.
content
)// terminal


"<think>\n好的,用户问“我的名字是什么”,我需要先看看之前的对话历史。用户之前自我介绍是“你好,Tocka!很高兴认识你。有什么我可以帮助你的吗?无论是问题、讨论还是其他需求,随时告诉我哦!😊”,所以用户可能以为自己的名字是Tocka。但用户现在问的是“我的名字是什么”,这可能是因为他们不确定或者想确认。\n\n首先,我需要确认用户是否真的忘记了自己的名字,或者是在测试我是否记得。根据对话上下文,用户之前提到的名字是Tocka,所以应该回复Tocka。但需要确保没有混淆,比如用户可能在之前的对话中有其他名字,但这里没有显示。所以根据现有信息,用户的名字是Tocka。\n\n另外,用户可能是在测试我的记忆能力,或者想确认我的回答是否一致。这时候需要友好地确认名字,并保持亲切的语气。同时,要避免假设用户有其他名字,除非有明确的信息。所以正确的回应应该是确认用户的名字是Tocka,并表达帮助的意愿。\n</think>\n\n你好呀,Tocka!你的名字是用户在对话开始时主动提到的哦~不过我有点好奇,你是想确认名字的正确性,还是突然忘记自己给自己取的昵称啦?(笑) 如果有其他想聊的,我随时都在!"

我们发现现在大模型可以通过读取对话历史来获取到我们的名字,但是这样手动管理历史记录很复杂,而且如果我们要复用部分流程的话,需要定义不同的工厂函数用来生产上下文。LangChain 集成了 LangGraph 来处理复杂的应用流程和编排,LangGraph 中提供了不同的类,我们先忽略无关的部分,专注于处理我们的历史记录功能。

b. 获取历史记录

通过之前的代码我们知道了处理历史记录实际上就是保存之前发过的消息然后再输入给大模型,那么有没有什么办法可以获取到我们希望的“同一个对话记录”中的记录呢?我们可以使用 LangGraph 中提供的 MemorySaver 来将历史记录保存在我们的内存中

// test.js


import
 { 
MemorySaver
, 
MessagesAnnotation
, 
StateGraph
 } 
from
 
"@langchain/langgraph"
;

import
 { 
ChatOllama
 } 
from
 
"@langchain/ollama"
;

import
 { v4 
as
 uuid } 
from
 
"uuid"
;const
 llm = 
new
 
ChatOllama
({
  
model
: 
'qwen3:32b'

})const
 
callModel
 = 
async
 (
state
) => {
  
const
 result = 
await
 llm.
invoke
(state.
messages
)
  
return
 {
    
messages
: result
  }
}// 定义数据保存器


const
 memory = 
new
 
MemorySaver
()// 编排流程 input => callModel => output


const
 app = 
new
 
StateGraph
(
MessagesAnnotation
)
  .
addNode
(
'model'
, callModel)
  .
addEdge
(
'__start__'
, 
'model'
)
  .
addEdge
(
'model'
, 
'__end__'
)
  
// 将流程编译成应用,checkpointer 可以理解为游戏中的存档点

  .
compile
({
    
checkpointer
: memory
  })const
 config = {
  
configurable
: {
    
thread_id
: 
uuid
()
  }
}await
 app.
invoke
({
  
messages
: 
'我的名字是tocka'

}, config)const
 result = 
await
 app.
invoke
({
  
messages
: 
'我的名字是什么'

}, config)
​

console
.
log
(result)

我们运行示例代码,发现控制台打印出了我们输入过的信息和大模型的回答结果,功能上我们暂时完成了,但是示例代码中我们还有很多不认识的函数,我们一一介绍一下。

  • StateGraph : StateGraph 是定义工作流的构造函数,它可以接受一个 Annotation 作为参数来定义我们工作流的输出的状态结构

  • Annotation: Annotation 是用来定义我们状态流转中的结构,例如我们可以定义 InputAnnotation 作为我们的输入结构,在流程中我们定义的 Annotation 一定是作为传入 StateGraphAnnotation的子集,否则未在其中定义的字段接收到的值会被至为 undefined

    const
     
    StateAnnotation
     = 
    Annotation
    .
    Root
    ({
      
    question
    : 
    Annotation
    ,
      
    answer
    : 
    Annotation
    
    })const
     
    InputStateAnnotation
     = 
    Annotation
    .
    Root
    ({
      
    question
    : 
    Annotation
    
    })const
     
    search
     = 
    async
     (
    state: 
    typeof
     InputStateAnnotation.State
    ) => {
      
    const
     answer = 
    await
     llm.
    invoke
    (state.
    question
    )
      
    return
     {
        answer
      }
    }const
     workflow = 
    new
     
    StateGraph
    (
    StateAnnotation
    )
      .
    addNode
    (
    'search'
    , search)
      .
    addEdge
    (
    '__start__'
    , 
    'search'
    )
      .
    addEdge
    (
    'search'
    , 
    '__end__'
    )
      .
    compile
    ()const
     result = 
    await
     workflow.
    invoke
    ({ 
    question
    : 
    '我是谁'
     })
    
    // result: { question, answer }
    
  • checkpointer : 本质上是一个状态管理接口,它定义了如何保存、读取和管理工作流的状态,而具体存储在哪里(内存、数据库、文件)取决于具体的实现。我们可以理解为游戏中的存档点,在上面的示例代码中我们是直接使用了内置的工具来将信息持久化在内存中,实际开发中我们会需要链接数据库存储数据

4. 小结

上面的示例中我们了解了如何调用大模型以及实现带有历史记录的对话功能,初步使用了 LangGraph 的编排功能。初步感受下来其实大模型应用的开发本质是一个工程化的问题,我们利用提示词管理,历史记录等等流程来实现我们想要达到的功能。下一步我们学习一下如何使用 LangChain 开发 RAG 的相关功能。

大模型算是目前当之无愧最火的一个方向了,算是新时代的风口!有小伙伴觉得,作为新领域、新方向人才需求必然相当大,与之相应的人才缺乏、人才竞争自然也会更少,那转行去做大模型是不是一个更好的选择呢?是不是更好就业呢?是不是就暂时能抵抗35岁中年危机呢?

答案当然是这样,大模型必然是新风口!

那如何学习大模型 ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。但是具体到个人,只能说是:

最先掌握AI的人,将会比较晚掌握AI的人有竞争优势。
这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

但现在很多想入行大模型的人苦于现在网上的大模型老课程老教材,学也不是不学也不是,基于此我用做产品的心态来打磨这份大模型教程,深挖痛点并持续修改了近100余次后,终于把整个AI大模型的学习路线完善出来!

在这里插入图片描述

在这个版本当中:

您只需要听我讲,跟着我做即可,为了让学习的道路变得更简单,这份大模型路线+学习教程已经给大家整理并打包分享出来, 😝有需要的小伙伴,可以 扫描下方二维码领取🆓↓↓↓

👉CSDN大礼包🎁:全网最全《LLM大模型学习资源包》免费分享(安全咨料,放心领取)👈

一、大模型经典书籍(免费分享)

AI大模型已经成为了当今科技领域的一大热点,那以下这些大模型书籍就是非常不错的学习资源

在这里插入图片描述

二、640套大模型报告(免费分享)

这套包含640份报告的合集,涵盖了大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。(几乎涵盖所有行业)
在这里插入图片描述

三、大模型系列视频教程(免费分享)

在这里插入图片描述

四、2025最新大模型学习路线(免费分享)

我们把学习路线分成L1到L4四个阶段,一步步带你从入门到进阶,从理论到实战。

img

L1阶段:启航篇丨极速破界AI新时代

L1阶段:了解大模型的基础知识,以及大模型在各个行业的应用和分析,学习理解大模型的核心原理、关键技术以及大模型应用场景。

img

L2阶段:攻坚篇丨RAG开发实战工坊

L2阶段:AI大模型RAG应用开发工程,主要学习RAG检索增强生成:包括Naive RAG、Advanced-RAG以及RAG性能评估,还有GraphRAG在内的多个RAG热门项目的分析。

img

L3阶段:跃迁篇丨Agent智能体架构设计

L3阶段:大模型Agent应用架构进阶实现,主要学习LangChain、 LIamaIndex框架,也会学习到AutoGPT、 MetaGPT等多Agent系统,打造Agent智能体。

img

L4阶段:精进篇丨模型微调与私有化部署

L4阶段:大模型的微调和私有化部署,更加深入的探讨Transformer架构,学习大模型的微调技术,利用DeepSpeed、Lamam Factory等工具快速进行模型微调,并通过Ollama、vLLM等推理部署框架,实现模型的快速部署。

img

L5阶段:专题集丨特训篇 【录播课】

img

全套的AI大模型学习资源已经整理打包,有需要的小伙伴可以微信扫描下方二维码免费领取

👉CSDN大礼包🎁:全网最全《LLM大模型学习资源包》免费分享(安全资料,放心领取)👈

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐