news 2026/10/3 9:22:49

本地知识库问答新方案:Ollama+Neo4j搭建GraphRAG系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
本地知识库问答新方案:Ollama+Neo4j搭建GraphRAG系统

做本地知识库问答最尴尬的场景,不是模型效果不够好,而是你辛辛苦苦搭好了一套 RAG 流水线,结果问它“A 和 B 之间是什么关系”这类问题,它只能甩给你两段语义相近但互不关联的文本片段。传统向量检索擅长找相似段落,却很难理解实体之间的网状关联。GraphRAG 正好补上这个短板——它先在文档里抽取实体和关系,构建成知识图谱,再基于图谱做检索增强生成。这篇文章分享一套完整落地过程:用 Ollama 做本地推理引擎,把 GraphRAG 索引管线和 Neo4j 图数据库串起来,从零搭一套能回答复杂关系问题的私有化问答系统。整个过程不依赖任何云端服务,数据不出内网,适合企业知识库、内部文档问答,也适合想搞懂 GraphRAG 原理的开发者直接参考。

1. 整体设计拆解:GraphRAG + 本地模型为什么能成

1.1 传统 RAG 的短板和 GraphRAG 的补位

传统 RAG 的流程是:把文档切片,做向量化,建立向量索引。用户提问时,拿问题向量去库里找 Top-K 相似片段,再把片段拼进 prompt 丢给大模型。这个流程在“这个问题在某一段落里有明确答案”的时候很好用,比如“物流部门的负责人是谁”。但一旦问题是跨段落、跨文档的,比如“研发部负责的 XX 项目用了哪些技术栈”,传统 RAG 就抓瞎了。因为答案分散在多个实体和关系里,向量相似度检索只会给你“看似相关但不完整”的片段。

GraphRAG 的思路是把信息抽成图:文档里的“部门”“项目”“技术栈”都是节点,它们之间的关系是边。比如(研发部)-【负责】->(XX 项目)-【使用】->(Python)。问答时我们先在图里找到相关实体,再沿着边跳一步或两步,把所有直接相关的路径捞出来,交给大模型综合回答。这样得到的上下文不是零散碎片,而是结构化的关系网络,回答“谁和谁什么关系”这类问题就顺理成章了。

实际部署里我不建议把图检索和向量检索做成二选一。我的做法是:核心关系存在图里,细节描述继续走向量召回。两者结果合并后一起进 prompt,既能给出关系型答案,又能保留原始文档里的关键描述,效果比单一方案稳得多。

1.2 选用 Ollama 做本地推理的几个关键理由

本地化推理引擎有很多选择:llama.cpp、LM Studio、vLLM、FastGPT 自带推理模块等。我最终选择 Ollama,倒不是因为它的推理速度最快,而是在 GraphRAG 这个场景里,Ollama 的集成成本最低。

第一,Ollama 内置 OpenAI 兼容接口。GraphRAG 索引管线和问答模块只需要按照 OpenAI 客户端的方式调用,把base_url指到http://localhost:11434/v1就行。这省掉了自己封装推理接口的工作量,也不用改 GraphRAG 底层代码。

第二,模型管理和量化开箱即用。Ollama 一条命令就能拉取模型、做量化参数选择、加载到显存里跑推理。模型文件用 GGUF 格式,显存不够就换小量化级别,非常灵活。它不像 vLLM 那样需要写一堆调度配置,也不像 llama.cpp 那样要自己编译和写启动脚本。

第三,Ollama 支持“抽取用模型”和“问答用模型”分离。知识图谱的实体抽取任务比较重,但对创造性要求不高;最终问答则更考验语言表达和逻辑。我可以让抽取流程用 7B 的 Qwen,问答流程用 14B 甚至更大的模型,互不干扰。这种分工只用修改配置,成本上很划算。

1.3 系统整体工作流程

整套系统从原始文档到用户回答,分两条链路。

索引链路是离线的:文档经过清洗和分块后,交给大模型做实体和关系抽取。抽取结果写入 Neo4j,同时把每个实体关联的原始文本片段做向量化,存储到向量索引里。GraphRAG 的索引管线还会额外做社区检测,把关系密集的一组实体合并成社区摘要,后续做全局提问时能直接利用社区级的上下文。

