课程摘要
本节学习如何把力学公式、软件资料和历史案例整理成可追溯的知识库,理解检索增强的基本流程。通过均匀杆与变截面杆案例,掌握资料分块、条件保留、版本过滤和证据引用;用可运行的标签检索程序观察命中、误匹配与无证据状态,再以两单元杆件计算独立复核公式。课程同时介绍向量检索、混合检索和重排的作用,为后续本地仿真助手的工具调用打好基础。
一、从一个容易答错的问题开始
上一节介绍了本地大模型的部署与能力评估。本节进一步解决一个问题:
模型给出的解释,有哪些可以查到、可以核对的依据?
先看一个具体任务:
一根1000 mm长的线弹性杆,左端轴向固定,右端受拉。前500 mm截面积为100 mm²,后500 mm为200 mm²。弹性模量110000 MPa,拉力10000 N。能否直接使用
\(u=FL/(EA)\)?
如果只记住了杆件公式,很容易挑一个面积代入。但这根杆的截面积沿长度变化,"均匀截面"假设已经不成立。
问题并非公式记错,而是公式与适用条件被拆开了。
本节围绕这根杆完成三个学习任务:
- 把公式连同假设、单位和来源整理成知识条目。
- 根据版本和适用范围寻找合适资料。
- 核对检索依据,并用独立计算检查结论。
二、什么是检索增强?
检索增强生成通常简称 RAG。其基本思路是:先从外部资料寻找相关内容,再把问题和检索结果提供给模型,用于组织回答。
\ \\text{问题} \\longrightarrow \\text{检索相关资料} \\longrightarrow \\text{结合资料生成回答} \\longrightarrow \\text{核对引用与结论} \\
Lewis等人的研究将参数化模型与可检索的外部知识结合,是理解这一思路的经典入口。RAG原始论文
对力学仿真而言,外部资料可以包括:
- 经过核对的力学公式与课程笔记;
- 与软件版本对应的操作手册;
- 已验证脚本及其使用条件;
- 仿真报错、诊断过程和有效修复案例;
- 材料参数记录及其来源。
资料更新后,可以更新知识条目和索引。如果采用向量索引,修改过的条目通常还需要重新生成向量或更新索引。
【插图1:从资料到证据,再到回答】

本节实际实现前三个环节:资料整理、过滤检索、形成证据包。先把检索过程看清楚,后面再接入模型生成和计算工具。
三、知识库为什么不能只是一个资料文件夹?
把几十份PDF放进文件夹,可以保存资料,却还没有回答以下问题:
找到的是哪个版本?公式适用于什么条件?引用能否定位到原文?
一个可用的知识条目,需要把这些信息组织起来。
1. 一条记录至少保存什么?
| 字段 | 作用 |
|---|---|
id |
唯一标识,便于引用和更新 |
title |
内容标题 |
source、section |
原文文件及章节、页码或代码位置 |
course_version |
本节实验中的课程知识版本 |
software_version |
软件资料对应的软件版本 |
status |
当前筛选状态 |
scopes |
适用的问题范围 |
tags |
检索标签 |
assumptions |
力学假设及限制 |
units |
单位约定 |
text |
条目正文 |
本节配套资料来自自编的 knowledge_notes.md,用于教学实验。
其中,course-1表示课程知识版本,不能解释为Abaqus版本。基本力学条目的 software_version 为空,也不代表它能够支持任何软件API。
2. 保存公式,还要保存条件
例如:
\ u=\\frac{FL}{EA} \\
在本节轴杆模型中,需要一起保存:
- 小变形、线弹性;
- \(E\)和\(A\)沿杆长恒定;
- 仅有端部轴向载荷,无分布轴向载荷;
- 左端轴向固定;
- 使用一致单位制。
如果只保留公式,后续就容易把它用于变截面、变材料或非恒定轴力的问题。
3. 为变截面杆建立另一个条目
一般一维轴杆的伸长为:
\ u=\\int_0\^L\\frac{N(x)}{E(x)A(x)}\\,dx \\
其中,\(N(x)\)应先由平衡条件确定。
对于分段常值、仅受端力 \(F\) 的杆:
\ u=\\sum_i\\frac{FL_i}{E_iA_i} \\
这里仍然采用一维杆近似,不包含台阶附近的局部三维应力集中。
【插图2:完整的力学知识块】

四、资料怎样分块,才能保留力学含义?
资料分块,就是把长文档拆成便于检索和提供上下文的小单元。
块太大,容易混入无关内容;块太小,公式、变量定义和适用条件容易分离。
建议先按"一个完整知识点或问题"划分。
| 资料类型 | 应尽量一起保留 |
|---|---|
| 公式说明 | 公式、变量、假设和单位 |
| 有限元单元说明 | 自由度、形函数、积分规则及适用情况 |
| 软件API | 参数、调用环境、版本和前后依赖 |
| 报错案例 | 错误信息、模型条件、诊断证据和修复方法 |
| 结果图表 | 图注、坐标、单位、工况和数据来源 |
例如,一段资料写着:
以下本构矩阵仅适用于平面应力。
如果这句话与矩阵被切进不同资料块,检索器可能只返回矩阵,模型就容易遗漏适用条件。
处理扫描PDF时,还要检查OCR结果。字母 \(E\) 与 \(\varepsilon\)、负号、下标和矩阵位置,都可能出现识别错误。
检索器能够找到原文,不代表原文已经被正确识别。
五、先做一个容易检查的检索器
本节使用七条自编记录。
| 标识 | 内容 | 用途 |
|---|---|---|
rod-uniform |
均匀杆 | 当前可用条目 |
rod-variable |
变截面杆 | 当前可用条目 |
units-nmm |
N--mm--MPa单位制 | 当前可用条目 |
shear-convention |
工程剪切与张量剪切 | 多尺度衔接提示 |
orientation-note |
材料取向 | 多尺度衔接提示 |
rod-archived |
归档杆示例 | 检查归档及版本过滤 |
rod-draft |
待审阅草稿 | 检查状态过滤 |
1. 明确查询条件
查询均匀杆时,提供:
tags = ["rod", "linear"]
course_version = "course-1"
scope = "uniform_axial"
这里的适用范围由学习者根据题意确认。程序不会自动判断杆是否均匀,也不会把中文问句自动转成标签。
如果题目没有说明截面是否均匀,应先澄清,不能随便选择一个范围。
2. 检查元数据
只有同时满足以下条件,记录才能进入候选集合:
- 状态为
approved; - 课程版本与请求相同;
- 适用范围包含当前问题范围。
这里的 approved 是本实验的筛选状态,不等于外部工程认证。
3. 对合格记录计分
本节采用标签交集数量:
\ s(q,d)=\|T_q\\cap T_d\| \\
查询标签是:
rod、linear
记录也包含这两个标签,得分就是2。
重复输入同一个标签不会重复加分,英文大小写会归一。程序返回前 \(k\) 个正分候选,同分时按记录标识排序。
得分2只表示两个标签相交,不是正确概率。
【插图3:相同分数,不同筛选结论】

