建個(gè)人智能知識(shí)庫(kù):從Karpathy‘s LLM Wiki到第二大腦)
在AI技術(shù)快速迭代的今天如何系統(tǒng)性地學(xué)習(xí)并沉淀大語(yǔ)言模型LLM知識(shí)是許多開(kāi)發(fā)者和研究者面臨的共同挑戰(zhàn)。網(wǎng)上資料雖然豐富但往往零散、不成體系導(dǎo)致學(xué)習(xí)效率低下知識(shí)難以形成長(zhǎng)期有效的積累。本文將圍繞一個(gè)極具啟發(fā)性的項(xiàng)目——Karpathy‘s LLM Wiki as a “Brain KIT”為你拆解如何將其作為構(gòu)建個(gè)人“知識(shí)復(fù)利”系統(tǒng)的核心工具。我們將從概念解析、環(huán)境搭建、核心功能實(shí)踐到高級(jí)應(yīng)用手把手帶你打造一個(gè)專屬于你的、能夠持續(xù)進(jìn)化的LLM知識(shí)庫(kù)。無(wú)論你是AI領(lǐng)域的初學(xué)者還是希望深化理解的進(jìn)階開(kāi)發(fā)者都能從中獲得一套可落地的完整方案。1. 背景與核心概念什么是“Brain KIT”在深入實(shí)踐之前我們首先要理解這個(gè)項(xiàng)目的核心價(jià)值。它并非一個(gè)全新的軟件而是一個(gè)基于現(xiàn)有優(yōu)秀工具的方法論與實(shí)踐框架。1.1 LLM Wiki 與 Andrej KarpathyAndrej Karpathy 是AI領(lǐng)域的知名專家前特斯拉AI總監(jiān)、OpenAI研究員。他創(chuàng)建的LLM Wiki是一個(gè)開(kāi)源的知識(shí)庫(kù)項(xiàng)目旨在系統(tǒng)化地收集、整理關(guān)于大語(yǔ)言模型的一切知識(shí)包括論文解讀、技術(shù)架構(gòu)、訓(xùn)練技巧、應(yīng)用場(chǎng)景等。這個(gè)Wiki本身就是一個(gè)高質(zhì)量、結(jié)構(gòu)化的知識(shí)源。1.2 “Brain KIT” 的核心理念“Brain KIT” 在這里是一個(gè)比喻它代表一套用于構(gòu)建和管理個(gè)人知識(shí)并能產(chǎn)生“復(fù)利效應(yīng)”的工具包Knowledge Investment Toolkit。其核心思想是知識(shí)系統(tǒng)化將碎片化信息如論文、博客、代碼片段、個(gè)人筆記轉(zhuǎn)化為相互關(guān)聯(lián)的結(jié)構(gòu)化知識(shí)網(wǎng)絡(luò)。知識(shí)可計(jì)算化利用LLM的能力對(duì)知識(shí)庫(kù)進(jìn)行智能查詢、總結(jié)、關(guān)聯(lián)和推理讓靜態(tài)知識(shí)“活”起來(lái)。知識(shí)復(fù)利隨著知識(shí)庫(kù)的不斷積累和內(nèi)部鏈接的增強(qiáng)你每次查詢或?qū)W習(xí)新知識(shí)的效率會(huì)越來(lái)越高新知識(shí)能快速與舊知識(shí)建立連接產(chǎn)生“112”的效應(yīng)。1.3 與本項(xiàng)目相關(guān)的技術(shù)生態(tài)理解以下關(guān)鍵概念有助于我們更好地構(gòu)建系統(tǒng)LLM大語(yǔ)言模型如GPT-4、Llama、ChatGLM等是本項(xiàng)目的“大腦”負(fù)責(zé)理解和處理知識(shí)。Wiki系統(tǒng)一種支持鏈接、分類和協(xié)作的內(nèi)容管理系統(tǒng)。本項(xiàng)目常使用基于Markdown的Wiki工具如Wiki.js、MkDocs或筆記軟件如Obsidian、Logseq。RAG檢索增強(qiáng)生成。這是實(shí)現(xiàn)“可計(jì)算知識(shí)庫(kù)”的關(guān)鍵技術(shù)。它允許LLM從你的本地知識(shí)庫(kù)中檢索相關(guān)信息再基于這些信息生成更準(zhǔn)確、更相關(guān)的回答。AI Agent能夠自主執(zhí)行復(fù)雜任務(wù)的智能體。在本項(xiàng)目中可以構(gòu)建一個(gè)Agent來(lái)自動(dòng)化知識(shí)庫(kù)的維護(hù)如抓取新論文、總結(jié)內(nèi)容、建立索引等。簡(jiǎn)單來(lái)說(shuō)本項(xiàng)目的目標(biāo)是將Karpathy的LLM Wiki或其他優(yōu)質(zhì)知識(shí)源作為種子結(jié)合Wiki工具和RAG技術(shù)打造一個(gè)屬于你個(gè)人的、持續(xù)生長(zhǎng)且智能交互的“第二大腦”。2. 環(huán)境準(zhǔn)備與工具選型工欲善其事必先利其器。構(gòu)建“Brain KIT”需要一系列工具的配合。以下是一個(gè)推薦的技術(shù)棧你可以根據(jù)自身情況調(diào)整。2.1 核心工具清單工具類別推薦選項(xiàng)作用說(shuō)明知識(shí)管理/ WikiObsidian, Logseq, Wiki.js, MkDocs用于編輯、組織和可視化你的知識(shí)網(wǎng)絡(luò)。Obsidian/Logseq適合個(gè)人Wiki.js適合團(tuán)隊(duì)。內(nèi)容存儲(chǔ)本地Markdown文件, Git倉(cāng)庫(kù)所有知識(shí)以Markdown格式保存用Git進(jìn)行版本管理。向量數(shù)據(jù)庫(kù)Chroma, Qdrant, Weaviate, Pinecone存儲(chǔ)知識(shí)片段的向量嵌入實(shí)現(xiàn)快速語(yǔ)義檢索。本地開(kāi)發(fā)推薦Chroma。嵌入模型text-embedding-ada-002 (OpenAI), BGE, sentence-transformers將文本轉(zhuǎn)換為向量。本地部署可選BAAI/bge-small-zh-v1.5或all-MiniLM-L6-v2。大語(yǔ)言模型GPT-4 API, Claude API, 本地部署的Llama 3, ChatGLM作為推理和生成的核心。根據(jù)預(yù)算和隱私要求選擇云端或本地。開(kāi)發(fā)框架LangChain, LlamaIndex簡(jiǎn)化RAG流程的構(gòu)建連接LLM、向量庫(kù)和你的數(shù)據(jù)。自動(dòng)化腳本Python用于編寫(xiě)數(shù)據(jù)爬取、處理、導(dǎo)入和知識(shí)庫(kù)維護(hù)的Agent。2.2 基礎(chǔ)環(huán)境搭建我們以最通用的本地開(kāi)發(fā)環(huán)境為例。操作系統(tǒng)Windows 10/11, macOS, 或 Linux (Ubuntu 20.04)編程語(yǔ)言Python 3.9包管理pip 或 conda首先創(chuàng)建一個(gè)項(xiàng)目目錄并初始化Python環(huán)境。# 創(chuàng)建項(xiàng)目目錄 mkdir brain-kit-llm-wiki cd brain-kit-llm-wiki # 創(chuàng)建虛擬環(huán)境 (可選但推薦) python -m venv venv # Windows 激活 venv\Scripts\activate # macOS/Linux 激活 source venv/bin/activate # 安裝核心Python庫(kù) pip install langchain langchain-community langchain-openai pip install chromadb sentence-transformers pip install beautifulsoup4 requests markdownify # 用于網(wǎng)頁(yè)內(nèi)容抓取和轉(zhuǎn)換 pip install pypdf python-docx # 用于處理PDF和Word文檔2.3 知識(shí)管理工具安裝以O(shè)bsidian為例Obsidian是一個(gè)強(qiáng)大的、基于本地Markdown文件的知識(shí)管理工具其“雙向鏈接”和“圖譜視圖”功能完美契合“Brain KIT”的理念。訪問(wèn) Obsidian官網(wǎng) 下載并安裝。打開(kāi)Obsidian創(chuàng)建一個(gè)新的倉(cāng)庫(kù)Vault路徑指向我們項(xiàng)目下的一個(gè)子目錄例如./knowledge_vault。這個(gè)目錄將存放我們所有的Markdown筆記也是我們后續(xù)進(jìn)行文本處理和向量化的源數(shù)據(jù)目錄。至此基礎(chǔ)環(huán)境準(zhǔn)備完畢。接下來(lái)我們將進(jìn)入核心環(huán)節(jié)構(gòu)建知識(shí)庫(kù)。3. 核心流程拆解從數(shù)據(jù)到智能問(wèn)答構(gòu)建一個(gè)智能知識(shí)庫(kù)包含幾個(gè)關(guān)鍵步驟數(shù)據(jù)獲取、文本處理、向量化存儲(chǔ)、檢索與生成。下面我們逐一拆解。3.1 數(shù)據(jù)獲取與預(yù)處理我們的知識(shí)源可以是多元化的。以“Karpathy‘s LLM Wiki”為起點(diǎn)我們可以擴(kuò)展至論文、技術(shù)博客、官方文檔等。步驟1獲取LLM Wiki內(nèi)容Karpathy的LLM Wiki通常托管在GitHub上。我們可以克隆倉(cāng)庫(kù)或直接下載Markdown文件。# 克隆Wiki倉(cāng)庫(kù)假設(shè)倉(cāng)庫(kù)地址 git clone https://github.com/karpathy/llm-wiki.git ./source_data/llm-wiki克隆后./source_data/llm-wiki目錄下會(huì)包含一系列.md文件。步驟2編寫(xiě)預(yù)處理腳本我們需要一個(gè)Python腳本將Markdown文件中的純文本內(nèi)容提取出來(lái)并進(jìn)行清洗和分塊。分塊是為了避免文本過(guò)長(zhǎng)影響后續(xù)的嵌入和檢索效果。創(chuàng)建一個(gè)文件data_processor.py# data_processor.py import os import re from pathlib import Path from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.schema import Document def load_markdown_files(directory_path): 加載指定目錄下的所有Markdown文件 docs [] for root, dirs, files in os.walk(directory_path): for file in files: if file.endswith(“.md”): file_path Path(root) / file try: with open(file_path, ‘r’, encoding‘utf-8’) as f: text f.read() # 獲取相對(duì)路徑作為元數(shù)據(jù)的一部分 relative_path os.path.relpath(file_path, directory_path) # 創(chuàng)建LangChain Document對(duì)象 doc Document( page_contenttext, metadata{“source”: str(file_path), “relative_path”: relative_path} ) docs.append(doc) except Exception as e: print(f“Error reading {file_path}: {e}”) return docs def split_documents(documents, chunk_size1000, chunk_overlap200): 將文檔分割成小塊 text_splitter RecursiveCharacterTextSplitter( chunk_sizechunk_size, chunk_overlapchunk_overlap, length_functionlen, separators[“\n\n”, “\n”, “。”, “.”, “ ”, “”] ) return text_splitter.split_documents(documents) if __name__ “__main__”: # 示例處理LLM Wiki數(shù)據(jù) wiki_dir “./source_data/llm-wiki” raw_docs load_markdown_files(wiki_dir) print(f“Loaded {len(raw_docs)} markdown files.”) split_docs split_documents(raw_docs) print(f“Split into {len(split_docs)} chunks.”) # 可以在這里將 split_docs 保存為JSON或直接送入下一步向量化 # 例如保存到文件 import json with open(‘./processed_data/split_chunks.json’, ‘w’, encoding‘utf-8’) as f: # 將Document對(duì)象轉(zhuǎn)換為可序列化的字典 data_to_save [{“page_content”: doc.page_content, “metadata”: doc.metadata} for doc in split_docs] json.dump(data_to_save, f, ensure_asciiFalse, indent2) print(“Chunks saved to JSON file.”)3.2 向量化與存儲(chǔ)文本分塊后我們需要將其轉(zhuǎn)換為向量嵌入并存入向量數(shù)據(jù)庫(kù)以便進(jìn)行語(yǔ)義搜索。步驟創(chuàng)建向量數(shù)據(jù)庫(kù)創(chuàng)建文件vector_store.py# vector_store.py import chromadb from chromadb.config import Settings from sentence_transformers import SentenceTransformer import json class VectorStoreManager: def __init__(self, persist_directory“./chroma_db”, embedding_model_name“BAAI/bge-small-zh-v1.5”): # 初始化嵌入模型本地 self.embedding_model SentenceTransformer(embedding_model_name) # 初始化Chroma客戶端設(shè)置持久化路徑 self.client chromadb.PersistentClient(pathpersist_directory) # 獲取或創(chuàng)建集合 self.collection self.client.get_or_create_collection( name“l(fā)lm_wiki_knowledge”, metadata{“hnsw:space”: “cosine”} # 使用余弦相似度 ) def get_embedding(self, text): 生成單個(gè)文本的嵌入向量 return self.embedding_model.encode(text).tolist() def add_documents(self, documents): 將文檔列表添加到向量數(shù)據(jù)庫(kù) ids [] embeddings [] metadatas [] contents [] for idx, doc in enumerate(documents): content doc[“page_content”] embedding self.get_embedding(content) ids.append(f“id_{idx}”) embeddings.append(embedding) metadatas.append(doc[“metadata”]) contents.append(content) # 批量添加到集合 self.collection.add( embeddingsembeddings, documentscontents, metadatasmetadatas, idsids ) print(f“Added {len(documents)} documents to vector store.”) def search(self, query, top_k5): 語(yǔ)義搜索 query_embedding self.get_embedding(query) results self.collection.query( query_embeddings[query_embedding], n_resultstop_k ) return results if __name__ “__main__”: # 1. 初始化向量存儲(chǔ)管理器 vs_manager VectorStoreManager() # 2. 加載預(yù)處理好的數(shù)據(jù) with open(‘./processed_data/split_chunks.json’, ‘r’, encoding‘utf-8’) as f: documents json.load(f) # 3. 添加到向量數(shù)據(jù)庫(kù) vs_manager.add_documents(documents[:50]) # 先添加前50條作為測(cè)試 # 4. 測(cè)試搜索 test_query “什么是Transformer模型” search_results vs_manager.search(test_query) print(f“\nQuery: ‘{test_query}’”) print(“Top results:“) for i, (doc, meta) in enumerate(zip(search_results[‘documents’][0], search_results[‘metadatas’][0])): print(f”[{i1}] {doc[:200]}...“) # 打印前200個(gè)字符 print(f” Source: {meta.get(‘relative_path’, ‘N/A’)}\n”)運(yùn)行此腳本后會(huì)在./chroma_db目錄下生成向量數(shù)據(jù)庫(kù)文件。后續(xù)查詢將直接讀取這個(gè)數(shù)據(jù)庫(kù)無(wú)需重復(fù)計(jì)算嵌入。3.3 構(gòu)建RAG問(wèn)答鏈有了向量庫(kù)我們就可以構(gòu)建一個(gè)完整的問(wèn)答系統(tǒng)。這里使用LangChain來(lái)簡(jiǎn)化流程。創(chuàng)建文件rag_qa.py# rag_qa.py from langchain.chains import RetrievalQA from langchain_community.llms import Ollama # 假設(shè)使用本地Ollama運(yùn)行的Llama 3 from langchain_openai import ChatOpenAI # 或者使用OpenAI API from vector_store_manager import VectorStoreManager # 導(dǎo)入我們上面寫(xiě)的類 from langchain.embeddings import HuggingFaceEmbeddings from langchain.vectorstores import Chroma import os class RAGQASystem: def __init__(self, use_local_llmTrue): # 初始化嵌入模型與向量庫(kù)創(chuàng)建時(shí)保持一致 embeddings HuggingFaceEmbeddings(model_name“BAAI/bge-small-zh-v1.5”) # 從持久化目錄加載向量庫(kù) persist_directory “./chroma_db” self.vectorstore Chroma( persist_directorypersist_directory, embedding_functionembeddings, collection_name“l(fā)lm_wiki_knowledge” ) # 初始化LLM if use_local_llm: # 使用本地Ollama服務(wù)確保已安裝并運(yùn)行了Ollama及模型如llama3:8b self.llm Ollama(model“l(fā)lama3:8b”, temperature0.1) else: # 使用OpenAI API (需要設(shè)置環(huán)境變量 OPENAI_API_KEY) self.llm ChatOpenAI(model_name“gpt-3.5-turbo”, temperature0.1) # 構(gòu)建RetrievalQA鏈 self.qa_chain RetrievalQA.from_chain_type( llmself.llm, chain_type“stuff”, # 簡(jiǎn)單地將檢索到的文檔“塞”給LLM retrieverself.vectorstore.as_retriever(search_kwargs{“k”: 4}), return_source_documentsTrue, # 返回源文檔用于引用 verboseFalse ) def ask(self, question): 提問(wèn)并獲取答案 result self.qa_chain({“query”: question}) answer result[“result”] source_docs result[“source_documents”] # 格式化輸出 response f“Q: {question}\nA: {answer}\n\n---\n**參考來(lái)源:**\n” for i, doc in enumerate(source_docs): source doc.metadata.get(“source”, “Unknown”) response f”{i1}. {source}\n” return response if __name__ “__main__”: # 初始化系統(tǒng)使用本地LLM qa_system RAGQASystem(use_local_llmTrue) # 進(jìn)行問(wèn)答測(cè)試 questions [ “請(qǐng)解釋一下注意力機(jī)制Attention Mechanism的基本思想。”, “GPT模型和BERT模型的主要區(qū)別是什么”, “如何評(píng)估一個(gè)大語(yǔ)言模型的好壞” ] for q in questions: print(qa_system.ask(q)) print(“”*50)這個(gè)系統(tǒng)的工作流程是用戶提問(wèn) - 將問(wèn)題轉(zhuǎn)換為向量 - 在向量庫(kù)中搜索最相關(guān)的知識(shí)片段 - 將問(wèn)題和相關(guān)片段一起提交給LLM - LLM生成基于知識(shí)的答案。4. 完整實(shí)戰(zhàn)搭建個(gè)人LLM知識(shí)庫(kù)系統(tǒng)現(xiàn)在我們將上述模塊整合并加入自動(dòng)化與可視化構(gòu)建一個(gè)更完整的系統(tǒng)。4.1 項(xiàng)目結(jié)構(gòu)規(guī)劃一個(gè)清晰的項(xiàng)目結(jié)構(gòu)有助于長(zhǎng)期維護(hù)。brain-kit-llm-wiki/ ├── README.md ├── requirements.txt ├── config.yaml # 配置文件 ├── source_data/ # 原始知識(shí)源 │ ├── llm-wiki/ # Karpathy‘s LLM Wiki │ ├── papers/ # 下載的論文PDF │ └── blogs/ # 收藏的技術(shù)博客 ├── processed_data/ # 處理后的中間數(shù)據(jù) │ └── split_chunks.json ├── chroma_db/ # 向量數(shù)據(jù)庫(kù)自動(dòng)生成 ├── knowledge_vault/ # Obsidian知識(shí)庫(kù)目錄 ├── scripts/ # 自動(dòng)化腳本 │ ├── data_processor.py │ ├── vector_store.py │ ├── rag_qa.py │ ├── web_crawler.py # 網(wǎng)頁(yè)抓取腳本 │ └── sync_obsidian.py # 與Obsidian同步的腳本 ├── app/ # 簡(jiǎn)單的Web或CLI應(yīng)用 │ ├── main.py │ └── templates/ └── tests/ # 測(cè)試文件4.2 編寫(xiě)自動(dòng)化知識(shí)更新腳本知識(shí)庫(kù)需要持續(xù)更新。我們可以編寫(xiě)一個(gè)腳本定期從指定的RSS源或GitHub倉(cāng)庫(kù)抓取新內(nèi)容自動(dòng)處理后更新向量庫(kù)。scripts/web_crawler.py示例簡(jiǎn)化版# scripts/web_crawler.py import feedparser from bs4 import BeautifulSoup import requests from data_processor import split_documents # 復(fù)用之前的處理函數(shù) from vector_store_manager import VectorStoreManager import hashlib def fetch_blog_posts(rss_url“https://karpathy.ai/feed.xml”): 從RSS訂閱抓取博客文章 feed feedparser.parse(rss_url) new_docs [] for entry in feed.entries: # 檢查是否已處理過(guò)通過(guò)URL哈希 url_hash hashlib.md5(entry.link.encode()).hexdigest() if not is_already_processed(url_hash): print(f“Fetching: {entry.title}”) # 獲取文章內(nèi)容 try: response requests.get(entry.link, timeout10) soup BeautifulSoup(response.content, ‘html.parser’) # 提取正文這里需要根據(jù)目標(biāo)網(wǎng)站結(jié)構(gòu)調(diào)整選擇器 main_content soup.find(‘a(chǎn)rticle’).get_text(stripTrue) if soup.find(‘a(chǎn)rticle’) else soup.get_text(stripTrue) doc { “page_content”: f“# {entry.title}\n\n{main_content}”, “metadata”: {“source”: entry.link, “title”: entry.title, “type”: “blog”, “hash”: url_hash} } new_docs.append(doc) mark_as_processed(url_hash) except Exception as e: print(f“Error fetching {entry.link}: {e}”) return new_docs def is_already_processed(url_hash): 檢查URL是否已處理簡(jiǎn)單示例可用數(shù)據(jù)庫(kù)或文件記錄 try: with open(‘./processed_data/processed_urls.txt’, ‘r’) as f: processed f.read().splitlines() return url_hash in processed except FileNotFoundError: return False def mark_as_processed(url_hash): 標(biāo)記URL為已處理 with open(‘./processed_data/processed_urls.txt’, ‘a(chǎn)’) as f: f.write(url_hash ‘\n’) def update_knowledge_base(): 主更新流程 print(“開(kāi)始抓取新內(nèi)容...”) new_posts fetch_blog_posts() if new_posts: print(f“抓取到 {len(new_posts)} 篇新文章。”) # 文本分塊 split_new_docs split_documents(new_posts) # 更新向量數(shù)據(jù)庫(kù) vs_manager VectorStoreManager() vs_manager.add_documents(split_new_docs) print(“知識(shí)庫(kù)更新完成”) # 可選將新內(nèi)容也保存為Markdown文件到Obsidian目錄 for doc in new_posts: save_to_obsidian(doc) else: print(“未發(fā)現(xiàn)新內(nèi)容。”) def save_to_obsidian(document): 將文檔保存為Obsidian筆記 import os import frontmatter import yaml vault_path “./knowledge_vault” title document[“metadata”].get(“title”, “Untitled”) # 生成安全的文件名 safe_title “”.join([c for c in title if c.isalnum() or c in (‘ ‘, ‘-’, ‘_’)]).rstrip() filename f”{safe_title}.md” filepath os.path.join(vault_path, “Inbox”, filename) # 放到Inbox文件夾便于整理 # 使用frontmatter添加元數(shù)據(jù) post frontmatter.Post( document[“page_content”], **document[“metadata”] ) with open(filepath, ‘w’, encoding‘utf-8’) as f: f.write(frontmatter.dumps(post)) print(f“Saved to Obsidian: {filepath}”) if __name__ “__main__”: update_knowledge_base()4.3 創(chuàng)建簡(jiǎn)易交互界面為了方便使用我們可以創(chuàng)建一個(gè)簡(jiǎn)單的命令行或Web界面。這里使用Gradio快速搭建一個(gè)Web UI。創(chuàng)建app/main.py# app/main.py import gradio as gr from scripts.rag_qa import RAGQASystem import sys import os sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # 初始化QA系統(tǒng)啟動(dòng)時(shí)加載有一定延遲 qa_system RAGQASystem(use_local_llmTrue) def answer_question(question, history): 處理用戶提問(wèn) try: response qa_system.ask(question) # 將回答添加到歷史記錄 history.append((question, response)) return history, “” # 清空輸入框 except Exception as e: return history, f“出錯(cuò)啦{str(e)}” # 使用Gradio創(chuàng)建界面 with gr.Blocks(title“LLM Brain KIT - 智能知識(shí)庫(kù)助手”) as demo: gr.Markdown(“# LLM Brain KIT 智能知識(shí)庫(kù)助手”) gr.Markdown(“基于您的個(gè)人知識(shí)庫(kù)LLM Wiki等進(jìn)行智能問(wèn)答。”) chatbot gr.Chatbot(label“對(duì)話歷史”, height500) msg gr.Textbox(label“請(qǐng)輸入您的問(wèn)題”, placeholder“例如Transformer的架構(gòu)是怎樣的”) clear gr.Button(“清空對(duì)話”) def user(user_message, history): return “”, history [[user_message, None]] def bot(history): question history[-1][0] response qa_system.ask(question) history[-1][1] response return history msg.submit(user, [msg, chatbot], [msg, chatbot], queueFalse).then( bot, chatbot, chatbot ) clear.click(lambda: None, None, chatbot, queueFalse) gr.Markdown(“---\n**說(shuō)明**回答基于您本地知識(shí)庫(kù)生成首次加載模型和向量庫(kù)可能需要一些時(shí)間。”) if __name__ “__main__”: demo.launch(server_name“0.0.0.0”, server_port7860, shareFalse)運(yùn)行python app/main.py即可在瀏覽器中打開(kāi)一個(gè)交互式問(wèn)答界面。5. 常見(jiàn)問(wèn)題與排查思路在搭建和使用過(guò)程中你可能會(huì)遇到以下問(wèn)題問(wèn)題現(xiàn)象可能原因排查與解決思路運(yùn)行腳本時(shí)提示缺少模塊依賴未安裝或虛擬環(huán)境未激活。1. 確認(rèn)已激活虛擬環(huán)境。2. 運(yùn)行pip install -r requirements.txt安裝所有依賴。向量搜索返回?zé)o關(guān)內(nèi)容1. 嵌入模型不匹配。2. 文本分塊不合理過(guò)大或過(guò)小。3. 向量數(shù)據(jù)庫(kù)相似度度量方式不合適。1. 確保創(chuàng)建和查詢時(shí)使用相同的嵌入模型。2. 調(diào)整chunk_size和chunk_overlap參數(shù)如500/100。3. 嘗試更換嵌入模型如從BAAI/bge-small-zh換為text-embedding-ada-002。4. 在Chroma中嘗試不同的距離函數(shù)cosine,l2,ip。LLM回答質(zhì)量差或胡言亂語(yǔ)1. 檢索到的上下文不相關(guān)。2. LLM本身能力不足或提示詞不佳。3. 上下文長(zhǎng)度超出模型限制。1. 先檢查上一條“搜索無(wú)關(guān)”的問(wèn)題。2. 在RAG鏈中使用chain_type“map_reduce”或“refine”處理長(zhǎng)文檔。3. 優(yōu)化提示詞在RetrievalQA中通過(guò)chain_type_kwargs傳入自定義提示。4. 考慮升級(jí)LLM如從7B模型升級(jí)到70B或使用GPT-4。Ollama本地模型無(wú)法連接Ollama服務(wù)未啟動(dòng)或模型未拉取。1. 在終端運(yùn)行ollama serve啟動(dòng)服務(wù)。2. 運(yùn)行ollama pull llama3:8b拉取模型。3. 在代碼中檢查Ollama的API地址默認(rèn)http://localhost:11434。知識(shí)庫(kù)更新后問(wèn)答未生效向量數(shù)據(jù)庫(kù)未持久化或未重新加載。1. 確保VectorStoreManager.add_documents被正確調(diào)用。2. 檢查向量數(shù)據(jù)庫(kù)的持久化路徑是否正確。3. 重啟你的問(wèn)答應(yīng)用以加載新的向量庫(kù)數(shù)據(jù)。Gradio界面無(wú)法打開(kāi)端口被占用或防火墻阻止。1. 更改demo.launch(server_port7861)中的端口號(hào)。2. 檢查本地防火墻設(shè)置。3. 確保在正確的網(wǎng)絡(luò)環(huán)境下運(yùn)行server_name“0.0.0.0”允許局域網(wǎng)訪問(wèn)。6. 最佳實(shí)踐與工程建議要讓你的“Brain KIT”真正產(chǎn)生復(fù)利而不僅僅是一個(gè)玩具項(xiàng)目需要遵循一些工程最佳實(shí)踐。6.1 知識(shí)管理規(guī)范統(tǒng)一文件格式堅(jiān)持使用Markdown。它純文本、易版本管理、被廣泛支持。建立筆記模板在Obsidian中為不同類型的知識(shí)如論文筆記、概念解析、代碼示例創(chuàng)建模板包含固定的元數(shù)據(jù)字段如tags、author、date、status。善用雙向鏈接在筆記中積極鏈接相關(guān)概念。例如在“注意力機(jī)制”筆記中鏈接到“Transformer”筆記。這不僅能強(qiáng)化記憶未來(lái)也能被圖分析工具利用。定期回顧與清理設(shè)定“知識(shí)維護(hù)日”回顧近期添加的筆記建立更深的鏈接歸檔或刪除過(guò)時(shí)內(nèi)容。6.2 技術(shù)架構(gòu)優(yōu)化分層存儲(chǔ)策略熱數(shù)據(jù)近期高頻訪問(wèn)的知識(shí)存儲(chǔ)在內(nèi)存或SSD上的向量庫(kù)中保證檢索速度。溫?cái)?shù)據(jù)歷史知識(shí)存儲(chǔ)在向量庫(kù)中但可能使用更經(jīng)濟(jì)的存儲(chǔ)介質(zhì)。冷數(shù)據(jù)原始Markdown文件用Git管理提供版本歷史和完整上下文。混合檢索結(jié)合語(yǔ)義搜索向量檢索和關(guān)鍵詞搜索如BM25。語(yǔ)義搜索擅長(zhǎng)理解意圖關(guān)鍵詞搜索擅長(zhǎng)精確匹配術(shù)語(yǔ)。LangChain的EnsembleRetriever可以輕松實(shí)現(xiàn)。元數(shù)據(jù)過(guò)濾在檢索時(shí)利用元數(shù)據(jù)如source、type、date進(jìn)行過(guò)濾。例如當(dāng)詢問(wèn)“最新的LLM技術(shù)”時(shí)可以優(yōu)先檢索date較近的文檔。查詢重寫(xiě)與擴(kuò)展在用戶提問(wèn)后、檢索前使用一個(gè)小型LLM對(duì)查詢進(jìn)行重寫(xiě)或擴(kuò)展以提高召回率。例如將“怎么訓(xùn)練GPT”擴(kuò)展為“如何訓(xùn)練GPT模型GPT模型的訓(xùn)練步驟、訓(xùn)練數(shù)據(jù)、計(jì)算資源需求。”6.3 自動(dòng)化與智能體定時(shí)抓取使用cronLinux/macOS或Task SchedulerWindows定時(shí)運(yùn)行你的web_crawler.py腳本實(shí)現(xiàn)知識(shí)庫(kù)的自動(dòng)更新。構(gòu)建知識(shí)消化Agent設(shè)計(jì)一個(gè)更復(fù)雜的Agent讓它不僅能抓取文章還能自動(dòng)總結(jié)長(zhǎng)文。提取關(guān)鍵實(shí)體和概念。根據(jù)內(nèi)容自動(dòng)打上標(biāo)簽。建議與現(xiàn)有筆記的鏈接。建立反饋循環(huán)在問(wèn)答界面添加“答案是否有用”的反饋按鈕。將用戶反饋特別是負(fù)面反饋記錄下來(lái)用于優(yōu)化檢索策略或提示詞。6.4 安全與隱私敏感信息處理如果你的知識(shí)庫(kù)包含公司內(nèi)部或個(gè)人敏感信息務(wù)必使用本地部署的嵌入模型和LLM如Llama 3、ChatGLM、BGE。避免使用需要上傳數(shù)據(jù)到第三方API的服務(wù)。數(shù)據(jù)備份定期備份你的knowledge_vault目錄和chroma_db目錄。可以考慮將整個(gè)項(xiàng)目目錄用Git管理并推送到私有Git倉(cāng)庫(kù)。訪問(wèn)控制如果你將Web界面部署到公網(wǎng)必須設(shè)置身份驗(yàn)證如Gradio的auth參數(shù)防止未授權(quán)訪問(wèn)。通過(guò)將Karpathy的LLM Wiki作為高質(zhì)量種子并運(yùn)用上述工具和方法論你構(gòu)建的不僅僅是一個(gè)知識(shí)庫(kù)而是一個(gè)能夠持續(xù)學(xué)習(xí)、進(jìn)化并與你共同成長(zhǎng)的“第二大腦”。這個(gè)系統(tǒng)會(huì)隨著你的使用和喂養(yǎng)變得越來(lái)越了解你的領(lǐng)域和思維習(xí)慣最終成為你學(xué)習(xí)和工作中不可替代的伙伴。