基于腾讯云轻量服务器与RAG技术构建低成本私有知识库AI助手
1. 项目缘起:为什么选择“轻量服务器+RAG”这个组合?
最近两年,AI应用开发的门槛肉眼可见地降低了。以前想做个能“懂你”的智能问答助手,要么得养一个庞大的算法团队,要么就得忍受公有云API高昂的调用成本和数据隐私的顾虑。现在,随着大语言模型(LLM)的开源化和RAG(检索增强生成)技术的成熟,个人开发者或小团队完全有能力在可控的成本下,搭建一个专属的、高质量的AI知识库助手。
我选择“腾讯云轻量服务器 + RAG方案”这个组合,核心驱动力就三个字:性价比。这里的性价比,不只是指金钱成本,更是时间成本、运维复杂度和最终效果的平衡。
首先看硬件基础——腾讯云轻量应用服务器。对于个人项目或初创团队来说,它有几个难以拒绝的优点:一是开箱即用,预装了应用镜像(比如Docker、WordPress),省去了从零配置操作系统的麻烦;二是价格亲民,入门配置(2核4G)每月几十块钱,还自带流量包,对于访问量不大的知识库应用完全够用;三是网络优化,国内访问速度稳定,这对于需要实时响应的问答应用至关重要。你不需要一开始就为可能不存在的百万级并发去购买高配ECS,轻量服务器提供了一个完美的“试验田”和“起步器”。
然后是技术核心——RAG方案。简单来说,RAG解决了大模型的两个核心痛点:“幻觉”(胡编乱造)和“知识陈旧”。它通过将你的私有知识库(文档、笔记、手册)转换成向量并存储,在用户提问时,先从这个“记忆库”里检索出最相关的片段,再把这些片段连同问题一起交给大模型生成答案。这样,答案的准确性和专业性就有了保障。更重要的是,整个流程——文档处理、向量化、检索、生成——现在都有成熟的开源框架(比如LangChain、LlamaIndex)和工具(比如Chroma、Qdrant)来实现,技术栈非常清晰。
所以,这个组合的本质是:用最轻量、易得的云资源,搭载一套经过验证的、能落地的AI应用架构。它让你能把精力集中在“如何用好我的知识”这个核心问题上,而不是纠缠于基础设施的泥潭。接下来,我就带你一步步拆解,如何从零开始,把这个组合跑起来。
2. 核心组件选型与架构设计:不只是“跑起来”,更要“跑得稳”
在动手敲命令之前,花点时间设计架构是绝对值得的。一个好的架构能让你后续的开发、调试、扩展事半功倍。我们的目标是在轻量服务器上构建一个稳定、可维护的RAG系统。下面是我经过多次实践后总结出的组件选型与架构思路。
2.1 服务器环境与基础服务
我们以一台腾讯云轻量应用服务器(2核4G,Ubuntu 22.04 LTS)为例。这个配置足以支撑一个小型知识库的日常运行。
- 操作系统:选择Ubuntu LTS版本,社区支持好,软件包丰富。
- 容器化:Docker + Docker Compose是必选项。它能把复杂的依赖环境(Python版本、各种库)打包隔离,保证环境一致性,也极大简化了部署流程。腾讯云轻量服务器很多镜像已经预装了Docker,如果没有,安装也非常简单。
- 向量数据库:这是RAG的“记忆中枢”。我们需要一个轻量、高效、易于集成的向量数据库。经过对比,我推荐PGVector(PostgreSQL的向量扩展)或Qdrant。
- PGVector:优势是与成熟的关系型数据库PostgreSQL无缝集成,可以利用其事务、备份等成熟特性,管理起来更顺手。如果你的知识库还需要一些结构化查询(比如按文档类别过滤),PGVector是很好的选择。
- Qdrant:专为向量搜索设计的数据库,纯内存或磁盘存储都支持,性能非常出色,API简洁。对于纯向量检索场景,它更轻快。
- 考虑到轻量服务器的资源和我们的入门目标,我优先推荐PGVector。因为它可以和后续的Web应用共用数据库实例,减少组件数量。Docker部署一个带PGVector的PostgreSQL就是一条命令的事。
- 大语言模型(LLM):这是“大脑”。有两种选择:
- 调用云端API:如OpenAI的GPT、国内深度求索的DeepSeek等。优点是模型能力强、省事,但会产生持续费用,且有网络延迟和数据出境风险(需注意合规)。
- 本地部署开源模型:如ChatGLM3、Qwen、Llama等通过Ollama或vLLM部署。优点是数据完全私有、无网络延迟,但对服务器算力有要求(2核4G跑7B参数模型勉强可行,但响应慢)。
- 建议:在项目初期,为了快速验证和降低成本,可以先使用云端API。等流程跑通、确有需求后,再考虑升级服务器配置来本地部署轻量化模型。本文将以使用DeepSeek的API为例进行说明,因为它对国内开发者友好,价格也实惠。
2.2 RAG流程与框架选择
一个标准的RAG流程包括:文档加载 -> 文本分割 -> 向量化(嵌入) -> 存储 -> 检索 -> 提示构建 -> 生成回答。
我们需要一个框架来编排这些步骤。主流选择是LangChain或LlamaIndex。
- LangChain:功能极其强大,模块化程度高,几乎可以构建任何AI应用链。但学习曲线稍陡,概念较多。
- LlamaIndex:专为RAG场景设计,API更简洁直观,对数据连接器和检索器做了很多优化,上手更快。
对于我们的“低成本知识库助手”目标,LlamaIndex是更优的选择。它能让我们的代码更清晰,更快地看到效果。我们将使用LlamaIndex来连接我们的文档、向量数据库和LLM。
2.3 最终架构图(逻辑层面)
整个系统的逻辑架构如下,我们将在服务器上通过Docker Compose来编排这些服务:
用户 Web/API 请求 | v [Nginx / Python Web框架 (如FastAPI)] # 对外接口 | v [核心应用服务 (Python + LlamaIndex)] # 处理RAG流程 | \ | \ v v [向量数据库 (PGVector)] [大模型 API (如DeepSeek)] | / | / v / [原始文档存储 (本地目录或OSS)] <--(文档读取与处理)简单解释一下数据流:
- 用户通过网页或API提问。
- Web服务(如FastAPI)接收到问题,调用核心的RAG应用服务。
- RAG应用使用LlamaIndex,先将用户问题转换成向量。
- 用这个向量去PGVector数据库中检索出最相关的几段文本(知识片段)。
- 将问题和检索到的知识片段组合成一个详细的提示(Prompt),发送给DeepSeek API。
- 将DeepSeek返回的答案通过Web服务返回给用户。
文档入库流程则是离线进行的:将PDF、Word、TXT等文档放入指定目录,运行一个脚本,LlamaIndex会负责读取、分割、向量化并存入PGVector。
这个架构清晰地将计算密集型任务(文档处理、向量化)与实时服务(问答)解耦,非常适合在资源有限的服务器上稳定运行。
3. 实战部署:一步步在轻量服务器上搭建系统
理论说完了,我们进入最实在的实操环节。请确保你有一台全新的腾讯云轻量Ubuntu服务器,并已通过SSH登录。
3.1 基础环境准备与Docker部署
首先,更新系统并安装必要的工具。
# 更新软件包列表 sudo apt-get update && sudo apt-get upgrade -y # 安装常用工具(可选但推荐) sudo apt-get install -y git curl wget vim # 安装 Docker(如果镜像未预装) # 具体安装命令请参考腾讯云官方文档或Docker官网,通常是一段curl脚本。 # 假设已经安装好Docker和Docker Compose。接下来,我们创建项目目录,并编写docker-compose.yml文件来启动最核心的向量数据库。
# 创建项目目录 mkdir ~/rag-knowledge-base && cd ~/rag-knowledge-base mkdir data docs scripts # 创建数据、文档和脚本目录 # 创建 docker-compose.yml vim docker-compose.yml将以下内容写入docker-compose.yml。这里我们启动一个带有PGVector扩展的PostgreSQL数据库,并挂载数据卷到本地,防止容器重启后数据丢失。
version: '3.8' services: postgres: image: ankane/pgvector:latest # 这个镜像已经包含了pgvector扩展 container_name: rag-pgvector restart: unless-stopped environment: POSTGRES_USER: rag_user POSTGRES_PASSWORD: your_secure_password_here # 务必修改为强密码! POSTGRES_DB: rag_db ports: - "5432:5432" # 将主机5432端口映射到容器,方便本地调试连接 volumes: - ./data/postgres:/var/lib/postgresql/data # 持久化数据 healthcheck: test: ["CMD-SHELL", "pg_isready -U rag_user -d rag_db"] interval: 10s timeout: 5s retries: 5保存文件后,启动服务:
docker-compose up -d使用docker ps命令检查容器是否正常运行。现在,你的向量数据库就已经在后台运行了。
3.2 Python环境与依赖安装
我们将在宿主机上(而非容器内)开发Python应用,这样调试更方便。当然,你也可以选择将应用也容器化,这里我们先采用宿主机模式。
# 进入项目目录 cd ~/rag-knowledge-base # 创建Python虚拟环境(推荐使用Python 3.9+) python3 -m venv venv source venv/bin/activate # 升级pip pip install --upgrade pip # 安装核心依赖 pip install llama-index llama-index-vector-stores-postgres llama-index-llms-openai # 解释: # llama-index: 核心框架 # llama-index-vector-stores-postgres: 用于连接PGVector # llama-index-llms-openai: 虽然叫openai,但其接口兼容所有遵循OpenAI API格式的模型,包括DeepSeek # 安装文档读取器(按需安装) pip install llama-index-readers-file pymupdf # 用于读取PDF pip install python-docx # 用于读取Word pip install unstructured # 强大的非结构化文本提取库 # 安装Web框架(用于提供API) pip install fastapi uvicorn python-multipart3.3 构建知识库:文档处理与向量入库
这是构建智能助手的基础。我们在scripts目录下创建一个名为ingest.py的脚本。
# ~/rag-knowledge-base/scripts/ingest.py import os import sys sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, StorageContext from llama_index.core.node_parser import SentenceSplitter from llama_index.vector_stores.postgres import PGVectorStore from llama_index.embeddings.openai import OpenAIEmbedding import psycopg2 from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT # 1. 配置连接参数(请根据你的docker-compose配置修改) db_name = "rag_db" user = "rag_user" password = "your_secure_password_here" # 修改为你的密码 host = "localhost" port = "5432" # 2. 确保数据库和扩展存在(首次运行) conn = psycopg2.connect(dbname="postgres", user=user, password=password, host=host, port=port) conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) cur = conn.cursor() cur.execute(f"SELECT 1 FROM pg_database WHERE datname = '{db_name}';") if not cur.fetchone(): cur.execute(f"CREATE DATABASE {db_name};") print(f"Database {db_name} created.") cur.close() conn.close() # 连接到目标数据库,创建pgvector扩展 conn = psycopg2.connect(dbname=db_name, user=user, password=password, host=host, port=port) conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) cur = conn.cursor() cur.execute("CREATE EXTENSION IF NOT EXISTS vector;") cur.close() conn.close() # 3. 初始化向量存储和嵌入模型 vector_store = PGVectorStore.from_params( database=db_name, host=host, password=password, port=port, user=user, table_name="llama_index_vectors", # 存储向量的表名 embed_dim=1536, # OpenAI text-embedding-ada-002 的维度,DeepSeek Embedding也兼容 ) # 注意:这里使用OpenAIEmbedding,但我们会配置其base_url指向DeepSeek embed_model = OpenAIEmbedding( api_key="your_deepseek_api_key_here", # 替换为你的DeepSeek API Key api_base="https://api.deepseek.com/v1", # DeepSeek的API端点 model="text-embedding-3-small", # DeepSeek当前支持的嵌入模型,请查阅其最新文档 ) # 4. 读取文档 documents_path = os.path.join(os.path.dirname(__file__), "../docs") documents = SimpleDirectoryReader(documents_path).load_data() print(f"Loaded {len(documents)} documents.") # 5. 分割文本(将长文档切成小块,便于检索) node_parser = SentenceSplitter(chunk_size=512, chunk_overlap=50) nodes = node_parser.get_nodes_from_documents(documents) # 6. 构建索引并存储 storage_context = StorageContext.from_defaults(vector_store=vector_store) index = VectorStoreIndex( nodes=nodes, storage_context=storage_context, embed_model=embed_model, ) print("Knowledge base indexing completed!")关键点说明与实操心得:
- 嵌入模型(Embedding Model):这是将文本转换成向量的模型,其质量直接决定检索的准确性。我们使用了DeepSeek的Embedding API,需要在其平台申请API Key。
embed_dim=1536是text-embedding-ada-002的标准维度,DeepSeek的模型与之兼容。务必查阅DeepSeek最新文档确认模型名。 - 文本分割(Chunking):
chunk_size=512和chunk_overlap=50是常用参数。chunk_size太小会丢失上下文,太大会引入噪声。chunk_overlap可以避免在句子中间切断语义。你需要根据自己文档的特点(如技术文档句子长,问答记录句子短)进行调整。 - 运行脚本前:将你的知识文档(PDF、TXT等)放入
~/rag-knowledge-base/docs/目录。然后运行:
你会看到加载和处理的日志。完成后,你的知识就已经以向量的形式存入PGVector数据库了。cd ~/rag-knowledge-base source venv/bin/activate python scripts/ingest.py
3.4 构建问答服务:FastAPI后端与RAG查询链
现在,我们来创建提供问答服务的API。在项目根目录创建app.py。
# ~/rag-knowledge-base/app.py from fastapi import FastAPI, HTTPException from pydantic import BaseModel from typing import List, Optional import os from llama_index.core import VectorStoreIndex, Settings from llama_index.core.retrievers import VectorIndexRetriever from llama_index.core.query_engine import RetrieverQueryEngine from llama_index.core.postprocessor import SimilarityPostprocessor from llama_index.llms.openai import OpenAI from llama_index.embeddings.openai import OpenAIEmbedding from llama_index.vector_stores.postgres import PGVectorStore # 配置LLM和Embedding(同样指向DeepSeek) Settings.llm = OpenAI( api_key="your_deepseek_api_key_here", # 替换 api_base="https://api.deepseek.com/v1", model="deepseek-chat", # DeepSeek的聊天模型 temperature=0.1, # 较低的温度使输出更确定,适合知识问答 ) Settings.embed_model = OpenAIEmbedding( api_key="your_deepseek_api_key_here", # 替换 api_base="https://api.deepseek.com/v1", model="text-embedding-3-small", ) # 初始化向量存储连接 vector_store = PGVectorStore.from_params( database="rag_db", host="localhost", password="your_secure_password_here", # 替换 port="5432", user="rag_user", table_name="llama_index_vectors", ) # 从已有的向量存储加载索引 index = VectorStoreIndex.from_vector_store(vector_store=vector_store) # 配置检索器:从索引中取出前k个最相关的片段 retriever = VectorIndexRetriever( index=index, similarity_top_k=5, # 每次检索5个最相关的文本块 ) # 配置后处理器:可以按相似度分数过滤,这里我们简单设置一个阈值 postprocessor = SimilarityPostprocessor(similarity_cutoff=0.7) # 相似度低于0.7的结果将被过滤 # 组装查询引擎 query_engine = RetrieverQueryEngine( retriever=retriever, node_postprocessors=[postprocessor], ) app = FastAPI(title="RAG Knowledge Base QA API") class QueryRequest(BaseModel): question: str stream: Optional[bool] = False # 是否启用流式输出(可选功能) class QueryResponse(BaseModel): answer: str source_nodes: List[dict] # 可以返回答案的来源片段,增加可信度 @app.post("/query", response_model=QueryResponse) async def query_knowledge_base(request: QueryRequest): """ 核心问答接口。 """ try: # 使用查询引擎获取答案 response = query_engine.query(request.question) # 整理响应,包含答案和来源 source_info = [] for node in response.source_nodes: source_info.append({ "text": node.node.get_content()[:200], # 截取部分文本 "score": node.score, # 相似度分数 # 可以添加更多元数据,如文件名、页码等 }) return QueryResponse( answer=response.response, source_nodes=source_info ) except Exception as e: raise HTTPException(status_code=500, detail=f"Query failed: {str(e)}") @app.get("/health") async def health_check(): return {"status": "healthy"} if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)关键点说明与实操心得:
similarity_top_k:这个参数控制每次检索返回多少个相关片段。太少可能信息不足,太多可能引入无关噪声并增加API调用成本(因为提示词会变长)。从3-5开始调整。similarity_cutoff:这是一个重要的质量阀门。如果检索到的片段与问题相似度太低(比如低于0.7),很可能是无关信息,让大模型基于这些信息生成答案会导致“幻觉”。设置一个阈值可以过滤掉低质量检索结果。- 流式输出:代码中预留了
stream参数。对于需要长时间生成的答案,流式输出能极大提升用户体验。LlamaIndex和FastAPI都支持流式响应,实现稍复杂,但值得探索。 - 来源追溯:返回
source_nodes至关重要。它让用户知道答案是从哪段原文来的,增加了系统的可信度和可解释性,这在企业应用中几乎是刚需。
启动API服务:
cd ~/rag-knowledge-base source venv/bin/activate python app.py服务将在http://你的服务器IP:8000启动。你可以访问http://你的服务器IP:8000/docs查看自动生成的API文档并进行测试。
3.5 前端界面(可选但推荐):一个简单的聊天界面
为了让体验更完整,我们可以用一个简单的HTML页面作为前端。在根目录创建static文件夹,并新建index.html。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>我的知识库AI助手</title> <style> body { font-family: sans-serif; max-width: 800px; margin: 20px auto; padding: 20px; } #chatbox { border: 1px solid #ccc; height: 400px; overflow-y: auto; padding: 10px; margin-bottom: 10px; } .message { margin-bottom: 10px; } .user { text-align: right; color: blue; } .bot { text-align: left; color: green; } .source { font-size: 0.8em; color: #666; border-left: 3px solid #eee; padding-left: 5px; margin-top: 5px; } #inputArea { display: flex; } #questionInput { flex-grow: 1; padding: 10px; } #sendBtn { padding: 10px 20px; } </style> </head> <body> <h2>📚 知识库AI问答助手</h2> <div id="chatbox"></div> <div id="inputArea"> <input type="text" id="questionInput" placeholder="请输入您的问题..."> <button id="sendBtn">发送</button> </div> <script> const chatbox = document.getElementById('chatbox'); const input = document.getElementById('questionInput'); const sendBtn = document.getElementById('sendBtn'); const apiBase = 'http://localhost:8000'; // 部署时改为你的服务器IP function addMessage(sender, text, sources = []) { const msgDiv = document.createElement('div'); msgDiv.className = `message ${sender}`; msgDiv.innerHTML = `<strong>${sender === 'user' ? '您' : '助手'}:</strong> ${text}`; if (sources && sources.length > 0) { const sourceDiv = document.createElement('div'); sourceDiv.className = 'source'; sourceDiv.innerHTML = '<strong>参考来源:</strong><br>' + sources.map(s => `· ${s.text}... (相关度: ${s.score.toFixed(3)})`).join('<br>'); msgDiv.appendChild(sourceDiv); } chatbox.appendChild(msgDiv); chatbox.scrollTop = chatbox.scrollHeight; } async function sendQuestion() { const question = input.value.trim(); if (!question) return; addMessage('user', question); input.value = ''; sendBtn.disabled = true; try { const response = await fetch(`${apiBase}/query`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ question: question, stream: false }) }); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const data = await response.json(); addMessage('bot', data.answer, data.source_nodes); } catch (error) { console.error('Error:', error); addMessage('bot', `抱歉,出错了: ${error.message}`); } finally { sendBtn.disabled = false; input.focus(); } } sendBtn.addEventListener('click', sendQuestion); input.addEventListener('keypress', (e) => { if (e.key === 'Enter') sendQuestion(); }); </script> </body> </html>为了让FastAPI能提供这个静态页面,我们需要修改一下app.py,添加静态文件服务。
# 在 app.py 的 FastAPI 实例化后添加 from fastapi.staticfiles import StaticFiles app.mount("/static", StaticFiles(directory="static"), name="static") # 添加一个根路径路由,返回前端页面 from fastapi.responses import FileResponse @app.get("/") async def read_index(): return FileResponse("static/index.html")现在,重启app.py,访问http://你的服务器IP:8000,就能看到一个简单的聊天界面,可以和你的知识库对话了。
4. 优化、监控与成本控制:让系统真正可用
系统跑起来只是第一步,要让它稳定、可靠、成本可控,还需要做一些优化和运维工作。
4.1 性能与效果优化
检索优化:
- 混合检索(Hybrid Search):除了向量相似度检索,可以结合关键词(BM25)检索。有些问题用关键词匹配更准。LlamaIndex支持很容易地集成混合检索器。
- 重排序(Re-ranking):先用向量检索出Top K(比如20个)结果,再用一个更精细但更慢的“重排序模型”对这20个结果排序,选出最相关的Top N(比如5个)给大模型。这能显著提升精度。可以试试开源的
bge-reranker模型。 - 元数据过滤:在存储向量时,为每个文本块附加元数据(如文档标题、章节、日期)。检索时,可以先根据元数据过滤(如“只搜索2023年后的产品手册”),再进行向量搜索,能极大提升准确率和效率。
提示工程(Prompt Engineering):
- 默认的提示可能不够好。你可以自定义查询引擎的提示模板,明确指示模型“基于以下上下文回答问题,如果上下文不包含答案,就说不知道”。
from llama_index.core import PromptTemplate qa_prompt_tmpl = ( “上下文信息如下:\n” “---------------------\n” “{context_str}\n” “---------------------\n” “请严格基于上述上下文(不依赖外部知识)回答以下问题:\n” “问题:{query_str}\n” “答案:” ) qa_prompt = PromptTemplate(qa_prompt_tmpl) # 然后在创建query_engine时指定- 在提示词中要求模型以特定格式(如Markdown列表、表格)回答,可以使输出更结构化。
缓存:对于常见问题,答案可以缓存起来,避免重复进行向量检索和LLM调用,大幅降低延迟和成本。可以使用
Redis或简单的内存缓存(如cachetools)。
4.2 系统监控与日志
一个看不见的系统是危险的。你需要知道它是否健康,用户问了什么,回答得怎么样。
- 应用日志:使用Python的
logging模块,将关键步骤(收到请求、检索结果、调用LLM、返回答案)以及错误信息记录到文件。可以按天切割日志文件。 - 关键指标:
- 响应时间:从收到问题到返回答案的总耗时。拆解为检索时间、LLM生成时间。
- Token消耗:每次问答消耗的输入和输出Token数,这是成本的核心。
- 缓存命中率:如果引入了缓存。
- 错误率:API调用失败的比例。
- 简单监控:可以写一个脚本,定期调用
/health接口,或者检查关键进程(如Python app, PostgreSQL)是否存活。更正式一点,可以集成Prometheus和Grafana。
4.3 成本控制精打细算
在轻量服务器上,成本主要来自两块:云服务器本身和大模型API调用。
服务器成本:腾讯云轻量服务器是包月/包年付费。2核4G配置对于初期完全足够。主要关注流量,如果知识库对外公开,需注意流量超额费用。可以通过Nginx配置压缩、浏览器缓存来节省流量。
API调用成本(大头):
- 嵌入成本:文档入库时的一次性向量化,以及用户每次提问时问题的向量化。这部分成本相对固定且较低。
- LLM生成成本:这是变动成本,与问答频率和答案长度正相关。控制策略如下:
- 优化检索:检索越精准,提供给LLM的上下文就越短、越相关,消耗的输入Token就越少,生成无关内容的风险也越低。
- 设置回答长度限制:在调用LLM API时设置
max_tokens参数。 - 实施限流:在FastAPI层面,对
/query接口进行限流(例如每分钟每个IP 10次),防止恶意调用。 - 使用更经济的模型:在效果可接受的前提下,选择输入输出单价更低的模型。DeepSeek的定价就非常有竞争力。
- 异步处理与队列:对于非实时性要求高的场景(如批量生成文档摘要),可以将任务放入队列(如
Celery+Redis),在服务器闲时处理。
4.4 安全与权限考虑
- API密钥管理:绝对不要将API密钥硬编码在代码中!使用环境变量。
在代码中通过# 在启动应用前设置环境变量 export DEEPSEEK_API_KEY="your_key_here"os.getenv(“DEEPSEEK_API_KEY”)读取。 - 数据库密码:同样使用环境变量或Docker secrets管理。
- API访问控制:如果你的知识库是私有的,需要为FastAPI接口添加认证(如API Token、JWT)。可以使用
FastAPI的依赖注入系统轻松实现。 - 输入输出过滤:对用户输入的问题进行基本的清洗和过滤,防止Prompt注入攻击。对模型输出也可以进行敏感词过滤。
走到这一步,你已经拥有了一个功能完整、架构清晰、且具备一定优化和运维考虑的个人知识库AI助手。它运行在你的腾讯云轻量服务器上,数据私有,成本可控。你可以随时往docs文件夹里添加新文档,然后重新运行ingest.py脚本更新知识库。随着需求的增长,你可以沿着本文提到的优化方向持续迭代,例如引入更复杂的检索策略、搭建监控面板、或者将整个应用Docker化以实现一键部署。这个项目就像一个乐高底座,为你探索更广阔的AIGC应用世界提供了坚实而灵活的起点。