gup服务器环境初始化
机器申请
在星海算力购买gpu服务器
创建实例
选择如下配置
- CPU: 14核心
- 内存: 60GB
- GPU: RTX 4090D*1卡
- CUDA版本: 11.8
- 显存: 24GB
- 镜像: Pytorch-22.04/Pytorch2.1.2/CUDA11.8
- 系统盘: 26.24GB/100GB
- 磁盘费用: 100GB(免费) 0GB(付费)
ssh连接到gpu服务器
初始化开发环境
安装git-lfs
sudo apt update
sudo apt install git-lfs
git lfs install
创建工作目录
pwd
mkdri projects
cd projects
下载模型文件
选择 Qwen2.5-0.5B-Instruct
终端执行命令:
git clone https://www.modelscope.cn/Qwen/Qwen2.5-0.5B-Instruct.git
完成下载,整个模型文件目录1.9G
(base) root@xb2-7769:~# du -h ./Qwen2.5-0.5B-Instruct/
80K ./Qwen2.5-0.5B-Instruct/.git/hooks
8.0K ./Qwen2.5-0.5B-Instruct/.git/logs/refs/remotes/origin
12K ./Qwen2.5-0.5B-Instruct/.git/logs/refs/remotes
8.0K ./Qwen2.5-0.5B-Instruct/.git/logs/refs/heads
24K ./Qwen2.5-0.5B-Instruct/.git/logs/refs
32K ./Qwen2.5-0.5B-Instruct/.git/logs
4.0K ./Qwen2.5-0.5B-Instruct/.git/branches
8.0K ./Qwen2.5-0.5B-Instruct/.git/refs/remotes/origin
12K ./Qwen2.5-0.5B-Instruct/.git/refs/remotes
4.0K ./Qwen2.5-0.5B-Instruct/.git/refs/tags
8.0K ./Qwen2.5-0.5B-Instruct/.git/refs/heads
28K ./Qwen2.5-0.5B-Instruct/.git/refs
4.0K ./Qwen2.5-0.5B-Instruct/.git/lfs/tmp
4.0K ./Qwen2.5-0.5B-Instruct/.git/lfs/incomplete
943M ./Qwen2.5-0.5B-Instruct/.git/lfs/objects/fd/f7
943M ./Qwen2.5-0.5B-Instruct/.git/lfs/objects/fd
943M ./Qwen2.5-0.5B-Instruct/.git/lfs/objects
943M ./Qwen2.5-0.5B-Instruct/.git/lfs
3.7M ./Qwen2.5-0.5B-Instruct/.git/objects/pack
4.0K ./Qwen2.5-0.5B-Instruct/.git/objects/info
3.7M ./Qwen2.5-0.5B-Instruct/.git/objects
8.0K ./Qwen2.5-0.5B-Instruct/.git/info
947M ./Qwen2.5-0.5B-Instruct/.git
1.9G ./Qwen2.5-0.5B-Instruct/
python3.10环境
本服务器默认python环境是3.8,版本比较老,刚好自带安装过 conda
,所以决定使用conda创建python3.10环境
- 创建py310env
conda create --name py310env python=3.10
- 激活虚拟环境
conda activate py310env
- 退出虚拟环境
conda deactivate
安装依赖
pip install transformers torch
跑通quickstart
# coding = utf-8
from transformers import AutoModelForCausalLM, AutoTokenizer
model_name = "Qwen2.5-0.5B-Instruct"
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
prompt = "Give me a short introduction to large language model."
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]
print(response)
成功运行表示环境ok
项目说明
-
主题:
- 酒店评论情感识别
-
背景:
- 评论:来自携程酒店评论
- 情感:分为正面和负面
-
流程:
-
- 设计一个
Prompt
, 实现情感识别任务
- 设计一个
-
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
# 模型名称
model_name = "Qwen2.5-0.5B-Instruct"
# 加载模型和分词器
model = AutoModelForCausalLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 定义提示词和评论
prompt_template = """
请阅读以下评论,并判断其情感倾向是正面还是负面。回答正面或者负面即可。
评论: "{}"
回答:
"""
# 读取 tsv文件 [("xxxxx","正面"),("xxxxx","反面")]
with open("情感识别.tsv", "r") as f:
comments = [(line.strip().split("\t")[0], line.strip().split("\t")[1]) for line in f.readlines()[1:]]
def generate_response(prompt):
# 构建消息
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)
inputs = tokenizer([text], return_tensors="pt").to(model.device)
# 生成响应
outputs = model.generate(**inputs, max_new_tokens=512)
response = tokenizer.batch_decode(outputs[:, inputs.input_ids.shape[-1]:], skip_special_tokens=True)[0]
return response
if __name__ == '__main__':
# 处理每条评论
for comment,answer in comments:
prompt = prompt_template.format(comment)
response = generate_response(prompt)
print(f"评论: {comment}")
print(f"判断: {response} 样本: {answer}")
print("-" * 20)
-
- 借助
LangChain
,开发一个情感识别的Chain
- 借助
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain_community.llms import HuggingFacePipeline
import torch
# 加载本地模型和分词器
model_name = "Qwen2.5-0.5B-Instruct"
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.float16, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 使用 transformers 的 pipeline 创建一个 HuggingFacePipeline
# 设置参数以获得更稳定的输出
pipe = pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
max_new_tokens=2, # 限制生成长度
temperature=0.1, # 降低随机性
top_p=0.9, # 控制生成文本的多样性
repetition_penalty=1.2 # 避免重复
)
# 创建一个 HuggingFacePipeline 对象
llm = HuggingFacePipeline(pipeline=pipe)
# 优化后的提示模板
prompt_template = PromptTemplate(
input_variables=["text"],
template="""你是一个专业的情感分析专家。请仔细分析以下评论的情感倾向。回答"正面"或者"负面"即可,不要其他内容
评论内容:"{text}"
最终判断为:"""
)
# 创建一个 LLMChain
chain = LLMChain(
llm=llm,
prompt=prompt_template
)
-
- 调用这个
Chain
,在情感识别数据集上,测试准确率
- 调用这个
# 测试用例
# 读取 tsv文件 [("xxxxx","正面"),("xxxxx","反面")]
with open("情感识别.tsv", "r") as f:
test_cases = [(line.strip().split("\t")[0], line.strip().split("\t")[1]) for line in f.readlines()[1:]]
# 处理结果的函数
def process_result(result):
res = result.split("\n")[-1]
# 使用正则表达式提取"正面"或"负面"
match = re.search(r"(正面|负面)", res)
if match:
return match.group(0)
return "无法判断"
# 测试多个案例
for test_text,answer in test_cases:
print("\n评论:", test_text)
result = chain.run({"text": test_text})
final_result = process_result(result)
print(f"判断的情感倾向: {final_result}, 真实的情感倾向: {answer}")
-
- 不断调整
Prompt
, 逐步提升准确率
- 不断调整
# 优化后的提示模板
prompt_template = PromptTemplate(
input_variables=["text"],
template="""你是一个专业的情感分析专家。请仔细分析以下评论的情感倾向。回答"正面"或者"负面"即可,不要其他内容
评论内容:"{text}"
最终判断为:"""
)
-
- 把最终开发好的
Chain
,发布成大模型能力API
- 把最终开发好的
# -*- coding: utf-8 -*-
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain_community.llms import HuggingFacePipeline
import torch
import uvicorn
# 创建 FastAPI 应用
app = FastAPI(
title="情感分析 API",
description="基于 Qwen 大模型的情感分析服务",
version="1.0.0"
)
# 定义请求模型
class SentimentRequest(BaseModel):
text: str
# 定义响应模型
class SentimentResponse(BaseModel):
text: str
sentiment: str
# 全局变量存储模型和链
global_chain = None
# 初始化模型和链
def init_model():
global global_chain
# 加载模型和分词器
model_name = "Qwen2.5-0.5B-Instruct"
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16,
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
pipe = pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
max_new_tokens=2, # 限制生成长度
temperature=0.1, # 降低随机性
top_p=0.9, # 控制生成文本的多样性
repetition_penalty=1.2 # 避免重复
)
# 创建一个 HuggingFacePipeline 对象
llm = HuggingFacePipeline(pipeline=pipe)
# 优化后的提示模板
prompt_template = PromptTemplate(
input_variables=["text"],
template="""你是一个专业的情感分析专家。请仔细分析以下评论的情感倾向。回答"正面"或者"负面"即可,不要其他内容
评论内容:"{text}"
断定为:
"""
)
# 创建链
global_chain = LLMChain(
llm=llm,
prompt=prompt_template
)
# 启动时初始化模型
@app.on_event("startup")
async def startup_event():
init_model()
# 健康检查端点
@app.get("/health")
async def health_check():
return {"status": "healthy"}
# 情感分析端点
@app.post("/analyze_sentiment", response_model=SentimentResponse)
async def analyze_sentiment(request: SentimentRequest):
try:
# 使用链进行分析
result = global_chain.run({"text": request.text})
sentiment = result.split("\n")[-1]
return SentimentResponse(
text=request.text,
sentiment=sentiment
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# 主函数
if __name__ == "__main__":
# 运行服务器
uvicorn.run(app, host="0.0.0.0", port=8000)
健康检测
(py310env) root@xb2-7769:~# curl --request GET \
> --url http://0.0.0.0:8000/health \
> --header 'Accept: */*' \
> --header 'Accept-Encoding: gzip, deflate, br' \
> --header 'Connection: keep-alive' \
> --header 'User-Agent: PostmanRuntime-ApipostRuntime/1.1.0'
{"status":"healthy"}