大模型本地部署及langchain接入

概要:总结ollama、vllm部署大模型的特点、步骤及注意事项。langchain接入本地大模型可能遇到的问题。

零、基础准备

如果你只有CPU,只想做一些简单测试,那么这步可以跳过。如果你想使用GPU,则需要先安装驱动。Windows就去官网下载安装包,如:NVIDIA-GRID-WHQL-512.95.exe。ubuntu推荐在【软件和更新】里的【附件驱动】里选择你要的版本,一键安装。通过命令行安装比较麻烦,容易出错。

一、ollama

ollama部署大模型,过程比较简单,不易出错。但缺点是并发性能较差,前段时间还爆出安全性问题。适合个人或实验阶段。支持llama、deepseek、千问等模型,框架支持mac、Linux、Windows。

mac和windows安装应用,可视化操作,没什么额外需要讲的。这里总结基于容器的部署。

1、拉取官方镜像

docker pull ollama/ollama

 如果不了解docker的,可以先看下这篇总结:

docker安装使用基础_docker 安装使用-CSDN博客

2、创建容器

# -v 是路径挂载,主要为了同步模型文件。/llm/models是宿主机的路径,名字无所谓
docker run -d --gpus=all -v /llm/models:/llm/models -v /llm/ollama:/root/.ollama -p 22515:11434 --restart=always --name ollama ollama/ollama

3、启动模型

# 进入容器
docker exec -it ollama /bin/bash/
# 执行,会自动下载模型文件,也可以自行下载后上传,将deepseek-r1:70b替换为你的路径
ollama run deepseek-r1:70b

 4、使用

启动后会自动进入对话窗,可以做一些简单测试。另外,默认开启API接口,使用postman测试如下:(注意:我对外的端口不是默认的11434)

二、vllm

相对于ollama,vllm部署大模型稍微复杂一点。但优势在于能够更好的使用多张显卡,提供多种加速推理的技术,如混合精度(FP16)和张量并行(Tensor Parallelism)等。推理速度和并发性能更强,适合企业正式部署。

1、拉取包含驱动的基础镜像

其实最复杂的就是驱动的问题,所以有现成的镜像可用,直接解决了一半问题。如果不想研究版本的,可以直接参考我的。

# 更多版本详见https://catalog.ngc.nvidia.com/orgs/nvidia/containers/cuda-dl-base/tags
docker pull nvcr.io/nvidia/24.10-cuda12.6-devel-ubuntu22.04

2、创建容器

# --mount 路径挂载的另一种方式
docker run --restart=unless-stopped --mount type=bind,source=/AI-Agent/models,target=/AI-Agent/models --gpus all --name ai_model -p 22525:22525 -it your_image_id /bin/bash

3、配置容器环境

# 安装python环境,推荐conda
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh  
# 创建一个新的python环境
conda create --name python311 python=3.11.11
conda activate python311
# 安装vllm
pip install vllm==0.8.0

4、启动模型

前面创建容器时,做了路径挂载,你需要把下载好的模型放到这个路径。

(Qwen3建议使用vllm0.9.0)

# CUDA_VISIBLE_DEVICES:指定使用的显卡编号
# tensor-parallel-size:张量并行数,和前面指定的显卡对应
# swap-space:每个GPU配置的内存交换 G,主要考虑显存波动时,需要动态CPU支持
# --cpu-offload-gb:直接卸载一部分权重到CPU,对响应速度影响较大
# max-num-seqs:并发数
# gpu-memory-utilization:每张显卡占用的上限
# --dtype half:半精度,可选参数值:auto,half,float16,bfloat16,float,float32
#               float16,bfloat16都是16位,首位表示正负,剩下15位。float16:5+10,bfloat16:8+7
#               float16能表示的数值范围较小,但小数位更多,精度更高
# --max-model-len:单个输入token长度限制
# --max_num_batched_tokens:总吞吐量,考虑并发请求
# --enable-lora:开启lora,通过矩阵分解降低参数量
# --kv-cache-dtype:设置kv缓存精度,如fp8,也可降低显存需求
# --served-model-name:取一个名字,默认是路径名字,调用接口时需要传递
# --quantization:量化方式:aqlm,awq,deepspeedfp,tpu_int8,fp8等
# --enable-reasoning --reasoning-parser deepseek_r1/qwen3 需要深度思考并指定解析方式
# --enable-auto-tool-choice --tool-call-parser hermes 需要工具解析
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python -m vllm.entrypoints.openai.api_server --model /AI-Agent/models/deepseek-r1-70b --port 22525 --tensor-parallel-size 8 --swap-space 16 --max-num-seqs 16 --gpu-memory-utilization 0.8 --dtype half --max-model-len 10240 --served-model-name dsk70b

5、调用接口

因为vllm的接口部分使用的是fastapi,其提供了一个文档接口,其中v1/chat就是对话窗口。兼容langchain中的ChatOpenAI接口。

 三、问题解决

1、启动时写入临时文件失败

如果你跟着上述步骤操作,那么大概率会遇到NCCL运行错误,通过增加参NCCL_DEBUG=INFO可以大致看到,启动时往路径/dev/shm写入文件失败。这是因为这个文件夹是默认的临时文件夹,容量受限,可以根据自己的模型大小修改。

重新生成容器:

docker run --shm-size=128G ……

 模型启动后,通过nvidia-smi命令查看显卡占用情况:

 2、分词器下载失败

如果将本地模型接入Agent,并且使用langchain_openai.ChatOpenAI去接入该服务。会涉及一个token计算过程,如果遇到下载失败或你的环境不允许访问外网,会出现如下报错信息:

File "/root/anaconda3/lib/python3.11/site-packages/tiktoken_ext/openai_public.py", line 76, in cl100k_base
mergeable_ranks = load_tiktoken_bpe(
^^^^^^^^^^^^^^^^^^
File "/root/anaconda3/lib/python3.11/site-packages/tiktoken/load.py", line 148, in load_tiktoken_bpe
contents = read_file_cached(tiktoken_bpe_file, expected_hash)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/anaconda3/lib/python3.11/site-packages/tiktoken/load.py", line 63, in read_file_cached
contents = read_file(blobpath)
^^^^^^^^^^^^^^^^^^^
File "/root/anaconda3/lib/python3.11/site-packages/tiktoken/load.py", line 22, in read_file
resp = requests.get(blobpath)
^^^^^^^^^^^^^^^^^^^^^^
File "/root/anaconda3/lib/python3.11/site-packages/requests/api.py", line 73, in get
return request("get", url, params=params, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/anaconda3/lib/python3.11/site-packages/requests/api.py", line 59, in request
return session.request(method=method, url=url, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/anaconda3/lib/python3.11/site-packages/requests/sessions.py", line 589, in request
resp = self.send(prep, **send_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/anaconda3/lib/python3.11/site-packages/requests/sessions.py", line 703, in send
r = adapter.send(request, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/anaconda3/lib/python3.11/site-packages/requests/adapters.py", line 501, in send
raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer'))

可以提前单独下载后复制到部署服务器:

# 在能访问外网的服务器下载cl100k_base分词器
wget https://openaipublic.blob.core.windows.net/encodings/cl100k_base.tiktoken \
     -P ~/.cache/tiktoken/

 并配置环境变量或在代码中增加:

# 替换为你实际的路径
os.environ["TIKTOKEN_CACHE_DIR"] = '/root/.cache/tiktoken'

3、 get_num_tokens_from_messages 方法未实现

第2步完成后,遇到新的问题。提示这个分词器没有实现get_num_tokens_from_messages方法。查看报错具体位置:

从源码可以看出,该模块仅支持gpt系列,因为接入时使用的是ChatOpenAI。解决方法就是,我们本地起的模型,可以取一个名字伪装,比如就叫gpt-4。如果langchai中后面有vLLM专用接口,或许就能解决这个问题。

4、工具调用异常

因为我的模型是Qwen,指定了工具解析是hermes,因此必须按照其格式要求定义函数。其中,工具函数必须有输入参数,没有也硬凑一个吧,否则会报错:validation erro。

### LangChain本地大模型的集成方法 LangChain 是一种用于构建语言模型驱动的应用程序的框架,它支持多种语言模型以及工具链的组合。要将 LangChain本地部署的大规模语言模型(Large Language Model, LLM)集成,可以遵循以下技术路径: #### 1. **配置本地模型服务** 为了使 LangChain 能够访问本地部署语言模型,通常需要先设置一个 REST API 或 gRPC 接口来暴露该模型的服务功能。这可以通过使用 FastAPI、Flask 等轻量级 Web 框架实现[^1]。 例如,在 Python 中创建一个简单的 Flask 应用来提供预测接口: ```python from flask import Flask, request, jsonify import torch from transformers import AutoTokenizer, AutoModelForCausalLM app = Flask(__name__) tokenizer = AutoTokenizer.from_pretrained("path/to/local/model") model = AutoModelForCausalLM.from_pretrained("path/to/local/model") @app.route('/predict', methods=['POST']) def predict(): data = request.json input_text = data['text'] inputs = tokenizer(input_text, return_tensors="pt").to(model.device) outputs = model.generate(**inputs, max_length=50) result = tokenizer.decode(outputs[0], skip_special_tokens=True) return jsonify({"result": result}) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) ``` 此代码片段展示了如何加载本地存储的 Hugging Face 预训练模型并将其作为 HTTP 服务运行[^4]。 #### 2. **修改 LangChain 的模型适配器** LangChain 提供了一个灵活的设计模式,允许开发者自定义不同的语言模型适配器。对于本地部署的模型,需调整 `llm` 参数指向上述服务地址。具体来说,可通过继承 `BaseLanguageModel` 类来自定义适配逻辑。 下面是一个示例类,展示如何连接到前面提到的 Flask 后端: ```python from langchain.llms.base import BaseLanguageModel import requests class LocalLLM(BaseLanguageModel): def _call(self, prompt: str, stop=None) -> str: response = requests.post( "http://localhost:5000/predict", json={"text": prompt} ) return response.json()["result"] ``` 这样就可以无缝嵌入任何依赖于标准 LLM 实现的功能组件之中。 #### 3. **优化性能考量** 当处理大规模数据集或者复杂推理任务时,应特别注意计算资源分配策略。比如采用 FlashAttention 技术加速注意力机制运算过程;合理规划 GPU 上线程块数量以充分利用硬件潜能。 另外还需关注批量大小(batch size)的选择及其对最终效果的影响关系研究发现适当增大批次有助于提升整体吞吐率同时保持较高精度水平[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值