From 332fe4d25ea60042c3a62b6db8b5096b3fd656f5 Mon Sep 17 00:00:00 2001 From: tegnike Date: Sat, 11 Jan 2025 23:52:06 +0100 Subject: [PATCH 1/8] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E3=83=96?= =?UTF-8?q?=E3=83=AD=E3=83=83=E3=82=AF=E5=89=8D=E3=81=A7=E6=96=87=E7=AB=A0?= =?UTF-8?q?=E3=81=8C=E9=80=94=E5=88=87=E3=82=8C=E3=81=A6=E3=81=97=E3=81=BE?= =?UTF-8?q?=E3=81=86=E4=B8=8D=E5=85=B7=E5=90=88=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/chat/handlers.ts | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/features/chat/handlers.ts b/src/features/chat/handlers.ts index ef5ea5de..a8cb1fb7 100644 --- a/src/features/chat/handlers.ts +++ b/src/features/chat/handlers.ts @@ -177,13 +177,8 @@ export const processAIResponse = async ( // 返答を一文単位で切り出して処理する while (receivedMessage.length > 0) { - if (isCodeBlock && !receivedMessage.includes('```')) { - codeBlockText += receivedMessage - continue - } - - if (receivedMessage.includes('```')) { - if (isCodeBlock) { + if (isCodeBlock) { + if (receivedMessage.includes('```')) { // コードブロックの終了処理 const [codeEnd, ...restOfSentence] = receivedMessage.split('```') aiTextLog.push({ @@ -191,14 +186,30 @@ export const processAIResponse = async ( content: codeBlockText + codeEnd, }) - receivedMessage = restOfSentence.join('```') - + receivedMessage = restOfSentence.join('```').trimStart() codeBlockText = '' isCodeBlock = false + continue + } else { + // コードブロック中だが終了マークがまだない + codeBlockText += receivedMessage + receivedMessage = '' + continue + } + } + + if (receivedMessage.includes('```')) { + // コードブロックの開始処理 + const [beforeCode, ...rest] = receivedMessage.split('```') + + // コードブロック前のテキストを処理 + if (beforeCode.trim()) { + receivedMessage = beforeCode } else { - // コードブロックの開始処理 isCodeBlock = true - ;[receivedMessage, codeBlockText] = receivedMessage.split('```') + codeBlockText = rest.join('```') + receivedMessage = '' + continue } } From 4c58fc9820e2a62c309f7777321fa19f4a6c448f Mon Sep 17 00:00:00 2001 From: tegnike Date: Tue, 14 Jan 2025 08:50:34 +0100 Subject: [PATCH 2/8] =?UTF-8?q?=E3=83=AD=E3=82=B0=E7=94=BB=E9=9D=A2?= =?UTF-8?q?=E3=81=A7=E3=82=B3=E3=83=BC=E3=83=89=E3=83=96=E3=83=AD=E3=83=83?= =?UTF-8?q?=E3=82=AF=E3=81=8C=E3=83=A6=E3=83=BC=E3=82=B6=E7=99=BA=E3=81=AB?= =?UTF-8?q?=E8=A6=8B=E3=81=88=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=AA?= =?UTF-8?q?=E3=81=A3=E3=81=A6=E3=81=84=E3=81=9F=E3=81=AE=E3=81=A7AI?= =?UTF-8?q?=E7=99=BA=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/settings/log.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/settings/log.tsx b/src/components/settings/log.tsx index 3c3db471..622a3aa4 100644 --- a/src/components/settings/log.tsx +++ b/src/components/settings/log.tsx @@ -53,7 +53,7 @@ const Log = () => { className="my-8 grid grid-flow-col grid-cols-[min-content_1fr] gap-x-fixed" >
- {value.role === 'assistant' ? 'Character' : 'You'} + {value.role === 'user' ? 'You' : 'Character'}
{typeof value.content == 'string' ? ( Date: Tue, 14 Jan 2025 08:51:26 +0100 Subject: [PATCH 3/8] =?UTF-8?q?=E6=A4=9C=E7=B4=A2=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=82=92=E5=88=A9=E7=94=A8=E3=81=99=E3=82=8B=E3=81=8C=E5=86=8D?= =?UTF-8?q?=E8=AA=AD=E3=81=BF=E8=BE=BC=E3=81=BF=E3=81=A7=E3=83=AA=E3=82=BB?= =?UTF-8?q?=E3=83=83=E3=83=88=E3=81=95=E3=82=8C=E3=81=A6=E3=81=97=E3=81=BE?= =?UTF-8?q?=E3=81=86=E5=95=8F=E9=A1=8C=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/stores/settings.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/features/stores/settings.ts b/src/features/stores/settings.ts index 40d41c3a..ec376444 100644 --- a/src/features/stores/settings.ts +++ b/src/features/stores/settings.ts @@ -388,6 +388,7 @@ const settingsStore = create()( audioModeVoice: state.audioModeVoice, messageReceiverEnabled: state.messageReceiverEnabled, clientId: state.clientId, + useSearchGrounding: state.useSearchGrounding, openaiTTSKey: state.openaiTTSKey, openaiTTSVoice: state.openaiTTSVoice, openaiTTSModel: state.openaiTTSModel, From 35c5e15bbd0c03951bd396ec608be086f90e9749 Mon Sep 17 00:00:00 2001 From: tegnike Date: Tue, 14 Jan 2025 09:16:32 +0100 Subject: [PATCH 4/8] =?UTF-8?q?=E7=89=B9=E5=AE=9A=E3=81=AEgemini=E3=83=A2?= =?UTF-8?q?=E3=83=87=E3=83=AB=E3=81=A7=E6=A4=9C=E7=B4=A2=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=81=8C=E4=BD=BF=E3=81=88=E3=81=9A=E3=81=AB=E3=82=A8=E3=83=A9?= =?UTF-8?q?=E3=83=BC=E3=81=8C=E5=87=BA=E3=81=A6=E3=81=84=E3=81=9F=E3=81=AE?= =?UTF-8?q?=E3=81=A7=E3=83=90=E3=83=AA=E3=83=87=E3=83=BC=E3=82=B7=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/settings/modelProvider.tsx | 28 +++++++++++++++++++---- src/features/stores/settings.ts | 8 +++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/components/settings/modelProvider.tsx b/src/components/settings/modelProvider.tsx index b32fe249..27af751b 100644 --- a/src/components/settings/modelProvider.tsx +++ b/src/components/settings/modelProvider.tsx @@ -6,7 +6,10 @@ import { SYSTEM_PROMPT } from '@/features/constants/systemPromptConstants' import { Link } from '../link' import { TextButton } from '../textButton' import { useCallback } from 'react' -import { multiModalAIServices } from '@/features/stores/settings' +import { + multiModalAIServices, + googleSearchGroundingModels, +} from '@/features/stores/settings' import { AudioModeInputType, OpenAITTSVoice, @@ -87,6 +90,12 @@ const ModelProvider = () => { if (newService !== 'openai' && newService !== 'azure') { settingsStore.setState({ realtimeAPIMode: false }) } + + if (newService === 'google') { + if (!googleSearchGroundingModels.includes(selectAIModel as any)) { + settingsStore.setState({ useSearchGrounding: false }) + } + } }, [] ) @@ -455,11 +464,17 @@ const ModelProvider = () => { @@ -991,6 +994,31 @@ const ModelProvider = () => { ) + } else if (selectAIService === 'deepseek') { + return ( +
+
+ {t('DeepSeekAPIKeyLabel')} +
+
+ {t('APIKeyInstruction')} +
+ +
+ + settingsStore.setState({ deepseekKey: e.target.value }) + } + /> +
+ ) } })()} diff --git a/src/features/chat/aiChatFactory.ts b/src/features/chat/aiChatFactory.ts index 5cd1c783..9817d7ad 100644 --- a/src/features/chat/aiChatFactory.ts +++ b/src/features/chat/aiChatFactory.ts @@ -25,6 +25,7 @@ export async function getAIChatResponseStream( case 'mistralai': case 'perplexity': case 'fireworks': + case 'deepseek': return getVercelAIChatResponseStream(messages) case 'localLlm': return getLocalLLMChatResponseStream( diff --git a/src/features/constants/settings.ts b/src/features/constants/settings.ts index a492568f..3a5b2e0e 100644 --- a/src/features/constants/settings.ts +++ b/src/features/constants/settings.ts @@ -10,6 +10,7 @@ export type AIService = | 'perplexity' | 'fireworks' | 'dify' + | 'deepseek' export interface AIServiceConfig { openai: { key: string; model: string } @@ -27,6 +28,7 @@ export interface AIServiceConfig { url: string conversationId: string } + deepseek: { key: string; model: string } } export type AIVoice = diff --git a/src/features/stores/settings.ts b/src/features/stores/settings.ts index fc4d5e00..0855a80c 100644 --- a/src/features/stores/settings.ts +++ b/src/features/stores/settings.ts @@ -46,6 +46,7 @@ interface APIKeys { mistralaiKey: string perplexityKey: string fireworksKey: string + deepseekKey: string koeiromapKey: string youtubeApiKey: string elevenlabsApiKey: string @@ -173,6 +174,7 @@ const settingsStore = create()( perplexityKey: '', fireworksKey: '', difyKey: '', + deepseekKey: '', koeiromapKey: process.env.NEXT_PUBLIC_KOEIROMAP_KEY || '', youtubeApiKey: process.env.NEXT_PUBLIC_YOUTUBE_API_KEY || '', elevenlabsApiKey: '', diff --git a/src/pages/api/aiChat.ts b/src/pages/api/aiChat.ts index baba7a8e..9e8c8cae 100644 --- a/src/pages/api/aiChat.ts +++ b/src/pages/api/aiChat.ts @@ -5,6 +5,7 @@ import { createGoogleGenerativeAI } from '@ai-sdk/google' import { createCohere } from '@ai-sdk/cohere' import { createMistral } from '@ai-sdk/mistral' import { createAzure } from '@ai-sdk/azure' +import { createDeepSeek } from '@ai-sdk/deepseek' import { streamText, generateText, CoreMessage } from 'ai' import { NextRequest } from 'next/server' @@ -18,6 +19,7 @@ type AIServiceKey = | 'mistralai' | 'perplexity' | 'fireworks' + | 'deepseek' type AIServiceConfig = Record any> // Allow streaming responses up to 30 seconds @@ -116,6 +118,7 @@ export default async function handler(req: NextRequest) { baseURL: 'https://api.fireworks.ai/inference/v1', apiKey: aiApiKey, }), + deepseek: () => createDeepSeek({ apiKey: aiApiKey }), } const aiServiceInstance = aiServiceConfig[aiService as AIServiceKey] From 64261c214c7b05f9fdcf64caed50ad9c8a099c6e Mon Sep 17 00:00:00 2001 From: tegnike Date: Tue, 14 Jan 2025 10:21:36 +0100 Subject: [PATCH 6/8] =?UTF-8?q?=E3=81=AB=E3=81=98=E3=83=9C=E3=82=A4?= =?UTF-8?q?=E3=82=B9=E3=81=AEAPI=E3=82=92=E7=9B=B4=E6=8E=A5base64=E3=81=8C?= =?UTF-8?q?=E8=BF=94=E5=8D=B4=E3=81=95=E3=82=8C=E3=82=8B=E7=89=88=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/api/tts-nijivoice.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/pages/api/tts-nijivoice.ts b/src/pages/api/tts-nijivoice.ts index 9bc88e44..7301b4b4 100644 --- a/src/pages/api/tts-nijivoice.ts +++ b/src/pages/api/tts-nijivoice.ts @@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next' import axios from 'axios' type Data = { - audio?: ArrayBuffer + audio?: Buffer error?: string } @@ -20,11 +20,11 @@ export default async function handler( try { const response = await axios.post( - `https://api.nijivoice.com/api/platform/v1/voice-actors/${voiceActorId}/generate-voice`, + `https://api.nijivoice.com/api/platform/v1/voice-actors/${voiceActorId}/generate-encoded-voice`, { script, speed: speed.toString(), - format: 'wav', + format: 'mp3', emotionalLevel: emotionalLevel.toString(), soundDuration: soundDuration.toString(), }, @@ -37,15 +37,14 @@ export default async function handler( } ) - const audioUrl = response.data.generatedVoice.audioFileUrl + const base64Audio = response.data.generatedVoice.base64Audio + const audioBuffer = Buffer.from(base64Audio, 'base64') - const audioResponse = await axios.get(audioUrl, { - responseType: 'stream', - timeout: 30000, + res.writeHead(200, { + 'Content-Type': 'audio/mpeg', + 'Content-Length': audioBuffer.length, }) - - res.setHeader('Content-Type', 'audio/mpeg') - audioResponse.data.pipe(res) + res.end(audioBuffer) } catch (error) { console.error('Error in Nijivoice TTS:', error) res.status(500).json({ error: 'Internal Server Error' }) From 0726cb3b8439bacb86887ee74f6088cc2f03dd75 Mon Sep 17 00:00:00 2001 From: tegnike Date: Tue, 14 Jan 2025 11:04:15 +0100 Subject: [PATCH 7/8] =?UTF-8?q?deepseekKey=E3=81=AE=E6=B0=B8=E7=B6=9A?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/stores/settings.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/features/stores/settings.ts b/src/features/stores/settings.ts index 0855a80c..3e14f651 100644 --- a/src/features/stores/settings.ts +++ b/src/features/stores/settings.ts @@ -348,6 +348,7 @@ const settingsStore = create()( perplexityKey: state.perplexityKey, fireworksKey: state.fireworksKey, difyKey: state.difyKey, + deepseekKey: state.deepseekKey, koeiromapKey: state.koeiromapKey, youtubeApiKey: state.youtubeApiKey, elevenlabsApiKey: state.elevenlabsApiKey, From 757cc5b289c34b7966beff73f2f5b30eba3ae431 Mon Sep 17 00:00:00 2001 From: tegnike Date: Tue, 14 Jan 2025 11:04:31 +0100 Subject: [PATCH 8/8] =?UTF-8?q?=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/settings/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/settings/index.tsx b/src/components/settings/index.tsx index 8f18da92..8070ee7e 100644 --- a/src/components/settings/index.tsx +++ b/src/components/settings/index.tsx @@ -126,7 +126,7 @@ const Main = () => { const Footer = () => { return ( ) }