先说几个核心判断。在电信运营商的日常运维中,“故障→修复”这件事,考验的远不止是网络本身,更是整个组织的信息流转和流程协同。单靠人力排班和经验规则,在高并发和复杂依赖面前,早晚会崩盘。而指望一次性把所有信息都丢给大模型、让它“全剧终”,也会因为上下文窗口、时序依赖、接口幂等等工程问题,分分钟翻车。
那么,出路在哪?不是找一个更强的模型,而是换个思路——把「智能判断」变成「可控流程」。具体来说,就是把模型的判断作为一个节点,把工单、告警、计费这些都做成受控接口,然后用工作流把这些节点按规则串起来。这就是本文想讲清楚的核心视角。接下来,你会看到清晰的原理、面向运营商的实战样例,以及可以直接运行的工程代码——能立刻验证思路并产生业务价值。

一、从招人看门道:工作流到底解决了什么问题
想象一下,运营商需要招一位什么样的“员工”来应付海量用户请求?
- 能快速判断问题类型(断网、账单、套餐变更、新装),并且懂得先用合适的话术安抚用户;
- 能把复杂的流程拆解开来——比如断网场景,要经历排查、生成工单、派单、跟进、反馈,而且每一步都能做清晰记录;
- 还得懂得什么时候该放手——遇到高风险或需要现场介入的场景,能自动升级到人工或NOC(网络运营中心)。
把“模型+代码”作为这个员工的智能中枢,工作流就是它的SOP(标准操作流程)和流水线。道理其实挺朴素的。
二、单次请求为什么扛不住?
让一个模型单次对话就搞定一切,现实中有三个很要命的局限:
- 上下文窗口不够用:用户的历史记录、设备信息、基站状态、上次的工单内容……这些信息一长,根本没法一次性全塞进prompt里。
- 思路不可见,但又不能暴露给用户:直接让模型写思维链(CoT),会把内部推演过程“写给用户看”,既不专业也显得不成熟。
- 时序依赖太重:工单生成后,还有异步回调、第三方接口、现场派单、收费结算……这些操作都需要跨请求来管理状态。一次对话根本hold不住。
单靠“问一句、答一句”,在运营商的业务场景里,就是一条走不通的路。
三、工作流到底带来了什么好处?
好处是显而易见的:
- 节点职责清晰:比如“意图识别”“设备定位”“本地化排障规则”“生成工单”“派单给工程师”“客户回访”——每个节点只管自己的事,边界清楚。
- 外部系统想插就插:在节点里可以直接调用OSS/BSS接口、计费系统、工单系统或者告警平台,不费劲。
- 中间状态可审计:每个节点产出的结构化数据——比如
ticket_id、site_id、confidence——都能持久化,方便事后回溯和统计。 - 自动化是可控的:对低风险且能自动修复的问题(比如远程重启、配置下发),工作流可以直接执行;高风险场景则自动转向人工,绝不会失控。
四、面向电信运营商的工作流实战(Agently 示例代码)
下面这段代码,展示的就是一个面向运营商客服/故障处理场景的完整工作流。我们设定的场景是:用户报障(比如家庭宽带断网)或咨询(账单、流量异常、套餐变更)。工作流会走完以下流程:意图识别 → 快速安抚 → 设备/用户信息查询 → 线下排障规则判断 → 生成或更新工单 → 派单或提示自助操作 → 最终回复用户。
前提是,你已经在工程里配好了模型API(在ENV中设置deep_seek_url、deep_seek_api_key、deep_seek_default_model),并且能正常使用Agently框架。如果没有Agently,把业务逻辑移植到等效的框架中也完全可行。
# file: telecom_workflow_agently.py
from ENV import deep_seek_url, deep_seek_api_key, deep_seek_default_model
import Agently
import time
import json
# 创建 agent(示例)
agent = (
Agently.create_agent()
.set_settings("current_model", "OAIClient")
.set_settings("model.OAIClient.url", deep_seek_url)
.set_settings("model.OAIClient.auth", {"api_key": deep_seek_api_key})
.set_settings("model.OAIClient.options", {"model": deep_seek_default_model})
)
# 假设:有本地函数封装对 OSS/BSS/工单系统的简单调用
def query_customer_info(msisdn):
# 伪代码:实际应调用 BSS/CRM 接口
return {"customer_name": "张先生", "address": "上海市浦东区", "site_id": "SITE-1001", "last_visit": "2025-08-20"}
def query_latest_alarm(site_id):
# 伪代码:调用告警系统或基站监控
# 返回最近 24 小时的关键告警摘要
return {"has_recent_alarm": True, "alarm_summary": "OLT link flapping"}
def create_ticket(payload):
# 伪代码:写入工单系统,返回 ticket_id
return f"TICKET-{int(time.time())}"
def assign_to_engineer(ticket_id, skill):
# 伪代码:派单逻辑
return {"assigned": True, "engineer_id": "ENG-237"}
# 工作流定义
workflow = Agently.Workflow()
@workflow.chunk()
def user_input(inputs, storage):
storage.set("user_input", input("[请输入用户描述或工单ID/MSISDN]: ").strip())
return
@workflow.chunk()
def detect_intent(inputs, storage):
# 用模型来做意图分类(更精细的规则可以结合本地正则/黑白表)
result = (
agent
.input(storage.get("user_input"))
.output({
"intent": ("断网 | 账单 | 套餐变更 | 查询工单 | 其他", "判断用户请求属于哪类"),
"confidence": ("float", "模型对意图判断的置信度(0-1)")
})
.start()
)
storage.set("intent", result["intent"])
storage.set("intent_confidence", result.get("confidence", 0.9))
return result["intent"]
@workflow.chunk()
def quick_ack_and_guidance(inputs, storage):
# 立即给出快速安抚或指引(提升用户体验)
intent = storage.get("intent")
if intent == "断网":
quick = "我们已收到您关于断网的报告,正在为您排查。请先确认路由器电源是否正常并尝试重启。"
elif intent == "账单":
quick = "收到关于账单的咨询,请稍等,我帮您查看最近账单明细。"
elif intent == "查询工单":
quick = "请提供工单号或我们将根据您的号码查询最近工单进展。"
else:
quick = "已收到您的问题,我们会尽快处理。"
storage.set("quick_reply", quick)
print("[快速回复]:", quick)
return
@workflow.chunk()
def enrich_with_customer_info(inputs, storage):
# 从输入解析 MSISDN 或工单号(此处简化)
text = storage.get("user_input")
msisdn = None
ticket_id = None
if text.upper().startswith("TICKET-"):
ticket_id = text.strip().upper()
else:
msisdn = text # 假设直接输入手机号
storage.set("msisdn", msisdn)
storage.set("ticket_id", ticket_id)
if msisdn:
cust = query_customer_info(msisdn)
storage.set("customer_info", cust)
return
@workflow.chunk()
def diagnose_and_route(inputs, storage):
intent = storage.get("intent")
cust = storage.get("customer_info", {})
# 结合本地规则与模型建议决定是否立刻生成工单或给出自助指引
if intent == "断网":
# 查询告警系统
site_id = cust.get("site_id")
alarm = query_latest_alarm(site_id) if site_id else {"has_recent_alarm": False}
storage.set("alarm", alarm)
# 模型建议(使用模型来补充自然语言诊断与操作建议)
model_suggest = agent.input(
f"""用户:{storage.get("user_input")}
已知信息:{json.dumps(cust)}
最近告警:{json.dumps(alarm)}
请判断是否需要生成现场工单,或先引导用户做远程排查(如重启ONT/路由器)。
输出格式:{{"action":"dispatch|remote_diagnose|ask_more_info","reason":"str","estimated_time_minutes":int}}"""
).start()
# 约定模型返回结构化数据(实际需用 output/schema 强制)
# 这里假设模型返回 JSON 字符串
try:
suggestion = json.loads(model_suggest)
except Exception:
suggestion = {"action": "dispatch", "reason": "模型解析失败,默认派单", "estimated_time_minutes": 60}
storage.set("suggestion", suggestion)
elif intent == "账单":
# 直接拉账单数据(伪)
storage.set("bill_summary", {"last_amount": 98.5, "due_date": "2025-09-05"})
return storage.get("suggestion", None)
@workflow.chunk()
def execute_action(inputs, storage):
suggestion = storage.get("suggestion", {})
if suggestion.get("action") == "dispatch":
payload = {
"msisdn": storage.get("msisdn"),
"customer": storage.get("customer_info"),
"alarm": storage.get("alarm"),
"reason": suggestion.get("reason")
}
ticket_id = create_ticket(payload)
storage.set("ticket_id", ticket_id)
assign = assign_to_engineer(ticket_id, skill="OLT/FTTx")
storage.set("assignment", assign)
storage.set("reply", f"已为您创建工单 {ticket_id},预计处理时间约 {suggestion.get('estimated_time_minutes')} 分钟,工程师 {assign.get('engineer_id')} 会跟进。")
elif suggestion.get("action") == "remote_diagnose":
# 可下发远程命令或给用户自助操作步骤
storage.set("reply", "请先按以下步骤:1) 断电30秒后重启路由器;2) 若仍有问题,请告知指示灯状态。")
else:
storage.set("reply", "需要更多信息,请描述您看到的指示灯状态或上次何时能正常使用。")
return
@workflow.chunk_class()
def final_reply(inputs, storage):
print("[最终回复]:", storage.get("reply"))
return
(
workflow
.connect_to("user_input")
.connect_to("detect_intent")
.connect_to("quick_ack_and_guidance")
.connect_to("enrich_with_customer_info")
.connect_to("diagnose_and_route")
.connect_to("execute_action")
.connect_to("final_reply")
)
if __name__ == "__main__":
workflow.start()
代码的关键点说明
快速回复(quick_ack_and_guidance):在后台做复杂判断之前,先给用户一个即时反馈。这不仅能提升用户体验,还能有效减少用户因为等待而重复催促的情况。
enrich_with_customer_info:把OSS/BSS/CRM的真实数据拉到工作流里,为后续的判断节点提供“弹药”。
diagnose_and_route:把“模型推理”和“本地规则(告警、黑白表)”结合起来做决策。既利用了模型的泛化能力,又保留了工程上的可控性。
execute_action:把最终的执行动作(下发远程命令、生成工单、派单)封装成幂等的API调用,并把
ticket_id等关键信息存入storage,方便后续查询和追溯。可扩展点:把
create_ticket、assign_to_engineer替换成公司真实的工单平台API,并在节点前后加上schema验证与异常重试逻辑,就基本能投产了。
五、落地工程中的几个注意事项
幂等性不是锦上添花,是底线:派单、计费等操作必须保证幂等。用业务键(比如
msisdn + alarm_hash)来防止重复执行,是基本操作。告警与工单的去重:同一故障可能会触发多条告警。工单系统需要设计合理的聚合策略——比如同站点5分钟内同类告警只产生一个工单。
SLA驱动的分级处理:对高价值客户或SLA要求高的业务(比如企业专线),应该设计不同的工作流分支——优先派单、专员跟进,都是常规操作。
审计与回溯:存储每个节点的输入输出(记得脱敏),并保留版本号。这对于事后追责、模型迭代和规则调整来说,非常关键。
灰度策略很重要:先在小范围(比如某个城市、某类故障)跑自动化,持续观测误判率和NPS,再逐步扩大范围。千万别一上来就全量铺开。
人机协作界面:为人工客服和工程师提供一个“操作建议+证据链”的界面(比如模型的诊断理由、相关告警快照),让人能更快决策,而不是完全依赖模型。
安全与隐私:手机号、地址、账单金额这类敏感信息,在日志中必须掩码。如果模型返回的内容可能包含敏感推断,应该自动触发人工复核。
六、实战示例:典型对话与工作流走向
用户输入:
家里宽带突然断线了,路由器指示灯只有 PON 亮- detect_intent → 断网
- quick_reply → “我们收到断网报告,请先重启设备...”
- enrich → 拉到site_id与最近告警(发现OLT link flapping)
- diagnose → 模型建议派单
- execute → 创建工单、派单给具备OLT经验的工程师
- final_reply → 给用户工单号与预计处理时长
用户输入:
我的上月账单异常,多扣了流量- detect_intent → 账单
- quick_reply → “收到账单咨询,正在核实...”
- enrich → 拉取账单摘要
- diagnose → 如果金额异常且是小额,可以走自动退款流程;否则转人工审核。
七、指标与持续改进
- 关键指标:自动处理率、误判率(误派工单)、平均修复时长(MTTR)、NPS/用户满意度、人工接入率——这些都应该纳入日常监控看板。
- 持续改进:定期把误判样本回流,用于优化prompt或规则。按工单类型设置微调优先级——高频问题,优先优化。
八、总结
工作流干的,就是把“人类的分工思路”、“工程化的执行规范”和“模型的智能判断”拧成一股绳。在运营商这个场景里,它是把“智能”变成“稳定服务”的关键路径。
把模型能力视为“判断与建议”,把核心的写操作(工单、计费、派单)视为受控的接口和节点——做到了这一点,你就能同时拥有自动化带来的效率和工程上的可控性。
当工作流把“判断—决策—执行”拆成一串可观测、可回溯的节点时,智能就不再是“猜”,而是变成了一种可以被衡量、被改进、被数据证明的能力。对于运营商来说,这意味着更少的误派工单、更短的平均修复时间(MTTR)、更高的自动化通过率,以及更少的客户流失。
把模型当作“建议引擎”,把工作流当作“执行引擎”——每一次客户投诉,都可能变成一次可以被复制、被量化的服务改进。这才是把智能变成运营竞争力的实际路径。
