Browse Source

chatgpt服务使用vllm方式预测

master
majiahui@haimaqingfan.com 2 years ago
parent
commit
f4ed2c6b17
  1. 54
      README.md
  2. 51
      flask_predict.py
  3. 21
      gunicorn_config.py
  4. 57
      mistral_model_predict_vllm.py
  5. 1
      run_api.sh
  6. 1
      run_model_predict.sh
  7. 47
      yace.py
  8. 76
      yace2.py
  9. 51
      yuce3.py

54
README.md

@ -1,58 +1,14 @@
# VLLM项目
## 项目启动
bash run_app_flask.sh
bash run_model_predict.sh
bash run_api.sh
## 调用示例
![img.png](img.png)
http://114.116.25.228:18000/predict
"http://192.168.31.74:12000/predict"
{
"texts": "论文题目是“晚清至民国温州瓯柑运销体制的转变”,目录是“一、引言\n1. 研究背景\n2. 研究意义\n3. 研究方法\n\n二、晚清至民国时期温州瓯柑的运销体制\n1. 温州瓯柑的产地和品种\n2. 运销渠道及其特点\n3. 运销体制的演变\n\n三、温州瓯柑运销体制转变的原因\n1. 经济背景\n2. 政治背景\n3. 社会背景\n\n四、温州瓯柑运销体制转变的影响\n1. 经济影响\n2. 社会影响\n3. 文化影响\n\n五、温州瓯柑运销体制转变的启示\n1. 历史经验\n2. 现实意义\n3. 发展前景\n\n六、结论\n\n七、参考文献”,请为这篇论文生成15篇左右的参考文献,要求其中有有中文参考文献不低于12篇,英文参考文献不低于2篇"
"texts": "User:你好\nAssistant:"
}
## 返回示例
![img_1.png](img_1.png)
## 请求参数
### 仅有标题生成的任务
{
"生成论文来源的背景#\n问:以《习近平新时代中国特色社会主义法治观初探》为论文题目,写一段题目来源的背景,要求字数在200字以内\n答:\n"
"生成研究内容#\n问:请帮我生成《基于神经网络的商品推荐系统的研究与实现》为题目的研究内容,包括整体简介和分最少三个方面总结\n答:\n"
"生成目录#\n问:为论文题目《我国医患纠纷行政调解前置程序问题的研究》生成目录,要求只有一级标题和二级标题,一级标题使用中文数字 例如一、xxx;二级标题使用阿拉伯数字 例如1.1 xxx;一级标题不少于7个;每个一级标题至少包含3个二级标题\n答:\n"
"生成课题的研究背景和意义#\n问:请分别写出以《商业车险费率市场化改革对财险公司影响研究》为课题的研究背景和意义,字数不少于1000字\n答:\n"
"生成论文简短总结#\n问:以《用于智能马桶盖的无袖带式血压监测系统开发》为论文题目,写一个论文简短总结,要求在300字以内\n答:\n"
"生成课题的国内外研究状况综述#\n问:请写出以《新时代中国院线电影观感积极率研究》为课题的国内外研究状况综述,字数在800字左右\n答:\n"
"生成6点本篇论文应完成的主要内容#\n问:请根据题目为《兰州市数字化城市管理提升研究》,和研究内容为“{生成研究内容}”总结出至少6点本篇论文应完成的主要内容,使用阿拉伯数字排列\"\n答:\n"
"生成参考文献#"
"生成论文小标题内容#\n问:论文题目是《1926-1930年归绥地区灾荒与社会流动》,目录是“{生成目录}”,请把其中的小标题“{小标题}”的内容补充完整,补充内容字数在900字左右\n答:\n"
"生成论文摘要#\n问:论文题目是《纳米水化硅酸钙改性隔热涂料的研究》,目录是“{生成目录}”,生成论文摘要,要求生成的字数在600字左右\"\n答:\n"
"生成关键字#\n问:请为“{生成论文摘要}”这段论文摘要生成3-5个关键字,使用阿拉伯数字作为序号标注,例如“1.xxx \n2.xxx \n3.xxx \n4.xxx \n5.xxx \n”\"\n答:\n"
"翻译摘要#\n问:请把“{生成论文摘要}”这段文字翻译成英文\"\n答:\n"
"翻译关键词#\n问:请把“{生成关键字}”这几个关键字翻译成英文\"\n答:\n"
}
### 带着核心内容和标题的生成任务
{
"生成论文来源的背景#\n问:以《民航繁忙干线机票最低价格预测方法研究》为论文题目,以“本研究旨在探索一种新的机票价格预测方法,以提高乘客购票体验和航空公司的经济效益。该研究包括数据采集、数据预处理、特征工程、机器学习模型构建和模型评估等步骤。最终成果是开发出一款可预测繁忙干线机票最低价格的模型,并通过对比实际价格和预测价格的误差,验证该模型的准确性和可靠性。通过本研究,我们希望能为航空公司提供更准确的价格预测,为乘客提供更便捷的购票体验。”为论文的研究方向,写一段题目来源的背景,要求字数在200字以内\n答:\n"
"生成研究内容#\n问:请帮我生成《A公司3C产品逆向物流业务流程优化》为题目,以“本文旨在优化A公司3C产品逆向物流业务流程,包括对退货、维修、换货等环节进行调研和分析,提出改善方案。最终成果是优化后的逆向物流业务流程实施,并以一个特定3C产品的退货流程为例,验证所设计方案的可行性和有效性。”为论文的研究方向,生成论文研究内容,包括整体简介和分最少三个方面总结\n答:\n"
"生成目录#\n问:论文题目为《低碳试点城市的绿色GDP核算研究》,以“该研究旨在通过对低碳试点城市的绿色GDP核算,探索一种新的经济发展模式,以实现经济增长与环境保护的双赢。研究将结合城市资源利用情况、环境质量、生态系统服务等方面进行综合评估,建立低碳经济发展指标体系,从而为低碳试点城市的可持续发展提供理论和实践支持。最终成果将是一份完整的绿色GDP核算报告,以低碳试点城市为例,验证该研究的可行性和实用性。”为论文的研究方向,为论文生成目录,要求只有一级标题和二级标题,一级标题使用中文数字 例如一、xxx;二级标题使用阿拉伯数字 例如1.1 xxx;一级标题不少于7个;每个一级标题至少包含3个二级标题\n答:\n"
"生成课题的研究背景和意义#\n问:请分别写出以《企业拟上市过程中的政府服务方式探析》为课题,以“研究拟上市企业在上市过程中,政府部门如何提供服务,探讨政府服务方式的优化和提升。最终成果是通过实地调研和案例分析,总结出一套适用于拟上市企业的政府服务模式,以提高拟上市企业上市成功率和促进经济发展。”为论文的研究方向,生成论文的研究背景和意义,字数不少于1000字\n答:\n"
"生成论文简短总结#\n问:以《韩国民主巩固的困境问题研究》为论文题目,以“研究韩国民主化进程中所面临的困境问题,包括政治、经济、社会等多个方面的因素。最终成果是通过对韩国民主化进程的深入分析,提出一些可行的解决方案,以促进韩国民主巩固的发展。通过对韩国政治体制、经济发展、社会文化等方面的综合研究,探讨韩国民主化进程中所面临的困境问题,如政治腐败、经济不平等、社会分化等,分析其根源及影响因素。在此基础上,提出一些可行的解决方案,如加强反腐败力度、促进经济平等、强化社会文化建设等,以推动韩国民主巩固的进程。最终,通过实践验证所提出的解决方案的可行性,为韩国民主巩固的发展提供有益的借鉴。”为论文的研究方向,写一个论文简短总结,要求在300字以内\n答:\n"
"生成课题的国内外研究状况综述#\n问:以《鲤疱疹病毒3型vIL-10基因的克隆表达及其对免疫相关因子调节作用的研究》为课题,以“研究鲤疱疹病毒3型vIL-10基因的克隆表达,探究其在免疫调节中的作用。通过实验验证其对免疫相关因子的调节作用,并分析其在免疫调节过程中的机制。最终成果是获得鲤疱疹病毒3型vIL-10基因的表达载体,并证明其在免疫调节中具有重要的调节作用。”为论文的研究方向,请写出这篇论文的国内外研究状况综述,字数在800字左右\n答:\n"
}

