Ai大模型应用开发工程师 -- 学习记录
大模型原理
ai 生成答案其实是通过前面上下文推算后面一个字的概率,但是 ai 是需要通过大量的学习和计算才能拟合出这个概率公式,所以这就涉及到很多东西了,这些数据信息该如何存储,ai 如何识别这些数据集,如何计算概率等等。
人类理解中的对象或者认知是一种很复杂,并且多元化的信息,我们在存储时,现在常用的方法就是将信息向量化或者归一化,例如:人可以有很多信息,年龄,身高,体重,爱好,技能等等,我们可以将这些信息存储起来,当然很多信息其实是没有用的,我们需要进行信息压缩和特征提取,这样在模式识别里我们就可以通过这些信息去确认是哪个人,文字我们其实可以用数字表示,所以任何事物我们都可以使用数字的方式表示存储,这样方便计算。
当特征都被数字表示时,我们可以想象一个多维向量空间,当物体所有的特征都能在空间里表示时,就唯一确定了空间中的位置,而且数字也运算,我们可以想成从特征集合里拿掉或者添加特征,这样就成为了另外一个东西了,而对比正确的答案,我们就知道了差距,通过损失函数我们就能拟合出正确答案,所以这也是ai需要训练的理由。
谷歌公司提出了一种注意力机制,也就是 transformer 架构,用来解决 cnn(循环神经网络)不能考虑上下文,后面也衍生出了 rnn(卷积神经网络),这个算法是用来特征提取的,一开始使用在翻译器和图片上面,gpt 使用的就是翻译器的解码器。
编码器的发展历程
首先是独热编码模式,存储每个(单词)对象向量信息时,我们把所有的维度特征都存储一个值给该对象向量,这样就能让计算机一下子就知道该对象是什么东西,但是这个东西非常的耗费空间资源,而且每个对象向量之间没有联系。
之后就出现了 word2vec 方式,这个方式通过将对象向量乘上一个矩阵,这样就可以获得一个维度更小的向量,本质其实就是行列式的乘法特性导致,而且计算过后的这个向量产生了和其他向量的关联。
但是上面也就还有一个问题,就是多义词的问题,所以升级到了 ELMo 模型,是基于上下文的 Embedding ,所有就有了预训练的任务。
编码器和解码器的执行流程
机器学习就是一个 y=wx+c 函数执行过程,激活函数其实就是对这个函数的放大,缩小,平移的变换,作用就是去拟合更多的使用场景。可以看到解码器有两层多头注意力计算,第一层和编码器一样,但是第二层则是使用了交叉注意力机制的方式。编码器和解码器是一个训练的过程,不是推理的过程。Norm 是归一化计算,作用是将结果转变为0-1之间的概率数。Add 是一个优化的计算方式,在机器学习的过程中,有可能系数本身很小,这样在梯度下降的计算下,可能导致变量 x 为0,所以在计算标准化后需要加上一个变量 x 优化一下。

自注意力机制
在 Transformer 模型中摒弃了循环和卷积操作,注意力机制是核心组成部分,而在自注意力机制(Self-Attention)中,单头注意力(Single-head Attention)和多头注意力(Multi-head Attention)是两种重要的注意力计算方式。它们虽然在本质上都属于注意力机制,但在计算方式、能力表现和应用场景上有显著的差异。
单头注意力: 通过生成查询、键和值向量,计算并归一化注意力分数,最终对值向量进行加权求和,从而得到输入序列中每个位置的加权表示。

在线大模型开发
Completion api 注重文字补全功能,Chat Completion api 注重对话,更符合人类思维模式。
要使用 OpenAI 的api接口的话,需要去官网下载依赖包,但是官网是在外网的,而且使用接口有识别鉴权的限制,所以需要使用 VPN 才可以调试,所以这里就只介绍参数和函数等,官网也有使用的教学。
创建对话时,最重要的有两个参数,messages 和 model ,前者是我们提出的对话内容,后者是需要计算的模型名字。messages 是一个对象列表,每个对象里面有 role 和 content 属性,content 是用户提出对话的字符串,而 role 则是指定该消息的作用目标,有三个角色 assistant,user,system,user 角色指代我们用户,模型针对用户的对话作出回答;system 则是指代模型本身,模型针对里面的消息相应的改变自己的作答方式,例如:消息为“假如你是一个天真浪漫的孩子”,那么模型则会调整自己以孩子的视角回答问题。messages 消息列表里只有最后一条消息是 user 的,才会处理该对话,而且模型只会回答最后一条消息,如果其他角色的消息是最后则不生效。
max_tokens 参数,这个控制返回结果的 token 数量,相当于字数;temperature 参数,这个是模型活跃度,范围 0-2 ,默认 1,活跃度越大,选择概率低的词汇越多,文本多样性越多。stream 参数,控制返回结果是全部一起返回,还是流式一个字一个字返回。stop 参数,字符串列表,模型生成的文本遇到这些字符串中的任意一个就会停止生成。presence_penalty 参数,范围 -2-2,默认 0,控制模型生成新内容,新主题的倾向概率。frequency_penalty 参数,取值 -2-2,默认值 0,控制模型避免重复内容生成的倾向概率。tools 参数,对象列表,参数对象是模型调用外部函数以及它的详细说明,影响模型根据用户文本自动调用函数的准确率。tool_choice 参数,字符串,只有 no 和 auto 选项,决定模型是否使用外部函数。
Function Calling 流程,就是模型在分析用户文本的时候,会自动判断是否需要调用外部函数来获取信息,如果需要则会去 tools 参数里的函数里自动调用对应函数,选择函数的判断标准则是通过函数的说明描述,所以 tools 里的函数描述不能乱写。在代码里该流程是通过两次消息对话完成的,第一次将用户对话作为参数,返回结果里包含了函数的描述说明(类似于方法权柄),然后将该说明解析出来作为对话参数传入第二次发送请求,返回的就是调用函数后的结果。
//第二次参数对象修改为是如下例子:
client.chat.completions.create(
model="chatgpt-xxx-xxx",
messages=[{
“tool_call_id”: "唯一值,主键",
"role":"tool",
"name": "my-function-name",
"content":"第一次返回的函数描述结果"
}]
);
ChatGPT Plugin 是用来安装工具插件的,有点像谷歌浏览器里面的插件,相当于就是手机里面的应用市场,可以从里面下载软件安装使用。插件我们也可以开发,和后端服务器代码一样,需要 ai-plugin.json 文件描述插件,openapi.yaml 去描述调用的函数方法,然后就是在 main 主方法里写下方法的实现,本质上就是让 chatgpt 去调用我们服务器上面的接口地址。
面向目标和面向过程
使用 Agent 开发就属于面向目标的一种,面向目标主要着重点是在于用户的目标或者结果,而面向过程主要是如何得到用户的答案,面向目标拥有自动规划的能力和自动执行的能力,面向过程就只有自动执行的能力;例如:我要去xx市xx景区,面向目标的模型就会自动规划好路线和买好车票和景点门票,而面向过程就只能回答该问题,无法做出规划和行动。
Function Calling的问题
Function Calling 是为了让大模型调用外部函数的方式,但是由于用户对话中的无法预料性,我们不知道大模型在处理用户的 Prompt 会出现什么问题,所以导致出现了第一种问题,就是模型可能会出现误调用错误的函数,或许是不需要调用函数却调用了,或许是调用了错误函数,或许是答案处理错了返回错误答案。
解决这个问题,可以将函数的 json schema 描述文件里函数名和描述尽可能写的够精确,够独特,这样模型在调用的时候就减少了错误的概率;也可以使用模型的自我审查机制,或者固定的条件判断去处理用户对话,当用户对话在大模型自己能够回答时就不需要调用外部文件;对于处理答案错误的情况,可以将答案再次以对话的形式询问模型,然后让模型只返回答案数字,和自我审查机制类似。
//首先提问模型这个问题的答案是否自己能回答,只能回答是或否
answer = response.choices[0].message.content
if '是' in answer then {
//调用模型直接回答
} else {
//调用函数回答
}
第二种问题则是关于函数过多,在现实中有极大可能会出现函数过多,当出现海量函数时,如何快速找到对应需要调用的函数;当函数过于复杂(例如链式调用),时间耗费长该如何处理;返回过大的内容数据该如何处理等;
解决这个问题,首先我们可以将函数通过分组,分层的形式弄出一个树形结构,类似于索引的效果,这样就可以快速找到函数;但是为了提高精准命中率,我们可以让模型先意图识别该提示词是属于哪一分组,然后层层找到对应函数,但是有个问题就是,当函数描述文件里函数过多,过长,模型会把函数库看成一个知识库,返回一个函数描述的字符串结果,所以遇到这种情况我们需要自己去解析这个字符串得到提示词,然后让模型调用函数,当然也可以让模型解析,不过这个难度较大;想要串行执行任务时,可以做提示词让模型只返回解决问题的步骤顺序,然后我们循环结果依次调用就可以了;并行就很简单,官方提供了并行任务的函数和例子;时间太慢这个问题没有太好的解决方法,可以使用缓存的形式存储外部函数的数据可以减少调用次数,但是场景要求比较高;返回数据可以采用流式形式返回就可以避免返回内容过大的影响。
当我们想要解决某些问题时,我们首先需要考虑到,通过另类的提示词形式让模型能否自我可以解决问题,如果解决不了再用技术手段去解决,这也叫提示词工程技术。
提示词工程技术
当要求过多时,我们可以分点1,2,3这样例举出来,并且格式要整齐统一,这样模型才更容易理解。
当返回结果格式有问题时,我们可以给一个例子,这也叫 one-shot,多个不同的例子叫 few-shot 。
这种给例子,可以让模型结果更加准确,结果样式。
当问题求解困难时,我们可以让模型自己整理需要求解的步骤,然后按步骤求解。
如果一个问题非常复杂,问题求解需要很多东西,这种简单的方式肯定无法实现,需要分治算法的思想,也可以建立知识库,现在一般都考虑用 Agent 和 COT 去解决。
现在使用大模型解决问题的五种方式:1.提示词工程;2.agent;3.rag;4.微调;5.预训练。
这五种方式越往后成本越高,时间耗费越久。
Agent
agent 也叫智能体,不是一种技术,而是一种应用的设计理念,让模型不要上来就直接求解,而是让模型首先规划如何求解,求解的步骤,考虑之前的问答等情况,然后再根据得到的方式尝试求解。所以这就要求模型需要有非常好的推理能力,才会有一个非常不错的效果,而 o1 模型就是一个非常强的推理能力,甚至有顶级奥数和博士的物理水平,非常好的推动了 agent 的发展。

agent 的设计模式:1.反思类型(reflection),能够自我审查自己的输出并且修正,能不断优化策略并保证正确率和效率;2.工具使用类型(tools use),能调用外部的 API 和工具,能扩展自我的知识库,让应用范围更广泛和灵活;3.思维链类型(chain of thoughts),能将问题分解成多个步骤并有序的执行,适合复杂问题以及长期管理执行的应用;4.多智能体类型(多agent),让多个 agent 扮演不同的角色,共同配合完成一个复杂的任务,可以提高效率,灵活性高。
现在 agent 的框架是层出不穷,有在线,离线的,有开源闭源的,例如 COZE,Dify,AutoGen,LangChain,Swarm 等。
agent 工作方案有两种,一种是先规划完,然后一步一步执行完成;另外一种就是先思考下一步要做什么,然后执行,执行完毕后再思考,知道完成,这种架构也叫 React,提示词一般都是先指定系统角色,然后指定工作方式,也就是怎么分解步骤,然后指定使用的工具,最后给出示例。
多模态
统一多模态,其实就是输入输出的形态可以不同,例如传入图像数据,输出图像;传入文本,输出图像。。等等。
Dify 的使用
介绍
dify 平台是一个快速开发大模型应用的平台,是一个开源的平台,有在线的API使用,也可以本地私有化部署,使用的门槛非常低,即使是不会开发的人员也能使用;能够支持现流行的大部分大模型技术,例如:agent,rag,工作流,使用拖拽的方式即可完成,非常方便。
本地化部署
官方推荐使用 docker 部署,这样我们可以很简单的部署并且保证环境的正常。首先我们需要查看部署的最低配置,否则安装会出现问题,没有安装 docker 的在本地安装 docker ,这个如果有互联网很好安装,百度可以搜索怎么安装;然后通过官网的命令一步一步来就可以完成部署访问了。
虽然 dify 部署好了,但是这个框架没有模型管理的功能,所以这个软件是需要提供模型,可以在线也可以本地安装 ollama 或者 xinference 框架去管理模型。
模型供应商插件
dify 适配了很多的主流大模型供应框架,例如 ollama,xinference,chatgpt等,我们在本地安装了这些框架后,下载大模型,然后将大模型的接入接口填入配置里就可以了,也可以使用在在线的大模型平台Api接口。
ollama 适合语言类模型,而 xinference 则适合 embedding 模型和 rerank 等模型;embedding 模型将数据进行映射到向量空间里,通过对比距离来找出相似数据,能高效进行初始筛选;rerank 模型则是将 embedding 模型召回结果进行逐队评分,根据得分进行排序,提高结果的精密度;
更新后的 dify 需要安装模型供应商的插件才能使用,但是由于这个安装走的是 http 请求的方式,如果是在内网或者租的云服务器上安装,网络上面可能会有些问题,所以我们可以打开开发者工具,查看网络请求参数,参数里面有要下载插件的地址,我们可以复制出来本地下载,然后通过插件安装导入包就可以了。
参数说明
温度:范围0-1,值越高代表模型生成的文本随机性和多样性越多,越低越稳定,精确。
Top-k:生成的词通过排序结果最高的K个随机选择,如果是1,则每次都选择概率最大的词生成。
Top-p:生成的词不是完全随机的,也会考虑上下文的内容,这个值相当于一个阈值,累积概率超过这个值的词得到一个集合,随 机从这个集合里面选择,这是将准确和多样性进行综合考虑的方法。
在提示词里也可以使用插值表达式 {{xxxx}} 去设置一个用户变量,根据用户的选择进行相应的改变。
可以通过内容审查过滤掉敏感词汇。如果想要调用外部函数,可以通过添加工具的方式去设置,dify 提供了很多内置的工具供用用户使用。
agent,work flow,rag 区别
agent 智能体是让大模型遇到复杂问题时制定一个计划,分步骤去执行,根据不同目的,指定的步骤和计划都不同;work flow 工作流则是人为设置的一个执行流程,不具备动态改变;rag 检索增强生成是为了解决模型本身知识不足的问题,由于现在知识太多太多,单独模型是不具备这么多的知识储备,所以需要构建一个知识库,通过让模型使用知识库里的数据,然后根据这些数据生成答案。
rag 会将知识库里的自然语言数据进行嵌入模型的向量化保存到数据库,然后将用户的问题也向量化,通过相似性算法或者其他匹配算法找到相似度较高的答案,选择其中的答案拼接成提示词,将提示词给模型生成回复对话,架构如下图:

