从零搭一个会引用资料的 AI 搜索小项目:原理、流程和 Python 源码
AI搜索 新手入门指南|附源码
随着大模型(LLM)、向量数据库、搜索引擎和知识库问答技术的快速发展,“AI搜索”已经成为近两年非常热门的应用方向。相比传统搜索引擎只返回一堆网页链接,AI搜索更强调“理解问题、检索资料、总结答案、给出引用”,用户可以像和助手聊天一样获取信息。
本文将面向新手,从概念、原理、技术架构到实战代码,系统讲解如何搭建一个基础版 AI 搜索应用。文章末尾会附上一个可运行的 Python 示例源码,帮助你快速入门。
一、什么是 AI 搜索?
AI搜索可以简单理解为:
使用人工智能技术增强传统搜索能力,让系统不仅能“找到信息”,还能“理解信息、整合信息并生成答案”。
传统搜索通常是这样的流程:
- 用户输入关键词;
- 搜索引擎匹配相关网页;
- 返回网页标题、摘要和链接;
- 用户自己点开多个页面阅读、筛选和总结。
而 AI 搜索的流程更像这样:
- 用户用自然语言提出问题;
- 系统理解用户意图;
- 从互联网、数据库或本地知识库中检索相关内容;
- 将检索结果交给大语言模型;
- 大模型根据资料生成结构化答案;
- 返回答案,并附上参考来源。
例如,用户输入:
“2024年新能源汽车行业有哪些发展趋势?”
传统搜索会返回一批网页;AI搜索则可能直接输出:
- 智能化与自动驾驶加速发展;
- 插混车型市场占比提升;
- 电池成本下降推动价格竞争;
- 充电基础设施继续扩张;
- 海外市场成为车企增长重点。
并且在每个观点后附上来源。
二、AI搜索和传统搜索的区别
| 对比维度 | 传统搜索 | AI搜索 |
|---|---|---|
| 输入方式 | 关键词为主 | 自然语言问题 |
| 输出结果 | 链接列表 | 总结后的答案 |
| 用户成本 | 需要自己阅读多个网页 | 系统自动整合信息 |
| 核心技术 | 倒排索引、排序算法 | 搜索引擎 + 向量检索 + 大模型 |
| 适用场景 | 查找网页、导航 | 问答、研究、决策辅助 |
| 局限性 | 信息分散 | 可能出现幻觉,需要引用校验 |
AI搜索并不是完全替代传统搜索,而是在传统搜索基础上增加了理解、推理和总结能力。很多成熟的 AI 搜索产品,本质上仍然依赖搜索引擎提供底层资料,只是用大模型做了信息加工。
三、AI搜索的核心组成
一个基础的 AI 搜索系统通常由以下几个部分组成:
1. 用户输入层
用户输入问题,例如:
什么是RAG?它和微调有什么区别?
系统需要接收用户问题,并对问题进行预处理,比如去除无效符号、判断语言、提取关键词等。
2. 查询理解层
查询理解的目标是弄清楚用户到底想问什么。
例如用户输入:
苹果最新财报怎么样?
这里的“苹果”可能指水果,也可能指 Apple 公司。AI搜索系统需要结合上下文判断用户意图。
常见查询理解能力包括:
- 意图识别;
- 关键词提取;
- 查询改写;
- 同义词扩展;
- 时间范围识别;
- 多轮对话上下文理解。
对于新手来说,可以先不做复杂的查询理解,直接使用用户原始问题进行搜索。
3. 检索层
检索层负责从数据源中找出相关资料。常见方式有两种:
关键词检索
关键词检索类似传统搜索引擎,依赖文本中的词语匹配。典型技术包括:
- 倒排索引;
- BM25;
- Elasticsearch;
- OpenSearch;
- Meilisearch。
优点是速度快、可解释性强,适合精确匹配;缺点是对语义理解能力较弱。
向量检索
向量检索会先把文本转换成向量,也就是一组数字,然后根据向量之间的相似度找到语义相关内容。
例如:
“如何降低数据库查询耗时”
和:
“数据库性能优化有哪些方法”
虽然字面词不完全一样,但语义接近,向量检索可以更好地匹配。
常见向量数据库包括:
- FAISS;
- Milvus;
- Chroma;
- Weaviate;
- Qdrant;
- Pinecone。
4. 排序与筛选层
检索结果并不一定全部有用,因此需要排序和筛选。
常见策略包括:
- 按关键词匹配得分排序;
- 按向量相似度排序;
- 按发布时间排序;
- 按来源可信度排序;
- 使用大模型进行重排序;
- 去除重复内容。
在生产环境中,经常会将关键词检索和向量检索结合起来,这种方式叫做“混合检索”。
5. 生成层
生成层通常由大语言模型完成。
系统会把用户问题和检索到的资料一起传给模型,让模型基于资料生成答案。
这个过程常被称为 RAG。
RAG 的全称是:
Retrieval-Augmented Generation
中文通常翻译为:
检索增强生成
RAG 的核心思想是:
不让大模型凭空回答,而是先检索外部资料,再让模型根据资料回答。
这样可以降低幻觉,提高答案准确性,并且可以更新知识。
6. 引用与溯源层
AI搜索一个非常重要的能力是“给出来源”。
如果模型输出了结论,但没有引用,用户很难判断答案是否可信。因此,一个好的 AI 搜索系统通常会在答案中附带:
- 参考链接;
- 文档标题;
- 段落编号;
- 发布时间;
- 原文片段。
例如:
根据资料[1],RAG通常由检索模块和生成模块组成。
引用可以帮助用户进一步验证答案,也可以减少模型胡编乱造的问题。
四、AI搜索的典型架构
一个基础版 AI 搜索系统架构如下:
用户问题
↓
查询预处理
↓
搜索 / 向量检索
↓
结果排序与截断
↓
构造 Prompt
↓
调用大语言模型
↓
生成答案 + 引用来源
↓
返回给用户
如果是本地知识库问答,架构通常是:
文档上传
↓
文本切分
↓
向量化
↓
存入向量数据库
↓
用户提问
↓
向量检索相关片段
↓
大模型生成答案
五、新手应该如何学习 AI 搜索?
对于新手来说,不建议一开始就追求复杂架构。可以按照以下路线学习。
第一阶段:理解基本概念
需要掌握:
- 什么是大语言模型;
- 什么是 Embedding;
- 什么是向量数据库;
- 什么是 RAG;
- 什么是 Prompt;
- 什么是搜索排序。
如果这些概念还不熟,建议先做一个最简单的文本问答系统。
第二阶段:做本地知识库问答
可以先准备几篇本地文档,比如公司制度、产品说明、技术文章,然后实现:
- 读取文档;
- 文本切分;
- 生成向量;
- 存储向量;
- 用户提问;
- 找到相关片段;
- 大模型生成答案。
这个项目难度适中,非常适合作为 AI搜索入门练习。
第三阶段:接入联网搜索
在本地知识库问答的基础上,可以接入搜索 API,例如:
- Bing Search API;
- Google Custom Search API;
- SerpAPI;
- Tavily;
- Brave Search API;
- 自建爬虫。
联网搜索的优势是资料更新快,适合回答实时性问题。
第四阶段:优化检索质量
当系统能跑起来之后,可以继续优化:
- 增加查询改写;
- 加入混合检索;
- 使用 reranker 重排序;
- 优化文本切分策略;
- 增加引用来源;
- 过滤低质量网页;
- 检测答案是否有依据。
六、RAG 是 AI搜索的核心技术
很多 AI搜索系统背后的核心就是 RAG。下面我们重点讲一下 RAG 的流程。
1. 文档切分
大模型一次能够处理的文本长度有限,所以不能直接把一整本书或一整篇长文全部丢给模型。通常需要把文档切成多个小片段。
常见切分方式:
- 按固定字符数切分;
- 按段落切分;
- 按标题结构切分;
- 按语义边界切分。
例如将一篇文章切成每段 500 字左右,并保留一定重叠:
chunk_size = 500
chunk_overlap = 100
重叠的作用是避免上下文被截断。
2. 文本向量化
文本切分后,需要将每个片段转换为向量。
例如:
“AI搜索是一种结合搜索引擎和大语言模型的技术”
会被转换成类似这样的数字数组:
[0.021, -0.132, 0.087, ...]
这些数字本身不适合人阅读,但机器可以通过它们计算文本之间的语义相似度。
3. 向量存储
生成向量后,需要存入向量数据库。每条数据通常包含:
- 向量;
- 原文片段;
- 文档标题;
- 来源 URL;
- 创建时间;
- 元数据。
4. 相似度检索
用户提问时,系统先把问题也转换成向量,然后和数据库中的文档向量进行比较,找到最相似的几个片段。
常见相似度计算方法:
- 余弦相似度;
- 欧氏距离;
- 点积相似度。
5. 构造 Prompt
检索到资料后,需要将资料和问题组合成 Prompt。
示例:
请根据以下资料回答用户问题。
如果资料中没有答案,请回答“根据现有资料无法确定”。
资料:
[1] AI搜索结合了搜索引擎和大语言模型,可以根据检索结果生成答案。
[2] RAG 是检索增强生成,通过外部知识减少模型幻觉。
用户问题:
AI搜索和RAG有什么关系?
好的 Prompt 可以明显提升答案质量。
七、AI搜索常见问题
1. 为什么AI搜索会胡说八道?
主要原因包括:
- 检索结果不相关;
- Prompt 没有限制模型;
- 模型本身存在幻觉;
- 用户问题过于模糊;
- 没有要求模型基于资料回答;
- 没有做答案引用和校验。
解决方法包括:
- 提高检索质量;
- 明确要求模型只根据资料回答;
- 加入引用来源;
- 对答案进行事实校验;
- 检测资料是否支持答案。
2. 为什么检索结果不准?
常见原因包括:
- 文本切分太粗或太细;
- Embedding 模型效果不好;
- 没有做 query rewrite;
- 数据源质量低;
- 只使用单一检索方式;
- top_k 设置不合理。
可以尝试:
- 调整 chunk_size;
- 增加 chunk_overlap;
- 使用更好的 embedding 模型;
- 混合 BM25 和向量检索;
- 引入 reranker。
3. AI搜索适合哪些应用?
常见场景包括:
- 企业知识库问答;
- 学术论文搜索;
- 法律法规查询;
- 医疗资料检索;
- 电商智能导购;
- 金融研报分析;
- 程序员文档助手;
- 客服机器人;
- 竞品信息分析;
- 个人知识管理。
八、实战:用 Python 实现一个基础版 AI搜索
下面我们实现一个简单的本地 AI 搜索系统。它具备以下能力:
- 加载本地文档;
- 将文档切分为片段;
- 使用 TF-IDF 做文本检索;
- 根据用户问题找出相关片段;
- 构造 Prompt;
- 输出模拟版 AI 回答。
为了降低新手门槛,这个版本不依赖向量数据库,也不强制调用外部大模型 API。你可以先理解整体流程,再替换成真正的大模型和 Embedding 服务。
九、项目结构
建议创建如下目录:
ai-search-demo/
├── main.py
├── documents/
│ ├── rag.txt
│ ├── ai_search.txt
│ └── vector_db.txt
└── requirements.txt
十、安装依赖
创建 requirements.txt:
scikit-learn==1.4.2
numpy==1.26.4
安装依赖:
pip install -r requirements.txt
十一、准备示例文档
在 documents/rag.txt 中写入:
RAG 是 Retrieval-Augmented Generation 的缩写,中文通常称为检索增强生成。
它的核心思想是在大语言模型生成答案之前,先从外部知识库中检索相关资料。
这样可以减少模型幻觉,提高答案准确性,并且让模型能够使用最新知识。
RAG 通常包括文档切分、向量化、检索、Prompt 构造和答案生成几个步骤。
在 documents/ai_search.txt 中写入:
AI搜索是一种结合搜索技术和人工智能生成能力的新型信息获取方式。
传统搜索引擎主要返回网页链接,而AI搜索会根据检索到的资料生成结构化答案。
AI搜索通常会使用关键词检索、向量检索、大语言模型和引用溯源等技术。
它适合企业知识库、学术搜索、智能客服、产品文档问答等场景。
在 documents/vector_db.txt 中写入:
向量数据库用于存储和检索高维向量。
在AI搜索和RAG系统中,文本会先被Embedding模型转换为向量。
用户问题也会被转换为向量,然后系统通过相似度计算找到相关文本片段。
常见向量数据库包括FAISS、Milvus、Qdrant、Chroma和Weaviate。
十二、基础版 AI搜索源码
创建 main.py:
import os
import glob
from typing import List, Dict
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
class DocumentChunk:
"""
文档片段对象
"""
def __init__(self, doc_name: str, content: str, chunk_id: int):
self.doc_name = doc_name
self.content = content
self.chunk_id = chunk_id
def to_dict(self):
return {
"doc_name": self.doc_name,
"chunk_id": self.chunk_id,
"content": self.content
}
class AISearchEngine:
"""
一个基础版 AI搜索引擎:
1. 加载本地文档
2. 切分文本
3. 使用 TF-IDF 建立索引
4. 根据用户问题检索相关片段
5. 构造回答
"""
def __init__(self, docs_dir: str = "documents", chunk_size: int = 120):
self.docs_dir = docs_dir
self.chunk_size = chunk_size
self.chunks: List[DocumentChunk] = []
self.vectorizer = TfidfVectorizer()
self.tfidf_matrix = None
def load_documents(self):
"""
加载 documents 目录下的 txt 文档
"""
file_paths = glob.glob(os.path.join(self.docs_dir, "*.txt"))
if not file_paths:
raise FileNotFoundError(f"未找到文档,请检查目录:{self.docs_dir}")
for file_path in file_paths:
doc_name = os.path.basename(file_path)
with open(file_path, "r", encoding="utf-8") as f:
text = f.read().strip()
chunks = self.split_text(text)
for idx, chunk in enumerate(chunks):
self.chunks.append(DocumentChunk(
doc_name=doc_name,
content=chunk,
chunk_id=idx
))
def split_text(self, text: str) -> List[str]:
"""
简单文本切分:
按固定字符长度切分。
实际项目中可以按段落、标题、语义边界切分。
"""
result = []
for i in range(0, len(text), self.chunk_size):
chunk = text[i:i + self.chunk_size].strip()
if chunk:
result.append(chunk)
return result
def build_index(self):
"""
使用 TF-IDF 建立文本索引
"""
if not self.chunks:
raise ValueError("文档片段为空,请先加载文档")
corpus = [chunk.content for chunk in self.chunks]
self.tfidf_matrix = self.vectorizer.fit_transform(corpus)
def search(self, query: str, top_k: int = 3) -> List[Dict]:
"""
根据用户问题检索最相关的 top_k 个片段
"""
if self.tfidf_matrix is None:
raise ValueError("索引尚未建立,请先调用 build_index()")
query_vec = self.vectorizer.transform([query])
scores = cosine_similarity(query_vec, self.tfidf_matrix).flatten()
ranked_indices = scores.argsort()[::-1][:top_k]
results = []
for idx in ranked_indices:
chunk = self.chunks[idx]
results.append({
"score": float(scores[idx]),
"doc_name": chunk.doc_name,
"chunk_id": chunk.chunk_id,
"content": chunk.content
})
return results
def build_prompt(self, query: str, search_results: List[Dict]) -> str:
"""
构造给大模型的 Prompt
"""
context_text = ""
for i, item in enumerate(search_results, start=1):
context_text += (
f"[{i}] 来源:{item['doc_name']},片段:{item['chunk_id']}\n"
f"{item['content']}\n\n"
)
prompt = f"""
请你根据以下资料回答用户问题。
要求:
1. 只能根据资料回答,不要编造资料中没有的信息;
2. 如果资料不足,请回答“根据现有资料无法确定”;
3. 回答时尽量结构清晰;
4. 如使用某条资料,请在句末标注引用编号,例如:[1]。
资料:
{context_text}
用户问题:
{query}
请输出答案:
"""
return prompt.strip()
def mock_llm_answer(self, query: str, search_results: List[Dict]) -> str:
"""
模拟大语言模型回答。
新手可以先用这个方法理解流程。
实际项目中可以替换为 OpenAI、通义千问、智谱、DeepSeek 等模型 API。
"""
if not search_results:
return "根据现有资料无法确定。"
best = search_results[0]
answer = f"""根据检索到的资料,和“{query}”最相关的信息如下:
{best['content']}
参考来源:
[1] {best['doc_name']},片段 {best['chunk_id']}
说明:
当前示例使用的是本地 TF-IDF 检索和模拟回答,并未真正调用大语言模型。
如果接入大模型,可以将 build_prompt() 生成的 Prompt 发送给模型,让模型生成更自然的答案。
"""
return answer
def ask(self, query: str, top_k: int = 3):
"""
完整问答流程
"""
results = self.search(query, top_k=top_k)
prompt = self.build_prompt(query, results)
answer = self.mock_llm_answer(query, results)
return {
"query": query,
"search_results": results,
"prompt": prompt,
"answer": answer
}
def main():
engine = AISearchEngine(docs_dir="documents", chunk_size=120)
print("正在加载文档...")
engine.load_documents()
print("正在建立索引...")
engine.build_index()
print("AI搜索系统已启动,输入 exit 退出。")
while True:
query = input("\n请输入你的问题:").strip()
if query.lower() in ["exit", "quit"]:
print("已退出。")
break
if not query:
print("问题不能为空。")
continue
result = engine.ask(query, top_k=3)
print("\n========== 检索结果 ==========")
for i, item in enumerate(result["search_results"], start=1):
print(f"\n[{i}] 得分:{item['score']:.4f}")
print(f"来源:{item['doc_name']},片段:{item['chunk_id']}")
print(f"内容:{item['content']}")
print("\n========== 构造的 Prompt ==========")
print(result["prompt"])
print("\n========== AI回答 ==========")
print(result["answer"])
if __name__ == "__main__":
main()
十三、运行项目
在项目根目录运行:
python main.py
示例输入:
什么是RAG?
可能输出:
根据检索到的资料,和“什么是RAG?”最相关的信息如下:
RAG 是 Retrieval-Augmented Generation 的缩写,中文通常称为检索增强生成。
它的核心思想是在大语言模型生成答案之前,先从外部知识库中检索相关资料。
参考来源:
[1] rag.txt,片段 0
再输入:
AI搜索适合哪些场景?
可能输出:
AI搜索适合企业知识库、学术搜索、智能客服、产品文档问答等场景。
十四、如何接入真正的大语言模型?
上面的示例为了简单,没有真实调用大模型。如果你想让系统输出更自然、更完整的答案,可以将 mock_llm_answer 替换成真实模型调用。
下面给出一个伪代码示例:
def call_llm(prompt: str) -> str:
"""
这里以伪代码形式展示。
你可以替换成 OpenAI、DeepSeek、通义千问、智谱等模型 API。
"""
response = client.chat.completions.create(
model="your-model-name",
messages=[
{
"role": "system",
"content": "你是一个严谨的AI搜索助手,必须根据资料回答问题。"
},
{
"role": "user",
"content": prompt
}
],
temperature=0.2
)
return response.choices[0].message.content
然后在 ask 方法中改成:
prompt = self.build_prompt(query, results)
answer = call_llm(prompt)
这样,你的系统就从“检索演示程序”升级成了一个真正的 AI 搜索问答系统。
十五、如何升级为向量检索版本?
当前示例使用的是 TF-IDF。它适合入门,但语义理解能力有限。如果要升级为向量检索,可以使用如下方案:
方案一:Embedding API + FAISS
流程如下:
- 调用 Embedding 模型,将文档片段转为向量;
- 使用 FAISS 建立本地向量索引;
- 用户提问时,也将问题转成向量;
- 用 FAISS 搜索最相似片段;
- 将结果交给大模型生成答案。
常见依赖:
pip install faiss-cpu numpy
伪代码:
import faiss
import numpy as np
dimension = 1536
index = faiss.IndexFlatL2(dimension)
doc_vectors = np.array([...]).astype("float32")
index.add(doc_vectors)
query_vector = np.array([...]).astype("float32")
distances, indices = index.search(query_vector, k=5)
方案二:Chroma 向量数据库
Chroma 更适合做本地知识库原型。
安装:
pip install chromadb
使用方式大致如下:
import chromadb
client = chromadb.Client()
collection = client.create_collection("ai_search_docs")
collection.add(
documents=[
"RAG 是检索增强生成技术。",
"AI搜索结合了搜索引擎和大语言模型。"
],
ids=["doc1", "doc2"]
)
results = collection.query(
query_texts=["什么是AI搜索?"],
n_results=2
)
print(results)
这种方式比自己管理向量索引更方便。
十六、AI搜索的优化方向
当你完成基础版本之后,可以从以下方面继续优化。
1. 优化文本切分
文本切分会直接影响检索质量。
过大的片段会包含太多无关信息;过小的片段又容易丢失上下文。一般可以根据文档类型调整:
| 文档类型 | 建议切分方式 |
|---|---|
| 技术文档 | 按标题和段落切分 |
| 法律法规 | 按条款切分 |
| FAQ | 按问题答案对切分 |
| 论文 | 按章节和段落切分 |
| 网页内容 | 按正文段落切分 |
2. 增加查询改写
用户问题有时很短,例如:
怎么收费?
如果没有上下文,系统很难检索准确。可以用大模型先改写为:
该产品的收费标准、套餐价格和计费方式是什么?
查询改写可以显著提升检索效果。
3. 使用混合检索
向量检索擅长语义匹配,关键词检索擅长精确匹配。混合检索可以结合两者优点。
例如:
最终得分 = 0.6 * 向量相似度 + 0.4 * BM25得分
对于包含专有名词、产品型号、错误码的问题,关键词检索尤其重要。
4. 引入 Reranker
Reranker 是重排序模型。它会对“问题 + 候选文档”进行更精细的相关性判断。
流程:
先召回 top 20 个片段
↓
Reranker 重新排序
↓
选出 top 5 个片段
↓
交给大模型生成答案
这种方式通常比单纯向量检索更准确。
5. 做答案可信度判断
可以让模型在回答后输出:
- 答案是否有足够资料支持;
- 引用是否覆盖关键结论;
- 是否存在不确定信息;
- 哪些内容需要用户自行验证。
例如:
{
"answer": "……",
"confidence": "high",
"sources": [1, 2],
"unsupported_claims": []
}
这对严肃场景非常重要。
十七、生产环境需要注意什么?
如果要把 AI搜索用于真实业务,还需要考虑更多工程问题。
1. 数据安全
企业知识库中可能包含敏感信息,因此需要:
- 权限控制;
- 数据加密;
- 用户访问审计;
- 文档级权限过滤;
- 防止 Prompt 注入;
- 防止模型泄露系统提示词。
2. 成本控制
调用大模型和 Embedding API 都会产生成本。可以通过以下方式优化:
- 缓存常见问题答案;
- 缓存文档向量;
- 控制 top_k;
- 压缩上下文;
- 使用较小模型处理简单问题;
- 对长文档做摘要索引。
3. 实时更新
如果文档经常变化,需要设计增量更新机制:
- 新文档自动入库;
- 修改文档后重新向量化;
- 删除文档时同步删除索引;
- 定期重建索引;
- 保留文档版本。
4. 评测体系
AI搜索不能只靠主观感觉,需要建立评测集。
可以准备一批标准问题,并标注:
- 正确答案;
- 应该命中的文档;
- 关键引用;
- 不应回答的内容。
常见指标包括:
- Recall@K;
- Precision@K;
- MRR;
- 答案准确率;
- 引用准确率;
- 幻觉率;
- 用户满意度。
十八、AI搜索学习路线总结
如果你是新手,可以按照下面路线实践:
第1步:理解 AI搜索、RAG、Embedding、向量数据库
第2步:实现一个本地文档检索 Demo
第3步:接入大语言模型 API
第4步:替换 TF-IDF 为向量检索
第5步:加入引用来源
第6步:增加查询改写和重排序
第7步:接入联网搜索
第8步:做权限、缓存、评测和监控
不需要一开始就搭建复杂系统。最重要的是先跑通“检索 + 生成”的闭环。
十九、结语
AI搜索的本质并不是简单地把大模型接到搜索框后面,而是构建一个可靠的信息获取系统。它需要搜索技术提供资料基础,需要向量检索理解语义,需要大语言模型整合表达,也需要引用溯源和评测体系保证可信度。
对于新手来说,学习 AI搜索最好的方式不是只看概念,而是动手实现一个最小可用版本。本文提供的源码虽然简单,但已经包含了 AI搜索的核心流程:文档加载、文本切分、索引构建、相关性检索、Prompt 构造和答案生成。
当你理解这个基础版本后,就可以逐步替换和升级其中的模块,例如将 TF-IDF 替换为 Embedding,将本地文档扩展为联网搜索,将模拟回答替换为真实大模型调用。这样一步步迭代,你就能从一个简单 Demo 走向完整的 AI搜索产品。