问答链路是在线的:用户问题进来后,先做实体识别,把问题里的关键实体定位到图上;然后在图里做多跳扩展,找到相关路径和邻居节点;同时用向量检索召回相关文档片段。图谱路径和文本片段合并,统一拼进 prompt,交给 Ollama 上的本地模型生成最终答案。

这个链路的好处是每个环节都可以独立调试。实体抽取得不准就调提示词;图路径扩展太宽就限制跳数;向量召回结果不好就换 embedding 模型。后面我会逐个环节讲实操细节。

2. 环境准备与基础部署

2.1 Ollama 安装:Windows / Mac / Linux 通用流程

先装 Ollama。在 Linux 服务器上,官方提供了安装脚本:

curl -fsSL https://ollama.com/install.sh | sh

脚本执行完成后,用ollama --version验证安装。Windows 则是去官网下载 OllamaSetup.exe,双击安装即可。Mac 有 brew 方式:

brew install ollama

这里有个坑:Windows 默认安装路径在 C 盘,模型也默认存 C 盘,系统盘小的话很快就会被撑爆。我建议从一开始就把模型目录迁移到另外的盘,避免后面返工。

Windows 上设置模型路径的方法是:先彻底退出 Ollama(任务栏图标右键退出,保险起见再去任务管理器结束ollama app.exe),然后按Win + R输入sysdm.cpl打开系统属性,在“高级—环境变量”里新建用户环境变量:

变量名:OLLAMA_MODELS 变量值:D:\ollama\models

再把 Ollama 重新启动,输入ollama pull qwen2.5:7b,打开文件夹D:\ollama\models\blobs,看到模型文件在增长,说明迁移成功。

安装后最好确认一下服务状态。Linux 上 Ollama 本身是 systemd 服务,会自动启动。想调整监听地址,打开/etc/systemd/system/ollama.service,修改Environment里的OLLAMA_HOST,比如改成0.0.0.0:11434,然后:

systemctl daemon-reload systemctl restart ollama

这样就允许局域网内其他机器访问这台机器的推理服务,后面做私有化知识库问答很有用。

2.2 模型下载与国内网络优化

Ollama 官方模型仓库的下载速度在部分地区不太稳定,经常出现pull model manifest: file does not exist或下载到一半超时。遇到这种情况,别死磕ollama pull,更快的办法是从国内的模型托管平台下载 GGUF 文件,再用 Ollama 导入。

以通义千问 7B 为例。先从魔搭社区的模型仓库下载qwen2.5-7b-instruct的 GGUF 量化文件,选q4_k_m版本,大小约 4.4GB。下载后放到一个目录,比如D:\models\qwen2.5-7b。

然后创建一个Modelfile,内容如下:

FROM ./qwen2.5-7b-instruct-q4_k_m.gguf TEMPLATE """{{- if .System }} <|im_start|>system {{ .System }}<|im_end|> {{- end }} <|im_start|>user {{ .Prompt }}<|im_end|> <|im_start|>assistant """ PARAMETER temperature 0.3 PARAMETER top_p 0.9 PARAMETER stop "<|im_end|>"

这个文件告诉 Ollama 如何加载 GGUF 模型,同时定义了 prompt 模板。然后执行:

ollama create qwen2.5-7b-chat -f Modelfile

创建完成后,ollama run qwen2.5-7b-chat就能直接用了。如果下载的是其他模型,比如 DeepSeek 或 ChatGLM,Modelfile 里的 TEMPLATE 要对应改成该模型的对话模板,否则回答格式会乱。

Embedding 模型我建议用bge-m3,中文语义效果好于开源界大部分同类模型。它也有 GGUF 版本,同样可以用 Modelfile 导入。当然,Ollama 官方仓库里也有nomic-embed-text,如果你网络允许,直接ollama pull nomic-embed-text最省事。

2.3 模型选择:不同显存怎么挑

本地跑大模型,显存是第一约束条件。我根据自己的实测拉了一张推荐表,方便你按机器配置直接选:

显存规模推荐模型量化级别用途
4GBQwen2.5-3Bq4_k_m简单抽取、问答
6GBQwen2.5-7Bq4_k_m实体抽取、通用问答
8GBQwen2.5-7B / DeepSeek-R1-Distill-Qwen-7Bq4_k_m / q5_k_m抽取 + 中文问答效果均衡
12GBQwen2.5-14Bq4_k_m高质量抽取、复杂关系推理
24GB+Qwen2.5-32Bq4_k_m生产级知识图谱问答

