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()