Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import google.generativeai as genai | |
| import pdfplumber | |
| import os | |
| # 推荐用 Hugging Face Spaces 的 Secrets 管理 API Key | |
| API_KEY = os.environ.get("GEMINI_API_KEY", "你的_Gemini_API_Key") | |
| def extract_text_from_pdf(file): | |
| """从PDF文件提取文本""" | |
| try: | |
| with pdfplumber.open(file.name) as pdf: | |
| text = "" | |
| for page in pdf.pages: | |
| page_text = page.extract_text() | |
| if page_text: | |
| text += page_text + "\n" | |
| return text.strip() | |
| except Exception as e: | |
| return f"PDF解析失败: {str(e)}" | |
| def call_gemini(prompt, model="gemini-2.5-flash", api_key=API_KEY): | |
| genai.configure(api_key=api_key) | |
| model = genai.GenerativeModel(model) | |
| response = model.generate_content(prompt) | |
| return response.text.strip() | |
| def generate_outline(text, api_key=API_KEY): | |
| prompt = ( | |
| "请根据以下内容,提炼出结构化的复习大纲,分层级展示,使用有条理的短语或句子:\n" | |
| f"{text}\n" | |
| "请用Markdown格式输出,主标题用#,二级用##,三级用###,不要有多余解释。" | |
| ) | |
| return call_gemini(prompt, api_key=api_key) | |
| def generate_qa(text, max_questions=5, api_key=API_KEY): | |
| prompt = ( | |
| f"请根据以下内容,生成{max_questions}道典型考题及标准答案,题型以简答题为主,内容覆盖重点知识点:\n" | |
| f"{text}\n" | |
| "请用如下格式输出:\n" | |
| "【问题】xxx\n【答案】xxx\n" | |
| ) | |
| return call_gemini(prompt, api_key=api_key) | |
| def generate_mindmap(text, api_key=API_KEY): | |
| prompt = ( | |
| "请根据以下内容,生成结构化的思维导图,使用Markdown格式,主标题用#,二级用##,三级用###," | |
| "内容要分层、条理清晰,突出知识点之间的关系。只输出Markdown,不要有多余解释。\n" | |
| f"{text}" | |
| ) | |
| return call_gemini(prompt, api_key=api_key) | |
| def create_markmap_html(markdown_content): | |
| html_content = f""" | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <script src="https://cdn.jsdelivr.net/npm/d3@6"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/markmap-lib@0.15.3/dist/browser/standalone.min.js"></script> | |
| </head> | |
| <body> | |
| <svg id="mindmap" style="width:100%;height:600px"></svg> | |
| <script> | |
| window.markmap.Markmap.create(document.getElementById('mindmap'), null, `{markdown_content}`); | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| return html_content | |
| def main_func(file, max_questions, api_key): | |
| if file is None: | |
| return "请上传PDF文件", "", "", "" | |
| text = extract_text_from_pdf(file) | |
| if not text or text.startswith("PDF解析失败"): | |
| return text, "", "", "" | |
| outline_md = generate_outline(text, api_key) | |
| qa_md = generate_qa(text, max_questions, api_key) | |
| mindmap_md = generate_mindmap(text, api_key) | |
| mindmap_html = create_markmap_html(mindmap_md) | |
| return outline_md, qa_md, mindmap_md, mindmap_html | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# 📚 PDF自动复习助手:大纲 + 考题 + 思维导图 (Gemini)") | |
| with gr.Row(): | |
| with gr.Column(): | |
| file = gr.File(label="上传PDF文件", file_types=[".pdf"]) | |
| max_questions = gr.Slider(3, 20, value=5, label="考题数量") | |
| api_key = gr.Textbox(label="Gemini API Key(建议用Spaces Secrets,不建议明文填写)", value=API_KEY, type="password") | |
| submit_btn = gr.Button("一键生成") | |
| with gr.Column(): | |
| with gr.Tab("📝 大纲"): | |
| output_outline = gr.Textbox(label="复习大纲 (Markdown)", lines=15, interactive=False) | |
| with gr.Tab("📚 考题"): | |
| output_qa = gr.Textbox(label="考题与答案 (Markdown)", lines=15, interactive=False) | |
| with gr.Tab("🌳 思维导图源码"): | |
| output_md = gr.Textbox(label="思维导图 Markdown", lines=15, interactive=False) | |
| with gr.Tab("🌳 交互式思维导图"): | |
| output_html = gr.HTML(label="思维导图", elem_id="output-tree") | |
| submit_btn.click( | |
| main_func, | |
| inputs=[file, max_questions, api_key], | |
| outputs=[output_outline, output_qa, output_md, output_html] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |