-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RealtimeAPI不具合修正 #209
RealtimeAPI不具合修正 #209
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Walkthroughこのプルリクエストでは、プロジェクトのREADMEファイルとローカライズファイルに関する重要な変更が行われています。READMEには、バージョンv2.0.0からのカスタムライセンスの導入と、商業利用に関するガイドラインが追加されました。また、多言語サポートに関する貢献ガイドラインが強化され、新しい言語を追加するための手順が詳細に説明されています。ローカライズファイルでは、リアルタイムAPIに関連する新しいエントリが追加され、WebSocket接続や音声データ処理に関する機能が強化されています。 Changes
Possibly related PRs
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 13
🧹 Outside diff range and nitpick comments (4)
docs/README_en.md (1)
Line range hint
157-378
: Realtime APIモードのドキュメント改善提案Realtime APIモードのセクションについて、以下の改善を提案します:
- 機能の具体的なユースケース
- 関数実行の詳細な例
- トラブルシューティングガイド
- パフォーマンスに関する注意事項
以下のような内容の追加を検討してください:
### Realtime API Mode - This is a mode where you can interact with the character with low latency using OpenAI's Realtime API. - Function execution can be defined. +#### Key Features +- リアルタイムの音声認識と応答 +- カスタム関数の実行機能 +- 低レイテンシーな対話処理 + +#### Performance Considerations +- 推奨されるネットワーク帯域幅 +- メモリ使用量の目安 +- 同時接続数の制限 + #### Usage 1. Select OpenAI or Azure OpenAI as the AI service. 2. Turn on Realtime API mode. 3. Use the microphone to talk to the character. +4. 必要に応じて音声認識の設定を調整 +5. カスタム関数の動作確認 + +#### Troubleshooting +- 音声認識が機能しない場合の対処法 +- エラーメッセージの説明 +- よくある問題と解決方法 #### Function Execution - Define new functions in src/components/realtimeAPITools.tsx and src/components/realtimeAPITools.json. - Refer to the existing get_current_weather function as an example. + +Example of a custom function: +\`\`\`typescript +{ + "name": "get_current_weather", + "description": "天気情報を取得する関数", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "天気を確認する場所" + } + }, + "required": ["location"] + } +} +\`\`\`src/components/realtimeAPIUtils.tsx (3)
156-160
:console.log
のメッセージを詳細化しましょうエラーデータを受信した際のログメッセージが一般的です。受信したエラー内容を含めると、デバッグが容易になります。
case 'error': - console.log('Received error data', jsonData) + console.error('Received error data:', jsonData) break
238-239
: 条件式をわかりやすく整理しましょう複雑な条件式は可読性を下げる可能性があります。条件を変数に分けることで、コードの読みやすさを向上させましょう。
const isAudioDeltaLarge = jsonData.type === 'response.audio.delta' && accumulatedAudioDataRef.current?.buffer?.byteLength > 100_000 const isAudioDone = jsonData.type === 'response.audio.done' -if ( - (jsonData.type === 'response.audio.delta' && - accumulatedAudioDataRef.current?.buffer?.byteLength > 100_000) || - jsonData.type === 'response.audio.done' -) { +if (isAudioDeltaLarge || isAudioDone) {
115-119
: トーストの削除処理を簡潔にしましょう複数のトーストを削除する際、配列とループを使ってコードを簡潔にできます。
export function removeToast() { - toastStore.getState().removeToast('websocket-connection-error') - toastStore.getState().removeToast('websocket-connection-close') - toastStore.getState().removeToast('websocket-connection-info') + const toastTags = [ + 'websocket-connection-error', + 'websocket-connection-close', + 'websocket-connection-info', + ] + toastTags.forEach((tag) => { + toastStore.getState().removeToast(tag) + }) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (15)
- docs/README_en.md (2 hunks)
- docs/README_ko.md (0 hunks)
- docs/README_zh.md (0 hunks)
- locales/en/translation.json (1 hunks)
- locales/ja/translation.json (1 hunks)
- locales/ko/translation.json (1 hunks)
- locales/zh/translation.json (1 hunks)
- src/components/realtimeAPIUtils.tsx (1 hunks)
- src/components/settings/index.tsx (1 hunks)
- src/components/settings/modelProvider.tsx (5 hunks)
- src/components/settings/voice.tsx (1 hunks)
- src/components/useRealtimeAPI.tsx (4 hunks)
- src/features/chat/handlers.ts (1 hunks)
- src/features/constants/settings.ts (1 hunks)
- src/features/stores/settings.ts (4 hunks)
💤 Files with no reviewable changes (2)
- docs/README_ko.md
- docs/README_zh.md
✅ Files skipped from review due to trivial changes (1)
- src/components/settings/index.tsx
🧰 Additional context used
🪛 Biome
src/components/realtimeAPIUtils.tsx
[error] 181-182: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (20)
src/features/constants/settings.ts (1)
60-60
: 型の定義が適切です!
RealtimeAPIModeContentType
の型定義は、入力形式を明確に制限しており、型安全性が確保されています。locales/zh/translation.json (2)
145-145
: 音声タイプの翻訳が追加されましたリアルタイムAPIモードの音声タイプ設定のための翻訳が適切に追加されています。
148-149
: WebSocketセッション更新に関する重要な説明が追加されましたリアルタイムAPI設定の更新に関する重要な情報が追加されています。以下の点で適切な実装となっています:
- 設定更新ボタンの説明が明確
- 更新が必要なパラメータ(APIキー、Azureエンドポイント、音声タイプ、システムプロンプト)が具体的に列挙されている
- WebSocketセッションの再開始に関する説明が含まれている
他の言語ファイルでも同様の変更が行われているか確認するスクリプトを実行します:
✅ Verification successful
Let me verify the content of these translation files to ensure consistency.
翻訳の整合性が確認できました
すべての言語ファイル(英語、日本語、韓国語、中国語)で以下の点が確認できました:
- 各言語で
UpdateRealtimeAPISettings
とUpdateRealtimeAPISettingsInfo
のキーが適切に実装されています- 翻訳の内容が一貫しており、各言語で同じ意味が正確に伝えられています
- WebSocketセッションの更新に関する重要な情報が、それぞれの言語で適切に表現されています
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # 説明: 他の言語ファイルでも同じキーが追加されているか確認します echo "各言語ファイルでの新規キーの存在確認:" for key in "RealtimeAPIModeVoice" "UpdateRealtimeAPISettings" "UpdateRealtimeAPISettingsInfo"; do echo "キー: $key" rg -l "\"$key\":" locales/ doneLength of output: 1219
Script:
#!/bin/bash # 各言語ファイルの該当キーの内容を確認 for key in "UpdateRealtimeAPISettings" "UpdateRealtimeAPISettingsInfo"; do echo "キー: $key の各言語での内容:" echo "-----------------------------------" for lang in en ja ko zh; do echo "$lang:" rg "\"$key\":" "locales/$lang/translation.json" -A 1 echo done doneLength of output: 2850
locales/ja/translation.json (2)
146-146
: 翻訳の追加を承認「ボイスタイプ」という訳語は適切で、UIの一貫性が保たれています。
149-150
: 設定更新に関する翻訳の追加を承認設定更新に関する翻訳が追加され、ユーザーに対して明確な指示が提供されています。WebSocketセッションの再開始に関する説明も適切に含まれています。
以下の点について確認をお願いします:
- この変更に関連して、エラーメッセージやトースト通知の翻訳も必要ではないでしょうか
- 設定更新後のフィードバックメッセージの翻訳も必要かもしれません
✅ Verification successful
WebSocket関連のエラーメッセージと通知の翻訳は既に完備されています
検証の結果、以下の翻訳が既に実装されていることを確認しました:
- WebSocket接続に関するトースト通知
- 接続エラー
- 接続終了
- 接続試行中
- 接続成功
- 一般的なエラーメッセージ
- APIエラー
- TTSサービスエラー
- 実行失敗通知
設定更新に関する翻訳は適切に実装されており、関連するエラーメッセージや通知も十分にカバーされています。追加の翻訳は必要ありません。
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # 関連するエラーメッセージやトースト通知の翻訳の有無を確認 rg "RealtimeAPI.*Error|UpdateRealtimeAPI.*Failed" locales/Length of output: 60
Script:
#!/bin/bash # エラーメッセージやトースト通知に関連する翻訳を広く検索 rg -i "realtime.*api|websocket" locales/ja/translation.json -A 2 -B 2Length of output: 1040
Script:
#!/bin/bash # 設定更新関連のメッセージを検索 rg -i "update.*settings?|settings?.*updated" locales/ja/translation.json -A 2 -B 2Length of output: 349
Script:
#!/bin/bash # エラー関連の翻訳を検索 rg -i "error|failed|failure" locales/ja/translation.json -A 2 -B 2Length of output: 1107
locales/ko/translation.json (2)
145-145
: 音声タイプの翻訳が追加されました翻訳の追加は適切で、既存の韓国語のトーンと一貫性が保たれています。
148-149
: リアルタイムAPI設定の更新に関する翻訳が追加されました翻訳は明確で、ユーザーに必要なアクションを適切に伝えています。WebSocketセッションの更新に関する技術的な説明も正確に翻訳されています。
以下の点について確認をお願いします:
- 他の言語ファイル(en/ja/zh)でも同様の翻訳が追加されているか
- 翻訳キーが他の言語ファイルと完全に一致しているか
✅ Verification successful
リアルタイムAPI設定の翻訳キーの検証が完了しました
検証結果:
- すべての言語ファイル(en/ja/zh/ko)で必要な翻訳キーが存在することを確認
- 各言語で翻訳の内容が適切に対応していることを確認
- 翻訳キーの命名規則が統一されていることを確認
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # 他の言語ファイルで同じキーが存在するか確認 for lang in en ja zh; do echo "Checking ${lang} translation..." rg "RealtimeAPIModeVoice|UpdateRealtimeAPISettings|UpdateRealtimeAPISettingsInfo" "locales/${lang}/translation.json" doneLength of output: 1256
src/features/stores/settings.ts (2)
12-13
: 型の定義が適切に更新されています!
RealtimeAPIModeContentType
とRealtimeAPIModeVoice
の型を導入することで、型安全性が向上し、実行時エラーを防ぐことができます。Also applies to: 96-97
274-274
: 永続化の設定を確認してください
realtimeAPIModeVoice
の状態が正しく永続化されていることを確認してください。特に以下の点に注意が必要です:
- アプリケーションのリロード後も設定が保持されること
- 初期値が正しく反映されること
✅ Verification successful
Let me gather more information about the persistence implementation.
Let me check one more aspect of the persistence implementation to ensure completeness.
Based on the previous results, I can now provide the final response:
realtimeAPIModeVoice
の永続化は適切に実装されています
- 初期値は環境変数
NEXT_PUBLIC_REALTIME_API_MODE_VOICE
から設定され、デフォルト値は'shimmer'です- stateのpartialize関数で正しく永続化対象として含まれています
- 型定義とstore実装の整合性が取れています
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # 永続化に関連するファイルの検索 rg -l "realtimeAPIModeVoice" --type tsLength of output: 148
Script:
#!/bin/bash # Check the persistence implementation in settings store rg "realtimeAPIModeVoice" src/features/stores/settings.ts -C 5 # Check the initial state definition ast-grep --pattern 'const initialState = { $$$ }' src/features/stores/settings.tsLength of output: 1432
Script:
#!/bin/bash # Check the store creation and persistence setup rg "create\(" src/features/stores/settings.ts -A 10 # Check the type definition ast-grep --pattern 'type $_ = { $$$ realtimeAPIModeVoice: $_ $$$ }'Length of output: 129
locales/en/translation.json (2)
145-145
: 音声タイプの選択オプションが適切に追加されていますRealtimeAPIモードでの音声タイプ選択機能が正しく実装されており、UIの一貫性が保たれています。
148-149
: WebSocketセッション管理の改善提案設定更新時のWebSocketセッション再接続に関する説明文が追加されていますが、以下の点について確認・改善をお願いします:
- ユーザーが設定を変更した際に、自動的にWebSocketセッションを再接続する仕組みの実装を検討してください
- 設定更新ボタンを押し忘れた場合のフォールバック処理や警告メッセージの追加を推奨します
以下のスクリプトで関連する実装を確認します:
docs/README_en.md (2)
157-157
: セクション区切りの一貫性についてスライドモードセクションの後の空行は、ドキュメントの構造を明確にする上で適切です。他のセクションでも同様の区切りを維持することを推奨します。
378-378
: ファイル末尾の空行についてファイル末尾の空行は、多くのエディタで推奨される標準的なプラクティスに従っています。
src/components/settings/voice.tsx (1)
227-227
: スタイリングの改善を承認!VoiceVoxの設定セクションに
font-bold
クラスを追加することで、視覚的な階層構造が改善され、他のセクションとの一貫性が保たれています。src/components/useRealtimeAPI.tsx (4)
6-13
: 必要なインポートが追加されています
./realtimeAPIUtils
からの機能や型のインポートが適切に追加されています。コードの再利用性と保守性が向上しています。
48-48
: セッション更新の送信が適切に行われていますWebSocket接続が開かれた際に
sendSessionUpdate(ws)
を呼び出しており、セッション情報の更新が適切に実装されています。
74-79
: WebSocket接続の設定とメッセージハンドリングが適切です
setupWebsocket(t)
を使用してWebSocketを設定し、handleMessage
関数でメッセージを処理しています。リアルタイムなデータ処理が正しく構成されています。
77-78
:handleMessage
の呼び出しにおける引数の順序と型を確認してください
handleMessage
関数に渡している引数が正しい順序と型であることを確認してください。特に、ws!
とt
の順序や必要性を再確認してください。必要であれば、関数シグネチャを確認し、適切な引数の順序を提案することができます。
src/components/realtimeAPIUtils.tsx (2)
293-343
: WebSocket 再接続のロジックが適切です
reconnectWebSocket
関数では、WebSocket の再接続処理が適切に実装されています。イベントリスナーの設定と状態管理が正しく行われています。
221-231
:⚠️ Potential issueエラーハンドリングを強化しましょう
JSON.parse
中にエラーが発生した場合、ユーザーに適切なフィードバックを提供するためにトースト通知を確実に表示しましょう。} catch (error) { console.error('Error parsing function arguments:', error) if (toastId) { toastStore.getState().removeToast(toastId) } - toastId = toastStore.getState().addToast({ + toastStore.getState().addToast({ message: t('Toasts.FunctionExecutionFailed', { funcName }), type: 'error', duration: 3000, tag: `run-${funcName}`, }) }Likely invalid or redundant comment.
@@ -56,3 +56,6 @@ export type OpenAITTSVoice = | |||
| 'nova' | |||
| 'shimmer' | |||
export type OpenAITTSModel = 'tts-1' | 'tts-1-hd' | |||
|
|||
export type RealtimeAPIModeContentType = 'input_text' | 'input_audio' | |||
export type RealtimeAPIModeVoice = 'alloy' | 'echo' | 'shimmer' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
既存の型定義の再利用を推奨します
RealtimeAPIModeVoice
で定義されている音声オプションは、既にOpenAITTSVoice
型に含まれています。コードの重複を避けるため、以下のようなリファクタリングを提案します。
-export type RealtimeAPIModeVoice = 'alloy' | 'echo' | 'shimmer'
+export type RealtimeAPIModeVoice = Extract<OpenAITTSVoice, 'alloy' | 'echo' | 'shimmer'>
この変更により:
- コードの重複が解消されます
OpenAITTSVoice
型との一貫性が保たれます- 将来的な保守性が向上します
Committable suggestion was skipped due to low confidence.
(process.env | ||
.NEXT_PUBLIC_REALTIME_API_MODE_CONTENT_TYPE as RealtimeAPIModeContentType) || | ||
'input_text', | ||
realtimeAPIModeVoice: | ||
(process.env | ||
.NEXT_PUBLIC_REALTIME_API_MODE_VOICE as RealtimeAPIModeVoice) || | ||
'shimmer', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
環境変数の参照方法を改善することを推奨します
現在の実装は複数行に分かれており、可読性が低下しています。以下のようにリファクタリングすることで、コードの可読性が向上します。
- realtimeAPIModeContentType:
- (process.env
- .NEXT_PUBLIC_REALTIME_API_MODE_CONTENT_TYPE as RealtimeAPIModeContentType) ||
- 'input_text',
- realtimeAPIModeVoice:
- (process.env
- .NEXT_PUBLIC_REALTIME_API_MODE_VOICE as RealtimeAPIModeVoice) ||
- 'shimmer',
+ realtimeAPIModeContentType: (process.env.NEXT_PUBLIC_REALTIME_API_MODE_CONTENT_TYPE as RealtimeAPIModeContentType) || 'input_text',
+ realtimeAPIModeVoice: (process.env.NEXT_PUBLIC_REALTIME_API_MODE_VOICE as RealtimeAPIModeVoice) || 'shimmer',
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
(process.env | |
.NEXT_PUBLIC_REALTIME_API_MODE_CONTENT_TYPE as RealtimeAPIModeContentType) || | |
'input_text', | |
realtimeAPIModeVoice: | |
(process.env | |
.NEXT_PUBLIC_REALTIME_API_MODE_VOICE as RealtimeAPIModeVoice) || | |
'shimmer', | |
realtimeAPIModeContentType: (process.env.NEXT_PUBLIC_REALTIME_API_MODE_CONTENT_TYPE as RealtimeAPIModeContentType) || 'input_text', | |
realtimeAPIModeVoice: (process.env.NEXT_PUBLIC_REALTIME_API_MODE_VOICE as RealtimeAPIModeVoice) || 'shimmer', |
} else if (ss.realtimeAPIMode) { | ||
if (hs.ws?.readyState === WebSocket.OPEN) { | ||
// ユーザーの発言を追加して表示 | ||
const updateLog: Message[] = [ | ||
...hs.chatLog, | ||
{ role: 'user', content: newMessage }, | ||
] | ||
homeStore.setState({ | ||
chatLog: updateLog, | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RealtimeAPIモードの実装が不完全です
以下の問題点が見られます:
- WebSocket接続が閉じている場合のエラーハンドリングが実装されていません
- チャットログの更新のみで、実際のAPI通信処理が実装されていません
- 他のモード(
webSocketMode
など)と比較して、実装パターンに一貫性がありません
以下のような実装を提案します:
} else if (ss.realtimeAPIMode) {
if (hs.ws?.readyState === WebSocket.OPEN) {
// ユーザーの発言を追加して表示
const updateLog: Message[] = [
...hs.chatLog,
{ role: 'user', content: newMessage },
]
homeStore.setState({
chatLog: updateLog,
})
+
+ // RealtimeAPI通信処理
+ try {
+ hs.ws.send(JSON.stringify({
+ content: newMessage,
+ type: 'realtime_chat'
+ }))
+ } catch (error) {
+ console.error('RealtimeAPI通信エラー:', error)
+ homeStore.setState({
+ assistantMessage: errors['APIError'],
+ chatProcessing: false
+ })
+ }
+ } else {
+ homeStore.setState({
+ assistantMessage: errors['NotConnectedToExternalAssistant'],
+ chatProcessing: false
+ })
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
} else if (ss.realtimeAPIMode) { | |
if (hs.ws?.readyState === WebSocket.OPEN) { | |
// ユーザーの発言を追加して表示 | |
const updateLog: Message[] = [ | |
...hs.chatLog, | |
{ role: 'user', content: newMessage }, | |
] | |
homeStore.setState({ | |
chatLog: updateLog, | |
}) | |
} | |
} else if (ss.realtimeAPIMode) { | |
if (hs.ws?.readyState === WebSocket.OPEN) { | |
// ユーザーの発言を追加して表示 | |
const updateLog: Message[] = [ | |
...hs.chatLog, | |
{ role: 'user', content: newMessage }, | |
] | |
homeStore.setState({ | |
chatLog: updateLog, | |
}) | |
// RealtimeAPI通信処理 | |
try { | |
hs.ws.send(JSON.stringify({ | |
content: newMessage, | |
type: 'realtime_chat' | |
})) | |
} catch (error) { | |
console.error('RealtimeAPI通信エラー:', error) | |
homeStore.setState({ | |
assistantMessage: errors['APIError'], | |
chatProcessing: false | |
}) | |
} | |
} else { | |
homeStore.setState({ | |
assistantMessage: errors['NotConnectedToExternalAssistant'], | |
chatProcessing: false | |
}) | |
} |
@@ -224,7 +224,7 @@ const Voice = () => { | |||
{t('TestVoice')} | |||
</TextButton> | |||
</div> | |||
<div className="my-24"> | |||
<div className="my-24 font-bold"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Azure TTSの実装に関する重要な問題
現在の実装には以下の問題があります:
- OpenAI TTSのstate(openaiTTSVoice、openaiTTSModel、openaiTTSSpeed)を誤って再利用しています
- Azure固有の音声オプションが実装されていません
- UIの構造が一貫していません
以下の修正を提案します:
- const openaiTTSVoice = settingsStore((s) => s.openaiTTSVoice)
- const openaiTTSModel = settingsStore((s) => s.openaiTTSModel)
- const openaiTTSSpeed = settingsStore((s) => s.openaiTTSSpeed)
+ const azureTTSVoice = settingsStore((s) => s.azureTTSVoice)
+ const azureTTSSpeed = settingsStore((s) => s.azureTTSSpeed)
// Azureセクション内で
- <select
- value={openaiTTSVoice}
- onChange={(e) =>
- settingsStore.setState({
- openaiTTSVoice: e.target.value as OpenAITTSVoice,
- })
- }
+ <select
+ value={azureTTSVoice}
+ onChange={(e) =>
+ settingsStore.setState({
+ azureTTSVoice: e.target.value as AzureTTSVoice,
+ })
+ }
className="px-16 py-8 bg-surface1 hover:bg-surface1-hover rounded-8"
>
- <option value="alloy">alloy</option>
- <option value="echo">echo</option>
- <option value="fable">fable</option>
- <option value="onyx">onyx</option>
- <option value="nova">nova</option>
- <option value="shimmer">shimmer</option>
+ <option value="ja-JP-NanamiNeural">Nanami (女性)</option>
+ <option value="ja-JP-KeitaNeural">Keita (男性)</option>
+ <option value="ja-JP-AoiNeural">Aoi (女性)</option>
</select>
- <div className="mt-16 font-bold">{t('OpenAITTSModel')}</div>
- <div className="mt-16 font-bold">
- {t('OpenAITTSSpeed')}: {openaiTTSSpeed}
+ <div className="mt-16 font-bold">
+ {t('AzureTTSSpeed')}: {azureTTSSpeed}
</div>
<input
type="range"
min={0.25}
max={4.0}
step={0.01}
- value={openaiTTSSpeed}
+ value={azureTTSSpeed}
className="mt-8 mb-16 input-range"
onChange={(e) => {
settingsStore.setState({
- openaiTTSSpeed: Number(e.target.value),
+ azureTTSSpeed: Number(e.target.value),
})
}}
/>
また、以下の型定義の追加も必要です:
export type AzureTTSVoice =
| 'ja-JP-NanamiNeural'
| 'ja-JP-KeitaNeural'
| 'ja-JP-AoiNeural'
Also applies to: 590-676
import { | ||
RealtimeAPIModeContentType, | ||
RealtimeAPIModeVoice, | ||
} from '@/features/constants/settings' | ||
import toastStore from '@/features/stores/toast' | ||
import { sendSessionUpdate } from '@/components/realtimeAPIUtils' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
新しい状態管理とWebSocket関連の実装について
新しく追加されたRealtimeAPI関連の実装について、以下の改善を提案します:
- WebSocketインスタンスの型安全性が確保されていません
- 状態管理の初期値が明示的に設定されていません
以下の修正を提案します:
+// WebSocket型の定義
+type CustomWebSocket = WebSocket & {
+ // 必要に応じて追加のプロパティを定義
+};
-const ws = homeStore((s) => s.ws)
+const ws = homeStore((s) => s.ws as CustomWebSocket | null)
+// 初期状態の設定
+const initialState = {
+ realtimeAPIModeVoice: 'alloy' as RealtimeAPIModeVoice,
+ // 他の初期値
+};
Also applies to: 25-25, 45-46
// chatLogを空配列に初期化 | ||
homeStore.setState({ ws: ws, chatLog: [] }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chatLog
の初期化に注意が必要です
handleOpen
関数内でchatLog
を空の配列に初期化していますが、これにより既存のチャット履歴が失われる可能性があります。WebSocket接続が再確立されるたびにチャット履歴がリセットされることは、ユーザーエクスペリエンスに影響を与える可能性があります。必要に応じて、chatLog
の初期化を再検討してください。
ws = setupWebsocket(t) | ||
if (ws) { | ||
ws.addEventListener('open', handleOpen) | ||
ws.addEventListener('message', (event) => | ||
handleMessage( | ||
event, | ||
accumulatedAudioDataRef, | ||
processMessage, | ||
ws!, | ||
t | ||
) | ||
) | ||
ws.addEventListener('error', handleError) | ||
ws.addEventListener('close', handleClose) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
再接続ロジックの改善を検討してください
再接続時に新しいWebSocket接続を設定していますが、イベントリスナーの重複登録に注意が必要です。再接続ごとにイベントリスナーを追加しているため、同一のリスナーが複数回登録され、予期しない動作を引き起こす可能性があります。イベントリスナーを登録する前に、既存のリスナーを適切に削除するか、再接続時に新しいWebSocketインスタンスを作成する方法を検討してください。
修正案として、再接続時に古いWebSocketのイベントリスナーをクリアし、新しい接続に対してリスナーを再登録することを提案します。
ws.close()
+ ws.removeEventListener('open', handleOpen)
+ ws.removeEventListener('message', messageHandler)
+ ws.removeEventListener('error', handleError)
+ ws.removeEventListener('close', handleClose)
ws = setupWebsocket(t)
if (ws) {
- ws.addEventListener('open', handleOpen)
+ ws.addEventListener('open', handleOpen)
+ const messageHandler = (event) =>
+ handleMessage(event, accumulatedAudioDataRef, processMessage, ws!, t)
+ ws.addEventListener('message', messageHandler)
ws.addEventListener('error', handleError)
ws.addEventListener('close', handleClose)
}
この修正の実装について、さらにサポートが必要な場合はお知らせください。
Committable suggestion was skipped due to low confidence.
if (jsonData.part && jsonData.part.transcript) { | ||
await processMessage({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
オプショナルチェイニングを使用してコードを簡潔にしましょう
jsonData.part
と jsonData.part.transcript
の存在チェックをオプショナルチェイニングで簡潔に表現できます。
-if (jsonData.part && jsonData.part.transcript) {
+if (jsonData.part?.transcript) {
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if (jsonData.part && jsonData.part.transcript) { | |
await processMessage({ | |
if (jsonData.part?.transcript) { | |
await processMessage({ |
🧰 Tools
🪛 Biome
[error] 181-182: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
const newWs = setupWebsocket(t) | ||
if (newWs) { | ||
newWs.addEventListener('open', (event) => { | ||
console.log('WebSocket connection opened:', event) | ||
removeToast() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setupWebsocket
が null
を返す場合の処理を追加しましょう
setupWebsocket
関数が null
を返す可能性がありますが、その場合のエラーハンドリングがありません。接続に失敗した場合のユーザーへの通知を追加しましょう。
const newWs = setupWebsocket(t)
-if (newWs) {
+if (newWs !== null) {
newWs.addEventListener('open', (event) => {
// 既存のコード
})
+} else {
+ console.error('Failed to establish WebSocket connection.')
+ toastStore.getState().addToast({
+ message: t('Toasts.WebSocketConnectionFailed'),
+ type: 'error',
+ duration: 5000,
+ tag: 'websocket-connection-failed',
+ })
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const newWs = setupWebsocket(t) | |
if (newWs) { | |
newWs.addEventListener('open', (event) => { | |
console.log('WebSocket connection opened:', event) | |
removeToast() | |
const newWs = setupWebsocket(t) | |
if (newWs !== null) { | |
newWs.addEventListener('open', (event) => { | |
console.log('WebSocket connection opened:', event) | |
removeToast() | |
} else { | |
console.error('Failed to establish WebSocket connection.') | |
toastStore.getState().addToast({ | |
message: t('Toasts.WebSocketConnectionFailed'), | |
type: 'error', | |
duration: 5000, | |
tag: 'websocket-connection-failed', | |
}) | |
} |
;(wsConfig.session as any).tools = realtimeAPIToolsConfig | ||
;(wsConfig.session as any).tool_choice = 'auto' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
as any
の使用を避けて型安全性を向上させましょう
wsConfig.session
に対して as any
を使用していますが、session
の型を適切に定義することで、as any
を避けることができます。これにより、型安全性が高まり、将来的なバグを防止できます。
// Session 型を定義します
interface SessionConfig {
modalities: string[];
instructions: string;
voice: string;
input_audio_format: string;
output_audio_format: string;
input_audio_transcription: {
model: string;
};
turn_detection: null;
temperature: number;
max_response_output_tokens: number;
// ↓ 追加
+ tools?: typeof realtimeAPIToolsConfig;
+ tool_choice?: string;
}
// wsConfig の型を SessionConfig を使用して更新します
const wsConfig = {
type: 'session.update',
session: {
// 既存のプロパティ...
+ tools: realtimeAPIToolsConfig,
+ tool_choice: 'auto',
} as SessionConfig,
};
-;(wsConfig.session as any).tools = realtimeAPIToolsConfig
-;(wsConfig.session as any).tool_choice = 'auto'
Committable suggestion was skipped due to low confidence.
Summary by CodeRabbit
新機能
バグ修正
ドキュメント