Spaces:
Sleeping
Sleeping
update app.py
Browse files
app.py
CHANGED
|
@@ -1,7 +1,187 @@
|
|
| 1 |
import gradio as gr
|
|
|
|
|
|
|
| 2 |
|
| 3 |
-
def
|
| 4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
+
import pandas as pd
|
| 3 |
+
# from smolagents import CodeAgent, GradioUI # 我们稍后会用到 smolagents
|
| 4 |
|
| 5 |
+
def generate_report(file_obj, analysis_type, creator_ids, strategy_ids, plan_ids, time_range, time_dimension):
|
| 6 |
+
"""
|
| 7 |
+
处理上传的文件并根据用户输入生成分析报告。
|
| 8 |
+
"""
|
| 9 |
+
if file_obj is None:
|
| 10 |
+
return "请先上传一个 Excel 文件。"
|
| 11 |
|
| 12 |
+
try:
|
| 13 |
+
# 读取 Excel 文件
|
| 14 |
+
# 注意:Gradio 的 File 组件返回一个临时文件对象,我们需要从中获取路径
|
| 15 |
+
df = pd.read_excel(file_obj.name)
|
| 16 |
+
except Exception as e:
|
| 17 |
+
return f"读取 Excel 文件失败: {e}"
|
| 18 |
+
|
| 19 |
+
# TODO: 在这里根据用户的输入筛选 DataFrame (df)
|
| 20 |
+
# 1. 根据 analysis_type (短信/电销) 筛选
|
| 21 |
+
# 2. 根据 creator_ids, strategy_ids, plan_ids 筛选 (如果提供了这些ID)
|
| 22 |
+
# 3. 根据 time_range 和 time_dimension 筛选和聚合数据
|
| 23 |
+
|
| 24 |
+
# TODO: 生成报告内容
|
| 25 |
+
# 1. 整体情况
|
| 26 |
+
# 2. 按日期趋势
|
| 27 |
+
# 3. 按创建人、策略ID、计划ID分组
|
| 28 |
+
|
| 29 |
+
report_content = f"分析类型: {analysis_type}\n"
|
| 30 |
+
report_content += f"创建用户IDs: {creator_ids if creator_ids else '全部'}\n"
|
| 31 |
+
report_content += f"策略IDs: {strategy_ids if strategy_ids else '全部'}\n"
|
| 32 |
+
report_content += f"计划IDs: {plan_ids if plan_ids else '全部'}\n"
|
| 33 |
+
report_content += f"时间范围: {time_range}\n"
|
| 34 |
+
report_content += f"时间维度: {time_dimension}\n\n"
|
| 35 |
+
report_content += "--- 数据预览 (前5行) ---\n"
|
| 36 |
+
report_content += df.head().to_string()
|
| 37 |
+
|
| 38 |
+
# 临时返回一些信息,实际报告会更复杂
|
| 39 |
+
return report_content
|
| 40 |
+
|
| 41 |
+
# 定义 Gradio 界面组件
|
| 42 |
+
with gr.Blocks() as demo:
|
| 43 |
+
gr.Markdown("## 智能分析报告生成器")
|
| 44 |
+
|
| 45 |
+
with gr.Row():
|
| 46 |
+
file_input = gr.File(label="上传 Excel 数据文件 (.xlsx)", file_types=[".xlsx"])
|
| 47 |
+
|
| 48 |
+
with gr.Row():
|
| 49 |
+
analysis_type_dropdown = gr.Dropdown(label="选择分析类型", choices=["短信", "电销"], value="短信")
|
| 50 |
+
time_dimension_dropdown = gr.Dropdown(label="选择时间维度", choices=["日", "周", "月"], value="日")
|
| 51 |
+
|
| 52 |
+
with gr.Row():
|
| 53 |
+
# 使用 DateRange 作为时间范围选择器,但 Gradio 目前没有直接的 DateRange
|
| 54 |
+
# 我们暂时用两个 Date 输入框代替,或者一个 Text 输入框让用户手动输入
|
| 55 |
+
# 更优的方案是使用 gr.Textbox 并提示用户格式,或者等待 Gradio 支持 DateRange
|
| 56 |
+
# 这里为了简单,我们先用文本框,后续可以改进
|
| 57 |
+
# time_range_input = gr.Textbox(label="时间范围 (例如: YYYY-MM-DD to YYYY-MM-DD)")
|
| 58 |
+
# 或者使用两个 gr.inputs.Textbox
|
| 59 |
+
date_start_input = gr.Textbox(label="开始日期 (YYYY-MM-DD)", placeholder="例如: 2023-01-01")
|
| 60 |
+
date_end_input = gr.Textbox(label="结束日期 (YYYY-MM-DD)", placeholder="例如: 2023-01-31")
|
| 61 |
+
# 将两个日期输入合并为一个元组或列表传递给处理函数
|
| 62 |
+
# time_range_input = [date_start_input, date_end_input] # 这样直接传递组件对象是不对的
|
| 63 |
+
# 我们需要在调用 generate_report 时将它们的值组合起来
|
| 64 |
+
|
| 65 |
+
with gr.Row():
|
| 66 |
+
creator_input = gr.Textbox(label="创建用户ID (多个用逗号分隔, 留空为全部)", placeholder="例如: user1,user2")
|
| 67 |
+
strategy_input = gr.Textbox(label="策略ID (多个用逗号分隔, 留空为全部)", placeholder="例如: strategyA,strategyB")
|
| 68 |
+
plan_input = gr.Textbox(label="计划ID (多个用逗号分隔, 留空为全部)", placeholder="例如: planX,planY")
|
| 69 |
+
|
| 70 |
+
generate_button = gr.Button("生成分析报告")
|
| 71 |
+
report_output = gr.Textbox(label="分析报告", lines=15, interactive=False)
|
| 72 |
+
|
| 73 |
+
# 定义按钮点击事件的输入和输出
|
| 74 |
+
# 注意:对于日期范围,我们需要在调用时从 date_start_input 和 date_end_input 获取值
|
| 75 |
+
# Gradio 的 inputs 参数直接接受组件列表
|
| 76 |
+
generate_button.click(
|
| 77 |
+
fn=generate_report,
|
| 78 |
+
inputs=[
|
| 79 |
+
file_input,
|
| 80 |
+
analysis_type_dropdown,
|
| 81 |
+
creator_input,
|
| 82 |
+
strategy_input,
|
| 83 |
+
plan_input,
|
| 84 |
+
# 我们需要一个方式来组合 date_start_input 和 date_end_input
|
| 85 |
+
# Gradio 的 click 事件的 inputs 参数直接取组件的当前值
|
| 86 |
+
# 所以我们可以直接列出这两个组件,然后在 generate_report 函数内部处理它们的值
|
| 87 |
+
date_start_input,
|
| 88 |
+
date_end_input,
|
| 89 |
+
time_dimension_dropdown
|
| 90 |
+
],
|
| 91 |
+
outputs=report_output
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
# 为了正确传递时间范围,我们需要修改 generate_report 的签名,或者在调用前处理
|
| 95 |
+
# 让我们修改 generate_report 的签名,使其分别接收开始和结束日期
|
| 96 |
+
# 或者,更 Gradio 的方式是,让 generate_report 接收���有输入组件的值,然后在函数内部解析
|
| 97 |
+
# 当前的 generate_report 签名是:
|
| 98 |
+
# def generate_report(file_obj, analysis_type, creator_ids, strategy_ids, plan_ids, time_range, time_dimension):
|
| 99 |
+
# 我们需要将 time_range 拆分或修改 inputs 列表
|
| 100 |
+
|
| 101 |
+
# 修正后的 click 事件,假设 generate_report 签名改为接收 start_date 和 end_date
|
| 102 |
+
# def generate_report(file_obj, analysis_type, creator_ids, strategy_ids, plan_ids, start_date, end_date, time_dimension):
|
| 103 |
+
# 那么 inputs 列表应该是:
|
| 104 |
+
# inputs=[file_input, analysis_type_dropdown, creator_input, strategy_input, plan_input, date_start_input, date_end_input, time_dimension_dropdown]
|
| 105 |
+
# 这与我们上面已经写的是一致的,所以只需要确保 generate_report 函数的参数顺序和数量匹配。
|
| 106 |
+
# 我们需要修改 generate_report 函数的签名以匹配这里的 inputs。
|
| 107 |
+
|
| 108 |
+
# 修改 generate_report 函数签名以匹配 Gradio inputs
|
| 109 |
+
def generate_report_updated(file_obj, analysis_type, creator_ids, strategy_ids, plan_ids, start_date, end_date, time_dimension):
|
| 110 |
+
"""
|
| 111 |
+
处理上传的文件并根据用户输入生成分析报告。
|
| 112 |
+
(签名已更新以匹配Gradio输入)
|
| 113 |
+
"""
|
| 114 |
+
if file_obj is None:
|
| 115 |
+
return "请先上传一个 Excel 文件。"
|
| 116 |
+
|
| 117 |
+
try:
|
| 118 |
+
df = pd.read_excel(file_obj.name)
|
| 119 |
+
except Exception as e:
|
| 120 |
+
return f"读取 Excel 文件失败: {e}"
|
| 121 |
+
|
| 122 |
+
# 将逗号分隔的字符串ID转换为列表,如果为空则为 None 或空列表
|
| 123 |
+
creator_ids_list = [c.strip() for c in creator_ids.split(',') if c.strip()] if creator_ids else []
|
| 124 |
+
strategy_ids_list = [s.strip() for s in strategy_ids.split(',') if s.strip()] if strategy_ids else []
|
| 125 |
+
plan_ids_list = [p.strip() for p in plan_ids.split(',') if p.strip()] if plan_ids else []
|
| 126 |
+
|
| 127 |
+
# 时间范围处理 (这里简单组合,实际应用中可能需要日期校验和转换)
|
| 128 |
+
time_range_str = f"{start_date} 至 {end_date}"
|
| 129 |
+
|
| 130 |
+
# TODO: 数据筛选和报告生成逻辑 (与原 generate_report 中的 TODO 相同)
|
| 131 |
+
# ...
|
| 132 |
+
|
| 133 |
+
report_content = f"分析类型: {analysis_type}\n"
|
| 134 |
+
report_content += f"创建用户IDs: {creator_ids_list if creator_ids_list else '全部'}\n"
|
| 135 |
+
report_content += f"策略IDs: {strategy_ids_list if strategy_ids_list else '全部'}\n"
|
| 136 |
+
report_content += f"计划IDs: {plan_ids_list if plan_ids_list else '全部'}\n"
|
| 137 |
+
report_content += f"时间范围: {time_range_str}\n"
|
| 138 |
+
report_content += f"时间维度: {time_dimension}\n\n"
|
| 139 |
+
report_content += "--- 数据预览 (前5行) ---\n"
|
| 140 |
+
report_content += df.head().to_string()
|
| 141 |
+
|
| 142 |
+
return report_content
|
| 143 |
+
|
| 144 |
+
# 更新 Gradio Blocks 中的 click 事件以使用新的函数签名
|
| 145 |
+
# 我们需要重新定义 Blocks 或者确保上面的 click 事件使用了正确的函数
|
| 146 |
+
# 最好的做法是只定义一次 generate_report 函数,并确保其签名与 inputs 匹配
|
| 147 |
+
# 为了清晰,我将直接在 Blocks 定义中调用 generate_report_updated
|
| 148 |
+
|
| 149 |
+
with gr.Blocks() as demo_final:
|
| 150 |
+
gr.Markdown("## 智能分析报告生成器")
|
| 151 |
+
|
| 152 |
+
with gr.Row():
|
| 153 |
+
file_input_final = gr.File(label="上传 Excel 数据文件 (.xlsx)", file_types=[".xlsx"])
|
| 154 |
+
|
| 155 |
+
with gr.Row():
|
| 156 |
+
analysis_type_dropdown_final = gr.Dropdown(label="选择分析类型", choices=["短信", "电销"], value="短信")
|
| 157 |
+
time_dimension_dropdown_final = gr.Dropdown(label="选择时间维度", choices=["日", "周", "月"], value="日")
|
| 158 |
+
|
| 159 |
+
with gr.Row():
|
| 160 |
+
date_start_input_final = gr.Textbox(label="开始日期 (YYYY-MM-DD)", placeholder="例如: 2023-01-01")
|
| 161 |
+
date_end_input_final = gr.Textbox(label="结束日期 (YYYY-MM-DD)", placeholder="例如: 2023-01-31")
|
| 162 |
+
|
| 163 |
+
with gr.Row():
|
| 164 |
+
creator_input_final = gr.Textbox(label="创建用户ID (多个用逗号分隔, 留空为全部)", placeholder="例如: user1,user2")
|
| 165 |
+
strategy_input_final = gr.Textbox(label="策略ID (多个用逗号分隔, 留空为全部)", placeholder="例如: strategyA,strategyB")
|
| 166 |
+
plan_input_final = gr.Textbox(label="计划ID (多个用逗号分隔, 留空为全部)", placeholder="例如: planX,planY")
|
| 167 |
+
|
| 168 |
+
generate_button_final = gr.Button("生成分析报告")
|
| 169 |
+
report_output_final = gr.Textbox(label="分析报告", lines=15, interactive=False)
|
| 170 |
+
|
| 171 |
+
generate_button_final.click(
|
| 172 |
+
fn=generate_report_updated, # 使用更新了签名的函数
|
| 173 |
+
inputs=[
|
| 174 |
+
file_input_final,
|
| 175 |
+
analysis_type_dropdown_final,
|
| 176 |
+
creator_input_final,
|
| 177 |
+
strategy_input_final,
|
| 178 |
+
plan_input_final,
|
| 179 |
+
date_start_input_final,
|
| 180 |
+
date_end_input_final,
|
| 181 |
+
time_dimension_dropdown_final
|
| 182 |
+
],
|
| 183 |
+
outputs=report_output_final
|
| 184 |
+
)
|
| 185 |
+
|
| 186 |
+
if __name__ == "__main__":
|
| 187 |
+
demo_final.launch()
|