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

news2024/11/14 18:12:56

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).parameters
    tool_params = []
    for name, param in python_params.items():
        annotation = param.annotation
        if 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_def

    return 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 requests
    try:
        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 traceback
        ret = "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.arguments
        function_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 torch

DEVICE = "cuda"
DEVICE_ID = "0"
CUDA_DEVICE = f"{DEVICE}:{DEVICE_ID}" if DEVICE_ID else DEVICE


def 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, tokenizer
    json_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 answer


if __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.coloradmin.cn/o/1616808.html

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

相关文章

在数字化转型过程中,企业的资产管理需要做出哪些调整?

在数字化转型过程中&#xff0c;企业的资产管理做出调整的常见于以下几个方面&#xff1a; 1、提高工作效率&#xff1a;数字化转型能够让员工在部门与部门之间的沟通更加顺畅&#xff0c;节省时间&#xff0c;提高效率。这要求企业在资产管理中采用数字化工具和流程&#xff…

高中数学:三角函数之考点精华-单调性问题

一、解题方法 1、换元 2、画图 3、反向求解 参考&#xff1a;整体换元法 二、练习 例题1 解析&#xff1a; 这一题&#xff0c;比较简单&#xff0c;是标准的换元法应用题。 这里稍微注意下第二小问的对称中心&#xff0c;因为&#xff0c;B1&#xff0c;所以&#xff0c;对…

单机三pxc节点集群,+docker-haproxy2.0负载均衡实现

一.下载 https://www.haproxy.org/download/2.0/src/haproxy-2.0.5.tar.gz 或者在这里下载&#xff08;下面需要的各个配置文件都有&#xff09;&#xff1a; https://download.csdn.net/download/cyw8998/89170129 二.编写文件&#xff0c;制作docker镜像 1.Dockerfile&a…

恒峰智慧科技—森林消防泵,你了解多少?

在我们的日常生活中&#xff0c;森林火灾是一种非常危险的现象。为了保护森林资源和人民的生命财产安全&#xff0c;森林消防泵成为了一种非常重要的设备。那么&#xff0c;你对森林消防泵了解多少呢&#xff1f;本文将为您详细介绍森林消防泵的操作步骤、注意事项以及维护保养…

第⑮讲:Ceph集群管理与监控操作指南

文章目录 1.查看集群的状态信息2.动态的查看集群的状态信息3.查看集群的利用率4.查看OSD的资源利用率5.查看OSD的列表6.查看各组件的状态7.查看集群的仲裁信息8.查看/修改集群组件sock的配置参数 1.查看集群的状态信息 通过集群状态信息可以看到集群的健康状态、各个组件的运行…

Spark 中的分桶分化

Spark 中的分桶分化 Bucketing是 Spark 和 Hive 中用于优化任务性能的一种技术。在分桶桶&#xff08;集群列&#xff09;中确定数据分区并防止数据混洗。根据一个或多个分桶列的值&#xff0c;将数据分配给预定义数量的桶。 分桶有两个主要好处&#xff1a; 改进的查询性能&…

jvm(JVM快速入门、stack栈、堆、GC垃圾回收、Arthas)

文章目录 1. JVM快速入门1.1. 结构图1.2. 类加载器ClassLoader1.3. 执行引擎Execution Engine1.4. 本地接口Native Interface1.5. Native Method Stack1.6. PC寄存器(程序计数器)1.7. Method Area方法区 2. stack栈3. 堆3.1. 堆体系概述3.1.1. 新生区3.1.2. 老年代3.1.3. 永久代…

2024统计建模:大数据与人工智能时代的统计研究

文章目录 题目解读你需要具备的知识点课题推荐视频分析 题目解读 主要做的是“大数据”与“人工智能”。 其中“大数据”所涉及的的第一个就是大量的数据&#xff0c;数据从哪里来&#xff1f;拿到数据后&#xff0c;我们需要做基本的数据分析&#xff0c;如何对大量的数据进…

【UnityShader]使用Shader将图片进行水平/竖直镜像翻转

