OrgGraph AI:一种无需硬编码的、专为人力资源数据设计的智能知识图谱。
大语言模型如何从任何Excel或CSV文件中识别图表结构,利用动态Cypher语句将其加载到Neo4j中,并通过LangGraph聊天机器人回答人员配置相关问题。
来源: Building a Fully Agentic Employee Knowledge Graph: **OrgGraph AI — using LangGraph & Neo4j**
大型企业掌握的员工数据比以往任何时候都多,但人员配置依然依赖猜测。人力资源相关数据存储在Workday系统中,项目分配信息则存放在Jira中,而技能、熟练程度及认证资料却仍留在旧版的培训平台上。一旦有高优先级的AI项目出现,项目负责人就会询问孟买或浦那办事处中谁具备高级Python技能、持有AWS认证、了解AI/ML技术、有过银行项目经验,且还有空余精力承担这项工作。
即便真的要寻找这样的人选,也需要大约一周的时间。相关数据确实存在,但却分散在各个独立的系统中,无法相互关联分析。
OrgGraph AI正是为填补这一空白而设计的系统。它能够接收任何Excel或CSV格式的原始组织数据,由大语言模型自行分析并构建图结构,再将所有数据加载到Neo4j中,最终以通俗的语言回答问题。系统中没有任何硬编码的领域逻辑。
关系比记录更重要
传统的人力资源工具基于扁平的SQL表格运行。对于查询班加罗尔的所有员工或所有会使用Python的人,这类操作对他们来说很简单。但一旦遇到需要同时考虑多维度关系的复杂问题,他们就会束手无策。而知识图谱则能实现四种类型的操作:
- 精准的人员配置。只需一次遍历即可找到同时具备技能A、证书B、工作地点C且有空闲时间的人,而无需进行四次独立的连接操作。
零硬编码的含义
大多数知识图谱项目都藏着同一个棘手的秘密:其架构是硬编码的。工程师会查看电子表格,确定员工和技能都是节点,再用HAS_SKILL边将它们连接起来,为每个实体编写自定义的Cypher语句并投入使用。但一旦人力资源部门新增了Certifications表格,或将PrimarySkill重命名为TechStack,整个流程就会停止运行。
OrgGraph AI则颠覆了这一模式。由大型语言模型决定架构应为何种形式。对于任何表格文件,该系统都会:
- 分析数据,包括列类型、基数以及可能的外键
- 通过Pydantic验证后,利用结构化的大型语言模型输出推断出图谱架构
- 动态生成并执行Cypher的
MERGE查询语句 - 分析生成的图谱结构,以便聊天机器人能够对其进行查询
没有人会手动绘制任何图表,也不存在预先写好的代码。明天若将人力资源数据替换为供应链物流数据,同一个代码库就能生成完全不同的图结构。测试数据集是合成的,大约有十几张表格,而处理流程会原封不动地接收所有输入数据。
四个阶段
该系统通过 Python、LangChain、LangGraph、Pydantic 和 Neo4j 共同协作,分四个阶段运行。
第一阶段:元数据分析
在启用任何大型语言模型之前,MetadataProfiler 会先在本地分析原始数据,并生成一个简洁的结构特征指纹。这是出于隐私保护的刻意设计——真实的员工记录永远不会传送到模型中。该工具能获取列名、数据类型、每列的不同值数量以及一些样本值。
性能分析工具最实用的技巧是自动检测外键。当某列的值大多出现在其他地方的主键列中时,该工具会将该列标记为可能的外键:
# Simplified FK detection logic from profiler.py
overlap = col_values & ref_values
if len(overlap) / len(col_values) >= 0.8:
fk_candidates.append({
"source_table": tname,
"source_column": col,
"target_table": ref_table,
"target_column": ref_col,
"match_pct": round(len(overlap) / len(col_values) * 100, 1),
})
在HR数据集中,这一情况表明Employees表中的Manager_Employee_ID与Employee_ID的匹配度超过80%,这暗示存在自引式的REPORTS_TO关系。这一线索指向了大型语言模型,因为仅凭列名无法推断出层级结构。
第二阶段:模式发现
该任务会交由大型语言模型处理,可选择OpenAI GPT-4o、Google Gemini或Groq作为模型,同时通过提示词将其设定为主图数据库架构师。
核心工程难题在于大型语言模型生成的是自由形式的文本,而图数据库则需要严格的结构。LangChain的with_structured_output()功能通过强制模型返回经过验证的Pydantic对象,从而弥合了这一差距:
# The LLM is coerced to return this exact structure
class GraphMappingModel(BaseModel):
nodes: List[NodeMapping] # What becomes a Node?
relationships: List[RelationshipMapping] # What becomes an Edge?
notes: str # LLM's reasoning notes
class NodeMapping(BaseModel):
label: str # e.g., "Employee"
source_table: str # e.g., "Employees"
primary_key_column: str # e.g., "Employee_ID"
properties: List[PropertyMapping] # All columns to map
class RelationshipMapping(BaseModel):
type: str # e.g., "HAS_SKILL"
from_node_label: str # e.g., "Employee"
to_node_label: str # e.g., "Skill"
from_key_column: str # FK column in source table
to_key_column: str # PK column of target node
properties: List[PropertyMapping] # Edge properties
GraphMappingModel充当整个系统的契约。模式生成器负责创建它,而数据导入引擎则使用它。如果验证失败,会再次请求大语言模型处理,因此不会有格式错误的模式被传送到Neo4j。
第三阶段:动态Cypher导入
在模式通过验证后,引擎会即时生成参数化的Cypher语句。无需模板,也不存在针对每种实体类型的条件判断语句。它会读取映射关系,为每种节点类型和关系类型分别生成MERGE及SET语句:
# Dynamically generated Cypher from the mapping — zero hardcoding
UNWIND $rows AS row
MERGE (n:Employee {employee_id: row.employee_id})
SET n.full_name = row.full_name,
n.designation = row.designation,
n.date_of_joining = row.date_of_joining,
n.annual_ctc_lpa = toFloat(row.annual_ctc_lpa)
由于推断出的模式包含主键,引擎会使用MERGE而非CREATE,这使得处理流程具有幂等性。对相同数据执行三次操作仍会得到相同的图结构且不会产生重复项。此外,该引擎还会进行类型转换(toInteger()、toFloat())、将NaN转换为None,并跳过主键为null的行。
演示数据集并非简单模型:包含13个相互关联的表,涉及151名员工,数据包括935条技能映射、285项项目分配、107份认证信息、313条评价以及453条培训记录,这些数据分布在10个部门及10家全球办事处中。
第四阶段:智能GraphRAG聊天功能
聊天层不仅仅是文本到Cypher语句的转换工具,它还是一个内置错误恢复功能的四节点LangGraph状态机:
User Question
↓
┌─────────────┐
│ Planner │ → Analyzes intent, extracts entities, maps to schema
└──────┬──────┘
↓
┌─────────────┐
│ CypherGen │ → Generates Cypher query using schema + few-shot examples
└──────┬──────┘
↓
┌─────────────┐ ┌─── Error? ───→ Retry CypherGen (up to 2x)
│ Executor │ ────┤
└──────┬──────┘ └─── Success ──→
↓
┌──────────────┐
│ Synthesizer │ → Formats raw graph data into natural language
└──────────────┘
有三个特性使其具备良好的适应性。
运行时模式自检。在启动时,该代理会从Neo4j获取实时模式信息,包括存在的节点类型、关系类型、它们的属性以及彼此之间的连接方式。这些模式信息会被纳入每个查询提示中,因此代理无需预先假设数据库中包含什么内容。
自动生成的少量示例。许多GraphRAG系统会硬编码Cypher查询示例。而此处,大型语言模型会根据实时模式信息和抽样数据自行编写少量示例,并且在新的数据上传导致模式变化后,这些示例会自动重新生成。
具备错误感知的重试机制。如果生成的查询失败,错误信息会反馈到CypherGen节点,该节点会修正查询并再次尝试,最多可进行两次。这使代理在面对边缘情况下的语法问题时具有很强的容错能力。
企业级考量
隐私保护。大型语言模型只能识别结构而非具体人员。只有列名、数据类型和基数等信息会传递给分析工具,个人数据仍保留在您的服务器上。
供应商灵活性。通过采用LLM Factory模式,只需更改一个环境变量即可在这类大型语言模型服务之间切换,例如从OpenAI切换到Gemini或Groq。
# .env: LLM_PROVIDER=gemini | openai | groq
llm = get_llm() # Returns the configured ChatModel
无需修改代码,也不会陷入供应商锁定。
杂乱的数据。企业中的电子表格从来都不整洁。数据导入引擎能够处理尾随空格、混合的日期格式、意外的NaN值以及空的主键,它会跳过或转换有问题的行,而不会崩溃。
从上传到结果
前端是一个Streamlit控制面板。用户可以在侧边栏上传Excel或CSV文件,实时查看整个处理流程:数据分析、模式识别、数据导入,再到代理初始化。之后,用户就可以直接进行对话了。
另一个演示案例使用Vis.js实现基于物理原理的图表渲染,再结合GSAP实现滚动触发的动画效果。节点会通过重力和斥力作用逐个呈现出来。点击任意节点即可打开一个面板,显示该节点的属性及关联关系。模拟聊天功能则会同时展示自然语言回复以及其背后的Cypher查询语句。
应用范围超越人力资源领域
该架构并不局限于人力资源领域。同样的代码可用于构建IT资产管理的知识图谱,从而映射服务器、应用程序、团队及它们之间的依赖关系。它还能用于追踪供应链中的供应商、原材料、仓库及物流路线,或在研究网络中连接研究人员、论文、机构及资金来源。
代理架构正朝着让数据管道适应数据而非工程师将数据强行塞入固定模式的方向发展,而这个项目正是其实现方案之一。