
基于 LangChain + Ollama + Llama3 + Faiss 的中文 RAG 单车治理系统
最近在投递AI应用相关的实习,欠缺相关的项目经验,于是在学习了站内超级智能体项目学的RAG相关知识后,使用Python相关的技术栈完成了基于 LangChain + Ollama + Llama3 + FAISS 的中文 RAG 单车治理系统。
项目简介
基于 LangChain + Ollama + Llama3 + Faiss 的中文 RAG 单车治理系统。
源码: https://github.com/myth8/cycleai.git
效果图:

技术栈
-
LangChain
-
Ollama
-
LLama3:8b
-
Faiss
-
FastAPI
环境
-
python = 3.10
-
环境管理工具为 Anaconda3
-
代码涉及的依赖均为最新版本
各模块介绍
智能RAG问答

文档收集和切割
文档收集

文档格式采用 txt 方式,便于后续添加到 Faiss 向量数据库中。文档内容来自 AI生成,示例:
▼plain复制代码主题:共享单车淤积与供需不平衡问题 一、问题概述 单车“淤积”是指在特定区域或时段,单车过度集中或严重短缺的现象。例如早高峰地铁口单车被骑走,居民区周边迅速“空车”;而中午或晚上商圈、景区等地则“堆车如山”。 根据2023年广州共享单车运维中心的数据,单车供需匹配率仅为72%,意味着近三成用户无法在需要时就近找到可骑单车。 二、形成原因 1. 时空需求不平衡上下班通勤造成“早进晚出”模式——早上大量单车流向商业区,晚上又回流至居民区。 2. 天气与节假日因素雨天、寒潮或假期期间,用户出行规律发生变化,导致短时间内车辆调度无法响应。 3. 地理环境影响坡度较大或交通复杂的区域(如重庆、香港等地)出现“上山难、下山易”的单向流动现象。据重庆市一项研究显示,共享单车的单向骑行比例高达87%。 4. 调度滞后与预测不足企业往往依赖人工经验进行调度,缺乏动态数据支持,难以及时调整运维策略。 三、典型案例分析 • 北京中关村地区高峰期办公人流密集,午餐和下班时段单车需求激增。企业通过历史数据分析发现,每天约有4000辆单车集中堆积在写字楼南门200米范围内。通过设置中转调度点和AI预测模型,该区域单车周转效率提升了近30%。 • 杭州西湖景区节假日游客量大,单车常出现“堆积成墙”现象。当地管理部门在2022年启用“动态调度系统”,实时监测各停车点车量,并自动派单至运维团队,日均淤积量减少45%。 四、解决思路 1. 建设“虚拟停车区”系统根据实时需求动态调整虚拟停车范围,避免物理空间限制。 2. 数据驱动的调度优化借助AI模型预测未来1–2小时内的单车流量分布,提前调拨。例如,美团单车的“城市大脑系统”可提前预测早高峰淤积点位,调度效率提升约25%。 3. 用户激励机制鼓励用户在非高峰期将单车骑至低密度区域,还车可获得积分或优惠券。 4. 与公共交通协同调度在地铁出入口与公交站点间设置智能停车区,实现多模式衔接,减少极端聚集。 五、未来方向 • 多源数据融合:整合天气、节假日、交通流量等多维数据,提高预测准确率。 • 智能运维车队:采用电动运维车、无人调度车,实现夜间自动分配。 • 区域弹性管理:针对不同城市特征设定弹性调度模型,实现“城市自适应运营”。
文件切割
本系统的中文 RAG 切割策略,满足以下条件:
-
按自然段落切割(而不是硬切字符)
-
每个 chunk 开头结尾为完整句子
-
chunk 大约 250 字,相邻 chunk 重叠 80-100 字
实现核心代码:
▼python复制代码# =============================== # 2️⃣ 中文自然段切割 # =============================== def chinese_paragraph_chunker(text, chunk_size=250, chunk_overlap=100): paragraphs = [p.strip() for p in text.split('\n') if p.strip()] chunks = [] buffer = "" for para in paragraphs: sentences = re.split(r'(。|!|?|\n)', para) sentences = [s for s in sentences if s.strip()] for s in sentences: if len(buffer) + len(s) <= chunk_size: buffer += s else: if buffer: chunks.append(buffer) buffer = buffer[-chunk_overlap:] + s if chunk_overlap < len(buffer) else buffer + s if buffer: chunks.append(buffer) return chunks
向量转换和存储
Embedding 模型
使用 Ollama 库 包含的 Embedding 模型:
▼python复制代码from langchain_ollama import OllamaEmbeddings, ChatOllama
向量存储
使用 Faiss 向量数据库,Faiss(全称 Facebook AI Similarity Search)是一个由 Meta(原 Facebook)AI 团队 开发的高性能相似度搜索库,用来在海量向量数据中快速查找相似项。 它是现代 RAG(Retrieval-Augmented Generation)系统中最常用的“向量数据库后端”之一。 FAISS 不是传统意义上的数据库,而是一个 高效的向量相似度搜索与聚类库,用于执行诸如:在百万甚至十亿级向量集合中,快速找到与某个查询向量最相似的前 K 个向量(Top-K 搜索),常用于:
-
文本向量检索(LLM RAG 系统)
-
图像相似检索(视觉搜索)
-
向量聚类 / 相似性推荐等任务
安装:
▼bash复制代码pip install faiss-cpu
Faiss 加载文档核心代码:
▼python复制代码embedding_model = OllamaEmbeddings(model=MODEL_NAME) vectors = [embedding_model.embed_query(doc.page_content) for doc in chunked_documents] vectors_np = np.array(vectors).astype("float32") dim = vectors_np.shape[1] index = faiss.IndexFlatL2(dim) index.add(vectors_np) docstore = InMemoryDocstore({str(i): doc for i, doc in enumerate(chunked_documents)}) # 核心代码 vector_store = FAISS( index=index, embedding_function=embedding_model, # 直接传 Embeddings 对象,去警告 docstore=docstore, # chunked_documents 为切割后的文档 index_to_docstore_id={i: str(i) for i in range(len(chunked_documents))} ) print("FAISS 向量库创建完成。")
文档过滤和检索
利用 Faiss 的 相似度检索算法 和 TopK 选出候选的文档,然后使用 stuff 的策略,将文档内容连接合并,加入提示词中。

