部署Qwen2.5-7b大模型详解

部署Qwen2.5-7b大模型详解

本文参考教程:https://qwen.readthedocs.io/en/latest/getting_started/quickstart.html

下载模型

https://modelscope.cn/organization/qwen

搜索 qwen2.5-7b

在这里插入图片描述

可以看到它提供了六个模型,以满足不同的需求,从下载量来看,Qwen2.5-7B-Instruct 远超其他五个。

1、预训练 (Pre-training) 和基模型 (Base models): 是基础语言模型,不建议直接使用基础语言模型进行对话任务。您可以在此模型基础上进行后训练,例如SFT、RLHF、持续预训练等。基础模型不带Instruct字样,你可以对其进行情景学习,下游微调等。

2、后训练 (Post-training) 和指令微调模型 (Instruction-tuned models): 是专门设计用于理解并以对话风格执行特定指令的模型。这些模型经过微调,能准确地解释用户命令,并能以更高的准确性和一致性执行诸如摘要、翻译和问答等任务。与在大量文本语料库上训练的基础模型不同,指令调优模型会使用包含指令示例及其预期结果的数据集进行额外训练,通常涵盖多个回合。这种训练方式使它们非常适合需要特定功能的应用,同时保持生成流畅且连贯文本的能力。

-Instruct模型就是之前的-Chat模型。

3、GGUF: 以GGUF格式保存的模型,用于 llama.cpp。

4、AWQ量化,GPTQ量化: 属于经过量化算法优化后的版本,意在降低部署门槛,后面介绍。

显存要求

一般而言,模型加载所需显存可以按参数量乘二计算,例如,7B 模型需要 14GB 显存加载,其原因在于,对于大语言模型,计算所用数据类型为16位浮点数。当然,推理运行时还需要更多显存以记录激活状态。

对于 transformers ,推荐加载时使用 torch_dtype="auto" ,这样模型将以 bfloat16 数据类型加载。否则,默认会以 float32 数据类型加载,所需显存将翻倍。也可以显式传入 torch.bfloat16torch.float16 作为 torch_dtype

关于多卡推理

transformers 依赖 accelerate 支持多卡推理,其实现为一种简单的模型并行策略:不同的卡计算模型的不同层,分配策略由 device_map="auto" 或自定义的 device_map 指定。

然而,这种实现方式并不高效,因为对于单一请求而言,同时只有单个 GPU 在进行计算而其他 GPU 则处于等待状态。为了充分利用所有的 GPU ,你需要像流水线一样安排多个处理序列,确保每个 GPU 都有一定的工作负载。但是,这将需要进行并发管理和负载均衡,这些超出了 transformers 库的范畴。即便实现了所有这些功能,整体吞吐量可以通过提高并发提高,但每个请求的延迟并不会很理想。

对于多卡推理,建议使用专门的推理框架,如 vLLM 和 TGI,这些框架支持张量并行。

INFERENCE 推理

1、Hugging Face Transformers

https://qwen.readthedocs.io/zh-cn/latest/inference/chat.html

transformers 支持手动和Pipeline两种作业方式。

支持继续对话,流式输出

2、ModelScope

ModelScope的用法与Transformers基本一样,就是下载安装快一些,在使用时将包名由transformers改成modelscope即可。

https://github.com/modelscope/modelscope

https://www.modelscope.cn/docs

RUN LOCALLY 运行模型

1、llama.cpp

https://qwen.readthedocs.io/zh-cn/latest/run_locally/llama.cpp.html

https://github.com/ggerganov/llama.cpp

https://www.cnblogs.com/ghj1976/p/18063411/gguf-mo-xing

它是一个用来运行大模型的工具,其特点是以最小的代价来启动模型进行推理,它允许LLM在CPU上运行和推理。

The main goal of llama.cpp is to enable LLM inference with minimal setup and state-of-the-art performance on a wide variety of hardware - locally and in the cloud.

  • 纯粹的C/C++实现,没有外部依赖
  • 支持广泛的硬件:
    • x86_64 CPU的AVX、AVX2和AVX512支持
    • 通过Metal和Accelerate支持Apple Silicon(CPU和GPU)
    • NVIDIA GPU(通过CUDA)、AMD GPU(通过hipBLAS)、Intel GPU(通过SYCL)、昇腾NPU(通过CANN)和摩尔线程GPU(通过MUSA)
    • GPU的Vulkan后端
  • 多种量化方案以加快推理速度并减少内存占用
  • CPU+GPU混合推理,以加速超过总VRAM容量的模型

对于不是很精通c++的使用者,主要还是使用llama-cli 工具

因此要求模型保存为GGUF格式,同时,它支持将一个大模型分割成多个文件保存。

在这里插入图片描述

2、Ollama

https://github.com/ollama/ollama

https://ollama.com/

Go语言开发的,类似于docker一样的工具,用来管理和运行LLM。它利用了 llama.cpp 提供的底层功能,它不仅支持gguf,还支持pt(PyTorch)和 safetensors(Tensorflow)。

它支持以 CLI 和 API 的方式运行LLM。

Ollama并不托管基模型。即便模型标签不带instruct后缀,实际也是instruct模型。

Ollama也可以运行已保存在本地的模型。

需要区分一下:LLaMa 是一个Meta公司开源的预训练大型语言模型,llama.cpp用于加载和运行GGUF语言模型。Ollama是大模型运行框架。

WEB UI

Text Generation Web UI(简称TGW)

