DataAnalyst / app.py
HeyEden's picture
update app.py
06ee7cd verified
import gradio as gr
import pandas as pd
# from smolagents import CodeAgent, GradioUI # 我们稍后会用到 smolagents
def generate_report(file_obj, analysis_type, creator_ids, strategy_ids, plan_ids, time_range, time_dimension):
"""
处理上传的文件并根据用户输入生成分析报告。
"""
if file_obj is None:
return "请先上传一个 Excel 文件。"
try:
# 读取 Excel 文件
# 注意:Gradio 的 File 组件返回一个临时文件对象,我们需要从中获取路径
df = pd.read_excel(file_obj.name)
except Exception as e:
return f"读取 Excel 文件失败: {e}"
# TODO: 在这里根据用户的输入筛选 DataFrame (df)
# 1. 根据 analysis_type (短信/电销) 筛选
# 2. 根据 creator_ids, strategy_ids, plan_ids 筛选 (如果提供了这些ID)
# 3. 根据 time_range 和 time_dimension 筛选和聚合数据
# TODO: 生成报告内容
# 1. 整体情况
# 2. 按日期趋势
# 3. 按创建人、策略ID、计划ID分组
report_content = f"分析类型: {analysis_type}\n"
report_content += f"创建用户IDs: {creator_ids if creator_ids else '全部'}\n"
report_content += f"策略IDs: {strategy_ids if strategy_ids else '全部'}\n"
report_content += f"计划IDs: {plan_ids if plan_ids else '全部'}\n"
report_content += f"时间范围: {time_range}\n"
report_content += f"时间维度: {time_dimension}\n\n"
report_content += "--- 数据预览 (前5行) ---\n"
report_content += df.head().to_string()
# 临时返回一些信息,实际报告会更复杂
return report_content
# 定义 Gradio 界面组件
with gr.Blocks() as demo:
gr.Markdown("## 智能分析报告生成器")
with gr.Row():
file_input = gr.File(label="上传 Excel 数据文件 (.xlsx)", file_types=[".xlsx"])
with gr.Row():
analysis_type_dropdown = gr.Dropdown(label="选择分析类型", choices=["短信", "电销"], value="短信")
time_dimension_dropdown = gr.Dropdown(label="选择时间维度", choices=["日", "周", "月"], value="日")
with gr.Row():
# 使用 DateRange 作为时间范围选择器,但 Gradio 目前没有直接的 DateRange
# 我们暂时用两个 Date 输入框代替,或者一个 Text 输入框让用户手动输入
# 更优的方案是使用 gr.Textbox 并提示用户格式,或者等待 Gradio 支持 DateRange
# 这里为了简单,我们先用文本框,后续可以改进
# time_range_input = gr.Textbox(label="时间范围 (例如: YYYY-MM-DD to YYYY-MM-DD)")
# 或者使用两个 gr.inputs.Textbox
date_start_input = gr.Textbox(label="开始日期 (YYYY-MM-DD)", placeholder="例如: 2023-01-01")
date_end_input = gr.Textbox(label="结束日期 (YYYY-MM-DD)", placeholder="例如: 2023-01-31")
# 将两个日期输入合并为一个元组或列表传递给处理函数
# time_range_input = [date_start_input, date_end_input] # 这样直接传递组件对象是不对的
# 我们需要在调用 generate_report 时将它们的值组合起来
with gr.Row():
creator_input = gr.Textbox(label="创建用户ID (多个用逗号分隔, 留空为全部)", placeholder="例如: user1,user2")
strategy_input = gr.Textbox(label="策略ID (多个用逗号分隔, 留空为全部)", placeholder="例如: strategyA,strategyB")
plan_input = gr.Textbox(label="计划ID (多个用逗号分隔, 留空为全部)", placeholder="例如: planX,planY")
generate_button = gr.Button("生成分析报告")
report_output = gr.Textbox(label="分析报告", lines=15, interactive=False)
# 定义按钮点击事件的输入和输出
# 注意:对于日期范围,我们需要在调用时从 date_start_input 和 date_end_input 获取值
# Gradio 的 inputs 参数直接接受组件列表
generate_button.click(
fn=generate_report,
inputs=[
file_input,
analysis_type_dropdown,
creator_input,
strategy_input,
plan_input,
# 我们需要一个方式来组合 date_start_input 和 date_end_input
# Gradio 的 click 事件的 inputs 参数直接取组件的当前值
# 所以我们可以直接列出这两个组件,然后在 generate_report 函数内部处理它们的值
date_start_input,
date_end_input,
time_dimension_dropdown
],
outputs=report_output
)
# 为了正确传递时间范围,我们需要修改 generate_report 的签名,或者在调用前处理
# 让我们修改 generate_report 的签名,使其分别接收开始和结束日期
# 或者,更 Gradio 的方式是,让 generate_report 接收所有输入组件的值,然后在函数内部解析
# 当前的 generate_report 签名是:
# def generate_report(file_obj, analysis_type, creator_ids, strategy_ids, plan_ids, time_range, time_dimension):
# 我们需要将 time_range 拆分或修改 inputs 列表
# 修正后的 click 事件,假设 generate_report 签名改为接收 start_date 和 end_date
# def generate_report(file_obj, analysis_type, creator_ids, strategy_ids, plan_ids, start_date, end_date, time_dimension):
# 那么 inputs 列表应该是:
# inputs=[file_input, analysis_type_dropdown, creator_input, strategy_input, plan_input, date_start_input, date_end_input, time_dimension_dropdown]
# 这与我们上面已经写的是一致的,所以只需要确保 generate_report 函数的参数顺序和数量匹配。
# 我们需要修改 generate_report 函数的签名以匹配这里的 inputs。
# 修改 generate_report 函数签名以匹配 Gradio inputs
def generate_report_updated(file_obj, analysis_type, creator_ids, strategy_ids, plan_ids, start_date, end_date, time_dimension):
"""
处理上传的文件并根据用户输入生成分析报告。
(签名已更新以匹配Gradio输入)
"""
if file_obj is None:
return "请先上传一个 Excel 文件。"
try:
df = pd.read_excel(file_obj.name)
except Exception as e:
return f"读取 Excel 文件失败: {e}"
# 将逗号分隔的字符串ID转换为列表,如果为空则为 None 或空列表
creator_ids_list = [c.strip() for c in creator_ids.split(',') if c.strip()] if creator_ids else []
strategy_ids_list = [s.strip() for s in strategy_ids.split(',') if s.strip()] if strategy_ids else []
plan_ids_list = [p.strip() for p in plan_ids.split(',') if p.strip()] if plan_ids else []
# 时间范围处理 (这里简单组合,实际应用中可能需要日期校验和转换)
time_range_str = f"{start_date}{end_date}"
# TODO: 数据筛选和报告生成逻辑 (与原 generate_report 中的 TODO 相同)
# ...
report_content = f"分析类型: {analysis_type}\n"
report_content += f"创建用户IDs: {creator_ids_list if creator_ids_list else '全部'}\n"
report_content += f"策略IDs: {strategy_ids_list if strategy_ids_list else '全部'}\n"
report_content += f"计划IDs: {plan_ids_list if plan_ids_list else '全部'}\n"
report_content += f"时间范围: {time_range_str}\n"
report_content += f"时间维度: {time_dimension}\n\n"
report_content += "--- 数据预览 (前5行) ---\n"
report_content += df.head().to_string()
return report_content
# 更新 Gradio Blocks 中的 click 事件以使用新的函数签名
# 我们需要重新定义 Blocks 或者确保上面的 click 事件使用了正确的函数
# 最好的做法是只定义一次 generate_report 函数,并确保其签名与 inputs 匹配
# 为了清晰,我将直接在 Blocks 定义中调用 generate_report_updated
with gr.Blocks() as demo_final:
gr.Markdown("## 智能分析报告生成器")
with gr.Row():
file_input_final = gr.File(label="上传 Excel 数据文件 (.xlsx)", file_types=[".xlsx"])
with gr.Row():
analysis_type_dropdown_final = gr.Dropdown(label="选择分析类型", choices=["短信", "电销"], value="短信")
time_dimension_dropdown_final = gr.Dropdown(label="选择时间维度", choices=["日", "周", "月"], value="日")
with gr.Row():
date_start_input_final = gr.Textbox(label="开始日期 (YYYY-MM-DD)", placeholder="例如: 2023-01-01")
date_end_input_final = gr.Textbox(label="结束日期 (YYYY-MM-DD)", placeholder="例如: 2023-01-31")
with gr.Row():
creator_input_final = gr.Textbox(label="创建用户ID (多个用逗号分隔, 留空为全部)", placeholder="例如: user1,user2")
strategy_input_final = gr.Textbox(label="策略ID (多个用逗号分隔, 留空为全部)", placeholder="例如: strategyA,strategyB")
plan_input_final = gr.Textbox(label="计划ID (多个用逗号分隔, 留空为全部)", placeholder="例如: planX,planY")
generate_button_final = gr.Button("生成分析报告")
report_output_final = gr.Textbox(label="分析报告", lines=15, interactive=False)
generate_button_final.click(
fn=generate_report_updated, # 使用更新了签名的函数
inputs=[
file_input_final,
analysis_type_dropdown_final,
creator_input_final,
strategy_input_final,
plan_input_final,
date_start_input_final,
date_end_input_final,
time_dimension_dropdown_final
],
outputs=report_output_final
)
if __name__ == "__main__":
demo_final.launch()