1 line
9.0 KiB
JSON
1 line
9.0 KiB
JSON
{"repo": "767-767/knowledge-base-assistant", "files": {"app.py": {"609c09a1bb618e1096fd14c67079509d8c727df9": {"t": 1785745408.6800077, "n": 7083, "h": "ca43260d36b1ae3a", "c": "import os\nimport ssl\nimport random\nfrom dotenv import load_dotenv\nload_dotenv()\nos.environ[\"HF_ENDPOINT\"] = \"https://hf-mirror.com\"\nssl._create_default_https_context = ssl._create_unverified_context\n\nimport gradio as gr\nfrom langchain_text_splitters import RecursiveCharacterTextSplitter\nfrom langchain_community.document_loaders import PyPDFLoader, TextLoader, Docx2txtLoader\nfrom sentence_transformers import SentenceTransformer\nimport chromadb\nimport uuid\nfrom openai import OpenAI\n\n# ---------- 初始化 ----------\nDEEPSEEK_API_KEY = os.getenv(\"DEEPSEEK_API_KEY\")\nif not DEEPSEEK_API_KEY:\n raise ValueError(\"请在 .env 文件中设置 DEEPSEEK_API_KEY\")\n\nclient = OpenAI(api_key=DEEPSEEK_API_KEY, base_url=\"https://api.deepseek.com/v1\")\nembedding_model = SentenceTransformer(\"BAAI/bge-small-zh-v1.5\")\nchroma_client = chromadb.PersistentClient(path=\"./chroma_db\")\ncollection = chroma_client.get_or_create_collection(\n name=\"knowledge_base\",\n metadata={\"hnsw:space\": \"cosine\"}\n)\n\n# ---------- 文档处理 (保持不变) ----------\ndef load_and_split_document(file_path):\n if file_path.endswith(\".pdf\"):\n loader = PyPDFLoader(file_path)\n elif file_path.endswith(\".txt\"):\n loader = TextLoader(file_path, encoding=\"utf-8\")\n elif file_path.endswith(\".docx\"):\n loader = Docx2txtLoader(file_path)\n else:\n raise ValueError(\"不支持的文件类型\")\n documents = loader.load()\n text_splitter = RecursiveCharacterTextSplitter(\n chunk_size=512, chunk_overlap=64, length_function=len,\n separators=[\"\\n\\n\", \"\\n\", \"。\", \"!\", \"?\", \";\", \",\", \" \", \"\"]\n )\n return text_splitter.split_documents(documents)\n\ndef add_document_to_db(file_path):\n chunks = load_and_split_document(file_path)\n for chunk in chunks:\n chunk_id = str(uuid.uuid4())\n text = chunk.page_content\n metadata = {\"source\": os.path.basename(file_path)}\n embedding = embedding_model.encode(text).tolist()\n collection.add(\n ids=[chunk_id],\n embeddings=[embedding],\n documents=[text],\n metadatas=[metadata]\n )\n return f\"✅ 成功添加 {len(chunks)} 个文本块到知识库,当前共 {collection.count()} 个。\"\n\ndef upload_file(file):\n if file is None:\n return \"请选择一个文件\"\n return add_document_to_db(file.name)\n\n# ---------- 核心问答 (保持不变) ----------\ndef respond(message, history):\n if not message:\n return \"请输入一个问题。\"\n if collection.count() == 0:\n return \"📚 知识库为空,请先上传文档。\"\n \n question_embedding = embedding_model.encode(message).tolist()\n results = collection.query(query_embeddings=[question_embedding], n_results=3)\n retrieved_texts = results['documents'][0] if results['documents'] else []\n if not retrieved_texts:\n return \"未找到相关内容,请换个问法。\"\n \n context = \"\\n\\n---\\n\\n\".join(retrieved_texts)\n system_prompt = \"你是一个专业的学习助手。请根据参考资料回答问题,并注明来源。\"\n user_prompt = f\"【参考资料】\\n{context}\\n\\n【问题】\\n{message}\"\n \n try:\n response = client.chat.completions.create(\n model=\"deepseek-chat\",\n messages=[\n {\"role\": \"system\", \"content\": system_prompt},\n {\"role\": \"user\", \"content\": user_prompt}\n ],\n temperature=0.3,\n max_tokens=2048\n )\n answer = response.choices[0].message.content\n sources = [f\"- {meta.get('source', '未知')}\" for meta in results['metadatas'][0]]\n return answer + \"\\n\\n📌 **参考来源:**\\n\" + \"\\n\".join(sources)\n except Exception as e:\n return f\"❌ 调用出错:{str(e)}\"\n\n# ---------- 🆕 功能1:生成学习大纲/脑图 ----------\ndef generate_mindmap():\n if collection.count() == 0:\n return \"📚 知识库为空,请先上传文档。\"\n \n # 获取所有文档的片段(取前20个不同来源的块,防止token超限)\n all_chunks = collection.get()\n if not all_chunks or not all_chunks['documents']:\n return \"无法读取文档内容。\"\n \n # 简单去重,拼接上下文\n context = \"\\n\\n\".join(all_chunks['documents'][:15]) # 取前15块\n \n system_prompt = \"你是一位顶级学术助教。请根据提供的课程资料,生成一份层级清晰、结构完整的学习大纲。\"\n user_prompt = f\"\"\"请基于以下资料生成一份Markdown格式的层级大纲(使用 # ## ### - 表示层级),不要包含任何开场白或结尾总结,直接输出大纲结构。\n\n资料内容:\n{context}\n\"\"\"\n try:\n response = client.chat.completions.create(\n model=\"deepseek-chat\",\n messages=[\n {\"role\": \"system\", \"content\": system_prompt},\n {\"role\": \"user\", \"content\": user_prompt}\n ],\n temperature=0.3,\n max_tokens=2000\n )\n return response.choices[0].message.content\n except Exception as e:\n return f\"❌ 生成大纲失败:{str(e)}\"\n\n# ---------- 🆕 功能2:智能出题 ----------\ndef generate_quiz():\n if collection.count() == 0:\n return \"📚 知识库为空,请先上传文档。\"\n \n all_chunks = collection.get()\n if not all_chunks or not all_chunks['documents']:\n return \"无法读取文档内容。\"\n \n # 随机抽取5-8个块作为出题素材\n sample_chunks = random.sample(all_chunks['documents'], min(8, len(all_chunks['documents'])))\n context = \"\\n\\n\".join(sample_chunks)\n \n system_prompt = \"你是一个严谨的大学教师。请根据资料出5道单项选择题,用于考察学生对知识的掌握程度。\"\n user_prompt = f\"\"\"请根据以下资料,生成5道单项选择题。\n输出格式要求(严格遵守):\n第1题:[题目内容]\nA. [选项A] B. [选项B] C. [选项C] D. [选项D]\n答案:X\n解析:[详细解释为什么选这个]\n\n资料内容:\n{context}\n\"\"\"\n try:\n response = client.chat.completions.create(\n model=\"deepseek-chat\",\n messages=[\n {\"role\": \"system\", \"content\": system_prompt},\n {\"role\": \"user\", \"content\": user_prompt}\n ],\n temperature=0.4, # 稍微提高一点随机性让题目更有趣\n max_tokens=2000\n )\n return response.choices[0].message.content\n except Exception as e:\n return f\"❌ 出题失败:{str(e)}\"\n\n# ---------- Gradio 集成界面 (全新升级) ----------\nwith gr.Blocks(title=\"AI 大学生学习工作台\", theme=gr.themes.Soft()) as demo:\n gr.Markdown(\"# 🎓 AI 大学生学习工作台\")\n gr.Markdown(\"上传你的课件或论文,用 AI 帮你学!\")\n \n # 第一栏:上传文档(通用)\n with gr.Tab(\"📤 上传文档\"):\n file_input = gr.File(label=\"选择文档\", file_types=[\".pdf\", \".txt\", \".docx\"])\n upload_output = gr.Textbox(label=\"上传状态\", lines=3)\n upload_button = gr.Button(\"添加到知识库\")\n upload_button.click(upload_file, inputs=file_input, outputs=upload_output)\n # 显示当前知识库状态\n gr.Markdown(f\"**当前知识库文本块数:** {collection.count()}\")\n\n # 第二栏:智能问答(原有升级)\n with gr.Tab(\"💬 智能问答\"):\n gr.ChatInterface(\n fn=respond,\n title=\"📖 基于文档的问答\",\n description=\"输入问题,AI会从已上传的文档中检索答案。\",\n chatbot=gr.Chatbot(height=450),\n textbox=gr.Textbox(placeholder=\"例如:这篇论文的核心创新点是什么?\", scale=7)\n )\n\n # 第三栏:🆕 生成大纲/脑图\n with gr.Tab(\"🧠 生成学习大纲\"):\n gr.Markdown(\"### 一键生成层级学习大纲(自动转为脑图结构)\")\n btn_mindmap = gr.Button(\"🚀 生成大纲与脑图\")\n output_mindmap = gr.Markdown(label=\"📋 大纲内容\", value=\"点击上方按钮生成...\")\n btn_mindmap.click(generate_mindmap, inputs=[], outputs=output_mindmap)\n\n # 第四栏:🆕 智能出题\n with gr.Tab(\"📝 智能出题\"):\n gr.Markdown(\"### 基于当前知识库自动生成练习题(含解析)\")\n btn_quiz = gr.Button(\"📝 生成5道选择题\")\n output_quiz = gr.Markdown(label=\"📋 题目与解析\", value=\"点击上方按钮生成...\")\n btn_quiz.click(generate_quiz, inputs=[], outputs=output_quiz)\n\n# ---------- 启动 ----------\nif __name__ == \"__main__\":\n demo.launch()"}}}} |