git clone https://github.com/oobabooga/text-generation-webui
cd text-generation-webui

你可以根据你的操作系统直接运行相应的脚本,例如在Linux系统上运行 start_linux.sh ,在Windows系统上运行 start_windows.bat ,在MacOS系统上运行 start_macos.sh ,或者在Windows子系统Linux(WSL)上运行 start_wsl.bat

访问:http://localhost:7860/?__theme=dark

DEPLOYMENT 部署

1、vLLM

vLLM是伯克利大学LMSYS组织开源的大语言模型高速推理框架,旨在极大地提升实时场景下的语言模型服务的吞吐与内存使用效率。vLLM是一个快速且易于使用的库,用于 LLM 推理和服务,可以和HuggingFace 无缝集成。vLLM利用了全新的注意力算法「PagedAttention」,有效地管理注意力键和值。吞吐量最多可以达到 huggingface 实现的24倍,文本生成推理(TGI)高出3.5倍,并且不需要对模型结构进行任何的改变。vLLM 库要比 HaggingFace Transformers库的推理速度高出一倍左右。

使用vLLM运行Qwen大模型:https://qwen.readthedocs.io/en/latest/deployment/vllm.html

vLLM 文档:https://docs.vllm.ai/en/stable/

要部署 Qwen2.5 ,我们建议您使用 vLLM 。 vLLM 是一个用于 LLM 推理和服务的快速且易于使用的框架。

# vLLM>=0.4.0pip install vllm# 构建一个与 OpenAI 兼容的 API 服务
python -m vllm.entrypoints.openai.api_server --model Qwen/Qwen2.5-7B-Instruct

vllm>=0.5.3 ,也可以如下启动:

vllm serve Qwen/Qwen2.5-7B-Instruct

默认情况下,它将在 http://localhost:8000 启动服务器。您可以通过 --host--port 参数来自定义地址。

curl http://localhost:8000/v1/chat/completions -H "Content-Type: application/json" -d '{"model": "Qwen/Qwen2.5-7B-Instruct","messages": [{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},{"role": "user", "content": "Tell me something about large language models."}],"temperature": 0.7,"top_p": 0.8,"repetition_penalty": 1.05,"max_tokens": 512
}'

或者您可以按照下面所示的方式,使用 openai Python 包中的 Python 客户端:

from openai import OpenAI
# Set OpenAI's API key and API base to use vLLM's API server.
openai_api_key = "EMPTY"
openai_api_base = "http://localhost:8000/v1"client = OpenAI(api_key=openai_api_key,base_url=openai_api_base,
)chat_response = client.chat.completions.create(model="Qwen/Qwen2.5-7B-Instruct",messages=[{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},{"role": "user", "content": "Tell me something about large language models."},],temperature=0.7,top_p=0.8,max_tokens=512,extra_body={"repetition_penalty": 1.05,},
)
print("Chat response:", chat_response)

也可以使用 vLLM 包来运行大模型。

