Commit ea8e4d8c by Leo

upload code

parent 0ba55505
run = "pip install -r requirements.txt;streamlit run --server.enableXsrfProtection=false main.py"
run = "pip install -r requirements.txt;streamlit run --server.enableXsrfProtection=false main.py"
language = "python"
[packager]
AUTO_PIP = true
[env]
VIRTUAL_ENV = "/root/${PROJECT_DIR}/venv"
PATH = "${VIRTUAL_ENV}/bin:${PATH}"
PYTHONPATH = "$PYTHONHOME/lib/python3.10:${VIRTUAL_ENV}/lib/python3.10/site-packages"
REPLIT_POETRY_PYPI_REPOSITORY = "http://mirrors.csdn.net.cn/repository/csdn-pypi-mirrors/simple"
MPLBACKEND = "TkAgg"
POETRY_CACHE_DIR = "/root/${PROJECT_DIR}/.cache/pypoetry"
[debugger]
program = "main.py"
This source diff could not be displayed because it is too large. You can view the blob instead.
from openai import OpenAI
from openai import OpenAI
from tqdm import tqdm
import argparse
import os
import time
def parse_args():
parser = argparse.ArgumentParser(description="Train a language model with PEFT and LoRA.")
parser.add_argument("--model_name", type=str, default="sql-lora", help="Directory to save the trained model")
parser.add_argument("--jsol_output_name", type=str, default="model1.jsonl", help="Directory to save the trained model")
parser.add_argument("--start_vllm", type=str, default="True", help="Directory to save the trained model")
return parser.parse_args()
args = parse_args()
if args.start_vllm=="True":
time.sleep(180)
# Modify OpenAI's API key and API base to use vLLM's API server.
openai_api_key = "sk-xxx"
openai_api_base = "http://localhost:8000/v1"
# openai_api_base='http://127.0.0.1:8000/v1'
client = OpenAI(
api_key=openai_api_key,
base_url=openai_api_base,
)
print("----------------------开始查看日志----------------------")
try:
with open("nohup.out","r",encoding="utf8") as f:
data=f.read()
print(data)
except Exception as e:
print(e)
print("运行失败")
test_dir=os.path.join("/tcdata","round2_test_data.jsonl")
new_test_json_dir="round2_test_data_new.jsonl"
import pandas as pd
test_texts=pd.read_json(new_test_json_dir, lines=True)
pred_list=[]
try:
for i in tqdm(test_texts.values):
instruction = i[0]
input_value = i[1]
chat_response = client.chat.completions.create(
model=args.model_name,
messages = [
{"role": "system", "content": f"{instruction}"},
{"role": "user", "content": f"{input_value}"}
]
)
pred_list.append(chat_response.choices[0].message.content)
import json
data1=[]
with open(test_dir, "r",encoding="utf8") as file:
idx = 0
for line in file:
data_line = json.loads(line)
current_id = data_line["id"]
questions = data_line["questions"]
# 添加预测答案到问题列表中
combined_questions = []
for question in questions:
combined_questions.append({'answer': pred_list[idx]})
idx += 1
# 添加到结果数据中
data1.append({'id': current_id, 'questions': combined_questions})
with open(args.jsol_output_name, 'w', encoding='utf-8') as f:
for entry in data1:
f.write(json.dumps(entry, ensure_ascii=False) + '\n')
except:
pass
\ No newline at end of file
import json
import time
from string import Template
from typing import List, Dict, Optional
import requests
_PLANNER = '''你是一位出色的AI助手,擅长解决用户的问题,你的做法是将用户的问题分解为更小的子问题,
每个子问题都可以通过一个工具调用解决,每个工具需要提供工具名称、调用该工具的原因以及接受的参数,你的输出格式形如 [{"tool_name": "工具名称", "reason": "调用工具的原因", "params": {"param1": 1}]。
注意,输出不要包含额外的信息,只需要提供工具调用的信息。
你可以调用的工具列表及其描述如下:
$tool_desc
注意,你只能从上面给出的工具中选择合适的工具。
下面是示例:
用户的问题:如何快速掌握一个领域的知识?
输出:[{"tool_name": "GoogleSearch", "reason": "搜索领域知识", "params": {"query": "如何快速掌握一个领域的知识"}}]
接下来是用户的问题:$question
输出:
'''
_SOLVER = '''你是一位出色的AI助手,你可以基于用户的问题以及参考信息来回答用户的问题。
用户的问题:$question
参考信息:$reference
请基于用户的问题以及参考信息输出回答:
'''
PLANNER_TEMPLATE = Template(_PLANNER)
SOLVER_TEMPLATE = Template(_SOLVER)
class My_qwen2_5_response: ## 获取llm的一个回答
def __init__(self, client):
self.model = client
# self.tokenizer=tokenizer
def chat(self, messages: List[dict]):
chat_response = self.model.chat.completions.create(
model="qwen",
messages=messages
)
return chat_response.choices[0].message.content
class Tool:
@property
def name(self):
return self.__class__.__name__
def __call__(self, **kwargs) -> str:
raise NotImplementedError
class GoogleSearch(Tool):
"""使用谷歌搜索问题"""
description = '使用谷歌搜索问题,它的输入是一个问题,参数名为 query,输出是搜索结果。'
def __init__(self, api_key: Optional[str] = None, topk: int = 5) -> None:
self.api_key = 'f1718e344d6195e3e8234bdb957a8c6dd59ad84e'
self.base_url = 'https://google.serper.dev/search'
self.topk = topk
def __call__(self, query: str) -> str:
headers = {'x-api-key': self.api_key, 'Content-Type': 'application/json'}
response = requests.post(self.base_url, params={'q': query}, headers=headers)
print(response)
results = self._parse_snippets(response.json())
return ' '.join(results)
def _parse_snippets(self, results: dict) -> str:
# copy from https://github.com/langchain-ai/langchain
snippets = []
if results.get('answerBox'):
answer_box = results.get('answerBox', {})
if answer_box.get('answer'):
return [answer_box.get('answer')]
elif answer_box.get('snippet'):
return [answer_box.get('snippet').replace('\n', ' ')]
elif answer_box.get('snippetHighlighted'):
return answer_box.get('snippetHighlighted')
if results.get('knowledgeGraph'):
kg = results.get('knowledgeGraph', {})
title = kg.get('title')
entity_type = kg.get('type')
if entity_type:
snippets.append(f'{title}: {entity_type}.')
description = kg.get('description')
if description:
snippets.append(description)
for attribute, value in kg.get('attributes', {}).items():
snippets.append(f'{title} {attribute}: {value}.')
for result in results['organic'][:self.topk]:
if 'snippet' in result:
snippets.append(result['snippet'])
for attribute, value in result.get('attributes', {}).items():
snippets.append(f'{attribute}: {value}.')
if len(snippets) == 0:
assert False, 'No snippets found in the search results.'
return snippets
class CurrentTime(Tool): #CurrentTime:'获取当前时间的工具,它不接受输入,输出是当前时间。'
"""获取当前时间"""
description = '获取当前时间的工具,它不接受输入,输出是当前时间。'
def __call__(self) -> str:
currtent_time = time.asctime(time.localtime(time.time()))
return currtent_time
class Agent:
def __init__(self, llm, tools: List[Tool], retry: int = 3, verbose: bool = False):
self.llm = llm
self.name2tools = {tool.name: tool for tool in tools}
self.retry = retry
self.verbose = verbose
def chat(self, message: str):
parsed_tools = self._plan(message) ## 规划
action_res = self._action(parsed_tools) ## 执行
output = self._gen_output(message, action_res) ##结合生成输出
return output
def _plan(self, message: str) -> List[dict]:
"""规划工具调用"""
tool_desc = '\n'.join([f'- {name}: {tool.description}' for name, tool in self.name2tools.items()])
# print(tool_desc)
content = PLANNER_TEMPLATE.substitute(tool_desc=tool_desc, question=message)
# print()
if self.verbose:
print(f'\nllm input: {content}')
for _ in range(self.retry):
response = self.llm.chat([{'role': 'user', 'content': content}])
if self.verbose:
print(f'\nllm output: {response}')
parsed_tools = json.loads(response.strip().lstrip('```json').rstrip('```'))
if isinstance(parsed_tools, list) and all(isinstance(tool, dict) for tool in parsed_tools):
return parsed_tools
else:
assert False, 'Failed to parse tools from llm response.'
def _action(self, tools: List[dict]) -> Dict[str, str]:
"""调用工具"""
res = {}
for tool_info in tools:
name = tool_info['tool_name']
#res= CurrentTime() xxxx GoogleSearch("如何快速掌握一个领域的知识")
res[name] = self.name2tools[name](**tool_info['params']) #CurrentTime()
if self.verbose:
print(f'\naction_res: {res}')
return res
def _gen_output(self, message: str, action_res: Dict[str, str]) -> str:
"""根据用户输入和工具调用结果生成回答"""
content = SOLVER_TEMPLATE.substitute(question=message, reference=json.dumps(action_res, ensure_ascii=False))
if self.verbose:
print(f'\ncontent: {content}')
output = self.llm.chat([{'role': 'user', 'content': content}])
return output
\ No newline at end of file
{"id":1,"bingli_json":"{ \"诊断\": \"自觉发热原因待查\", \"诊断依据\": \"1. 患者主诉发热10天,但最高体温为36.7℃,体检时体温36.08℃,均在正常范围内,未达发热标准(≥37.3℃);\\n2. 无咳嗽、咳痰、畏寒、寒战等呼吸道感染症状;无尿频、尿急、尿痛等泌尿系感染症状;无腹痛、腹泻等消化道症状;\\n3. 无全身乏力、体重减轻、盗汗等全身性症状;\\n4. 既往体健,无慢性疾病史;\\n5. 为明确患者自觉发热的原因,需进一步完善检查,如血常规、炎症指标、甲状腺功能等,排除感染、内分泌疾病或其他潜在病因。\"}","diseases":"发热","feature_content":"性别: 男\n年龄: 65\n主诉: 发热10天\n现病史: 患者10天前无明显诱因开始出现发热,体温最高36.7℃,无咳嗽咳痰,无畏寒、寒战,无鼻塞流涕,无咽痛,无周身乏力,无嗅觉味觉减退,无胸闷、憋气,无头痛头晕,无恶心呕吐,无腹痛腹泻,无尿频、尿急、尿痛不适,于当地输液治疗,为求进一步治疗,来我院就诊。\n既往史: 无\n个人史: 有新型冠状病毒疫苗接种史,共3针。\n过敏史: \n婚育史: \n流行病史: \n体格检查: T36.08℃。\n辅助检查: "}
{"id":1,"bingli_json":"{ \"诊断\": \"自觉发热原因待查\", \"诊断依据\": \"1. 患者主诉发热10天,但最高体温为36.7℃,体检时体温36.08℃,均在正常范围内,未达发热标准(≥37.3℃);\\n2. 无咳嗽、咳痰、畏寒、寒战等呼吸道感染症状;无尿频、尿急、尿痛等泌尿系感染症状;无腹痛、腹泻等消化道症状;\\n3. 无全身乏力、体重减轻、盗汗等全身性症状;\\n4. 既往体健,无慢性疾病史;\\n5. 为明确患者自觉发热的原因,需进一步完善检查,如血常规、炎症指标、甲状腺功能等,排除感染、内分泌疾病或其他潜在病因。\"}","diseases":"发热","feature_content":"性别: 男\n年龄: 65\n主诉: 发热10天\n现病史: 患者10天前无明显诱因开始出现发热,体温最高36.7℃,无咳嗽咳痰,无畏寒、寒战,无鼻塞流涕,无咽痛,无周身乏力,无嗅觉味觉减退,无胸闷、憋气,无头痛头晕,无恶心呕吐,无腹痛腹泻,无尿频、尿急、尿痛不适,于当地输液治疗,为求进一步治疗,来我院就诊。\n既往史: 无\n个人史: 有新型冠状病毒疫苗接种史,共3针。\n过敏史: \n婚育史: \n流行病史: \n体格检查: T36.08℃。\n辅助检查: "}
{"id":2,"bingli_json":"{ \"诊断\": \"1. 高尿酸血症;2. 皮炎;3. 失眠;4. 原发性高血压(1级)。\", \"诊断依据\": \"1. 主诉中提到高尿酸血症,提示患者血尿酸水平升高;\\n2. 主诉中提到皮炎,提示存在皮肤炎症,可能为过敏性或接触性皮炎;\\n3. 主诉中提到失眠,提示存在睡眠障碍,可能与精神压力或其他疾病有关;\\n4. 体格检查中血压142\/78mmHg,收缩压≥140mmHg,提示存在1级高血压;\\n5. 无发热、感染等症状,生命体征基本正常,心肺腹部检查未见明显异常。\"}","diseases":"皮炎|失眠|高尿酸血症","feature_content":"性别: 女\n年龄: 45\n主诉: 皮炎失眠高尿酸血症\n现病史: 给予中药治疗。无发热、干咳、乏力、嗅(味)觉减退、鼻塞、流涕、咽痛、结膜炎、肌痛、腹泻\n既往史: \n个人史: 无发病前14天内有病例报告社区的旅行史或居住史;无发病前14天内与新型冠状病毒感染的患者或无症状感染者有接触史;无发病前14天内曾接触过来自有病例报告社区的发热或有呼吸道症状的患者;无聚集性发病;近14天内无进口冷链食品接触史。\n过敏史: \n婚育史: \n流行病史: \n体格检查: T36.5℃,P78次\/分,R20次\/分,BP142\/78mmHg。心肺听诊未见异常,腹平软,无压痛。\n辅助检查: "}
{"id":3,"bingli_json":"{ \"诊断\": \"多囊卵巢综合征(PCOS)导致的不孕症\", \"诊断依据\": \"1. 患者25岁,与丈夫未避孕未怀孕3年,符合不孕症的诊断标准;2. 患者多次经阴道B超提示多囊卵巢(PCO)表现,已诊断为多囊卵巢综合征(PCOS);3. 末次月经为2023年7月2日,月经周期不规律,符合PCOS的临床特征;4. 体格检查血压正常,无特殊异常,辅助检查暂未见明显异常。\"}","diseases":"多囊卵巢综合征","feature_content":"性别: 女\n年龄: 25\n主诉: 未避孕未怀孕3年\n现病史: 2018年起与丈夫有性生活,2020年起未避孕未怀孕至今3年,2021年12月登记结婚。LMP2023.7.2,我科多次阴B提示PCO,诊断PCOS。\n既往史: 无特殊\n个人史: \n过敏史: 无\n婚育史: \n流行病史: 暂无\n体格检查: 血压(收缩压\/舒张压)110\/60mmHg \n 空腹血糖测定值:mmol\/L \n 餐后血糖测定值:mmol\/L \n T:℃ \n P:次\/分 \n R:次\/分 \n 神志: \n 呼吸: \n \n辅助检查: 2023-06-14,UU-DNA"}
{"id":10001,"reason":"1. 患者主诉发热10天,但最高体温为36.7℃,体检时体温36.08℃,均在正常范围内,未达发热标准(≥37.3℃);\\n2. 无咳嗽、咳痰、畏寒、寒战等呼吸道感染症状;无尿频、尿急、尿痛等泌尿系感染症状;无腹痛、腹泻等消化道症状;\\n3. 无全身乏力、体重减轻、盗汗等全身性症状;\\n4. 既往体健,无慢性疾病史;\\n5. 为明确患者自觉发热的原因,需进一步完善检查,如血常规、炎症指标、甲状腺功能等,排除感染、内分泌疾病或其他潜在病因。","diseases":"发热","feature_content":"性别: 男\n年龄: 65\n主诉: 发热10天\n现病史: 患者10天前无明显诱因开始出现发热,体温最高36.7℃,无咳嗽咳痰,无畏寒、寒战,无鼻塞流涕,无咽痛,无周身乏力,无嗅觉味觉减退,无胸闷、憋气,无头痛头晕,无恶心呕吐,无腹痛腹泻,无尿频、尿急、尿痛不适,于当地输液治疗,为求进一步治疗,来我院就诊。\n既往史: 无\n个人史: 有新型冠状病毒疫苗接种史,共3针。\n过敏史: \n婚育史: \n流行病史: \n体格检查: T36.08℃。\n辅助检查: "}
{"id":10001,"reason":"1. 患者主诉发热10天,但最高体温为36.7℃,体检时体温36.08℃,均在正常范围内,未达发热标准(≥37.3℃);\\n2. 无咳嗽、咳痰、畏寒、寒战等呼吸道感染症状;无尿频、尿急、尿痛等泌尿系感染症状;无腹痛、腹泻等消化道症状;\\n3. 无全身乏力、体重减轻、盗汗等全身性症状;\\n4. 既往体健,无慢性疾病史;\\n5. 为明确患者自觉发热的原因,需进一步完善检查,如血常规、炎症指标、甲状腺功能等,排除感染、内分泌疾病或其他潜在病因。","diseases":"发热","feature_content":"性别: 男\n年龄: 65\n主诉: 发热10天\n现病史: 患者10天前无明显诱因开始出现发热,体温最高36.7℃,无咳嗽咳痰,无畏寒、寒战,无鼻塞流涕,无咽痛,无周身乏力,无嗅觉味觉减退,无胸闷、憋气,无头痛头晕,无恶心呕吐,无腹痛腹泻,无尿频、尿急、尿痛不适,于当地输液治疗,为求进一步治疗,来我院就诊。\n既往史: 无\n个人史: 有新型冠状病毒疫苗接种史,共3针。\n过敏史: \n婚育史: \n流行病史: \n体格检查: T36.08℃。\n辅助检查: "}
{"id":10001,"reason":"1. 主诉中提到高尿酸血症,提示患者血尿酸水平升高;\\n2. 主诉中提到皮炎,提示存在皮肤炎症,可能为过敏性或接触性皮炎;\\n3. 主诉中提到失眠,提示存在睡眠障碍,可能与精神压力或其他疾病有关;\\n4. 体格检查中血压142\/78mmHg,收缩压≥140mmHg,提示存在1级高血压;\\n5. 无发热、感染等症状,生命体征基本正常,心肺腹部检查未见明显异常。","diseases":"1. 高尿酸血症;2. 皮炎;3. 失眠;4. 原发性高血压(1级)","feature_content":"性别: 女\n年龄: 45\n主诉: 皮炎失眠高尿酸血症\n现病史: 给予中药治疗。无发热、干咳、乏力、嗅(味)觉减退、鼻塞、流涕、咽痛、结膜炎、肌痛、腹泻\n既往史: \n个人史: 无发病前14天内有病例报告社区的旅行史或居住史;无发病前14天内与新型冠状病毒感染的患者或无症状感染者有接触史;无发病前14天内曾接触过来自有病例报告社区的发热或有呼吸道症状的患者;无聚集性发病;近14天内无进口冷链食品接触史。\n过敏史: \n婚育史: \n流行病史: \n体格检查: T36.5℃,P78次\/分,R20次\/分,BP142\/78mmHg。心肺听诊未见异常,腹平软,无压痛。\n辅助检查: "}
{"id":10001,"reason":"1. 患者25岁,与丈夫未避孕未怀孕3年,符合不孕症的诊断标准;2. 患者多次经阴道B超提示多囊卵巢(PCO)表现,已诊断为多囊卵巢综合征(PCOS);3. 末次月经为2023年7月2日,月经周期不规律,符合PCOS的临床特征;4. 体格检查血压正常,无特殊异常,辅助检查暂未见明显异常。","diseases":"多囊卵巢综合征(PCOS)","feature_content":"性别: 女\n年龄: 25\n主诉: 未避孕未怀孕3年\n现病史: 2018年起与丈夫有性生活,2020年起未避孕未怀孕至今3年,2021年12月登记结婚。LMP2023.7.2,我科多次阴B提示PCO,诊断PCOS。\n既往史: 无特殊\n个人史: \n过敏史: 无\n婚育史: \n流行病史: 暂无\n体格检查: 血压(收缩压\/舒张压)110\/60mmHg \n 空腹血糖测定值:mmol\/L \n 餐后血糖测定值:mmol\/L \n T:℃ \n P:次\/分 \n R:次\/分 \n 神志: \n 呼吸: \n \n辅助检查: 2023-06-14,UU-DNA"}
This source diff could not be displayed because it is too large. You can view the blob instead.
{ pkgs }: {
{ pkgs }: {
deps = [
pkgs.python310Packages.pip
pkgs.python310Full
];
}
\ No newline at end of file
import streamlit as st
import streamlit as st
from streamlit_option_menu import option_menu
import numpy as np
import pandas as pd
import time
from openai import OpenAI
from tqdm import tqdm
from string import Template
from agent import Agent,My_qwen2_5_response,GoogleSearch,CurrentTime
from rag import extract_text_from_pdf,split_text,extract_text_from_docx,embed_and_index,retrieve_relevant_chunks,extract_text_from_txt
# 设置Streamlit应用程序的标题
st.set_page_config(page_title="streamlit WebUI", layout="wide")
st.sidebar.title("streamlit samples")
menu1="LLM+RAG"
menu2="LLM+Agent"
menu3="LLM-chat"
#本地llm
# model_dir="/home/un/桌面/QC/qwen2_5/Qwen2.5-7B-Instruct/"
# llm = vllm.LLM(
# model_dir,
# tensor_parallel_size=1,
# gpu_memory_utilization=0.90,
# trust_remote_code=True,
# enforce_eager=True,
# max_model_len=2800,
# disable_log_stats=True,
# )
# tokenizer = llm.get_tokenizer()
#后台vllm
openai_api_key = "sk-xxx"
openai_api_base = "http://localhost:8000/v1"
client = OpenAI(
api_key=openai_api_key,
base_url=openai_api_base,
)
with st.sidebar:
menu = option_menu("功能分类", [menu1, menu2,menu3],
icons=['house', "list-task"],
menu_icon="cast", default_index=0)
def main():
if menu == menu1:
# st.subheader("LLM+RAG")
show_llm_rag(client)
if menu == menu2:
# st.subheader("LLM+Agent")
show_llm_agent(client)
if menu == menu3:
# st.subheader("LLM-chat")
showLLMChatbot(client)
def get_llm_response(prompts,client):
chat_response = client.chat.completions.create(
model="qwen",
messages = [
{"role": "system", "content": f"You are a helpful assistant."},
{"role": "user", "content": f"{prompts}"}
]
)
return chat_response.choices[0].message.content
#显示dataframe
def show_llm_rag(client):
st.title("基于 LangChain 的 RAG 系统")
st.caption("🚀 支持上传 PDF 或 Word 文件,构建向量数据库并进行对话问答。")
# 文件上传
uploaded_file = st.file_uploader("上传 PDF 或 Word 文件", type=["pdf", "docx","txt"])
if uploaded_file is not None:
# 保存上传文件到本地
file_path = f"uploaded_{uploaded_file.name}"
with open(file_path, "wb") as f:
f.write(uploaded_file.getbuffer())
# 提取文本
if file_path.endswith(".pdf"):
text = extract_text_from_pdf(file_path)
elif file_path.endswith(".docx"):
text = extract_text_from_docx(file_path)
elif file_path.endswith(".txt"):
text = extract_text_from_txt(file_path)
else:
st.error("不支持的文件格式,请上传 PDF 或 Word txt 文件。")
return
# 分块处理
chunks = split_text(text)
st.info(f"文档已分块,共 {len(chunks)} 个块。")
# 构建或加载向量数据库
index, embeddings = embed_and_index(chunks)
st.success("向量数据库构建完成。")
if "messages_rag" not in st.session_state:
st.session_state.messages_rag = []
# st.session_state.messages_rag_context = []
for message in st.session_state.messages_rag:
with st.chat_message(message["role"]):
# st.write(message["content"])
st.write(message["content"])
if "context" in message: # 如果存在上下文,显示在 expander 中
with st.expander("点击查看检索到的相关文档块", expanded=False):
for i, chunk in enumerate(message["context"]):
st.write(f"块 {i + 1}: {chunk}")
# 用户输入问题并检索相关块
user_input = st.chat_input("请输入您的问题:")
if user_input:
# st.session_state.messages_rag.append({"role": "user", "content": user_input})
with st.chat_message("user"):
st.write(user_input)
# 检索相关块
relevant_chunks = retrieve_relevant_chunks(user_input, index, chunks)
# st.subheader("检索到的相关文档块:")
# for i, chunk in enumerate(relevant_chunks):
# st.write(f"块 {i + 1}: {chunk}")
with st.expander("检索到的相关文档块", expanded=False): # 默认折叠
for i, chunk in enumerate(relevant_chunks):
st.write(f"块 {i + 1}: {chunk}")
# st.session_state.messages_rag_context(chunk)
st.session_state.messages_rag.append({
"role": "user",
"content": user_input,
"context": relevant_chunks # 保存检索到的上下文
})
context = "\n".join(relevant_chunks)
# print(context)
inputs = user_input+"\n"+f"这是检索的相关内容:\n{context}"
# st.subheader("回答:")
# st.write(inputs)
import gc
gc.collect()
with st.chat_message("assistant"):
assistant_response=get_llm_response(inputs,client)
# assistant_response = "感谢您的提问!我会逐步回答您的问题。"
placeholder = st.empty() # 创建一个占位符用于流式输出
full_response = ""
for chunk in assistant_response.split(): # 模拟逐词输出
full_response += chunk + " "
time.sleep(0.05) # 模拟延迟
placeholder.markdown(full_response) # 更新占位符内容
# st.session_state.messages_rag.append({"role": "assistant", "content": full_response.strip()})
st.session_state.messages_rag.append({
"role": "assistant",
"content": full_response.strip()
})
def show_llm_agent(client):
# 设置页面标题
st.title("千城老师的 💬 大语言LLM结合agent聊天机器人")
st.caption("🚀 欢迎使用!本系统支持agent,可以联网搜索和查看时间。")
# 初始化会话状态
if "messages_agent" not in st.session_state:
st.session_state.messages_agent = []
# 显示历史对话
for message in st.session_state.messages_agent:
with st.chat_message(message["role"]):
st.write(message["content"])
# 获取用户输入
user_input = st.chat_input("请输入您的问题...")
if user_input:
# 保存用户输入到会话状态
st.session_state.messages_agent.append({"role": "user", "content": user_input})
with st.chat_message("user"):
st.write(user_input)
# 模拟机器人回复(流式输出)
with st.chat_message("assistant"):
assistant_response=get_llm_agent(user_input,client)
# assistant_response = "感谢您的提问!我会逐步回答您的问题。"
placeholder = st.empty() # 创建一个占位符用于流式输出
full_response = ""
for chunk in assistant_response.split(): # 模拟逐词输出
full_response += chunk + " "
time.sleep(0.05) # 模拟延迟
placeholder.markdown(full_response) # 更新占位符内容
st.session_state.messages_agent.append({"role": "assistant", "content": full_response.strip()})
def get_llm_agent(prompts,client):
llms = My_qwen2_5_response(client)
agent = Agent(llms, tools=[GoogleSearch(),CurrentTime()], verbose=True)
messages = prompts
outputs=agent.chat(messages)
return outputs
def showLLMChatbot(client):
# 设置页面标题
st.title("千城老师的 💬 大语言LLM聊天机器人")
st.caption("🚀 欢迎使用!本系统使用了微调大模型,本地部署,构建本地私有定制聊天机器人。")
# 初始化会话状态
if "messages" not in st.session_state:
st.session_state.messages = []
# 显示历史对话
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.write(message["content"])
# 获取用户输入 text_input
user_input = st.chat_input("请输入您的问题...")
if user_input:
# 保存用户输入到会话状态
st.session_state.messages.append({"role": "user", "content": user_input})
with st.chat_message("user"):
st.write(user_input)
# 模拟机器人回复(流式输出)
with st.chat_message("assistant"):
### 多轮对话
prompts="""对话历史信息:\n{}
"""
conversation_history = [{"role": msg["role"], "content": msg["content"]} for msg in st.session_state.messages]
if len(conversation_history)>10:
conversation_history=conversation_history[int(len(conversation_history)*0.5):]
d_prompt=prompts.format("\n".join([f"{msg['role']}: {msg['content']}" for msg in conversation_history]),user_input)
print(d_prompt)
assistant_response=get_llm_response(d_prompt,client)
placeholder = st.empty() # 创建一个占位符用于流式输出
full_response = ""
for chunk in assistant_response.split(): # 模拟逐词输出
full_response += chunk + " "
time.sleep(0.05) # 模拟延迟
placeholder.markdown(full_response) # 更新占位符内容
st.session_state.messages.append({"role": "assistant", "content": full_response.strip()})
if __name__ == '__main__':
main()
This source diff could not be displayed because it is too large. You can view the blob instead.
import os
import os
from PyPDF2 import PdfReader
from docx import Document
from sentence_transformers import SentenceTransformer
from langchain.text_splitter import RecursiveCharacterTextSplitter
import faiss #构建索引和向量数据库的
import numpy as np
# 初始化 bge-中文模型
embedding_model = SentenceTransformer('/home/un/桌面/QC/Streamlit-master/bge-large-zh-v1.5')
# 文本分块函数
def split_text(text, chunk_size=512, chunk_overlap=50):
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=chunk_overlap,
length_function=len
)
chunks = text_splitter.split_text(text)
return chunks
# 提取 PDF 文本
def extract_text_from_pdf(file_path):
reader = PdfReader(file_path)
text = ""
for page in reader.pages:
text += page.extract_text()
return text
# 提取 Word 文本
def extract_text_from_docx(file_path):
doc = Document(file_path)
text = "\n".join([para.text for para in doc.paragraphs])
return text
# 提取 txt 文本
def extract_text_from_txt(file_path):
with open(file_path,"r",encoding="utf-8") as f:
text = f.read()
# doc = Document(file_path)
# text = "\n".join([para.text for para in doc.paragraphs])
return text
# 嵌入向量并保存到 FAISS 索引
def embed_and_index(chunks):
embeddings = embedding_model.encode(chunks)
dimension = embeddings.shape[1]
index = faiss.IndexFlatL2(dimension) # 使用 L2 距离计算相似度
index.add(np.array(embeddings))
return index, embeddings
# 检索相关文档块
def retrieve_relevant_chunks(query, index, chunks, top_k=3):
query_embedding = embedding_model.encode([query])
distances, indices = index.search(np.array(query_embedding), top_k) #相似度计算 3 l2
relevant_chunks = [chunks[i] for i in indices[0]]
return relevant_chunks
# 主函数:处理上传文件并构建 RAG 系统
def main():
print("欢迎使用基于 LangChain 的 RAG 系统!")
file_path = input("请输入 PDF 或 Word 文件路径:")
# 提取文本
if file_path.endswith(".pdf"):
text = extract_text_from_pdf(file_path)
elif file_path.endswith(".docx"):
text = extract_text_from_docx(file_path)
elif file_path.endswith(".docx"):
text = extract_text_from_txt(file_path)
else:
raise ValueError("不支持的文件格式,请上传 PDF 或 Word 文件。")
# 分块处理
chunks = split_text(text)
print(f"文档已分块,共 {len(chunks)} 个块。")
# 生成嵌入并保存到 FAISS 索引
index, embeddings = embed_and_index(chunks)
print("嵌入向量已生成并保存到 FAISS 索引。")
# 用户输入问题并检索相关块
while True:
query = input("请输入您的问题(输入 'exit' 退出):")
if query.lower() == "exit":
break
# 检索相关块
relevant_chunks = retrieve_relevant_chunks(query, index, chunks)
print("检索到的相关文档块:")
for i, chunk in enumerate(relevant_chunks):
print(f"块 {i + 1}: {chunk}")
# 结合相关块生成回答(这里可以集成大语言模型)
context = "\n".join(relevant_chunks)
response = f"根据检索到的内容,以下是回答:\n{context}"
print(response)
# if __name__ == "__main__":
# main()
\ No newline at end of file
North-D博客:northd.blog.csdn.net
North-D博客:northd.blog.csdn.net
# 说明:
Streamlit-northd是一个集成了streamlit的例程的框架程序。当前版本:V0.0.1。
目前已经集成了:
- 显示dataframe
- 显示折线图
- 显示地图
- 显示进度条
- 大语言模型LLM对话框
# 继续更新中...
TODO
pip install python-docx
pip install python-docx
pip install PyPDF2
pip install langchain_core
pip install langchain
pip install streamlit
pip install sentence-transformers
pip install openai
pip install faiss-cpu
pip isntall vllm
pip install transformers
pip install torch
pip install datasets
nohup python -m vllm.entrypoints.openai.api_server \
nohup python -m vllm.entrypoints.openai.api_server \
--model /home/un/桌面/QC/qwen2_5/Qwen2.5-7B-Instruct/ \
--served-model-name qwen \
--max-model-len=2800 \
--enforce-eager
# --enable-lora \
# --lora-modules sql-lora=checkpoint1-6328
\ No newline at end of file
import argparse
import argparse
import json
import os
import time
from string import Template
from typing import List, Dict, Optional
import requests
from openai import OpenAI
from transformers import AutoTokenizer,AutoModelForCausalLM
_PLANNER = '''你是一位出色的AI助手,擅长解决用户的问题,你的做法是将用户的问题分解为更小的子问题,
每个子问题都可以通过一个工具调用解决,每个工具需要提供工具名称、调用该工具的原因以及接受的参数,你的输出格式形如 [{"tool_name": "工具名称", "reason": "调用工具的原因", "params": {"param1": 1}]。
注意,输出不要包含额外的信息,只需要提供工具调用的信息。
你可以调用的工具列表及其描述如下:
$tool_desc
注意,你只能从上面给出的工具中选择合适的工具。
下面是示例:
用户的问题:如何快速掌握一个领域的知识?
输出:[{"tool_name": "GoogleSearch", "reason": "搜索领域知识", "params": {"query": "如何快速掌握一个领域的知识"}}]
接下来是用户的问题:$question
输出:
'''
_SOLVER = '''你是一位出色的AI助手,你可以基于用户的问题以及参考信息来回答用户的问题。
用户的问题:$question
参考信息:$reference
请基于用户的问题以及参考信息输出回答:
'''
PLANNER_TEMPLATE = Template(_PLANNER)
SOLVER_TEMPLATE = Template(_SOLVER)
class My_qwen2_5_response:
def __init__(self, model_path):
self.model = AutoModelForCausalLM.from_pretrained(model_path,torch_dtype="auto",device_map="auto")
self.tokenizer=AutoTokenizer.from_pretrained(model_path)
def chat(self, messages: List[dict]):
text = self.tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
model_inputs = self.tokenizer([text], return_tensors="pt").to(self.model.device)
generated_ids = self.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 = self.tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
# print(response)
return response
# qwen=My_qwen2_5_response("/home/un/桌面/QC/2024_全国大数据智能大赛/342000_点头教育科技有限公司/data/user_data/Qwen2.5-7B-Instruct")
# prompt = "今天天气是什么?"
# messages = [
# {"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},
# {"role": "user", "content": prompt}
# ]
# responses=qwen.chat(messages)
# print(responses)
class Tool:
@property
def name(self):
return self.__class__.__name__
def __call__(self, **kwargs) -> str:
raise NotImplementedError
class GoogleSearch(Tool):
"""使用谷歌搜索问题"""
description = '使用谷歌搜索问题,它的输入是一个问题,参数名为 query,输出是搜索结果。'
def __init__(self, api_key: Optional[str] = None, topk: int = 5) -> None:
self.api_key = 'f1718e344d6195e3e8234bdb957a8c6dd59ad84e'
self.base_url = 'https://google.serper.dev/search'
self.topk = topk
def __call__(self, query: str) -> str:
headers = {'x-api-key': self.api_key, 'Content-Type': 'application/json'}
response = requests.post(self.base_url, params={'q': query}, headers=headers)
print(response)
results = self._parse_snippets(response.json())
return ' '.join(results)
def _parse_snippets(self, results: dict) -> str:
# copy from https://github.com/langchain-ai/langchain
snippets = []
if results.get('answerBox'):
answer_box = results.get('answerBox', {})
if answer_box.get('answer'):
return [answer_box.get('answer')]
elif answer_box.get('snippet'):
return [answer_box.get('snippet').replace('\n', ' ')]
elif answer_box.get('snippetHighlighted'):
return answer_box.get('snippetHighlighted')
if results.get('knowledgeGraph'):
kg = results.get('knowledgeGraph', {})
title = kg.get('title')
entity_type = kg.get('type')
if entity_type:
snippets.append(f'{title}: {entity_type}.')
description = kg.get('description')
if description:
snippets.append(description)
for attribute, value in kg.get('attributes', {}).items():
snippets.append(f'{title} {attribute}: {value}.')
for result in results['organic'][:self.topk]:
if 'snippet' in result:
snippets.append(result['snippet'])
for attribute, value in result.get('attributes', {}).items():
snippets.append(f'{attribute}: {value}.')
if len(snippets) == 0:
assert False, 'No snippets found in the search results.'
return snippets
class CurrentTime(Tool):
"""获取当前时间"""
description = '获取当前时间的工具,它不接受输入,输出是当前时间。'
def __call__(self) -> str:
currtent_time = time.asctime(time.localtime(time.time()))
return currtent_time
class Agent:
def __init__(self, llm, tools: List[Tool], retry: int = 3, verbose: bool = False):
self.llm = llm
self.name2tools = {tool.name: tool for tool in tools}
self.retry = retry
self.verbose = verbose
def chat(self, message: str):
parsed_tools = self._plan(message)
action_res = self._action(parsed_tools)
output = self._gen_output(message, action_res)
return output
def _plan(self, message: str) -> List[dict]:
"""规划工具调用"""
tool_desc = '\n'.join([f'- {name}: {tool.description}' for name, tool in self.name2tools.items()])
content = PLANNER_TEMPLATE.substitute(tool_desc=tool_desc, question=message)
if self.verbose:
print(f'\nllm input: {content}')
for _ in range(self.retry):
response = self.llm.chat([{'role': 'user', 'content': content}])
if self.verbose:
print(f'\nllm output: {response}')
parsed_tools = json.loads(response.strip().lstrip('```json').rstrip('```'))
if isinstance(parsed_tools, list) and all(isinstance(tool, dict) for tool in parsed_tools):
return parsed_tools
else:
assert False, 'Failed to parse tools from llm response.'
def _action(self, tools: List[dict]) -> Dict[str, str]:
"""调用工具"""
res = {}
for tool_info in tools:
name = tool_info['tool_name']
res[name] = self.name2tools[name](**tool_info['params'])
if self.verbose:
print(f'\naction_res: {res}')
return res
def _gen_output(self, message: str, action_res: Dict[str, str]) -> str:
"""根据用户输入和工具调用结果生成回答"""
content = SOLVER_TEMPLATE.substitute(question=message, reference=json.dumps(action_res, ensure_ascii=False))
if self.verbose:
print(f'\ncontent: {content}')
output = self.llm.chat([{'role': 'user', 'content': content}])
return output
if __name__ == '__main__':
message="现在是几点,你知道今天的湖南长沙天气如何"
llm = My_qwen2_5_response("/home/un/桌面/QC/2024_全国大数据智能大赛/342000_点头教育科技有限公司/data/user_data/Qwen2.5-7B-Instruct")
agent = Agent(llm, tools=[GoogleSearch(),CurrentTime()], verbose=True)
print(f'agent output: {agent.chat(message)}')
\ No newline at end of file
# 机器人模型调参以及优化2 ++ /dev/null
# 机器人模型调参以及优化2
链接: https://pan.baidu.com/s/1ZSp6SPooK0IU8Kg8UCwAhw?pwd=gx8i
提取码: gx8i
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment