update.log
33.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
# 更新日志
## 2025-05-27 - SessionId管理机制优化 - AIfeng
### 功能增强:SessionId持久化存储和恢复机制
**问题背景:**
- 启动日志显示sessionId是在数字人模型启动时创建的
- 页面刷新后sessionId重置为0,与后端运行的数字人会话不一致
- 缺少sessionId的持久化管理机制
- 用户无法手动重置会话连接
**解决方案:**
1. **SessionId本地存储**
- 实现sessionId的localStorage持久化存储
- 页面刷新后自动恢复之前的sessionId
- 显示当前会话ID状态
2. **会话状态管理**
- 新增可视化的当前会话ID显示框
- 实现会话重置功能,支持手动清除sessionId
- 自动重连机制,页面刷新后尝试恢复WebSocket连接
3. **用户交互优化**
- 添加"重置"按钮,允许用户手动断开并重新连接
- 提供确认对话框,防止误操作
- 增强状态提示和用户反馈
**技术实现:**
```javascript
// SessionId管理功能
function saveSessionId(sessionId) {
localStorage.setItem('currentSessionId', sessionId);
document.getElementById('current-sessionid').value = sessionId;
}
function restoreSessionId() {
var savedSessionId = localStorage.getItem('currentSessionId');
if (savedSessionId && savedSessionId !== '0') {
document.getElementById('sessionid').value = savedSessionId;
return savedSessionId;
}
return null;
}
```
**界面改进:**
- 新增"当前会话ID"显示框,实时显示连接状态
- 添加"重置"按钮,支持会话管理操作
- 优化用户体验,提供清晰的状态反馈
---
## 2025-01-27 - FunASR集成分析与连接验证 - AIfeng
### 技术分析:FunASR服务架构与集成方案
**问题识别:**
- 用户从其他项目拷贝的FunASR相关文件存在依赖缺失问题
- ASR_server.py实际提供WebSocket服务,而非gRPC服务
- funasr.py和ali_nls.py引用的core、utils模块在当前项目中不存在
- 需要验证本地FunASR服务的连接可行性
**技术架构分析:**
1. **服务协议确认**
- ASR_server.py使用websockets库提供WebSocket接口
- 默认监听端口10197,支持CPU/GPU模式切换
- 消息格式:JSON字符串 + 二进制音频数据
- 异步队列处理音频文件识别请求
2. **模型配置**
- 使用FunASR的paraformer-zh模型进行中文语音识别
- 集成VAD(语音活动检测)和标点预测功能
- 支持热词配置,提升特定领域识别准确率
3. **依赖问题分析**
- 缺失模块:core.wsa_server, utils.config_util, utils.util
- 现有代码无法直接运行,需要重构或补全依赖
**解决方案设计:**
1. **简化集成方案(推荐)**
- 创建独立的SimpleFunASRClient类
- 避免复杂依赖,直接使用WebSocket通信
- 提供异步音频识别接口
2. **连接验证工具**
- 开发test_funasr_connection.py测试脚本
- 支持基本连接测试、音频识别测试、消息格式验证
- 自动生成测试音频文件,验证完整流程
**技术实现要点:**
```python
# 简化客户端实现
class SimpleFunASRClient:
async def connect(self):
uri = f"ws://{self.host}:{self.port}"
self.websocket = await websockets.connect(uri)
async def recognize_file(self, wav_path):
message = {"url": wav_path}
await self.websocket.send(json.dumps(message))
return await self.websocket.recv()
```
**部署指导:**
- 启动命令:`python -u ASR_server.py --host "127.0.0.1" --port 10197 --ngpu 0`
- 依赖安装:torch, modelscope, websockets, FunASR, torchaudio
- 热词配置:创建data/hotword.txt文件
**性能优化建议:**
1. 模型量化减少内存占用
2. WebSocket连接池管理
3. 自动重连和错误恢复机制
4. 结构化日志和监控指标
**技术债务识别:**
- 原有代码依赖外部模块,需要重构
- 缺少完善的异常处理机制
- 配置管理硬编码,需要外部化
- 缺少单元测试和集成测试覆盖
**集成建议:**
- 短期:使用简化客户端快速验证连接
- 中期:修复依赖问题,完善错误处理
- 长期:重构为微服务架构,支持多模型切换
---
# 2025-01-27 FunASR测试增强 - 实际音频文件测试功能
**AIfeng/2025-01-27**
## 问题背景
用户提供了三个实际音频文件(yunxi.mp3、yunxia.mp3、yunyang.mp3),需要在现有测试脚本中增加对真实音频文件的识别测试功能,以验证FunASR服务的实际效果。
## 技术实现
### 新增测试方法
- **test_real_audio_files()**: 专门测试实际音频文件的识别功能
- 支持批量测试多个音频文件
- 文件存在性检查
- 30秒超时保护机制
- 详细的识别结果解析和展示
- 错误处理和状态分类
### 测试流程优化
- 将实际音频文件测试集成到主测试序列中
- 测试顺序:基础连接 → 音频识别 → **实际音频文件** → 消息格式
- 增加文件间等待机制,避免服务器压力
### 功能特性
1. **智能文件检测**: 自动检查音频文件是否存在
2. **多格式响应处理**: 支持JSON和纯文本响应解析
3. **详细状态分类**: success/received/timeout/error四种状态
4. **可视化结果展示**: 使用emoji和格式化输出提升可读性
5. **超时保护**: 30秒超时机制防止测试卡死
### 测试结果输出
```
📊 实际音频文件测试总结:
1. 文件: yunxi.mp3
✅ 识别成功: [识别文本]
2. 文件: yunxia.mp3
✅ 识别成功: [识别文本]
3. 文件: yunyang.mp3
✅ 识别成功: [识别文本]
```
## 技术要点
- **异步处理**: 使用asyncio.wait_for实现超时控制
- **错误容错**: 完善的异常处理机制
- **资源管理**: 每个文件独立WebSocket连接,避免状态污染
- **性能优化**: 文件间1秒等待,平衡测试效率和服务器负载
## 使用方法
```bash
# 确保音频文件在项目根目录
# 启动FunASR服务
python -u ASR_server.py --host "127.0.0.1" --port 10197 --ngpu 0
# 运行增强测试
python test_funasr_connection.py
```
## 技术价值
- **验证真实场景**: 从测试WAV文件升级到实际音频文件测试
- **提升测试覆盖**: 增加对MP3格式和真实语音内容的测试
- **改善用户体验**: 直观的测试结果展示和状态反馈
- **增强可维护性**: 模块化的测试方法设计
---
## 2024-12-19 ASR/TTS技术架构分析与扩展方案设计 - AIfeng
### 新增文档
- `doc/dev/asr_tts_architecture_analysis.md` - ASR/TTS技术架构分析与扩展方案
### 技术分析内容
1. **ASR技术实现分析**
- 基于BaseASR的模块化架构设计
- 4种ASR实现: NerfASR、MuseASR、HubertASR、LipASR
- Web端实时ASR基于WebSocket + Web Audio API
- 音频处理流水线: 16kHz采样率,20ms帧长度
2. **TTS技术实现分析**
- 基于BaseTTS的统一框架
- 6种TTS服务: EdgeTTS、FishTTS、SovitsTTS、CosyVoiceTTS、TencentTTS、XTTS
- 异步流式处理架构
- 统一16kHz音频输出
3. **扩展方案设计**
- 第三方ASR集成: 百度、阿里云、腾讯云、Whisper、SenseVoice
- 第三方TTS集成: 百度、Azure、Coqui、PaddleSpeech
- 本地离线服务Docker容器化部署
- 微服务架构重构方案
4. **性能优化策略**
- 模型量化和缓存机制
- 流式处理和异步优化
- GPU资源调度和负载均衡
### 实施建议
- Phase 1: 基础扩展(1-2周) - Whisper ASR + 云端TTS
- Phase 2: 服务化改造(2-3周) - Docker容器化
- Phase 3: 性能优化(2-3周) - 模型优化
- Phase 4: 生产就绪(1-2周) - 部署自动化
### 技术债务识别
- 当前ASR/TTS耦合度较高,需要服务化解耦
- 缺乏统一的配置管理机制
- 性能监控和告警体系待建设
**分析人员**: AIfeng
**工作类型**: 技术架构分析
**影响范围**: ASR/TTS模块
**验证结果:**
- ✅ 页面刷新后sessionId自动恢复
- ✅ 与后端数字人会话保持一致性
- ✅ 支持手动会话重置和重连
- ✅ 提升用户操作便利性
---
## 2025-05-27 - WebSocket连接时序问题修复 - AIfeng
### 问题修复:刷新页面后sessionId未被websocket_connections接收
**问题描述:**
- 刷新页面重新连接数字人后,新的sessionId没有被websocket_connections正确接收
- WebRTC连接建立和WebSocket连接存在时序问题
- sessionId在WebSocket登录时可能仍为0,导致连接关联失败
**根本原因:**
- WebSocket连接建立速度快于WebRTC协商完成
- negotiate()函数设置sessionId到DOM元素存在异步延迟
- connectWebSocket()函数立即读取sessionId值,可能获取到初始值0
**修复方案:**
1. **实现重试机制**
- 在WebSocket连接建立后,等待sessionId正确设置
- 最多重试20次,每次间隔200ms
- 总等待时间不超过4秒
2. **增强日志输出**
- 详细记录sessionId获取过程
- 标记重试次数和等待状态
- 区分正常连接和异常情况
3. **容错处理**
- 即使sessionId为0也允许连接,但记录错误日志
- 避免因时序问题完全阻断WebSocket连接
**技术实现:**
```javascript
function attemptLogin(retryCount = 0) {
var sessionid = parseInt(document.getElementById('sessionid').value) || 0;
if (sessionid === 0 && retryCount < 20) {
console.log(`等待sessionid设置,重试次数: ${retryCount + 1}/20`);
setTimeout(() => attemptLogin(retryCount + 1), 200);
return;
}
// 发送登录消息逻辑...
}
```
**验证结果:**
- ✅ 解决刷新页面后sessionId时序问题
- ✅ 确保新sessionId正确收入websocket_connections
- ✅ 提升WebSocket连接稳定性
- ✅ 增强错误诊断能力
---
## 2025-06-27 - WebSocket消息处理逻辑重构 - AIfeng
### 问题修复:前端消息显示不一致
**问题描述:**
- 对话框中仅显示页面端发出的数据,缺少第三方服务推送的消息
- 用户消息和AI回复未通过WebSocket统一推送
- 语音输入消息直接添加到界面,未等待服务器确认
- 缺少不同大模型的标识区分
**修复方案:**
1. **统一消息推送机制**
- 移除前端直接添加消息到界面的逻辑
- 所有消息(用户输入、语音输入、AI回复)均通过WebSocket推送
- 添加`X-Request-Source: 'web'`头部标识消息来源
2. **新增聊天消息处理**
- 添加`chat_message`类型的WebSocket消息处理
- 支持消息发送者识别(user/human/ai/assistant)
- 集成模型信息和请求来源显示
3. **本地存储增强**
- 自动保存聊天记录到本地存储
- 支持按sessionId区分不同会话
- 记录时间戳、模型信息等元数据
**技术实现:**
```javascript
// WebSocket聊天消息处理
if (messageData.type === 'chat_message') {
var alignment = sender === 'user' ? 'right' : 'left';
var senderLabel = modelInfo ? `AI回复(${modelInfo})` : 'AI回复';
addMessage(messageContent, alignment, senderLabel, messageMode, modelInfo, requestSource);
}
// 移除直接添加消息逻辑
fetch('/human', {
headers: {
'Content-Type': 'application/json',
'X-Request-Source': 'web'
}
});
```
**验证结果:**
- ✅ 前端完全依赖WebSocket接收消息
- ✅ 支持第三方服务推送消息显示
- ✅ 语音输入通过服务器确认后显示
---
## 2025-01-27 - WebSocket连接时序问题修复 - AIfeng
### 问题修复:刷新页面后新sessionId未加入websocket_connections
**问题描述:**
- 页面刷新后,WebSocket连接在页面加载时立即建立
- 此时sessionId仍为默认值0,WebRTC连接尚未建立
- 真正的sessionId在WebRTC连接建立后才从服务器获取
- 导致新会话的WebSocket连接无法正确关联到websocket_connections
**根本原因:**
连接建立时序错误:WebSocket连接 → sessionId获取,应该是:sessionId获取 → WebSocket连接
**修复方案:**
1. **调整连接时序**
- 移除页面加载时的自动WebSocket连接
- 在WebRTC连接建立并获得sessionId后触发WebSocket连接
2. **前端逻辑优化**
- 修改`client.js`:在设置sessionId后触发WebSocket连接
- 修改`webrtcapichat.html`:移除页面初始化时的connectWebSocket调用
- 添加sessionId有效性验证和警告日志
3. **保持重连机制**
- 保留页面可见性变化时的重连逻辑
- 保留网络异常时的自动重连机制
**技术实现:**
```javascript
// client.js - 在获得sessionId后触发WebSocket连接
.then((answer) => {
document.getElementById('sessionid').value = answer.sessionid
console.log('SessionID已设置:', answer.sessionid);
if (typeof connectWebSocket === 'function') {
console.log('触发WebSocket连接...');
connectWebSocket();
}
return pc.setRemoteDescription(answer);
})
// webrtcapichat.html - 移除自动连接
// connectWebSocket(); // 移除自动连接,改为在获得sessionid后连接
// 添加sessionId验证
if (sessionid === 0) {
console.warn('警告: sessionid为0,可能WebRTC连接尚未建立');
}
```
**验证结果:**
- ✅ WebSocket连接在获得有效sessionId后建立
- ✅ 新会话正确添加到websocket_connections中
- ✅ 保持原有重连和错误处理机制
- ✅ 添加调试日志便于问题排查
- ✅ AI回复显示模型信息标识
- ✅ 本地存储自动保存聊天记录
---
## 2024-12-19 SessionId 管理机制优化
**AIfeng/2024-12-19**
### 问题描述
前端页面刷新后sessionId丢失,导致数字人会话中断,用户体验不佳。
### 解决方案
1. **持久化存储**: 实现sessionId的本地存储和自动恢复机制
2. **会话状态管理**: 添加会话ID显示和手动重置功能
3. **智能重连**: 页面加载时自动尝试恢复之前的会话连接
4. **用户交互优化**: 提供直观的会话状态反馈和控制选项
### 技术实现
- 在`webrtcapichat.html`中添加sessionId管理函数:`saveSessionId`、`restoreSessionId`、`clearSessionId`
- 修改`client.js`中的`negotiate`函数,在获取sessionId后自动保存到localStorage
- 在WebSocket连接成功后更新UI显示当前sessionId
- 添加"重置"按钮支持手动清除sessionId并重新连接
- 页面初始化时自动尝试恢复sessionId并延迟重连WebSocket
### 界面改进
- 当前会话ID输入框:实时显示连接状态和sessionId值
- 重置按钮:支持用户确认后清除会话并提示重新连接
- 状态提示:连接成功后placeholder显示"已连接"
### ChatOverlay 对话框优化
**背景**: 对话框遮挡数字人界面,影响视觉体验;缺乏灵活的显示控制和透明度调节功能。
**解决方案**:
1. **透明度优化**: 将所有背景透明度调整至50%,减少对数字人界面的遮挡
2. **功能重构**: 将"清空对话记录"按钮改为"隐藏对话框"功能
3. **配置管理**: 在侧边栏新增"对话框配置"模块,集中管理对话框相关设置
4. **持久化配置**: 所有配置项支持本地存储,页面刷新后自动恢复
**技术实现**:
- 调整CSS透明度:chatOverlay主背景、消息框、头像背景均设为50%透明度
- 新增JavaScript函数:`toggleChatOverlay`、`updateChatOverlayOpacity`、`updateMessageOpacity`、`loadChatOverlayConfig`
- 动态样式管理:通过JavaScript动态创建CSS样式实现实时透明度调节
- 事件监听器:滑块控件实时响应用户调整,立即应用视觉效果
**界面改进**:
- 对话框配置模块:显示/隐藏开关、对话框透明度滑块、消息框透明度滑块
- 实时反馈:滑块旁显示当前透明度百分比值
- 重置功能:一键恢复所有配置到默认状态
- 隐藏按钮:原清空按钮改为"-"图标,点击隐藏对话框
### 验证结果
- ✅ SessionId现在能够在页面刷新后自动恢复,保持数字人会话的连续性
- ✅ 对话框现在更加透明,不会过度遮挡数字人界面
- ✅ 用户可根据需要灵活调节透明度和显示状态
- ✅ 所有配置项支持持久化存储,提升用户体验
---
## 2025-01-27 - LLM模型信息显示修复 - AIfeng
### 问题修复:页面显示"Unknown LLM"而非实际模型名称
**问题背景:**
- 启用豆包模型后,页面始终显示"Unknown LLM"
- app.py中尝试获取`nerfreals[sessionid].llm.model_name`但获取失败
- LLM处理函数只创建模型实例处理响应,未设置到nerfreal对象
**根因分析:**
1. **缺失LLM实例绑定**
- `llm.py`中的处理函数创建Doubao实例但未赋值给`nerfreal.llm`
- `app.py`中无法通过`nerfreals[sessionid].llm.model_name`获取模型信息
2. **模型名称属性缺失**
- Doubao类缺少`model_name`属性用于页面显示
- 通义千问使用OpenAI客户端,无统一的模型名称接口
**解决方案:**
1. **Doubao类增强**
- 添加`model_name = "豆包大模型"`属性
- 提供统一的模型名称显示接口
2. **LLM实例绑定**
- 在`_handle_doubao_response`中设置`nerfreal.llm = doubao`
- 同时设置`nerfreal.llm_model_name = doubao.model_name`
3. **通义千问兼容**
- 创建QwenWrapper包装类提供`model_name`属性
- 统一模型信息获取机制
**技术实现:**
```python
# Doubao.py - 添加模型名称属性
self.model_name = "豆包大模型" # 添加model_name属性用于页面显示
# llm.py - 绑定LLM实例
doubao = Doubao()
nerfreal.llm = doubao
nerfreal.llm_model_name = doubao.model_name
# 通义千问包装类
class QwenWrapper:
def __init__(self):
self.model_name = "通义千问"
```
**验证结果:**
- ✅ 豆包模型页面正确显示"豆包大模型"
- ✅ 通义千问模型页面正确显示"通义千问"
- ✅ app.py中`getattr(nerfreals[sessionid], 'llm_model_name', 'Unknown LLM')`正常工作
- ✅ `nerfreals[sessionid].llm.model_name`属性访问成功
- ✅ 模型信息在WebSocket消息中正确传递到前端
---
## 2024-12-19 WebSocket通信机制修正
**AIfeng/2024-12-19**
### 问题描述
用户指出前期实现存在误解,不应该通过HTTP接口返回数据来获取消息内容,而是完全通过WebSocket通信同步数据。需要修正代码,确保所有消息数据都通过WebSocket推送。
### 修复方案
1. **纯WebSocket通信**:移除HTTP响应中的消息数据返回,只保留简单的处理状态
2. **统一数据流**:所有消息显示完全依赖WebSocket推送,不再从HTTP响应获取任何消息数据
3. **简化响应格式**:HTTP接口只返回处理状态,不包含具体的消息内容
4. **保持错误处理**:网络错误仍通过前端直接处理,服务器错误通过WebSocket推送
### 技术实现
**后端修改** (`e:\fengyang\eman_one\app.py`):
- 简化`/human`接口返回格式,只包含`code`和`message`状态信息
- 移除HTTP响应中的`user_message`、`ai_response`、`model_info`等数据字段
- 保持WebSocket推送机制不变,所有消息数据通过WebSocket传输
**前端修改** (`e:\fengyang\eman_one\web\webrtcapichat.html`):
- 移除对HTTP响应数据的处理和界面显示逻辑
- 保留网络错误的本地处理机制
- 所有消息显示完全依赖WebSocket推送的`chat_message`类型数据
- 简化HTTP响应处理,只检查处理状态
### 验证结果
- ✅ HTTP接口不再返回消息数据,只返回处理状态
- ✅ 所有消息显示完全通过WebSocket推送实现
- ✅ 前端不再依赖HTTP响应获取消息内容
- ✅ 网络错误处理机制保持正常
- ✅ WebSocket推送机制保持完整功能
- ✅ 实现了纯WebSocket数据通信架构
---
## 2025-06-26 - AIfeng
### 问题修复:LLM模块导入错误
**问题描述:**
- `ImportError: cannot import name 'llm_response' from 'llm'`
- app.py无法从llm包中导入llm_response函数
**修复方案:**
- 修改 `llm/__init__.py` 文件,添加llm_response函数的正确导入
- 使用importlib.util动态加载llm.py模块,避免循环导入问题
- 更新__all__列表,确保llm_response函数正确导出
**技术实现:**
```python
# 使用importlib.util动态导入
import importlib.util
spec = importlib.util.spec_from_file_location("llm_module", os.path.join(parent_dir, "llm.py"))
llm_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(llm_module)
llm_response = llm_module.llm_response
```
**验证结果:**
- ✅ `from llm import llm_response` 导入成功
- ✅ app.py可以正常导入llm_response函数
- ✅ 豆包模型集成功能完全可用
---
# 2024-12-19 代码质量与可维护性增强建议
## 新增文件
- `doc/dev/code_quality_enhancement.md` - 代码质量与可维护性增强建议文档
## 功能增强
### 架构优化建议
- **依赖注入模式**: 实现LLM容器管理,解耦模型选择逻辑
- **策略模式重构**: 替换if-elif条件判断,提升代码可扩展性
- **配置管理中心化**: 统一配置管理器,支持热重载和变更监听
### 代码质量提升
- **类型注解完善**: 全面添加类型提示,提升代码可读性
- **错误处理标准化**: 自定义异常类型和错误处理链
- **日志系统增强**: 结构化日志和链路追踪
### 测试策略完善
- **单元测试覆盖**: 完整的测试套件和Mock策略
- **集成测试自动化**: 模型切换和配置热重载测试
### 性能监控与优化
- **性能指标收集**: 响应时间、令牌速率、内存使用监控
- **缓存策略**: LRU缓存和智能缓存键生成
### 安全性增强
- **敏感信息保护**: API密钥加密存储
- **输入验证和清理**: XSS防护和输入长度限制
### 文档和规范
- **API文档自动生成**: FastAPI集成和Swagger文档
- **代码规范检查**: pre-commit钩子和自动化检查
### 部署和运维
- **容器化部署**: Docker配置和健康检查
- **监控和告警**: 系统健康检查和故障预警
## 实施优先级
- **高优先级**: 类型注解、错误处理、单元测试、输入验证
- **中优先级**: 策略模式、配置管理、性能监控、缓存策略
- **低优先级**: 依赖注入、微服务架构、分布式缓存、自动化运维
## 技术价值
- 🏗️ 提升架构设计质量
- 🔧 增强代码可维护性
- 🧪 完善测试覆盖率
- 📊 强化性能监控
- 🔒 提升安全保障
- 📚 完善文档体系
- 🚀 优化部署运维
---
## 2024-12-19
### WebSocket双向通信系统实现
**问题描述:**
- `/human` 接口处理的消息无法实时推送到前端页面
- 第三方调用 `/human` 接口时,页面无法获得反馈
- 缺乏页面与服务端的实时通信机制
**解决方案:**
1. **后端WebSocket服务器实现**
- 在 `app.py` 中添加 WebSocket 支持(aiohttp)
- 实现会话级连接管理(`websocket_connections`)
- 添加消息推送函数 `broadcast_message_to_session`
- 支持心跳检测和自动重连机制
2. **前端WebSocket客户端优化**
- 修改 `webrtcapichat.html` 连接到新的 `/ws` 端点
- 实现会话登录和消息类型处理
- 添加聊天消息推送的实时显示
3. **消息推送集成**
- 修改 `human` 函数,在处理消息后推送到WebSocket
- 支持 `chat` 和 `echo` 两种消息类型的推送
- 区分用户消息、AI回复和回音消息的显示
**技术实现:**
- **后端架构**:aiohttp WebSocket + weakref连接管理
- **消息格式**:JSON格式,包含类型、会话ID、内容和来源
- **连接管理**:基于sessionid的会话级连接池
- **错误处理**:连接异常自动清理和日志记录
**核心功能:**
- ✅ 实时双向通信:页面↔服务端
- ✅ 会话级消息推送:支持多用户并发
- ✅ 消息类型区分:用户/AI助手/回音
- ✅ 连接状态管理:自动重连和心跳检测
- ✅ 第三方接口支持:外部调用也能推送到页面
**测试工具:**
- 创建 `websocket_test.html` 测试页面
- 支持连接状态监控和消息发送测试
- 实时日志显示和错误诊断
**技术价值:**
- 🚀 **实时性提升**:消息即时推送,无需轮询
- 🔄 **双向通信**:支持服务端主动推送
- 🎯 **精准推送**:基于会话ID的定向消息
- 🛡️ **稳定性增强**:自动重连和异常处理
- 🔧 **扩展性强**:支持未来更多消息类型
# 2024-12-19 WebRTC Chat页面消息类型支持修复
## 问题描述
- `webrtcapichat.html`中使用"type": "chat"的模型对话数据没有被收录到chatOverlay
- 表单提交时固定发送"type": "echo",无法发送chat类型消息
- WebSocket消息处理逻辑未正确识别chat类型回复
## 修复内容
### 1. 添加消息类型选择器
- 在文本输入表单中添加消息类型下拉选择框
- 支持"智能对话"(chat)和"回音模式"(echo)两种类型
- 默认选择为"智能对话"模式
### 2. 修改表单提交逻辑
- 获取用户选择的消息类型,替代固定的'echo'类型
- 动态发送用户选择的消息类型到服务器
### 3. 优化WebSocket消息处理
- 增加对`messageData.Data.Type`字段的检查
- 根据服务器返回的消息类型正确设置显示模式
- 添加调试日志输出,便于问题排查
- 修复TTS推送时使用原始消息类型而非固定echo类型
## 技术实现
### HTML表单增强
```html
<div class="form-group">
<label for="message-type">消息类型</label>
<select class="form-control" id="message-type">
<option value="chat">智能对话</option>
<option value="echo">回音模式</option>
</select>
</div>
```
### JavaScript逻辑优化
```javascript
// 动态获取消息类型
var messageType = document.getElementById('message-type') ?
document.getElementById('message-type').value : 'chat';
// 消息模式判断增强
if (messageData.Data.Mode) {
mode = messageData.Data.Mode;
} else if (messageData.Data.Type) {
mode = messageData.Data.Type;
} else {
// 启发式判断逻辑
}
```
## 修复效果
- ✅ 用户可以选择发送chat或echo类型消息
- ✅ chat类型的大模型回复正确显示在chatOverlay中
- ✅ 不同消息类型有对应的视觉标识(头像和颜色)
- ✅ 调试信息完善,便于后续维护
## 兼容性说明
- 保持向后兼容,默认消息类型为chat
- 原有echo模式功能不受影响
- 支持服务器端返回的Mode和Type字段
---
## 2024-12-19 - AIfeng
### 功能增强:豆包大模型集成与配置化改造
**新增文件:**
- `llm/Doubao.py` - 豆包大模型API接口实现
- `config/doubao_config.json` - 豆包模型详细配置文件
- `config/llm_config.json` - LLM模型统一配置管理
**文件修改:**
- `llm.py` - 重构LLM响应函数,支持多模型切换
**新增功能:**
1. **豆包模型集成**
- 基于火山引擎豆包API实现对话功能
- 支持流式和非流式响应模式
- 完整的错误处理和异常捕获机制
- 支持自定义API密钥和基础URL配置
2. **配置化架构设计**
- 人物设定完全配置化(性格、背景、对话风格等)
- API参数可配置(模型名称、温度、top_p、最大token等)
- 响应行为配置(流式传输、重试机制、超时设置)
- 高级功能配置(安全过滤、内容审核、日志记录)
3. **多模型统一管理**
- 通过`llm_config.json`统一管理模型选择
- 支持通义千问和豆包模型无缝切换
- 保持原有通义千问功能完整性
- 统一的性能监控和日志记录
4. **流式响应优化**
- 豆包模型支持实时流式输出
- 智能分句处理,提升用户体验
- 首个token时间和总响应时间监控
- 回调函数机制支持自定义处理逻辑
5. **配置文件结构**
- `doubao_config.json`:包含API配置、人物设定、响应配置等
- `llm_config.json`:模型选择和通用设置
- 支持环境变量和配置文件双重配置方式
**技术实现:**
- 重构`llm_response`函数为模块化架构
- 新增`_load_llm_config`、`_handle_doubao_response`、`_handle_qwen_response`函数
- 实现豆包API的HTTP请求封装和流式处理
- 配置文件JSON格式化和错误处理机制
- 性能监控和详细日志记录
**配置示例:**
```json
{
"model_type": "doubao",
"models": {
"doubao": {
"config_file": "config/doubao_config.json"
}
}
}
```
**兼容性:**
- 完全向后兼容原有通义千问配置
- 支持动态模型切换,无需重启服务
- 保持原有API接口不变
---
## 2024-12-19 - AIfeng
### 功能增强:数字人对话记录系统
**文件修改:**
- `web/webrtcapichat.html` - 增强数字人对话页面
**新增功能:**
1. **对话框界面优化**
- 在数字人视频右下角添加完整的对话记录框
- 增加聊天框头部显示"数字人对话记录"
- 添加清空对话记录按钮
- 优化消息显示样式,支持消息动画效果
2. **消息来源标注**
- 用户输入:标注为"用户输入"或"用户语音"
- 数字人回复:标注为"数字人回复"
- 支持不同模式的头像颜色区分(回声模式、对话模式、纯文本模式)
3. **多种输入模式支持**
- 文字输入:通过文本框发送消息
- 语音输入:通过录音功能发送语音消息
- 自动识别并标注输入类型
4. **智能模式识别**
- 回声模式:数字人复述用户输入
- 对话模式:大模型生成回复内容
- 纯文本模式:直接文本显示
- 基于消息内容的启发式模式判断
5. **本地存储功能**
- 自动保存对话记录到浏览器本地存储
- 页面刷新后自动恢复历史对话
- 支持手动清空对话记录
6. **用户体验优化**
- 消息自动滚动到底部
- 空消息输入验证
- 消息时间戳显示
- 响应式布局适配
**技术实现:**
- 扩展 `addMessage` 函数支持来源和模式参数
- 新增 `clearChatHistory`、`saveChatHistory`、`loadChatHistory` 函数
- 优化 WebSocket 消息处理逻辑
- 增强 CSS 样式支持动画和多状态显示
**兼容性:**
- 保持原有 WebRTC 功能完整性
- 向后兼容现有 API 接口
- 支持所有主流浏览器
---
## WebRTC连接优化更新日志
### 问题描述
用户反映WebRTC连接状态显示"Connection state is connecting"但连接时长很长,需要分析和优化连接建立过程。
### 根因分析
通过代码分析发现连接延迟可能由以下原因造成:
1. 模型初始化过程耗时过长(ernerf/musetalk/wav2lip/ultralight模型加载)
2. ICE候选者收集和连接建立过程缺乏监控
3. 音视频轨道初始化缺乏性能监控
4. SDP协商过程缺乏时间追踪
### 优化措施
#### 1. 连接状态监控增强
- 在`app.py`的`on_connectionstatechange`函数中添加详细的时间戳记录
- 增加SessionID标识,便于多会话调试
- 添加连接状态变化的详细日志(connecting/connected/failed/closed)
- 改进错误处理,避免重复删除会话
#### 2. ICE连接监控
- 新增`on_iceconnectionstatechange`事件监听器
- 监控ICE连接状态变化(checking/connected/completed/failed/disconnected)
- 新增`on_icegatheringstatechange`事件监听器
- 监控ICE候选者收集过程(gathering/complete)
#### 3. 模型初始化优化
- 在`build_nerfreal`函数中添加详细的加载时间监控
- 为每种模型类型(Wav2Lip/MuseTalk/ERNeRF/UltraLight)添加专门的日志
- 增强错误处理和资源清理机制
- 添加垃圾回收以优化内存使用
#### 4. 音视频轨道初始化监控
- 监控HumanPlayer创建时间
- 监控音频轨道和视频轨道添加时间
- 记录整个音视频初始化过程的总耗时
#### 5. 编解码器配置监控
- 监控视频编解码器配置过程
- 记录可用编解码器列表(H264/VP8/rtx)
- 监控编解码器偏好设置时间
#### 6. SDP协商过程监控
- 监控SDP协商的完整过程
- 记录远程描述设置、应答创建、本地描述设置的各个阶段
- 计算SDP协商总耗时
### 技术实现细节
#### 时间戳格式
所有时间戳使用`time.time()`获取,精确到毫秒(%.3f格式)
#### 日志格式标准化
```
[SessionID:XXXXXX] 操作描述 at 时间戳
[SessionID:XXXXXX] 操作描述 in X.XXX seconds
```
#### 错误处理改进
- 使用try-catch包装模型初始化过程
- 添加资源清理机制
- 避免重复删除会话导致的KeyError
### 预期效果
1. **问题定位精确化**:通过详细的时间戳记录,可以精确定位连接建立过程中的瓶颈
2. **性能监控可视化**:各个阶段的耗时记录有助于识别性能热点
3. **调试效率提升**:SessionID标识和结构化日志便于多会话并发调试
4. **系统稳定性增强**:改进的错误处理和资源清理机制
### 后续优化建议
1. **模型预加载**:考虑在服务启动时预加载常用模型
2. **连接池优化**:实现模型实例复用机制
3. **网络配置优化**:优化STUN/TURN服务器配置
4. **异步初始化**:将模型初始化与WebRTC连接建立并行处理
## 2024-01-XX STUN服务器优化更新
### 优化背景
基于日志分析发现ICE候选者收集延迟(5秒+)是主要性能瓶颈,需要优化STUN服务器配置。
### 技术实现
#### 1. 多STUN服务器配置
- 添加Google多个STUN服务器节点
- 实现负载均衡和故障转移
- 配置ICE候选者池大小优化
#### 2. ICE收集超时机制
- 设置3秒超时限制
- 避免无限等待ICE收集完成
- 提供降级处理方案
#### 3. 连接状态监控增强
- 添加实时ICE状态显示
- 提供用户友好的连接状态反馈
- 增强调试和问题定位能力
### 文件变更记录
- 修改文件:`e:\fengyang\eman_one\app.py`
- 变更类型:功能增强、性能监控、错误处理改进
- 影响范围:WebRTC连接建立流程、模型初始化流程
- `web/client.js`: 优化STUN配置,添加超时机制和状态监控
- `web/whep.js`: 同步STUN服务器配置优化
### 预期效果
- ICE收集时间从5秒降低到1-2秒
- 总连接时间减少50-60%
- 提升用户连接体验
### 测试建议
1. 启动服务后观察日志输出格式
2. 建立WebRTC连接,记录各阶段耗时
3. 模拟网络延迟环境测试ICE连接过程
4. 测试多会话并发场景下的日志区分度