from transformers import AutoTokenizer
from vllm import LLM, SamplingParams# Initialize the tokenizer
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")# Pass the default decoding hyperparameters of Qwen2.5-7B-Instruct
# max_tokens is for the maximum length for generation.
sampling_params = SamplingParams(temperature=0.7, top_p=0.8, repetition_penalty=1.05, max_tokens=512)# Input the model name or path. Can be GPTQ or AWQ models.
llm = LLM(model="Qwen/Qwen2.5-7B-Instruct")# Prepare your prompts
prompt = "Tell me something about large language models."
messages = [{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},{"role": "user", "content": prompt}
]
text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True
)# generate outputs
outputs = llm.generate([text], sampling_params)# Print the outputs.
for output in outputs:prompt = output.promptgenerated_text = output.outputs[0].textprint(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")

工具(函数)使用

结构化/JSON输出

多卡分布式部署

上下文支持扩展:YaRN

部署量化模型:只需要指定参数 quantization的值

2、TGI

https://qwen.readthedocs.io/en/latest/deployment/tgi.html

Hugging Face 的 Text Generation Inference (TGI) 是一个专为部署大规模语言模型 (Large Language Models, LLMs) 而设计的生产级框架。TGI提供了流畅的部署体验,并稳定支持如下特性:

  • 推测解码 (Speculative Decoding) :提升生成速度。
  • 张量并行 (Tensor Parallelism) :高效多卡部署。
  • 流式生成 (Token Streaming) :支持持续性生成文本。
  • 灵活的硬件支持:与 AMD , Gaudi 和 [AWS Inferentia](https://aws.amazon.com/blogs/machine-learning/announcing-the-launch-of-new-hugging-face-llm-inference-containers-on-amazon-sagemaker/#:~:text=Get started with TGI on SageMaker Hosting) 无缝衔接。

以docker的方式,通过TGI部署Qwen2.5

model=Qwen/Qwen2.5-7B-Instruct
volume=$PWD/data # share a volume with the Docker container to avoid downloading weights every rundocker run --gpus all --shm-size 1g -p 8080:80 -v $volume:/data ghcr.io/huggingface/text-generation-inference:2.0 --model-id $model

访问

curl http://localhost:8080/generate_stream -H 'Content-Type: application/json' \-d '{"inputs":"Tell me something about large language models.","parameters":{"max_new_tokens":512}}'

也可使用 OpenAI 风格的 API 访问TGI,注意,JSON 中的 model 字段不会被 TGI 识别,您可传入任意值。

curl http://localhost:8080/v1/chat/completions -H "Content-Type: application/json" -d '{"model": "","messages": [{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},{"role": "user", "content": "Tell me something about large language models."}],"temperature": 0.7,"top_p": 0.8,"repetition_penalty": 1.05,"max_tokens": 512
}'

完整 API 文档,请查阅 [TGI Swagger UI](https://huggingface.github.io/text-generation-inference/#/Text Generation Inference/completions) 。

你也可以使用 Python 访问

from openai import OpenAI# initialize the client but point it to TGI
client = OpenAI(base_url="http://localhost:8080/v1/",  # replace with your endpoint urlapi_key="",  # this field is not used when running locally
)
chat_completion = client.chat.completions.create(model="",  # it is not used by TGI, you can put anythingmessages=[{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},{"role": "user", "content": "Tell me something about large language models."},],stream=True,temperature=0.7,top_p=0.8,max_tokens=512,
)# iterate and print stream
for message in chat_completion:print(message.choices[0].delta.content, end="")

多卡分布式部署

部署量化模型:只需要指定参数--quantize gptq

QUANTIZATION

0、量化

大语言模型(LLM)在自然语言处理(NLP)任务中取得了显著的进展。然而,LLM 通常具有非常大的模型大小和计算复杂度,这限制了它们在实际应用中的部署。

量化是将浮点数权重转换为低精度整数的过程,可以显著减少模型的大小和计算复杂度。近年来,LLM 量化的研究取得了很大进展,出现了许多新的量化方法。

GPTQ 和 AWQ 是目前最优的 LLM 量化方法之一。GPTQ 是 Google AI 提出的一种基于 group 量化和 OBQ 方法的量化方法。AWQ 是 Facebook AI 提出的一种基于 activation-aware 方法的量化方法。

1、GPTQ

GPTQ是一种针对类GPT大型语言模型的量化方法,它基于近似二阶信息进行一次性权重量化。

GPTQ 的工作原理如下:

  1. 首先,GPTQ 使用 group 量化将权重分组为多个子矩阵。
  2. 然后,GPTQ 使用 OBQ 方法来量化每个子矩阵。
  3. 最后,GPTQ 使用动态反量化来恢复权重的原始值。

GPTQ 的改进主要体现在以下几个方面:

  • 分组量化:GPTQ 使用分组量化来将权重分组为多个子矩阵,这可以降低量化精度损失。
  • OBQ 方法:GPTQ 使用 OBQ 方法来量化权重,该方法可以实现高精度的量化。
  • 动态反量化:GPTQ 使用动态反量化来恢复权重的原始值,这可以提高量化的性能。

GPTQ 在各种 LLM 上进行了实验,结果表明,GPTQ 可以实现 3/4 位量化,在相同精度下,GPTQ 的模型大小比原始模型小 1/4。

vLLM 和 Hugging Face transformers 均已支持了 GPTQ 量化模型,用法和普通的模型是一样的。

使用AutoGPTQ来对您自己的模型进行量化处理。

2、AWQ

AWQ 的工作原理如下:

  1. 首先,AWQ 使用 group 量化将权重分组为多个子矩阵。
  2. 然后,AWQ 使用 activation-aware 的方法来量化每个子矩阵。
  3. 最后,AWQ 使用无重新排序的在线反量化来提高量化性能。

AWQ 的 activation-aware 方法可以提高量化精度,这是因为激活值在量化后的影响可以通过量化系数进行补偿。具体来说,AWQ 首先计算每个子矩阵的激活分布,然后使用该分布来生成量化系数。

AWQ 的无重新排序的在线反量化可以提高量化性能,这是因为它不需要对权重进行重新排序,可以直接在量化后的权重上进行反量化。

AWQ 在各种 LLM 上进行了实验,结果表明,AWQ 可以实现 3/4 位量化,在相同精度下,AWQ 的模型大小比原始模型小 1/4,推理速度比 GPTQ 快 1.45 倍。

vLLM 和 Hugging Face transformers 均已支持了 AWQ 量化模型,用法和普通的模型是一样的。

如果您希望将自定义的模型量化为AWQ量化模型,我们建议您使用AutoAWQ。

git clone https://github.com/casper-hansen/AutoAWQ.git
cd AutoAWQ
pip install -e .

假设你已经基于 Qwen2.5-7B 模型进行了微调,并将其命名为 Qwen2.5-7B-finetuned ,且使用的是你自己的数据集,比如Alpaca。若要构建你自己的AWQ量化模型,你需要使用训练数据进行校准。以下,我们将为你提供一个简单的演示示例以便运行:

from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer# Specify paths and hyperparameters for quantization
model_path = "your_model_path"
quant_path = "your_quantized_model_path"
quant_config = { "zero_point": True, "q_group_size": 128, "w_bit": 4, "version": "GEMM" }# Load your tokenizer and model with AutoAWQ
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoAWQForCausalLM.from_pretrained(model_path, device_map="auto", safetensors=True)

接下来,您需要准备数据以进行校准。您需要做的就是将样本放入一个列表中,其中每个样本都是一段文本。由于我们直接使用微调数据来进行校准,所以我们首先使用ChatML模板对其进行格式化。例如:

data = []
for msg in dataset:text = tokenizer.apply_chat_template(msg, tokenize=False, add_generation_prompt=False)data.append(text.strip())

其中每个 msg 是一个典型的聊天消息,如下所示:

[{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},{"role": "user", "content": "Tell me who you are."},{"role": "assistant", "content": "I am a large language model named Qwen..."}
]

然后只需通过一行代码运行校准过程:

model.quantize(tokenizer, quant_config=quant_config, calib_data=data)

最后,保存量化模型:

model.save_quantized(quant_path, safetensors=True, shard_size="4GB")
tokenizer.save_pretrained(quant_path)

然后你就可以得到一个可以用于部署的AWQ量化模型。

3、AWQ与GPTQ比较
特征AWQGPTQ
量化精度优秀良好
模型大小最小较小
计算速度最快较快
实现难度较易较难
量化成本较高较低

AWQ 在量化精度、模型大小和计算速度方面都优于 GPTQ,但在量化成本方面略高。

有监督微调:LLaMA-Factory

我们将介绍如何使用 LLaMA-Factory 微调 Qwen2.5 模型。本脚本包含如下特点:

  • 支持单卡和多卡分布式训练
  • 支持全参数微调、LoRA、Q-LoRA 和 DoRA 。

https://qwen.readthedocs.io/zh-cn/latest/training/SFT/llama_factory.html

FRAMEWORK 框架

https://qwen.readthedocs.io/zh-cn/latest/framework/function_call.html

函数调用

为了解决大语言模型的局限性,就需要模型在处理用户需求的过程中可以去调用指定的工具,这里具体就是函数,比如查天气,数学运算等等。

其实现流程是:

  1. 定义函数,定义函数描述json schema。
  2. 与LLM对话,将你的需求和上面的函数定义传给LLM,它会返回你该调用什么函数。
  3. 你自己调用函数。
  4. 将计算结果追加到message中再次丢给LLM,让其整合为最终的结果。

以 qwen-agent 框架为例。

1、定义函数,定义函数描述 TOOLS

import jsondef get_current_temperature(location: str, unit: str = "celsius"):"""Get current temperature at a location.Args:location: The location to get the temperature for, in the format "City, State, Country".unit: The unit to return the temperature in. Defaults to "celsius". (choices: ["celsius", "fahrenheit"])Returns:the temperature, the location, and the unit in a dict"""return {"temperature": 26.1,"location": location,"unit": unit,}def get_temperature_date(location: str, date: str, unit: str = "celsius"):"""Get temperature at a location and date.Args:location: The location to get the temperature for, in the format "City, State, Country".date: The date to get the temperature for, in the format "Year-Month-Day".unit: The unit to return the temperature in. Defaults to "celsius". (choices: ["celsius", "fahrenheit"])Returns:the temperature, the location, the date and the unit in a dict"""return {"temperature": 25.9,"location": location,"date": date,"unit": unit,}def get_function_by_name(name):if name == "get_current_temperature":return get_current_temperatureif name == "get_temperature_date":return get_temperature_dateTOOLS = [{"type": "function","function": {"name": "get_current_temperature","description": "Get current temperature at a location.","parameters": {"type": "object","properties": {"location": {"type": "string","description": 'The location to get the temperature for, in the format "City, State, Country".',},"unit": {"type": "string","enum": ["celsius", "fahrenheit"],"description": 'The unit to return the temperature in. Defaults to "celsius".',},},"required": ["location"],},},},{"type": "function","function": {"name": "get_temperature_date","description": "Get temperature at a location and date.","parameters": {"type": "object","properties": {"location": {"type": "string","description": 'The location to get the temperature for, in the format "City, State, Country".',},"date": {"type": "string","description": 'The date to get the temperature for, in the format "Year-Month-Day".',},"unit": {"type": "string","enum": ["celsius", "fahrenheit"],"description": 'The unit to return the temperature in. Defaults to "celsius".',},},"required": ["location", "date"],},},},
]
MESSAGES = [{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant.\n\nCurrent Date: 2024-09-30"},{"role": "user",  "content": "What's the temperature in San Francisco now? How about tomorrow?"},
]

2、请求LLM

functions = [tool["function"] for tool in TOOLS]for responses in llm.chat(messages=messages,functions=functions,extra_generate_cfg=dict(parallel_function_calls=True),
):passmessages.extend(responses)

返回信息如下

[{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_current_temperature', 'arguments': '{"location": "San Francisco, CA, USA", "unit": "celsius"}'}},{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_temperature_date', 'arguments': '{"location": "San Francisco, CA, USA", "date": "2024-10-01", "unit": "celsius"}'}},
]

3、调用函数

for message in responses:if fn_call := message.get("function_call", None):fn_name: str = fn_call['name']fn_args: dict = json.loads(fn_call["arguments"])fn_res: str = json.dumps(get_function_by_name(fn_name)(**fn_args))messages.append({"role": "function","name": fn_name,"content": fn_res,})

此时messages变成了

[{'role': 'system', 'content': 'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.\n\nCurrent Date: 2024-09-30'},{'role': 'user', 'content': "What's the temperature in San Francisco now? How about tomorrow?"},{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_current_temperature', 'arguments': '{"location": "San Francisco, CA, USA", "unit": "celsius"}'}},{'role': 'assistant', 'content': '', 'function_call': {'name': 'get_temperature_date', 'arguments': '{"location": "San Francisco, CA, USA", "date": "2024-10-01", "unit": "celsius"}'}},{'role': 'function', 'name': 'get_current_temperature', 'content': '{"temperature": 26.1, "location": "San Francisco, CA, USA", "unit": "celsius"}'},{'role': 'function', 'name': 'get_temperature_date', 'content': '{"temperature": 25.9, "location": "San Francisco, CA, USA", "date": "2024-10-01", "unit": "celsius"}'},
]

4、让LLM整合结果

for responses in llm.chat(messages=messages, functions=functions):pass
messages.extend(responses)

最终响应应如下所示

{'role': 'assistant', 'content': 'Currently, the temperature in San Francisco is approximately 26.1°C. Tomorrow, on 2024-10-01, the temperature is forecasted to be around 25.9°C.'}

Hugging Face transformers 框架调用函数

tools = TOOLS
messages = MESSAGES[:]text = tokenizer.apply_chat_template(messages, tools=tools, add_generation_prompt=True, tokenize=False)
....

剩下的过程与上面一样,具体参看上面的文档。

Ollama / vLLM 框架调用函数的过程与上面基本一致。

在这里插入图片描述

Qwen-Agent

LlamaIndex

此工具旨在为了实现 Qwen2.5 与外部数据(例如文档、网页等)的连接,以快速部署检索增强生成(RAG)技术。

以下将演示如何从文档或网站构建索引。

import torch
from llama_index.core import Settings
from llama_index.core.node_parser import SentenceSplitter
from llama_index.llms.huggingface import HuggingFaceLLM
from llama_index.embeddings.huggingface import HuggingFaceEmbedding# Set prompt template for generation (optional)
from llama_index.core import PromptTemplatedef completion_to_prompt(completion):return f"<|im_start|>system\n<|im_end|>\n<|im_start|>user\n{completion}<|im_end|>\n<|im_start|>assistant\n"def messages_to_prompt(messages):prompt = ""for message in messages:if message.role == "system":prompt += f"<|im_start|>system\n{message.content}<|im_end|>\n"elif message.role == "user":prompt += f"<|im_start|>user\n{message.content}<|im_end|>\n"elif message.role == "assistant":prompt += f"<|im_start|>assistant\n{message.content}<|im_end|>\n"if not prompt.startswith("<|im_start|>system"):prompt = "<|im_start|>system\n" + promptprompt = prompt + "<|im_start|>assistant\n"return prompt# Set Qwen2.5 as the language model and set generation config
Settings.llm = HuggingFaceLLM(model_name="Qwen/Qwen2.5-7B-Instruct",tokenizer_name="Qwen/Qwen2.5-7B-Instruct",context_window=30000,max_new_tokens=2000,generate_kwargs={"temperature": 0.7, "top_k": 50, "top_p": 0.95},messages_to_prompt=messages_to_prompt,completion_to_prompt=completion_to_prompt,device_map="auto",
)# Set embedding model
Settings.embed_model = HuggingFaceEmbedding(model_name = "BAAI/bge-base-en-v1.5"
)# Set the size of the text chunk for retrieval
Settings.transformations = [SentenceSplitter(chunk_size=1024)]

1、检索文件内容

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader# document 为文件夹,里面支持PDF和TXT格式的文件。
documents = SimpleDirectoryReader("./document").load_data()
index = VectorStoreIndex.from_documents(documents,embed_model=Settings.embed_model,transformations=Settings.transformations
)

embed_model:由来向量化数据的模型,您可以使用 bge-base-en-v1.5 模型来检索英文文档,下载 bge-base-zh-v1.5 模型以检索中文文档。根据您的计算资源,您还可以选择 bge-largebge-small 作为向量模型,或调整上下文窗口大小或文本块大小。Qwen2.5模型系列支持最大32K上下文窗口大小(7B 、14B 、32B 及 72B可扩展支持 128K 上下文,但需要额外配置)。比如BAAI/bge-base-en-v1.5

2、检索网站内容

from llama_index.readers.web import SimpleWebPageReader
from llama_index.core import VectorStoreIndex, SimpleDirectoryReaderdocuments = SimpleWebPageReader(html_to_text=True).load_data(["web_address_1","web_address_2",...]
)
index = VectorStoreIndex.from_documents(documents,embed_model=Settings.embed_model,transformations=Settings.transformations
)

要保存和加载已构建的索引,您可以使用以下代码示例。

from llama_index.core import StorageContext, load_index_from_storage# save index
storage_context = StorageContext.from_defaults(persist_dir="save")# load index
index = load_index_from_storage(storage_context)

检索增强RAG的实现

现在您可以输入查询,Qwen2.5 将基于索引文档的内容提供答案。

query_engine = index.as_query_engine()
your_query = "<your query here>"
print(query_engine.query(your_query).response)
Langchain

它是一个大模型应用框架,对很多应用场景做了封装,下面将使用Langchain与qwen2.5构建一个本地知识库问答系统。其原理为:将文件(PDF或TXT)内容分段并向量化,将其放在prompt最前面,然后连带问题一起发送给LLM,由LLM来匹配答案。

PROMPT_TEMPLATE = """Known information:{context_str}Based on the above known information, respond to the user's question concisely and professionally. If an answer cannot be derived from it, say 'The question cannot be answered with the given information' or 'Not enough relevant information has been provided,' and do not include fabricated details in the answer. Please respond in English. The question is {question}"""

具体代码如下:

from langchain.chains import RetrievalQA
from langchain.prompts.prompt import PromptTemplate
from langchain.docstore.document import Document
from langchain.text_splitter import CharacterTextSplitter
from langchain.document_loaders import TextLoader
import numpy as np
from typing import List, Tuple
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
from langchain.vectorstores import FAISS
import argparse
import torch
import re
import os
from transformers import AutoModelForCausalLM, AutoTokenizer
from abc import ABC
from langchain.llms.base import LLM
from typing import Any, List, Mapping, Optional
from langchain.callbacks.manager import CallbackManagerForLLMRun'''
您可以仅使用您的文档配合langchain来构建一个问答应用。该项目的实现流程包括:
加载文件 -> 阅读文本 -> 文本分段 -> 文本向量化 -> 问题向量化 -> 将最相似的前k个文本向量与问题向量匹配 -> 将匹配的文本作为上下文连同问题一起纳入提示 -> 提交给Qwen2.5-7B-Instruct生成答案。
''''''
pip install langchain==0.0.174
pip install faiss-gpu
'''model_name = "Qwen/Qwen2.5-7B-Instruct"model = AutoModelForCausalLM.from_pretrained(model_name,torch_dtype="auto",device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_name)class Qwen(LLM, ABC):max_token: int = 10000temperature: float = 0.01top_p = 0.9history_len: int = 3def __init__(self):super().__init__()@propertydef _llm_type(self) -> str:return "Qwen"@propertydef _history_len(self) -> int:return self.history_lendef set_history_len(self, history_len: int = 10) -> None:self.history_len = history_lendef _call(self,prompt: str,stop: Optional[List[str]] = None,run_manager: Optional[CallbackManagerForLLMRun] = None,) -> str:messages = [{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},{"role": "user", "content": prompt}]text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True)model_inputs = tokenizer([text], return_tensors="pt").to(model.device)generated_ids = model.generate(**model_inputs,max_new_tokens=512)generated_ids = [output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)]response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]return response@propertydef _identifying_params(self) -> Mapping[str, Any]:"""Get the identifying parameters."""return {"max_token": self.max_token,"temperature": self.temperature,"top_p": self.top_p,"history_len": self.history_len}class ChineseTextSplitter(CharacterTextSplitter):def __init__(self, pdf: bool = False, **kwargs):super().__init__(**kwargs)self.pdf = pdfdef split_text(self, text: str) -> List[str]:if self.pdf:text = re.sub(r"\n{3,}", "\n", text)text = re.sub('\s', ' ', text)text = text.replace("\n\n", "")sent_sep_pattern = re.compile('([﹒﹔﹖﹗.。!?]["’”」』]{0,2}|(?=["‘“「『]{1,2}|$))')sent_list = []for ele in sent_sep_pattern.split(text):if sent_sep_pattern.match(ele) and sent_list:sent_list[-1] += eleelif ele:sent_list.append(ele)return sent_listdef load_file(filepath):loader = TextLoader(filepath, autodetect_encoding=True)textsplitter = ChineseTextSplitter(pdf=False)docs = loader.load_and_split(textsplitter)write_check_file(filepath, docs)return docsdef write_check_file(filepath, docs):folder_path = os.path.join(os.path.dirname(filepath), "tmp_files")if not os.path.exists(folder_path):os.makedirs(folder_path)fp = os.path.join(folder_path, 'load_file.txt')with open(fp, 'a+', encoding='utf-8') as fout:fout.write("filepath=%s,len=%s" % (filepath, len(docs)))fout.write('\n')for i in docs:fout.write(str(i))fout.write('\n')fout.close()def separate_list(ls: List[int]) -> List[List[int]]:lists = []ls1 = [ls[0]]for i in range(1, len(ls)):if ls[i - 1] + 1 == ls[i]:ls1.append(ls[i])else:lists.append(ls1)ls1 = [ls[i]]lists.append(ls1)return listsclass FAISSWrapper(FAISS):chunk_size = 250chunk_conent = Truescore_threshold = 0def similarity_search_with_score_by_vector(self, embedding: List[float], k: int = 4) -> List[Tuple[Document, float]]:scores, indices = self.index.search(np.array([embedding], dtype=np.float32), k)docs = []id_set = set()store_len = len(self.index_to_docstore_id)for j, i in enumerate(indices[0]):if i == -1 or 0 < self.score_threshold < scores[0][j]:# This happens when not enough docs are returned.continue_id = self.index_to_docstore_id[i]doc = self.docstore.search(_id)if not self.chunk_conent:if not isinstance(doc, Document):raise ValueError(f"Could not find document for id {_id}, got {doc}")doc.metadata["score"] = int(scores[0][j])docs.append(doc)continueid_set.add(i)docs_len = len(doc.page_content)for k in range(1, max(i, store_len - i)):break_flag = Falsefor l in [i + k, i - k]:if 0 <= l < len(self.index_to_docstore_id):_id0 = self.index_to_docstore_id[l]doc0 = self.docstore.search(_id0)if docs_len + len(doc0.page_content) > self.chunk_size:break_flag = Truebreakelif doc0.metadata["source"] == doc.metadata["source"]:docs_len += len(doc0.page_content)id_set.add(l)if break_flag:breakif not self.chunk_conent:return docsif len(id_set) == 0 and self.score_threshold > 0:return []id_list = sorted(list(id_set))id_lists = separate_list(id_list)for id_seq in id_lists:for id in id_seq:if id == id_seq[0]:_id = self.index_to_docstore_id[id]doc = self.docstore.search(_id)else:_id0 = self.index_to_docstore_id[id]doc0 = self.docstore.search(_id0)doc.page_content += " " + doc0.page_contentif not isinstance(doc, Document):raise ValueError(f"Could not find document for id {_id}, got {doc}")doc_score = min([scores[0][id] for id in [indices[0].tolist().index(i) for i in id_seq if i in indices[0]]])doc.metadata["score"] = int(doc_score)docs.append((doc, doc_score))return docsif __name__ == '__main__':# load docs (pdf file or txt file)filepath = 'your file path'# Embedding model nameEMBEDDING_MODEL = 'text2vec'PROMPT_TEMPLATE = """Known information:{context_str}Based on the above known information, respond to the user's question concisely and professionally. If an answer cannot be derived from it, say 'The question cannot be answered with the given information' or 'Not enough relevant information has been provided,' and do not include fabricated details in the answer. Please respond in English. The question is {question}"""# Embedding running deviceEMBEDDING_DEVICE = "cuda"# return top-k text chunk from vector storeVECTOR_SEARCH_TOP_K = 3CHAIN_TYPE = 'stuff'embedding_model_dict = {"text2vec": "your text2vec model path",}llm = Qwen()embeddings = HuggingFaceEmbeddings(model_name=embedding_model_dict[EMBEDDING_MODEL], model_kwargs={'device': EMBEDDING_DEVICE})docs = load_file(filepath)docsearch = FAISSWrapper.from_documents(docs, embeddings)prompt = PromptTemplate(template=PROMPT_TEMPLATE, input_variables=["context_str", "question"])chain_type_kwargs = {"prompt": prompt,"document_variable_name": "context_str"}qa = RetrievalQA.from_chain_type(llm=llm,chain_type=CHAIN_TYPE,retriever=docsearch.as_retriever(search_kwargs={"k": VECTOR_SEARCH_TOP_K}),chain_type_kwargs=chain_type_kwargs)query = "Give me a short introduction to large language model."print(qa.run(query))