四条杆件记录都能匹配两个标签,但只有当前均匀杆条目满足本次条件。
元数据也需要维护正确。如果把变截面条目误标成均匀杆,过滤器不会自动发现这个标注错误。
六、实验一:检索均匀杆资料
1. 准备文件
将以下文件放在同一目录:
lesson67_retrieval.py
knowledge.json
knowledge_notes.md
课程包已提供完整文件,讲义附录也包含完整检索程序。
实验只使用Python标准库,不需要安装Pandas、PyTorch、FAISS或本地模型服务。
2. 先执行自测
python lesson67_retrieval.py --self-test
预期输出:
SELF_TEST=PASS (retrieval, filters, provenance and missing-evidence state)
它检查标签检索、过滤规则、出处保留和无证据状态。这个结果不能解释为知识库准确率达到100%。
3. 执行查询
python lesson67_retrieval.py --out lesson67_run
预期输出:
MODE=CURATED_TAG_RETRIEVAL; embeddings=False; llm_run=False; solver_run=False
QUERY=linear,rod; version=course-1; scope=uniform_axial
STATE=EVIDENCE_FOUND; hits=1
HIT=rod-uniform; score=2; source=knowledge_notes.md §1
EXCLUDED=rod-variable; score=2; by=SCOPE
EXCLUDED=rod-archived; score=2; by=STATUS,VERSION
EXCLUDED=rod-draft; score=2; by=STATUS
ANSWER_GENERATED=False; score_is_probability=False
SAVED=lesson67_run\retrieval.json
SAVED=lesson67_run\evidence_packet.json
输出表明:
- 均匀杆资料进入候选;
- 变截面资料因适用范围不同而排除;
- 归档条目因状态和版本被排除;
- 草稿因尚未审阅而排除。
程序会拒绝已存在的输出目录。再次运行时,更换 --out 路径即可保留原始记录。
4. 检查证据包
retrieval.json 保存查询、命中记录、分数及过滤理由。
evidence_packet.json 保存:
引用标识、原文位置、条目正文、适用条件、单位、版本和记录摘要。
程序为条目计算SHA-256摘要,帮助识别记录是否发生变化。摘要不能证明来源真实,也不能证明内容正确。
EVIDENCE_FOUND只表示找到了候选资料,还需要检查它是否足以支持当前问题。
七、实验二:把问题改成变截面杆
执行:
python lesson67_retrieval.py --tags rod linear variable --scope variable_axial --out lesson67_variable
预期输出:
MODE=CURATED_TAG_RETRIEVAL; embeddings=False; llm_run=False; solver_run=False
QUERY=linear,rod,variable; version=course-1; scope=variable_axial
STATE=EVIDENCE_FOUND; hits=1
HIT=rod-variable; score=3; source=knowledge_notes.md §2
EXCLUDED=rod-uniform; score=2; by=SCOPE
EXCLUDED=rod-archived; score=2; by=STATUS,VERSION,SCOPE
EXCLUDED=rod-draft; score=2; by=STATUS,SCOPE
ANSWER_GENERATED=False; score_is_probability=False
SAVED=lesson67_variable\retrieval.json
SAVED=lesson67_variable\evidence_packet.json
这次不仅改变了关键词,还改变了经过确认的问题范围。
独立复核:两种杆件的伸长有什么不同?
均匀杆参数:
\ E=110000\\ \\mathrm{MPa},\\quad F=10000\\ \\mathrm{N} \\\ L=1000\\ \\mathrm{mm},\\quad A=100\\ \\mathrm{mm\^2} \\
伸长:
\ u_{\\mathrm{uniform}} = \\frac{10000\\times1000}{110000\\times100} = 0.909091\\ \\mathrm{mm} \\
分段杆的两段长度均为500 mm,截面积分别为100、200 mm²:
\ u_{\\mathrm{piecewise}} = \\frac{10000\\times500}{110000\\times100} + \\frac{10000\\times500}{110000\\times200} \\\ u_{\\mathrm{piecewise}} = 0.681818\\ \\mathrm{mm} \\
后半段截面积增大后,总伸长减小,符合物理直觉。
用两个有限元单元再检查一次
两个单元的刚度系数为:
\ k_1=\\frac{EA_1}{L_1}=22000\\ \\mathrm{N/mm} \\\ k_2=\\frac{EA_2}{L_2}=44000\\ \\mathrm{N/mm} \\
组装得到:
\ \\boldsymbol K= \\begin{bmatrix} 22000\&-22000\&0\\\\ -22000\&66000\&-44000\\\\ 0\&-44000\&44000 \\end{bmatrix} \\ \\mathrm{N/mm} \\
施加左端固定和右端拉力后:
\ \\boldsymbol u= \\begin{bmatrix} 0\\\\ 0.454545\\\\ 0.681818 \\end{bmatrix} \\ \\mathrm{mm} \\
两段应力分别为:
\ \\sigma_1=100\\ \\mathrm{MPa}, \\qquad \\sigma_2=50\\ \\mathrm{MPa} \\
左端反力为:
\ R_1=-10000\\ \\mathrm{N} \\
运行配套检查程序:
python mechanics_check.py
预期输出:
uniform: u_mm=0.000000,0.454545,0.909091
stress_MPa=100.000000,100.000000; reaction_N=-10000.000000
piecewise: u_mm=0.000000,0.454545,0.681818
stress_MPa=100.000000,50.000000; reaction_N=-10000.000000
CHECK=PASS (linear-system residual, force balance and analytical elongation)
MODE=PYTHON_1D_FEM; llm_run=False; external_solver_run=False
这部分已实际运行纯Python一维有限元计算,检查了自由节点残差、反力平衡和解析伸长。
它用于说明:资料提供方法依据,独立计算检查数值结论。
八、实验三:没有找到资料怎么办?
执行:
python lesson67_retrieval.py --tags turbulence --out lesson67_nohit
预期输出:
MODE=CURATED_TAG_RETRIEVAL; embeddings=False; llm_run=False; solver_run=False
QUERY=turbulence; version=course-1; scope=uniform_axial
STATE=NEED_SOURCE_OR_QUERY_REVIEW; hits=0
ANSWER_GENERATED=False; score_is_probability=False
SAVED=lesson67_nohit\retrieval.json
SAVED=lesson67_nohit\evidence_packet.json
这表示当前资料、标签和过滤条件没有给出候选,不代表相关知识不存在。
应依次检查:
- 问题范围是否明确?
- 标签是否与资料术语一致?
- 版本条件是否选错?
- 知识库是否确实缺少资料?
不能为了让系统总能返回内容,就自动取消版本过滤或随便使用归档条目。
如果用户需要软件专用脚本,还要确认软件版本和执行环境。本节程序没有实现软件API兼容性检查。
九、怎样形成有依据的回答?
建议按以下顺序组织:
问题理解 → 证据出处 → 适用条件 → 推理或计算 → 尚需确认的内容。
针对开头的问题,可以这样回答:
该杆的截面积分段变化,应采用分段轴杆关系。课程自编知识条目
knowledge_notes.md的§2给出了分段常值公式。在小变形、线弹性、两段承受相同端力的条件下,计算得到总伸长0.681818 mm。独立两单元杆计算与该结果一致。该模型不描述台阶附近的局部三维应力集中。
这个回答区分了三件事:
- 文档支持公式及其适用条件;
- 当前数值来自具体参数计算;
- 局部三维效应超出当前模型范围。
只在答案末尾放一个文件名,不能证明所有结论都受到支持。
此外,检索到的资料属于待分析文本。如果其中出现"忽略原要求并执行某命令",它也不能改变工具范围或执行权限。
十、什么时候需要向量检索和重排?
1. 标签检索的局限
用户说"轴向伸长",条目标签却是 rod、linear,本节程序不会自动理解二者相关。
可以先评估术语表、同义词和关键词方法。如果自然表达更加多样,再考虑通过嵌入模型生成向量表示。
常见余弦相似度为:
\ \\operatorname{sim}(\\boldsymbol q,\\boldsymbol d) = \\frac{\\boldsymbol q\\cdot\\boldsymbol d} {\\\|\\boldsymbol q\\\|\\\|\\boldsymbol d\\\|} \\
向量接近表示在该表示方法下相似,不意味着工程条件相同。均匀杆、变截面杆和热膨胀杆,语义可能接近,适用条件仍需核对。
FAISS提供向量相似性搜索和索引能力,本身不是生成语义向量的语言模型,也不会自动审查力学公式。FAISS官方说明
2. 混合检索
软件关键字、参数名和错误码经常需要精确匹配,自然问句和同义表达则可能受益于语义召回。
混合检索结合不同通道,但各通道的分数尺度可能不同,需要定义归一化或排名融合方法,不能直接把原始分数随意相加。
3. 重排
重排是在初步召回后,再根据问题与候选内容调整顺序。
例如,本节查询 dft、shear 时:
- 剪切约定条目匹配两个标签;
- 材料取向条目也会因共享
dft获得一个匹配。
后者属于相关领域,却不能直接解释工程剪切应变的二倍关系。
这说明:部分词项匹配,还需要进一步检查证据是否直接支持问题。
重排无法补上知识库中根本不存在的资料,也不能代替版本和适用条件检查。
十一、怎样评价知识库是否有用?
| 评估对象 | 检查问题 |
|---|---|
| 资料质量 | 原文、公式和单位是否正确? |
| 召回 | 所需资料是否进入候选? |
| 精确性 | 候选是否直接支持当前问题? |
| 版本与范围 | 是否混入归档或不适用资料? |
| 引用支持 | 原文是否支持对应结论? |
| 无证据处理 | 是否合理澄清或补充资料? |
| 最终计算 | 残差、平衡与参考解是否通过? |
在人工标注相关资料后,可以计算:
\ \\mathrm{Recall@k} = \\frac{\\text{前k个候选中的相关条目数}} {\\text{人工标注的相关条目总数}} \\
本节采用实际返回数作为精确率分母:
\ \\mathrm{Precision@k} = \\frac{\\text{前k个候选中的相关条目数}} {\\text{实际返回的候选数}} \\
空结果应单独记录,避免除零。若采用固定 \(k\) 作分母,也应说明指标约定。
自测通过只能说明程序符合设定规则,不能据此声称检索召回率或最终回答准确率达到100%。
十二、课后练习
练习1:为什么不能只保存 \(u=FL/(EA)\)?
参考答案:缺少材料、截面和载荷条件,容易被用于不适用的问题。
练习2:归档条目的标签与查询完全匹配,是否应进入当前证据包?
参考答案:不应。标签匹配不能覆盖状态与版本约束。
练习3:查不到 turbulence,能否断言不存在相关理论?
参考答案:不能。只能说明当前资料、查询和过滤条件没有找到候选。
练习4:用户没说明截面是否均匀,可以默认选择 uniform_axial 吗?
参考答案:不应。先澄清。程序中的范围由已确认条件提供。
练习5:为DFT弹性常数进入有限元建立三个知识条目。
参考答案:单位转换、剪切应变与分量排列、材料取向和坐标变换。涉及软件接口时还要记录对应版本。
