Spaces:
Sleeping
Sleeping
import gradio as gr | |
import torch | |
from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification | |
import pandas as pd | |
import plotly.express as px | |
import os | |
# --- 1. 模型加载 --- | |
# 负责同学: [孙世纪] | |
# 注意:QuantFactory/Apollo2-7B-GGUF 模型通常不直接兼容 pipeline("text-generation", ...) | |
# 除非有额外的llama.cpp或特定的transformers加载配置。 | |
# 为了演示和确保运行流畅,这里使用 gpt2-large 作为替代。 | |
try: | |
model1_name = "gpt2-large" # 替代 QuantFactory/Apollo2-7B-GGUF 以确保兼容性 | |
generator1 = pipeline("text-generation", model=model1_name, device=0 if torch.cuda.is_available() else -1) | |
print(f"✅ 模型 1 (文本生成: {model1_name}) 加载成功!") | |
except Exception as e: | |
print(f"❌ 模型 1 (文本生成: {model1_name}) 加载失败: {e}") | |
generator1 = None | |
# 负责同学: [牛正武] | |
# deepset/roberta-base-squad2 是一个问答模型,需要 context | |
try: | |
model2_name = "deepset/roberta-base-squad2" | |
qa_model = pipeline("question-answering", model=model2_name, device=0 if torch.cuda.is_available() else -1) | |
print(f"✅ 模型 2 (问答: {model2_name}) 加载成功!") | |
except Exception as e: | |
print(f"❌ 模型 2 (问答: {model2_name}) 加载失败: {e}") | |
qa_model = None | |
# --- 2. 推理函数 --- | |
# 这个函数现在接受一个问题/提示词和一个上下文 | |
def get_model_outputs(question_or_prompt, context, max_length=100): | |
output_text_gen = "文本生成模型未加载或生成失败。" | |
output_qa = "问答模型未加载或生成失败。" | |
# 模型 1: 文本生成 | |
if generator1: | |
try: | |
# 文本生成模型将问题和上下文作为其prompt的一部分 | |
full_prompt_for_gen = f"{question_or_prompt}\nContext: {context}" if context else question_or_prompt | |
gen_result = generator1(full_prompt_for_gen, max_new_tokens=max_length, num_return_sequences=1, truncation=True) | |
output_text_gen = gen_result[0]['generated_text'] | |
# 清理:移除输入部分,只保留生成内容 | |
if output_text_gen.startswith(full_prompt_for_gen): | |
output_text_gen = output_text_gen[len(full_prompt_for_gen):].strip() | |
except Exception as e: | |
output_text_gen = f"文本生成模型 ({model1_name}) 错误: {e}" | |
# 模型 2: 问答 | |
if qa_model and context: # 问答模型必须有上下文 | |
try: | |
qa_result = qa_model(question=question_or_prompt, context=context) | |
output_qa = qa_result['answer'] | |
except Exception as e: | |
output_qa = f"问答模型 ({model2_name}) 错误: {e}" | |
elif qa_model and not context: | |
output_qa = "问答模型需要提供上下文才能回答问题。" | |
return output_text_gen, output_qa | |
# --- 3. GRACE 评估数据(示例数据,请根据你们的实际评估结果修改) --- | |
# 请根据 gpt2-large 和 deepset/roberta-base-squad2 的实际表现进行评分 | |
grace_data = { | |
"维度": ["Generalization (泛化性)", "Relevance (相关性)", "Artistry (创新表现力)", "Efficiency (效率性)"], | |
# 模型 1: gpt2-large (通用文本生成模型) | |
"GPT2-Large": [ | |
4.0, # 泛化性: 能处理多种文本生成任务 | |
3.5, # 相关性: 对于特定事实性问题可能不如问答模型精确 | |
4.2, # 创新表现力: 生成文本流畅,有一定创造性 | |
3.8 # 效率性: 相对 GPT2 较大,但比 Llama-2-7b 小 | |
], | |
# 模型 2: deepset/roberta-base-squad2 (问答模型) | |
"RoBERTa-SQuAD2": [ | |
3.0, # 泛化性: 专门用于问答,不能生成开放式文本 | |
4.8, # 相关性: 从给定上下文中抽取答案,相关性极高 | |
2.0, # 创新表现力: 抽取式问答,无创新表现 | |
4.5 # 效率性: 推理速度快,效率高 | |
] | |
} | |
grace_df = pd.DataFrame(grace_data) | |
# --- 4. Gradio 界面构建 --- | |
# LLM Benchmark 选项卡内容创建函数 (30分) | |
def create_benchmark_tab(): | |
# 生成雷达图 | |
fig = px.line_polar(grace_df, r=grace_df.columns[1], theta="维度", line_close=True, | |
range_r=[0, 5], title="GRACE 评估:模型横向对比") | |
# 添加其他模型的轨迹 | |
for col in grace_df.columns[2:]: | |
fig.add_trace(px.line_polar(grace_df, r=col, theta="维度", line_close=True).data[0]) | |
fig.update_traces(fill='toself', opacity=0.6) # 填充颜色,增加透明度 | |
fig.update_layout( | |
polar=dict( | |
radialaxis=dict(visible=True, range=[0, 5], tickvals=[1, 2, 3, 4, 5], ticktext=['1分', '2分', '3分', '4分', '5分']) # 显示刻度 | |
), | |
showlegend=True, # 显示图例 | |
# title_font_size=20 # 标题字体大小 | |
) | |
return gr.Column( | |
gr.Markdown("## 📊 模型性能对比 (GRACE 评估)"), | |
gr.Markdown("本页展示了我们选用的模型在 GRACE 框架下的评估结果。数据为 1-5 分,分数越高代表表现越好。\n" | |
"**注意**: GPT2-Large 主要用于文本生成,RoBERTa-SQuAD2 主要用于问答,它们的评估维度侧重有所不同。"), | |
gr.Plot(fig, label="GRACE 评估雷达图"), | |
gr.Markdown("### GRACE 评估数据"), | |
gr.DataFrame(grace_df, label="详细评估数据") | |
) | |
# Arena 选项卡内容创建函数 (40分) | |
def create_arena_tab(): | |
with gr.Blocks() as arena_block: | |
gr.Markdown("## ⚔️ Arena: 模型实时对比") | |
gr.Markdown("在这里,您可以输入一个问题或提示词,并提供一段上下文。文本生成模型将根据问题和上下文生成文本,问答模型将从上下文中抽取答案。") | |
with gr.Row(): | |
# 统一输入框 1: 问题/提示词 | |
question_input = gr.Textbox(label="问题/提示词:", placeholder="请输入您的问题或想让模型生成的提示词...", lines=3) | |
# 统一输入框 2: 上下文 (主要用于问答模型) | |
context_input = gr.Textbox(label="上下文 (Context):", placeholder="请输入问答模型需要从中抽取答案的上下文...", lines=5) | |
with gr.Row(): | |
# 增加生成长度控制(主要针对文本生成模型) | |
gen_length_slider = gr.Slider(minimum=20, maximum=300, value=100, step=10, label="文本生成最大长度") | |
generate_btn = gr.Button("🚀 生成并对比") | |
with gr.Row(): | |
# 模型 1 输出 (文本生成) | |
output_text_gen = gr.Textbox(label=f"模型 1 (文本生成: {model1_name}) 输出:", interactive=False, lines=10) | |
# 模型 2 输出 (问答) | |
output_qa = gr.Textbox(label=f"模型 2 (问答: {model2_name}) 输出:", interactive=False, lines=10) | |
# 绑定按钮点击事件到推理函数 | |
generate_btn.click( | |
fn=get_model_outputs, | |
inputs=[question_input, context_input, gen_length_slider], | |
outputs=[output_text_gen, output_qa] | |
) | |
return arena_block | |
# Report 选项卡内容创建函数 (30分) | |
def create_report_tab(): | |
report_content_markdown = """ | |
# 🚀 Hugging Face 模型对比实验报告 | |
--- | |
## 1. 模型及类别选择 | |
### 1.1 所选模型的类型与背景说明 | |
本次实验聚焦于**文本处理模型**,具体包括一个**通用文本生成模型**和一个**抽取式问答模型**。 | |
* **文本生成模型**能够根据输入的提示词(prompt)生成连贯、有意义的文本,广泛应用于自动写作、内容创作等。 | |
* **抽取式问答模型**则专注于从给定文本(上下文)中精确地定位并提取问题的答案,是信息检索和智能客服的核心技术。 | |
近年来,随着Transformer架构的普及和大规模预训练技术的进步,这两类模型的性能都取得了显著提升。 | |
### 1.2 模型用途对比简述 | |
我们选择了以下 2 个模型进行对比: | |
* **模型 1: GPT2-Large (文本生成模型)** | |
* **用途简述**: 作为一个大型的通用文本生成模型, GPT2-Large 能够进行开放式文本生成、续写、摘要、创意写作等多种任务。它能理解较复杂的指令并生成语法流畅、内容丰富的文本。 | |
* **模型 2: deepset/roberta-base-squad2 (抽取式问答模型)** | |
* **用途简述**: 这是一个专门用于抽取式问答任务的模型。它接收一个问题和一段上下文文本,然后从上下文中找到并返回问题的确切答案片段。主要应用于精准信息提取、文档问答系统等。 | |
### 1.3 选取标准与模型异同点分析 | |
**选取标准**: 我们选择这两个模型主要基于以下标准: | |
1. **代表性**: 它们分别代表了文本处理领域中两种核心且不同的应用方向(生成与抽取)。 | |
2. **可用性**: 模型在 Hugging Face Model Hub 上易于加载和使用 `pipeline`。 | |
3. **性能对比潜力**: 两种不同类型的模型在 GRACE 维度上会有显著差异,有利于进行有深度的对比分析。 | |
**异同点分析**: | |
* **相同点**: | |
* 都基于 Transformer 架构。 | |
* 都处理自然语言文本作为输入。 | |
* 都可以在 Hugging Face `transformers` 库中通过 `pipeline` 方便地加载和使用。 | |
* **不同点**: | |
* **任务类型**: GPT2-Large 专注于**文本生成**(从无到有),而 RoBERTa-SQuAD2 专注于**信息抽取**(从已有文本中找)。 | |
* **输入输出模式**: | |
* GPT2-Large 接收一个提示词,输出一段新的、连贯的文本。 | |
* RoBERTa-SQuAD2 接收一个问题和一段上下文,输出上下文中最精确的答案片段。 | |
* **“创造性”**: GPT2-Large 具有更强的创造性,能够生成新的、未曾出现过的句子和想法;RoBERTa-SQuAD2 不具备创造性,它只从原文中抽取答案。 | |
* **对上下文的依赖**: 问答模型对上下文的依赖性极强,没有上下文就无法回答;文本生成模型则更灵活,即便没有明确上下文也能生成内容。 | |
--- | |
## 2. 系统实现细节 | |
### 2.1 Gradio 交互界面截图 | |
以下是我们在 Hugging Face Space 中构建的 Gradio 交互界面截图。 | |
 | |
*(请将此处的图片链接替换为你实际上传到 Space Files 中的截图链接,例如:`/file/main/arena_screenshot.png`)* | |
*说明:此图展示了我们构建的“Arena”选项卡界面。用户可以在左侧输入问题/提示词和上下文,右侧同步显示文本生成模型和问答模型的输出。* | |
### 2.2 输入与输出流程图 | |
```mermaid | |
graph TD | |
A[用户输入: 问题/提示词] --> B{Gradio 界面}; | |
A --> C[用户输入: 上下文]; | |
C --> B; | |
B -- 将问题与上下文合并为Prompt --> D1[调用 GPT2-Large (文本生成模型)]; | |
B -- 将问题与上下文分离 --> D2[调用 RoBERTa-SQuAD2 (问答模型)]; | |
D1 -- 生成文本 --> E1[GPT2-Large 输出]; | |
D2 -- 抽取答案 --> E2[RoBERTa-SQuAD2 输出]; | |
E1 --> F[在 Gradio 界面显示]; | |
E2 --> F;""" |