精选

基于 LangChain + Ollama + Llama3 + Faiss 的中文 RAG 单车治理系统

最近在投递AI应用相关的实习,欠缺相关的项目经验,于是在学习了站内超级智能体项目学的RAG相关知识后,使用Python相关的技术栈完成了基于 LangChain + Ollama + Llama3 + FAISS 的中文 RAG 单车治理系统。

项目简介

基于 LangChain + Ollama + Llama3 + Faiss 的中文 RAG 单车治理系统。 源码: https://github.com/myth8/cycleai.git 效果图:

技术栈

  1. LangChain

  2. Ollama

  3. LLama3:8b

  4. Faiss

  5. 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 搜索),常用于:

  1. 文本向量检索(LLM RAG 系统)

  2. 图像相似检索(视觉搜索)

  3. 向量聚类 / 相似性推荐等任务

安装:

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 作为大模型

  1. 官网下载并安装Ollama

  2. 本地计算机进入 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):

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
CRZZX
下载 APP