一、需求 在开发时从很多地方取出来的图片可能并不是图像原本的模样&#xff0c;可能是被水平或者竖直镜像翻转后的图形&#xff0c;这时候我们要将图片再次镜像回来&#xff0c;只需要一个小小的Shader即可。 二、实现 下面是镜像翻转Shader的思路: 一般来说我们在顶点着色…

C++奇迹之旅:从0开始实现日期时间计算器

文章目录 &#x1f4dd;前言&#x1f320; 头文件Date.h&#x1f309;日期计算函数&#x1f320;前后置&#x1f309;前后置-- &#x1f320;两对象日期相减&#x1f309;自定义流输入和输出 &#x1f309; 代码&#x1f309; 头文件Date.h&#x1f320;Date.cpp&#x1f309; …

ECALL介绍

一、ECALL关键词介绍 ECALL:Emergency Call,紧急呼叫 PSTN:Public Switched Telephone Network MSD:Minimum Set of Data PLMN: Public Land Mobile Network PASP:Public Safety Answering Point IVS: in-vehicle system(车载系统)是内部的调制解调器,以全双工的方式…

【漏洞复现】手机卡号推广商城 login.php接口处存在 SQL 注入漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

STM32应用开发教程进阶--UART串口重定向(printf)

实现目标 1、掌握STM32 HAL库的串口重定向 2、具体目标&#xff1a;1、实现printf “打印”各种常用的类型的数据变量 一、串口“打印” UART串口通信协议是我们常用的通信协议&#xff08;UART、I2C、SPI等&#xff09;之一&#xff0c;全称叫做通用异步收发传输器&#xf…

卷积神经网络CNN入门

卷积神经网络应用领域 因为卷积神经网络主要应用场景就是计算机视觉任务&#xff0c;因此有必要简单介绍一下CV领域发展情况&#xff1a; 可以发现&#xff0c;在 ImageNet 图像数据集中分析图像的错误率十年间已经被深度学习给降低到了比人类&#xff08;HuMan&#xff09;识…

阿里云短信渠道专属优惠价格,全网最便宜入口

阿里云短信渠道专属优惠&#xff0c;1000条短信30元、2000条短信优惠价格60元、3000元短信套餐包价格90元、5000短信优惠150元&#xff0c;活动页面 aliyunbaike.com/go/duanxin 链接打开如下图&#xff1a; 阿里云短信渠道专属优惠价格 阿里云短信支持国内快速发送验证码、通…

算法——BFS算法

1. 什么是BFS算法 BFS&#xff08;广度优先搜索&#xff0c;Breadth-First Search&#xff09;算法是一种用于图和树等数据结构中进行搜索的基本算法。它从指定的起始节点开始&#xff0c;逐层地向外扩展搜索&#xff0c;直到找到目标节点或遍历完整个图。 BFS算法的基本思想是…

R可视化:桑基图展示数据层流动

介绍 以桑基图形式展示数据分布情况 加载R包 knitr::opts_chunk$set(message = FALSE, warning = FALSE) library(tidyverse) library(ggalluvial)# rm(list = ls()) options(stringsAsFactors = F) options(future.globals.maxSize = 10000 * 1024^2) 导入数据 metadata…

【Qt 学习笔记】Qt常用控件 | 显示类控件 | Label的使用及说明

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 显示类控件 | Label的使用及说明 文章编号&#xff1a;Q…

CentOS 系统的优缺点

CentOS &#xff08;社区企业操作系统的缩写&#xff09;是一个基于红帽企业 Linux (RHEL)的免费开源发行版&#xff0c; 旨在为服务器和工作站提供稳定、可靠和安全的平台。 不应将其与CentOS Stream 混淆&#xff0c;后者是即将发布的 RHEL 版本的上游开发平台。 CentOS Li…

虚拟化及Docker基础

一、虚拟化 1.1 云端 1.2 云计算服务模式分层 1.3 虚拟化架构 1.3.1 寄居架构 1.3.2 原生架构 1.4 虚拟化产品 1.4.1 仿真虚拟化产品&#xff08;对系统硬件没有要求&#xff0c;性能最低&#xff09; 1.4.2 半虚拟化 &#xff08;虚拟机可以使用真机物理机&#xff09…