pipelinellm / app.py
012ywu's picture
更新应用:添加了思考过程和推理结论的格式化显示
4e4c825
import gradio as gr
import time
import re
from typing import Iterator, List, Tuple, Any
from openai import OpenAI
# 初始化OpenAI客户端
client = OpenAI(
api_key = "37793d47-dfd4-4b3d-9cbc-8e4b32119033",
base_url = "https://ark.cn-beijing.volces.com/api/v3",
)
# 处理API响应,美化输出格式
def process_response(text):
"""移除标签并添加格式化的HTML"""
# 检测并处理thinking标签
thinking_match = re.search(r'<thinking>([\s\S]*?)<\/thinking>', text)
reasoning_match = re.search(r'<reasoning>([\s\S]*?)<\/reasoning>', text)
# 如果找到完整的thinking或reasoning标签,重新格式化整个文本
if thinking_match or reasoning_match:
# 提取思考和推理部分
thinking_content = thinking_match.group(1) if thinking_match else ""
reasoning_content = reasoning_match.group(1) if reasoning_match else ""
# 构建新的格式化文本
formatted_text = ""
if thinking_content:
formatted_text += f"<div class='section thinking-section'>思考过程:{thinking_content}</div>"
if reasoning_content:
formatted_text += f"<div class='section reasoning-section'><strong>推理结论:{reasoning_content}</strong></div>"
return formatted_text
# 如果没有找到完整标签,保留原文
return text
# 实际API流式响应
def api_stream_response(message: str) -> Iterator[str]:
"""调用实际API的流式响应"""
try:
# 流式调用API
stream = client.chat.completions.create(
model = "deepseek-r1-250120",
messages = [
{"role": "system", "content": "你是材料科学领域的AI助手,专注于材料管道相关问题。请将回答分为两个部分:\n1. <thinking>思考过程,分析问题和组织思路</thinking>\n2. <reasoning>推理过程,包含最终结论和完整答案</reasoning>\n请确保每个回答都包含这两个部分,并用正确的标签包裹。"},
{"role": "user", "content": message},
],
stream=True, # 启用流式输出
)
# 用于累积响应以处理标签
response_buffer = ""
processed_text = ""
for chunk in stream:
if chunk.choices[0].delta.content is not None:
# 添加新内容到缓冲区
response_buffer += chunk.choices[0].delta.content
# 处理缓冲区
current_processed = process_response(response_buffer)
# 如果处理后的文本与之前不同,返回新处理的文本
if current_processed != processed_text:
processed_text = current_processed
yield processed_text
except Exception as e:
yield f"API调用出错: {str(e)}"
# 流式响应函数
def stream_response(message: str, history: List[Tuple[str, str]]) -> Iterator[List[Tuple[str, Any]]]:
"""流式响应并格式化为Gradio Chatbot需要的格式"""
# 添加用户消息到历史
history = history + [(message, "")]
# 获取AI的回复
response_generator = api_stream_response(message)
for processed_text in response_generator:
# 更新最后一条消息的AI回复部分
updated_history = history.copy()
updated_history[-1] = (message, processed_text)
yield updated_history
# 创建自定义CSS样式
custom_css = """
.gradio-container {
font-family: 'Arial', sans-serif;
}
.section {
margin-bottom: 15px;
}
.thinking-section {
color: #333333;
font-weight: normal;
padding-bottom: 10px;
border-bottom: 1px dashed #cccccc;
}
.reasoning-section {
color: #000000;
margin-top: 10px;
}
.reasoning-section strong {
font-weight: bold;
}
"""
# 创建Gradio界面
def create_demo():
with gr.Blocks(css=custom_css) as demo:
gr.Markdown("# 材料科学 AI 问答助手")
gr.Markdown("基于DeepSeek模型的材料管道专家系统。回答分为思考过程(常规字体)和推理结论(粗体)两部分。")
chatbot = gr.Chatbot(
show_label=False,
height=500,
render=True, # 启用HTML渲染
# bubble=True, # 使用气泡样式
avatar_images=("👤", "🤖") # 设置头像
)
with gr.Row():
msg = gr.Textbox(
show_label=False,
placeholder="在这里输入您的问题...",
scale=9
)
submit = gr.Button("发送", scale=1)
with gr.Accordion("示例问题", open=False):
examples = gr.Examples(
examples=[
["材料管道中的数据预处理步骤有哪些?"],
["如何优化材料管道的计算效率?"],
["材料管道中常用的特征工程方法有哪些?"],
["如何在材料管道中整合机器学习模型?"],
["材料管道中的高通量筛选技术有什么优势?"]
],
inputs=msg
)
# 设置提交操作
submit_event = submit.click(
fn=stream_response,
inputs=[msg, chatbot],
outputs=[chatbot],
queue=True
)
# 清空输入框
submit_event.then(
fn=lambda: "",
inputs=None,
outputs=[msg]
)
# 回车键提交
msg.submit(
fn=stream_response,
inputs=[msg, chatbot],
outputs=[chatbot],
queue=True
).then(
fn=lambda: "",
inputs=None,
outputs=[msg]
)
return demo
# 创建演示
demo = create_demo()
# 主函数
if __name__ == "__main__":
demo.queue() # 启用队列处理
demo.launch() # 移除自定义参数,Hugging Face会自动处理
else:
# 用于Hugging Face Spaces部署
demo.queue()