从零开始搭建飞秒激光加工RAG系统(Langchain实战版)
1 场景定义与需求分析
在动手写代码前,需要明确系统要解决的核心问题。飞秒激光加工领域知识分散在学术论文、设备手册、实验记录和专利中,工程师常面临"查参数半天、读文献一天"的困境。
典型问题示例:
-
"如何在石英玻璃上加工高深宽比的微孔,同时减少热影响区?"
-
"针对不锈钢表面LIPSS结构,脉宽和通量的一般工艺窗口是多少?"
-
"双光子聚合加工中,如何避免结构坍塌?"
基于Langchain的特性,我们将在实现中重点关注多源文档加载、领域术语的分块策略、混合检索架构这三个关键点。
2 环境准备与依赖安装
2.1 基础环境配置
bash
# 创建专用虚拟环境 python -m venv fs_laser_rag source fs_laser_rag/bin/activate # Linux/Mac # 或 fs_laser_rag\Scripts\activate # Windows # 安装核心依赖 pip install langchain langchain-community langchain-openai chromadb pip install pypdf docx2txt unstructured # 文档解析 pip install tiktoken # 文本分块 pip install sentence-transformers # 本地嵌入模型
2.2 飞秒加工领域特定准备
收集初始知识库文档,建议从以下三类开始:
-
综述论文PDF:如飞秒激光与材料相互作用的综述
-
设备操作手册:激光器参数说明、加工系统指南
-
实验记录表格:工艺参数与结果的对应关系
3 文档加载与预处理(Langchain Loader实战)
飞秒激光加工文档格式多样,Langchain提供了丰富的文档加载器。
3.1 多格式文档加载器实现
python
import os
from langchain_community.document_loaders import (
PyPDFLoader,
TextLoader,
Docx2txtLoader,
CSVLoader,
UnstructuredMarkdownLoader
)
def load_fs_laser_documents(data_dir: str):
"""加载飞秒激光加工领域的多格式文档"""
documents = []
for root, dirs, files in os.walk(data_dir):
for file in files:
file_path = os.path.join(root, file)
if file.endswith('.pdf'):
# 学术论文PDF加载
loader = PyPDFLoader(file_path)
docs = loader.load()
# 为每个文档块添加元数据
for doc in docs:
doc.metadata["source_type"] = "academic_paper"
doc.metadata["file_name"] = file
documents.extend(docs)
elif file.endswith('.txt') or file.endswith('.md'):
# 实验记录或说明文档
loader = TextLoader(file_path, encoding='utf-8')
docs = loader.load()
for doc in docs:
doc.metadata["source_type"] = "lab_note"
doc.metadata["file_name"] = file
documents.extend(docs)
elif file.endswith('.docx'):
loader = Docx2txtLoader(file_path)
docs = loader.load()
for doc in docs:
doc.metadata["source_type"] = "manual"
doc.metadata["file_name"] = file
documents.extend(docs)
elif file.endswith('.csv'):
# 工艺参数表格
loader = CSVLoader(file_path)
docs = loader.load()
for doc in docs:
doc.metadata["source_type"] = "parameter_table"
doc.metadata["file_name"] = file
documents.extend(docs)
print(f"加载完成,共 {len(documents)} 个文档块")
return documents
# 使用示例
docs = load_fs_laser_documents("./fs_laser_knowledge_base")
关键决策点:飞秒激光加工文档常包含图表和公式,纯文本加载会丢失信息。对于PDF中的图表,后续可考虑多模态模型提取,初期建议优先选择文本丰富的综述文章。
3.2 领域特定的文档清洗
python
import re
def clean_fs_laser_document(doc):
"""针对飞秒激光加工领域的文本清洗"""
text = doc.page_content
# 保留专业术语的格式(如FWHM、LIPSS等)
# 但去除不必要的换行和特殊字符
# 处理常见的PDF提取问题
text = re.sub(r'-\n', '', text) # 连字符换行连接
text = re.sub(r'\n+', ' ', text) # 多个换行替换为空格
# 提取关键参数(正则示例)
# 寻找"脉宽: 35 fs"、"波长: 800 nm"这类模式
param_pattern = r'([脉波长功频])[长宽率]\s*[:\:]\s*(\d+\.?\d*)\s*(fs|nm|W|kHz|MHz)'
params = re.findall(param_pattern, text)
if params:
doc.metadata["extracted_params"] = params
doc.page_content = text
return doc
# 应用清洗
cleaned_docs = [clean_fs_laser_document(doc) for doc in docs]
4 文档分块策略(Chunking)
飞秒激光加工文档中,技术描述和参数往往紧密相关。分块策略需要保持语义单元的完整性。
4.1 智能分块实现
python
from langchain.text_splitter import RecursiveCharacterTextSplitter
def create_fs_laser_chunks(documents):
"""针对飞秒激光文档的智能分块"""
# 基础分块器配置
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, # 可根据文档长度调整
chunk_overlap=200, # 重叠保证上下文连续性
separators=["\n\n", "\n", "。", ";", ",", " "], # 优先保持段落完整
length_function=len,
)
chunks = text_splitter.split_documents(documents)
# 为每个块添加领域标签
for i, chunk in enumerate(chunks):
# 根据内容自动判断主题
content = chunk.page_content.lower()
if any(word in content for word in ["烧蚀", "ablation", "微孔", "hole"]):
chunk.metadata["process_type"] = "ablation"
elif any(word in content for word in ["聚合", "polymerization", "双光子"]):
chunk.metadata["process_type"] = "polymerization"
elif any(word in content for word in ["光栅", "LIPSS", "条纹"]):
chunk.metadata["process_type"] = "structuring"
chunk.metadata["chunk_id"] = i
print(f"分块完成,共 {len(chunks)} 个知识块")
return chunks
chunks = create_fs_laser_chunks(cleaned_docs)
5 向量化与存储(Embedding + VectorStore)
5.1 嵌入模型选择
飞秒激光加工领域的术语具有专业性,建议使用领域适配性较好的嵌入模型。
python
from langchain_openai import OpenAIEmbeddings
from langchain_community.embeddings import HuggingFaceEmbeddings
# 方案A:使用OpenAI(需要API密钥)
# embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
# 方案B:使用本地开源模型(推荐,保护数据隐私)
embeddings = HuggingFaceEmbeddings(
model_name="BAAI/bge-large-zh-v1.5", # 中文场景推荐
# 或 "BAAI/bge-large-en-v1.5" # 英文场景
model_kwargs={'device': 'cpu'},
encode_kwargs={'normalize_embeddings': True}
)
5.2 向量数据库构建
python
from langchain_community.vectorstores import Chroma
import chromadb
# 创建持久化向量数据库
persist_directory = "./fs_laser_chroma_db"
# 初始化Chroma
vectordb = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory=persist_directory,
collection_name="fs_laser_knowledge",
collection_metadata={
"hnsw:space": "cosine", # 余弦相似度
"description": "飞秒激光加工知识库"
}
)
# 持久化保存
vectordb.persist()
print(f"向量数据库已保存至 {persist_directory}")
6 检索增强生成(RAG Chain构建)
6.1 基础检索器配置
python
# 从持久化数据库加载
vectordb = Chroma(
persist_directory=persist_directory,
embedding_function=embeddings,
collection_name="fs_laser_knowledge"
)
# 创建检索器
retriever = vectordb.as_retriever(
search_type="similarity", # 可选 "similarity" 或 "mmr"
search_kwargs={
"k": 5, # 返回前5个最相关文档
"fetch_k": 20, # MMR时预取的文档数
}
)
6.2 混合检索增强
飞秒激光加工问题常涉及精确参数,需要结合关键词检索。
python
from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
# 创建BM25检索器(关键词匹配)
bm25_retriever = BM25Retriever.from_documents(
chunks,
k=3
)
# 创建混合检索器
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, retriever],
weights=[0.3, 0.7] # 关键词检索权重30%,语义检索70%
)
6.3 Prompt模板设计
针对飞秒激光加工领域,设计专门的提示模板。
python
from langchain.prompts import ChatPromptTemplate
# 飞秒激光加工专用提示模板
fs_laser_prompt = ChatPromptTemplate.from_messages([
("system", """你是一个飞秒激光加工领域的专家助手。请基于提供的知识片段,准确回答用户关于飞秒激光加工的问题。
回答要求:
1. 如果涉及工艺参数(功率、脉宽、波长等),请用清晰的格式呈现
2. 区分理论解释和实验数据,分别标注来源
3. 如果不确定或知识片段中没有相关信息,请明确说明
4. 对于工艺建议,注明参数范围仅供参考,实际需根据设备调试
知识片段:
{context}
"""),
("human", "{question}")
])
6.4 完整RAG Chain构建
python
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
# 初始化LLM(可使用本地模型或API)
llm = ChatOpenAI(
model="gpt-4", # 或使用本地部署的模型
temperature=0.1, # 低温度保证准确性
max_tokens=1000
)
# 构建RAG链
def format_docs(docs):
return "\n\n".join([f"[来源: {doc.metadata.get('source_type', '未知')}, 文件: {doc.metadata.get('file_name', '未知')}]\n{doc.page_content}" for doc in docs])
rag_chain = (
{"context": ensemble_retriever | format_docs, "question": RunnablePassthrough()}
| fs_laser_prompt
| llm
| StrOutputParser()
)
7 查询测试与效果评估
7.1 基础测试
python
# 测试查询
test_questions = [
"飞秒激光加工石英玻璃微孔的最佳参数范围是多少?",
"如何减少不锈钢表面LIPSS结构的粗糙度?",
"双光子聚合加工中,结构坍塌的原因和解决方法"
]
for question in test_questions:
print(f"\n问题: {question}")
print("-" * 50)
answer = rag_chain.invoke(question)
print(f"回答: {answer}")
print("=" * 70)
7.2 检索质量诊断
python
def inspect_retrieval(question, retriever, k=5):
"""检查检索到的文档质量"""
docs = retriever.get_relevant_documents(question)
print(f"\n问题: {question}")
print(f"检索到 {len(docs)} 个相关文档:\n")
for i, doc in enumerate(docs):
print(f"--- 文档 {i+1} ---")
print(f"来源: {doc.metadata.get('source_type', '未知')}")
print(f"内容预览: {doc.page_content[:200]}...")
print()
# 诊断示例
inspect_retrieval("飞秒激光加工石英玻璃微孔的工艺参数", ensemble_retriever)
8 进阶优化策略
8.1 多查询检索(Multi-Query)
python
from langchain.retrievers.multi_query import MultiQueryRetriever
# 使用LLM生成多个相关查询,提高召回率
multi_query_retriever = MultiQueryRetriever.from_llm(
retriever=ensemble_retriever,
llm=llm,
prompt=ChatPromptTemplate.from_template(
"""你是一个飞秒激光加工专家。请针对用户的原始问题,生成5个不同角度但相关的查询,以提高检索覆盖率。
原始问题: {question}
生成5个不同角度的查询(每行一个):"""
)
)
8.2 上下文压缩(Contextual Compression)
python
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor
# 使用LLM提取最相关的内容片段,减少上下文长度
compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=ensemble_retriever
)
8.3 飞秒激光加工知识图谱增强
python
# 伪代码示例:构建简单的实体关系网络
fs_laser_kg = {
"material": ["石英玻璃", "不锈钢", "硅", "钙钛矿"],
"process": ["烧蚀", "聚合", "改性", "LIPSS"],
"parameter": ["脉宽", "波长", "功率", "重复频率"],
"effect": ["热影响区", "粗糙度", "深宽比", "衍射效率"]
}
# 可在检索时根据实体类型调整权重
def kg_enhanced_retrieval(question, retriever, kg):
# 识别问题中的实体类型
# 根据实体类型调整检索参数
pass
9 部署与服务化
9.1 简单Web服务(FastAPI)
python
from fastapi import FastAPI
from pydantic import BaseModel
import uvicorn
app = FastAPI(title="飞秒激光加工RAG系统")
class Query(BaseModel):
question: str
history: list = []
class Response(BaseModel):
answer: str
sources: list
@app.post("/ask", response_model=Response)
async def ask_fs_laser(query: Query):
answer = rag_chain.invoke(query.question)
# 获取来源文档
docs = ensemble_retriever.get_relevant_documents(query.question)
sources = [
{
"content": doc.page_content[:200],
"source_type": doc.metadata.get("source_type", ""),
"file_name": doc.metadata.get("file_name", "")
}
for doc in docs[:3]
]
return Response(answer=answer, sources=sources)
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
9.2 交互式命令行工具
python
# cli.py
def main():
print("=" * 60)
print("飞秒激光加工RAG助手 - 输入问题,Q退出")
print("=" * 60)
while True:
question = input("\n请输入问题: ")
if question.upper() == 'Q':
break
print("\n正在检索...")
answer = rag_chain.invoke(question)
print(f"\n回答: {answer}\n")
print("-" * 60)
if __name__ == "__main__":
main()
10 系统迭代路线图
基于类似项目的经验,飞秒激光加工RAG系统的迭代可按以下阶段推进:
| 阶段 | 目标 | 关键任务 |
|---|---|---|
| Phase 1 | MVP验证 | 加载20-30篇核心文献,测试基础问答效果 |
| Phase 2 | 知识库扩充 | 加入设备手册、专利、实验记录,覆盖更多加工场景 |
| Phase 3 | 检索优化 | 实现混合检索、多查询、上下文压缩,提高准确率 |
| Phase 4 | 多模态增强 | 集成图表理解能力,支持从SEM图像检索相似案例 |
| Phase 5 | 用户闭环 | 部署Web服务,收集真实用户反馈,持续优化 |
总结
通过以上步骤,我们实现了:
-
文档加载:支持飞秒激光加工领域的PDF、Word、TXT、CSV等多种格式
-
智能分块:针对技术文档特点,保持段落和参数的完整性
-
向量存储:使用领域适配的嵌入模型,构建持久化向量数据库
-
混合检索:结合语义检索和关键词检索,提高召回质量
-
RAG链:设计领域专用Prompt,生成准确、可追溯的回答
-
服务化:提供API接口和命令行工具,方便实际使用
这套系统可以作为飞秒激光加工研究的智能知识助手,帮助工程师快速获取工艺参数、理解加工机理、借鉴已有案例,大幅提升研发效率。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)