BENCHMARK 基准测试

1、关于GPU内存需求及相应吞吐量的结果

https://qwen.readthedocs.io/en/latest/benchmark/speed_benchmark.html

对于vLLM,由于GPU显存预分配,实际显存使用难以评估。

在这里插入图片描述

在这里插入图片描述

2、对于量化的模型,与原始 bfloat16 模型的基准测试结果

https://qwen.readthedocs.io/en/latest/benchmark/quantization_benchmark.html

  • MMLU (准确率)
  • C-Eval (准确率)
  • IFEval (提示词级的严格准确率,Strict Prompt-Level Accuracy)

在这里插入图片描述

其他阅读

https://mp.weixin.qq.com/s/Gn8kV04e_Y_BmXdxSMBiSQ

https://mp.weixin.qq.com/s/Fy-dNFOf-KhAMTJnBwjICQ

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

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

相关文章

【RoadRunner】自动驾驶模拟3D场景构建 | 软件简介与视角控制

&#x1f4af; 欢迎光临清流君的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落 &#x1f4af; &#x1f525; 个人主页:【清流君】&#x1f525; &#x1f4da; 系列专栏: 运动控制 | 决策规划 | 机器人数值优化 &#x1f4da; &#x1f31f;始终保持好奇心&…

【MATLAB代码,带TDOA数据导入】TDOA三维空间的位置(1主锚点、3副锚点),多个时间点、输出位置的坐标

