尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

AI-Meeting 项目复盘:WebSocket+Redis+MongoDB+LiteFlow 的配置骨架与验证清单

发布时间:2026/9/27 20:56:15

资讯中心
01
ARTICLE

AI-Meeting 项目复盘:WebSocket+Redis+MongoDB+LiteFlow 的配置骨架与验证清单

AI-Meeting 项目复盘:WebSocket+Redis+MongoDB+LiteFlow 的配置骨架与验证清单
1. AI-Meeting 项目复盘从“能跑”到“可验证”的工程骨架AI-Meeting 这类实时会议系统表面看是“上传音频、出文字、给评分”但真正决定它能不能稳定跑下去的是 WebSocket 长连接、Redis 热状态、MongoDB 持久化和 LiteFlow 规则编排这几条链路能不能协同工作。我这次复盘的目标不是讲概念而是给出一套可以在本地复现的配置骨架和逐项验证清单让你能确认每个组件到底通没通、数据有没有落对地方。适合谁看如果你正在做实时语音转写、AI 面试、在线会议纪要这类项目或者你已经有一个能跑的 Demo但不确定 Redis 丢了会不会崩、MongoDB 快照有没有写进去、LiteFlow 规则链有没有真正生效那这篇就是给你准备的。我会按“先配好、再验证、最后排障”的顺序来写每一步都有可复制的配置和可观察的结果。另外AI 工具侧的调用我会统一走 TaoToken 的 API 通道这样你不需要在多个模型平台之间来回切换 Key配置一次就能在评分、追问、抽题这些场景里复用。下面从项目场景开始拆。2. 原问题与场景四个组件各管什么为什么必须一起验证AI-Meeting 的核心链路可以压缩成一句话用户提交答案后系统要完成评分、追问裁决、flow 推进、turn log 写入和快照刷新。这条链路里四个组件各自承担不同职责任何一个没配好都会让长会话变得不可控。WebSocket 负责前端和后端之间的双向实时通信。前端持续上传音频分片后端持续把 ASR 识别结果推回前端。它不是“一次请求一次响应”而是长连接上的帧传输。验证 WebSocket 是否正常不能只看连接建没建上还要看二进制帧能不能持续写入、文本帧能不能持续回推。Redis 保存在线热状态比如当前 flow、当前题号、追问题缓存、分数聚合、最近 turn log 和幂等回放材料。它的特点是读写快适合高频变化的数据。但 Redis 不能当唯一真相源因为它可能过期、被淘汰、重启或网络抖动。验证 Redis 的重点不是“能不能连上”而是“写入后能不能读到、TTL 是否符合预期、丢失后能不能从 MongoDB 恢复”。MongoDB 保存恢复材料主要分三类Hot Snapshot 保存 flow、分数、近期状态Cold Snapshot 保存简历上下文、题库、岗位信息Turn Archive 保存每一轮答题轨迹。验证 MongoDB 的关键是确认快照有没有按 sessionId 正确写入以及 turn archive 的 archiveWatermark 有没有单调递增。LiteFlow 负责规则编排最典型的场景是追问裁决。评分 Agent 返回“是否建议追问”后系统不会完全听 AI 的而是把分数、缺失点、AI 建议、当前追问次数、最大追问次数、当前题类型组装成规则上下文交给 LiteFlow 规则链做最终判断。验证 LiteFlow 的重点是确认规则链真的被触发、上下文参数传对了、不同分支能走到对应结果。这四个组件的协作链路是WebSocket 收到答案 → Redis 加载热运行态 → 评分 Agent 调用 → LiteFlow 裁决追问 → 写 turn log → 刷新 MongoDB 快照。所以验证不能只测单个组件要按链路顺序逐项确认。3. TaoToken 前置统一 Key 与 API 通道接入 AI 工具侧在开始配 WebSocket、Redis、MongoDB 和 LiteFlow 之前先把 AI 调用侧的统一入口配好。AI-Meeting 里评分、追问、抽题、神态分析都会调模型如果每个场景各配一套 Key后面排查问题时会很乱。我建议统一走 TaoToken 的 API 通道配置一次后续所有 AI 调用都复用这个入口。先到 TaoToken 控制台创建一个 API Key。地址是 https://taotoken.net/api-keys 创建后复制保存后面配置文件里会用到。注意这个 Key 不要硬编码在代码里放到环境变量或配置中心。然后在项目配置文件里加上统一入口。下面是一个application-ai.yml的骨架你可以直接复制后改字段ai: provider: taotoken base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} timeout-ms: 30000 connect-timeout-ms: 5000 max-retries: 2 stages: interview-evaluation: model: claude-sonnet temperature: 0.3 max-tokens: 2048 interview-followup: model: claude-sonnet temperature: 0.5 max-tokens: 1024 interview-extraction: model: claude-sonnet temperature: 0.2 max-tokens: 4096 interview-demeanor: model: claude-sonnet temperature: 0.1 max-tokens: 1024这里base-url用https://taotoken.net/api不要加多余路径。api-key从环境变量读本地调试时可以临时 export。stages下面按业务场景分模型和参数这样后面 LiteFlow 规则链里引用 stage 时能直接对应到具体配置。如果你需要确认模型对话是否正常可以到 https://taotoken.net/models 先手动发一条测试消息确认 Key 有效、模型能返回。这一步不要跳过因为后面评分链路出问题时你至少能排除“Key 本身不通”这个因素。对于长期做编码和 Agent 场景的可以了解 Coding Planhttps://taotoken.net/coding-plan 。接入文档在 https://taotoken.net/doc 里面有完整的请求格式和错误码说明排障时会用到。4. 可复制配置WebSocket、Redis、MongoDB、LiteFlow 骨架这一节给出四个组件的配置骨架你可以按自己的项目结构调整但字段含义和验证点要保持一致。4.1 WebSocket 配置骨架WebSocket 的核心是会话级上下文和音频缓冲管道。下面是一个TranscriptionSessionContext的配置骨架public class TranscriptionSessionContext { private final PipedOutputStream audioOutputStream; private final PipedInputStream audioInputStream; private final AtomicBoolean active new AtomicBoolean(true); private final AtomicBoolean stopRequested new AtomicBoolean(false); private final AtomicBoolean closed new AtomicBoolean(false); private volatile RealtimeTranscriptionUpdate lastUpdate; public TranscriptionSessionContext(int pipeBufferSize) throws IOException { this.audioInputStream new PipedInputStream(pipeBufferSize); this.audioOutputStream new PipedOutputStream(this.audioInputStream); } public void writeAudio(byte[] chunk) throws IOException { if (!active.get() || closed.get()) { throw new IllegalStateException(session not active); } audioOutputStream.write(chunk); audioOutputStream.flush(); } public void requestStop() { stopRequested.set(true); try { audioOutputStream.close(); } catch (IOException ignored) { } } public void updateLast(RealtimeTranscriptionUpdate update) { this.lastUpdate update; } }对应的 WebSocket Handler 配置Configuration EnableWebSocket public class AudioWebSocketConfig implements WebSocketConfigurer { Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(audioWebSocketHandler(), /ws/asr) .setAllowedOrigins(*); } Bean public WebSocketHandler audioWebSocketHandler() { return new AudioWebSocketHandler(); } }验证点连接建立后前端发二进制帧后端writeAudio不抛异常调用requestStop后audioInputStream能读到 EOF。4.2 Redis 配置骨架Redis 保存热运行态key 设计要按 sessionId 和业务 scope 区分。下面是application-redis.ymlspring: redis: host: ${REDIS_HOST:127.0.0.1} port: ${REDIS_PORT:6379} password: ${REDIS_PASSWORD:} database: 0 timeout: 3000ms lettuce: pool: max-active: 16 max-idle: 8 min-idle: 2 max-wait: 2000ms meeting: redis: key-prefix: ai-meeting runtime-ttl-seconds: 7200 idempotent-ttl-seconds: 3600 followup-cache-ttl-seconds: 1800 lock-ttl-seconds: 30对应的 key 命名规范public final class RedisKeys { private static final String PREFIX ai-meeting; public static String runtimeFlow(String sessionId) { return PREFIX :runtime:flow: sessionId; } public static String runtimeScore(String sessionId) { return PREFIX :runtime:score: sessionId; } public static String followupCache(String sessionId, String questionNo) { return PREFIX :followup: sessionId : questionNo; } public static String idempotent(String sessionId, String requestId) { return PREFIX :idem: sessionId : requestId; } public static String questionLock(String sessionId, String questionNo) { return PREFIX :lock:q: sessionId : questionNo; } }验证点写入runtimeFlow后能读到TTL 符合配置questionLock能正常加锁和解锁。4.3 MongoDB 配置骨架MongoDB 保存快照和归档。下面是application-mongo.ymlspring: data: mongodb: uri: ${MONGO_URI:mongodb://127.0.0.1:27017/ai_meeting} auto-index-creation: true meeting: mongo: hot-snapshot-collection: hot_snapshot cold-snapshot-collection: cold_snapshot turn-archive-collection: turn_archive snapshot-version-field: snapshotVersion last-mutation-field: lastMutationId对应的文档结构骨架Document(collection hot_snapshot) public class HotSnapshot { Id private String id; private String sessionId; private Long snapshotVersion; private String lastMutationId; private Long lastTurnSeq; private Long archiveWatermark; private Integer scoreCount; private String flowState; private Instant updatedAt; }验证点写入后能按 sessionId 查到snapshotVersion在 CAS 更新时递增lastTurnSeq和archiveWatermark不倒退。4.4 LiteFlow 配置骨架LiteFlow 负责追问裁决。下面是liteflow.xml规则链骨架?xml version1.0 encodingUTF-8? flow chain namefollowUpDecisionChain THEN( checkMaxFollowUp, checkCurrentQuestionType, checkAiSuggestion, checkMissingPoints, decideFollowUp ); /chain /flow对应的组件骨架Component(checkMaxFollowUp) public class CheckMaxFollowUpComponent extends NodeComponent { Override public void process() { FollowUpContext ctx this.getContextBean(FollowUpContext.class); boolean reached ctx.getFollowUpCount() ctx.getMaxFollowUp(); ctx.setMaxFollowUpReached(reached); } } Component(decideFollowUp) public class DecideFollowUpComponent extends NodeComponent { Override public void process() { FollowUpContext ctx this.getContextBean(FollowUpContext.class); boolean shouldFollowUp !ctx.isMaxFollowUpReached() !ctx.isCurrentQuestionFollowUp() (ctx.isAiSuggested() || ctx.hasMissingPoints()); ctx.setShouldFollowUp(shouldFollowUp); } }验证点规则链能被触发上下文参数传入正确不同分支能走到对应结果。5. 验证请求与成功结果逐项确认连通性配置写完后不要急着跑完整链路先逐项验证。下面给出每个组件的验证请求和预期结果。5.1 验证 TaoToken API 通道用 curl 发一条测试请求curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: claude-sonnet, messages: [{role: user, content: 回复 OK}], max_tokens: 16 }预期结果返回 JSON 里choices[0].message.content包含OK。如果返回 401检查 Key如果返回 404检查 base-url 是否多了路径。5.2 验证 WebSocket 音频写入用 Java 写一个最小测试Test public void testAudioPipe() throws Exception { TranscriptionSessionContext ctx new TranscriptionSessionContext(8192); byte[] chunk new byte[]{1, 2, 3, 4}; ctx.writeAudio(chunk); byte[] read new byte[4]; int n ctx.audioInputStream.read(read); assertEquals(4, n); assertArrayEquals(chunk, read); ctx.requestStop(); assertEquals(-1, ctx.audioInputStream.read()); }预期结果写入 4 字节后能读出 4 字节调用requestStop后读到 EOF。5.3 验证 Redis 读写与 TTLTest public void testRedisRuntime() { String sessionId session-test-001; String key RedisKeys.runtimeFlow(sessionId); redisTemplate.opsForValue().set(key, ASKING, Duration.ofSeconds(7200)); String value redisTemplate.opsForValue().get(key); assertEquals(ASKING, value); Long ttl redisTemplate.getExpire(key, TimeUnit.SECONDS); assertTrue(ttl 7000 ttl 7200); }预期结果写入后能读到ASKINGTTL 在 7000 到 7200 之间。5.4 验证 MongoDB 快照写入与版本递增Test public void testHotSnapshotCas() { String sessionId session-test-001; HotSnapshot snapshot new HotSnapshot(); snapshot.setSessionId(sessionId); snapshot.setSnapshotVersion(1L); snapshot.setLastTurnSeq(0L); snapshot.setArchiveWatermark(0L); snapshot.setScoreCount(0); snapshot.setFlowState(ASKING); mongoTemplate.save(snapshot); HotSnapshot loaded mongoTemplate.findOne( Query.query(Criteria.where(sessionId).is(sessionId)), HotSnapshot.class ); assertNotNull(loaded); assertEquals(1L, loaded.getSnapshotVersion()); }预期结果写入后能按 sessionId 查到snapshotVersion为 1。5.5 验证 LiteFlow 规则链Test public void testFollowUpDecision() { FollowUpContext ctx new FollowUpContext(); ctx.setFollowUpCount(0); ctx.setMaxFollowUp(2); ctx.setCurrentQuestionFollowUp(false); ctx.setAiSuggested(true); ctx.setHasMissingPoints(true); LiteflowResponse response flowExecutor.execute2Resp( followUpDecisionChain, null, ctx ); assertTrue(response.isSuccess()); assertTrue(ctx.isShouldFollowUp()); }预期结果规则链执行成功shouldFollowUp为 true。5.6 验证完整链路把上面几步串起来WebSocket 收到答案 → Redis 加载 flow → 调 TaoToken 评分 → LiteFlow 裁决 → 写 turn log → 刷新 MongoDB 快照。预期结果是Redis 里 flow 从ASKING推进到FOLLOW_UP或下一题MongoDB 里lastTurnSeq递增archiveWatermark递增。6. 本篇常见错排查6.1 WebSocket 连接建立后收不到音频先检查前端发的是不是二进制帧。如果前端发的是文本帧后端writeAudio会收到字符串而不是字节数组。再检查pipeBufferSize是不是太小如果音频分片大于缓冲区写入会阻塞。最后检查active和closed状态如果requestStop被提前调用后续写入会抛异常。6.2 Redis 写入成功但读不到先检查 key 前缀是否一致。如果代码里用了RedisKeys.runtimeFlow但手动查的时候用了别的前缀就会读不到。再检查序列化方式如果写入时用了 JSON 序列化读取时用了 String 序列化会反序列化失败。最后检查 TTL如果 TTL 设得太短可能刚写入就过期了。6.3 MongoDB 快照版本不递增先检查 CAS 更新逻辑。如果snapshotVersion没有在更新时递增后续 CAS 会一直失败。再检查lastMutationId如果同一个 requestId 重复提交幂等判断会跳过写入。最后检查lastTurnSeq和archiveWatermark的单调性校验如果新值小于旧值写入会被拒绝。6.4 LiteFlow 规则链不触发先检查liteflow.xml里的 chain name 和代码里执行的名字是否一致。再检查组件有没有加Component注解以及组件名和 XML 里的名字是否对应。最后检查上下文 bean 有没有正确传入如果FollowUpContext没传进去组件里getContextBean会返回 null。6.5 TaoToken API 返回 401 或 404401 通常是 Key 无效或没带Authorization头。检查环境变量TAOTOKEN_API_KEY有没有 export以及请求头格式是不是Bearer key。404 通常是 base-url 多了路径比如写成了https://taotoken.net/api/v1正确应该是https://taotoken.net/api具体路径由 SDK 或请求体里的 endpoint 决定。6.6 追问裁决结果和预期不一致先检查 LiteFlow 上下文里的参数有没有传全。比如followUpCount和maxFollowUp如果没传默认值可能是 0导致maxFollowUpReached判断错误。再检查规则链顺序如果decideFollowUp在checkMaxFollowUp之前执行会拿到未初始化的状态。最后检查 AI 建议和缺失点的优先级如果规则里写了“AI 建议优先”但实际业务要求“缺失点优先”结果就会不一致。7. 语义一致 CTA按场景选择下一步如果你在排障或接入阶段优先看 API Keys 和接入文档。API Keys 在 https://taotoken.net/api-keys 接入文档在 https://taotoken.net/doc 里面有完整的请求格式、错误码和限流说明。如果你要验证模型对话是否正常到 https://taotoken.net/models 手动发一条测试消息确认 Key 有效、模型能返回。这一步在排查评分链路问题时特别有用能快速排除“Key 本身不通”这个因素。如果你长期做编码和 Agent 场景可以了解 Coding Planhttps://taotoken.net/coding-plan 里面有适合长期调用的配置方案。最后如果你要把这套配置跑起来建议按这个顺序先验证 TaoToken API 通道再验证 WebSocket 音频写入然后验证 Redis 读写接着验证 MongoDB 快照最后验证 LiteFlow 规则链。每一步都确认通过后再串完整链路这样出问题时能快速定位到具体组件。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。