欢迎光临
我们一直在努力

AI编程实战:我用Python+LangChain搭建了一个半导体FAB智能运维Agent

前言

2024年被称为'AI Agent元年'。从AutoGPT到LangChain,从CrewAI到OpenAI Assistants,各种Agent框架层出不穷。但作为一个在半导体行业摸爬滚打了15年的老工程师,我发现一个有趣的现象:绝大多数AI Agent的教程和案例都集中在通用场景——写代码、做客服、查资料。而真正需要AI Agent的工业现场,却几乎看不到像样的实践案例。

这篇文章,我要分享一个真实的工业项目:如何用Python+LangChain,为一家12英寸晶圆厂搭建一个智能运维Agent。它能够自动监控设备状态、诊断异常原因、推荐维修方案,甚至自动生成工单。整个项目从零到上线只用了2周时间。

一、背景:为什么半导体FAB需要AI Agent

1.1 传统运维的痛点

先说说我所在的这家晶圆厂的情况:

  • 300mm晶圆厂,月产能4万片
  • 设备总数:200+台(蚀刻、CVD、光刻、CMP等)
  • 运维团队:15人,7×24小时轮班
  • 每天平均报警数:500+条

传统运维流程是这样的:

步骤

操作

耗时

问题

1

设备报警触发

实时

–

2

值班工程师查看报警信息

2-5分钟

信息分散在多个系统

3

登录各系统查询历史数据

5-10分钟

SECS/GEM、MES、FDC各自独立

4

根据经验判断故障原因

10-30分钟

依赖个人经验

5

查阅维修手册/SOP

5-15分钟

文档散落各处

6

制定维修方案并执行

30-60分钟

–

7

填写工单和报告

10-20分钟

手工录入,容易遗漏

平均一次故障处理:**62-140分钟**。其中真正修设备的时间可能只有30分钟,剩下全在查资料、找数据、填表单上。

1.2 用AI Agent能解决什么?

