Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/767-767_knowledge-base-assistant.json
T

1 line
9.0 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"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()"}}}}