
commit
53672a0582
5 changed files with 858 additions and 0 deletions
@ -0,0 +1,207 @@ |
|||||
|
# 这是一个示例 Python 脚本。 |
||||
|
|
||||
|
# 按 Shift+F10 执行或将其替换为您的代码。 |
||||
|
# 按 双击 Shift 在所有地方搜索类、文件、工具窗口、操作和设置。 |
||||
|
import faiss |
||||
|
import numpy as np |
||||
|
from tqdm import tqdm |
||||
|
from sentence_transformers import SentenceTransformer |
||||
|
import requests |
||||
|
import time |
||||
|
from flask import Flask, jsonify |
||||
|
from flask import request |
||||
|
|
||||
|
app = Flask(__name__) |
||||
|
app.config["JSON_AS_ASCII"] = False |
||||
|
|
||||
|
model = SentenceTransformer('/home/majiahui/project/models-llm/bge-large-zh-v1.5') |
||||
|
propmt_connect = '''我是一名中医,你是一个中医的医生的助理,我的患者有一个症状,症状如下: |
||||
|
{} |
||||
|
根据这些症状,我通过查找资料,{} |
||||
|
请根据上面的这些资料和方子,根据患者的症状帮我开出正确的药方和治疗方案''' |
||||
|
|
||||
|
propmt_connect_ziliao = '''在“{}”资料中,有如下相关内容: |
||||
|
{}''' |
||||
|
|
||||
|
|
||||
|
def dialog_line_parse(url, text): |
||||
|
""" |
||||
|
将数据输入模型进行分析并输出结果 |
||||
|
:param url: 模型url |
||||
|
:param text: 进入模型的数据 |
||||
|
:return: 模型返回结果 |
||||
|
""" |
||||
|
|
||||
|
response = requests.post( |
||||
|
url, |
||||
|
json=text, |
||||
|
timeout=100000 |
||||
|
) |
||||
|
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)) |
||||
|
return {} |
||||
|
|
||||
|
|
||||
|
def shengcehng_array(data): |
||||
|
embs = model.encode(data, normalize_embeddings=True) |
||||
|
return embs |
||||
|
|
||||
|
def Building_vector_database(type, name, data): |
||||
|
data_ndarray = np.empty((0, 1024)) |
||||
|
for sen in data: |
||||
|
data_ndarray = np.concatenate((data_ndarray, shengcehng_array([sen]))) |
||||
|
print("data_ndarray.shape", data_ndarray.shape) |
||||
|
|
||||
|
print("data_ndarray.shape", data_ndarray.shape) |
||||
|
np.save(f'data_np/{name}.npy', data_ndarray) |
||||
|
|
||||
|
|
||||
|
|
||||
|
def ulit_request_file(file, title): |
||||
|
file_name = file.filename |
||||
|
file_name_save = "data_file/{}.txt".format(title) |
||||
|
file.save(file_name_save) |
||||
|
|
||||
|
try: |
||||
|
with open(file_name_save, encoding="gbk") as f: |
||||
|
content = f.read() |
||||
|
except: |
||||
|
with open(file_name_save, encoding="utf-8") as f: |
||||
|
content = f.read() |
||||
|
# elif file_name.split(".")[-1] == "docx": |
||||
|
# content = docx2txt.process(file_name_save) |
||||
|
|
||||
|
content_list = [i for i in content.split("\n")] |
||||
|
|
||||
|
return content_list |
||||
|
|
||||
|
|
||||
|
def main(question, db_type, top): |
||||
|
db_dict = { |
||||
|
"1": "yetianshi" |
||||
|
} |
||||
|
''' |
||||
|
定义文件路径 |
||||
|
''' |
||||
|
|
||||
|
''' |
||||
|
加载文件 |
||||
|
''' |
||||
|
|
||||
|
''' |
||||
|
文本分割 |
||||
|
''' |
||||
|
|
||||
|
''' |
||||
|
构建向量数据库 |
||||
|
1. 正常匹配 |
||||
|
2. 把文本使用大模型生成一个问题之后再进行匹配 |
||||
|
''' |
||||
|
|
||||
|
''' |
||||
|
根据提问匹配上下文 |
||||
|
''' |
||||
|
d = 1024 |
||||
|
db_type_list = db_type.split(",") |
||||
|
|
||||
|
paper_list_str = "" |
||||
|
for i in db_type_list: |
||||
|
embs = shengcehng_array([question]) |
||||
|
index = faiss.IndexFlatL2(d) # buid the index |
||||
|
data_np = np.load(f"data_np/{i}.npy") |
||||
|
data_str = open(f"data_file/{i}.txt").read().split("\n") |
||||
|
index.add(data_np) |
||||
|
D, I = index.search(embs, int(top)) |
||||
|
print(I) |
||||
|
|
||||
|
reference_list = [] |
||||
|
for i in I[0]: |
||||
|
reference_list.append(data_str[i]) |
||||
|
|
||||
|
for i,j in enumerate(reference_list): |
||||
|
paper_list_str += "第{}篇\n{}\n".format(str(i+1), j) |
||||
|
|
||||
|
''' |
||||
|
构造prompt |
||||
|
''' |
||||
|
print("paper_list_str", paper_list_str) |
||||
|
propmt_connect_ziliao_input = [] |
||||
|
for i in db_type_list: |
||||
|
propmt_connect_ziliao_input.append(propmt_connect_ziliao.format(i, paper_list_str)) |
||||
|
|
||||
|
propmt_connect_ziliao_input_str = ",".join(propmt_connect_ziliao_input) |
||||
|
propmt_connect_input = propmt_connect.format(question, propmt_connect_ziliao_input_str) |
||||
|
''' |
||||
|
生成回答 |
||||
|
''' |
||||
|
url_predict = "http://192.168.31.74:26000/predict" |
||||
|
url_search = "http://192.168.31.74:26000/search" |
||||
|
|
||||
|
# data = { |
||||
|
# "content": propmt_connect_input |
||||
|
# } |
||||
|
data = { |
||||
|
"content": propmt_connect_input, |
||||
|
"model": "qwq-32", |
||||
|
"top_p": 0.9, |
||||
|
"temperature": 0.6 |
||||
|
} |
||||
|
|
||||
|
res = dialog_line_parse(url_predict, data) |
||||
|
id_ = res["texts"]["id"] |
||||
|
|
||||
|
data = { |
||||
|
"id": id_ |
||||
|
} |
||||
|
|
||||
|
while True: |
||||
|
res = dialog_line_parse(url_search, data) |
||||
|
if res["code"] == 200: |
||||
|
break |
||||
|
else: |
||||
|
time.sleep(1) |
||||
|
spilt_str = "</think>" |
||||
|
think, response = str(res["text"]).split(spilt_str) |
||||
|
return think, response |
||||
|
|
||||
|
|
||||
|
@app.route("/upload_file", methods=["POST"]) |
||||
|
def upload_file(): |
||||
|
print(request.remote_addr) |
||||
|
file = request.files.get('file') |
||||
|
title = request.form.get("title") |
||||
|
data = ulit_request_file(file, title) |
||||
|
Building_vector_database("1", title, data) |
||||
|
return_json = { |
||||
|
"code": 200, |
||||
|
"info": "上传完成" |
||||
|
} |
||||
|
return jsonify(return_json) # 返回结果 |
||||
|
|
||||
|
|
||||
|
@app.route("/search", methods=["POST"]) |
||||
|
def search(): |
||||
|
print(request.remote_addr) |
||||
|
texts = request.json["texts"] |
||||
|
text_type = request.json["text_type"] |
||||
|
top = request.json["top"] |
||||
|
think, response = main(texts, text_type, top) |
||||
|
return_json = { |
||||
|
"code": 200, |
||||
|
"think": think, |
||||
|
"response": response |
||||
|
} |
||||
|
return jsonify(return_json) # 返回结果 |
||||
|
|
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
app.run(host="0.0.0.0", port=27000, threaded=True, debug=False) |
@ -0,0 +1,179 @@ |
|||||
|
import os |
||||
|
os.environ["CUDA_VISIBLE_DEVICES"] = "1,2,3,4" |
||||
|
from transformers import AutoModelForCausalLM, AutoTokenizer |
||||
|
import logging |
||||
|
from threading import Thread |
||||
|
import requests |
||||
|
import redis |
||||
|
import uuid |
||||
|
import time |
||||
|
import json |
||||
|
from flask import Flask, jsonify |
||||
|
from flask import request |
||||
|
|
||||
|
app = Flask(__name__) |
||||
|
app.config["JSON_AS_ASCII"] = False |
||||
|
pool = redis.ConnectionPool(host='localhost', port=63179, max_connections=50,db=17, password="zhicheng123*") |
||||
|
redis_ = redis.Redis(connection_pool=pool, decode_responses=True) |
||||
|
|
||||
|
# model config |
||||
|
model_name = "/home/majiahui/project/models-llm/QwQ-32" |
||||
|
model = AutoModelForCausalLM.from_pretrained( |
||||
|
model_name, |
||||
|
torch_dtype="auto", |
||||
|
device_map="auto" |
||||
|
) |
||||
|
tokenizer = AutoTokenizer.from_pretrained(model_name) |
||||
|
|
||||
|
db_key_query = 'query' |
||||
|
db_key_querying = 'querying' |
||||
|
db_key_result = 'result' |
||||
|
batch_size = 15 |
||||
|
|
||||
|
|
||||
|
def main(prompt): |
||||
|
# prompt = "电视剧《人世间》导演和演员是谁" |
||||
|
messages = [ |
||||
|
{"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=32768 |
||||
|
) |
||||
|
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] |
||||
|
response = str(response).split("</think>")[1] |
||||
|
return response |
||||
|
|
||||
|
|
||||
|
def classify(): # 调用模型,设置最大batch_size |
||||
|
while True: |
||||
|
if redis_.llen(db_key_query) == 0: # 若队列中没有元素就继续获取 |
||||
|
time.sleep(2) |
||||
|
continue |
||||
|
|
||||
|
query = redis_.lpop(db_key_query).decode('UTF-8') # 获取query的text |
||||
|
data_dict_path = json.loads(query) |
||||
|
path = data_dict_path['path'] |
||||
|
|
||||
|
with open(path, encoding='utf8') as f1: |
||||
|
# 加载文件的对象 |
||||
|
data_dict = json.load(f1) |
||||
|
|
||||
|
query_id = data_dict['id'] |
||||
|
input_text = data_dict["text"] |
||||
|
|
||||
|
output_text = main(input_text) |
||||
|
|
||||
|
return_text = { |
||||
|
"input": input_text, |
||||
|
"output": output_text |
||||
|
} |
||||
|
|
||||
|
load_result_path = "./new_data_logs/{}.json".format(query_id) |
||||
|
print("query_id: ", query_id) |
||||
|
print("load_result_path: ", load_result_path) |
||||
|
|
||||
|
with open(load_result_path, 'w', encoding='utf8') as f2: |
||||
|
# ensure_ascii=False才能输入中文,否则是Unicode字符 |
||||
|
# indent=2 JSON数据的缩进,美观 |
||||
|
json.dump(return_text, f2, ensure_ascii=False, indent=4) |
||||
|
redis_.set(query_id, load_result_path, 86400) |
||||
|
# log.log('start at', |
||||
|
# 'query_id:{},load_result_path:{},return_text:{}, debug_id_1:{}, debug_id_2:{}, debug_id_3:{}'.format( |
||||
|
# query_id, load_result_path, return_text) |
||||
|
|
||||
|
|
||||
|
@app.route("/predict", methods=["POST"]) |
||||
|
def predict(): |
||||
|
print(request.remote_addr) |
||||
|
content = request.json["content"] |
||||
|
|
||||
|
id_ = str(uuid.uuid1()) # 为query生成唯一标识 |
||||
|
print("uuid: ", id_) |
||||
|
d = {'id': id_, 'text': content} # 绑定文本和query id |
||||
|
|
||||
|
load_request_path = './request_data_logs/{}.json'.format(id_) |
||||
|
with open(load_request_path, 'w', encoding='utf8') as f2: |
||||
|
# ensure_ascii=False才能输入中文,否则是Unicode字符 |
||||
|
# indent=2 JSON数据的缩进,美观 |
||||
|
json.dump(d, f2, ensure_ascii=False, indent=4) |
||||
|
redis_.rpush(db_key_query, json.dumps({"id": id_, "path": load_request_path})) # 加入redis |
||||
|
redis_.sadd(db_key_querying, id_) |
||||
|
return_text = {"texts": {'id': id_, }, "probabilities": None, "status_code": 200} |
||||
|
print("ok") |
||||
|
return jsonify(return_text) # 返回结果 |
||||
|
|
||||
|
|
||||
|
@app.route("/search", methods=["POST"]) |
||||
|
def search(): |
||||
|
id_ = request.json['id'] # 获取用户query中的文本 例如"I love you" |
||||
|
result = redis_.get(id_) # 获取该query的模型结果 |
||||
|
if result is not None: |
||||
|
# redis_.delete(id_) |
||||
|
result_path = result.decode('UTF-8') |
||||
|
with open(result_path, encoding='utf8') as f1: |
||||
|
# 加载文件的对象 |
||||
|
result_dict = json.load(f1) |
||||
|
texts = result_dict["output"] |
||||
|
result_text = {'code': 200, 'text': texts, 'probabilities': None} |
||||
|
else: |
||||
|
querying_list = list(redis_.smembers("querying")) |
||||
|
querying_set = set() |
||||
|
for i in querying_list: |
||||
|
querying_set.add(i.decode()) |
||||
|
|
||||
|
querying_bool = False |
||||
|
if id_ in querying_set: |
||||
|
querying_bool = True |
||||
|
|
||||
|
query_list_json = redis_.lrange(db_key_query, 0, -1) |
||||
|
query_set_ids = set() |
||||
|
for i in query_list_json: |
||||
|
data_dict = json.loads(i) |
||||
|
query_id = data_dict['id'] |
||||
|
query_set_ids.add(query_id) |
||||
|
|
||||
|
query_bool = False |
||||
|
if id_ in query_set_ids: |
||||
|
query_bool = True |
||||
|
|
||||
|
if querying_bool == True and query_bool == True: |
||||
|
result_text = {'code': "201", 'text': "", 'probabilities': None} |
||||
|
elif querying_bool == True and query_bool == False: |
||||
|
result_text = {'code': "202", 'text': "", 'probabilities': None} |
||||
|
else: |
||||
|
result_text = {'code': "203", 'text': "", 'probabilities': None} |
||||
|
load_request_path = './request_data_logs_203/{}.json'.format(id_) |
||||
|
with open(load_request_path, 'w', encoding='utf8') as f2: |
||||
|
# ensure_ascii=False才能输入中文,否则是Unicode字符 |
||||
|
# indent=2 JSON数据的缩进,美观 |
||||
|
json.dump(result_text, f2, ensure_ascii=False, indent=4) |
||||
|
|
||||
|
return jsonify(result_text) # 返回结果 |
||||
|
|
||||
|
|
||||
|
t = Thread(target=classify) |
||||
|
t.start() |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
logging.basicConfig(level=logging.DEBUG, # 控制台打印的日志级别 |
||||
|
filename='rewrite.log', |
||||
|
filemode='a', ##模式,有w和a,w就是写模式,每次都会重新写日志,覆盖之前的日志 |
||||
|
# a是追加模式,默认如果不写的话,就是追加模式 |
||||
|
format= |
||||
|
'%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s' |
||||
|
# 日志格式 |
||||
|
) |
||||
|
app.run(host="0.0.0.0", port=26000, threaded=True, debug=False) |
@ -0,0 +1,169 @@ |
|||||
|
import os |
||||
|
os.environ["CUDA_VISIBLE_DEVICES"] = "1,2,3,4" |
||||
|
from transformers import AutoModelForCausalLM, AutoTokenizer |
||||
|
import logging |
||||
|
from threading import Thread |
||||
|
import requests |
||||
|
import redis |
||||
|
import uuid |
||||
|
import time |
||||
|
import json |
||||
|
from flask import Flask, jsonify |
||||
|
from flask import request |
||||
|
import deepspeed |
||||
|
|
||||
|
app = Flask(__name__) |
||||
|
app.config["JSON_AS_ASCII"] = False |
||||
|
pool = redis.ConnectionPool(host='localhost', port=63179, max_connections=50,db=17, password="zhicheng123*") |
||||
|
redis_ = redis.Redis(connection_pool=pool, decode_responses=True) |
||||
|
|
||||
|
# model config |
||||
|
model_name = "/home/majiahui/project/models-llm/QwQ-32" |
||||
|
|
||||
|
ds_config = { |
||||
|
"dtype": "fp16", |
||||
|
"tensor_parallel": { |
||||
|
"tp_size": 4 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
model = AutoModelForCausalLM.from_pretrained(model_name) |
||||
|
tokenizer = AutoTokenizer.from_pretrained(model_name) |
||||
|
model = deepspeed.init_inference(model, config=ds_config) |
||||
|
|
||||
|
db_key_query = 'query' |
||||
|
db_key_querying = 'querying' |
||||
|
db_key_result = 'result' |
||||
|
batch_size = 15 |
||||
|
|
||||
|
|
||||
|
def main(prompt): |
||||
|
# prompt = "电视剧《人世间》导演和演员是谁" |
||||
|
inputs = tokenizer(prompt, return_tensors="pt").to("cuda") |
||||
|
output = model.generate(**inputs) |
||||
|
response = tokenizer.decode(output[0]) |
||||
|
return response |
||||
|
|
||||
|
|
||||
|
def classify(): # 调用模型,设置最大batch_size |
||||
|
while True: |
||||
|
if redis_.llen(db_key_query) == 0: # 若队列中没有元素就继续获取 |
||||
|
time.sleep(2) |
||||
|
continue |
||||
|
|
||||
|
query = redis_.lpop(db_key_query).decode('UTF-8') # 获取query的text |
||||
|
data_dict_path = json.loads(query) |
||||
|
path = data_dict_path['path'] |
||||
|
|
||||
|
with open(path, encoding='utf8') as f1: |
||||
|
# 加载文件的对象 |
||||
|
data_dict = json.load(f1) |
||||
|
|
||||
|
query_id = data_dict['id'] |
||||
|
input_text = data_dict["text"] |
||||
|
|
||||
|
output_text = main(input_text) |
||||
|
|
||||
|
return_text = { |
||||
|
"input": input_text, |
||||
|
"output": output_text |
||||
|
} |
||||
|
|
||||
|
load_result_path = "./new_data_logs/{}.json".format(query_id) |
||||
|
print("query_id: ", query_id) |
||||
|
print("load_result_path: ", load_result_path) |
||||
|
|
||||
|
with open(load_result_path, 'w', encoding='utf8') as f2: |
||||
|
# ensure_ascii=False才能输入中文,否则是Unicode字符 |
||||
|
# indent=2 JSON数据的缩进,美观 |
||||
|
json.dump(return_text, f2, ensure_ascii=False, indent=4) |
||||
|
redis_.set(query_id, load_result_path, 86400) |
||||
|
# log.log('start at', |
||||
|
# 'query_id:{},load_result_path:{},return_text:{}, debug_id_1:{}, debug_id_2:{}, debug_id_3:{}'.format( |
||||
|
# query_id, load_result_path, return_text) |
||||
|
|
||||
|
|
||||
|
@app.route("/predict", methods=["POST"]) |
||||
|
def predict(): |
||||
|
print(request.remote_addr) |
||||
|
content = request.json["content"] |
||||
|
|
||||
|
id_ = str(uuid.uuid1()) # 为query生成唯一标识 |
||||
|
print("uuid: ", id_) |
||||
|
d = {'id': id_, 'text': content} # 绑定文本和query id |
||||
|
|
||||
|
load_request_path = './request_data_logs/{}.json'.format(id_) |
||||
|
with open(load_request_path, 'w', encoding='utf8') as f2: |
||||
|
# ensure_ascii=False才能输入中文,否则是Unicode字符 |
||||
|
# indent=2 JSON数据的缩进,美观 |
||||
|
json.dump(d, f2, ensure_ascii=False, indent=4) |
||||
|
redis_.rpush(db_key_query, json.dumps({"id": id_, "path": load_request_path})) # 加入redis |
||||
|
redis_.sadd(db_key_querying, id_) |
||||
|
return_text = {"texts": {'id': id_, }, "probabilities": None, "status_code": 200} |
||||
|
print("ok") |
||||
|
return jsonify(return_text) # 返回结果 |
||||
|
|
||||
|
|
||||
|
@app.route("/search", methods=["POST"]) |
||||
|
def search(): |
||||
|
id_ = request.json['id'] # 获取用户query中的文本 例如"I love you" |
||||
|
result = redis_.get(id_) # 获取该query的模型结果 |
||||
|
if result is not None: |
||||
|
# redis_.delete(id_) |
||||
|
result_path = result.decode('UTF-8') |
||||
|
with open(result_path, encoding='utf8') as f1: |
||||
|
# 加载文件的对象 |
||||
|
result_dict = json.load(f1) |
||||
|
texts = result_dict["output"] |
||||
|
result_text = {'code': 200, 'text': texts, 'probabilities': None} |
||||
|
else: |
||||
|
querying_list = list(redis_.smembers("querying")) |
||||
|
querying_set = set() |
||||
|
for i in querying_list: |
||||
|
querying_set.add(i.decode()) |
||||
|
|
||||
|
querying_bool = False |
||||
|
if id_ in querying_set: |
||||
|
querying_bool = True |
||||
|
|
||||
|
query_list_json = redis_.lrange(db_key_query, 0, -1) |
||||
|
query_set_ids = set() |
||||
|
for i in query_list_json: |
||||
|
data_dict = json.loads(i) |
||||
|
query_id = data_dict['id'] |
||||
|
query_set_ids.add(query_id) |
||||
|
|
||||
|
query_bool = False |
||||
|
if id_ in query_set_ids: |
||||
|
query_bool = True |
||||
|
|
||||
|
if querying_bool == True and query_bool == True: |
||||
|
result_text = {'code': "201", 'text': "", 'probabilities': None} |
||||
|
elif querying_bool == True and query_bool == False: |
||||
|
result_text = {'code': "202", 'text': "", 'probabilities': None} |
||||
|
else: |
||||
|
result_text = {'code': "203", 'text': "", 'probabilities': None} |
||||
|
load_request_path = './request_data_logs_203/{}.json'.format(id_) |
||||
|
with open(load_request_path, 'w', encoding='utf8') as f2: |
||||
|
# ensure_ascii=False才能输入中文,否则是Unicode字符 |
||||
|
# indent=2 JSON数据的缩进,美观 |
||||
|
json.dump(result_text, f2, ensure_ascii=False, indent=4) |
||||
|
|
||||
|
return jsonify(result_text) # 返回结果 |
||||
|
|
||||
|
|
||||
|
t = Thread(target=classify) |
||||
|
t.start() |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
logging.basicConfig(level=logging.DEBUG, # 控制台打印的日志级别 |
||||
|
filename='rewrite.log', |
||||
|
filemode='a', ##模式,有w和a,w就是写模式,每次都会重新写日志,覆盖之前的日志 |
||||
|
# a是追加模式,默认如果不写的话,就是追加模式 |
||||
|
format= |
||||
|
'%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s' |
||||
|
# 日志格式 |
||||
|
) |
||||
|
app.run(host="0.0.0.0", port=26000, threaded=True, debug=False) |
||||
|
|
||||
|
|
@ -0,0 +1,303 @@ |
|||||
|
import os |
||||
|
os.environ["CUDA_VISIBLE_DEVICES"] = "1,2,3,4" |
||||
|
import argparse |
||||
|
from typing import List, Tuple |
||||
|
from threading import Thread |
||||
|
from vllm import EngineArgs, LLMEngine, RequestOutput, SamplingParams |
||||
|
from transformers import AutoTokenizer |
||||
|
# from vllm.utils import FlexibleArgumentParser |
||||
|
from flask import Flask, jsonify |
||||
|
from flask import request |
||||
|
import redis |
||||
|
import time |
||||
|
import json |
||||
|
import uuid |
||||
|
|
||||
|
|
||||
|
# http接口服务 |
||||
|
# app = FastAPI() |
||||
|
app = Flask(__name__) |
||||
|
app.config["JSON_AS_ASCII"] = False |
||||
|
|
||||
|
pool = redis.ConnectionPool(host='localhost', port=63179, max_connections=50,db=17, password="zhicheng123*") |
||||
|
redis_ = redis.Redis(connection_pool=pool, decode_responses=True) |
||||
|
|
||||
|
db_key_query = 'query' |
||||
|
db_key_querying = 'querying' |
||||
|
db_key_queryset = 'queryset' |
||||
|
db_key_result = 'result' |
||||
|
db_key_error = 'error' |
||||
|
batch_size = 2 |
||||
|
tokenizer = AutoTokenizer.from_pretrained("/home/majiahui/project/models-llm/QwQ-32") |
||||
|
|
||||
|
|
||||
|
def smtp_f(name): |
||||
|
# 在下面的代码行中使用断点来调试脚本。 |
||||
|
import smtplib |
||||
|
from email.mime.text import MIMEText |
||||
|
from email.header import Header |
||||
|
|
||||
|
sender = '838878981@qq.com' # 发送邮箱 |
||||
|
receivers = ['838878981@qq.com'] # 接收邮箱 |
||||
|
auth_code = "jfqtutaiwrtdbcge" # 授权码 |
||||
|
|
||||
|
message = MIMEText('基础大模型出现错误,紧急', 'plain', 'utf-8') |
||||
|
message['From'] = Header("Sender<%s>" % sender) # 发送者 |
||||
|
message['To'] = Header("Receiver<%s>" % receivers[0]) # 接收者 |
||||
|
|
||||
|
subject = name |
||||
|
message['Subject'] = Header(subject, 'utf-8') |
||||
|
|
||||
|
try: |
||||
|
server = smtplib.SMTP_SSL('smtp.qq.com', 465) |
||||
|
server.login(sender, auth_code) |
||||
|
server.sendmail(sender, receivers, message.as_string()) |
||||
|
print("邮件发送成功") |
||||
|
server.close() |
||||
|
except smtplib.SMTPException: |
||||
|
print("Error: 无法发送邮件") |
||||
|
|
||||
|
class log: |
||||
|
def __init__(self): |
||||
|
pass |
||||
|
|
||||
|
def log(*args, **kwargs): |
||||
|
format = '%Y/%m/%d-%H:%M:%S' |
||||
|
format_h = '%Y-%m-%d' |
||||
|
value = time.localtime(int(time.time())) |
||||
|
dt = time.strftime(format, value) |
||||
|
dt_log_file = time.strftime(format_h, value) |
||||
|
log_file = 'log_file/access-%s' % dt_log_file + ".log" |
||||
|
if not os.path.exists(log_file): |
||||
|
with open(os.path.join(log_file), 'w', encoding='utf-8') as f: |
||||
|
print(dt, *args, file=f, **kwargs) |
||||
|
else: |
||||
|
with open(os.path.join(log_file), 'a+', encoding='utf-8') as f: |
||||
|
print(dt, *args, file=f, **kwargs) |
||||
|
|
||||
|
|
||||
|
def initialize_engine() -> LLMEngine: |
||||
|
"""Initialize the LLMEngine from the command line arguments.""" |
||||
|
# model_dir = "/home/majiahui/project/models-llm/Qwen-0_5B-Chat" |
||||
|
# model_dir = "/home/majiahui/project/models-llm/openbuddy-qwen2.5llamaify-7b_train_11_prompt_mistral_gpt_xiaobiaot_real_paper" |
||||
|
# model_dir = "/home/majiahui/project/models-llm/openbuddy-qwen2.5llamaify-7b_train_11_prompt_mistral_gpt_xiaobiaot_real_paper_2" |
||||
|
# model_dir = "/home/majiahui/project/models-llm/Qwen2.5-7B-Instruct-1M" |
||||
|
# model_dir = "/home/majiahui/project/models-llm/openbuddy-qwen2.5llamaify-7b-v23.1-200k" |
||||
|
model_dir = "/home/majiahui/project/models-llm/QwQ-32" |
||||
|
args = EngineArgs(model_dir) |
||||
|
args.max_num_seqs = 2 # batch最大20条样本 |
||||
|
# args.gpu_memory_utilization = 0.8 |
||||
|
args.tensor_parallel_size = 4 |
||||
|
args.max_model_len=8192 |
||||
|
# 加载模型 |
||||
|
return LLMEngine.from_engine_args(args) |
||||
|
|
||||
|
engine = initialize_engine() |
||||
|
|
||||
|
|
||||
|
def create_test_prompts(prompt_texts, query_ids, sampling_params_list) -> List[Tuple[str,str, SamplingParams]]: |
||||
|
"""Create a list of test prompts with their sampling parameters.""" |
||||
|
|
||||
|
return_list = [] |
||||
|
|
||||
|
for i,j,k in zip(prompt_texts, query_ids, sampling_params_list): |
||||
|
return_list.append((i, j, k)) |
||||
|
return return_list |
||||
|
|
||||
|
|
||||
|
def process_requests(engine: LLMEngine, |
||||
|
test_prompts: List[Tuple[str, str, SamplingParams]]): |
||||
|
"""Continuously process a list of prompts and handle the outputs.""" |
||||
|
|
||||
|
return_list = [] |
||||
|
while test_prompts or engine.has_unfinished_requests(): |
||||
|
if test_prompts: |
||||
|
prompt, query_id, sampling_params = test_prompts.pop(0) |
||||
|
engine.add_request(str(query_id), prompt, sampling_params) |
||||
|
|
||||
|
request_outputs: List[RequestOutput] = engine.step() |
||||
|
|
||||
|
for request_output in request_outputs: |
||||
|
if request_output.finished: |
||||
|
return_list.append(request_output) |
||||
|
return return_list |
||||
|
|
||||
|
|
||||
|
def main(prompt_texts, query_ids, sampling_params_list): |
||||
|
"""Main function that sets up and runs the prompt processing.""" |
||||
|
|
||||
|
test_prompts = create_test_prompts(prompt_texts, query_ids, sampling_params_list) |
||||
|
return process_requests(engine, test_prompts) |
||||
|
|
||||
|
|
||||
|
def classify(batch_size): # 调用模型,设置最大batch_size |
||||
|
while True: |
||||
|
texts = [] |
||||
|
query_ids = [] |
||||
|
sampling_params_list = [] |
||||
|
if redis_.llen(db_key_query) == 0: # 若队列中没有元素就继续获取 |
||||
|
time.sleep(2) |
||||
|
continue |
||||
|
|
||||
|
# for i in range(min(redis_.llen(db_key_query), batch_size)): |
||||
|
while True: |
||||
|
query = redis_.lpop(db_key_query) # 获取query的text |
||||
|
if query == None: |
||||
|
break |
||||
|
|
||||
|
query = query.decode('UTF-8') |
||||
|
data_dict_path = json.loads(query) |
||||
|
|
||||
|
path = data_dict_path['path'] |
||||
|
with open(path, encoding='utf8') as f1: |
||||
|
# 加载文件的对象 |
||||
|
data_dict = json.load(f1) |
||||
|
# query_ids.append(json.loads(query)['id']) |
||||
|
# texts.append(json.loads(query)['text']) # 拼接若干text 为batch |
||||
|
query_id = data_dict['id'] |
||||
|
print("query_id", query_id) |
||||
|
text = data_dict["text"] |
||||
|
model = data_dict["model"] |
||||
|
top_p = data_dict["top_p"] |
||||
|
temperature = data_dict["temperature"] |
||||
|
presence_penalty = 1.1 |
||||
|
max_tokens = 8192 |
||||
|
query_ids.append(query_id) |
||||
|
messages = [ |
||||
|
{"role": "user", "content": text} |
||||
|
] |
||||
|
text = tokenizer.apply_chat_template( |
||||
|
messages, |
||||
|
tokenize=False, |
||||
|
add_generation_prompt=True |
||||
|
) |
||||
|
texts.append(text) |
||||
|
# sampling_params = SamplingParams(temperature=0.3, top_p=0.5, stop="<|end|>", presence_penalty=1.1, max_tokens=8192) |
||||
|
sampling_params_list.append(SamplingParams( |
||||
|
temperature=temperature, |
||||
|
top_p=top_p, |
||||
|
stop="<|im_end|>", |
||||
|
presence_penalty=presence_penalty, |
||||
|
max_tokens=max_tokens |
||||
|
)) |
||||
|
if len(texts) == batch_size: |
||||
|
break |
||||
|
|
||||
|
print("texts", len(texts)) |
||||
|
print("query_ids", len(query_ids)) |
||||
|
print("sampling_params_list", len(sampling_params_list)) |
||||
|
outputs = main(texts, query_ids, sampling_params_list) |
||||
|
|
||||
|
print("预测完成") |
||||
|
generated_text_dict = {} |
||||
|
print("outputs", len(outputs)) |
||||
|
for i, output in enumerate(outputs): |
||||
|
index = output.request_id |
||||
|
print(index) |
||||
|
generated_text = output.outputs[0].text |
||||
|
generated_text_dict[index] = generated_text |
||||
|
|
||||
|
print(generated_text_dict) |
||||
|
for id_, output in generated_text_dict.items(): |
||||
|
|
||||
|
return_text = {"texts": output, "probabilities": None, "status_code": 200} |
||||
|
load_result_path = "./new_data_logs/{}.json".format(id_) |
||||
|
with open(load_result_path, 'w', encoding='utf8') as f2: |
||||
|
# ensure_ascii=False才能输入中文,否则是Unicode字符 |
||||
|
# indent=2 JSON数据的缩进,美观 |
||||
|
json.dump(return_text, f2, ensure_ascii=False, indent=4) |
||||
|
redis_.set(id_, load_result_path, 86400) |
||||
|
# redis_.set(id_, load_result_path, 30) |
||||
|
redis_.srem(db_key_querying, id_) |
||||
|
log.log('start at', |
||||
|
'query_id:{},load_result_path:{},return_text:{}'.format( |
||||
|
id_, load_result_path, return_text)) |
||||
|
|
||||
|
|
||||
|
@app.route("/predict", methods=["POST"]) |
||||
|
def predict(): |
||||
|
content = request.json["content"] # 获取用户query中的文本 例如"I love you" |
||||
|
model = request.json["model"] |
||||
|
top_p = request.json["top_p"] |
||||
|
temperature = request.json["temperature"] |
||||
|
id_ = str(uuid.uuid1()) # 为query生成唯一标识 |
||||
|
print("uuid: ", uuid) |
||||
|
d = {'id': id_, 'text': content, 'model': model, 'top_p': top_p,'temperature': temperature} # 绑定文本和query id |
||||
|
print(d) |
||||
|
try: |
||||
|
load_request_path = './request_data_logs/{}.json'.format(id_) |
||||
|
with open(load_request_path, 'w', encoding='utf8') as f2: |
||||
|
# ensure_ascii=False才能输入中文,否则是Unicode字符 |
||||
|
# indent=2 JSON数据的缩进,美观 |
||||
|
json.dump(d, f2, ensure_ascii=False, indent=4) |
||||
|
redis_.rpush(db_key_query, json.dumps({"id": id_, "path": load_request_path})) # 加入redis |
||||
|
redis_.sadd(db_key_querying, id_) |
||||
|
redis_.sadd(db_key_queryset, id_) |
||||
|
return_text = {"texts": {'id': id_, }, "probabilities": None, "status_code": 200} |
||||
|
except: |
||||
|
return_text = {"texts": {'id': id_, }, "probabilities": None, "status_code": 400} |
||||
|
smtp_f("vllm-main-paper") |
||||
|
return jsonify(return_text) # 返回结果 |
||||
|
|
||||
|
|
||||
|
@app.route("/search", methods=["POST"]) |
||||
|
def search(): |
||||
|
id_ = request.json['id'] # 获取用户query中的文本 例如"I love you" |
||||
|
result = redis_.get(id_) # 获取该query的模型结果 |
||||
|
try: |
||||
|
if result is not None: |
||||
|
result_path = result.decode('UTF-8') |
||||
|
with open(result_path, encoding='utf8') as f1: |
||||
|
# 加载文件的对象 |
||||
|
result_dict = json.load(f1) |
||||
|
code = result_dict["status_code"] |
||||
|
texts = result_dict["texts"] |
||||
|
probabilities = result_dict["probabilities"] |
||||
|
if str(code) == 400: |
||||
|
redis_.rpush(db_key_error, json.dumps({"id": id_})) |
||||
|
return False |
||||
|
result_text = {'code': code, 'text': texts, 'probabilities': probabilities} |
||||
|
else: |
||||
|
querying_list = list(redis_.smembers(db_key_querying)) |
||||
|
querying_set = set() |
||||
|
for i in querying_list: |
||||
|
querying_set.add(i.decode()) |
||||
|
|
||||
|
querying_bool = False |
||||
|
if id_ in querying_set: |
||||
|
querying_bool = True |
||||
|
|
||||
|
query_list_json = redis_.lrange(db_key_query, 0, -1) |
||||
|
query_set_ids = set() |
||||
|
for i in query_list_json: |
||||
|
data_dict = json.loads(i) |
||||
|
query_id = data_dict['id'] |
||||
|
query_set_ids.add(query_id) |
||||
|
|
||||
|
query_bool = False |
||||
|
if id_ in query_set_ids: |
||||
|
query_bool = True |
||||
|
|
||||
|
if querying_bool == True and query_bool == True: |
||||
|
result_text = {'code': "201", 'text': "", 'probabilities': None} |
||||
|
elif querying_bool == True and query_bool == False: |
||||
|
result_text = {'code': "202", 'text': "", 'probabilities': None} |
||||
|
else: |
||||
|
result_text = {'code': "203", 'text': "", 'probabilities': None} |
||||
|
load_request_path = './request_data_logs_203/{}.json'.format(id_) |
||||
|
with open(load_request_path, 'w', encoding='utf8') as f2: |
||||
|
# ensure_ascii=False才能输入中文,否则是Unicode字符 |
||||
|
# indent=2 JSON数据的缩进,美观 |
||||
|
json.dump(result_text, f2, ensure_ascii=False, indent=4) |
||||
|
except: |
||||
|
smtp_f("vllm-main") |
||||
|
result_text = {'code': "400", 'text': "", 'probabilities': None} |
||||
|
return jsonify(result_text) # 返回结果 |
||||
|
|
||||
|
|
||||
|
t = Thread(target=classify, args=(batch_size,)) |
||||
|
t.start() |
||||
|
|
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
app.run(debug=False, host='0.0.0.0', port=26000) |
Loading…
Reference in new issue