DeepSeek
deepseek 的使用方法和 chatgpt 的使用方法,包括代码是一模一样的,只是模型名和api接口地址不同而已,现在大多数的模型规范其实都和 chatgpt 对齐了的,所以不需要再次学习。
function calling
说到底就是我们程序内部首先有一个特殊作用的函数,然后我们需要将这个函数的描述信息给大模型,当我们的对话中可能需要调用这个函数时,让模型根据对话给出相应的输入参数信息,最后我们将输入参数信息代入函数调用,就实现了一次流程,模型不可能真的主动调用我们写好的函数,而且调用也需要运行环境。
我们需要先建立一个字符串列表对象,存的是外部方法的详细信息描述的 json schama 格式字符串。

//方法描述的列表
List<String> toolsList = new ArrayList<>();
tools.add(sunwukong);
//将列表作为参数传入,不管是在线 api 还是本地模型部署传入参数结构都是下面这种
{
model: "xxx",
messages: xxx,
tools:toolsList,
tool_choice:"auto"
}
现在大模型也可以自己输出描述字符串,所以我们可以通过处理模型返回的信息,然后将这个流程封装成一个函数用来自动生成函数的描述。
deepseek-r1
这是一个推理模型,刚出来的时候是不支持 funcion call ,json 输出等功能的,但是这个模型的推理能力相较于同等算力的其他模型,确实是比较出色的。
思维链(Chain of Thought, CoT)是一种人工智能技术,通过将复杂任务分解为一系列逻辑步骤来模拟人类推理过程,从而提升模型的准确性和可解释性。这个模型会将思维链的内容也输出过来。
Janus Pro
这是一个很厉害的多模态模型,有 1b 和 7b 的版本,但是本地部署要求显卡要好一点,不然带不动的。(1b 代表着模型的参数有10亿个,7b则是70亿,参数越多拟合的场景多,效果往往要更好一点)
微调
微调是由于模型知识储备的不足,导致无法解决用户的问题,但是用户的问题各种各样,每个行业可能都有,我们可以通过微调让这个模型具备回答这些行业的问题,看起来像专家系统一样;RAG 也是让模型具备额外的知识,但是微调和 RAG 不同的是,微调是准备数据集训练模型,让模型具备回答这类问题的能力,我们将模型导出给其他人用也是能用的,RAG 则是通过一个额外的知识库,让模型去这个知识库里寻找相关知识去回答,模型本身不具备这种能力,回答再多这类相关问题也不具备,因为没有让模型进行学习。
适合微调的场景:让模型对话具备独特性,让模型更具备专业性,让模型各个能力提升的需求,例如推理能力,执行能力。
适合 RAG 的场景:数据知识是动态改变的,随着周期或者不确定的数据都不能适合微调,程序需要具有可解释性的时候适合。
全量微调和高效微调 :微调分为全量微调和高效微调两类,全量是指将全部的参数都带入数据训练调整;高效微调是只代入部分的参数进行训练调整。前者消耗算力资源极其庞大,但是效果更彻底明显。

微调的算法有很多,上图全是,但是经过目前的使用情况来看,LoRa 算法是普适性非常好的一种,也是大家首要选择。
蒸馏 :蒸馏不是一种技术手段,只是一种提升模型效率的一种方法,也就是利用效果较好且参数大的模型去指导效果欠佳的小模型,让小模型通过学习大模型的行为模式,具备比较好的一个效果并且保持着较低的成本。
微调工具(蒸馏工具) :微调需要使用工具,推荐 unsloth ,LLaMA-Factory ,ms-swift 等等。
微调-显存准备 :在我们微调时,一般需要准备显存充足的显卡,而多少显存才合适,自己可以大概的计算出来。

例如上图:选择微调 7B 的模型,那么参数就是 70亿个,而精度则是选择微调的方式,QLoRA 是 LoRA 的量化方式,能减少显存的消耗,而括号里的则是参数的需要的显存大小,FP 是双精度浮点型,16 是16位 那么16bit * 70 亿则是需要的显存大小(16bit=2byte 1kb=1024byte),当然实际不能刚好准备的这么极限,需要多出大概一半的显存用来保险。
sft(监督微调):是深度学习中一种利用少量标注数据对预训练模型进行微调的技术,主要用于快速适配特定任务。
LangChain
langchain 是一个能快速使用语言模型开发应用的框架,就像java里的spring框架一样,框架结构如下图所示。

