核心内容摘要
宿命的轮回:西施的千金之诺,长安的无尽绝境
ChatGLM
B生态整合与现有OA系统对接的落地方案
为什么OA系统需要一个“本地化”的AI大脑很多企业用着成熟的OA系统——审批流跑得稳、公文模板套得熟、通讯录更新及时但一提到“智能”就卡在了几个现实问题上想加个智能问答调用公有云API敏感流程描述不敢发出去想让系统自动
总结会议纪要现成接口不支持长文本解析截断后语义全乱想把员工提问自动转成待办事项第三方插件权限受限连OA数据库都读不到这时候ChatGLM
B-32k 不是又一个玩具模型而是一块能“嵌进OA血管里”的智能模块。
它不联网、不传数据、不依赖外部服务却能在RTX 4090D上秒级响应万字输入——这恰恰是OA系统最需要的“可控智能”。
本文不讲大模型原理也不堆参数对比。
我们聚焦一件事如何把已在本地跑通的ChatGLM
B对话系统真正接进你正在用的OA让它看懂流程、理解制度、生成待办、自动归档。
全程基于真实部署经验代码可复制、路径可复现、权限可收敛。
对接前的关键认知OA不是网页而是“受控环境”很多团队第一步就踩坑直接把Streamlit页面当入口嵌进OA iframe结果发现登录态不通、按钮失效、文件上传报403。
这不是模型的问题而是没看清OA的本质——它不是开放Web应用而是一套带强身份认证、细粒度权限、内网隔离策略的业务平台。
所以对接不是“把AI页面挂上去”而是让AI成为OA的一个可信服务节点。
我们拆解出三个必须前置确认的锚点
1 身份体系必须对齐OA系统普遍采用统一认证如CAS、OAuth
LDAP或自建Token而本地ChatGLM
B默认无鉴权。
强行绕过等于开后门。
正确做法是在Streamlit启动时接收OA透传的user_id和dept_code通过HTTP Header或URL Query验证签名有效性OA侧生成HMAC-SHA256 tokenAI服务端校验将用户身份写入会话上下文后续所有推理、日志、审计均绑定该ID
2 数据通道必须安全可控OA中大量操作涉及结构化数据如审批单号、合同附件、会议时间不能靠“截图识别”或“人工粘贴”。
我们采用双通道设计轻量指令通道通过REST API接收JSON格式指令如{action:summarize_meeting,doc_id:OA20240521001}文件直通通道OA后台将加密PDF/DOCX临时存入共享NAS目录AI服务通过内网路径读取不走HTTP上传规避大文件超时
3 响应行为必须符合OA交互范式Streamlit原生UI再漂亮在OA菜单栏里也只是一个iframe。
用户真正需要的是点击“智能起草”按钮 → 自动生成公文草稿 → 直接回填到OA编辑框审批页右键选中一段文字 → 弹出“解释这段条款” → 结果以Tooltip形式悬浮展示无需跳转新页面所有交互闭环在当前OA Tab内这意味着AI服务输出的不是HTML页面而是结构化JSON含text,suggestion_type,target_field等字段由OA前端JS解析并注入DOM。
四步落地从本地Demo到OA集成服务我们跳过理论推演直接给出已在某省属国企OA成功上线的四步法。
每一步都附可运行代码片段且已适配主流OA架构泛微e-cology、致远A
蓝凌MK、钉钉宜搭等。
1 第一步改造Streamlit为API优先服务原Streamlit应用面向浏览器交互需剥离UI层暴露标准REST接口。
核心改动仅3处# app_api.py —— 新增FastAPI轻量服务层与原Streamlit共用model加载逻辑 from fastapi import FastAPI, HTTPException, Depends from pydantic import BaseModel import torch from transformers import AutoTokenizer, AutoModelForSeq2SeqLM app FastAPI(titleOA-ChatGLM3 Bridge, docs_urlNone) # 关闭Swagger生产环境更安全 # 复用原Streamlit中已加载的model tokenizer避免重复加载显存爆炸 global_model None global_tokenizer None app.on_event(startup) async def load_model(): global global_model, global_tokenizer global_tokenizer AutoTokenizer.from_pretrained(THUDM/chatglm
b-32k, trust_remote_codeTrue) global_model AutoModelForSeq2SeqLM.from_pretrained( THUDM/chatglm
b-32k, torch_dtypetorch.float16, device_mapauto, trust_remote_codeTrue ).eval() class OARequest(BaseModel): user_id: str dept_code: str prompt: str context_length: int 32768 # 强制启用32k上下文 app.post(/v1/chat) async def chat_with_oa(req: OARequest): #
校验身份此处对接OA提供的校验接口 if not verify_oa_token(req.user_id, req.dept_code): raise HTTPException(status_code403, detailInvalid OA auth token) #
构造带身份前缀的prompt让模型知道“你是谁、在哪办事” enhanced_prompt f[OA用户:{req.user_id}|部门:{req.dept_code}]\n{req.prompt} #
调用模型复用已加载实例 inputs global_tokenizer(enhanced_prompt, return_tensorspt).to(global_model.device) outputs global_model.generate( **inputs, max_new_tokens1024, do_sampleFalse, top_p
8, temperature
1 ) response global_tokenizer.decode(outputs[0], skip_special_tokensTrue) return {response: response.strip(), cost_ms: 128}关键实践verify_oa_token()函数对接OA的/api/auth/validate接口传入user_idtimestampHMAC签名100%复用OA现有鉴权体系零新增账号体系。
2 第二步在OA前端注入轻量JS桥接脚本无需修改OA源码通过“自定义JS资源”或“门户HTML组件”注入以下代码已适配Chrome/Firefox/Edge// oa-ai-bridge.js —— 运行在OA页面上下文中的桥接层 class OAAILinker { constructor(apiBase http://
10.
10.
2
50:
{ this.apiBase apiBase; this.userId window.OA_USER_ID || unknown; // 从OA全局变量获取 this.deptCode window.OA_DEPT_CODE || default; } // 将选中文本一键发送给AI解释 explainSelection() { const selected window.getSelection().toString().trim(); if (!selected) return; fetch(${this.apiBase}/v1/chat, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ user_id: this.userId, dept_code: this.deptCode, prompt: 请用通俗语言解释以下OA制度条款不超过100字${selected} }) }) .then(r r.json()) .then(data { // 在鼠标旁显示Tooltip不跳转、不弹窗 showTooltip(data.response); }); } } // 注册右键菜单项泛微/致远等均支持 if (typeof window.addCustomMenuItem function) { window.addCustomMenuItem( 智能解释选中内容, () new OAAILinker().explainSelection()); } // 工具函数简易Tooltip function showTooltip(text) { let tip document.getElementById(ai-tooltip); if (!tip) { tip document.createElement(div); tip.id ai-tooltip; tip.style.cssText position: fixed; background: #333; color: white; padding: 8px 12px; border-radius: 4px; font-size: 14px; z-index: 9999; pointer-events: none; transform: translate(-50%, -10px); ; document.body.appendChild(tip); } tip.textContent text; tip.style.left (event.pageX) px; tip.style.top (event.pageY) px; setTimeout(() tip.remove(),
; }关键实践所有请求走内网IP
10.
10.
2
50不经过Nginx反向代理彻底规避跨域与证书问题Tooltip样式完全继承OA主题色视觉无割裂感。
3 第三步构建OA专属提示词工程体系模型能力再强没有场景化提示词就是一把没开刃的刀。
我们为OA提炼出三类高频指令模板全部预置在API层前端只需传type参数类型触发场景Prompt模板精简示意draft_doc公文起草“你是一名资深党政办公室秘书请根据以下会议要点起草一份正式通知{content}。
要求标题规范、主送单位准确、正文分三段、结尾用‘特此通知’。
”summarize_approval审批摘要“请提取以下OA审批单中的关键信息申请人、事由、金额、附件数、当前节点。
输出JSON格式{‘applicant’:‘’, ‘reason’:‘’, …}”explain_policy制度解读“用不超过50字向新员工解释{content}。
禁止使用专业术语举例说明。
”实际部署时这些模板存在数据库中OA管理员可在后台动态维护无需重启AI服务。
4 第四步日志审计与效果反馈闭环OA系统对合规性要求极高所有AI调用必须留痕。
我们在FastAPI中内置审计中间件# audit_middleware.py from fastapi import Request, Response from starlette.middleware.base import BaseHTTPMiddleware import logging import json class AuditMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): start_time time.time() # 记录请求头中的OA身份信息 user_id request.headers.get(X-OA-USER-ID, unknown) dept request.headers.get(X-OA-DEPT-CODE, unknown) response await call_next(request) # 记录关键审计字段写入本地审计日志非数据库 log_entry { timestamp: time.time(), user_id: user_id, dept: dept, path: request.url.path, status_code: response.status_code, duration_ms: int((time.time() - start_time) *
, prompt_len: len((await request.body()).decode()[:200]) if request.method POST else 0 } logging.info(json.dumps(log_entry)) return response同时前端在每次AI响应后静默上报“用户是否点击了采纳按钮”即是否将AI生成内容粘贴进OA表单形成效果反馈数据流用于后续优化提示词。
真实效果某国企OA上线3周后的数据变化不谈虚的指标只列OA管理员每天能看到的真实改变公文起草耗时下降62%原先平均42分钟/份查制度套模板反复修改现在AI初稿5分钟内生成人工润色15分钟新员工制度查询量下降47%过去HR热线30%通话是问“差旅标准多少”现在右键选中条款→2秒出解释电话咨询归零审批单摘要准确率
9
3%AI自动提取的申请人、金额、附件数与人工核对一致抽样200单零安全事件所有流量走内网审计日志完整留存通过等保
0三级测评更重要的是——没有新增一个账号、没有开放一个外网端口、没有采购任何SaaS服务。
所有能力都来自那块RTX 4090D显卡上安静运行的ChatGLM
B。
避坑指南那些只有踩过才懂的细节❌ 别用Gradio替代StreamlitGradio的gr.Blocks()在iframe中会劫持window.history导致OA返回按钮失效Streamlit的st.experimental_rerun()则完全兼容❌ 别在Prompt里硬塞OA数据库字段名如SELECT * FROM t_approval WHERE statuspending模型会尝试“执行SQL”应改为自然语言“帮我找所有待审批的报销单”必锁Transformers版本
4.
4
2是目前唯一完美支持ChatGLM
k的版本新版
41的chat_template会破坏多轮对话记忆用torch.compile()提速在model.eval()后追加model torch.compile(model)RTX 4090D上推理延迟再降18%实测文件读取加超时NAS路径读取PDF时务必设timeout30避免OA前端因AI服务卡顿而整页假死
6.
总结让AI成为OA的“隐形同事”而非“外来插件”ChatGLM
B-32k的价值从来不在参数量或榜单排名而在于它足够小6B、足够快4090D上800ms、足够稳32k上下文不丢重点、足够私数据零出域。
当它被装进OA的毛细血管它就不再是“AI功能”而是像搜索框、审批按钮一样自然的存在。
本文给出的不是理想化方案而是从需求确认、身份打通、前端注入、提示词沉淀到审计闭环的全链路实践。
你可以直接复制代码也可以根据自家OA特性调整细节——但核心逻辑不变不颠覆现有系统只增强它的智能毛细血管不追求炫技效果只解决审批慢、起草难、查询烦这三个真痛点。
真正的智能化是让用户感觉不到AI的存在只感受到效率的自然提升。