news 2026/4/5 14:58:00

极简LLM入门指南5

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
极简LLM入门指南5

【LLM实操系列05】RAG实战:知识库问答系统从0到生产

在开始之前,建议先完成第03篇(API调用)和第04篇(Prompt技巧)的学习。你需要理解Embedding(文本向量化)的基本原理,并安装langchain、chromadb等依赖。

10分钟实现最简RAG

什么是RAG?

检索增强生成 = 搜索相关文档 + 结合文档回答问题

Embedding是什么?

Embedding将文本转换为高维向量表示。语义相似的文本会有相似的向量,这使得我们可以用它来计算文本相似度和进行语义搜索。

最小可运行代码

# pip install langchain chromadb openai tiktokenfromlangchain.embeddingsimportOpenAIEmbeddingsfromlangchain.vectorstoresimportChromafromlangchain.chat_modelsimportChatOpenAIfromlangchain.chainsimportRetrievalQA# 1. 准备文档docs=["Python是1991年发布的编程语言","JavaScript主要用于网页开发","Rust注重内存安全和性能"]# 2. 创建向量库embeddings=OpenAIEmbeddings()vectordb=Chroma.from_texts(docs,embeddings)# 3. 创建RAG链llm=ChatOpenAI(temperature=0)qa=RetrievalQA.from_chain_type(llm=llm,retriever=vectordb.as_retriever())# 4. 提问answer=qa.run("Python是什么时候发布的?")print(answer)# 输出:Python是1991年发布的

生产级RAG架构

完整实现

importosfromtypingimportList,Dict,Anyimportnumpyasnpfromdataclassesimportdataclass@dataclassclassDocument:"""文档数据结构"""content:strmetadata:Dict[str,Any]embedding:np.ndarray=NoneclassProductionRAG:"""生产环境RAG系统"""def__init__(self,embedding_model="text-embedding-ada-002",llm_model="gpt-3.5-turbo",vector_db="chroma"):# 初始化组件self.embeddings=OpenAIEmbeddings(model=embedding_model)self.llm=ChatOpenAI(model=llm_model,temperature=0)# 向量数据库ifvector_db=="chroma":self.vectordb=Chroma(persist_directory="./chroma_db",embedding_function=self.embeddings)elifvector_db=="faiss":fromlangchain.vectorstoresimportFAISS self.vectordb=FAISS.load_local("./faiss_index",self.embeddings)# 文档处理器self.text_splitter=self._init_splitter()def_init_splitter(self):"""智能文档分块"""fromlangchain.text_splitterimportRecursiveCharacterTextSplitterreturnRecursiveCharacterTextSplitter(chunk_size=500,# 块大小chunk_overlap=100,# 重叠separators=["\n\n",# 段落"\n",# 行"。",# 句号"!",# 感叹号"?",# 问号";",# 分号",",# 逗号" "# 空格])defadd_documents(self,file_paths:List[str]):"""批量添加文档"""fromlangchain.document_loadersimport(PDFLoader,TextLoader,UnstructuredWordDocumentLoader,CSVLoader)loaders={'.pdf':PDFLoader,'.txt':TextLoader,'.docx':UnstructuredWordDocumentLoader,'.csv':CSVLoader}all_docs=[]forpathinfile_paths:ext=os.path.splitext(path)[1].lower()loader_class=loaders.get(ext,TextLoader)loader=loader_class(path)# 加载并分块docs=loader.load()splits=self.text_splitter.split_documents(docs)all_docs.extend(splits)# 添加到向量库self.vectordb.add_documents(all_docs)print(f"已添加{len(all_docs)}个文档块")defsearch(self,query:str,k=3,use_rerank=True):"""增强搜索"""# 1. 初步检索docs=self.vectordb.similarity_search(query,k=k*2ifuse_rerankelsek)# 2. 重排序(可选)ifuse_rerank:docs=self._rerank(query,docs,top_k=k)returndocsdef_rerank(self,query:str,docs:List,top_k:int):"""使用CrossEncoder重排序"""fromsentence_transformersimportCrossEncoder# 加载重排序模型(首次会下载)reranker=CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')# 计算相关性分数pairs=[[query,doc.page_content]fordocindocs]scores=reranker.predict(pairs)# 按分数排序doc_scores=list(zip(docs,scores))doc_scores.sort(key=lambdax:x[1],reverse=True)return[docfordoc,_indoc_scores[:top_k]]defquery(self,question:str,use_memory=False):"""智能问答"""# 检索相关文档docs=self.search(question)# 构建上下文context="\n\n".join([d.page_contentfordindocs])# 生成答案ifuse_memory:fromlangchain.memoryimportConversationBufferWindowMemory memory=ConversationBufferWindowMemory(k=3)fromlangchain.chainsimportConversationalRetrievalChain chain=ConversationalRetrievalChain.from_llm(llm=self.llm,retriever=self.vectordb.as_retriever(),memory=memory)response=chain({"question":question})else:# 自定义Promptprompt=f""" 基于以下信息回答问题。如果信息不足,请说"根据提供的信息无法回答"。 信息:{context}问题:{question}回答:"""response=self.llm.predict(prompt)return{"answer":response,"sources":[{"content":d.page_content,"metadata":d.metadata}fordindocs]}

