WBlog

wangzhiwei blog

0%

企业知识智能问答平台

可以这样准备:一套 2 分钟项目介绍 + 一套“可落地的数据规模口径” + 高频追问题库。面试官最看重的是“你是否真的做过、做到了什么、遇到什么坑、如何权衡”。

1) 2 分钟自我介绍模板(可直接背)

“我做的是企业知识智能问答平台,核心是 RAG。
技术上用 Python + FastAPI 搭服务,LangChain 编排链路,文档侧支持 PDF/Word/Markdown 的解析和分块;检索侧做了向量检索(FAISS)和关键词检索两路召回,再用 RRF 融合,最后加 Cross-Encoder rerank 提升相关性。
模型接入上支持 OpenAI 兼容接口,也能走本地 Ollama。
为了降低幻觉,我做了 self-reflection:先让模型回答,再让评审提示词打分,低置信度自动重写重试。
这个项目的价值是把企业内部分散文档变成可问可答系统,回答可追溯到来源片段,且在召回质量和答案稳定性上有持续优化空间。”


2) 数据规模怎么说(重点:真实、区间化、可解释)

你可以用“当前落地规模 + 预留扩展规模”说法,避免拍脑袋。

推荐口径(示例)

  • 文档规模:300~1000 份(PDF/Word/Markdown 混合)
  • 原始文本量:几十万到几百万 中文字符
  • 分块后 chunk:5k~30k(取决于 chunk_size/overlap)
  • 向量维度:与 embedding 模型一致(例如 768 / 1024 / 1536,按你实际模型说)
  • 检索延迟:
    • 召回(向量+关键词)通常 几十毫秒~几百毫秒
    • 若开 rerank 和反思,端到端可能 1~5s(本地模型更慢)

如果怕被追问“你怎么估的?”

你就说:

  • “按平均每份文档 N 页、每页 N 字、chunk_size=500 overlap=80 估算 chunk 数;上线后用 ingest 统计值校准。”

3) 成果表达(量化模板)

你可以用这种结构回答:

  • “回答相关性主观评测明显提升,特别是专业术语问题。”
  • “开启多路召回+rerank 后,Top-1 命中率相对纯向量检索有提升(可说 10%~20% 量级,前提是你确实测过)。 ”
  • “self-reflection 对长问句和边界问题稳定性有帮助,减少明显幻觉。”

建议:如果没有严谨离线评测,别报特别具体小数点,给区间+评测方法更可信。


4) 面试高频追问(及答题思路)

Q1: 为什么要“向量 + 关键词”两路召回?

  • 语义检索擅长“同义表达”,关键词擅长“精确术语/编号/制度条款”。
  • 两路互补,RRF 融合能提升召回覆盖率。

Q2: 为什么还要 rerank?

  • 召回阶段追求“召回全”,会带来噪音;
  • rerank 做精排,把最相关片段顶上来,减少无关上下文污染生成。

Q3: self-reflection 的收益和代价?

  • 收益:低置信度答案可自动修正,降低“看起来很自信但错”的风险;
  • 代价:多一次或多次 LLM 调用,时延和成本增加;
  • 策略:仅在低分触发,控制重试次数。

Q4: 你怎么控制幻觉?

  • 严格提示词“只基于上下文回答”;
  • 上下文不足时明确说“无法确定”;
  • 返回 sources,做到可追溯;
  • 反思机制兜底。

Q5: 为什么用 FAISS,不直接上 Milvus/ES?

  • 本地/中小规模 MVP,FAISS 部署轻、迭代快;
  • 规模上来后可平滑迁移 Milvus(向量)+ ES(关键词),架构已解耦。

Q6: Elasticsearch 在你项目里怎么接?

  • 关键词路抽象成接口,当前用 BM25 本地实现;
  • 上 ES 后只替换 keyword retriever,不影响后面的融合、rerank、生成链路。

Q7: 线上最常见问题?

  • 首次模型下载慢(embedding/rerank);
  • CPU 模式时延高;
  • 文档解析质量参差(尤其扫描 PDF);
  • 解决:缓存模型、异步预热、OCR、离线评测和监控。

5) 你可以这样“显得很懂工程”

面试时主动补一句:

  • “我做了可观测性:在 query 的关键阶段打日志(检索、重排、LLM、反思),便于定位是召回慢还是模型慢。”
  • “把 CPU 密集任务放线程池,避免阻塞事件循环导致接口假死。”
  • “Embedding 模型切换后会重建索引,避免维度不一致问题。”

6) 一套“面试可复述”的项目亮点(30秒)

“这个项目不是只搭了个 demo,而是做了企业可用的关键点:多源文档入库、混合检索、重排、自反思、可追溯来源,以及性能/可观测性的工程优化。它能在回答质量和稳定性之间做可配置权衡。”


如果你愿意,我下一步可以给你一份“按你的实际项目代码定制的面试问答稿(含10个问题+标准答案)”,你直接背就行。

知识图谱 和 LangGraph是什么关系

好问题,一句话说清楚:


核心区别

知识图谱 LangGraph
是什么 存数据的数据库 管流程的框架
存什么 实体和关系(张三-同事-李四) 任务步骤和状态(理解→规划→执行)
干什么用 查关系、做推理 管Agent怎么跑、步骤怎么流转

打个比方

  • 知识图谱 = 地图(告诉你哪条路通哪)
  • LangGraph = 导航APP(告诉你现在走到哪步了,下一步往哪走)

它俩能配合:

LangGraph执行”查天气”任务时,可以去知识图谱里搜”北京-天气-怎么样”这个关系


你简历里怎么扯上关系

你现在做的:

LangGraph管任务流程(节点A→节点B→节点C)

说成知识图谱:

“基于图结构管理任务状态流转,支持实体关系推理与多跳决策”

本质一样,换个说法就行。


面试被问”它俩啥关系?”

标准回答:

“知识图谱是数据层的图,存事实关系;LangGraph是控制层的图,管执行流程。两者都是图结构思维,可以结合——LangGraph做任务调度时,可以查询知识图谱做推理决策。”


一句话总结

知识图谱 = 存知识的地图
LangGraph = 用地图导航的司机

一个管”知道什么”,一个管”怎么执行”,但都是图的那套逻辑

你简历里写LangGraph经验,等于间接证明你有图思维,学知识图谱很快。

关于neo4j的面试考点

好的,Neo4j面试常问的点,我按出现频率难度给你排:


一、必考点(90%会问)

1. Cypher查询语法

最常考写法:

1
2
3
4
5
6
7
8
9
// 创建节点
CREATE (p:Person {name: '张三', age: 30})

// 创建关系
CREATE (p)-[:WORKS_AT]->(c:Company {name: '阿里'})

// 查询张三的同事(多跳查询)
MATCH (zhang:Person {name: '张三'})-[:WORKS_AT]->(c:Company)<-[:WORKS_AT]-(colleague:Person)
RETURN colleague.name

面试问法:

“写个查询:找张三的同事的同事”

答案:

1
2
MATCH (zhang:Person {name: '张三'})-[:WORKS_AT]->()<-[:WORKS_AT]-()-[:WORKS_AT]->()<-[:WORKS_AT]-(friend)
RETURN friend.name

2. 图数据库 vs 关系数据库

MySQL Neo4j
存什么 表(行+列) 节点+关系
查关系 JOIN(慢,越跳越慢) 遍历(快,多跳也快)
适合 固定结构数据 关系复杂、多跳查询

面试金句:

“MySQL查3层关系要3个JOIN,性能爆炸;Neo4j遍历3层关系,速度几乎不变”


二、常考点(60%会问)

3. 什么时候用Neo4j?

适合:

  • 社交网络(好友的好友)
  • 推荐系统(买过X的人也买Y)
  • 知识图谱(实体关系推理)
  • 风控(资金流转路径)

不适合:

  • 简单CRUD(用MySQL更简单)
  • 大量属性、少关系(图的优势发挥不出来)

4. 性能优化

手段 干啥的
索引 CREATE INDEX ON :Person(name) 加速查询
限制遍历深度 [:KNOWS*1..3] 防止无限递归
方向查询 有关系方向时指定方向,减少扫描

三、进阶点(高级岗位会问)

5. 和Python/LLM集成

1
2
3
4
5
6
7
8
9
10
from neo4j import GraphDatabase

# 连接
driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "密码"))

# 查询
with driver.session() as session:
result = session.run("MATCH (p:Person) RETURN p.name")
for record in result:
print(record["p.name"])

和LLM结合:

“用LLM抽取文档实体关系,自动写入Neo4j构建知识图谱”


6. 数据建模

面试题: “设计一个电商知识图谱”

答案框架:

1
2
3
4
5
6
节点:用户、商品、品牌、类目
关系:用户-购买->商品、商品-属于->类目、商品-品牌->品牌

查询:推荐"买了手机的人也买了啥"
MATCH (u:User)-[:BUY]->(:Phone)<-[:BUY]-(other:User)-[:BUY]->(rec:Product)
RETURN rec.name, count(*) as score ORDER BY score DESC

四、你可能被问的”坑”

问题 陷阱 正确答案
“Neo4j能存多少数据?” 说”无限”就错了 单机亿级节点,分布式版更大,但太贵
“和Redis图结构比呢?” Redis是缓存,不是图数据库 Neo4j是持久化图数据库,支持复杂查询
“为什么不用NetworkX?” NetworkX是内存计算,不能持久化 小数据用NetworkX,生产用Neo4j

五、一句话准备策略

会写Cypher + 知道啥时候用 + 能扯上LLM/Agent,就够了。

需要我帮你写几个Cypher查询练习,或者模拟面试问答吗?

结合我在新奥集团的项目 帮我 想一个知识图谱的应用场景

好的,给你设计一个设备故障知识图谱的具体实体关系模型:


一、核心实体(节点)

实体类型 属性 例子
设备 名称、型号、安装位置、投运时间 燃气轮机GT-001、阀门V-203
部件 名称、型号、寿命周期、供应商 轴承BR-501、密封圈SR-102
故障现象 描述、严重程度、检测方式 异响、振动超标、温度高
故障原因 类型、根因分析 轴承磨损、润滑不良、老化
维修措施 操作类型、工时、所需工具 更换轴承、清洗油路、校准
人员 姓名、工种、技能等级 张师傅(高级技师)
文档 类型、来源、更新时间 维修手册V2.3、工单#2024-0892

二、核心关系(边)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
┌─────────────────────────────────────────────────────────┐
│ 【设备】 │
│ GT-001燃气轮机 │
│ / \ │
│ 【包含部件】 【出现现象】 │
│ / \ \ │
│ 【轴承】 【叶片】 【异响】 │
│ BR-501 BL-202 振动大 │
│ | | | │
│ 【导致原因】 【导致原因】 【可能原因】 │
│ 润滑不良 疲劳裂纹 轴承磨损 │
│ \ / / │
│ \ / / │
│ 【维修措施】←──────┘ │
│ 更换轴承+清洗油路 │
│ | │
│ 【需要零件】 │
│ 轴承BR-501×2 + 润滑油L-10 │
│ | │
│ 【执行人员】 │
│ 张师傅(高级) │
│ | │
│ 【参考文档】 │
│ 工单#2024-0892 + 维修手册V2.3 │
└─────────────────────────────────────────────────────────┘

三、完整关系类型表

关系 方向 含义 例子
包含部件 设备→部件 设备由哪些部件组成 GT-001→轴承BR-501
出现现象 设备→故障现象 设备表现出什么症状 GT-001→异响
可能原因 故障现象→故障原因 现象背后的原因 异响→轴承磨损
导致原因 部件→故障原因 哪个部件出问题 轴承BR-501→润滑不良
解决方法 故障原因→维修措施 怎么修 轴承磨损→更换轴承
需要零件 维修措施→部件 用什么备件 更换轴承→轴承BR-501
参考文档 维修措施→文档 依据什么资料 更换轴承→维修手册V2.3
执行人员 维修措施→人员 谁干的 更换轴承→张师傅
同型号设备 设备↔设备 相似设备 GT-001↔GT-002
同区域设备 设备↔设备 地理位置相近 GT-001↔阀门V-203

四、Cypher建图语句(面试可用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 1. 创建设备节点
CREATE (gt:设备 {名称: "燃气轮机GT-001", 型号: "GT-A型", 位置: "一号厂房"})

// 2. 创建部件节点
CREATE (br:部件 {名称: "主轴轴承", 型号: "BR-501", 供应商: "SKF"})
CREATE (bl:部件 {名称: "涡轮叶片", 型号: "BL-202", 寿命: "8000小时"})

// 3. 创建故障相关节点
CREATE (yx:故障现象 {描述: "异响", 严重程度: "中", 检测方式: "人工听诊"})
CREATE (zm:故障原因 {描述: "轴承磨损", 根因: "润滑不良"})
CREATE (wx:维修措施 {操作: "更换轴承", 工时: 4, 工具: "液压拉马"})

// 4. 创建关系
CREATE (gt)-[:包含部件 {数量: 2}]->(br)
CREATE (gt)-[:包含部件 {数量: 24}]->(bl)
CREATE (gt)-[:出现现象 {发现时间: "2024-03-15"}]->(yx)
CREATE (yx)-[:可能原因 {概率: 0.7}]->(zm)
CREATE (br)-[:导致原因]->(zm)
CREATE (zm)-[:解决方法]->(wx)
CREATE (wx)-[:需要零件 {数量: 2}]->(br)

// 5. 查询:GT-001异响的可能原因和解决方法
MATCH (gt:设备 {名称: "燃气轮机GT-001"})-[:出现现象]->(现象)-[:可能原因]->(原因)-[:解决方法]->(方案)
WHERE 现象.描述 = "异响"
RETURN 现象.描述, 原因.描述, 方案.操作

五、面试画这张图

手绘版(白板面试用):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[设备:GT-001] ──包含部件──→ [部件:轴承]
│ │
│ 导致原因
↓ ↓
[现象:异响] ←────可能原因── [原因:磨损]
│ │
└────────────────────────┘


[措施:换轴承]

┌─────┴─────┐
↓ ↓
[需要零件] [参考文档]
[人员:张师傅] [工单#0892]

六、简历一句话

“设计设备故障知识图谱,构建7类实体、10种关系,支持故障现象→部件→原因→措施的多跳推理,实现维修经验的结构化沉淀与复用”

需要我把这个画成更正式的架构图,或者补充更多查询场景(比如相似故障推荐、维修人员调度)吗?