具体步骤:
-
每个文档块都被
OllamaEmbeddings(model=MODEL_NAME)转换成一个向量。 -
用户问题被同样地向量化。
-
然后 FAISS 根据 欧氏距离(L2) 计算相似度。
-
按距离从小到大排序,取前 k 个 chunk(top-k)。
-
检索Top-5相似文档 → 拼接上下文 → Prompt注入 → 调用 Llama3 模型生成回答
相关代码:
▼python复制代码# =============================== # 6️⃣ RAG 问答链(推荐写法) # =============================== retriever = vector_store.as_retriever(search_type="similarity", search_kwargs={"k":5}) # 使用 from_chain_type 并传入 chain_type_kwargs 自定义 Prompt qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", # 连接文档上下文 retriever=retriever, return_source_documents=True, chain_type_kwargs={"prompt": prompt} # ✅ 自定义 Prompt 生效 )
查询增强和关联
增强提示词(提示词设计)
在获取 AI 回复时,我希望模型 以自身知识为主,仅在必要时参考检索文档,而不是每次回答都强制依赖文档。为此,需要对 提示词模板(Prompt Template)进行一定的设计,在此通过 明确优先级 的方式,设计模板, 告诉模型 先使用自己的知识,只在需要时参考文档,对应代码:
▼python复制代码# =============================== # 5️⃣ Prompt & LLM # =============================== prompt_template = """ 请先根据你已有的知识理解回答用户的问题,仅在必要时参考以下检索到的文档内容。 回答要求: - 用简体中文 - 尽量准确完整 - 如果文档信息不足,可以用你自己的理解补充 文档内容: {context} 用户问题: {question} """ prompt = ChatPromptTemplate.from_template(prompt_template)
设计好代码后,即可调用 Llama3 模型生成回答。
Ollama 部署 Llama3 作为大模型
-
官网下载并安装Ollama
-
本地计算机进入 CMD 命令行,运行 ollama run llama3:8b 命令即可在本地运行模型
之所以选择 Llama3 模型,是因为初始化 Faiss 向量数据库 EmbeddingModel = OllamaEmbeddings 时,是不支持gemma3的,但一定支持Llama,因为官方文档示例就是用的Llama(https://python.langchain.com/docs/integrations/text_embedding/ollama/)

多轮对话实现
通过 LangChain 的 ConversationBufferMemory 和ConversationalRetrievalChain 实现对话上下文记忆功能,使 AI能在多轮对话中保持语境连贯。


验证结果:


对话记忆持久化
通过定义对话 json 结构,实现对 AI 对话的记忆持久化,并在重启项目后加载本地对话至ChatMemory,同时维护每一次对话记录到本地对话 json 文件中。


效果:
最终回答和效果

为之添加一个 HTML 网页(后端为FastAPI):