向量数据库选型

对比表

数据库性能易用性成本适用场景
Chroma⭐⭐⭐⭐⭐⭐⭐⭐免费原型/小规模
FAISS⭐⭐⭐⭐⭐⭐⭐⭐免费单机高性能
Pinecone⭐⭐⭐⭐⭐⭐⭐⭐$70+/月SaaS云服务
Weaviate⭐⭐⭐⭐⭐⭐⭐⭐免费+云混合搜索
Milvus⭐⭐⭐⭐⭐⭐⭐⭐免费大规模生产

快速集成代码

# 1. Chroma(最简单)fromlangchain.vectorstoresimportChroma vectordb=Chroma.from_texts(texts,embeddings,persist_directory="./db")# 2. FAISS(最快)fromlangchain.vectorstoresimportFAISS vectordb=FAISS.from_texts(texts,embeddings)vectordb.save_local("./faiss_index")# 3. Pinecone(云服务)importpineconefromlangchain.vectorstoresimportPinecone pinecone.init(api_key="xxx",environment="us-east-1")vectordb=Pinecone.from_texts(texts,embeddings,index_name="my-index")# 4. Weaviate(混合搜索)fromlangchain.vectorstoresimportWeaviateimportweaviate client=weaviate.Client("http://localhost:8080")vectordb=Weaviate(client,index_name="Documents",text_key="content")

性能优化技巧

1. 智能分块策略

defsmart_chunking(text:str,max_tokens=500):"""基于语义的智能分块"""importtiktoken enc=tiktoken.encoding_for_model("gpt-3.5-turbo")# 按段落分割paragraphs=text.split('\n\n')chunks=[]current_chunk=[]current_tokens=0forparainparagraphs:para_tokens=len(enc.encode(para))ifcurrent_tokens+para_tokens>max_tokens:# 保存当前块ifcurrent_chunk:chunks.append('\n\n'.join(current_chunk))current_chunk=[para]current_tokens=para_tokenselse:current_chunk.append(para)current_tokens+=para_tokensifcurrent_chunk:chunks.append('\n\n'.join(current_chunk))returnchunks

2. 混合检索

classHybridSearch:"""结合关键词和语义搜索"""def__init__(self,vectordb):self.vectordb=vectordbfromrank_bm25importBM25Okapi self.bm25=Noneself.corpus=[]defindex_documents(self,documents):"""构建双索引"""# 向量索引self.vectordb.add_documents(documents)# BM25索引tokenized_corpus=[doc.page_content.split()fordocindocuments]self.bm25=BM25Okapi(tokenized_corpus)self.corpus=documentsdefsearch(self,query:str,k=5):"""混合搜索"""# 语义搜索semantic_results=self.vectordb.similarity_search(query,k=k)# 关键词搜索tokenized_query=query.split()bm25_scores=self.bm25.get_scores(tokenized_query)top_indices=np.argsort(bm25_scores)[-k:][::-1]keyword_results=[self.corpus[i]foriintop_indices]# 合并去重seen=set()final_results=[]fordocinsemantic_results+keyword_results:ifdoc.page_contentnotinseen:seen.add(doc.page_content)final_results.append(doc)iflen(final_results)>=k:breakreturnfinal_results

3. 缓存优化

fromfunctoolsimportlru_cacheimporthashlibclassCachedRAG:"""带缓存的RAG系统"""def__init__(self,rag_system):self.rag=rag_system self.cache={}@lru_cache(maxsize=1000)def_get_embedding_cached(self,text:str):"""缓存Embedding"""returnself.rag.embeddings.embed_query(text)defquery_with_cache(self,question:str):"""缓存查询结果"""# 生成查询键query_hash=hashlib.md5(question.encode()).hexdigest()# 检查缓存ifquery_hashinself.cache:print("Cache hit!")returnself.cache[query_hash]# 执行查询result=self.rag.query(question)# 保存缓存self.cache[query_hash]=resultreturnresult

实战部署

Docker部署

# docker-compose.ymlversion:'3.8'services:rag-api:build:.ports:-"8000:8000"environment:-OPENAI_API_KEY=${OPENAI_API_KEY}volumes:-./data:/app/data-./vectordb:/app/vectordbchromadb:image:chromadb/chromaports:-"8001:8000"volumes:-./chroma_data:/chroma/chroma

FastAPI服务

fromfastapiimportFastAPI,UploadFile,FilefrompydanticimportBaseModelimportuvicorn app=FastAPI()rag_system=ProductionRAG()classQuery(BaseModel):question:strk:int=3@app.post("/upload")asyncdefupload_document(file:UploadFile=File(...)):"""上传文档"""# 保存文件file_path=f"./uploads/{file.filename}"withopen(file_path,"wb")asf:content=awaitfile.read()f.write(content)# 添加到RAGrag_system.add_documents([file_path])return{"message":"文档已上传并索引"}@app.post("/query")asyncdefquery(q:Query):"""查询接口"""result=rag_system.query(q.question,k=q.k)returnresult@app.get("/stats")asyncdefstats():"""系统统计"""return{"total_documents":len(rag_system.vectordb.get()['ids']),"model":"gpt-3.5-turbo","embedding_model":"text-embedding-ada-002"}if__name__=="__main__":uvicorn.run(app,host="0.0.0.0",port=8000)

常见问题解决

问题原因解决方案
回答不准确检索质量差优化分块大小,增加overlap
速度慢每次都计算embedding使用缓存,批量处理
成本高调用API频繁本地embedding模型
文档更新困难没有版本管理增加metadata,支持增量更新
答案幻觉上下文不足增加检索数量,验证答案
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/1 10:37:38

npm create vite项目集成Qwen-Image REST API调用

npm create vite项目集成Qwen-Image REST API调用 在数字内容创作日益高频的今天,设计师、运营人员甚至开发者都面临一个共同挑战:如何快速将抽象的文字描述转化为高质量的视觉图像?传统流程依赖专业工具和人工介入,周期长、成本高…

作者头像 李华
网站建设 2026/3/30 14:27:57

LobeChat对比ChatGPT:开源替代品是否真的能平替商用产品?

LobeChat 对比 ChatGPT:开源能否真正挑战商业闭源? 在生成式 AI 爆发的今天,几乎每个接触技术的人都用过 ChatGPT。它流畅的对话、强大的推理能力,甚至能写代码、改简历、编故事——仿佛一位无所不能的数字助手。但当你在企业里试…

作者头像 李华
网站建设 2026/3/25 5:46:23

离谱!程序员降薪降出新高度。。。

老铁们,听我说句大实话!现在程序员圈子里,谁还没听过AI啊?但你知道2025年,不会AI的Java工程师,真的要被淘汰了吗?薪资断层:阿里P7岗位JD明码标价「AI微服务优化经验」薪资上浮50%&am…

作者头像 李华
网站建设 2026/4/4 12:16:20

17、日期和时间管理函数详解

日期和时间管理函数详解 在数据库操作中,日期和时间的处理是非常重要的一部分。本文将详细介绍一些常用的日期和时间管理函数,包括 LAST_DAY 、 MONTHS_BETWEEN 、 NEXT_DAY 、 NEXT_DATE 以及 TRUNC 函数,帮助你更好地处理日期和时间相关的任务。 1. 获取每月的…

作者头像 李华
网站建设 2026/3/30 8:58:38

ComfyUI中文界面设置教程(含安装包下载)

ComfyUI中文界面设置与本地部署全指南 在AI生成内容(AIGC)迅速普及的今天,越来越多创作者希望摆脱“黑箱式”工具的束缚——那些只能输入提示词、点击生成、结果难以复现的传统WebUI。如果你也曾为无法精准控制图像生成流程而困扰&#xff0c…

作者头像 李华
网站建设 2026/3/21 1:58:43

29、日期管理与闪回技术在数据库中的应用

日期管理与闪回技术在数据库中的应用 1. 命名日管理 在信息系统、应用程序和网站中,显示特定日期庆祝命名日的人员名单是很有用的。可以通过网络找到特定国家的命名日列表,通常以三列形式呈现:月中的日期、月份引用和姓名列表。 1.1 表结构 创建一个名为 nameday_tab …

作者头像 李华