Spaces:
Sleeping
Sleeping
| import os | |
| from pathlib import Path | |
| from dotenv import load_dotenv | |
| # LlamaIndex 核心组件 | |
| from llama_index.core import ( | |
| VectorStoreIndex, | |
| SimpleDirectoryReader, | |
| StorageContext, | |
| load_index_from_storage, | |
| Settings, | |
| ) | |
| from llama_index.embeddings.openai import OpenAIEmbedding | |
| # ============================ | |
| # 环境变量 & 路径配置 | |
| # ============================ | |
| # 加载 .env(和 Clare 项目保持一致,直接复用 OPENAI_API_KEY) | |
| load_dotenv() | |
| PROJECT_ROOT = Path(__file__).resolve().parent | |
| # 1. GENAI 课程目录(你要向量化的本地课程代码 / 笔记) | |
| # 这里用绝对路径更稳,不怕你从哪里运行脚本 | |
| EXPORT_DIR = PROJECT_ROOT / "GENAI COURSES" | |
| # 2. 向量数据库持久化路径 | |
| PERSIST_DIR = PROJECT_ROOT / "genai_courses_index" | |
| # 3. 显式指定 Embedding 模型(和 Clare 一致:text-embedding-3-small) | |
| Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small") | |
| def get_index(force_rebuild=False): | |
| """ | |
| 获取索引:优先读取本地缓存,如果不存在或强制刷新,则重新构建 | |
| """ | |
| # 情况 A: 数据库已存在,直接加载 (极快,不花钱) | |
| if PERSIST_DIR.exists() and not force_rebuild: | |
| print(f"📂 发现本地数据库 ({PERSIST_DIR}),正在加载...") | |
| try: | |
| storage_context = StorageContext.from_defaults(persist_dir=str(PERSIST_DIR)) | |
| index = load_index_from_storage(storage_context) | |
| print("✅ 加载成功!") | |
| return index | |
| except Exception as e: | |
| print(f"⚠️ 本地数据库加载失败: {e},准备重新构建...") | |
| # 情况 B: 数据库不存在,或者要求强制更新 -> 读取本地文件构建 | |
| print(f"🚀 开始扫描本地文件并构建向量数据库:{EXPORT_DIR}") | |
| if not EXPORT_DIR.exists(): | |
| raise FileNotFoundError(f"GENAI COURSES 目录不存在:{EXPORT_DIR}") | |
| # 1. 读取文件 | |
| # recursive=True 会读取子文件夹,确保附件和嵌套页面都被读取 | |
| # required_exts 可以指定只读 .md,如果不加这行则会读取所有支持的文件(pdf, txt, etc.) | |
| reader = SimpleDirectoryReader( | |
| input_dir=str(EXPORT_DIR), | |
| recursive=True, | |
| # 可以根据需要调整:这里把常见的课程文件类型都包含进来 | |
| required_exts=[".md", ".pdf", ".txt", ".py", ".ipynb"], | |
| ) | |
| documents = reader.load_data() | |
| print(f"📄 成功读取了 {len(documents)} 个文件片段") | |
| # 2. 构建索引 (这一步会调用 OpenAI API 进行 Embedding) | |
| print("🧠 正在生成向量索引 (Embedding)...") | |
| index = VectorStoreIndex.from_documents(documents) | |
| # 3. 保存到硬盘 | |
| print(f"💾 正在保存数据库到 {PERSIST_DIR} ...") | |
| index.storage_context.persist(persist_dir=PERSIST_DIR) | |
| return index | |
| if __name__ == "__main__": | |
| # --- 主程序 --- | |
| # 首次运行或通过参数控制 force_rebuild=True 来更新 | |
| index = get_index(force_rebuild=False) | |
| # 创建查询引擎 | |
| query_engine = index.as_query_engine() | |
| print("\n💬 本地知识库助手已就绪 (输入 'exit' 退出, 'update' 重建):") | |
| while True: | |
| question = input("\n请输入问题: ") | |
| if question.lower() == 'exit': | |
| break | |
| elif question.lower() == 'update': | |
| index = get_index(force_rebuild=True) | |
| query_engine = index.as_query_engine() | |
| print("✅ 数据库已更新!") | |
| continue | |
| response = query_engine.query(question) | |
| print(f"\n🤖 回答:\n{response}") |