LangServe:将项目部署成web服务,提供了 RESTFUL API ,能从网络调用服务。
LangSmith:是监控,追踪,评估应用和智能体的工具,用来帮助开发者。
LangChain:将调用各种 model I/O,chain,agent 的代码封装成 api 接口,提供开发者使用。
Templates:是快速开发应用的官方提供模板。
LangChain的使用
LangChain 的安装可以根据官方的文档一步一步来,编程可以使用python和js两种,都是脚本式语言。
LangChain 的Api分为很多模块,但是基本上这几个比较常用,model I/O(用来调用模型,和模型交互的接口),Retriveval(Rag架构的相关接口),Chains(链式调用模型功能的接口),memory(让模型拥有记忆功能的接口),agent(agent架构的相关接口),callback(回调函数的相关接口)。
LCEL:这是 LangChain 的一种表达语言,也是一种声明式方法,可以轻松将链组合在一起,就类似于 shell 里面的管道符 | ,将前一个的输出作为后一个的输入。
model I/O 模型输入:invoke(单次提问),batch(批量多次),stream(流式调用),ainvoke(异步单次),abatch(异步),astream(异步流式)。使用方式如下:
# pip install langchain langchain-openai langchain-anthropic
from langchain.chat_models import init_chat_model
configurable_model_with_default = init_chat_model(
"openai:gpt-4o",
configurable_fields="any", # this allows us to configure other params like temperature, max_tokens, etc at runtime.
config_prefix="foo",
temperature=0
)
configurable_model_with_default.invoke("what's your name")
# GPT-4o response with temperature 0
configurable_model_with_default.invoke(
"what's your name",
config={
"configurable": {
"foo_model": "anthropic:claude-3-5-sonnet-20240620",
"foo_temperature": 0.6
}
}
)
# Claude-3.5 sonnet response with temperature 0.6
如果想要看更多的例子,可以看官网的文档,写的很清楚。
下面这个是使用提示词的对话示例:
from langchain_core.prompts import ChatPromptTemplate
system_template = "Translate the following from English into {language}"
prompt_template = ChatPromptTemplate.from_messages(
[("system", system_template), ("user", "{text}")]
)
prompt = prompt_template.invoke({"language": "Italian", "text": "hi!"})
response = model.invoke(prompt)
当我们提示词非常大的时候,每次都将提示词给模型,非常消耗token,所以 LangChain 提供了示例器对象(ExampleSelector),例如: SemanticSimilarityExampleSelector ,这个对象可以根据用户的问题和提示词中的例子相似度来选择例子作为 few shot。
我们也可以自定义示例器,只需要实现BaseExampleSelector抽象类里的方法就可以了。
对于将模型输出的结果转类型,也提供了工具类去实现,在官网文档 core - output_parsers 下能找到示例学习,例如:JsonOutputParser 。
调用外部函数的核心就是如何创建函数的 schema 文档以及如何绑定函数工具到对话实例上,具体例子可以在官网 core - tools 下找到各种例子。
LangChain 也可以集成其他的大模型框架或者私有模型,在官网有使用的文档学习。

chains模块
LangChain 提供了一种模块化的设计理念去构建一套复杂的应用,就像乐高积木一样,通过每个简单的功能模块相互组合,形成一个更加复杂的,适合更广泛应用面的功能。
create_openai_fn_runnable 模块是较为常用的,作用就是传入函数和模型,能帮我们找到提问内容需要调用的函数是哪个。
LangChain 内部提供了许多以及构建好的chains了,我们可以在官网上搜到使用方法,例如:LLM chain,simplesequential chain 等。
memory模块
memory 模块让模型拥有记忆的功能,相当于一个历史记录保存器,以前的所有的对话都会保存在这容器里面,如果使用实体识别(spacy)配合提示词,可以实现通过对话里分析出来的实体,去找历史记录里是否包含了该实体,如果找到则让模型根据以前的对话生成相应的回答。
实体识别是自然语言处理里一个常见的任务,就是将一段文本里的特殊名词提取出来,如名字,地方,国家,数量,金额等。
而 LangChain 内置的 memory 模块分为了3类,conversation 对话类,entity 实体类,summary 摘要类,根据名字就能知道,这三类区别就是保存的内容不同,对话类:只有完整的对话;实体类:历史对话加上实体识别出来的内容;摘要类:为了节省资源,给对话生成总结性的摘要保存。
使用: 创建 LLMChain 对象的时候,里面有个 memory 参数,将创建的 memory 模块对象传入即可使用。
agents模块
LangChain 抽象出了两个概念,agent 和 AgentExecutor 。agent 是实现了规划的能力,AgentExecutor 则是实现了规划后每个步骤执行的能力。由于 agent 可能存在多次调用,所以输入有可能会是上一次模型的结果,或者是对话上下文,这个是根据规划的策略决定的,规划的策略则是通过提示词决定的。LangChain 提供了很多内置的不同策略模板的 agent 使用。