注意两件事:显存是“至少”值,因为除了模型权重,还要算 KV Cache。上下文长度设得越长,KV Cache 占显存越多。我早期用 8G 显存跑 7B 模型,上下文拉到 8192,加载模型还算顺利,但一进行长时间对话就显存爆,后来把num_ctx降到 4096 才稳定。

另一个经验是:抽取实体关系时,模型输出的是结构化结果,不是自然语言,其实 7B 就够用。真正考验模型推理能力的还是最终问答环节,如果机器允许,单独给问答分配一个大模型,效果提升非常明显。

2.4 部署 Neo4j,准备知识图谱存储

Neo4j 是目前最成熟的开源图数据库之一,GraphRAG 产出的是图和关系数据,用 Neo4j 存起来,后续查询、可视化、调优都方便。部署直接用 Docker Compose,不用在本地手工装 Java 环境。

新建docker-compose.yml:

services: neo4j: image: neo4j:5-community container_name: neo4j ports: - "7474:7474" - "7687:7687" environment: - NEO4J_AUTH=neo4j/your_password - NEO4J_PLUGINS=["apoc"] volumes: - ./neo4j/data:/data - ./neo4j/logs:/logs - ./neo4j/plugins:/plugins restart: unless-stopped

启动:

docker compose up -d

等容器状态变为running后,浏览器打开http://localhost:7474,用neo4j和刚才设置的密码登录。这里我建议装一下 APOC 插件,后面做路径搜索、图算法分析时能省很多 Cypher 代码。

如果机器没装 Docker,或者内存只有 4G 跑不动 Neo4j,可以先把数据落在 GraphRAG 生成的 parquet 文件里,图存储延后。但生产环境我还是建议上 Neo4j,否则后面查询关系路径还得自己写图遍历算法,维护成本很高。

3. 核心实操:从文档到知识图谱再到问答

3.1 数据清洗与分块

知识图谱的数据质量决定了抽取质量,这一步不能省。我先把原始 Word、PDF、Markdown 统一转成纯文本,再用脚本清洗掉页眉页脚、目录、超链接残留、乱码字符。最终每篇文档保存为单独的.md文件,统一 UTF-8 编码。

接下来做分块。GraphRAG 的索引管线本身会管理文本单元,但那是把整篇文档自动切成小块,再交给 LLM 抽取。如果我们手工分块,要给 GraphRAG 提供比较干净的输入。实践下来的推荐参数是:块大小 800 字左右,前后重叠 100 字。

分块目的有两个。一是让模型在单次抽取里看到足够完整的语义,太短会丢失上下文,太长又会超出模型上下文窗口;二是为了后续做社区检测时,文本单元之间有足够的关联度。我踩过一个大坑:把块切到 200 字,结果实体抽取特别碎,“北京总公司”和“北京分公司”被识别成两个完全不同的实体,后期还得费劲做实体对齐。

清洗后的文档放在项目根目录的input文件夹下,子目录可以让 GraphRAG 做更细粒度的文档分组。

查看数据目录结构:

graphrag-project/ ├── input/ │ ├── 研发部项目总结.md │ ├── 市场部产品手册.md │ └── 2025年度技术规划.md ├── output/ ├── prompts/ └── settings.yaml

3.2 实体与关系抽取:用 GraphRAG 索引管线跑一遍

GraphRAG 索引管线会把文档切块、调用 LLM 抽取实体关系、生成社区摘要,最后输出结构化数据。它支持通过环境变量和配置文件控制 LLM 类型。

项目根目录下初始化:

graphrag init --root .

这会生成settings.yaml。然后改成 Ollama 后端:

llm: api_key: ollama api_base: http://localhost:11434/v1 model: qwen2.5-7b-chat temperature: 0 max_tokens: 2000 embedding: api_key: ollama api_base: http://localhost:11434/v1 model: bge-m3 chunks: size: 800 overlap: 100 input: file_type: .md cache: type: file base_dir: cache

注意temperature: 0,抽取任务不需要任何创造性,温度设为 0 可以最大限度减少模型自由发挥,保证输出稳定。

然后执行索引:

graphrag index --root . --verbose

首次跑会比较久,7B 模型处理几千字文档也需要几分钟,因为每个文本块都要调一次抽取接口。中途如果提示rate limit或连接错误,是因为 Ollama 并发处理能力有限,可以在环境变量里限制一下:

export GRAPHRAG_LLM_CONCURRENCY=4 export GRAPHRAG_EMBEDDING_CONCURRENCY=8

跑完后在output目录里可以看到entities.parquet、relationships.parquet、communities.parquet等文件。这些文件就是图谱数据。

如果不想用 GraphRAG 自带的提示词,可以修改prompts/entity_extraction.txt。我一般会把抽取目标限定为“人物、组织、产品、技术栈、项目、地区、时间”七类,并在提示词里强调:

只抽取文本中明确出现的实体,不要联想;关系必须能通过原文佐证;输出格式严格为 JSON 数组;每个实体至少给出一个所属类型。

这样会让 7B 模型抽取质量稳定很多。

3.3 构建索引并入库 Neo4j

GraphRAG 输出的 parquet 文件是“图数据中间产物”,但真正想跑 Cypher 查询、做可视化,还得把它们导入 Neo4j。我写了一个导入脚本,思路很简单:读entities.parquet建节点,读relationships.parquet建边。

import pandas as pd from neo4j import GraphDatabase driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "your_password")) entities = pd.read_parquet("output/20250601_100000/entities.parquet") edges = pd.read_parquet("output/20250601_100000/relationships.parquet") with driver.session() as session: for row in entities.to_dict("records"): session.run( """ MERGE (e:Entity {id: $id}) SET e.name = $name, e.type = $type, e.description = $description """, id=row["id"], name=row["name"], type=row["type"], description=row.get("description") ) for row in edges.to_dict("records"): session.run( """ MATCH (a:Entity {id: $source}) MATCH (b:Entity {id: $target}) MERGE (a)-[r:RELATES_TO]->(b) SET r.type = $relation, r.description = $description """, source=row["source"], target=row["target"], relation=row["relation"], description=row.get("description") ) driver.close()

导入完成后,在 Neo4j Browser 里执行:

MATCH (n:Entity) RETURN n LIMIT 100

如果能看到实体节点和关系线,图谱就建起来了。这里容易翻车的是导入字段名不对,GraphRAG 不同版本的 parquet 列名略有差异,建议先print(entities.columns)确认完再跑。

导入脚本刚跑完时,图谱里可能有大量重复节点,比如“总公司”和“北京总公司”。要么在抽取提示词里强调“同名实体合并”,要么在导入时写一个简单的实体对齐规则。我的做法是导入后执行一次 Cypher 合并:

MATCH (a:Entity), (b:Entity) WHERE a.name = b.name AND id(a) < id(b) MERGE (a)-[r:ALIAS]->(b)

不过这种对齐规则要看具体数据形态,别盲跑大数据集,会卡住。

3.4 实现本地问答接口

图谱数据和文本向量都准备好之后,最后一步就是把它们联合起来接 LLM。推荐先用 GraphRAG 自带的查询命令验证:

graphrag query --root . --method global --query "XX项目使用了哪些关键技术?"

它会做全局搜索,利用社区摘要回答。但全局搜索对小型私有知识库来说太重了,我更常用“本地搜索”加自定义图遍历的方式。下面给出一个直接用 Python 调 Ollama 的问答实现。

import os from openai import OpenAI from neo4j import GraphDatabase client = OpenAI( base_url="http://localhost:11434/v1", api_key="ollama" ) driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "your_password")) def extract_entity_with_llm(question: str) -> str: prompt = f"从问题中抽取核心实体,只返回实体名:{question}" resp = client.chat.completions.create( model="qwen2.5-7b-chat", messages=[{"role": "user", "content": prompt}], temperature=0 ) return resp.choices[0].message.content.strip() def query_graph(entity: str, hops: int = 2): cypher = """ MATCH (a:Entity {name: $entity})-[r*1..%d]-(b:Entity) RETURN a, b, r LIMIT 100 """ % hops with driver.session() as session: results = session.run(cypher, entity=entity) return [record.data() for record in results] def ask(question: str) -> str: entity = extract_entity_with_llm(question) graph_res = query_graph(entity) context = f"问题:{question}\n实体:{entity}\n图谱检索结果:{graph_res}\n" messages = [ {"role": "system", "content": "你是一个企业知识库问答助手,请根据给定上下文中出现的事实回答问题,不要编造。若上下文不足,直接回答无法从知识库找到答案。"}, {"role": "user", "content": context} ] resp = client.chat.completions.create( model="qwen2.5-14b-chat", messages=messages, temperature=0.2 ) return resp.choices[0].message.content