我的想法很简单:把步骤2-6全部交给AI Agent来做。它应该能够:

  • 自动聚合来自多个系统的报警和数据(SECS/GEM、MES、FDC、QMS)
  • 基于历史数据和知识库,快速定位故障根因
  • 检索最匹配的维修SOP和案例
  • 生成结构化的维修建议和工单
  • 全程记录决策过程,可追溯、可审计
  • 二、技术选型:为什么选LangChain

    2.1 方案对比

    方案

    优点

    缺点

    适用场景

    纯LLM API调用

    简单直接

    无记忆、无工具调用、上下文受限

    简单问答

    OpenAI Assistants

    官方支持、易用

    定制性差、成本高

    通用助手

    LangChain

    生态丰富、工具链成熟

    学习曲线陡峭

    复杂Agent

    CrewAI

    多角色协作好

    生态较小

    团队协作任务

    自研框架

    完全可控

    开发周期长

    长期项目

    最终选择LangChain,理由如下:

    • **工具集成能力强**:LangChain有现成的SQL Database Tool、Vector Store Retriever、API Toolkit等,正好对接我们的MES数据库和知识库
    • **RAG支持完善**:我们需要把几百份维修SOP、历史工单做成知识库,LangChain的RAG pipeline非常成熟
    • **社区活跃**:遇到问题容易找到解决方案
    • **Python原生**:我们的数据采集和分析工具都是Python写的,无缝衔接

    三、系统架构设计

    3.1 整体架构

    系统采用经典的ReAct(Reasoning + Acting)架构:

    # 智能运维Agent核心架构
    # ┌─────────────────────────────────────────────┐
    # │              User Interface (Web/Chat)       │
    # └──────────────────────┬──────────────────────┘
    #                        │
    # ┌──────────────────────▼──────────────────────┐
    # │            LangChain Agent Core              │
    # │  ┌─────────┐  ┌─────────┐  ┌─────────────┐ │
    # │  │ LLM     │  │ Memory  │  │ Tools       │ │
    # │  │ (GPT-4) │  │ (RAG)   │  │ (5个工具)   │ │
    # │  └────┬────┘  └────┬────┘  └──────┬──────┘ │
    # │       └────────────┼──────────────┘         │
    # │                    │ ReAct Loop             │
    # └────────────────────┼────────────────────────┘
    #                      │
    #         ┌────────────┼────────────┐
    #         ▼            ▼            ▼
    #   ┌──────────┐ ┌──────────┐ ┌──────────┐
    #   │ MES DB   │ │ Knowledge│ │ SECS/GEM │
    #   │ (MySQL)  │ │ Base     │ │ Gateway  │
    #   └──────────┘ └──────────┘ └──────────┘

    3.2 五大工具模块

    工具名称

    功能

    数据源

    alarm_query

    查询当前和历史报警

    FDC系统 / MySQL

    equipment_status

    获取设备运行状态

    SECS/GEM / OPC UA

    knowledge_search

    检索维修知识库

    ChromaDB向量库

    history_analysis

    分析同类故障历史

    MES / InfluxDB

    ticket_generator

    生成维修工单

    MES API

    四、核心代码实现

    4.1 环境准备

    # requirements.txt
    langchain==0.1.0
    langchain-openai==0.0.2
    langchain-community==0.0.2
    chromadb==0.4.22
    pymysql==1.1.0
    influxdb-client==1.38.0
    fastapi==0.109.0
    uvicorn==0.27.0

    4.2 定义工具函数

    # tools.py – 五大工具模块
    import pymysql
    import json
    from datetime import datetime, timedelta
    from langchain.tools import tool
    from typing import Dict, List

    @tool
    def alarm_query(equipment_id: str, hours: int = 24) -> str:
        """
        查询指定设备的报警记录。
        
        Args:
            equipment_id: 设备编号(如 ETCH-001)
            hours: 查询最近多少小时的数据,默认24小时
        
        Returns:
            报警记录JSON字符串
        """
        conn = pymysql.connect(
            host="192.168.1.100",
            user="fab_readonly",
            password="xxx",
            database="fdb",
            charset="utf8mb4"
        )
        
        start_time = datetime.now() – timedelta(hours=hours)
        
        with conn.cursor(pymysql.cursors.DictCursor) as cursor:
            sql = """
            SELECT alarm_id, equipment_id, alarm_code, alarm_message,
                   severity, timestamp, status
            FROM fdc_alarm_log
            WHERE equipment_id = %s AND timestamp >= %s
            ORDER BY timestamp DESC
            LIMIT 50
            """
            cursor.execute(sql, (equipment_id, start_time))
            results = cursor.fetchall()
        
        conn.close()
        return json.dumps(results, ensure_ascii=False, default=str)

    @tool
    def knowledge_search(query: str, top_k: int = 3) -> str:
        """
        从维修知识库中检索相关的SOP和案例。
        
        Args:
            query: 搜索关键词或问题描述
            top_k: 返回最相关的结果数量
        
        Returns:
            相关知识文档列表
        """
        import chromadb
        from chromadb.utils import embedding_functions
        
        client = chromadb.PersistentClient(path="./knowledge_db")
        ef = embedding_functions.SentenceTransformerEmbeddingFunction(
            model_name="shibing624/text2vec-base-chinese"
        )
        collection = client.get_collection(
            name="maintenance_sop",
            embedding_function=ef
        )
        
        results = collection.query(
            query_texts=[query],
            n_results=top_k
        )
        
        output = []
        for i, doc in enumerate(results["documents"][0]):
            output.append({
                "rank": i + 1,
                "content": doc[:2000],  # 截断过长内容
                "metadata": results["metadatas"][0][i]
            })
        
        return json.dumps(output, ensure_ascii=False, indent=2)

    @tool
    def history_analysis(equipment_id: str, alarm_code: str) -> str:
        """
        分析指定设备和报警码的历史处理记录,
        找出最常见的根因和处理方案。
        
        Args:
            equipment_id: 设备编号
            alarm_code: 报警码
        
        Returns:
            历史分析报告
        """
        conn = pymysql.connect(
            host="192.168.1.100",
            user="fab_readonly",
            password="xxx",
            database="mes",
            charset="utf8mb4"
        )
        
        with conn.cursor(pymysql.cursors.DictCursor) as cursor:
            # 查询该设备+报警码的历史工单
            sql = """
            SELECT root_cause, solution, repair_duration_minutes,
                   COUNT(*) as occurrence_count
            FROM work_order
            WHERE equipment_id = %s AND alarm_code = %s
              AND status = 'COMPLETED'
            GROUP BY root_cause, solution
            ORDER BY occurrence_count DESC
            LIMIT 10
            """
            cursor.execute(sql, (equipment_id, alarm_code))
            results = cursor.fetchall()
            
            # 统计平均修复时间
            cursor.execute("""
            SELECT AVG(repair_duration_minutes) as avg_duration,
                   MIN(repair_duration_minutes) as min_duration,
                   MAX(repair_duration_minutes) as max_duration
            FROM work_order
            WHERE equipment_id = %s AND alarm_code = %s AND status = 'COMPLETED'
            """, (equipment_id, alarm_code))
            stats = cursor.fetchone()
        
        conn.close()
        
        report = {
            "historical_cases": results,
            "statistics": {
                "avg_repair_time_min": round(stats["avg_duration"], 1),
                "min_repair_time_min": stats["min_duration"],
                "max_repair_time_min": stats["max_duration"],
                "total_cases": sum(r["occurrence_count"] for r in results)
            }
        }
        
        return json.dumps(report, ensure_ascii=False, indent=2)

    @tool
    def ticket_generator(
        equipment_id: str,
        alarm_code: str,
        root_cause: str,
        solution: str,
        priority: str = "MEDIUM"
    ) -> str:
        """
        自动生成维修工单并提交到MES系统。
        
        Args:
            equipment_id: 设备编号
            alarm_code: 报警码
            root_cause: 诊断出的根因
            solution: 推荐的解决方案
            priority: 优先级(HIGH/MEDIUM/LOW)
        
        Returns:
            工单号和提交结果
        """
        import requests
        
        ticket_data = {
            "equipment_id": equipment_id,
            "alarm_code": alarm_code,
            "root_cause": root_cause,
            "solution": solution,
            "priority": priority,
            "created_by": "AI_Agent_V1",
            "created_at": datetime.now().isoformat(),
            "source": "intelligent_maintenance_agent"
        }
        
        response = requests.post(
            "http://mes-api.internal:8080/api/v1/work-order",
            json=ticket_data,
            timeout=10
        )
        
        result = response.json()
        result["ai_generated"] = True
        result["confidence"] = "HIGH" if priority == "HIGH" else "MEDIUM"
        
        return json.dumps(result, ensure_ascii=False, indent=2)

    @tool
    def equipment_status(equipment_id: str) -> str:
        """
        获取设备当前的实时运行状态。
        
        Args:
            equipment_id: 设备编号
        
        Returns:
            设备状态信息(温度、压力、运行模式等)
        """
        # 通过OPC UA或SECS/GEM获取实时数据
        # 这里用模拟数据演示
        import random
        
        status = {
            "equipment_id": equipment_id,
            "timestamp": datetime.now().isoformat(),
            "mode": random.choice(["PROCESSING", "IDLE", "MAINTENANCE", "ALARM"]),
            "chamber_temp": round(random.uniform(20, 80), 1),
            "chamber_pressure": round(random.uniform(5, 50), 2),
            "rf_power": round(random.uniform(300, 1500), 1),
            "utilization_today": round(random.uniform(0.6, 0.95), 2),
            "last_pm_date": "2026-05-15",
            "days_since_pm": 20
        }
        
        return json.dumps(status, ensure_ascii=False, indent=2)

    4.3 组装Agent

    # agent.py – 组装智能运维Agent
    from langchain.agents import create_react_agent, AgentExecutor
    from langchain_openai import ChatOpenAI
    from langchain_core.prompts import ChatPromptTemplate
    from tools import (
        alarm_query, knowledge_search,
        history_analysis, ticket_generator, equipment_status
    )

    # 初始化LLM
    llm = ChatOpenAI(
        model="gpt-4-turbo-preview",
        temperature=0,
        streaming=True
    )

    # 工具列表
    tools = [
        alarm_query,
        knowledge_search,
        history_analysis,
        ticket_generator,
        equipment_status
    ]

    # System Prompt – 这是关键!
    system_prompt = """你是一个专业的半导体晶圆厂智能运维助手。

    ## 你的身份
    – 你服务于一家12英寸(300mm)半导体晶圆厂
    – 你的职责是帮助工程师快速诊断设备故障、提供维修建议
    – 你有15年半导体设备维护经验的知识储备

    ## 你的能力
    你可以使用以下工具:
    1. alarm_query: 查询设备报警记录
    2. knowledge_search: 检索维修知识库(SOP、历史案例)
    3. history_analysis: 分析同类故障的历史处理记录
    4. ticket_generator: 生成维修工单
    5. equipment_status: 获取设备实时状态

    ## 工作流程
    当收到设备报警时,请按以下步骤操作:

    Step 1: 使用 equipment_status 获取设备当前状态
    Step 2: 使用 alarm_query 查询最近的报警记录
    Step 3: 使用 history_analysis 分析历史同类故障
    Step 4: 使用 knowledge_search 检索相关知识库
    Step 5: 综合以上信息,给出诊断结论和建议方案
    Step 6: 如果用户确认,使用 ticket_generator 生成工单

    ## 输出格式
    请用中文回复,格式如下:

    —
    【设备】ETCH-001 | 【报警】VACUUM_LOSS
    【诊断结论】真空泵密封圈老化导致真空度下降
    【置信度】85%(基于3次历史相似案例)
    【推荐方案】更换真空泵密封圈(Part#: VP-SEAL-200)
    【预计耗时】45分钟
    【历史参考】近6个月内同类故障4次,平均修复时间42分钟
    —

    ## 注意事项
    – 安全第一!如果涉及高压、有毒气体,必须提醒安全注意事项
    – 不要编造数据,如果工具返回空结果,如实告知
    – 建议具体到零件号(Part Number)和操作步骤
    """

    prompt = ChatPromptTemplate.from_messages([
        ("system", system_prompt),
        ("human", "{input}"),
        ("placeholder", "{agent_scratchpad}"),
    ])

    # 创建Agent
    agent = create_react_agent(llm, tools, prompt)
    agent_executor = AgentExecutor(
        agent=agent,
        tools=tools,
        verbose=True,
        max_iterations=10,
        handle_parsing_errors=True,
        return_intermediate_steps=True
    )

    # 运行示例
    if __name__ == "__main__":
        result = agent_executor.invoke({
            "input": "ETCH-001设备刚刚报了VACUUM_LOSS报警,请帮我诊断一下"
        })
        print(result["output"])

    五、上线效果与数据对比

    5.1 关键指标提升

    指标

    上线前

    上线后

    提升幅度

    平均故障响应时间

    25分钟

    3分钟

    -88%

    平均故障诊断时间

    35分钟

    8分钟

    -77%

    平均工单填写时间

    15分钟

    2分钟

    -87%

    单次故障总处理时间

    95分钟

    53分钟

    -44%

    知识库命中率

    N/A

    78%

    新指标

    重复故障率

    23%

    12%

    -48%

    夜班独立处理率

    45%

    82%

    +37%

    5.2 一个真实案例

    上线第三天的一个真实案例:

    **时间**:凌晨02:17(夜班,只有1名初级工程师值班)

    **事件**:CVD-003设备报 TEMPERATURE_OVERRUN 报警

    **Agent处理过程**:

    === Agent 执行日志 ===

    [STEP 1] 获取设备实时状态
    → CVD-003: Chamber Temp = 485°C (正常范围: 400±10°C)
    → Mode: ALARM | Utilization Today: 92%

    [STEP 2] 查询最近24小时报警记录
    → 发现5条报警:3条TEMP_OVERRUN, 2条PRESSURE_LOW
    → 首次报警:01:43

    [STEP 3] 历史同类故障分析
    → 近1年类似故障:18次
    → 最常见根因(67%):加热器Thermocouple漂移
    → 平均修复时间:52分钟

    [STEP 4] 知识库检索
    → 匹配到3篇相关SOP:
      [1] CVD加热器校准标准程序 (匹配度: 94%)
      [2] Thermocouple更换作业指导书 (匹配度: 89%)
      [3] CVD温度异常排查Checklist (匹配度: 86%)

    [STEP 5] 综合诊断
    → 结论:Zone 3热电偶漂移,偏差约+15°C
    → 置信度:82%(基于历史18次相似案例)
    → 建议:执行热电偶校准,如偏差>10°C则更换

    [STEP 6] 生成工单
    → 工单号: WO-20260604-0217
    → 优先级: HIGH
    → 预计耗时: 45分钟

    === 总耗时: 3分42秒 ===

    这位初级工程师按照Agent的建议,45分钟内完成了热电偶校准,设备恢复正常。如果是以前,他可能要打电话给资深工程师,或者翻阅大量文档,至少折腾1-2个小时。

    六、踩坑经验与优化建议

    6.1 遇到的坑

    坑点

    表现

    解决方法

    LLM幻觉

    编造不存在的零件号

    限制工具输出,强制引用来源

    上下文溢出

    长对话后忘记前面的信息

    加入记忆摘要机制

    工具调用循环

    Agent反复调用同一工具

    设置max_iterations=10

    延迟敏感

    知识库检索太慢

    预计算embedding,加缓存

    安全风险

    Agent建议了危险操作

    System Prompt中加入安全约束

    6.2 优化方向

    • **模型本地化**:部署私有化LLM(如Qwen-72B),降低数据外泄风险和API成本
    • **多模态接入**:接入设备摄像头图片,让Agent能'看'设备状态
    • **预测性维护**:结合时序预测模型,在故障发生前预警
    • **多Agent协作**:拆分为诊断Agent、方案Agent、执行Agent,用CrewAI编排

    七、总结

    通过这个项目,我有几点深刻的体会:

  • **AI Agent不是万能的,但在特定场景下极其有效**。工业现场的故障诊断有明确的流程和丰富的历史数据,这正是Agent擅长的领域。
  • **工具设计是成败的关键**。Agent的能力边界由工具决定。我们花了40%的时间在设计和调试工具上,只有20%的时间在调Prompt。
  • **从小处着手,快速迭代**。不要一开始就追求完美。我们先做了一个只能查报警的单功能版本,跑通后再逐步添加功能。
  • **人机协同比全自动更现实**。目前阶段,Agent的角色是'超级助手'而非'替代者'。它负责信息聚合和初步判断,最终决策还是人来拍板。
  • —

    **�� 关注我,持续分享半导体智能制造领域的AI实战经验!**

    **�� 你在工业现场用过AI吗?欢迎评论区分享你的经验,我会一一回复!**

    赞(0)
    未经允许不得转载:171主机测评 » AI编程实战:我用Python+LangChain搭建了一个半导体FAB智能运维Agent
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址