这一步确实就是 RAG:不是"训练模型",而是把官方 HTML 文档整理成可检索知识库,让 agent 写脚本前先查文档、再生成 TCL。你的场景很适合做成"文档检索工具 + 执行工具"两类工具。
已思考 5s
对,你说的就是 RAG。但你这里不要一上来搞复杂,建议先做成这个结构:
官方 HTML 文档
↓
清洗成纯文本
↓
切成小块 chunk
↓
做 embedding
↓
存进向量库 Chroma
↓
Agent 多一个工具:search_hm_docs
↓
Agent 先查文档,再写 TCL,再调用 run_hypermesh_tcl
LangChain 官方 RAG 文档也是这个思路:用 loader 加载资料、splitter 切块、embedding 编码、vector store 检索,再把检索结果交给模型使用。
你现在最适合的方案
你的 agent 现在已经有一个工具:
run_hypermesh_tcl
接下来再加一个工具:
search_hm_docs
以后 agent 流程变成:
用户:创建圆柱 / 布尔 / 网格
Agent:
1. 先调用 search_hm_docs 查相关官方命令
2. 根据查到的官方文档写 TCL
3. 再调用 run_hypermesh_tcl 执行
这比直接把一堆 HTML 塞进 prompt 强很多。
第一步:准备目录
比如你建:
D:/Altair_Agent_Knowledge/
docs_html/ # 放官方 html
chroma_db/ # 向量库自动生成
hmtools.py
hmagent.py
build_hm_rag.py
把官方 HTML 都放到:
D:/Altair_Agent_Knowledge/docs_html/
第二步:安装需要的包
先用最简单的 Chroma 本地向量库。LangChain 官方也有 Chroma vector store 集成,支持把文档放进向量库后做 similarity_search 检索。
pip install langchain langchain-community langchain-text-splitters langchain-chroma chromadb beautifulsoup4
如果你暂时不用 OpenAI embedding,可以用本地 embedding:
pip install langchain-huggingface sentence-transformers
第三步:写一个建库脚本 build_hm_rag.py
这个脚本只需要运行一次。以后文档变了再重新跑。
# build_hm_rag.py
# 把 HyperMesh 官方 HTML 文档做成 Chroma 向量库
from pathlib import Path
from bs4 import BeautifulSoup
from langchain_core.documents import Document
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_chroma import Chroma
from langchain_huggingface import HuggingFaceEmbeddings
DOCS_DIR = Path(r"D:/Altair_Agent_Knowledge/docs_html")
DB_DIR = r"D:/Altair_Agent_Knowledge/chroma_db"
def html_to_text(path: Path) -> str:
"""把 html 清洗成纯文本。"""
raw = path.read_text(encoding="utf-8", errors="ignore")
soup = BeautifulSoup(raw, "html.parser")
# 去掉没用内容
for tag in soup(["script", "style", "nav", "footer", "header"]):
tag.decompose()
text = soup.get_text("\n")
# 压缩空行
lines = [line.strip() for line in text.splitlines()]
lines = [line for line in lines if line]
return "\n".join(lines)
def main():
docs = []
html_files = list(DOCS_DIR.rglob("*.html")) + list(DOCS_DIR.rglob("*.htm"))
print(f"找到 HTML 文件数量: {len(html_files)}")
for path in html_files:
text = html_to_text(path)
if len(text) < 50:
continue
docs.append(Document(
page_content=text,
metadata={
"source": str(path),
"filename": path.name,
}
))
print(f"有效文档数量: {len(docs)}")
# LangChain 官方建议一般先用 RecursiveCharacterTextSplitter,比较稳。
# 它会尽量保留上下文,同时控制 chunk 大小。
splitter = RecursiveCharacterTextSplitter(
chunk_size=1200,
chunk_overlap=200,
)
chunks = splitter.split_documents(docs)
print(f"切分后 chunk 数量: {len(chunks)}")
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
)
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory=DB_DIR,
collection_name="hypermesh_docs",
)
print("✅ HyperMesh 文档向量库已建立:", DB_DIR)
if __name__ == "__main__":
main()
RecursiveCharacterTextSplitter 是 LangChain 文档里推荐的通用起步方案,适合先快速跑通。
第四步:在 hmtools.py 里加一个文档检索工具
你原来已经有 run_hypermesh_tcl。现在在同一个 hmtools.py 里加:
from langchain_core.tools import tool
from langchain_chroma import Chroma
from langchain_huggingface import HuggingFaceEmbeddings
DB_DIR = r"D:/Altair_Agent_Knowledge/chroma_db"
def _load_hm_vectorstore():
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
)
return Chroma(
persist_directory=DB_DIR,
embedding_function=embeddings,
collection_name="hypermesh_docs",
)
@tool
def search_hm_docs(query: str, k: int = 5) -> str:
"""
检索 HyperMesh 官方文档。
在编写 Tcl 脚本前,先用这个工具查询相关命令、参数和示例。
"""
print("🔎 search_hm_docs 工具已被调用", flush=True)
print(f"🔎 query = {query}", flush=True)
try:
vectorstore = _load_hm_vectorstore()
results = vectorstore.similarity_search(query, k=k)
if not results:
return "未检索到相关 HyperMesh 文档。"
parts = []
for i, doc in enumerate(results, start=1):
source = doc.metadata.get("source", "")
filename = doc.metadata.get("filename", "")
content = doc.page_content[:1500]
parts.append(
f"【结果 {i}】\n"
f"文件: {filename}\n"
f"路径: {source}\n"
f"内容:\n{content}"
)
return "\n\n" + ("\n\n" + "-" * 60 + "\n\n").join(parts)
except Exception as exc:
return f"❌ 检索 HyperMesh 文档失败: {exc}"
第五步:agent 里把两个工具都加上
原来是:
from hmtools import run_hypermesh_tcl
TOOLS = [run_hypermesh_tcl]
改成:
from hmtools import run_hypermesh_tcl, search_hm_docs
TOOLS = [search_hm_docs, run_hypermesh_tcl]
第六步:改 SYSTEM_PROMPT
重点是:不要让它手写 JSON。你之前已经踩过这个坑。
可以改成:
SYSTEM_PROMPT = """你是一个 HyperMesh 自动化专家。
你有两个工具:
1. search_hm_docs(query: str, k: int = 5)
- 用于检索 HyperMesh 官方文档。
- 在不确定 TCL 命令、参数、语法时,必须先调用它。
2. run_hypermesh_tcl(script: str, output_name: str = "model")
- 用于执行完整 HyperMesh TCL 脚本。
- 只有在脚本写好后才能调用它。
工作流程:
1. 先理解用户需求。
2. 如果涉及 HyperMesh TCL 命令、参数、建模、网格、布尔、保存等操作,先调用 search_hm_docs 查询相关官方文档。
3. 根据检索结果编写完整 TCL 脚本。
4. 调用 run_hypermesh_tcl 执行脚本。
5. 把执行日志返回给用户。
约束:
- 不要把 TCL 脚本作为普通文本回复。
- 不要手写 JSON。
- 不要输出 <tool_call>。
- 所有尺寸默认单位为 mm。
- 脚本必须保存 .hm 文件。
- 如果文档里没有找到某个命令,不要编造命令;可以先生成最小可验证脚本。
请始终使用中文回复。
"""
注意:虽然这里写了"不要手写 JSON",但如果你发现 qwen2.5 又被这句话带偏,就删掉这两句:
不要手写 JSON。
不要输出 <tool_call>。
你当前这个模型比较敏感,先以 521 能跑的 prompt 风格为主。
第七步:先别让 agent 自动解决复杂任务
先测试文档检索工具本身:
from hmtools import search_hm_docs
print(search_hm_docs.invoke({
"query": "HyperMesh Tcl solidblock command create block",
"k": 3,
}))
再测试 agent:
帮我查一下 HyperMesh 里创建 solid block 的 Tcl 命令怎么写
看到它能调用 search_hm_docs 后,再测试:
帮我创建一个长100mm、宽50mm、高30mm的长方体,文件名叫 mycube
你要记住的核心点
RAG 不是训练模型。它是:
把官方文档放到数据库里
用户问问题时先检索相关片段
再让模型基于片段生成答案/脚本
对你这个 HyperMesh Agent 来说,最终就是两个工具:
TOOLS = [
search_hm_docs, # 查官方文档
run_hypermesh_tcl, # 执行 TCL
]
先把这条链跑通,不要一开始就搞自动纠错、多轮反思、复杂 workflow。等 search_hm_docs 稳定后,再做"执行失败 → 查文档 → 改脚本 → 再执行"的闭环。