这里做了三步:先调 LLM 抽实体,再根据实体查 Neo4j 图路径,最后把路径结果拼入 prompt 让大模型回答。实际效果比单纯向量召回更接近“关系型”答案。

想做成线上服务,用 FastAPI 包一层:

from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class Query(BaseModel): question: str @app.post("/qa") def qa(query: Query): return {"answer": ask(query.question)}

然后运行:

uvicorn qa_server:app --host 0.0.0.0 --port 8000

局域网内其他服务就可以通过POST http://你的IP:8000/qa调用这个提问接口。

4. 常见问题与调优笔记

4.1 Ollama 下载慢、安装包获取难怎么破

这是本地部署里最普遍的问题之一。安装包体积、模型权重动辄几个 GB,一旦网络不稳定就前功尽弃。我的处理顺序是:官网下载安装包如果太慢,先找一个靠谱的网盘或镜像站下载同样的安装包,但下载完必须校验哈希值,防止文件损坏或被人改动。

模型下载同理。ollama pull如果卡在waiting for server或者下载到 90% 报错,最好别反复重试,改成从国内模型平台下载 GGUF 文件,然后通过Modelfile导入。这个方法基本一次成功。

还有一个需要留意的点是:用ollama create导入模型时,如果提示file does not exist,说明 Modelfile 里的FROM路径写错了。改成相对路径并确认文件确实在那个目录。Windows 下路径要用./开头,不要带盘符。

4.2 显存不足与 OOM 问题

跑抽取任务时,Ollama 进程会突然消失,或者终端输出Killed,十有八九是显存不够触发了系统 OOM。解决思路:

  • 换更小模型或量化级别,比如从q4_k_m换到q3_k_m。
  • 限制上下文长度,在 Modelfile 里设置PARAMETER num_ctx 4096。
  • 关闭并行加载,设置环境变量OLLAMA_MAX_LOADED_MODELS=1。
  • 让抽取和问答共用同一个模型时,两个任务别同时跑,否则模型会被反复调度。

查看显存占用用nvidia-smi,重点看Memory Usage和GPU-Util。我见过不少同事以为显存爆了,其实是num_ctx设置过大导致 KV Cache 占了大部分显存,调低后立刻能跑。

4.3 知识图谱效果不好怎么办

实体抽取质量差是最容易让新手心态崩溃的问题。症状通常是:实体识别不全、关系类型太泛、节点重复率高。

优先检查你的提示词。默认 GraphRAG 提示词对英文友好,处理中文时我会专门调整抽取提示词,明确加入中文实体类型和示例。此外,模型输出 JSON 时偶尔会少括号,建议在max_tokens上给足余量。

如果数据量很大,可以把文本拆小一点,分多次抽取,再做实体合并。比如每块 400 字,重叠 50 字,能显著提升实体召回率。但代价是抽取时间变长,需要做时间换质量。

另一个容易忽略的问题是:知识图谱抽取结果的质量上限,取决于你的文档“是否真的包含关系描述”。如果原文写作风格特别碎片化,没有主语、没有逻辑连接词,那模型再强也抽不出合理关系。我一般会先把这类文档做一轮“改写”预处理,把它变成逻辑清晰的段落,再喂给抽取管线。

4.4 检索效果和回答质量的调优

图谱答案错误或回答偏题,不一定是大模型能力问题,更多是检索上下文不够准。我建议按以下顺序调:

  • 先确认实体识别是否准确。问题里的实体名和图谱里的节点名如果不一致,后续一概查不到。
  • 再确认图谱遍历的跳数。跳数太少会漏,跳数太多会把无关路径都拉进来,噪音剧增。我常用 1 到 2 跳,最多 3 跳。
  • 然后确认向量检索阈值。如果混合了向量召回,误召回太多反而干扰大模型,可以设定相似度阈值,低于阈值的片段直接过滤。
  • 最后调 prompt。不要把图谱原始 JSON 直接扔给模型,先清洗成“A 和 B 之间存在某关系”这种自然语言描述,模型理解起来更省力。

