AI大模型实现软件智能化落地实践

1、什么是大模型

大型语言模型(Large Language Model,LLM;Large Language Models,LLMs)。

大语言模型是一种深度学习模型,特别是属于自然语言处理(NLP)的领域,一般是指包含数干亿(或更多)参数的语言模型,这些参数是在大量文本数据上训练的,例如模型GPT-3,Chatglm,PaLM,LLaMA等,大语言模型的目的是理解和生成自然语言,通过学习大量的文本数据来预测下一个词或生成与给定文本相关的内容。从实际应用表现来看,大语言模型具备回答各种问题、编写文章、编程、翻译等能力,如果深究其原理,LLM建立在Transformers架构之上,并在很大程度上扩展了模型的大小、预训练数据和总计算量

参数可以被理解为模型学习任务所需要记住的信息,参数的数量通常与模型的复杂性和学习能力直接相关,更多的参数意味着模型可能具有更强的学习能力。

大模型其核心思想是根据已有的文本序列生成下一个最可能出现的单词。这一切都是基于统计学习和推理,而非像人类那样进行逻辑推理或思考
在这里插入图片描述

2、Transformers架构

我们对LLM这样的聊天模型可能已经习以为常,一问即答似乎很正常。然而,如果深入思考其背后的工作原理,你会发现这实际上是一件令人惊奇的事情。所以,我想让大家明确一个问题:究竟什么是Transformer,以及它是如何获得这种革命性的影响力的。

Transformer由编码器(Encoder) 和解码器(Decoder)组成,其中编码器用于学习输入序列的表示,解码器用于生成输出序列。 GPT主要采用了transformer的解码器部分,用于构建语言模型。其结构是这样的:
在这里插入图片描述对于一条输入的数据,在这个复杂的架构中是如何流动和处理的?

文本编码

  • 词嵌入(Word Embedding): 文本中的每个单词都被转换为一个高维向量。这个转换通常是通过预训练的词嵌入模型(如Word2Vec、GloVe等)完成的。(确定计算机能理解单词)

  • 位置嵌入(Positional Embedding): 标准的Transformer模型没有内置的序列顺序感知能力,因此需要添加位置信息。这是通过位置嵌入完成的,它与词嵌入具有相同的维度,并且与词嵌入相加。(确定文本词顺序)

词嵌入和位置嵌入相加,得到一个包含了文本信息和位置信息的新的嵌入表示。
最终得到输入的Transformer表示x,这样,模型就能知道每个单词不仅是什么,还能知道它在序列中的位置

在这里插入图片描述通过文本编码的一个处理过程,模型就可以认识"扬帆起航"这样的一个输入。

Encoder(编码器部分)

Transformer中的编码器部分,作用是学习输入序列的表示,位置如下图所示:

在这里插入图片描述在Transformer模型的编码器(红色虚线框)部分,数据处理流程如下:

首先,输入数据(比如一段文字)会被送入注意力(Attention)机制进行处理,这里会给数据里的每一个元素(比如每一个字或词)打个分数,以决定哪些更重要

例如:小猫想过马路,但它累倒了,理解哪个更重要,“它”指谁

在"注意力机制"(Attention)这个步骤之后,会有一些新的数据生成。

在注意力机制"中产生的新数据会和最开始输入的原始数据合在一起,这个合并其实就是简单的加法。"Add"表示残差连接,这一操作的主要目的是确保数据经过注意力处理后的效果至少不逊于直接输入的原始数据。

数据会经过一个简单的数学处理,叫做“层归一化”(Norm)(缩小或放大),主要是为了让数据更稳定,便于后续处理。

简单来说,Transformer的编码器就是通过这些步骤来理解和处理输入的数据,然后输出一种新的,更容易理解的数据形式。如图:

在这里插入图片描述

Decoder(解码器部分)

在这里插入图片描述在Decoder部分,数据首先进入一个带遮罩(masked)的注意力(Attention)机制,这个遮罩的作用是确保解码器只能关注到它之前已经生成的词,而不能看到未来的词。

然后,这一层输出的信息会与来自Encoder部分的输出进行融合。具体来说,这两部分的信息会再次经历一个注意力机制的处理,从而综合考虑编码与解码的内容。

这个过程之后,解码器的操作与编码器部分大致相同。数据会经过层归一化、前馈神经网络,再次进行层归一化,最终输出一个词向量表示。

