96SEO 2026-08-03 18:43 17
RAG是让大模型回答私有/长尾知识的主流方案:先把文档切成块向量化。收到问题时检索相关片段,连同问题一起交给 LLM 生成带引用的回答。

使用者痛点:
本项目的主要原因全部从零手写不依赖上述框架,把 RAG 的每个环节亲手搭一遍。
语料是数篇原创的 iOS 开发知识笔记,RAG 的目标就是让模型能回答这些私有知识。
flowchart LR
subgraph 离线索引
A --> B
B --> C
C --> D
end
subgraph 在线问答
Q --> E
E --> F
F --> G
G --> H
end
D -. 相似度计算 .-> F
程序分为离线索引和在线问答两条流水线。下面分别说明每个环节的作用与原理。
标注依据,实现**答案可追溯**。开发环境:
+ Python。技术选型 & 参数:
| 环节 | 选型 |
|---|---|
| LLM 生成 | DeepSeek |
| 向量化模型 | 本地 BGE bge-base-zh-v1. |
| 存储&检索 | 纯 numpy 矩阵实现 |
Libraries:
: 调用 DeepSeek API : 向量矩阵存储 & 余弦相似度计算 : 加载 BGE 模型进行向量化 : HuggingFace 模型加载库。被 sentence‑transformers 依赖 : 深度学习框架,用于 BGE 前向推理 : 从 .env 读取 API Key,避免硬编码 The first design decision in any RAG pipeline is how to split documents into manageable pieces.
flowchart TD
A --> B
B --> C
C --> D{单行超过上限?}
D -->|是| E
D -->|否| F
E --> G
F --> G
G --> H
The design focuses on two key pain points:
-
*信息完整性* – 防止一句话被截断导致语义丢失;
通过 overlap 保证边界处上下文连续。
-
*长度控制* – 避免超出 embedding 模型最大输入长度,同时保持块足够小以提高检索精度。
A simple data class captures each chunk’s metadata:
@dataclass
class Chunk:
至于text,str # 文本内容
source的观点是,str # 来自哪个文件
index的观点是。int # 文件内自增编号
五、embed:把语义变成数字
The embedding model converts each chunk into a high‑dimensional vector.
from functools import lru_cache
from sentence_transformers import SentenceTransformer
@lru_cache
def get_model -> SentenceTransformer:
return SentenceTransformer
def embed -> list]:
"""批量返回归一化后的向量"""
return get_model.encode.tolist
The @lru_cache-wrapped loader ensures heavy model is loaded only once per process – a direct response to “模型加载慢”痛点。
"normalize_embeddings=True" 把所有向量归一化为单位长度。使得后续矩阵乘直接得到余弦相似度,从而省去额外除法步骤,提高查询效率。
为什么 embedding 不用 DeepSeek?
The DeepSeek service currently only exposes chat/completion APIs and lacks an embedding endpoint. By delegating generation to DeepSeek and retrieval to a local BGE model we achieve:
-
No extra cost for remote embeddings.
-
A clear separation of concerns – generation vs retrieval.
-
Easier debugging because embeddings are fully under our control.
\endul>
六、vector_store + retrieve:检索
A lightweight pure‑numpy store replaces heavyweight vector DBs.
class VectorStore:
def __init__:
self.vectors = np.empty。dtype=np.float32)
self.chunks =
def add:
self.chunks.append
self.vectors = np.vstack])
def search:
# 点积等价余弦,因为已归一化
scores = self.vectors @ qv.T #
order = np.argsort
return
This brute‑force approach runs in microseconds for tens of thousands of chunks – directly addressing “昂贵的向量数据库”痛点。
def retrieve(store: VectorStore,query: str,topk: int = 5,minscore: float = 0.6) -> list:
qvec = np.array)
hits = store.search
return
sequenceDiagram
participant U as 使用者
participant R as retrieve
participant VS as VectorStore
participant E as BGE
U->E这方面。问题文本
再看E-->R,问题向量
再看R->VS,search
再看VS-->R,前 k 个相似块 + 分数
R->U这方面,返回过滤后的块
七、answer:带引用的回答
The final step builds a prompt that forces LLM to cite sources using .
def build_prompt -> str:
context = "
".join)
return f"""只依据下面编号的资料回答问题,用 标注依据,资料没有的说"资料中没有相关信息"。再看资料,{context}
问题这方面,{query}"""
def answer -> dict:
resp = chat) # 调用 DeepSeek API 的封装函数
return {"answer": resp。"chunks": chunks}
资料: 循环引用是两个对象互相持有强引用…使用 weak 弱引用可以打破循环…怎么解决,说到规则,- 只依据资料回答,资料没有说“资料中没有相关信息”。- 用 标注依据,如“内存无法释放 ”。- 每条依据单独占一行,
User Pain Point Addressed: 明确且机器可解析的引用格式防止模型“幻觉”,让审计者能够快速定位答案出处。
八、evaluate:用数字说话
An objective evaluation suite quantifies both retrieval hit rate and citation correctness.
TEST_CASES =
def extractcitationnums -> list:
return ",text)]
def evaluate -> list:
results =
for query。expected in TESTCASES:
chunks = retrieve
hit = expected in {c.source for c in chunks}
citedsources = {chunks.source for n in extractcitationnums) if n ok = expected in citedsources
results.append)
return results
This numeric feedback loop lets us tune parameters,directly solving “调参无感知”痛点.
九、踩过的坑 & 实践建议
-
Intel Mac 兼容性:Torch 在 x8664 上最高只支持特定版本,需要匹配对应 CUDA/CPU wheel;否则会出现导入错误或性能下降。说起来,推荐使用官方 CPU‑only wheel 并锁定 transformers 与 numpy 的兼容版本。
-
Citation format 不稳定:LLM 有时会省略方括号或换行。通过在 Prompt 中加入严格示例并使用正则后处理,可明显提高一致性——这直接缓解了“答案不可追溯”的痛点。
-
Semi‑loose similarity threshold:If minscore is set too low you’ll see irrelevant blocks appear in answer. Empirically 0.6~0.7 works well on our iOS corpus;根据业务调低或调高即可避免“噪声答案”。"
-
Numpy 全表搜索规模限制: 对于上万甚至百万级文档,可考虑分桶或使用 Faiss 等轻量库。怎么说呢,但在小规模私有知识库里全表搜索已足够快且省去额外部署成本——
体现“低成本、本地化”的优势。"
<\/ol>
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback