办公文档
把 PDF/HTML/Markdown 等非结构化文档导入…
需要将非结构化或半结构化文档切块、抽取实体关系并写入 Neo4j 形成 Document→Chunk→Entity 知识图谱时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
把 PDF/HTML/Markdown 特定
解决思路
- 先按场景选方案:无代码拖拽用 LLM Graph Builder Web UI;程序化处理 PDF/文本用 SimpleKGPipeline(neo4j-graphrag);JSON/REST 响应用 apoc.load.json 或 Python+UNWIND;已有 LangChain 用 Neo4jGraph+文档加载器;已有 LlamaIndex 用 Neo4jQueryEngine/Neo4jVectorStore;只切块不抽实体则手动切块+MERGE。
- 安装依赖:pip install neo4j-graphrag(含 SimpleKGPipeline),按 LLM 供应商加 extra,如 [openai]、[anthropic]、[google]、[bedrock]、[ollama]、[mistralai];模糊匹配加 [fuzzy-matching];spaCy 解析器加 [nlp](仅 Python<=3.13)。要求 neo4j>=5.17.0、Python>=3.10、Neo4j>=5.18.1。
- 先定义图 schema 再建 pipeline:Option A 用 entities/relations/patterns 字符串列表(LLM 推断描述,适合原型);Option B 用 GraphSchema+NodeType+RelationshipType+PropertyType+ConstraintType(生产环境、抽取质量最好);Option C 用 schema="EXTRACTED"(LLM 推断类型)或 "FREE"(无约束,噪声最大),仅用于探索。
- 构建 SimpleKGPipeline:传入 llm、driver、embedder、schema、from_file=True(传文本时用 False 并改用 text=)、on_error="IGNORE"(要暴露失败用 RAISE)、perform_entity_resolution=True、neo4j_database。LLM 可换 AnthropicLLM、VertexAILLM、OllamaLLM(本地无需 key)、BedrockLLM。注意 OpenAI/VertexAI 会自动启用结构化输出,不要手动设 response_format。
- 运行 pipeline:PDF 用 asyncio.run(pipeline.run_async(file_path="report.pdf", document_metadata={...})) 自动走 PdfLoader;Markdown 同理走 MarkdownLoader;原始文本用 text=document_text;批量则循环 await pipeline.run_async(file_path=...)。document_metadata 会写成 :Document 节点属性。注意 from_pdf=True 自 v1.15.0 起已废弃,改用 from_file=True。
- 配置切块:默认 FixedSizeSplitter(chunk_size=300, chunk_overlap=50)。可自定义 chunk_size(密集技术文 256–512、叙事/新闻 512–1024、法律/金融 256–384)、chunk_overlap(约 chunk_size 的 10–15%)、approximate=True(尽量按句子/词边界切)。chunk 必须同时适配 LLM 上下文和 embedding 模型上限,绝不超过 2048。
- 运行实体解析合并重复实体:SinglePropertyExactMatchResolver(同名合并,最快基线)、FuzzyMatchResolver(driver, threshold=0.9)(处理拼写差异,需 rapidfuzz)、SpaCySemanticMatchResolver(余弦相似,需 [nlp])。可用 filter_query="WHERE n:Organization OR n:Person" 限定标签。应在批量导入后统一运行,不要内联执行。
- 理解生成的图结构:词法层为 (:Document)-[:HAS_CHUNK]->(:Chunk)-[:NEXT_CHUNK]->(:Chunk),并有 (:Chunk)-[:FROM_DOCUMENT]->(:Document) 反向指针;实体抽取再加 (:Chunk)-[:MENTIONS]->(:Person/:Organization) 以及实体间关系如 (:Person)-[:WORKS_AT]->(:Organization)。
- 导入后用 Cypher 验证:MATCH (d:Document)-[:HAS_CHUNK]->(c:Chunk) RETURN d.fileName, count(c);MATCH (c:Chunk)-[:MENTIONS]->(e) RETURN labels(e)[0] AS type, count(*) ORDER BY cnt DESC。
- 无代码场景用 LLM Graph Builder:托管版 https://llm-graph-builder.neo4jlabs.com/;本地版 git clone https://github.com/neo4j-labs/llm-graph-builder,在 .env 设 OPENAI_API_KEY 等,docker-compose up 后访问 http://localhost:8080。支持 PDF、文本、Markdown、图片、网页、YouTube 字幕、S3/GCS 上传;LLM 支持 OpenAI、Gemini、Claude、Llama3、Diffbot、Qwen。
- 半结构化 JSON 用 APOC:CALL apoc.load.json("https://...") YIELD value UNWIND value.articles AS article CALL (article){ MERGE (d:Document {id: article.id}) SET ... FOREACH (tag IN article.tags | MERGE (t:Tag {name: tag}) MERGE (d)-[:HAS_TAG]->(t)) } IN TRANSACTIONS OF 1000 ROWS。本地文件用 apoc.load.json("file:///import/data.json"),文件须放在 $NEO4J_HOME/import/ 或配置 APOC allowlist。用 RETURN apoc.version() 确认可用。
- LangChain 集成:用 Neo4jGraph 连接,PyPDFLoader 加载,RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=64) 切块,OpenAIEmbeddings 生成向量,再用 driver.execute_query 以 MERGE (doc:Document {id}) CREATE (c:Chunk {...}) CREATE (doc)-[:HAS_CHUNK]->(c) 写入。实体抽取可用 langchain_experimental.graph_transformers 的 LLMGraphTransformer,产出同样的 Document/Chunk/实体模式。
- 导入前先建约束和索引:CREATE CONSTRAINT doc_id_unique FOR (d:Document) REQUIRE d.id IS UNIQUE;chunk_id_unique 同理;person_name_unique、org_name_unique 用于实体去重;CREATE VECTOR INDEX chunk_embeddings FOR (c:Chunk) ON c.embedding OPTIONS {indexConfig: {`vector.dimensions`: 1536, `vector.similarity_function`: 'cosine'}}。用 SHOW INDEXES YIELD name, state WHERE state <> 'ONLINE' 轮询,全部 ONLINE 后才开始导入。
- 常见错误处理:LLM 抽出 schema 外类型→定义明确 entities+patterns 或用 Option B;MissingEmbedderError→即使不做向量检索也必须传 embedder;抽不到实体→减小 chunk_size 或换更大上下文模型;重复实体→批量导入后跑解析器;apoc.load.json 权限拒绝→配置 apoc.import.file.enabled 和 dbms.security.allow_csv_import_from_file_urls;切块断句→设 approximate=True;chunk_size 过大导致超时→GPT-4o 抽取保持 ≤512;SpaCySemanticMatchResolver 在 Python 3.14 失败→改用 FuzzyMatchResolver 或降到 3.13;neo4j-driver 找不到→改用 neo4j 包;NodeType 无属性报 ValidationError→至少加一个 PropertyType(name="name", type="STRING");from_pdf 弃用警告→改 from_file=True;response_format 被忽略→从 model_params 移除,pipeline 自动管理。
- 用 GraphSchema 当前 API(≥1.8.0):entities/relations/potential_schema 已废弃,改用 schema=GraphSchema(node_types=[...], relationship_types=[...], patterns=[...], constraints=[...])。约束类型有 UNIQUENESS、KEY(唯一+非空)、EXISTENCE(非空,替代已废弃的 PropertyType.required),v1.15.0+ 支持复合 KEY(property_names 元组)。
- 自动抽取 schema(v1.15.0+):不传 schema 时 SchemaFromTextExtractor 自动运行;也可显式用 SchemaFromTextExtractor(llm=llm, use_structured_output=True).run(text=sample_text) 从文本推断,或用 SchemaFromExistingGraphExtractor(driver=driver).run() 从已有图推断。
- Parquet 导出(实验性 v1.14.0+):在 Pipeline 中用 ParquetWriter(output_dir="/data/kg_export/") 替代 KGWriter,每个节点标签和关系类型各生成一个 Parquet 文件,元数据含 UNIQUENESS/EXISTENCE/KEY 约束。
- 自定义词法层标签:用 LexicalGraphConfig 覆盖默认值,如 document_node_label="Article"、chunk_node_label="Passage"、node_to_chunk_relationship_type="HAS_ENTITY"、chunk_text_property="content"。除非要与已有图集成,否则保持默认。
- 自定义文档加载器:默认 file_loader 按扩展名自动分发(.pdf→PdfLoader、.md→MarkdownLoader),支持 fsspec URI(s3://、gcs://)。处理 HTML/网页等自定义格式时继承 DataLoader 并实现 async run(filepath, metadata) 返回 LoadedDocument(text=..., document_info=DocumentInfo(path=..., metadata=...)),再传给 SimpleKGPipeline(file_loader=..., from_file=True)。
- 导入前逐项核对:约束已建且 ONLINE、向量索引已建、chunk_size 在 embedding 上限内(≤2048,抽取≤512)、chunk_overlap 为 chunk_size 的 10–15%、使用 Document→HAS_CHUNK→Chunk 模式、document_metadata 填了来源标识、批量导入后跑了实体解析、用 apoc.load.json 时确认 apoc.version()、.env 有 API key 且已加入 .gitignore。
适用边界 · 注意事项
- 结构化 CSV/关系型数据导入不适用,应改用 neo4j-import-skill。
- 导入后的 GraphRAG 检索不适用,应改用 neo4j-graphrag-skill;向量索引创建应改用 neo4j-vector-search-skill;Cypher 查询编写应改用 neo4j-cypher-skill。
- LLM Graph Builder 对表格数据(CSV/Excel)效果差、无法抽取可视化图表,这类场景不要用它。