ReAct 策略,让模型动态规划下一步的执行步骤,然后多次规划达到目的,例如:让模型说10个某个行业相关的专业词汇,模型可能规划先说出3个,然后根据这3个再衍生出7个出来。
retrieval模块
这个模块就是为了实现 RAG(Retrieval-augment-generation) 功能。LangChain 里的流程如下图所示,和 RAG 的流程一样,每个步骤 LangChain 都提供了很多组件给用户选择使用。

LangGraph
LangGraph 是专注于 agent 的开发,对比 LangChain 它能构建更加复杂的多 agent 应用,可以存在调用环的情况,就是数据结构里的有向图。
图的分类:里面有普通图,状态图,但所有的图都是有向图。
边的分类:图里面有顶点和边,边则分普通边,条件边(也就是或与非运算关系),入口边,条件入口边。
顶点的分类:顶点有开始点,结束点,以及普通点,开始结束是必须要有的,顶点就是一切可运行的代码片段,类似函数。
图对象创建完成后,必须要编译后才可以使用,否则会报错,代码创建图没法直观的检查问题,所以 LangGraph 提供了可视化工具,状态在图里面相当于一个全局字典列表变量,可以放入或者读取状态值(键值对)。
代理架构
LangGraph 里面分了四大类代理架构,其实也就是 agent 的架构,分为:路由代理,工具代理,自主循环代理和多代理。
路由代理:agent 根据某个条件判断调用的下一个顶点,通过添加条件边实现。
工具代理:agent 自己判断是否需要调用工具,调用哪个工具。
自主循环代理:agent 规划执行步骤,动态调整执行的下一个顶点。
多代理:多个分类的 agent ,根据情况自主选择调用相应功能模块的 agent。
结构化输出:让模型输出结果好看整洁,形成一种结构化的文本,例如 json ,xml 格式。
多代理架构有很多类型,如下图所示:

记忆模块
memory:里面分了长期记忆和短期记忆,短期记忆就只考虑这一次对话的消息,而长期记忆能考虑以往对话的消息。记忆保存的触发,是在图状态更新时,会生成一个快照作为检查点(checkpoint),而这个检查点会被保存起来作为记忆内容,如果要使用检查点,需要新建一个线程,这个检查点会绑定这个线程ID,其他线程访问不了当前线程的检查点的,长期记忆就是同个用户所有的短期记忆内容作为一个整体存储(仓库 store)。
MemorySaver:这个是将内容保存在内存中,如果需要持久化保存就需要用其他工具。
human-in-the-loop:HIL 人机交互,是为了避免模型直接执行一些危险操作,所以需要人为确认是否执行或者干预;LangGraph 就使用断点 breakpoint 这种方式实现,断点是基于检查点之上的,断点可以放置于顶点前或者顶点后。
动态断点:当断点打在某个顶点前时,每一次执行到这个顶点都会被拦截,在某些情况下这种显然不符合需求,可能只是这个顶点部分操作需要拦截,其他的不需要,这时候就需要动态断点来实现,要实现也简单,就是把这个节点里的涉及危险操作的内容抽出来单独作为一个顶点,然后在前置顶点里添加判断是否涉及危险操作,如果涉及就执行危险操作的路由。
数据预处理
Pandas 是一个开源的数据分析和数据处理库,基于 Python 编程语言开发的,提供了易于使用的数据结构和数据分析工具,特别适用于处理结构化数据,如表格型数据(类似于Excel表格),是数据科学和分析领域中常用的工具之一,它使得用户能够轻松地从各种数据源中导入数据,并对数据进行高效的操作和分析。
Ollama
Ollama 底层是基于 docker 容器的大模型运行工具。
安装以及使用
在官网下载需要部署的安装包,然后根据官网的教程部署就可以了。由于我安装的是windows的版本,所以很简单就完成了。
安装完成后,打开命令窗口(cmd),我们可以输入 ollama -h 命令来查看支持的参数和指令有哪些,如果不支持 ollama 命令就是没有配置环境变量,自己配一下就可以了,一般安装完成后程序会自动给你配置的。
模型是需要自己主动下载的,直接到官网查看有哪些模型是可以下载的,选好自己下载的模型,复制下载地址,然后在命令窗口输入下载模型的命令。下载完成后我们输入运行指令就可以进入对话了,但是如果我们想要自己程序接入模型,需要通过 http 请求的形式去接入。
ollama -h //帮助指令,查询可支持的命令和参数
ollama list //列出本地已下载的模型
ollama run xxxx //运行模型,如果没有这个模型,会自动去官网下载模型,xxxx是模型的标识,例如 qwen3:8b
/bye //运行模型后会进入对话窗体,这个命令就是退出对话的命令
模型返回结果可以有两种方式,一种是流式的,一种是非流式的;流式的相当于一点一点的返回结果给我们,反馈效果要强,非流式的就是等到结果全部算完后才返回,这个能节约性能。java 接受流式数据的方式在项目学习记录里。
如果我们嫌弃命令窗太难用,我们可以使用 Open WebUI 框架,这个框架是一个开源的可视化框架,能接入不同模型,不过这个框架是python写的,需要python的运行环境
模型下载
当我们需要其他模型时,我们可以在 Hugging Face 平台或者是 魔搭平台去下载,里面提供了很多不同的模型以及数据集。
RAG
rag 的流程和目的在上面已经说明,就不再叙述。rag 架构的也在不断的改进优化,下图就是原生架构的说明,原生架构会遇到很多问题,例如幻觉问题等,进阶架构就是为了解决了一些问题产生的,例如更改检索模式,优化检索算法,微调 embedding 模型等。