TDOA介绍 TDOA&#xff08;到达时间差&#xff09;是一种用于定位和跟踪信号源的技术&#xff0c;常用于无线通信、导航和雷达系统。它通过测量信号到达不同接收器的时间差&#xff0c;来计算信号源的位置。 基本原理 TDOA的基本原理是利用多个接收器&#xff08;或锚点&…

Power BI - 设置Waterfall Chart第一个Pillar的颜色

1.简单介绍 有的用户可能会单独设置Column Chart&#xff08;条形图&#xff09;的第一个柱子的颜色&#xff0c;如下图所示&#xff0c; 这种其实可以通过Column Chart的Conditional formating进行设置&#xff0c; - SWICH SELECTEDVALUE 或者也可以直接对单独的Column进行…

用户界面设计:视觉美学与交互逻辑的融合

1、什么是用户界面 用户界面&#xff08;UI&#xff09;是人与机器之间沟通的桥梁&#xff0c;同时也是用户体验&#xff08;UX&#xff09;的重要组成部分。用户界面设计包括两个核心要素&#xff1a;视觉设计&#xff08;即产品的外观和感觉&#xff09;和交互设计&#xff…

CSS 入门

1. CSS 1.1 概念 CSS&#xff08;Cascading Style Sheet&#xff09;&#xff0c;层叠样式表&#xff0c;用于控制页面的样式 CSS 能够对网页中元素位置的排版进行像素级精确控制&#xff0c;实现美化页面的效果&#xff0c;能够做到页面的样式和结构分离&#xff08;类似于…

