Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import os | |
| from llm_utils import parse_srt_file, analyze_meeting_transcript, generate_summary | |
| # Gradio State variables to hold intermediate values | |
| # transcript_state will store the raw text from the SRT file | |
| # auto_template_state will store the template suggested by the LLM after analysis | |
| def handle_file_upload(srt_file_obj): | |
| """ | |
| Handles the SRT file upload. | |
| Parses the file, analyzes it for industry, purpose, and template suggestion. | |
| Returns values to update the UI and state variables. | |
| """ | |
| if srt_file_obj is None: | |
| # Clear all fields if no file is present (e.g., file removed) | |
| return "", "", "", "", "", "", "请上传SRT文件后再试 (Please upload an SRT file)." | |
| srt_file_path = srt_file_obj.name | |
| transcript_text = parse_srt_file(srt_file_path) | |
| if transcript_text is None: | |
| return "", "", "", "SRT文件解析失败 (Error parsing SRT file).", "", "", "SRT文件解析失败,请检查文件格式 (SRT parsing failed, please check file format)." | |
| try: | |
| industry, meeting_purpose, auto_suggested_template_val = analyze_meeting_transcript(transcript_text) | |
| return ( | |
| industry, | |
| meeting_purpose, | |
| auto_suggested_template_val, # This will populate the editable Textbox | |
| transcript_text, | |
| transcript_text, # For transcript_state | |
| auto_suggested_template_val, # For auto_template_state (original LLM suggestion) | |
| '上传SRT文件成功,点击"开始总结"生成总结 (SRT file uploaded successfully. Click \'Start Summarization\' to generate summary.)' | |
| ) | |
| except ValueError as ve: # API key issue | |
| error_msg = f"API配置错误 (API Configuration Error): {str(ve)}" | |
| return "", "", "", transcript_text, transcript_text, "", error_msg # Industry, Purpose, Template, Preview, TranscriptState, AutoTemplateState, Summary | |
| except Exception as e: | |
| error_msg = f"会议分析出错 (Error during meeting analysis): {e}" | |
| print(error_msg) | |
| return "", "", "", transcript_text, transcript_text, "", error_msg # Consistent error return for 7 outputs | |
| def handle_summarization(current_transcript_text, edited_template_text, reference_summary_text, user_notes_text): | |
| """ | |
| Handles the summarization process after the 'Start Summarization' button is clicked. | |
| Uses the transcript and either the (potentially edited) auto-suggested template | |
| or a reference summary, along with user's manual notes. | |
| The edited_template_text comes directly from the output_suggested_template textbox. | |
| """ | |
| if not current_transcript_text: | |
| return "无转写内容可供总结,请先上传SRT文件 (No transcript to summarize. Please upload an SRT file first)." | |
| summary_output = "" | |
| try: | |
| if reference_summary_text and reference_summary_text.strip(): | |
| summary_output = generate_summary(current_transcript_text, reference_summary_text=reference_summary_text, user_notes=user_notes_text) | |
| elif edited_template_text and edited_template_text.strip(): # Prioritize edited template | |
| summary_output = generate_summary(current_transcript_text, auto_template_structure=edited_template_text, user_notes=user_notes_text) | |
| else: | |
| return "无可用模板,请输入或确保自动推荐的模板已生成且未被清空 (No template available. Please enter one or ensure the auto-suggested template was generated and not cleared)." | |
| except ValueError as ve: # API key issue | |
| return f"API配置错误 (API Configuration Error): {str(ve)}" | |
| except Exception as e: | |
| error_message = f"生成总结出错 (Error during summary generation): {e}" | |
| print(error_message) | |
| return error_message | |
| return summary_output | |
| # Gradio Interface Definition | |
| with gr.Blocks(theme=gr.themes.Soft()) as demo: | |
| gr.Markdown("## 会议总结程序 V1.2") # Version updated | |
| gr.Markdown( | |
| "上传会议的SRT格式录音转写文件,系统将:\n" + | |
| "1. **自动分析** 会议内容,给出所属行业和推荐的总结模板。\n" + | |
| "2. (可选)您可以输入一个参考总结文本。\n" + | |
| "3. (新增)您可以输入手动记录的关键笔记,系统将重点关注和包含这些内容。\n" + | |
| "4. 点击 **开始总结** 按钮后,系统将根据推荐模板或您提供的参考总结格式,结合您的手动笔记,生成最终的会议纪要。" | |
| ) | |
| # Hidden state variables | |
| transcript_state = gr.State(value="") | |
| auto_template_state = gr.State(value="") # Stores the original LLM template suggestion | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| srt_file_input = gr.File(label="上传SRT文件", file_types=[".srt"]) | |
| reference_summary_input = gr.Textbox( | |
| label="参考总结 (可选,优先使用此模板)", | |
| placeholder="如果希望按特定格式总结,请在此处粘贴参考总结文本...", | |
| lines=8 | |
| ) | |
| user_notes_input = gr.Textbox( | |
| label="手动记录的关键笔记 (可选)", | |
| placeholder="请在此处输入您在会议过程中记录的关键词、关键数字、重要观点等...", | |
| lines=6 | |
| ) | |
| submit_button = gr.Button("开始总结", variant="primary") | |
| with gr.Column(scale=2): | |
| gr.Markdown("### 分析结果 (SRT上传后自动更新)") | |
| output_industry = gr.Textbox(label="推测行业", interactive=False) | |
| output_meeting_purpose = gr.Textbox(label="会议目的", interactive=False) | |
| # Changed to Textbox, made interactive, and given more lines for editing | |
| output_suggested_template = gr.Textbox(label="推荐总结模板 (可编辑)", interactive=True, lines=10) | |
| gr.Markdown("### 会议总结 (点击按钮后生成)") | |
| output_summary = gr.Markdown(label="会议总结") # Output summary remains Markdown for rendering | |
| gr.Markdown("### 原始SRT转写内容 (上传SRT后自动更新)") | |
| output_transcript_preview = gr.Textbox(label="SRT文本预览", lines=8, interactive=False) | |
| # Event for file upload: triggers analysis | |
| srt_file_input.upload( | |
| fn=handle_file_upload, | |
| inputs=[srt_file_input], | |
| outputs=[ | |
| output_industry, | |
| output_meeting_purpose, | |
| output_suggested_template, # Now populates the Textbox | |
| output_transcript_preview, | |
| transcript_state, | |
| auto_template_state, | |
| output_summary | |
| ] | |
| ) | |
| # Event for button click: triggers summarization | |
| submit_button.click( | |
| fn=handle_summarization, | |
| inputs=[ | |
| transcript_state, | |
| output_suggested_template, # Use the current content of the textbox | |
| reference_summary_input, | |
| user_notes_input | |
| ], | |
| outputs=[output_summary] | |
| ) | |
| # Define a wrapper for the examples fn to match expected output structure | |
| def example_fn_wrapper(srt_file_obj, _reference_summary_text, _user_notes_text): | |
| analysis_results = handle_file_upload(srt_file_obj) | |
| if isinstance(analysis_results, tuple) and len(analysis_results) == 7: | |
| return analysis_results[:-1] + ("Example loaded. Edit template if needed, then click '开始总结'.",) | |
| else: | |
| return "Error", "Error", "Error loading example", "Please try manually.", "", "", "Error processing example." | |
| gr.Examples( | |
| examples=[ | |
| [os.path.join(os.path.dirname(__file__), "example_meeting.srt"), "", ""], | |
| [ | |
| os.path.join(os.path.dirname(__file__), "example_meeting.srt"), | |
| "会议纪要\n\n日期:YYYY-MM-DD\n主题:示例\n\n讨论点:\n- 点一\n- 点二\n\n行动项:\n- 某人:某事 (截止日期)", | |
| "重要数字:预算 50万元\n关键决策:选择方案A\n重点关注:Q2季度目标" | |
| ] | |
| ], | |
| inputs=[srt_file_input, reference_summary_input, user_notes_input], | |
| outputs=[output_industry, output_meeting_purpose, output_suggested_template, output_transcript_preview, transcript_state, auto_template_state, output_summary], | |
| fn=example_fn_wrapper, | |
| cache_examples=False | |
| ) | |
| if __name__ == "__main__": | |
| if not os.getenv("OPENROUTER_API_KEY"): | |
| print("警告: OPENROUTER_API_KEY 环境变量未设置。") | |
| print("请在您的环境中设置它,或在项目根目录创建一个 .env 文件,内容如下:") | |
| print('OPENROUTER_API_KEY="sk-or-v1-your-key-here"') | |
| print('OPENROUTER_MODEL="your-chosen-model" (例如 mistralai/mistral-7b-instruct)') | |
| print("程序可能无法正常与大模型交互。") | |
| demo.launch() |