实际调试时,我还会给问答接口加日志,把每次请求的实体、图谱路径、向量片段、最终 prompt 都记录下来。这样用户说效果差,直接看日志就知道是卡在“没抽到实体”还是“图路径为空”还是“prompt 太乱”,不用瞎猜。

这套系统我跑了小半个月,最大的体会是:GraphRAG 真正难的点不在模型选型,而在“怎么把图谱建模得恰到好处”。实体粒度太粗,问题答不细;粒度太细,图谱爆炸;检索跳数太广,上下文全是噪音。这个度没有标准答案,只能拿着自己的文档一遍遍调。但只要你把这条链路跑通,企业里大部分“跨文档关系型”问题,它都能给出比传统 RAG 扎实得多的答案。如果让我重新搭一遍,我会先把抽取提示词和文档预处理做扎实,再着急上图谱和向量,后面维护成本会低很多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 9:22:44

企业级图书管理系统实战:SpringBoot+Vue+MyBatis+MySQL全栈改造指南

这几年我接手了不少贴着"企业级"标签的图书管理系统源码&#xff0c;标题一个比一个完整&#xff1a;SpringBootVueMyBatisMySQL&#xff0c;看起来该有的都有。可真把源码下载下来本地启动一遍&#xff0c;能一次跑通的少得可怜——数据库脚本跟实体类字段对不上、M…

作者头像 李华
网站建设 2026/10/3 9:22:44

基于Java与Spark2x的新闻网大数据实时可视化系统实现

简介&#xff1a;基于Java与Spark2x技术栈的新闻网大数据实时分析可视化系统项目&#xff0c;面向大数据相关课程设计、毕业设计及需要掌握实时处理链路的开发者。项目围绕新闻数据采集、流式处理、结果存储与Web可视化展开&#xff0c;可帮助理解从Kafka接入、Spark流计算到HB…

作者头像 李华
网站建设 2026/10/3 9:22:33

SpringBoot+Vue图书进销存系统设计与实战:从进销存到库存预警

1. 项目概述与背景认知图书进销存管理系统&#xff0c;乍一听像是个传统的仓库管理软件&#xff0c;但真正动手做过的人都知道&#xff0c;它其实是进销存体系里最典型、也最适合练手的一类业务系统。进货、销货、存货三个环节环环相扣&#xff0c;再加上图书本身具备的ISBN、分…

作者头像 李华
网站建设 2026/10/3 9:22:30

MES整合IIOT实战:从设备数据采集到智能工厂落地

一条47页的PPT方案拿出来给客户讲&#xff0c;需求这事儿其实早就不新鲜了——产线上设备的数据上不来&#xff0c;上来了又跟MES对不上账&#xff0c;车间主任看报表还是靠Excel。这标题里的"MES整合IIOT"&#xff0c;说白了就是两件事&#xff1a;第一&#xff0c;…

作者头像 李华
网站建设 2026/10/3 9:21:07

混合云弹性伸缩实战:一个伸缩组统一管理IDC托管实例与ECS

做渠道商和代运维久了&#xff0c;你会碰上一个特别拧巴的场景&#xff1a;客户机房里那几台老物理机&#xff0c;业务跑得好好的&#xff0c;舍不得扔&#xff1b;但一到促销季、月初报表日&#xff0c;CPU就飙到95%&#xff0c;又必须上阿里云补容量。以前我都是两套班子两套…

作者头像 李华
网站建设 2026/10/3 9:21:04

全覆盖路径规划算法对比与工程实践:从牛耕法到深度强化学习

做全覆盖路径规划&#xff08;Complete Coverage Path Planning&#xff0c;简称CPP&#xff09;这个方向&#xff0c;前后折腾了快三年。从最开始的扫地机器人 demo&#xff0c;到后面做农业植保机器人和仓储 AGV 的项目&#xff0c;几乎把主流的覆盖算法都过了一遍。尤其是“…

作者头像 李华