51
flask_predict.py

@ -0,0 +1,51 @@
from flask import Flask, jsonify
from flask import request
import redis
import uuid
import json
import time
import socket
def get_host_ip():
"""
查询本机ip地址
:return: ip
"""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 80))
ip = s.getsockname()[0]
finally:
s.close()
return ip
app = Flask(__name__)
app.config["JSON_AS_ASCII"] = False
pool = redis.ConnectionPool(host='localhost', port=63179, max_connections=50,db=11, password="zhicheng123*")
redis_ = redis.Redis(connection_pool=pool, decode_responses=True)
db_key_query = 'query'
db_key_query_articles_directory = 'query_articles_directory'
db_key_result = 'result'
batch_size = 32
@app.route("/predict", methods=["POST"])
def handle_query():
text = request.json["texts"] # 获取用户query中的文本 例如"I love you"
id_ = str(uuid.uuid1()) # 为query生成唯一标识
d = {'id': id_, 'text': text} # 绑定文本和query id
redis_.rpush(db_key_query, json.dumps(d)) # 加入redis
while True:
result = redis_.get(id_) # 获取该query的模型结果
if result is not None:
redis_.delete(id_)
result_text = {'code': "200", 'data': json.loads(result)}
break
time.sleep(1)
return jsonify(result_text) # 返回结果
if __name__ == "__main__":
app.run(debug=False, host='0.0.0.0', port=18001)

21
gunicorn_config.py

@ -0,0 +1,21 @@
# 并行工作线程数
workers = 8
# 监听内网端口5000【按需要更改】
bind = '0.0.0.0:12000'
loglevel = 'debug'
worker_class = "gevent"
# 设置守护进程【关闭连接时,程序仍在运行】
daemon = True
# 设置超时时间120s,默认为30s。按自己的需求进行设置
timeout = 120
# 设置访问日志和错误信息日志路径
accesslog = './logs/acess.log'
errorlog = './logs/error.log'
# access_log_format = '%(h) - %(t)s - %(u)s - %(s)s %(H)s'
# errorlog = '-' # 记录到标准输出
# 设置最大并发量
worker_connections = 20000

57
mistral_model_predict_vllm.py

@ -0,0 +1,57 @@
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "3"
from transformers import pipeline
import redis
import uuid
import json
from threading import Thread
from vllm import LLM, SamplingParams
import time
import threading
import time
import concurrent.futures
import requests
import socket
pool = redis.ConnectionPool(host='localhost', port=63179, max_connections=50,db=11, password="zhicheng123*")
redis_ = redis.Redis(connection_pool=pool, decode_responses=True)
db_key_query = 'query'
db_key_query_articles_directory = 'query_articles_directory'
db_key_result = 'result'
batch_size = 512
sampling_params = SamplingParams(temperature=0.95, top_p=0.7,presence_penalty=0.9,stop="</s>", max_tokens=4096)
models_path = "/home/majiahui/project/models-llm/openbuddy-llama-7b-finetune"
llm = LLM(model=models_path, tokenizer_mode="slow")
def classify(batch_size): # 调用模型,设置最大batch_size
while True:
texts = []
query_ids = []
if redis_.llen(db_key_query) == 0: # 若队列中没有元素就继续获取
time.sleep(2)
continue
for i in range(min(redis_.llen(db_key_query), batch_size)):
query = redis_.lpop(db_key_query).decode('UTF-8') # 获取query的text
query_ids.append(json.loads(query)['id'])
texts.append(json.loads(query)['text']) # 拼接若干text 为batch
outputs = llm.generate(texts, sampling_params) # 调用模型
generated_text_list = [""] * len(texts)
print("outputs", len(outputs))
for i, output in enumerate(outputs):
index = output.request_id
generated_text = output.outputs[0].text
generated_text_list[int(index)] = generated_text
for (id_, output) in zip(query_ids, generated_text_list):
res = output
redis_.set(id_, json.dumps(res)) # 将模型结果送回队列
if __name__ == '__main__':
t = Thread(target=classify, args=(batch_size,))
t.start()

1
run_api.sh

@ -0,0 +1 @@
gunicorn flask_predict:app -c gunicorn_config.py

1
run_model_predict.sh

@ -0,0 +1 @@
nohup python mistral_model_predict_vllm.py > mistral_model_predict_vllm_logs.file 2>&1 &

47
yace.py

@ -0,0 +1,47 @@
import concurrent.futures
import requests
import socket
def dialog_line_parse(url, text):
"""
将数据输入模型进行分析并输出结果
:param url: 模型url
:param text: 进入模型的数据
:return: 模型返回结果
"""
response = requests.post(
url,
json=text,
timeout=1000
)
if response.status_code == 200:
return response.json()
else:
# logger.error(
# "【{}】 Failed to get a proper response from remote "
# "server. Status Code: {}. Response: {}"
# "".format(url, response.status_code, response.text)
# )
print("{}】 Failed to get a proper response from remote "
"server. Status Code: {}. Response: {}"
"".format(url, response.status_code, response.text))
print(text)
return []
nums = 1000
url = "http://192.168.31.74:18001/predict"
input_data = []
for i in range(nums):
input_data.append([url, {"texts": "User:你好\nAssistant:"}])
with concurrent.futures.ThreadPoolExecutor() as executor:
# 使用submit方法将任务提交给线程池,并获取Future对象
futures = [executor.submit(dialog_line_parse, i[0], i[1]) for i in input_data]
# 使用as_completed获取已完成的任务,并获取返回值
results = [future.result() for future in concurrent.futures.as_completed(futures)]
print(results)

76
yace2.py

@ -0,0 +1,76 @@
import threading
import requests
import time
# 用于记录成功和失败请求的全局变量
success_count = 0
failure_count = 0
lock = threading.Lock()
def dialog_line_parse(url, text):
"""
将数据输入模型进行分析并输出结果
:param url: 模型url
:param text: 进入模型的数据
:return: 模型返回结果
"""
response = requests.post(
url,
json=text,
timeout=1000
)
if response.status_code == 200:
return response.json()
else:
# logger.error(
# "【{}】 Failed to get a proper response from remote "
# "server. Status Code: {}. Response: {}"
# "".format(url, response.status_code, response.text)
# )
print("{}】 Failed to get a proper response from remote "
"server. Status Code: {}. Response: {}"
"".format(url, response.status_code, response.text))
print(text)
return []
# 定义一个函数来执行 HTTP 请求
def make_request(url):
global success_count, failure_count
try:
a = dialog_line_parse(url, {"texts": "User:你好\nAssistant:"})['data']
print(a)
with lock:
success_count += 1
except:
with lock:
failure_count += 1
# 要并发请求的 URL 列表
urls = [
'http://192.168.31.74:18001/predict',
# 可以添加更多的 URL
] * 30
# 创建一个线程列表
threads = []
# 创建并启动线程
start= time.time()
for url in urls:
thread = threading.Thread(target=make_request, args=(url,))
thread.start()
threads.append(thread)
# 等待所有线程完成
for thread in threads:
thread.join()
end = time.time()
print(end-start)
print(f"Successful requests: {success_count}")
print(f"Failed requests: {failure_count}")

51
yuce3.py

@ -0,0 +1,51 @@
import concurrent.futures
import requests
import socket
def dialog_line_parse(url, text):
"""
将数据输入模型进行分析并输出结果
:param url: 模型url
:param text: 进入模型的数据
:return: 模型返回结果
"""
response = requests.post(
url,
json=text,
timeout=1000
)
if response.status_code == 200:
return response.json()
else:
# logger.error(
# "【{}】 Failed to get a proper response from remote "
# "server. Status Code: {}. Response: {}"
# "".format(url, response.status_code, response.text)
# )
print("{}】 Failed to get a proper response from remote "
"server. Status Code: {}. Response: {}"
"".format(url, response.status_code, response.text))
print(text)
return []
text = "User:生成目录#\n问:为论文题目《基于跨文化意识培养的中职英语词汇教学模式及策略行动研究》生成目录,要求只有一级标题和二级标题,一级标题使用中文数字 例如一、xxx;二级标题使用阿拉伯数字 例如1.1 xxx;一级标题不少于7个;每个一级标题至少包含3个二级标题\n答:\n\nAssistant:" # 获取用户query中的文本 例如"I love you"
nums = 10
nums = int(nums)
url = "http://192.168.31.74:18001/predict"
input_data = []
for i in range(nums):
input_data.append([url, {"texts": text}])
with concurrent.futures.ThreadPoolExecutor() as executor:
# 使用submit方法将任务提交给线程池,并获取Future对象
futures = [executor.submit(dialog_line_parse, i[0], i[1]) for i in input_data]
# 使用as_completed获取已完成的任务,并获取返回值
results = [future.result() for future in concurrent.futures.as_completed(futures)]
print(results)
Loading…
Cancel
Save