-
Notifications
You must be signed in to change notification settings - Fork 57
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
ドキュメント更新とリファクタリング #164
ドキュメント更新とリファクタリング #164
Changes from 10 commits
01a327b
1668bfc
3071a29
7df2b39
33e9081
119bcbf
333b861
3071064
95b172c
2d582e5
2b28cc3
f93658a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,121 +9,123 @@ import slideStore from '@/features/stores/slide' | |
import { goToSlide } from '@/components/slides' | ||
|
||
/** | ||
* 文字列を処理する関数 | ||
* 受け取ったメッセージを処理し、AIの応答を生成して発話させる | ||
* @param receivedMessage 処理する文字列 | ||
* @param sentences 返答を一文単位で格納する配列 | ||
* @param aiTextLog AIの返答ログ | ||
* @param tag タグ | ||
* @param isCodeBlock コードブロックのフラグ | ||
* @param codeBlockText コードブロックのテキスト | ||
*/ | ||
export const processReceivedMessage = async ( | ||
receivedMessage: string, | ||
sentences: string[] = [], | ||
aiTextLog: Message[] = [], | ||
tag: string = '', | ||
isCodeBlock: boolean = false, | ||
codeBlockText: string = '' | ||
) => { | ||
export const speakMessageHandler = async (receivedMessage: string) => { | ||
const ss = settingsStore.getState() | ||
const hs = homeStore.getState() | ||
const currentSlideMessages: string[] = [] | ||
|
||
// 返答内容のタグ部分と返答部分を分離 | ||
const tagMatch = receivedMessage.match(/^\[(.*?)\]/) | ||
if (tagMatch && tagMatch[0]) { | ||
tag = tagMatch[0] | ||
receivedMessage = receivedMessage.slice(tag.length) | ||
} | ||
let isCodeBlock: boolean = false | ||
let codeBlockText: string = '' | ||
let logText: string = '' | ||
let assistantMessage = [] | ||
let remainingMessage = receivedMessage | ||
let prevRemainingMessage = '' | ||
const addedChatLog: Message[] = [] | ||
const delimiter = '```' | ||
|
||
while (remainingMessage.length > 0 || isCodeBlock) { | ||
let sentence = '' | ||
prevRemainingMessage = remainingMessage | ||
|
||
if (remainingMessage.includes(delimiter)) { | ||
// コードブロックの分割 | ||
isCodeBlock = true | ||
const [first, ...rest] = remainingMessage.split(delimiter) | ||
;[remainingMessage, codeBlockText] = [ | ||
first, | ||
rest.join(delimiter).replace(/^\n/, ''), | ||
] | ||
} else if (remainingMessage == '' && isCodeBlock) { | ||
// コードブロックの分割 | ||
let code = '' | ||
const [first, ...rest] = codeBlockText.split(delimiter) | ||
;[code, remainingMessage] = [first, rest.join(delimiter)] | ||
addedChatLog.push({ | ||
role: 'assistant', | ||
content: logText, | ||
}) | ||
addedChatLog.push({ | ||
role: 'code', | ||
content: code, | ||
}) | ||
|
||
codeBlockText = '' | ||
logText = '' | ||
isCodeBlock = false | ||
} | ||
|
||
// 返答内容のタグ部分と返答部分を分離 | ||
let tag: string = '' | ||
const tagMatch = remainingMessage.match(/^\[(.*?)\]/) | ||
if (tagMatch?.[0]) { | ||
tag = tagMatch[0] | ||
remainingMessage = remainingMessage.slice(tag.length) | ||
} | ||
|
||
// 返答を一文単位で切り出して処理する | ||
while (receivedMessage.length > 0) { | ||
const sentenceMatch = receivedMessage.match( | ||
/^(.+?[。..!?!?\n]|.{20,}[、,])/ | ||
const sentenceMatch = remainingMessage.match( | ||
/^(.{1,19}?[。..!?!?\n]|.{20,}?[、,])/ | ||
) | ||
if (sentenceMatch?.[0]) { | ||
let sentence = sentenceMatch[0] | ||
// 区切った文字をsentencesに追加 | ||
sentences.push(sentence) | ||
// 区切った文字の残りでreceivedMessageを更新 | ||
receivedMessage = receivedMessage.slice(sentence.length).trimStart() | ||
|
||
// 発話不要/不可能な文字列だった場合はスキップ | ||
if ( | ||
!sentence.includes('```') && | ||
!sentence.replace( | ||
/^[\s\u3000\t\n\r\[\(\{「[(【『〈《〔{«‹〘〚〛〙›»〕》〉』】)]」\}\)\]'"''""・、。,.!?!?::;;\-_=+~~**@@##$$%%^^&&||\\\//``]+$/gu, | ||
'' | ||
) | ||
) { | ||
continue | ||
} | ||
|
||
// タグと返答を結合(音声再生で使用される) | ||
let aiText = `${tag} ${sentence}` | ||
console.log('aiText', aiText) | ||
sentence = sentenceMatch?.[0] | ||
// 区切った文字の残りでremainingMessageを更新 | ||
remainingMessage = remainingMessage.slice(sentence.length).trimStart() | ||
} | ||
|
||
if (isCodeBlock && !sentence.includes('```')) { | ||
codeBlockText += sentence | ||
continue | ||
} | ||
if (remainingMessage != '' && remainingMessage == prevRemainingMessage) { | ||
sentence = prevRemainingMessage | ||
remainingMessage = '' | ||
} | ||
|
||
if (sentence.includes('```')) { | ||
if (isCodeBlock) { | ||
// コードブロックの終了処理 | ||
const [codeEnd, ...restOfSentence] = sentence.split('```') | ||
aiTextLog.push({ | ||
role: 'code', | ||
content: codeBlockText + codeEnd, | ||
}) | ||
aiText += `${tag} ${restOfSentence.join('```') || ''}` | ||
// 発話不要/不可能な文字列だった場合はスキップ | ||
if ( | ||
sentence == '' || | ||
sentence.replace( | ||
/^[\s\u3000\t\n\r\[\(\{「[(【『〈《〔{«‹〘〚〛〙›»〕》〉』】)]」\}\)\]'"''""・、。,.!?!?::;;\-_=+~~**@@##$$%%^^&&||\\\//``]+$/gu, | ||
'' | ||
) == '' | ||
) { | ||
continue | ||
} | ||
Comment on lines
+29
to
+91
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion メッセージ処理ロジックの改善 メッセージ処理のロジックが大幅に改善されていますが、いくつかの提案があります:
以下のようなリファクタリングを提案します: const CODE_BLOCK_DELIMITER = '```';
const SENTENCE_REGEX = /^(.{1,19}?[。..!?!?\n]|.{20,}?[、,])/;
function extractCodeBlock(message: string): [string, string] {
const [first, ...rest] = message.split(CODE_BLOCK_DELIMITER);
return [first, rest.join(CODE_BLOCK_DELIMITER).replace(/^\n/, '')];
}
function extractTag(message: string): [string, string] {
const tagMatch = message.match(/^\[(.*?)\]/);
if (tagMatch?.[0]) {
return [tagMatch[0], message.slice(tagMatch[0].length)];
}
return ['', message];
}
// メインのwhile文内で使用
const [remainingMessage, codeBlockText] = isCodeBlock
? extractCodeBlock(remainingMessage)
: [remainingMessage, ''];
const [tag, messageWithoutTag] = extractTag(remainingMessage); これらの変更により、メインのループがより読みやすくなり、各処理の意図がより明確になります。 |
||
|
||
// AssistantMessage欄の更新 | ||
homeStore.setState({ assistantMessage: sentences.join(' ') }) | ||
// 区切った文字をassistantMessageに追加 | ||
assistantMessage.push(sentence) | ||
// タグと返答を結合(音声再生で使用される) | ||
let aiText = tag ? `${tag} ${sentence}` : sentence | ||
|
||
codeBlockText = '' | ||
isCodeBlock = false | ||
} else { | ||
// コードブロックの開始処理 | ||
isCodeBlock = true | ||
;[aiText, codeBlockText] = aiText.split('```') | ||
} | ||
const aiTalks = textsToScreenplay([aiText], ss.koeiroParam) // TODO | ||
logText = logText + ' ' + sentence | ||
|
||
sentence = sentence.replace(/```/g, '') | ||
speakCharacter( | ||
aiTalks[0], | ||
() => { | ||
homeStore.setState({ | ||
assistantMessage: assistantMessage.join(' '), | ||
}) | ||
hs.incrementChatProcessingCount() | ||
// スライド用のメッセージを更新 | ||
currentSlideMessages.push(sentence) | ||
}, | ||
() => { | ||
hs.decrementChatProcessingCount() | ||
currentSlideMessages.shift() | ||
homeStore.setState({ | ||
slideMessages: currentSlideMessages, | ||
}) | ||
} | ||
) | ||
} // while loop end | ||
Comment on lines
+93
to
+119
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion メッセージ処理と発話ロジックの改善 メッセージの処理と発話ロジックが適切に実装されていますが、いくつかの改善点があります:
以下のようなリファクタリングを提案します: function updateHomeStore(sentence: string, assistantMessage: string[]) {
homeStore.setState({
assistantMessage: assistantMessage.join(' '),
slideMessages: [...homeStore.getState().slideMessages, sentence],
});
homeStore.getState().incrementChatProcessingCount();
}
// speakCharacter関数内で使用
speakCharacter(
aiTalks[0],
() => updateHomeStore(sentence, assistantMessage),
() => {
homeStore.getState().decrementChatProcessingCount();
homeStore.setState(state => ({
slideMessages: state.slideMessages.slice(1),
}));
}
); これらの変更により、ステート更新のロジックがより整理され、可読性が向上します。 |
||
|
||
const aiTalks = textsToScreenplay([aiText], ss.koeiroParam) | ||
aiTextLog.push({ role: 'assistant', content: sentence }) | ||
|
||
// 文ごとに音声を生成 & 再生、返答を表示 | ||
const currentAssistantMessage = sentences.join(' ') | ||
|
||
speakCharacter( | ||
aiTalks[0], | ||
() => { | ||
homeStore.setState({ | ||
assistantMessage: currentAssistantMessage, | ||
}) | ||
hs.incrementChatProcessingCount() | ||
// スライド用のメッセージを更新 | ||
currentSlideMessages.push(sentence) | ||
homeStore.setState({ | ||
slideMessages: currentSlideMessages, | ||
}) | ||
}, | ||
() => { | ||
hs.decrementChatProcessingCount() | ||
currentSlideMessages.shift() | ||
homeStore.setState({ | ||
slideMessages: currentSlideMessages, | ||
}) | ||
} | ||
) | ||
} else { | ||
// マッチする文がない場合、ループを抜ける | ||
break | ||
} | ||
} | ||
addedChatLog.push({ | ||
role: 'assistant', | ||
content: logText, | ||
}) | ||
homeStore.setState({ | ||
slideMessages: currentSlideMessages, | ||
chatLog: [...hs.chatLog, ...addedChatLog], | ||
}) | ||
} | ||
|
||
/** | ||
|
This file was deleted.
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.
型安全性の向上が必要です。
ss
とhs
変数の型がany
として推論されています。型安全性を高めるために、これらの変数に明示的な型アノテーションを追加することを推奨します。以下のように型を指定することを検討してください:
SettingsState
とHomeState
は適切なインターフェースまたは型エイリアスに置き換えてください。