动手点关注
干货不迷路
本文旨在让无大模型开发背景的工程师或者技术爱好者无痛理解大语言模型应用开发的理论和主流工具,因此会先从与LLM应用开发相关的基础概念谈起,并不刻意追求极致的严谨和完备,而是从直觉和本质入手,结合笔者调研整理及消化理解,帮助大家能够更容易的理解LLM技术全貌,大家可以基于本文衍生展开,结合自己感兴趣的领域深入研究。若有不准确或者错误的地方也希望大家能够留言指正。
本文体系完整,内容丰富,由于内容比较多,分多次连载 。
第一部分 基础概念
1.机器学习场景类别
2.机器学习类型(LLM相关)
3.深度学习的兴起
4.基础模型
第二部分 应用挑战
1.问题定义与基本思路
2.基本流程与相关技术
1)Tokenization与Embbeding
2)向量数据库
3)finetune(微调)
4)模型部署与推理
5)prompt
6)编排与集成
7)预训练
第三部分 场景案例
常用参考
2.基本流程与相关技术
4)模型部署与推理
模型服务层相关工具和框架
前文对模型服务层做了简单的分类,基于封装程度不同,有大量的框架和工具,笔者结合目前趋势,在每个类别中挑选了几个常见的项目和大家分享,它们各有特点,将从内向外一一介绍,最后给出一些选型建议以供参考。
从架构层面考虑,由于web服务和模型服务,在技术栈和开发者上都存在一定的差异性,所以一般会将二者拆分开,以便各司其职,针对性优化,另一方面,通过引入Inference Server的概念,可以让开发者不需要关心具体执行引擎和模型的细节,下层的引擎和模型对开发者透明,这样可以简化部署模型服务的复杂度。下面我们介绍三个较为流行的Inference Server供大家参考。
Triton Server
前面我们提到了tensorRT和tensorRTLLM,而triton早年便是为了运行tensorRT模型而设计的,故曾经的名字叫做TensorRT serving,而随着架构层面的不断优化以及能力的扩展,triton Server不在只是支持tensorRT模型,而是作为一个公共的模型服务后端而存在,能够运行多种深度学习和机器学习框架的模型,如ONNX,Tensorflow,pytorch,openVINO等,甚至前面提到的vLLM。在部署上,支持在英伟达GPU、x86 和 ARM CPU 或 AWS Inferentia 上跨云、数据中心、边缘和嵌入式设备。支持,不同的推理类型,包括批/实时,音频视频流等,以及简单的前后置处理这样的编排能力。得益于英伟达软硬一体优化,以及常见的推理优化手段,如动态批处理,并发执行。作为商业级方案,Triton的性能和稳定性都非常不错,现已经是模型服务的主流选型之一。
在架构上由triton Server和Model Repository构成。Model Repository是一个基于文件系统的模型库,Triton 将提供这些模型供推理使用。推理请求通过 HTTP/REST、GRPC 或 C API 到达服务器,然后被路由到相应的模型调度器。Triton 实现了多种调度和批处理算法,可按模型进行配置。每个模型的调度器可选择对推理请求进行批处理,然后将请求传递给与模型类型相对应的后端。后端使用批处理请求中提供的输入执行推理,生成请求的输出,然后返回输出结果。
架构不仅具备高吞吐的特点,并且具备较强的扩展性和开放性,可以与 Kubernetes 轻松集成,用于编排、metrics 和 autoscaling 等。Triton 还与主流的MLops工具集成,如 Kubeflow 和 KServe 集成以实现端到端的 AI 工作流,并导出 Prometheus 指标以监控 GPU 利用率、延迟、内存使用和推理吞吐量。它支持标准的 HTTP/gRPC 接口来连接负载均衡器(load balancer)等其他应用程序,并且可以轻松扩展到任意数量的服务器,来为任意模型处理日益增长的推理负载。Triton 可以服务数十个、甚至上百个模型。模型可以根据需求变化加载到推理服务中或从推理服务中卸载,以适应 GPU 或 CPU 的内存。同时,支持具有 GPU 和 CPU 的异构集群以实现跨平台推理,并可以动态扩展到任何 CPU 或 GPU 以处理峰值负载。
部署tritonserver一般的流程分两步,第一步创建模型库(Model Repository),模型库是Triton 拉取模型的目录。其格式为:
<model-repository-path>/
<model-name>/
[config.pbtxt]
[<output-labels-file> ...]
<version>/
<model-definition-file>
<version>/
<model-definition-file>
...
<model-name>/
[config.pbtxt]
[<output-labels-file> ...]
<version>/
<model-definition-file>
<version>/
<model-definition-file>
...
...
其可以使用下面命令指定具体的模型库,其路径可以是本地路径,s3,gcp等:
tritonserver --model-repository=<model-repository-path>
另外,Triton是有模型版本的概念,因此目录里至少要有一个数字子目录,代表着模型的版本。类似:
<model-repository-path>/
<model-name>/
config.pbtxt
1/
model.plan
这里面必须包含config.pbtxt,它是triton服务的配置文件,包含了有关模型的相关信息。基本最小配置如:
platform: "tensorrt_plan"
max_batch_size: 8
input [
{
name: "input0"
data_type: TYPE_FP32
dims: [ 16 ]
},
{
name: "input1"
data_type: TYPE_FP32
dims: [ 16 ]
}
]
output [
{
name: "output0"
data_type: TYPE_FP32
dims: [ 16 ]
}
]
配置文件包含Name,Platform,BackEnd,一些模型策略如Decoupled,max_batch_size等,以及输入输出的定义。
Triton能够自动推导TensorRT,TensorFlow,ONNX和OpenVINO模型配置。对于Python模型,可以在 Python 后端实现 auto_complete_config 函数,使用 set_max_batch_size、add_input 和 add_output 函数提供 max_batch_size、输入和输出属性。这些属性将允许 Triton 在没有配置文件的情况下,使用 "最小模型配置"加载 Python 模型。其他的模型类型都必须提供模型配置文件。
我们下面使用官方的model repository来说明:
$ git clone git@github.com:triton-inference-server/server.git
$ cd docs/examples
$ ./fetch_models.sh
#拉取后的目录结构
model_repository/
-- densenet_onnx
|-- 1
| -- model.onnx
|-- config.pbtxt
|-- densenet_labels.txt
第二步,运行triton:
docker run --gpus=1 --rm -p8000:8000 -p8001:8001 -p8002:8002 -v/full/path/to/docs/examples/model\_repository:/models nvcr.io/nvidia/tritonserver:<xx.yy>-py3 tritonserver --model-repository=/models
其中,<xx.yy> 是要使用的 Triton 版本。启动 Triton 后,会在控制台上看到服务器启动并加载模型的输出。当看到如下输出时,Triton 已经准备好接受推理请求了。
检查运行状态:
$ curl -v localhost:8000/v2/health/ready
...
< HTTP/1.1 200 OK
< Content-Length: 0
< Content-Type: text/plain
使用客户端发送推理请求:
docker pull nvcr.io/nvidia/tritonserver:<xx.yy>-py3-sdk
docker run -it --rm --net=host nvcr.io/nvidia/tritonserver:<xx.yy>-py3-sdk
+----------------------+---------+--------+
| Model | Version | Status |
+----------------------+---------+--------+
| <model_name> | <v> | READY |
| .. | . | .. |
| .. | . | .. |
+----------------------+---------+--------+
...
...
...
I1002 21:58:57.891440 62 grpc_server.cc:3914] Started GRPCInferenceService at 0.0.0.0:8001
I1002 21:58:57.893177 62 http_server.cc:2717] Started HTTPService at 0.0.0.0:8000
I1002 21:58:57.935518 62 http_server.cc:2736] Started Metrics Service at 0.0.0.0:8002
docker exec 进入该容器,运行示例图像客户端应用程序,使用示例 densenet_onnx 模型执行图像分类。
$ /workspace/install/bin/image_client -m densenet_onnx -c 3 -s INCEPTION /workspace/images/mug.jpg
Request 0, batch size 1
Image '/workspace/images/mug.jpg':
15.346230 (504) = COFFEE MUG
13.224326 (968) = CUP
10.422965 (505) = COFFEEPO
有了前面的概念,这里介绍一个vllm+triton的大模型推理部署例子。
1)打包一个包含vLLM的triton镜像。
Dockerfile:
FROM nvcr.io/nvidia/tritonserver:23.08-py3
RUN pip install vllm==0.1.7
打包:
docker build -t tritonserver\_vllm .
2)创建模型库
目录结构如下:
model_repository/
`-- vllm
|-- 1
| `-- model.py
|-- config.pbtxt
|-- vllm_engine_args.json
其中,model.py为python版本的模型文件, 在vllm_engine_args.json中可以设置HuggingFace上的模型。
{
"model": "facebook/opt-125m",
"disable_log_requests": "true",
"gpu_memory_utilization": 0.5
}
3)启动triton服务
docker run --gpus all -it --rm -p 8001:8001 --shm-size=1G --ulimit memlock=-1 --ulimit stack=67108864 -v ${PWD}:/work -w /work tritonserver\_vllm tritonserver --model-store ./model\_repository
如果成功有如下输出:
I0901 23:39:08.729123 1 grpc_server.cc:2451] Started GRPCInferenceService at 0.0.0.0:8001
I0901 23:39:08.729640 1 http_server.cc:3558] Started HTTPService at 0.0.0.0:8000
I0901 23:39:08.772522 1 http_server.cc:187] Started Metrics Service at 0.0.0.0:8002
4)使用client请求推理服务。
利用triton SDK container发送请求。
docker run -it --net=host -v ${PWD}:/workspace/ nvcr.io/nvidia/tritonserver:23.08-py3-sdk bash
进入容器运行client.py,它会读取镜像中的实例prompt.txt,发送给tritonserver:
python3 client.py
prompt.txt
Hello, my name is
The most dangerous animal is
The capital of France is
The future of AI is
输出:
Loading inputs from `prompts.txt`...
Storing results into `results.txt`...
PASS: vLLM example
RayLLM
RayLLM,原名为Aviary,是一个基于 Ray Serve 的 LLM 服务解决方案,可轻松部署和管理各种开源 LLM。可以看出,它是Ray针对于大模型开发的一个新方案,吸取众家之长,在其上搭载了当下领先的推理引擎,包含TGI和vLLM,天然继承它们的推理优化策略,获得更好的吞吐量和更低的延迟,再利用强大的Ray serve能力,原生支持自动扩展和多节点部署。RayLLM 可以扩展到零,并根据需求创建新的模型副本(每个副本由多个 GPU Worker 组成)。因而,它将会是当下重要的候选之一。
它最大特点是集成度高,流程标准化,预置了常见的开源LLM套件,默认开箱即用,Huggingface Hub及本地磁盘上的Transformer模型都可以使用,对整个部署使用流程都做了简化,做到了模型部署统一化,相较于推理引擎来讲,不用关心分布式部署的问题。另外,对外提供的类似OpenAI风格的接口,很方便的进行基础模型切换和评估比较。
rayLLM启动LLM服务时,需要提供模型服务配置文件。并且可以支持多个模型根据path路由。配置文件格式形如:
# File name: serve/config.yaml
applications:
- name: router
route_prefix: /
import_path: aviary.backend:router_application
args:
models:
amazon/LightGPT: ./models/continuous_batching/amazon--LightGPT.yaml
meta-llama/Llama-2-7b-chat-hf: ./models/continuous_batching/meta-llama--Llama-2-7b-chat-hf.yaml
- name: amazon--LightGPT
route_prefix: /amazon--LightGPT
import_path: aviary.backend:llm_application
args:
model: "./models/continuous_batching/amazon--LightGPT.yaml"
- name: meta-llama--Llama-2-7b-chat-hf
route_prefix: /meta-llama--Llama-2-7b-chat-hf
import_path: aviary.backend:llm_application
args:
model: "./models/continuous_batching/meta-llama--Llama-2-7b-chat-hf.yaml"
model文件中定义着具体的模型服务策略,包含deployment_config,engine_config,scaling_config三部分,新建一个model需要新增一个yaml文件,名字符合----.yaml规范,例如:meta-llama--Llama-2-13b-chat-hf.yaml,具体内容可以在这个模版上修改完善:
# true by default - you can set it to false to ignore this model
# during loading
enabled: true
deployment_config:
# This corresponds to Ray Serve settings, as generated with
# `serve build`.
autoscaling_config:
min_replicas: 1
initial_replicas: 1
max_replicas: 8
target_num_ongoing_requests_per_replica: 1.0
metrics_interval_s: 10.0
look_back_period_s: 30.0
smoothing_factor: 1.0
downscale_delay_s: 300.0
upscale_delay_s: 90.0
ray_actor_options:
# Resources assigned to each model deployment. The deployment will be
# initialized first, and then start prediction workers which actually hold the model.
resources:
accelerator_type_cpu: 0.01
engine_config:
# Model id
model_id: mosaicml/mpt-7b-instruct
# Id of the model on Hugging Face Hub. Can also be a disk path. Defaults to model_id if not specified.
hf_model_id: mosaicml/mpt-7b-instruct
# TGI and transformers keyword arguments passed when constructing the model.
model_init_kwargs:
trust_remote_code: true
# This is a metadata field that is used to display information about the model in the UI.
model_description: mosaic mpt 7b is a transformer trained from scratch...
# This is a metadata field that is used to display information about the model in the UI.
model_url: https://www.mosaicml.com/blog/mpt-7b
# Optional Ray Runtime Environment configuration. See Ray documentation for more details.
# Add dependent libraries, environment variables, etc.
runtime_env:
env_vars:
YOUR_ENV_VAR: "your_value"
# Optional configuration for loading the model from S3 instead of Hugging Face Hub. You can use this to speed up downloads or load models not on Hugging Face Hub.
s3_mirror_config:
bucket_uri: s3://large-dl-models-mirror/models--mosaicml--mpt-7b-instruct/main-safetensors/
# Parameters for configuring the scheduler. See above for more details.
scheduler:
policy:
max_batch_prefill_tokens: 58000
max_batch_total_tokens: 140000
max_input_length: 2048
max_iterations_curr_batch: 20
max_total_tokens: 4096
type: QuotaBasedTaskSelectionPolicy
waiting_served_ratio: 1.2
generation:
# Default kwargs passed to `model.generate`. These can be overrided by a
# user's request.
generate_kwargs:
do_sample: true
max_new_tokens: 512
min_new_tokens: 16
top_p: 1.0
top_k: 0
temperature: 0.1
repetition_penalty: 1.1
# Prompt format to wrap queries in. {instruction} refers to user-supplied input.
prompt_format:
system: "{instruction}\n" # System message. Will default to default_system_message
assistant: "### Response:\n{instruction}\n" # Past assistant message. Used in chat completions API.
trailing_assistant: "### Response:\n" # New assistant message. After this point, model will generate tokens.
user: "### Instruction:\n{instruction}\n" # User message.
default_system_message: "Below is an instruction that describes a task. Write a response that appropriately completes the request." # Default system message.
# Stopping sequences. The generation will stop when it encounters any of the sequences, or the tokenizer EOS token.
# Those can be strings, integers (token ids) or lists of integers.
stopping_sequences: ["### Response:", "### End"]
# Resources assigned to each model replica. This corresponds to Ray AIR ScalingConfig.
scaling_config:
# If using multiple GPUs set num_gpus_per_worker to be 1 and then set num_workers to be the number of GPUs you want to use.
num_workers: 1
num_gpus_per_worker: 1
num_cpus_per_worker: 4
resources_per_worker:
# You can use custom resources to specify the instance type / accelerator type
# to use for the model.
accelerator_type_a10: 0.01
如果是私有模型,不在huggingface上,可以在engine_config上修改,如:
# 本地路径
engine_config:
model_id: YOUR_MODEL_NAME
hf_model_id: YOUR_MODEL_LOCAL_PATH
# s3
engine_config:
model_id: YOUR_MODEL_NAME
s3_mirror_config:
bucket_uri: s3://YOUR_BUCKET_NAME/YOUR_MODEL_FOLDER
在部署层面,rayLLM支持本地和ray cluster。为了避免安装依赖问题,官方建议本地运行也直接使用镜像启动。
cache_dir=${XDG_CACHE_HOME:-$HOME/.cache}
docker run -it --gpus all --shm-size 1g -p 8000:8000 -e HF_HOME=~/data -v $cache_dir:~/data anyscale/aviary:latest bash
# Inside docker container
aviary run --model ~/models/continuous_batching/amazon--LightGPT.yaml
在ray cluster部署,首先需要启动ray集群,它可以是本地集群,也可以是通过kubeRay部署在k8s上。具体可参考:https://github.com/ray-project/ray-llm/blob/master/docs/kuberay/deploy-on-eks.md。 客户端发送推理请求,可以直接参考openAI的风格,也可以直接使用OpenAI的SDK。
RayLLM目前还比较新,在行业上还不算特别热门,但相信随着生产级场景不断增多,加上RAY在大模型上的发力,RayLLM还是会有不错的发展空间。
OpenLLM
OpenLLM定位于RayLLM一样,旨在统一整个模型部署推理过程,并且屏蔽基础LLM的差异性,在此技术将复杂的推理技术封装在框架内部,简化整个生产落地LLM的复杂度,进而提升LLM应用构建的复杂度。该项目社区热度及完成度相较于RayLLM来讲都更高,在架构上,OpenLLM更开放,并不耦合具体的底层部署框架,但由于是BentoML发起的,能够无缝的部署到BentoCloud上。同样,它集成了当前流行的LLM,如llama2,ChatGLM,StarCoder等,在生态集成上,与langchain,huggingface,BentoML都有很好的整合,能够方便的构建端到端的LLM应用。在推理优化上,支持长江的量化,流输出,动态批处理等能力。还有一个特色功能,支持以统一的API(LLM.tuning())finetune模型。
该框架安装使用比较简单。安装使用方法如下:
pip install openllm
$ openllm -h
Usage: openllm [OPTIONS] COMMAND [ARGS]...
██████╗ ██████╗ ███████╗███╗ ██╗██╗ ██╗ ███╗ ███╗
██╔═══██╗██╔══██╗██╔════╝████╗ ██║██║ ██║ ████╗ ████║
██║ ██║██████╔╝█████╗ ██╔██╗ ██║██║ ██║ ██╔████╔██║
██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║██║ ██║ ██║╚██╔╝██║
╚██████╔╝██║ ███████╗██║ ╚████║███████╗███████╗██║ ╚═╝ ██║
╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝╚══════╝╚══════╝╚═╝ ╚═╝.
An open platform for operating large language models in production.
Fine-tune, serve, deploy, and monitor any LLMs with ease.
Options:
-v, --version Show the version and exit.
-h, --help Show this message and exit.
Commands:
build Package a given models into a Bento.
embed Get embeddings interactively, from a terminal.
import Setup LLM interactively.
instruct Instruct agents interactively for given tasks, from a...
models List all supported models.
prune Remove all saved models, (and optionally bentos) built with...
query Ask a LLM interactively, from a terminal.
start Start any LLM as a REST server.
start-grpc Start any LLM as a gRPC server.
Extensions:
build-base-container Base image builder for BentoLLM.
dive-bentos Dive into a BentoLLM.
get-containerfile Return Containerfile of any given Bento.
get-prompt Get the default prompt used by OpenLLM.
list-bentos List available bentos built by OpenLLM.
list-models This is equivalent to openllm models...
playground OpenLLM Playground.
启动LLM服务,服务端口3000:
openllm start opt #opt是一个Meta出品的类似于GPT3的开源大模型
利用openLLM内置的client即可访问服务:
import openllm
client = openllm.client.HTTPClient('http://localhost:3000')
client.query('Explain to me the difference between "further" and "farther"')
也可以直接使用命令行访问:
export OPENLLM_ENDPOINT=http://localhost:3000
openllm query 'Explain to me the difference between "further" and "farther"'
OpenLLM 也可以通过提供 --model-id 选项指定基础模型的变体,比如不同的参数量或者微调模型:
openllm start opt --model-id facebook/opt-2.7b
在默认情况下,OpenLLM 不包含运行所有模型的依赖项。所以需要使用以下方式安装模型的依赖项。以baichuan为例:
安装依赖:
pip install "openllm[baichuan]"
然后启动验证:
openllm start baichuan --model-id baichuan-inc/baichuan-13b-base
export OPENLLM_ENDPOINT=http://localhost:3000
openllm query 'What are large language models?'
baichuan支持的一些变体,可以通过--model-id指定。
- baichuan-inc/baichuan-7b
- baichuan-inc/baichuan-13b-base
- baichuan-inc/baichuan-13b-chat
- fireballoon/baichuan-vicuna-chinese-7b
- fireballoon/baichuan-vicuna-7b
- hiyouga/baichuan-7b-sft
- 其他基于BaiChuanForCausalLM 架构的模型
可以通过--backend设置执行引擎后端:
pyTorch(默认)
openllm start baichuan --model-id baichuan-inc/baichuan-13b-base --backend pt
vLLM:
pip install "openllm[baichuan, vllm]"
openllm start baichuan --model-id baichuan-inc/baichuan-13b-base --backend vllm
另外,使用--workers-per-resource 选项指定每个资源分配的worker数量,在多个 GPU 上启动模型服务器。例如,如果您有 4 个可用的 GPU,您可以将值设为 1 除以数量,这样就只会生成一个 Runner 服务器实例。
openllm start opt --workers-per-resource 0.25
小结
目前推理服务器层面,由于长期的积累和沉淀,tritonServer目前是大多数人的选择,然而rayLLM和OpenLLM各有特点,且面向大模型应用设计,在使用上也更加简洁,随着未来功能和稳定性不断加强,想必也会获得更大的开发者青睐。
未完待续。。。
鉴于篇幅原因,在下一篇中将继续介绍一些主流的chatServer,它们更加高阶和易用,开箱即用,很值得初入LLM的开发者选择,欢迎关注。
合集目录:
3)微调
4)模型部署与推理
一文探秘LLM应用开发(8)-模型部署与推理(DEMO验证)
一文探秘LLM应用开发(9)-模型部署与推理(模型适配优化之GPU面面观-1)
一文探秘LLM应用开发(10)-模型部署与推理(模型适配优化之GPU面面观-2)
一文探秘LLM应用开发(11)-模型部署与推理(模型大小与推理性能的关系)
一文探秘LLM应用开发(12)-模型部署与推理(大模型相关参数计算及性能分析)
一文探秘LLM应用开发(15)-模型部署与推理(框架工具-推理执行引擎(HF pipeline))