输出的词向量首先会通过一个线性层(Linear)。这一步的目的是将向量映射到预先定义的词典大小,从而准备进行词预测。

最后,使用softmax函数计算每个词的生成概率。最终,选取概率最高的词作为该时刻的输出

举个例子:

现在假设有一个很小的词典,只有3个词:“apple”,“banana”,“cherry”。线性层会将这个3维向量转换成另一个3维向量(对应“词典”大小)。

假设转换后的向量是 [2.5, 1.0, -0.5]。

通过softmax函数,这个向量会转换为概率分布,比如 [0.8, 0.18, 0.02]。

这就意味着模型认为下一个词是“apple”的概率是80%,是“banana”的概率是18%,是“cherry”的概率是2%。

这样,就能从解码器的高维输出中预测出一个实际的词语了。

3、大模型

3.1、大模型选型

大模型目前分为通用大模型和垂直领域大模型(行业模型)

主流的开源大模型:

  • ollama3
  • qwen
  • chatglm3
  • GLM-3-Turbo

3.2、模型显存计算和量化

如果是想本地部署大模型需要考虑模型权重显存占用,因为gpu比较贵,要选取合适参数大小的模型,那么如何计算?

以7b模型为例:

7B,即是7 Billion个参数,70亿个参数。

目前的多数大模型中,参数是float32类型(全精度),一个参数占4个字节

70亿个参数则占70亿 x 4 = 280亿个字节 = 280亿(Byte)。

字节的单位有TB,GB,MB,KB,它们的换算关系是1024倍,即:

1TB=1025GB

1GB=1024MB

1MB=1024KB

1KB=1024Byte

1B(10亿)参数,每个参数占4个字节,则模型占用显存:

4 x 1000000000 / 1024(KB) / 1024(MB) / 1024(GB) = 3.725G

7B则是:7 x 3.725 = 26.08G

为了方便粗略估算,可以按1B参数占用4G显存来算(虽然多算了一点,但在实际推理过程中,除了加载模型需要显存外,计算过程也是临时需要额外显存的,因此具备合理性)。

7B模型则占用:7 x 4G = 28G

半精度(16)由于只占两个字节,1B参数占用2G显存,7B模型则占用14G。

8精度则只占1个字节,4精度一个参数只占半个字节,因此分别占显存7G和3.5G。

理解了这个计算方法,以后看到某个参数规模的模型时,就能自己计算显存需求了。

能不能让模型在使用效果相差不大的情况下,减少模型的显存占用?

模型量化技术正是针对解决这一问题而提出,一句话概述就是:通过用更少位数的数据类型近似表示32位浮点数,以较低的推理精度损失,达到减少模型尺寸、内存消耗和加快推理速度的目的。

先来看看不同参数规模的Llama2在不同精度下的推理显存预估要求:
在这里插入图片描述

3.3、大模型部署

以chatglm3-6b为例来本地部署大模型

首先环境上必须要安装conda,python3.11

通过nvidia-smi 来确定机器上的gpu的cuda版本,然后去pytorch官网下载对应的pytorch对应的依赖。注意pytorch与cuda不对应模型跑不起来

# 获取模型基础运行代码
! git clone https://github.com/THUDM/ChatGLM3.git# git lfs 是git大文件存储管理工具
# 如果没有# ! git clone https://www.modelscope.cn/ZhipuAI/chatglm3-6b.gitgit 要先安装git, 没有git lfs需要安装git lfs
# 通过感叹号! 可以实现运行linux的命令行语句
# 获取模型, git中启用git lfs
! git lfs install 
! git clone https://swanhub.co/ZhipuAI/chatglm3-6b.git# 要在conda虚拟环境中运行,进行环境隔离,不然会有依赖冲突
conda create -n test_env python=3.11
conda activate test_env#因无法实现cd 命令切换路径故使用python自带os库切换路径
import os 
os.chdir('/mnt/workspace')
os.chdir('ChatGLM3')
# 安装代码所需的环境依赖,注意一下 requirement上的pytorch要去除掉
! pip install -r requirements.txt
os.chdir('/mnt/workspace')# 启动模型
from modelscope import AutoTokenizer, AutoModel
model_dir = 'chatglm3-6b'
tokenizer = AutoTokenizer.from_pretrained(model_dir, trust_remote_code=True)
#cuda使用GPU计算, float使用CPU计算
model = AutoModel.from_pretrained(model_dir, trust_remote_code=True).half().cuda()
# model = AutoModel.from_pretrained(model_dir, trust_remote_code=True).half().float()
model = model.eval()

