大模型项目(一)模型部署
大模型项目(一)模型部署
1.ollama
ollama模型内外网都是win环境,所以就是模型的打包导入和python环境的打包导入。
1.1.模型
1.1.1下载
首先ollama下载并启动模型
ollama pull deepseek-r1:32b #1.ollama模型仓库下载模型到本地C:\Users\<用户名>\.ollama\models\blobs里面【ollama默认的模型存放地址,如果想修改,可以修改设置环境变量OLLAMA_MODELS来更改】
ollama serve #2.启动ollama服务
ollama run deepseek-r1:32b #3.启动模型命令行交互(ctrl+d退出)
1.1.2.打包
我内外网都是用的是ollama,外网pull下来的模型文件,通过gguf和Modelfile拿到内网使用。
1.ollama下载的模型文件在C:\Users<用户名>.ollama\models\blobs里面【ollama默认的模型存放地址,如果想修改,可以修改设置环境变量OLLAMA_MODELS来更改】,最大的那个就是模型,复制出来,改名为deepseek-r1.gguf
ollama list #2.查看模型文件叫什么(deepseek-r1:32b)
ollama show deepseek-r1:32b --modelfile > Modelfile #3.得到模型的Modelfile文件
4.修改Modelfile文件里面的模型路径,例如这里是./deepseek-r1.gguf
1.1.3.部署
1.将这两个文件复制到内网的空文件夹
ollama create deepseek-r1 -f Modelfile #2.将这个gguf模型文件就解到了c盘的cache目录下
ollama run deepseek-r1 #3.此时就可以启动这个模型了
如果模型启动后在局域网下访问不到,修改环境变量OLLAMA_HOST=0.0.0.0
1.2.python环境
环境我内网都使用的是anconda创建的虚拟环境,外网环境打包成压缩包,在内网直接解压使用。
1.2.1.打包
conda activate chatglm#1.激活我外网使用的anconda环境
conda install -c conda-forge conda-pack #2.使用conda-forge通道下载conda-pack包,后续打包使用
conda pack -n chatglm -o environment.tar.gz #3.将这个环境下的包全部打到environment.tar.gz压缩包里面
1.2.2.部署
mkdir v2 #1.内网电脑新建文件夹
tar -xzf environment.tar.gz -C v2 #2.将打包的压缩包解压到v2目录下
.\v2\Scripts\activate #3.使用conda激活这个v2环境
1.2.3.模型封装
使用openai接口包装模型地调用方式
from langchain.llms.base import LLM
from langchain_core.messages.ai import AIMessage
from openai import OpenAI
from flask import Flask, request, jsonify, stream_with_context
import re
import json
import time
from sm import session_manager
class MYLLM(LLM):
client:object = None
def __init__(self):
super().__init__()
self.client = OpenAI(
base_url="http://192.168.3.126:11434/v1",
api_key="ollama"
)
@property
def _llm_type(self):
return "deepseek-r1:8b"
def invoke(self,user_id,user_input):
if not isinstance(user_input,list):#prompt,否则就是history
history=[{"role":"user","content":user_input}]
else:
history=user_input
response = self.client.chat.completions.create(
model="deepseek-r1:8b",#"deepseek-r1",
messages=history,
)
result = response.choices[0].message.content
session_manager.update_history(user_id, result=result)
return AIMessage(content=result).content
def stream(self,user_id,user_input):
if not isinstance(user_input,list):#prompt,否则就是history
history=[{"role":"user","content":user_input}]
else:
history=user_input
result=""
response = self.client.chat.completions.create(
model="deepseek-r1:8b",
messages=history,
stream=True,
)
for chunk in response:
if hasattr(chunk.choices[0].delta,"content"):#yield f"data: {i} yes your right\n\n"
content_piece=chunk.choices[0].delta.content
if content_piece:
result+=content_piece
yield (json.dumps({"response":content_piece,"done":False})+"\n")#.encode('utf-8')
# print("stream_output:"+out)
session_manager.update_history(user_id, result=result)
yield json.dumps({"response":"","done":True})#.encode('utf-8')
2.llama.cpp
llama.cpp内外都是linux环境,打包系统环境包,python环境包和llama.cpp和模型文件。
2.1.安装系统环境
外网安装
sudo apt update
sudo apt install -y build-essential git cmake wget python3 python3-pip libcurl4-openssl-dev
安装cuda驱动
2.2.安装python环境
conda create -n llama python==3.11.9
conda activate llama
pip install -U transformers
pip3 install torch torchvision --index-url https://download.pytorch.org/whl/cu129
pip install mistral_common
pip install sentencepiece
2.3.下载编译llama
git clone https://github.com/ggml-org/llama.cpp.git
cd llama.cpp
mkdir build
cd build
cmake ..
cmake --build . --config Release
2.4.运行测试
2.4.1.下载模型
git clone https://www.modelscope.cn/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B.git
2.4.2.模型转换GGUF格式
使用llama.cpp把hf格式转换为 GGUF格式,也可以直接下载guff格式
python3 convert_hf_to_gguf.py ../DeepSeek-R1-Distill-Qwen-7B --outfile ../deepseek.gguf
2.4.3.运行推理
./build/bin/llama-cli -m ../deepseek.gguf -p "写一段Python代码,打印Hello World"
./build/bin/llama-cli -m ../deepseek.gguf -i #可交互模式
./build/bin/llama-cli -m ../deepseek.gguf -c 4096 -i #带上下文窗口(例如 4096)带记忆交互模式
./build/bin/llama-server -m ../deepseek.gguf --port 8080 --host 0.0.0.0 #server 模式进行API 部署
2.4.4.测试调用
curl -X POST http://localhost:8080/v1/chat/completions -H "Content-Type: application/json" -d '{"model": "deepseek","messages": [{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": "用C语言写一个快速排序"}],"max_tokens": 200}'
2.5.打包部署
打包系统所需包
mkdir ~/curl_pkg && cd ~/curl_pkg
apt-get download libcurl4-openssl-dev libcurl4 libnghttp2-14 librtmp1 libssh2-1 libidn2-0 libpsl5 libunistring2 zlib1g
tar -czvf curl_pkgs.tar.gz *.deb
在内网环境安装系统包
tar -xzvf curl_pkgs.tar.gz
sudo dpkg -i *.deb
sudo apt --fix-broken install
打包安装python环境win可以参考前面的ollama,麒麟的话可以参考第二篇。
2.6.模型封装
根据业务自己封装模型封装
import requests
import json
from functools import lru_cache
from sm import session_manager
from langchain_core.messages.ai import AIMessage
class MYLLM:
def __init__(self):
self.base_url_un = 'http://192.168.1.10:8001/v1/chat/completions'
self.base_url = 'http://192.168.1.10:8010/v1/chat/completions'
self.base_model_un = 'un_deep_think_model'
self.base_model = 'deep_think_model'
self.topp=0.9
self.temperature=0.1
def invoke(self,user_id,user_input):
if not isinstance(user_input,list):#prompt,否则就是history
history=[{"role":"user","content":user_input}]
else:
history=user_input
response = requests.post(self.base_url_un, json={
"temperature": self.temperature,
"model": self.base_model_un,
"topp": self.topp,
"messages": history
})
if response.status_code == 200:
result = response.json()
result = result.get("choices", [{}])[0].get("message", {}).get("content")
session_manager.update_history(user_id, result=result)
return AIMessage(content=result).content
def stream(self, user_id, user_input):
if not isinstance(user_input, list): # 如果是单个prompt,转换为history格式
history = [{"role": "user", "content": user_input}]
else:
history = user_input
result = ""
response = requests.post(
self.base_url,
json={
"temperature": self.temperature,
"model": self.base_model,
"topp": self.topp,
"messages": history,
"stream": True,
},
stream=True # 关键:启用流式传输
)
if response.status_code == 200:
decoder = json.JSONDecoder() # 用于解析JSON片段
buffer = "" # 用于累积不完整的JSON数据
for line in response.iter_lines(): # 直接逐行处理流式响应
if line: # 跳过空行
line = line.decode('utf-8')
if line.startswith('data: '): # 处理数据行
data = line[6:] # 去掉"data: "前缀
if data == "[DONE]": # 响应结束标记
break
buffer += data # 累积可能的多行JSON
try:
# 尝试解析完整的JSON对象
while buffer:
obj, idx = decoder.raw_decode(buffer)
buffer = buffer[idx:].lstrip() # 清理缓冲区
content_piece = obj.get("choices", [{}])[0].get("delta", {}).get("content")
if content_piece:
result += content_piece
yield json.dumps({"response": content_piece, "done": False}) + "\n"
except json.JSONDecodeError:
pass # 数据不完整,继续累积
# else: # 其他控制信息(如错误)可自行处理
session_manager.update_history(user_id, result=result)
yield json.dumps({"response": "", "done": True})
else:
# 处理错误响应(根据实际需求添加)
yield json.dumps({"response": "请求失败", "done": True})
def stream_unthink(self, user_id, user_input):
if not isinstance(user_input, list): # 如果是单个prompt,转换为history格式
history = [{"role": "user", "content": user_input}]
else:
history = user_input
result = ""
response = requests.post(
self.base_url_un,
json={
"temperature": self.temperature,
"model": self.base_model_un,
"topp": self.topp,
"messages": history,
"stream": True,
},
stream=True # 关键:启用流式传输
)
if response.status_code == 200:
decoder = json.JSONDecoder() # 用于解析JSON片段
buffer = "" # 用于累积不完整的JSON数据
for line in response.iter_lines(): # 直接逐行处理流式响应
if line: # 跳过空行
line = line.decode('utf-8')
if line.startswith('data: '): # 处理数据行
data = line[6:] # 去掉"data: "前缀
if data == "[DONE]": # 响应结束标记
break
buffer += data # 累积可能的多行JSON
try:
# 尝试解析完整的JSON对象
while buffer:
obj, idx = decoder.raw_decode(buffer)
buffer = buffer[idx:].lstrip() # 清理缓冲区
content_piece = obj.get("choices", [{}])[0].get("delta", {}).get("content")
if content_piece:
result += content_piece
yield json.dumps({"response": content_piece, "done": False}) + "\n"
except json.JSONDecodeError:
pass # 数据不完整,继续累积
# else: # 其他控制信息(如错误)可自行处理
session_manager.update_history(user_id, result=result)
yield json.dumps({"response": "", "done": True})
else:
# 处理错误响应(根据实际需求添加)
yield json.dumps({"response": "请求失败", "done": True})
# if __name__ == "__main__":
# model_caller = MYLLM()
# messages = [
# {"role": "user", "content": "你好,我是用户。"}
# ]
# # response = model_caller.invoke("1",messages)
# response2 = model_caller.stream("2",messages)
# print(response)
# print(response2)
参考博文
[1].https://www.zouht.com/3835.html
[2].https://blog.csdn.net/ATTK_Time/article/details/146184307
[3].https://zhuanlan.zhihu.com/p/682585600
[4].https://zhuanlan.zhihu.com/p/1895533879319836316
更多推荐
所有评论(0)