落地方案
在线平台:dify ,coze ,fastGPT 。
非在线平台:langchian ,LlamaIndex ,RagFlow。
ragflow 是一个开源项目,下载项目后就能使用,集成了 OCR 功能,支持从各种不同的数据源,数据格式提取成知识,也能支持本地模型以及本地嵌入模型,也就是本地实现 Rag。fastChat 是一个多模型管理平台项目,开源并且好用。
对于 RAG 的落地效果的评估,有现有项目可以使用,例如:Trulens ,Ragas 等。
向量数据库:Milvus ,Pinecone ,TencentCloud VectorDB ,Chroma ,Faiss 。
性能优化
- 多路召回:在检索信息时,我们有多种搜索知识的方式,如:文档,搜索引擎,向量数据库等,我们可以进行多种方式并行执行,找到的信息进行 ReRank ,得到最准确的答案给提示词,然后再传给大模型。
- 当需要让模型根据用户提出的问题,给予用户相对应推荐的产品,这个要求相当大的准确性,所以我们可以采用模拟用户提问的方式,提前将问题/答案做成 Q/A 对的形式保存到知识库,然后通过多路召回的方式去找相应的知识。
- 可解释性:由于很多知识涉及专业性,所以需要在回答里添加对文档,论文,书籍的引用,这样用户才能信任。
- 可交互性:对于某些危险操作,必须要弹窗让用户自己决定才行;也可以添加用户反馈机制。
- 添加缓存:如果很多用户都问了同一个问题,这种可以添加缓存提高响应速度。
其他知识
联网问答搜索工具 serper ,支持在网上找到最相关的几个网页,然后从里面提取出知识提供给模型回答。
评分函数:也叫得分函数(Score Function),是统计学和机器学习中用于参数估计、模型优化等场景的核心概念,主要指对数似然函数对参数的偏导数,举例说就是可以在两个数据之间得到某个特征的分数,可以用来在多路召回里计算知识库里的知识和用户对话匹配相关性的分数。
F1分数:是统计学和机器学习中用于评估二分类模型性能的指标,通过计算精确率(Precision)与召回率(Recall)的调和平均数,综合衡量模型在预测正类时的准确性与完整性平衡,其值范围在0到1之间,1表示最优性能,可以在 Rerank 算法中使用。
参考链接
dify github官网 :https://github.com/langgenius/dify/
ollama 官网 :https://ollama.com
open-webui官网 :https://github.com/open-webui/open-webui
unsloth官网 :https://github.com/unslothai/unsloth
LLaMA-Factory官网 :https://github.com/hiyouga/LLaMA-Factory
Hugging Face大模型平台官网 : https://huggingface.co/
魔搭社区 :https://www.modelscope.cn/home
LangChain官网 :https://www.langchain.com/
注意力机制动画讲解:https://developer.volcengine.com/articles/7382262877597466675
更多推荐


所有评论(0)