【数字图像处理】第5章 图像空域增强方法

上理考研周导师的哔哩哔哩频道 我在频道里讲课哦 目录 5.1 图像噪声 相关概念 ①图像噪声的产生 ② 图像噪声分类 ③ 图像噪声特点 5.2 图像增强方法分类 ①图像增强概念 ②图像增强目的 ③图像增强技术方法: 5.3 基于灰度变换的图像增强 1. 概述: 2. 灰度变换…

十大云手机排行榜:哪个云手机更好用?

近些年&#xff0c;市场上涌现出许多云手机产品&#xff0c;不同产品适合的应用场景也各不相同。在选用云手机之前&#xff0c;企业和个人用户需要了解它们的功能、特点以及适用的场景。本文将对当前主流的云手机进行对比&#xff0c;帮助大家挑选出最适合的云手机产品。 1. 红…

【数据结构与算法】之链表详解

链表是一种常用的数据结构&#xff0c;它是一种线性数据结构&#xff0c;但与数组不同&#xff0c;它并非连续存储数据&#xff0c;而是通过指针将数据节点连接起来。每个节点都包含数据域和指向下一个节点的指针域。这种结构赋予链表独特的优势和局限性&#xff0c;使其在某些…

九种排序,一次满足

我们在算法题进行练习提升时&#xff0c;经常会看到题目要求数据从大到小输出&#xff0c;从小到大输出&#xff0c;前一半从小到大输出&#xff0c;后一半从大到小输出等&#xff0c;那么这时候就需要用到排序算法&#xff0c;通过排序算法将数据按照一定的顺序进行排序。本文…

