allinaigc's picture
Update app.py
765383e verified
'''
重要说明:
1. 需要确认import的包是否是requirements.txt中的版本,否则会出现不兼容的情况。
2. 在LAN中如何访问Gradio app:
1. 在Gradio中制定demo.launch(height='1500px', server_name="0.0.0.0", server_port=7860, auth=auth_list, auth_message="欢迎使用中交建财务共享中心企业大语言模型平台", share=False).queue()
2. 在另外一台电脑上,通过http://http://192.168.1.104:7860/ (其中http://192.168.1.104是Gradio的IP地址+端口来访问。
产品说明:
1. 采用大模型的核心功能 + 专属定制化功能的方式,来实现一个专属的大语言模型解决方案。
2. 在专属定制化功能中包含了报告模块、商业分析模块、培训资料模块。配置了专属的prompt,以及对应的模型参数。【话术:定制化的大模型接口 + 结构化的提示词工程 + 业务流】
3. 此版本可以支持多轮对话【注:目前强行限制在3轮以内】,但是会收到大模型基座的影响,目前是ChatGLM3-6B中的4096个token的限制。
Theme默认设置为Dark:
1. css = """
#mybutton {background-color: #CEFAFE; color: #06B6D4;}
#textarea {-webkit-text-fill-color:black; -webkit-opacity: 1;}
.message {font: 16px Arial, sans-serif, 'ui-sans-serif', Montserrat, 'system-ui';}
"""
2. with gr.Blocks(theme=gr.themes.Base(primary_hue='sky', text_size='md'), css=css, title="大语言模型专项模块", js=js_func) as demo:
'''
##TODO 1. 将LLM改成公网Qwen API版本。
import gradio as gr
import requests
import os
from rich import print
import os
import sys
import time
import pandas as pd
import numpy as np
import sys
import time
import PyPDF2
from PyPDF2 import PdfReader
import docx ## 需要安装python-docx,否则会报错。
from typing import Any
import requests
import csv
import os
from rich import print
import pandas
import io
from io import StringIO
from transformers import AutoModel, AutoTokenizer
import mdtex2html
import dashscope
from dotenv import load_dotenv
from http import HTTPStatus
from dashscope import Generation
load_dotenv()
### 设置openai的API key
dashscope.api_key = os.environ['dashscope_api_key']
### Gradio设置为默认Dark
js_func = """
function refresh() {
const url = new URL(window.location);
if (url.searchParams.get('__theme') !== 'dark') {
url.searchParams.set('__theme', 'dark');
window.location.href = url.href;
}
}
"""
# ''' Start: Environment settings. '''
# os.environ['SENTENCE_TRANSFORMERS_HOME'] = '/Users/yunshi/Downloads/chatGLM/My_LocalKB_Project/'
# os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
# # import PyPDF4
# # from PyPDF4 import PdfFileReader
# import torch
# mps_device = torch.device("mps") ## 在mac机器上需要加上这句。
### 在langchain中定义chatGLM作为LLM。
from typing import Any, List, Mapping, Optional
from langchain.callbacks.manager import CallbackManagerForLLMRun
from langchain.llms.base import LLM
from transformers import AutoTokenizer, AutoModel
# llm_filepath = str("/Users/yunshi/Downloads/chatGLM/ChatGLM3-6B/6B") ## 第三代chatGLM 6B W/ code-interpreter
## 在ChatGLM3-6B中成功部署。
# class chatGLM():
# def __init__(self, model_name) -> None:
# self.tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
# # self.model = AutoModel.from_pretrained(model_name, trust_remote_code=True).half().cuda().eval() ##PC CUDA机器上用。
# self.model = AutoModel.from_pretrained(model_name, trust_remote_code=True).half().to('mps') ##Mac机器上用。
# def __call__(self, prompt) -> Any:
# # response, _ = self.model.chat(self.tokenizer , prompt) # 这里演示未使用流式接口. stream_chat()
# response, _ = self.model.stream_chat(self.tokenizer, prompt) # 尝试用stream_chat()
# return response
# chatglm = chatGLM(model_name=llm_filepath)
''' End: Environment settings. '''
# ''' Start: 以下加载本地知识的核心内容。'''
# from langchain.document_loaders import UnstructuredFileLoader
# from langchain.text_splitter import CharacterTextSplitter
# # from langchain.embeddings.openai import OpenAIEmbeddings
# from langchain.embeddings.huggingface import HuggingFaceEmbeddings
# from langchain.vectorstores import FAISS
# ## 加载文件
# filepath = "/Users/yunshi/Downloads/txt_dir/Sparks_of_AGI.pdf"
# # filepath = "/Users/yunshi/Downloads/txt_dir/浙江省院前急救质控统计指标.pdf"
# loader = UnstructuredFileLoader(filepath)
# docs = loader.load()
# ## 文本分割
# # text_splitter = CharacterTextSplitter(chunk_size=5000, chunk_overlap=200)
# docs = CharacterTextSplitter(chunk_size=5000, chunk_overlap=200).split_documents(docs)
# ## 创建向量数据库
# # embeddings = OpenAIEmbeddings(disallowed_special=())
# embedding_model_name = 'GanymedeNil/text2vec-large-chinese'
# # embeddings = HuggingFaceEmbeddings(model_name=embedding_model_name) ## 这里是联网情况下连接huggingface后使用。
# embeddings = HuggingFaceEmbeddings(model_name='/Users/yunshi/Downloads/chatGLM/My_LocalKB_Project/GanymedeNil_text2vec-large-chinese/') ## 这里会有个“No sentence-transformers model found with name“的warning,但不是error,不影响使用。
# ### 比较的中文embeddding之一。
# # from text2vec import SentenceModel
# # embeddings = SentenceModel('shibing624/text2vec-base-chinese-sentence', device=mps_device)
# # embeddings = HuggingFaceEmbeddings()
# vector_store = FAISS.from_documents(docs, embeddings)
# '''End: 至此本地加载知识库过程完成。'''
# ### 读取教材资料,docx文档
# doc = docx.Document("./sample.docx")
# mytext = ""
# for paragraph in doc.paragraphs:
# mytext += paragraph.text
# ### 在工作台展示一部分内容
# showtext = ""
# for paragraph in doc.paragraphs[:12]:
# showtext += paragraph.text
# print(showtext)
## 一键生成培训资料的环境设定
# training_content = mytext.replace("['", "").replace("']", "")
# generate_message = gr.Textbox(f"""你是一个专业的培训材料制作者。我需要你根据提供的内容生成培训材料,内容如下:{training_content}""", visible=False) #! 注意这里的type,不能是简单的str。
# system_prompt_message = """你是一个专业的培训材料制作者。我需要你根据提供的内容生成培训材料,内容如下:"""
# system_prompt = [{"role": "system", "content": f"""{system_prompt_message} {training_content}"""}]
# print('system_prompt:', system_prompt)
# prompt_templates = {"Default ChatGPT": ""}
### set an empty state in Gradio.
def get_empty_state():
return {"total_tokens": 0, "messages": []}
## 重新生成对话,regenerate功能的核心,主要是将最后一次chatbot的回答清空。
# def reload(chatbot):
def regenerate(chatbot):
chatbot[-1][1] = "" #! 清空最后一次的回答。
return chatbot
## system prompt for LLM
system_prompt = [{"role": "system", "content": '你是一个专业和友好的AI助手。除非被要求,否则你默认的回答语言是中文。'}]
### 手动添加prompt templates。
# prompt_templates = {
# '默认角色': "你是一个专业的人工智能助手。",
# '周报写作': "使用下面提供的文本作为中文周报的基础,生成一个简洁的摘要,突出最重要的内容。该报告应以 markdown 格式编写,并应易于阅读和理解,以满足一般受众的需要。特别是要注重提供对利益相关者和决策者有用的见解和分析。你也可以根据需要使用任何额外的信息或来源。",
# '写作建议': "我希望你能充当一名人工智能写作导师。我将为你提供一个需要帮助提高写作水平的学生,你的任务是使用人工智能工具,如自然语言处理,给学生反馈如何提高他们的写作水平。你还应该利用你的修辞学知识和关于有效写作技巧的经验,以建议该学生如何以书面形式更好地表达他们的思想和观点。我的第一个要求是 [修改文本]",
# }
### 导入收集到的有用prompts。
raw_prompts = pd.read_excel("./raw_prompts.xlsx", usecols=['category','prompt'], index_col='category')
prompt_templates = raw_prompts.to_dict()['prompt']
def on_prompt_template_change(prompt_template):
if not isinstance(prompt_template, str): return
# print(prompt_template)
return prompt_templates[prompt_template]
chat_hist = []
def submit_message(radio, chatbot_history, temperature, max_tokens,top_p,presence_penalty): ## working.
# input_prompt = chatbot_history ## 单轮对话 working。
input_prompt = chatbot_history ## working。支持多轮对话。
print("input_prompt", input_prompt)
###NOTE: 保留3次历史记录,原生ChatGPT的上下文也只能到这里了。
### 只把三次历史记录放入prompt中,这样可以保留三轮对话的历史。
prompt = []
if len(input_prompt) > 3:
for x in input_prompt[-3:]:
prompt.append(x)
else:
prompt = input_prompt
prompt = [item for sublist in prompt for item in sublist if item is not None]
prompt = '。'.join(prompt)
print('prompt now is:', prompt)
print('start the default version of Qwen')
## Role的范式。
# prompt_msg = {"role": "user", "content": prompt}
# system_prompt = [{"role": "system", "content": '你是一个专业和友好的AI助手。'}]
try:
## no stream version.
# completion_1 = openai.ChatCompletion.create(model="gpt-3.5-turbo",messages=system_prompt + [prompt_msg], temperature=0.7, max_tokens=1024)
# history.append(prompt_msg)
# history.append(completion_1.choices[0].message.to_dict())
# print('completion_1:',completion_1.choices[0].message.content)
# # state['total_tokens'] += completion_1['usage']['total_tokens']
# messages = system_prompt + [prompt_msg]
# input_prompt[-1][1] = ""
# openai_client = OpenAI()
# for resp in openai_client.chat.completions.create(model=model_choice, messages=messages, stream=True, temperature=temperature, max_tokens=max_tokens,top_p=top_p,presence_penalty=presence_penalty):
# answer = str(resp.choices[0].delta.content)
# if answer != "None":
# ##NOTE: 这里是单论聊天的版本。
# # resp_history.append(answer) #* working!
# # result = "".join(resp_history).strip() #* working!
# # yield [[prompt, result]] #* 记得这个格式。这只能单论聊天。
# ##* 多轮聊天的版本。
# input_prompt[-1][1] += answer
# yield input_prompt
##* 多轮会话,带有历史记忆。因为history参数的原因?
# for response, history in chatglm.model.stream_chat(chatglm.tokenizer, query=input_prompt[-1][0], history=history): ## 一轮对话。working.
# for response, history in chatglm.model.stream_chat(chatglm.tokenizer, query=str(input_prompt)): ## 这里保留了所有的chat history在input_prompt中。
# for response, history in chatglm.model.stream_chat(chatglm.tokenizer, query=str(input_prompt[-1][0])): ## 从用langchain的自定义方式来做。
# for response, history in chatglm.model.stream_chat(chatglm.tokenizer, query=prompt): ## 这里保留了所有的chat history在input_prompt中。
# for response, history in chatglm.model.stream_chat(chatglm.tokenizer, query=prompt): ### Working. original code here. 这里保留了所有的chat history在input_prompt中。
input_prompt[-1][1] = ""
messages = [
{'role': 'user', 'content': prompt}]
responses = Generation.call(model="qwen-turbo",
messages=messages,
result_format='message', # 设置输出为'message'格式
stream=True, # 设置输出方式为流式输出
incremental_output=True # 增量式流式输出
)
for response in responses:
if response.status_code == HTTPStatus.OK and len(response.output.choices[0]['message']['content']) > 0:
# if response != "<br>":
# print('response of model:', response)
# input_prompt[-1][1] = response ## working. ChatGLM的输出。
# response.output.choices[0]['message']['content'] ### 标准的Qwen输出格式。
# input_prompt[-1][1] = response.output.choices[0]['message']['content'] ## working.
input_prompt[-1][1] += response.output.choices[0]['message']['content'] ## working.
yield input_prompt
except Exception as e:
print(e)
error = str(e)
# messages = [{"role": "system", "content": "你是一个专业和友好的AI助手。"},]
# messages.append({"role": "user", "content": ""})
# input_prompt[-1][1] += error
input_prompt[-1][1] = error
yield input_prompt ## 将错误打印到output的textbox里面。
# print(input_prompt)
return input_prompt
## 插入chatbot的user问题。 原始代码参考: https://www.gradio.app/guides/creating-a-custom-chatbot-with-blocks
def user(user_message, chat_history):
# print('chat_history:', chat_history)
# return "", chat_history + [[user_message, None]] ## possiblly orginal code?
return "", chat_history + [[user_message, None]]
## 报告模块的内容合并。Gradio不接受直接的str相加,所以要通过函数来实现,并且在button click中实现。
def report_prompt(system_prompt, report_method, user_prompt, report_requirement):
total_prompt = system_prompt + "\n\n" + "你撰写报告时采用的分析方法是:" + report_method + "\n\n 以下是报告的基础信息:\n" + user_prompt + "\n\n 其他报告写作的要求如下:\n\n" + report_requirement
return total_prompt
## 数据分析模块的内容合并。Gradio不接受直接的str相加,所以要通过函数来实现,并且在button click中实现。
def data_prompt(system_prompt, method_prompt, user_prompt, report_requirement):
total_prompt = system_prompt + "\n" + user_prompt.to_markdown() + "\n\n" +"分析方法采用:"+ method_prompt + "\n\n"+ report_requirement
return total_prompt
### 培训模块的内容合并。Gradio不接受直接的str相加,所以要通过函数来实现,并且在button click中实现。
def train_combine_prompt(train_doc, user_prompt, train_requirement):
total_prompt = train_doc + "\n\n" + user_prompt + "\n\n" + train_requirement
return total_prompt
def clear_conversation():
return gr.update(value=None, visible=True), None, "", get_empty_state()
# return "", "", []
css = """
#mybutton {background-color: #CEFAFE; color: #06B6D4;}
#textarea {-webkit-text-fill-color:black; -webkit-opacity: 1;}
.message {font: 16px Arial, sans-serif, 'ui-sans-serif', Montserrat, 'system-ui';}
"""
# css = None
with gr.Blocks(theme=gr.themes.Base(primary_hue='sky', text_size='md'), css=css, title="大语言模型专项模块", js=js_func) as demo:
# with gr.Blocks(theme=gr.themes.Monochrome(text_size='md'), css=css, title="培训资料专项大语言模型") as demo:
state = gr.State(get_empty_state())
with gr.Row():
# with gr.Column(elem_id="col-container",scale=1):
# # with gr.Tab('参考提示词'):
# prompt_template = gr.Dropdown(label="选择提示词类型:", value="教案策划",choices=list(prompt_templates.keys()))
# default_prompt_value = "我希望您充当教育内容创建者。您需要为教科书、在线课程和讲义等学习材料创建引人入胜且信息丰富的内容。我的第一个建议请求是“我需要帮助制定针对高中生的可再生能源课程计划。”"
# prompt_template_preview = gr.Textbox(label="提示词预设内容:", value=default_prompt_value, show_label=True, lines=5, show_copy_button=True)
with gr.Column(elem_id="col-container",scale=4):
gr.Markdown("""# **大语言模型企业智能化管理中心** """, elem_id="header")
gr.Markdown(""" 说明: 本大模型为企业专项定制。提供高度可控、可调节、可迭代的大语言模型工具箱。用户可以根据自己的需求,灵活配置工具箱的功能和参数。可以满足不同用户的个性化需求,让用户能够充分发挥大语言模型的潜力。例如,对于常规业务人员,可以选择使用功能简单、参数较少的工具箱,以便快速上手。对于经验丰富的用户来说,可以选择使用功能复杂、参数较多的工具箱,以便进行更深入的研究。适用于各种业务场景的开发和使用。""")
with gr.Row():
with gr.Column():
# gr.Markdown("""### 企业级大语言模型 """)
chatbot = gr.Chatbot(elem_id="message", height=600, label="大模型对话区", show_label=True, show_copy_button=True, layout='panel', likeable=True) ## style来设置对话框高度。
# chatbot = gr.Chatbot(elem_id="message", height=600, label="中交建大模型对话区") ## style来设置对话框高度。
# output_message = gr.Textbox(label='大语言模型的回答',lines=10).style(show_copy_button=True) ## textbox version。style来设置对话框高度。
# radio = gr.Radio(['培训资料生成模式', '资料优化模型','配图生成模式'], value='培训资料生成模式',label="大语言模型运行模式")
## 根据要求选择不同的按键类型,button或者icon。
with gr.Row():
with gr.Column(min_width=837):
# with gr.Column(scale=8):
input_message = gr.Textbox(lines=1, label="输入您的要求", show_label=True, placeholder="在这里输入您的要求按Enter提交", visible=True, show_copy_button=True)
with gr.Row():
# with gr.Column(min_width=15):
with gr.Column(scale=1):
# btn_clear_conversation = gr.Button("\u2716", variant="primary", visible=True).style(full_width=False, size="lg")
btn_clear_conversation = gr.Button("开启新对话", variant="secondary", visible=True, size='lg')
# with gr.Column(scale=1):
# # btn_stop = gr.Button("\u25FD", variant="primary", visible=True).style(full_width=False, size="lg")
# btn_stop = gr.Button("终止当前问题/任务", variant="secondary", visible=True, size='lg')
# with gr.Column(scale=1):
# # btn_stop = gr.Button("\u25FD", variant="primary", visible=True).style(full_width=False, size="lg")
# btn_generate = gr.Button("一键生成分析报告", variant="primary", visible=True, size='lg')
with gr.Column(min_width=100):
# with gr.Column(scale=1):
btn_regenerate = gr.Button("重新生成答案", variant="secondary", visible=True, size='lg')
# with gr.Column(scale=1):
# # btn_stop = gr.Button("\u25FD", variant="primary", visible=True).style(full_width=False, size="lg")
# btn_exam = gr.Button("一键生成培训考题", variant="primary", visible=True, size='lg')
with gr.Column(scale=1):
# btn_submit = gr.Button("\u2714", variant="primary", visible=True).style(full_width=False, size="lg")
btn_submit = gr.Button("提交您的要求", variant="primary", visible=True, size='lg')
with gr.Column(scale=2): ### 原先设置为2.
# gr.Markdown("## 工作区")
# with gr.Tab('专项业务板块'):
'''以下为报告撰写模块'''
with gr.Tab('报告撰写模块'):
# with gr.Accordion('报告撰写模块', open=True):
# report_input = gr.Textbox(lines=5, label="输入报告基础内容", show_label=True, placeholder="报告基础内容", visible=True, show_copy_button=True)
report_input = gr.Textbox(lines=5, label="输入基本信息", show_label=True, placeholder="中小企业加快数字化转型,龙头骨干企业更要发挥引领示范作用。走进位于两江新区的集团自动化的“黑灯工厂”,1000多台机器人高速运转,机械手臂有序协作。在这里,冲压完成一套汽车部件仅需5秒钟,2分钟便可下线一辆新车。", visible=True, show_copy_button=True)
# train_sys_prompt = gr.Textbox("你是一个专业的咨询顾问。你写作的风格专业且详实,使用的语言为中文。我需要你根据如下内容撰写一份报告:", label="报告要求设定",visible=True, interactive=True, show_copy_button=True)
report_sys_prompt = gr.Textbox("你是一个专业的咨询顾问。我需要你撰写报告,你的写作风格专业且尽可能的详细,除非特别说明否则你使用的语言为中文。", label="报告要求设定", visible=True, interactive=True, show_copy_button=True)
report_method = gr.Dropdown(choices=['扩写内容','润色文案','重写材料'], interactive=True, label="报告撰写方法", value="扩写内容", multiselect=False, show_label=True)
report_requirement = gr.Textbox("""标题:简明扼要地概括汇报内容。
正文:分为[基本情况]、[主要做法]、[下一步计划]三个部分。
结尾:总结全文,提出希望。
""", label="报告格式设定",show_label=True, show_copy_button=True,visible=True, interactive=True)
# train_text = gr.Textbox(lines=3, label='输出内容风格', show_label=True, show_copy_button=True, value=report_requirement)
btn_report = gr.Button("一键生成汇报材料", variant="primary", visible=True, size='lg')
'''以下为简易分析模块'''
with gr.Tab('商业分析模块'):
# with gr.Accordion('报告撰写模块', open=True):
biz_analysis_input = gr.Textbox(lines=5, label="输入基本信息", show_label=True, placeholder="9月份我部门共成单19件(注:8月份为21件);收到既有客户投诉246起(注:8月份为199起);潜在客户咨询152起(注:与8月份124起)", visible=True, show_copy_button=True)
# train_sys_prompt = gr.Textbox("你是一个专业的咨询顾问。你写作的风格专业且详实,使用的语言为中文。我需要你根据如下内容撰写一份报告:", label="报告要求设定",visible=True, interactive=True, show_copy_button=True)
biz_analysis_sys_prompt = gr.Textbox(lines=3, value="你是一个专业的商业分析顾问。我需要你撰写商业分析材料,你的写作风格专业且尽可能的详细,除非特别说明否则你使用的语言为中文。", label="报告要求设定", visible=True, interactive=True, show_copy_button=True)
biz_analysis_method = gr.Dropdown(choices=['头脑风暴', '整体分析','趋势判断','SMART分析','SWOT分析','精益分析','5W1H分析','PEST分析','金字塔原理','六顶思考帽'], interactive=True, label="商业分析方法", value="头脑风暴", multiselect=False, show_label=True)
biz_analysis_requirement = gr.Textbox(lines=4, value="""1. 将数据整理成Markdown表格的形式。
2. 必须有标题。
3. 使用一、二、三格式的序号。
4. 最后有总结。
""", label="报告格式设定",show_label=True, show_copy_button=True,visible=True, interactive=True)
# train_text = gr.Textbox(lines=3, label='输出内容风格', show_label=True, show_copy_button=True, value=biz_analysis_requirement)
btn_biz_analysis = gr.Button("一键生成分析报告", variant="primary", visible=True, size='lg')
###NOTE: 以下模块为数据分析模块,国产模型不稳定,暂时不开放!
# with gr.Tab('高级分析模块'):
# ## 上传功能
# with gr.Row():
# # file_output = gr.UploadButton(label='上传数据文件区', file_count="single", file_types=[".csv"])
# file_output = gr.File(label='上传数据文件区', file_count="single", file_types=[".csv"])
# ##NOTE: convert the uploaded file into dataframe, so that the Gradio can process it.
# def csv_file(file_output):
# res = pd.read_csv(file_output)
# return res
# with gr.Row():
# md_table = gr.DataFrame()
# file_output.upload(fn=csv_file, inputs=file_output, outputs=md_table, queue=False) #! Gradio中需要通过函数来获得结果,否则都是Gradio内部定义的数据结构,如File,无法被直接访问或使用。
# # with gr.Row():
# # gr.DataFrame("/Users/yunshi/Downloads/360Data/Data Center/Working-On Task/演讲与培训/2023ChatGPT/Coding/code_interpreter/rawdata/iris.csv")
# data_sys_prompt = gr.Textbox("""你是一个专业的数据科学家。你需要保持专业的风格且分析内容详实,使用的语言为中文,回复时使用markdown格式。我需要你对如下数据中的[X, Y]进行分析并给出计算结果:\n\n""", lines=3, label="分析要求设定",visible=True, interactive=True, show_copy_button=True)
# data_method = gr.Dropdown(choices=['数据整体描述','描述性统计:汇总值、平均值、标准差、分位数', '相关性分析', '分类汇总'], label="数据分析方法", value="描述性统计:平均值、汇总值、标准差、中位数、极数", multiselect=False, interactive=True,show_label=True)
# # data_input = gr.Textbox(lines=5, label="输入数据内容", show_label=True, placeholder="数据基础内容", visible=True, show_copy_button=True, interactive=True)
# data_requirement = gr.Textbox("""目标:发现数据中的问题和关键点。
# 分析方法:解释上述分析方法的基本原理。
# 分析结论:提出结论,揭示潜在可能原因和对应的措施。
# """, lines=5, label="分析输出设定",show_label=True, show_copy_button=True,visible=True, interactive=True)
# # data_analysis_requirement = gr.Textbox(lines=3, label='输出内容风格', show_label=True, show_copy_button=True, value=data_requirement)
# btn_data = gr.Button("一键生成数据分析", variant="primary", visible=True, size='lg')
with gr.Tab('培训资料模块'):
# with gr.Accordion('培训资料模块', open=False):
with gr.Row():
# file_output = gr.UploadButton(label='上传数据文件区', file_count="single", file_types=[".csv"])
uploaded_training_file = gr.File(label='上传培训资料区(注:文档内容限制在3000个汉字以内)', file_count="single", file_types=[".docx"])
##NOTE: convert the uploaded file into dataframe, so that the Gradio can process it.
def convert_file(upload_file):
# res = pd.read_csv(file_output) ## read csv file.
### 读取教材资料,docx文档
doc = docx.Document(upload_file)
my_text = ""
for paragraph in doc.paragraphs:
if not paragraph.text.isspace(): ## 判断是否有空行。
my_text += paragraph.text
### 在工作台展示一部分内容
show_text = ""
for paragraph in doc.paragraphs[:5]:
if not paragraph.text.isspace(): ## 判断是否有空行。
show_text += paragraph.text
# print(show_text)
return my_text, show_text
# my_text, show_text = convert_file(uploaded_training_file) ## 单独运行一次这个函数,为了后面直接拼接字符串用。
with gr.Row():
my_doc = gr.TextArea(visible=False)
show_doc = gr.TextArea(label="培训资料展示与确认",visible=True, lines=5)
uploaded_training_file.upload(fn=convert_file, inputs=uploaded_training_file, outputs=[my_doc, show_doc],queue=False) #! Gradio中需要通过函数来获得结果,否则都是Gradio内部定义的数据结构,如File,无法被直接访问或使用。
## 一键生成培训资料的环境设定
# training_content = show_doc.replace("['", "").replace("']", "")
# system_prompt_message = """你是一个专业的培训材料制作者。我需要你根据提供的内容生成培训材料,内容如下:"""
train_prompt = gr.Textbox(value=("""你是一个专业的培训材料制作者。我需要你根据提供的内容生成培训材料,内容如下:"""), visible=False) #! 注意这里的type,不能是简单的str。
# system_prompt = [{"role": "system", "content": f"""{system_prompt_message} {training_content}"""}] ### userful only in OpenAI API.
# train_requirement_text = """标题:[培训主题]
# 培训目标:[培训目标]
# 模块内容:涵盖目标和关键领域的详细内容
# 培训方式:引人入胜的活动,以强化所讨论的概念
# 评估方法:评估学习者理解和知识保留的方法。
# """
# train_requirement = gr.Textbox(lines=5, label='报告风格', show_label=True, show_copy_button=True, value=train_requirement_text)
train_requirement = gr.Textbox(lines=5, label='培训材料风格', show_label=True, show_copy_button=True, value="""标题:[培训主题]
培训目标:[培训目标]
模块内容:涵盖目标和关键领域的详细内容
培训方式:引人入胜的活动,以强化所讨论的概念
评估方法:评估学习者理解和知识保留的方法。
""")
total_prompt = gr.TextArea(visible=False)
# uploaded_training_file.change(train_combine_prompt, [train_prompt, my_doc, train_requirement], total_prompt)
# total_prompt = (f"""你是一个专业的培训材料制作者。我需要你根据提供的内容生成培训材料,内容如下: \n {my_text}""") + "\n 培训内容设计需要参考如下要求:" + train_requirement
btn_training = gr.Button("一键生成培训资料", variant="primary", visible=True, size='lg')
traing_exam_prompt = gr.Textbox(lines=2, value="""你是一个专业的培训材料制作者。我需要你根据上述内容,设计3道单选题和2道问答题。你需要给出题目内容和对应的参考答案。""", label="培训考题要求", show_copy_button=True, visible=True) #! 注意这里的type,不能是简单的str。
btn_training_exam = gr.Button("一键生成培训考试题目", variant="primary", visible=True, size='lg')
with gr.Tab(label='高级设置', elem_id='tab'):
with gr.Accordion('模型设置', open=True):
radio = gr.Radio(['核心模式', '优化模式','其他模式'], value='核心模式', label="大语言模型运行模式")
claim_value = str("大语言具有多种高级设置选项来调整其模型。1. Temperature:温度调整文本的多样性。温度值越高,生成的文本越随机。2. Token:控制生成文本的长度。3. 'top_p':0.0到1.0 (默认 1.0) ,类似Temperature,也叫核采样。4.presence_penalty:惩罚原始文本中已经出现过的单词/短语,从而鼓励生成无重复的输出。"
)
claim = gr.Textbox(value=claim_value, label="大模型参数简介",type="text", show_label=True, lines=5)
temperature = gr.Slider(minimum=0, maximum=2.0, value=0.7, step=0.1, label="Temperature参数",info="数值越高语句越灵活")
max_tokens = gr.Slider(minimum=100, maximum=14096, value=3000, step=100,
label="单次聊天最多Token数", info="平均1.12个token约等于1个汉字")
top_p = gr.Slider(minimum=0, maximum=1, value=1, step=0.1, label="top_p参数",info="数值越低语句越固定")
presence_penalty = gr.Slider(minimum=0, maximum=1, value=0.5, step=0.1, label="penalty参数",info="0没有惩罚,1完全禁止输出复制的单词")
# with gr.Tab('参考提示词'):
with gr.Accordion('参考提示词', open=True):
prompt_template = gr.Dropdown(label="选择提示词类型:", value="教案策划",choices=list(prompt_templates.keys()))
default_prompt_value = "我希望您充当教育内容创建者。您需要为教科书、在线课程和讲义等学习材料创建引人入胜且信息丰富的内容。我的第一个建议请求是“我需要帮助制定针对高中生的可再生能源课程计划。”"
prompt_template_preview = gr.Textbox(label="提示词预设内容:", value=default_prompt_value, show_label=True, lines=5, show_copy_button=True)
### 上传功能模块
# with gr.Tab('上传文件'):
# with gr.Row():
# file_output = gr.File(label='上传文件区', file_count="single", file_types=[".pdf", ".docx",".csv"])
# with gr.Column(scale=1):
# btn_process = gr.Button('解析文件', variant="primary", visible=True, size='lg')
## click + submit. 注意,这里的input_message必须是类似gr.Textbox这样的模块type。普通的str不行。
btn_submit_event = btn_submit.click(user, [input_message, chatbot], [input_message, chatbot], queue=False).then(submit_message, [radio, chatbot,temperature,max_tokens,top_p,presence_penalty], chatbot)
input_message.submit(user, [input_message, chatbot], [input_message, chatbot], queue=False).then(submit_message, [radio, chatbot,temperature,max_tokens,top_p,presence_penalty], chatbot)
btn_clear_conversation.click(clear_conversation, [], [input_message, chatbot])
### 报告撰写专项模块按键
total_prompt = gr.Textbox(visible=False) ## 用于汇总所有的prompt,然后输入chatbot。
btn_report.click(report_prompt, [report_sys_prompt, report_method, report_input, report_requirement], [total_prompt], queue=True).then(user, [total_prompt, chatbot], [total_prompt, chatbot], queue=True).then(submit_message, [radio, chatbot,temperature,max_tokens,top_p,presence_penalty], chatbot)
### 商业分析撰写专项模块按键
total_prompt = gr.Textbox(visible=False) ## 用于汇总所有的prompt,然后输入chatbot。
btn_biz_analysis.click(report_prompt, [biz_analysis_sys_prompt, biz_analysis_method, biz_analysis_input, biz_analysis_requirement], [total_prompt], queue=False).then(user, [total_prompt, chatbot], [total_prompt, chatbot], queue=False).then(submit_message, [radio, chatbot,temperature,max_tokens,top_p,presence_penalty], chatbot)
# ### 数据分析专项模块按键
##TODO 尝试用ChatGLM3中的code-interpreter来完成。
# # report_prompt = gr.Textbox(value=f"你是一个专业的咨询顾问。你写作的风格专业且详实,使用的语言为中文。我需要你根据如下内容撰写一份报告:", visible=False)
# # train_sys_prompt = gr.Textbox("你是一个专业的咨询顾问。你写作的风格专业且详实,使用的语言为中文。我需要你根据如下内容撰写一份报告:")
# total_prompt = gr.Textbox(visible=False) ## 用于汇总所有的prompt,然后输入chatbot。
# # btn_report.click(user, [report_prompt, chatbot], [report_prompt, chatbot], queue=False).then(submit_message, [radio, chatbot,temperature,max_tokens,top_p,presence_penalty], chatbot)
# # btn_data.click(data_prompt, [data_sys_prompt, data_method, file_output, data_requirement], [total_prompt], queue=False).then(user, [total_prompt, chatbot], [total_prompt, chatbot], queue=False).then(submit_message, [radio, chatbot,temperature,max_tokens,top_p,presence_penalty], chatbot) ## 可以看见这个file_output的完整链接。
# btn_data.click(data_prompt, [data_sys_prompt, data_method, md_table, data_requirement], [total_prompt], queue=False).then(user, [total_prompt, chatbot], [total_prompt, chatbot], queue=False).then(submit_message, [radio, chatbot,temperature,max_tokens,top_p,presence_penalty], chatbot) ##TODO:尝试把数据导入。
### 培训资料专项模块按键
btn_training.click(train_combine_prompt, [train_prompt, my_doc, train_requirement], [total_prompt], queue=False).then(user, [total_prompt, chatbot], [total_prompt, chatbot], queue=False).then(submit_message, [radio, chatbot,temperature,max_tokens,top_p,presence_penalty], chatbot)
## 把total_prompt作为中间变量。否则,textbox中的内容用user()函数提交后会被清空。
def exam_prompt(traing_exam_prompt):
total_prompt = traing_exam_prompt
return total_prompt
btn_training_exam.click(exam_prompt, traing_exam_prompt, total_prompt).then(user, [total_prompt, chatbot], [total_prompt, chatbot], queue=False).then(submit_message, [radio, chatbot,temperature,max_tokens,top_p,presence_penalty], chatbot)
# null_message = gr.Textbox(value=None, visible=False)
# btn_regenerate.click(user, [null_message, chatbot], [null_message, chatbot], queue=False).then(submit_message, [radio, chatbot,temperature,max_tokens,top_p,presence_penalty], chatbot) ## working.
# exam_prompt = gr.Textbox("你根据上述的内容,生成3道单选题和2道简答题。风格专业且简洁。", visible=False)
# btn_exam.click(user, [exam_prompt, chatbot], [exam_prompt, chatbot], queue=False).then(submit_message, [radio, chatbot,temperature,max_tokens,top_p,presence_penalty], chatbot) ## working.
## regenerate button。重新提交对话。
btn_regenerate.click(regenerate, chatbot, chatbot).then(submit_message, [
radio, chatbot, temperature, max_tokens, top_p, presence_penalty], chatbot)
## stop button中止提交程序运行。
# btn_stop.click(fn=None, inputs=None, outputs=None, cancels=[btn_submit_event])
prompt_template.change(on_prompt_template_change, inputs=[prompt_template], outputs=[prompt_template_preview])
demo.load()
auth_list = (
('1234', '1234'),
('joeshi', 'joeshi'),
('guojing', 'guojing'),
('chengrui', 'chengrui'),
('lbh', 'lbh'),
('zhangqian888', 'zhangqian888'),
('scottl', 'scottl'),
('test001', 'test001'),
('test002', 'test002'),
('test003', 'test003'),
)
### 用户名和密码认证
# user_csv = pd.read_csv('auth_list_enterprise.csv')
# auth_list = [(x, y) for (x, y) in user_csv[['username', 'password']].values]
# demo.launch(height='1200px')
# demo.launch(height='1200px', auth=auth_list, auth_message="欢迎使用企业大语言模型培训专属模块", share=True)
# demo.launch(height='1500px', auth=auth_list, auth_message="欢迎使用中交建财务共享中心企业大语言模型平台", share=False).queue()
# demo.launch(height='1500px', server_name="0.0.0.0", server_port=7860, share=False).queue()
demo.launch(height='1500px', server_name="0.0.0.0", server_port=7860, auth=auth_list, auth_message="欢迎使用企业大语言模型平台", share=False).queue()