前言:为什么我要写这篇文章
最近在规划企业AI中台时,我面临一个选择:是用Dify、LangChain等开源框架快速搭建,还是自研一套更贴合业务的技术方案?
经过深入调研和思考,我选择了一条看起来更"笨"但长期更灵活的路------基于Palantir本体论思想,自研一套本体驱动的Agent智能中台。
本文不是广告,也不是理论空谈,而是一份可以直接落地的技术方案,包含架构设计、目录结构、核心代码和落地路线图。希望能给同样在探索企业AI落地的同行一些参考。
一、业务背景与核心诉求
我们公司已有ERP、MES、PLM等成熟系统,但存在一个典型问题:数据分散,查询困难。
业务人员想查一个"本月产线3的良率为什么下降",需要在三个系统间来回切换,手动导出数据、用Excel关联分析,耗时半天。
我们的目标是:搭建一个统一的Web入口,用户通过自然语言对话,AI自动完成以下四件事:
- 智能检索(跨系统找数据)
- 统计分析(自动汇总计算)
- 根因分析(找出问题原因)
- 行动建议(给出可执行方案)
核心理念:不是预设工作流(写死A→B→C),而是基于本体论(Ontology)配置业务知识,让AI自主决策该查什么、怎么查、用什么API。
二、为什么放弃纯工作流编排方案?
一开始我考虑过Dify这类工作流编排工具,但很快意识到一个问题:
| 对比项 | 工作流编排 | 本体论驱动(本文方案) |
|---|---|---|
| 路径确定方式 | 人工预设每一步 | AI实时推理决策 |
| 遇到未覆盖问题 | 报错或答不上来 | AI尝试组合现有工具解决 |
| 新增业务场景 | 新增一条工作流分支 | 只需更新本体定义 |
| 维护成本 | 随场景增多线性增长 | 随本体完善趋于稳定 |
| 是否"写死" | ✅ 本质是If-Else升级版 | ❌ 真正的智能体 |
结论:工作流编排适合流程固定、场景有限的RPA类需求,而我们想要的,是真正的AI智能体。
三、整体架构设计
3.1 四层架构
┌─────────────────────────────────────────────────────────┐
│ Web 对话入口 │
│ (Streamlit / FastAPI + HTML) │
├─────────────────────────────────────────────────────────┤
│ Agent 自主决策层 │
│ (LangChain ReAct Agent + LLM) │
│ 思考 → 选择工具 → 调用API → 分析 → 建议 │
├─────────────────────────────────────────────────────────┤
│ 本体论语义层 │
│ skill.md + references/*.md(业务概念地图) │
│ 实体定义 | 属性 | 关联关系 | API清单 | 权限 | 规则 │
├─────────────────────────────────────────────────────────┤
│ 数据与API层 │
│ ERP API │ MES API │ PLM API │ 其他系统 │
└─────────────────────────────────────────────────────────┘
3.2 核心设计理念
把业务知识从代码中剥离出来 ,放到本体文件中。业务人员可以直接阅读和修改skill.md和references/*.md,而不需要懂代码。
Agent启动时自动加载这些本体文件,就像给AI配备了一张完整的业务地图。用户提问后,AI自己在地图上找路、决定调用哪些API、以什么顺序组合。
四、目录结构与文件规范
/ai-agent-platform
├── /agent_core
│ ├── agent.py # 主Agent逻辑(ReAct循环)
│ ├── tool_retriever.py # 根据问题检索相关工具
│ └── llm_client.py # LLM客户端封装
│
├── /web_ui
│ ├── app.py # FastAPI服务
│ └── templates/ # 前端页面
│
├── /ontology # ⭐ 核心:本体定义目录
│ ├── skill.md # 系统总览(给Agent的"目录")
│ └── /references
│ ├── erp.md # ERP实体、属性、API
│ ├── mes.md # MES实体、属性、API
│ ├── plm.md # PLM实体、属性、API
│ └── cross_system.md # 跨系统关联规则
│
└── /api_proxy # 统一API网关(鉴权、路由)
五、核心文件内容示例
5.1 skill.md ------ 系统总览
markdown
# 企业AI智能中台 - 本体总览
## 系统清单
| 系统 | 简称 | 核心职责 |
|------|------|----------|
| ERP | 企业资源计划 | 订单、库存、采购、财务 |
| MES | 制造执行系统 | 工单、良率、设备状态、产线 |
| PLM | 产品生命周期管理 | BOM、物料规格、设计变更 |
## 核心业务实体(跨系统)
- **物料(Material)**:ERP有库存,PLM有规格,MES有消耗
- **工单(WorkOrder)**:ERP下达,MES执行,PLM关联BOM
- **设备(Equipment)**:MES采集状态,PLM记录维护
## 典型分析场景
- "本月良率下降原因" → MES良率 + ERP物料批次 + PLM设备维护
- "A物料够不够生产" → ERP库存 + MES消耗速率 + PLM BOM用量
5.2 references/erp.md ------ 详细本体定义
markdown
# ERP系统 - 本体定义
## 实体:Material(物料)
- **属性**:
- materialCode(string,唯一标识)
- name(string)
- safetyStock(float,安全库存)
- **链接**:
- consumedBy → MES.WorkOrder
- belongsToBOM → PLM.BOM
- **权限**:所有用户可查库存,仅采购可修改
## API列表
| API名称 | 端点 | 方法 | 参数 | 返回 |
|---------|------|------|------|------|
| 查询库存 | /api/erp/inventory | GET | materialCode | {quantity, warehouse} |
| 查询采购单 | /api/erp/purchase | GET | supplier? status? | [PurchaseOrder] |
## 业务规则
- 安全库存预警:inventory < safetyStock → 建议补货
5.3 references/cross_system.md ------ 跨系统关联
markdown
# 跨系统关联规则
## 实体映射
| 业务概念 | ERP | MES | PLM |
|---------|-----|-----|-----|
| 物料编码 | materialCode | materialId | partNumber |
## 关联查询规则
- 查询工单物料消耗:MES.WorkOrder.materialId → ERP.Material.materialCode → 查库存
- BOM展开:ERP.Material → PLM.BOM.partNumber → 子物料列表
六、核心代码实现
6.1 Agent核心逻辑(agent.py)
python
import os
import json
from langchain.agents import create_react_agent, AgentExecutor
from langchain.tools import Tool
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
# ============ 1. 加载本体文件 ============
def load_ontology():
"""加载 skill.md 和所有 references/*.md"""
with open("ontology/skill.md", "r", encoding="utf-8") as f:
skill_content = f.read()
refs = {}
ref_dir = "ontology/references"
for file in os.listdir(ref_dir):
if file.endswith(".md"):
with open(f"{ref_dir}/{file}", "r", encoding="utf-8") as f:
refs[file] = f.read()
return skill_content, refs
# ============ 2. 从本体动态生成工具 ============
def build_tools_from_ontology():
"""解析 references/*.md 中的 API列表,自动生成 LangChain Tools"""
tools = []
# 这里简化演示,实际需解析Markdown中的API表格
# 真实场景:遍历所有reference文件,提取API定义
# 然后为每个API生成一个Tool函数
# 示例:手动创建一个库存查询Tool
def query_inventory(material_code: str) -> str:
"""查询物料库存,参数material_code为物料编码"""
# 实际调用ERP API
response = requests.get(
f"http://erp.internal/api/inventory?code={material_code}",
headers={"Authorization": os.getenv("ERP_TOKEN")}
)
return response.text
tools.append(Tool(
name="query_inventory",
func=query_inventory,
description="查询物料库存,输入物料编码,返回库存数量和仓库位置"
))
# 更多工具通过解析本体文件自动生成...
return tools
# ============ 3. 创建Agent ============
def create_agent():
skill_content, refs = load_ontology()
llm = ChatOpenAI(
model="deepseek-chat", # 或 gpt-4
api_key=os.getenv("LLM_API_KEY"),
base_url=os.getenv("LLM_BASE_URL")
)
tools = build_tools_from_ontology()
# 系统提示词:将skill.md作为业务上下文注入
system_prompt = f"""
{skill_content}
你是一个企业智能助手,拥有以下工具:
{{tools}}
请遵循ReAct模式(思考→行动→观察):
1. Thought:理解用户问题,确定需要哪些数据
2. Action:选择并调用合适的工具
3. Observation:分析工具返回的结果
4. 重复1-3直到信息充足
5. 最终给出结论和行动建议
用户权限已在API调用时自动校验,你无需担心。
"""
prompt = PromptTemplate.from_template(system_prompt)
agent = create_react_agent(llm, tools, prompt)
return AgentExecutor(agent=agent, tools=tools, verbose=True)
# ============ 4. Web接口 ============
app = FastAPI(title="AI智能中台")
agent = create_agent()
class ChatRequest(BaseModel):
question: str
user_id: str
@app.post("/chat")
def chat(request: ChatRequest):
try:
# 注入用户身份(用于后续权限控制)
response = agent.invoke({
"input": request.question,
"user_id": request.user_id
})
return {
"code": 0,
"data": {
"answer": response["output"],
"steps": response.get("intermediate_steps", [])
}
}
except Exception as e:
return {"code": -1, "message": str(e)}
# ============ 5. 启动服务 ============
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8080)
6.2 前端页面(templates/chat.html)
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>AI智能中台</title>
<style>
body { font-family: Arial; max-width: 800px; margin: 0 auto; padding: 20px; }
#chat-box { height: 500px; overflow-y: auto; border: 1px solid #ddd; padding: 15px; border-radius: 8px; }
.user { text-align: right; color: #1890ff; margin: 10px 0; }
.assistant { text-align: left; color: #333; margin: 10px 0; background: #f5f5f5; padding: 10px; border-radius: 8px; }
#input-area { display: flex; margin-top: 15px; gap: 10px; }
#question { flex: 1; padding: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: 16px; }
#send { padding: 12px 30px; background: #1890ff; color: white; border: none; border-radius: 8px; cursor: pointer; }
.loading { color: #999; font-style: italic; }
</style>
</head>
<body>
<h1>🏢 AI智能中台</h1>
<p style="color:#666;">用自然语言提问,AI自动跨系统检索、分析、给出建议</p>
<div id="chat-box"></div>
<div id="input-area">
<input type="text" id="question" placeholder="例如:本月产线3的良率为什么下降了?">
<button id="send" onclick="sendQuestion()">发送</button>
</div>
<script>
async function sendQuestion() {
const input = document.getElementById('question');
const chatBox = document.getElementById('chat-box');
const question = input.value.trim();
if (!question) return;
// 显示用户消息
chatBox.innerHTML += `<div class="user">👤 ${question}</div>`;
input.value = '';
// 显示加载状态
const loadingId = Date.now();
chatBox.innerHTML += `<div class="assistant loading" id="loading-${loadingId}">🤔 思考中...</div>`;
chatBox.scrollTop = chatBox.scrollHeight;
try {
const resp = await fetch('/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ question, user_id: 'demo_user' })
});
const result = await resp.json();
// 移除加载状态
document.getElementById(`loading-${loadingId}`).remove();
if (result.code === 0) {
chatBox.innerHTML += `<div class="assistant">🤖 ${result.data.answer}</div>`;
} else {
chatBox.innerHTML += `<div class="assistant">❌ 错误:${result.message}</div>`;
}
} catch (e) {
document.getElementById(`loading-${loadingId}`).remove();
chatBox.innerHTML += `<div class="assistant">❌ 网络错误,请稍后重试</div>`;
}
chatBox.scrollTop = chatBox.scrollHeight;
}
document.getElementById('question').addEventListener('keydown', (e) => {
if (e.key === 'Enter') sendQuestion();
});
</script>
</body>
</html>
七、落地路线图(5周计划)
| 阶段 | 时间 | 目标 | 交付物 |
|---|---|---|---|
| Demo验证 | 第1周 | 接ERP 2-3个API,跑通"问库存→调API→回答" | 可演示的对话原型 |
| 本体完善 | 第2周 | 补全ERP/MES/PLM的references文件 | 完整本体定义 |
| Agent优化 | 第3周 | 调整Prompt,加入错误处理、重试机制 | 稳定版Agent |
| 权限+安全 | 第4周 | 接入企业SSO,API调用注入用户身份 | 安全合规版本 |
| 上线推广 | 第5周 | 业务试用,迭代本体定义 | 生产可用版本 |
八、关键注意事项
8.1 本体质量决定Agent上限
本体文件写得越清楚,Agent越聪明。建议拉着业务人员(生产主管、采购经理)一起写,他们用业务语言描述"怎么看数据",你负责转译成本体格式。
8.2 API规范化是前置条件
各系统API必须有清晰文档(至少是Swagger/OpenAPI格式),参数命名统一。否则Agent无法理解API的用途和参数含义。
8.3 数据不迁移,只做联邦查询
ERP/MES/PLM的数据留在原系统,通过API或只读视图暴露,避免数据迁移风险。
8.4 分阶段开放能力
- 第一阶段:只读(检索+统计)
- 第二阶段:分析建议
- 第三阶段:自动执行(需要严格审批流)
九、方案优势总结
| 对比维度 | 商业套件(如Palantir) | 开源框架(如Dify) | 本方案 |
|---|---|---|---|
| 成本 | 极高(千万级) | 免费 | 免费(仅LLM API费用) |
| 灵活性 | 受限于产品功能 | 受限于框架设计 | 完全自主控制 |
| 本体驱动 | ✅ 原生支持 | ❌ 需二次开发 | ✅ 自主实现 |
| 业务人员可维护 | ✅ 图形化编辑 | ❌ 需改代码 | ✅ 编辑Markdown即可 |
| 数据主权 | 数据上云 | 可私有化 | 完全本地私有 |
十、总结
本文分享的方案,本质上是用AI编程工具(Cursor)+ 本体论思想 + Agent模式,自研一套企业级AI智能中台。
核心亮点在于:
- 把业务知识从代码中剥离到本体文件,业务人员可直接维护
- Agent自主决策而非预设工作流,真正实现智能化
- 完全开源私有化部署,过程数据不出企业