解决PyCharm 2023 Python Packages列表为空

原因是因为没有设置镜像源 展开 > 之后&#xff0c;这里 点击齿轮 添加一个阿里云的源 最后还需要点击刷新 可以选择下面的任意一个国内镜像源&#xff1a; 清华&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple 阿里云&#xff1a;http://mirrors.aliyun.com/…

设计模式之-策略模式配合枚举

1、定义枚举接收不同的参数使用不同的handler, 2、定义个handerl接口&#xff0c;统一方法处理&#xff0c;每个handler实现该接口 public interface IMethodHandler<T, R> {/*** 处理统一入口** param req*/R process(T req); } java3、定义一个简单工厂统一处理 Comp…

送给正在入行的小白:最全最有用的网络安全学习路线已经安排上了,零基础入门到精通,收藏这一篇就够了

在这个圈子技术门类中&#xff0c;工作岗位主要有以下三个方向&#xff1a; 安全研发安全研究&#xff1a;二进制方向安全研究&#xff1a;网络渗透方向 下面逐一说明一下。 第一个方向&#xff1a;安全研发 你可以把网络安全理解成电商行业、教育行业等其他行业一样&#xf…

k8s 1.28.2 集群部署 harbor v2.11.1 接入 MinIO 对象存储

文章目录 [toc]提前准备什么是 HarborHarbor 架构描述Harbor 安装的先决条件硬件资源软件依赖端口依赖 Harbor 在 k8s 的高可用Harbor 部署Helm 编排YAML 编排创建 namespace导入镜像部署 Redis部署 PostgreSQL部署 Harbor core部署 Harbor trivy部署 Harbor jobservice部署 Ha…