在这里插入图片描述

3.4、大模型微调

大模型微调就是在有限的gpu资源环境下,对模型增加少量的参数,实现模型推理生成

微调适用的场景
通常来说,适合微调的场景主要分为行业场景和通用场景

对于行业场景:

  1. 例如客服助手,智能写作辅导等需要专门的回答范式和预期的场景
  2. 例如智慧医生,智慧律师等需要更专业的行业知识和思考能力的场景

对于通用场景

  1. NL2SQL等输出为指定范式的
  2. 支持可调整参数的工具调用等原生模型不具备的能力的

模型微调以chatglm3-6b模型为例

1、首先要明确想要达成的效果,例如实现广告生成语

2、然后我们要了解到chatglm3的数据微调格式,注意,每种模型对于数据要求可能是不一样的

  • 如果仅希望微调模型的对话能力,而非工具能力,应该按照以下格式整理数据
[{"conversations": [{"role": "system","content": "<system prompt text>"},{"role": "user","content": "<user prompt text>"},{"role": "assistant","content": "<assistant response text>"},// ... Muti Turn{"role": "user","content": "<user prompt text>"},{"role": "assistant","content": "<assistant response text>"}]}// ...
]
  • 如果希望微调模型的对话和工具能力,应该按照以下格式整理数据。
[{"tools": [// available tools, format is not restricted],"conversations": [{"role": "system","content": "<system prompt text>"},{"role": "user","content": "<user prompt text>"},{"role": "assistant","content": "<assistant thought to text>"},{"role": "tool","name": "<name of the tool to be called","parameters": {"<parameter_name>": "<parameter_value>"},"observation": "<observation>"},{"role": "assistant","content": "<assistant response to observation>"},// ... Muti Turn{"role": "user","content": "<user prompt text>"},{"role": "assistant","content": "<assistant response text>"}]}// ...
]

3、然后我们按照对应上述格式将数据进行处理

原始数据
在这里插入图片描述转换成大模型数据交互模型
在这里插入图片描述4、安装微调一些必要的依赖

jieba>=0.42.1
ruamel_yaml>=0.18.5
rouge_chinese>=1.0.3
jupyter>=1.0.0
datasets>=2.16.1
peft==0.7.1
transformers>=4.37.2
deepspeed>=0.13.1

5、通过lora将对应的数据输入大模型进行微调

# CUDA_VISIBLE_DEVICES 设置使用的显卡. 0指明使用0号位置的显卡,可以设置使用多个显卡,通过 nvidia-smi 查看显卡序号
!CUDA_VISIBLE_DEVICES=0 /home/pai/bin/python finetune_hf.py  data/AdvertiseGen_fix 
/mnt/workspace/chatglm3-6b  configs/lora.yaml no

finetune_hf.py :chatglm提供的微调文件
data/AdvertiseGen_fix:转换后的数据目录
/mnt/workspace/chatglm3-6b :模型权重
configs/lora.yaml :lora配置文件

6、使用微调的数据集进行推理

在完成微调任务之后,我们可以查看到 output 文件夹下多了很多个checkpoint-*的文件夹,这些文件夹代表了训练的轮数。我们选择最后一轮的微调权重,并使用inference进行导入。

!ls output/# 经过验证,根据输入的提示词,模型可以自动进行推理生成,不是一对一映射给出结果
# 但回答结果不尽如人意,应该是数据质量不行
!CUDA_VISIBLE_DEVICES=0 python inference_hf.py output/checkpoint-3000/ --prompt "衣服和裙子"

output/checkpoint-3000/ :微调后的模型权重目录
prompt:用户输入

在这里插入图片描述可以看到训练的结果,不是原本模型那种模板化的回答

3.5、RAG(检索增强生成)

RAG(Retrieval-Augmented Generation)是什么?

在这里插入图片描述

一个典型的 RAG 案例如图所示。如果我们向 ChatGPT 询问 OpenAI CEO Sam Atlman 在短短几天内突然解雇随后又被复职的事情。由于受到预训练数据的限制,缺乏对最近事件的知识,ChatGPT 则表示无法回答。RAG 则通过从外部知识库检索最新的文档摘录来解决这一差距。在这个例子中,它获取了一系列与询问相关的新闻文章。这些文章,连同最初的问题,随后被合并成一个丰富的提示,使 ChatGPT 能够综合出一个有根据的回应。

RAG实现原理

在这里插入图片描述
1、首先读取各种文件pdf,text,word,ppt等等,通过程序loader将它们转换为文档
2、通过文本分割器textSplit(这种分割器有很多)将文本分割成一块块的,存储在数据库中,可以是pgsql
3、将一块块文本块分别转换为向量,通过向量模型,然后存储在向量库中,可以pgsql+pgvector
4、当用户输入问题的时候,会将问题文本通过向量模型向量化,然后再去向量库进行模糊匹配一定范围内的向量块数据,最终取出topn 数据
5、将问题 和 取出来的多个文本块数据 一起作为输入,让模型推理生成,符合实际的答案
6、将问题和答案进行缓存,提高并发率

3.6、Function Calling(功能调用)

什么是工具调用?

大模型虽然强大,但是由于训练的时间和语料限制。大模型通常会存在以下问题:

  • 只能获取训练数据集中有的事件和内容,这意味着大模型不具备访问最新资料的能力。(RAG只是知识库的能力)
  • 模型以通用语料训练为主,因此,缺少专业领域的知识。
  • 体量较小,虽然拥有较强的数学,英语等能力,但仍然无法与GPT4等大模型进行抗衡,因此,会出现数学计算不准确等问题。(专业功能不强大)

想想一下大模型就是大脑用来思考,这时候,通过给大模型加上“四肢“,让大模型学会使用工具,这些问题将迎刃而解。

例如,我们通过编写计算器插件,使用Python的eval()验证功能,或者numexpr.evaluate() 等功能,将能有效的辅助模型进行计算。模型仅需要告诉插件计算的内容,由工具完成计算,并返回大模型,大模型将答案进行整合输出,便可以得到正确的答案。

那么这些外接的功能函数,就是function calling

那么,如何实现呢?我们依旧以chatglm3为例

1、定义工具信息

tools = [{"name": "track","description": "追踪指定股票的实时价格","parameters": {"type": "object","properties": {"symbol": {"description": "需要追踪的股票代码"}},"required": ['symbol']}},{"name": "text-to-speech","description": "将文本转换为语音","parameters": {"type": "object","properties": {"text": {"description": "需要转换成语音的文本"},"voice": {"description": "要使用的语音类型(男声、女声等)"},"speed": {"description": "语音的速度(快、中等、慢等)"}},"required": ['text']}}
]
system_info = {"role": "system","content": "Answer the following questions as best as you can. You have access to the following tools:","tools": tools
}

这个实际上是告诉大模型我有这些函数工具,以及对应的参数

2、理解工具运行流程

<|user|>
提出问题
<|assistant|>
思考应该做什么<|assistant|>调用工具的名称
python(这里的python是固定格式,并不一定是python语句)
tool_call(调用工具的参数)<|observation|>
工具回复的结果,为一个字符串
<|assistant|> 
(如果知道最后答案)我知道最后答案了,回答用户的问题 

3、工具注册到工具库,以便模型调用
在chatglm3的代码中,设计了一个工具注册的函数,用户可以在tool_register.py中寻找到这个函数。该函数如下

def register_tool(func: callable):tool_name = func.__name__tool_description = inspect.getdoc(func).strip()python_params = inspect.signature(func).parameterstool_params = []for name, param in python_params.items():annotation = param.annotationif annotation is inspect.Parameter.empty:raise TypeError(f"Parameter `{name}` missing type annotation")if get_origin(annotation) != Annotated:raise TypeError(f"Annotation type for `{name}` must be typing.Annotated")typ, (description, required) = annotation.__origin__, annotation.__metadata__typ: str = str(typ) if isinstance(typ, GenericAlias) else typ.__name__if not isinstance(description, str):raise TypeError(f"Description for `{name}` must be a string")if not isinstance(required, bool):raise TypeError(f"Required for `{name}` must be a bool")tool_params.append({"name": name,"description": description,"type": typ,"required": required})tool_def = {"name": tool_name,"description": tool_description,"params": tool_params}print("[registered tool] " + pformat(tool_def))_TOOL_HOOKS[tool_name] = func_TOOL_DESCRIPTIONS[tool_name] = tool_defreturn func

实现自己的工具代码,以下例子为天气查询工具的示例

@register_tool
def get_weather(city_name: Annotated[str, 'The name of the city to be queried', True],
) -> str:"""Get the current weather for `city_name`"""if not isinstance(city_name, str):raise TypeError("City name must be a string")key_selection = {"current_condition": ["temp_C", "FeelsLikeC", "humidity", "weatherDesc", "observation_time"],}import requeststry:resp = requests.get(f"https://wttr.in/{city_name}?format=j1")resp.raise_for_status()resp = resp.json()ret = {k: {_v: resp[k][0][_v] for _v in v} for k, v in key_selection.items()}except:import tracebackret = "Error encountered while fetching weather data!\n" + traceback.format_exc()return str(ret)if __name__ == "__main__":print(dispatch_tool("get_weather", {"city_name": "beijing"}))print(get_tools())

当用户输入“帮我查询下北京目前的天气”

大模型会根据语境理解,去函数库匹配 对应的方法,返回方法和对应的参数信息,然后python 根据方法名及参数去进行调用。

再举一个例子

本地定义如下两个外部函数供模型选择调用:

  • 查询两地之间某日航班号函数:get_flight_number(departure: str, destination: str, date: str)
  • 查询某航班某日票价函数:get_ticket_price(flight_number: str, date: str)
def get_flight_number(date:str , departure:str , destination:str):flight_number = {"北京":{"上海" : "1234","广州" : "8321",},"上海":{"北京" : "1233","广州" : "8123",}}return { "flight_number":flight_number[departure][destination] }
def get_ticket_price(date:str , flight_number:str):return {"ticket_price": "1000"}

然后编写函数库工具的描述

tools = [{"type": "function","function": {"name": "get_flight_number","description": "根据始发地、目的地和日期,查询对应日期的航班号","parameters": {"type": "object","properties": {"departure": {"description": "出发地","type": "string"},"destination": {"description": "目的地","type": "string"},"date": {"description": "日期","type": "string",}},"required": [ "departure", "destination", "date" ]},}},{"type": "function","function": {"name": "get_ticket_price","description": "查询某航班在某日的票价","parameters": {"type": "object","properties": {"flight_number": {"description": "航班号","type": "string"},"date": {"description": "日期","type": "string",}},"required": [ "flight_number", "date"]},}},
]

我们想查询2024年1月20日从北京前往上海的航班。我们向模型提供这个信息:

messages = []
messages.append({"role": "user", "content": "帮我查询从2024年1月20日,从北京出发前往上海的航班"})
response = client.chat.completions.create(model="glm-4",  # 填写需要调用的模型名称messages=messages,tools=tools,tool_choice='auto'
)
print(response.choices[0].message)
messages.append(response.choices[0].message.model_dump())

模型返回输出

content=None role='assistant' 
tool_calls[CompletionMessageToolCall(id='call_8495942909317716104', 
function=Function(arguments='{"date":"2024-01-20","departure":"北京","destination":"上海"}',name='get_flight_number'), type='function')]

然后编写一个解析函数,实现函数调用

def parse_function_call(model_response,messages):# 处理函数调用结果,根据模型返回参数,调用对应的函数。# 调用函数返回结果后构造tool message,再次调用模型,将函数结果输入模型# 模型会将函数调用结果以自然语言格式返回给用户。if model_response.choices[0].message.tool_calls:tool_call = model_response.choices[0].message.tool_calls[0]args = tool_call.function.argumentsfunction_result = {}if tool_call.function.name == "get_flight_number":function_result = get_flight_number(**json.loads(args))if tool_call.function.name == "get_ticket_price":function_result = get_ticket_price(**json.loads(args))messages.append({"role": "tool","content": f"{json.dumps(function_result)}","tool_call_id":tool_call.id})response = client.chat.completions.create(model="glm-4",  # 填写需要调用的模型名称messages=messages,tools=tools,)print(response.choices[0].message)messages.append(response.choices[0].message.model_dump())

可以看到此时模型成功触发对 get_flight_number 函数的调用 参数为:date=“2024-01-20”,departure=“北京”,destination=“上海”

3.7、本地模型对外提供API访问(FastAPI)

FastAPI是一个现代、快速(高性能)的python web框架,基于标准的python类型提示,使用python3.6+构建的web框架。

FastAPI的架构为RESTful风格,RESTful是一种网络应用程序的设计风格和开发方式,其特点为每一个URI代表一种资源,客户端通过GET、POST、PUT、DELETE等动作,对服务器端资源进行操作。

环境准备

安装FastAPI:pip install fastapi安装ASGI服务:pip install uvicorn

新建一个main.py文件,编写如下:

from fastapi import FastAPI  app = FastAPI()  
@app.get('/')  
def root():  return {'message': 'Hello World'}  

启动服务
命令:uvicorn main:app --reload

main:文件main.py(python模块)

app:在模块中app=FastAPI()行中创建的对象

–reload:代码更改后自动重启服务(上线时该参数值不能为true,降低性能)

访问服务

启动服务后,使用浏览器访问127.0.0.1:8000,
在这里插入图片描述
结合模型
以chatgml3为例
新增api.py文件

from fastapi import FastAPI, Request
from transformers import AutoTokenizer, AutoModel
import uvicorn, json, datetime
import torchDEVICE = "cuda"
DEVICE_ID = "0"
CUDA_DEVICE = f"{DEVICE}:{DEVICE_ID}" if DEVICE_ID else DEVICEdef torch_gc():if torch.cuda.is_available():with torch.cuda.device(CUDA_DEVICE):torch.cuda.empty_cache()torch.cuda.ipc_collect()app = FastAPI()@app.post("/")
async def create_item(request: Request):global model, tokenizerjson_post_raw = await request.json()json_post = json.dumps(json_post_raw)json_post_list = json.loads(json_post)prompt = json_post_list.get('prompt')history = json_post_list.get('history')max_length = json_post_list.get('max_length')top_p = json_post_list.get('top_p')temperature = json_post_list.get('temperature')response, history = model.chat(tokenizer,prompt,history=history,max_length=max_length if max_length else 2048,top_p=top_p if top_p else 0.7,temperature=temperature if temperature else 0.95)now = datetime.datetime.now()time = now.strftime("%Y-%m-%d %H:%M:%S")answer = {"response": response,"history": history,"status": 200,"time": time}log = "[" + time + "] " + '", prompt:"' + prompt + '", response:"' + repr(response) + '"'print(log)torch_gc()return answerif __name__ == '__main__':tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm3-6b", trust_remote_code=True)model = AutoModel.from_pretrained("THUDM/chatglm3-6b", trust_remote_code=True).cuda()# 多显卡支持,使用下面三行代替上面两行,将num_gpus改为你实际的显卡数量# model_path = "THUDM/chatglm2-6b"# tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)# model = load_model_on_gpus(model_path, num_gpus=2)model.eval()uvicorn.run(app, host='0.0.0.0', port=8000, workers=1)

4、大模型与软件智能化实践

4.1、什么是LangChain

LangChain是一个强大的框架,旨在帮助开发人员使用语言模型构建端到端的应用程序。它提供了一套工具、组件和接口,可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互,将多个组件链接在一起,并集成额外的资源,例如 API 和数据库。

官方文档:https://python.langchain.com/en/latest/
中文文档:https://www.langchain.com.cn/

LangChain有几个核心概念

1、agent(代理/智能体)通常用户的一个问题可能需要应用程序的多个逻辑处理才能完成相关任务,而且往往可能是动态的,会随着用户的输入不同而需要不同的 Action,或者 LLM 输出的不同而执行不同的 Action。因此应用程序不仅需要预先确定 LLM 以及其他工具调用链,而且可能还需要根据用户输入的不同而产生不同的链条。使用代理可以让 LLM 访问工具变的更加直接和高效,工具提供了无限的可能性,LLM 可以搜索网络、进行数学计算、运行代码等等相关功能。

LangChain 中代理使用 LLM 来确定采取哪些行动及顺序,查看观察结果,并重复直到完成任务。LangChain 库提供了大量预置的工具,也允许修改现有工具 或创建新工具。当代理被正确使用时,它们可以非常强大。在 LangChain 中,通过“代理人”的概念在这些类型链条中访问一系列的工具完成任务。根据用户的输入,代理人可以决定是否调用其中任何一个工具。

总结:首先我们需要告诉大模型有哪些工具库,agent概念呢,可以独立创建不同的agent分配给这些agent对应的工具库,例如:数据家agent(复杂计算,论文润色等),作家agent(论文润色,写作)。然后通过用户指定不同agent进行多轮交互,最终完成任务

在这里插入图片描述

2、chain(链)链允许我们将多个组件组合在一起以创建一个单一的、连贯的任务。例如,我们可以创建一个链,它接受用户输入,使用 PromptTemplate 对其进行格式化,然后将格式化的响应传递给 LLM。另外我们也可以通过将多个链组合在一起,或者将链与其他组件组合来构建更复杂的链。

3、index(索引)索引是指对文档进行结构化的方法,以便 LLM 能够更好的与之交互。该组件主要包括:Document Loaders(文档加载器)、Text Splitters(文本拆分器)、VectorStores(向量存储器)以及 Retrievers(检索器)。

4、memory(记忆存储)
5、models(模型)
6、prompts(提示词工程)基于模板做提示词

在这里插入图片描述

4.2、Langchain4j实践(java版langchain)

从概念上来说大体一致与langchain,但还是有一定的区别的

1、chatLanguageModel 指代大语言模型
2、chatMemory 问题和答案存储 内存缓存
3、AI service 基于他可以实现function call 和 RAG
4、embedding store
5、embedding model
6、document loader

问题:
1、如何通过java访问远程大模型,进行交互
2、langchain4j 如何做RAG
3、langchain4j 如何做function calling
4、function calling 思路
5、embedding model如何选择?,langchain4j如何接入
6、文档如何切割?才能让语义更加完整,进行向量匹配才能更加准确
7、如何编写长文档?

展示代码,运行测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/3234.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pandas 模块-操纵数据(11)-二元运算--超级add、sub、mul、div、mod、pow等等

目录 1. DataFrame.add 1.1 DataFrame.add 语法结构 1.2 DataFrame.add 参数说明 1.3 DataFrame.add 用法示例 1.3.1 正常的使用 1.3.2 需要注意类型相符合 2. DataFrame.sub 2.1 DataFrame.sub 语法结构 2.2 DataFrame.sub 参数说明 2.3 DataFrame.sub 用法示例 3.…

传媒论坛编辑部传媒论坛杂志社传媒论坛杂志2024年第7期目录

专题│场景传播研究 场景传播&#xff1a;一场遮盖自我与寻找自我的博弈 胡沈明; 3 基于CiteSpace的中国场景传播研究热点分析 管倩;粟银慧; 4-610《传媒论坛》投稿&#xff1a;cnqikantg126.com 数字世界的美与危&#xff1a;场景传播的失范与应对之举 王依晗;章洁…

分布式-知识体系

分布式系统 本质就是一堆机器的协同&#xff0c;要做的就是用各种手段来让机器的运行达到预期 分布式业务场景 分布式四纵四横说 基于 MSA&#xff08;微服务架构&#xff09;的分布式知识体系 相关概念 – 【摘自网络原文】 节点与网络 节点 传统的节点也就是一台单体的物…

MySQL数据类型:字符串类型详解

MySQL数据类型&#xff1a;字符串类型详解 在MySQL数据库中&#xff0c;字符串数据类型用于存储各种文本信息。这些数据类型主要包括CHAR、VARCHAR、TEXT和BLOB等。 CHAR与VARCHAR CHAR CHAR类型用于存储固定长度的字符串。它的长度在创建表时就已确定&#xff0c;长度范围…

QJ71C24N-R2 三菱Q系列串行通信模块

三菱Q系列串行通信模块是通过串行通信用的RS-232、RS-422/485线路将对方设备与Q系列可编程控制器CPU相连接,以实现如下所示的数据通信的模块。通过使用调制解调器/终端适配器,可以利用公共线路(模拟/数字)实现与远程设备间的数据通信。 QJ71C24N-R2参数说明&#xff1a;串行RS-…

为什么36KbRAM会配置为32K×1,少的那4Kb去哪了?

首先我们需要了解BRAM的相关知识&#xff0c;可以参考下面两篇文章&#xff1a; Xinlinx FPGA内的存储器BRAM全解-CSDN博客 为何有时简单双口RAM是真双口RAM资源的一半-CSDN博客 本问题的背景是&#xff1a; 每个36Kb块RAM也可以配置成深度宽度为64K 1(当与相邻的36KB块RA…

淘宝新店没有流量和访客怎么办

淘宝新店没有流量和访客时&#xff0c;可以采取以下措施来提升店铺的流量和吸引更多的访客&#xff1a; 3an推客是给商家提供的营销工具&#xff0c;3an推客CPS推广模式由商家自主设置佣金比例&#xff0c;以及设置商品优惠券&#xff0c;激励推广者去帮助商家推广商品链接&…

SVG 绘制微信订阅号icon

效果 代码 <!DOCTYPE html> <html> <body><svg xmlns"http://www.w3.org/2000/svg" version"1.1" width"600" height"600"><rect x"0" y"0" rx"0" ry"0" width&…

JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 UDP 通信 1.1 DatagramSocket 类 1.2 DatagramPacket 类 1.3 实现 UDP 通信&#xff08;一发一收&#xff09; 1.3.1 客户端的开发 1.3.2 服务端的开发 1.4 实现 …

Arm功耗管理精讲与实战

安全之安全(security)博客目录导读 思考 1、为什么要功耗管理&#xff1f;SOC架构中功耗管理示例&#xff1f;功耗管理挑战&#xff1f; 2、从单核->多核->big.LITTLE->DynamIQ&#xff0c;功耗管理架构演进? 3、什么是电压域&#xff1f;什么是电源域&#xff1f…

C++高级特性:异常概念与处理机制(十四)

1、异常的基本概念 异常&#xff1a;是指在程序运行的过程中发生的一些异常事件&#xff08;如&#xff1a;除数为0&#xff0c;数组下标越界&#xff0c;栈溢出&#xff0c;访问非法内存等&#xff09; C的异常机制相比C语言的异常处理&#xff1a; 函数的返回值可以忽略&…

《系统架构设计师教程(第2版)》第10章-软件架构的演化和维护-01-软件架构演化概述

文章目录 1. 演化的重要性2. 架构演化示例 教材中&#xff0c;本节名为&#xff1a;“软件架构演化和定义的关系” 1. 演化的重要性 演化目的&#xff1a;维持软件架构自身的有用性 为什么说&#xff0c;软件架构是演化来的&#xff0c;而不是设计来的&#xff1f; 软件架构的…

【LAMMPS学习】八、基础知识(4.3)TIP3P水模型

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

Python 基础 (Pandas):Pandas 入门

1. 官方文档 API reference — pandas 2.2.2 documentation 2. 准备知识&#xff1a;Pandas 数据结构 Series & DataFrame 2.1 Series 2.1.1 创建 Series 类型数据 一个 Series 对象包含两部分&#xff1a;值序列、标识符序列。可通过 .values (返回 NumPy ndarry 类型…

Fisher 准则分类

目录 一、什么是Fisher 准则 二、具体实例 三、代码实现 四、结果 一、什么是Fisher 准则 Fisher准则&#xff0c;即Fisher判别准则&#xff08;Fisher Discriminant Criterion&#xff09;&#xff0c;是统计学和机器学习中常用的一种分类方法&#xff0c;由统计学家罗纳…

C语言指针进阶:各类型指针变量详解

目录 1. 字符指针变量2. 数组指针变量2.1 什么是数组指针变量2.2 数组指针变量的初始化 3. 二维数组传参的本质4. 函数指针变量4.1 函数指针变量的创建4.2 函数指针变量的使用4.3 代码分析4.3.1 typedef 关键字 5. 函数指针数组6. 转移表 正文开始。 1. 字符指针变量 我们可以…

【WP】猿人学12_入门级js

https://match.yuanrenxue.cn/match/12 Fiddler分析发现&#xff0c;所有请求只是 page已经 m不一样 这个m看起来就很像 base64&#xff0c;解码发现确实如此 下面直接构建Python代码&#xff1a; import base64import requestsdef base64_encode_string(input_string):try:#…

搞嵌入式到底属于程序员吗?

搞嵌入式到底属不属于程序员呢&#xff1f;毫无疑问&#xff0c;当然算啊&#xff01;而且我十分赞同另一位朋友所说的&#xff1a;嵌入式程序员是难得的全栈型程序员。尽管嵌入式领域方向众多且繁杂&#xff0c;但他们同样也是会写代码的程序员。 嵌入式行业主要分为硬件和软…

LeetCode-219. 存在重复元素 II

题目描述 给你一个整数数组 nums 和一个整数 k &#xff0c;判断数组中是否存在两个 不同的索引 i 和 j &#xff0c;满足 nums[i] nums[j] 且 abs(i - j) < k 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&…

【写一个简单的service and client(C++)例子——services】

文章目录 1、概要2、引言3、服务开始的地方及步骤3.1 创建工作空间3.2 创建功能包3.3 更新package.xml3.4 编写service 节点3.4.1 添加可执行文件3.4.2 添加 install&#xff08;TARGETS…&#xff09; 部分 3.5 编写client 节点3.5.1 添加可执行文件 3.6 编译运行3.7 运行结果…