|
Download docs/friend/data-flow.md from chenbhao/codev: direct link, hf CLI and curl.
- Browser
- Download file 15.8 kB
-
https://huggingface.co/chenbhao/codev/resolve/afbc7edaae4e6bb0102ba024b49ce8be89d2264c/docs/friend/data-flow.md
- Command line
-
hf download hf://chenbhao/codev@afbc7edaae4e6bb0102ba024b49ce8be89d2264c/docs/friend/data-flow.md
-
curl -L -o data-flow.md https://huggingface.co/chenbhao/codev/resolve/afbc7edaae4e6bb0102ba024b49ce8be89d2264c/docs/friend/data-flow.md
15.8 kB
| # Friend ๆฐๆฎๆต | |
| ๆฌๆๆกฃ่ฏฆ็ปๆ่ฟฐ Friend ็ณป็ปไธญ็ๅ็งๆ ธๅฟๆฐๆฎๆต๏ผไปฅๅ SSE ไบไปถๆ ผๅผ่ง่ใ | |
| --- | |
| ## 1. ๆๅญๅฏน่ฏๆต | |
| ็จๆทๅจๅ็ซฏ่พๅ ฅๆก่พๅ ฅๆๅญ๏ผๆไธ Enter ๅ้ใ | |
| ``` | |
| ็จๆท่พๅ ฅๆๅญ | |
| โ | |
| โผ | |
| ChatInput.tsx โโ POST /plugins/friend/chat โโโโโโโโโโโโโโโโโโโ | |
| โ { message: "ไฝ ๅฅฝ" } โ | |
| โ โ | |
| โผ โ | |
| handleFriendApi() โโ friendService.start() โ | |
| โ friendService.sendText(message) โ | |
| โผ โ | |
| FriendService.sendText() โ | |
| โ โ | |
| โโโ ้็ฅ inboundListeners (bridge hook turn tracking) โ | |
| โ โ | |
| โโโ messageQueueManager.enqueue() โ | |
| โ { mode: 'prompt', skipSlashCommands: true, โ | |
| โ bridgeOrigin: true, origin: { server: 'friend' }} โ | |
| โ โ | |
| โผ โ | |
| AI Provider (Anthropic/NVIDIA/OpenAI) โ | |
| โ โ | |
| โโโ ๅค็ๆถๆฏ โ | |
| โโโ ๅฏ่ฐ็จ friend_emotion ๅทฅๅ ท่ฎพ็ฝฎ่กจๆ โ | |
| โโโ ๅฏ่ฐ็จ friend_screen_observe ่งๅฏๅฑๅน โ | |
| โ โ | |
| โผ โ | |
| AI ๅๅคๆตๅ (้่ฟ useFriendBridge / REPL) โ | |
| โ โ | |
| โผ โ | |
| FriendService.broadcastResponse(text) โ | |
| โ โ | |
| โโโ broadcastToVrm({ text }) โ | |
| โ โ โ | |
| โ โผ SSE data โ | |
| โ TextBubble ๆถๅฐ โ | |
| โ โ โ | |
| โ โโโ ้็ฝฎๆฐๆณก๏ผๆพ็คบๆๅญ โ | |
| โ โโโ ๅฏๅจๆๅญๆบๆๆ (้ๅญ็ฌฆๆพ็คบ) โ | |
| โ โ - CJK: 200ms/char (TTSๅผๅฏ) / 80ms (ๅ ณ้ญ) โ | |
| โ โ - English: 60ms/char (TTSๅผๅฏ) / 30ms (ๅ ณ้ญ)โ | |
| โ โโโ ๆๅญๆบๅฎๆๅๆธฒๆ Markdown โ | |
| โ โโโ 1็งๅ่งฆๅ onMessage โ VRMScene ่กจๆ ๅจไฝ โ | |
| โ โ | |
| โโโ if TTS enabled: โ | |
| โ โโโ generateTts(text) โ | |
| โ โ โโโ stripForTts() ๆธ ๆดๆๆฌ โ | |
| โ โ โโโ EdgeTTS ๆ QwenTTS ็ๆ MP3 โ | |
| โ โ โ | |
| โ โโโ broadcastToVrm({ audioUrl, sendFirstTts }) โ | |
| โ โ โ โ | |
| โ โ โผ SSE data โ | |
| โ โ TextBubble ๅผๅง้ณ้ข้ๅๆญๆพ โ | |
| โ โ โ โ | |
| โ โ โโโ LipSync.playAudio(url) โ | |
| โ โ โโโ fetch ้ณ้ขๆไปถ โ | |
| โ โ โโโ decodeAudioData โ | |
| โ โ โโโ ่ฟๆฅๅฐ lipSyncNode (ๅๆ) + gainNode (ๆฌๅฃฐๅจ) โ | |
| โ โ โโโ ๆญๆพๆถๅฎๆถๆดๆฐ VRM ๅดๅฝข โ | |
| โ โ โ | |
| โ โโโ extendMuteForTts(audioId) โ | |
| โ โโโ ็ฒพ็กฎ่ฎก็ฎ MP3 ๆถ้ฟ๏ผๆดๆฐ้้ณๅฎๆถๅจ โ | |
| โ โ | |
| โโโ broadcastToVrm({ replyDone: true }) โ | |
| โ โ | |
| โผ SSE data โ | |
| TextBubble ่ฐๅบฆๆฐๆณก้่ (2s ๅปถ่ฟ) โ | |
| ๆ็ญๅพ ๅ็ปญ appendText ๆถๆฏ โ | |
| ``` | |
| --- | |
| ## 2. ่ฏญ้ณๆ่ทๆต (F2 ้่ฏๆจกๅผ) | |
| ็จๆทๆไธ F2 ่ฟๅ ฅ่ฟ็ปญ่ฏญ้ณ้่ฏๆจกๅผ๏ผๅๆฌกๆไธ F2 ็ปๆ้่ฏใ | |
| ### 2.1 ๅฏๅจ้่ฏ | |
| ``` | |
| ็จๆทๆ F2 | |
| โ | |
| โผ | |
| ChatInput.startVoiceCall() | |
| โ | |
| โโโ setVoiceCallActive(true) | |
| โ | |
| โโโ useServerStt.startStreaming() | |
| โ | |
| โโโ POST /plugins/friend/voice/start | |
| โ | |
| โผ | |
| handleFriendApi() | |
| โ | |
| โโโ friendService.startVoiceCapture() | |
| โ | |
| โโโ ๆฃๆต STT provider (GroqโWhisperโAnthropicโDoubao) | |
| โ | |
| โโโ startSttConnection() (8s ่ถ ๆถ) | |
| โ โโโ Groq: connectGroqStream() | |
| โ โโโ Local: connectLocalWhisperStream() | |
| โ โโโ Anthropic: connectVoiceStream() | |
| โ โโโ Doubao: connectDoubaoStream() | |
| โ | |
| โโโ loadAudioCapture() | |
| โ โโโ ๅฐ่ฏ arecord (ALSA) | |
| โ โ args: -D default -r 16000 -f S16_LE -c 1 -t raw -q | |
| โ โโโ ๅคฑ่ดฅๅๅฐ่ฏ parecord (PulseAudio) | |
| โ โ args: --raw --rate=16000 --format=s16le --channels=1 | |
| โ โโโ 500ms ้ช่ฏ็ชๅฃ: ็กฎ่ฎคๅญ่ฟ็จ่พๅบ้ณ้ขๆฐๆฎ | |
| โ | |
| โโโ arecord ๆฐๆฎๅ่ฐ: | |
| โ โโโ if not muted โ ่ฝฌๅๅฐ STT connection.send(chunk) | |
| โ โโโ if not muted โ ่ฝฌๅๅฐ VAD processAudio(float32) | |
| โ | |
| โโโ vadInstance.start() | |
| ``` | |
| ### 2.2 ่ฏญ้ณๆฃๆตไธ่ฝฌๅฝ | |
| ``` | |
| ้บฆๅ ้ฃ้ณ้ขๆต (16kHz S16LE) | |
| โ | |
| โโโโบ STT Connection.send(chunk) (ๅฎๆถๆตๅผ่ฝฌๅฝ) | |
| โ | |
| โโโโบ SileroVad.processAudio(float32) | |
| โ | |
| โโโ RMS ้ข่ฟๆปค (้ๅผ 0.004) | |
| โ โโโ < ้ๅผ โ ๆฆ็ = 0 (่ทณ่ฟๆจ็) | |
| โ โโโ >= ้ๅผ โ ONNX ๆจ็ | |
| โ | |
| โโโ ็ถๆๆบ | |
| โ โโโ pre-speech: ้่ฆ่ฟ็ปญ 10 ๅธง (~320ms) ็กฎ่ฎค่ฏด่ฏ | |
| โ โโโ speaking: ่ฏญ้ณๆ็ปญไธญ | |
| โ โโโ silence redemption: ่ฟ็ปญ 20 ๅธง (~640ms) ้้ณ่งฆๅ endSpeech | |
| โ | |
| โโโ onSpeechEnd callback | |
| โ | |
| โผ | |
| FriendService._flushVadSegment() | |
| โ | |
| โโโ ๅๅปบๆฐ็ STT ่ฟๆฅ (ๆง็่ฟๆฅ็ปง็ปญๅค็) | |
| โ | |
| โโโ ็ญๅพ ๆง่ฟๆฅ finalize() | |
| โ โโโ ่ทๅ่ฝฌๅฝๆๆฌๆจๅ ฅ captureTranscripts | |
| โ | |
| โโโ if ๆ่ฝฌๅฝๆๆฌ: | |
| โ โโโ this.sendText(transcript) | |
| โ โ โ | |
| โ โ โผ | |
| โ โ messageQueueManager.enqueue() โ AI ๅผๅงๅค็ | |
| โ โ | |
| โ โโโ this.startAiTurnMute() | |
| โ โโโ muted = true | |
| โ โโโ VAD pause | |
| โ โโโ 30s ่ถ ๆถๅฎๅ จๆงๅฎๆถๅจ | |
| โ | |
| โโโ ๅพช็ฏ็ปง็ปญ็ๅฌไธไธๆฎต่ฏญ้ณ | |
| ``` | |
| ### 2.3 AI ๅๅคไธ้้ณ่งฃ้ค | |
| ``` | |
| AI ๅค็ๅฎๆ | |
| โ | |
| โผ | |
| FriendService.broadcastResponse(text) | |
| โ | |
| โโโ broadcastToVrm({ text }) // ๆพ็คบๆๅญ | |
| โ | |
| โโโ if TTS enabled: | |
| โ โโโ generateTts(text) | |
| โ โ โ | |
| โ โ โผ | |
| โ โโโ broadcastToVrm({ audioUrl, sendFirstTts: true }) | |
| โ โ | |
| โ โโโ extendMuteForTts(audioId) | |
| โ โโโ getMp3DurationMs() ็ฒพ็กฎ่ฎก็ฎ | |
| โ โโโ ๅๆถ 30s ๅฎๅ จๆงๅฎๆถๅจ | |
| โ โโโ ่ฎพๅฎ็ฒพ็กฎ็ๆญๆพๆถ้ฟๅฎๆถๅจ | |
| โ | |
| โโโ broadcastToVrm({ replyDone: true }) | |
| โ | |
| โผ | |
| ๆญๆพๅฎๆๅ โ unmute() | |
| โโโ muted = false | |
| โโโ VAD resume (ๅฏ็ปง็ปญๆฅๆถ่ฏญ้ณ) | |
| ``` | |
| ### 2.4 ็ปๆ้่ฏ | |
| ``` | |
| ็จๆทๆ F2 (ๅๆฌก) | |
| โ | |
| โผ | |
| ChatInput.endVoiceCall() | |
| โ | |
| โโโ useServerStt.stopStreaming() | |
| โ | |
| โโโ POST /plugins/friend/voice/stop | |
| โ | |
| โผ | |
| friendService.stopVoiceCapture() | |
| โ | |
| โโโ arecord.kill('SIGTERM') โ 2s ๅ SIGKILL | |
| โโโ capturing = false | |
| โโโ clearMute() | |
| โโโ VAD reset() | |
| โโโ STT connection.finalize() + close() | |
| โโโ ๅ้ๅฉไฝ่ฝฌๅฝๆๆฌ | |
| โโโ ่ฟๅๅฎๆด่ฝฌๅฝ | |
| ``` | |
| --- | |
| ## 3. ๆ ็ปช่กจๆ ๆต | |
| LLM ่ฐ็จ `friend_emotion` ๅทฅๅ ท่งฆๅๆ ็ปชๆดๆฐใ | |
| ``` | |
| LLM ๅค็ๅฎๆ๏ผ่ฐ็จ friend_emotion ๅทฅๅ ท | |
| โ | |
| โผ | |
| FriendEmotionTool.call({ emotion: 'happy', intensity: 0.8, mood_delta: 2 }) | |
| โ | |
| โโโ broadcastToVrm({ emotion: 'happy', emotionIntensity: 0.8 }) | |
| โ โ | |
| โ โผ SSE data | |
| โ App.tsx handleVrmMessage | |
| โ โ | |
| โ โโโ emotionActionMap['happy'] = 'happy' | |
| โ โ | |
| โ โโโ sceneRef.current.setEmotionWithReset('happy', 5000, 0.8) | |
| โ โ โ | |
| โ โ โผ | |
| โ โ VRMScene.setEmotionWithReset (via forwardRef) | |
| โ โ โ | |
| โ โ โโโ EmoteController.setEmotionWithReset('happy', 5000, 0.8) | |
| โ โ โโโ setEmotion('happy', 0.8) | |
| โ โ โ โโโ ่ทๅ happy ็ blend shapes: [{name:'happy', val:0.2}, {name:'aa', val:0.8}] | |
| โ โ โ โโโ ๅบ็จ intensity: aa = 0.8*0.8 = 0.64, happy = 0.2*0.8 = 0.16 | |
| โ โ โ โโโ isTransitioning = true | |
| โ โ โ โโโ ่ฎฐๅฝ็ฎๆ blendshape ๅผ | |
| โ โ โ | |
| โ โ โโโ setTimeout(5000ms โ setEmotion('neutral')) | |
| โ โ | |
| โ โโโ sceneRef.current.playAction('happy') | |
| โ โ | |
| โ โผ | |
| โ MotionController.playAction('happy') | |
| โ โโโ loadClip('happy.fbx') | |
| โ โโโ crossFadeTo(clip, 0.3s) | |
| โ โโโ LoopOnce + clampWhenFinished | |
| โ โโโ ๅฎๆๅ crossFade ๅ idle ๅจ็ป | |
| โ | |
| โโโ ๅค็ mood_delta | |
| โ โโโ ่ฏปๅๅฝๅ moodIndex = 60 | |
| โ โโโ newMood = clamp(60 + 2, 0, 100) = 62 | |
| โ โโโ ๆไน ๅๅฐ prefs | |
| โ โโโ broadcastToVrm({ moodDelta: 2, moodIndex: 62 }) | |
| โ โ | |
| โ โผ SSE data | |
| โ MoodIndicator ๆถๅฐ | |
| โ โโโ ๆพ็คบๅฟๆ ๆฐๅผๅๅๆฐๆณก (+2) | |
| โ โโโ Canvas ๅจ็ป: displayPercent ไป 60 โ 62 ๆธๅ | |
| โ โโโ 5s ๅ่ชๅจ้่ | |
| โ | |
| โโโ ่ฟๅ tool result | |
| ``` | |
| ### ๆฏๅธงๆดๆฐๅพช็ฏ (VRMScene animate) | |
| ``` | |
| requestAnimationFrame ๅพช็ฏ (็บฆ 60fps) | |
| โ | |
| โโโ 1. MotionController.update(delta) | |
| โ โโโ AnimationMixer.update(delta) | |
| โ | |
| โโโ 2. ๅบ็จ Relaxed Hand Pose (้่่น็ถๆ) | |
| โ โโโ ๆๆ่ช็ถๅผฏๆฒ + ๅพฎๅฆ้ขคๅจ | |
| โ | |
| โโโ 3. Humanoid.update() | |
| โ | |
| โโโ 4. ็ผ็่ฟฝ่ธช (camera ๆจกๅผ) | |
| โ โโโ lookAtTarget = camera.position | |
| โ | |
| โโโ 5. LookAt.update(delta) | |
| โ | |
| โโโ 6. Eye Saccades Controller.update() | |
| โ โโโ ๆฏ้ 400-1200ms ๆทปๅ ้ๆบ็ผ็ๅพฎๅจๅ็งป | |
| โ | |
| โโโ 7. Blink State Machine.update() | |
| โ โโโ ้ๆบ็จ็ผ (้ด้ 1-6s, ๆถ้ฟ 150ms, sin ๆฒ็บฟ) | |
| โ | |
| โโโ 8. EmoteController.update(delta) | |
| โ โโโ cubic ease ่ฟๆธกๅฐ็ฎๆ blendshape ๅผ | |
| โ | |
| โโโ 9. LipSync.update(vrm, delta) | |
| โ โโโ ่ฏปๅ wlipsync ้ณ้ขๅๆ่็น็้ณ็ด ๆ้ | |
| โ โโโ ้ๆฉ่่ /ไบๅ้ณ็ด | |
| โ โโโ Attack/Release ๅนณๆป (50/30) | |
| โ โโโ ่ฎพ็ฝฎ VRM ๅดๅฝข blendshapes (aa, ee, ih, oh, ou) | |
| โ | |
| โโโ 10. ExpressionManager.update() | |
| โ | |
| โโโ 11. SpringBoneManager.update(delta) | |
| โโโ ็ฉ็ๅคดๅ/่กฃๆ/้ฅฐๅๆจกๆ | |
| ``` | |
| --- | |
| ## 4. SSE ไบไปถๆ ผๅผ | |
| ๆๆๅ็ซฏ SSE ไบไปถ้่ฟ `GET /plugins/friend/events` ๆฅๆถ๏ผๆ ผๅผไธบๆ ๅ SSE (`data: {json}\n\n`)ใ | |
| ### 4.1 VrmBroadcastPayload ๅญๆฎต่ฏดๆ | |
| | ๅญๆฎต | ็ฑปๅ | ๅฟ ๅกซ | ่ฏดๆ | | |
| |------|------|------|------| | |
| | `text` | string | ๅฆ | AI ๅๅคๆๅญ๏ผTextBubble ๆพ็คบๅนถๅฏๅจๆๅญๆบๆๆ | | |
| | `emotion` | string | ๅฆ | VRM ่กจๆ ๅ๏ผ่งฆๅ EmoteController ๅๆข blend shapes | | |
| | `emotionIntensity` | number | ๅฆ | ่กจๆ ๅผบๅบฆ 0-1๏ผ้ป่ฎค 1 | | |
| | `audioUrl` | string | ๅฆ | TTS ้ณ้ข URL๏ผTextBubble ่งฆๅ LipSync ๆญๆพ | | |
| | `audioIndex` | number | ๅฆ | ้ณ้ขๆญๆพ้กบๅบ็ดขๅผ๏ผ็จไบๅคๅฅๆๅบ | | |
| | `clearText` | boolean | ๅฆ | ๆธ ็ฉบๆฐๆณกๆๅญๅ้ณ้ข้ๅ | | |
| | `imageUrl` | string | ๅฆ | ๅพ็ URL๏ผๅจๆฐๆณกไธญๆพ็คบ | | |
| | `moodDelta` | number | ๅฆ | ๅฟๆ ๅๅ้๏ผMoodIndicator ๆพ็คบๆตฎๅจๆฐๆณก | | |
| | `moodIndex` | number | ๅฆ | ๅฝๅๅฟๆ ๆๆฐ 0-100๏ผMoodIndicator Canvas ๆดๆฐ | | |
| | `sendFirstTts` | boolean | ๅฆ | ๅผๅง TTS ๆญๆพ็ไฟกๅท๏ผ้็ฝฎ้ณ้ข้ๅ | | |
| | `appendText` | boolean | ๅฆ | ่ฟฝๅ ๆๅญๆจกๅผ๏ผๅ็ปญๅฅๅญ็ๆๅญๅ้ณ้ข้ ๅฏน | | |
| | `replyDone` | boolean | ๅฆ | ๅๅคๅฎๆไฟกๅท๏ผTextBubble ่ฐๅบฆๆฐๆณก้่ | | |
| ### 4.2 ๅ ธๅๅๅคๅบๅ | |
| ``` | |
| 1. { text: "ไฝ ๅฅฝ๏ผไปๅคฉๅฟๆ ไธ้ๅ๏ผ", replyDone: true } | |
| โ ๆพ็คบๆๅญ๏ผๆๅญๆบๆๆ๏ผ1s ๅ่งฆๅ่กจๆ | |
| 2. { text: "ไธ่ตท็ฉๅง๏ผ" } | |
| { audioUrl: "http://127.0.0.1:3456/plugins/friend/audio/123-1", sendFirstTts: true } | |
| { replyDone: true } | |
| โ ๆพ็คบๆๅญ + ๆญๆพ TTS + ่ฏญ้ณ็ปๆๅ้่ๆฐๆณก | |
| 3. { text: "ไปๅคฉๅคฉๆฐ็ๅฅฝใ" } | |
| { audioUrl: "...", sendFirstTts: true, emotion: "happy", emotionIntensity: 0.8 } | |
| { appendText: true, text: "่ฆไธ่ฆๅบๅป่ตฐ่ตฐ๏ผ", audioUrl: "...", audioIndex: 1 } | |
| { appendText: true, text: "ๆ็ฅ้ไธไธชๅฅฝๅฐๆนใ", audioUrl: "...", audioIndex: 2 } | |
| { replyDone: true } | |
| โ ๅคๅฅๅญๅๅค๏ผๆฏๅฅ็ฌ็ซ้ณ้ข๏ผๆ็ดขๅผ้กบๅบๆญๆพ | |
| โ ็ฌฌไธๅฅๅ้ๆถ่งฆๅ happy ่กจๆ | |
| 4. { emotion: "think", emotionIntensity: 0.7 } | |
| โ ๆ่้ถๆฎต็่กจๆ ๆดๆฐ๏ผLLM ๅค็ไธญ๏ผ | |
| 5. { clearText: true } | |
| โ ๆธ ็ฉบๆฐๆณก๏ผๆฐไผ่ฏ๏ผ | |
| 6. { moodDelta: 3, moodIndex: 63 } | |
| โ ๅฟๆ ๆดๆฐ๏ผๆพ็คบ +3 ๆตฎๅจๆฐๆณก๏ผCanvas ๆถฒๆๅกซๅ ๅๅ | |
| ``` | |