RTSP流图片采样助手(yolov5)

在监控和视频分析领域&#xff0c;实时采样视频流中的图像数据是十分重要的。本文将介绍一个基于Python和Tkinter构建的RTSP流图片采样助手的设计与实现&#xff0c;旨在简化RTSP流的采样过程&#xff0c;并支持根据用户定义的特殊标签进行筛选。 项目概述 该项目的主要功能包…

Data+AI下的数据湖和湖仓一体发展史

DataAI下的数据湖和湖仓一体发展史 前言数据湖的“前世今生”AI时代的救星&#xff1a;湖仓一体湖仓一体实践演进未来趋势&#xff1a;智能化、实时化结语 前言 数据湖&#xff1f;湖仓一体&#xff1f;这是什么高科技新名词&#xff1f; 别急&#xff0c;我们慢慢聊。想象一…

ICT产业新征程:深度融合与高质量发展

在信息时代的浪潮中&#xff0c;每一场关于技术革新与产业融合的盛会都闪耀着智慧的光芒&#xff0c;引领着未来的方向。9月25日&#xff0c;北京国家会议中心内&#xff0c;一场聚焦全球信息通信业的顶级盛事——第32届“国际信息通信展”&#xff08;PT展&#xff09;隆重拉开…

Maven基于构建阶段分析多余的依赖

基于构建阶段 test compile 实现依赖分析 执行maven 命令: mvn dependency:analyze 关注:Maven-dependency-plugin 分析结果: [INFO] --- maven-dependency-plugin:2.10:analyze (default-cli) impl --- 配置依赖未使用的依赖项&#xff1a; [INFO] --- maven-dependency-…

Linux基础项目开发day2:量产工具——输入系统

文章目录 前言一、数据结构抽象1、数据本身2、设备本身3、input_manager.h 二、触摸屏编程1、touchscreen.c 三、触摸屏单元测试1、touchscreen.c2、上机测试 四、网络编程netiput.c 五、网络单元测试1、netiput.c2、client.c3、上机测试 六、输入系统的框架1、框架思路2、inpu…

数据库设计与开发—初识SQLite与DbGate

一、SQLite与DbGate简介 &#xff08;一&#xff09;SQLite[1][3] SQLite 是一个部署最广泛、用 C 语言编写的数据库引擎&#xff0c;属于嵌入式数据库&#xff0c;其作为库被软件开发人员嵌入到应用程序中。 SQLite 的设计允许在不安装数据库管理系统或不需要数据库管理员的情…

sublime配置(竞赛向)

我也想要有jiangly一样的sublime 先决条件 首先&#xff0c;到官网上下载最新的sublime4&#xff0c;然后在mingw官网上下载最新的mingw64 mingw64官网&#xff1a;左边菜单栏点击dowloads,然后选择MinGW-W64-builds(可能会有点慢)——然后有时候会变成选LLVM-minGW,接着选择…