Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d99b66e
TTSをAzure SpeechからOpenAI gpt-4o-mini-ttsの女性声へ全面移行 (#2)
TinyKitten Aug 13, 2026
b2ea58b
TTSの既定ボイスを日英で分けて早口寄りに調整する (#3)
TinyKitten Aug 13, 2026
7782d5c
AIチャットのモデルにGemini(Vertex AI)を追加する (#4)
TinyKitten Aug 17, 2026
bf4776d
TTSをOpenAIからGoogle Cloud Text-to-Speechへ全面移行する (#5)
TinyKitten Aug 17, 2026
16a6518
本番の AGENT_MODEL を Gemini(Vertex AI)へ切り替える (#6)
TinyKitten Aug 17, 2026
335bbf4
staging の駅検索を sapi-bff-stg から stationapi-stg へ切り替える (#7)
TinyKitten Aug 22, 2026
d7dcbb3
本番の駅検索を sapi-bff から stationapi へ切り替える (#9)
TinyKitten Aug 23, 2026
7370018
フィードバックを原因リポジトリへ振り分け、トリアージの起票品質を改善する (#14)
TinyKitten Aug 27, 2026
f850f3e
アプリ指定の読み上げ速度を受け付け既定速度を等速へ変更 (#16)
TinyKitten Aug 27, 2026
06ce6bc
フィードバックのキューに dead letter queue を設定する (#19)
TinyKitten Aug 27, 2026
631398b
DLQ の紐付けを確認する手順を README に追加する (#22)
TinyKitten Aug 27, 2026
8c47ab7
フィードバック再試行での Issue 重複起票を防ぐ (#23)
TinyKitten Aug 28, 2026
94a409c
AI エージェントのモデルを Gemini 3.8 Flash へ更新する (#24)
TinyKitten Sep 3, 2026
f3fa862
英語TTSで「Keisei」が「かいせい」と読まれる誤読を合成前の表記置換で修正する (#25)
TinyKitten Sep 6, 2026
e73f616
GitHub Actions で dev・master からのデプロイを自動化する (#26)
TinyKitten Sep 6, 2026
a63ffe3
英語TTSで「Seibu」が「さいぶ」と読まれる誤読を合成前の表記置換で修正する (#27)
TinyKitten Sep 6, 2026
439ec90
master を dev へ取り込み AGENTS.md を同期する (#30)
TinyKitten Sep 12, 2026
3dda858
フィードバックトリアージの判定をTypeSafeに切り替える (#32)
TinyKitten Sep 17, 2026
6ee0bef
提案駅のリランクをTypeSafeで判定して対話ターンへ組み込む (#33)
TinyKitten Sep 17, 2026
cce388d
リランクの注記を user ロールで注入し Gemini でのターン失敗を直す (#34)
TinyKitten Sep 17, 2026
a81fe64
フィードバックから自動で修正PRを出すワークフローを追加 (#36)
TinyKitten Sep 21, 2026
fe49160
feedback-autofixを更新し準備が失敗した場合も結果を報告するようにした (#38)
TinyKitten Sep 21, 2026
0c1e8f3
本文が空白のみのフィードバックをpostFeedbackで弾くようにする (#39)
TinyKitten Sep 21, 2026
69917f7
英語TTSでMineを「マイン」と読む誤読を修正する (#42)
TinyKitten Sep 21, 2026
69dcec7
Merge remote-tracking branch 'origin/master' into release/2026-09-22-…
TinyKitten Sep 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/utils/normalize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,32 @@ describe('utils/normalize.ts', () => {
expect(normalizeRomanText('Seibuen')).toBe('Seibuen');
});

it('replaces Mine with a spelling English TTS reads as みね', () => {
// 英語 TTS は "Mine" を英単語の「まいん」と読むため、辞書語の綴りへ倒す
expect(normalizeRomanText('Change here for the Mine Line.')).toBe(
'Change here for the Me-nay Line.'
);
expect(normalizeRomanText('The next station is MINE.')).toBe(
'The next station is Me-nay.'
);
expect(normalizeRomanText('The next station is Nishi-Mine.')).toBe(
'The next station is Nishi-me-nay.'
);
// 宇都宮ライトレールの峰(Mine)のような単独の駅名
expect(normalizeRomanText('The next stop is Mine.')).toBe(
'The next stop is Me-nay.'
);
expect(normalizeRomanText('This train is bound for Mine.')).toBe(
'This train is bound for Me-nay.'
);
// 語中・語頭に埋まった mine も置換する
expect(normalizeRomanText('Takamine')).toBe('Taka-me-nay');
expect(normalizeRomanText('Minezaki')).toBe('Me-nay-zaki');
expect(normalizeRomanText('KAMINEYAMA')).toBe('Ka-me-nay-yama');
// mine を含まない語は変えない
expect(normalizeRomanText('Minami-Urawa')).toBe('Minami-urawa');
});

it('keeps Kay-say stable when normalized twice', () => {
// 二重に適用しても結果が変わらないこと(キャッシュキーの安定性)
expect(normalizeRomanText(normalizeRomanText('Keisei Main Line'))).toBe(
Expand All @@ -62,6 +88,12 @@ describe('utils/normalize.ts', () => {
expect(normalizeRomanText(normalizeRomanText('Seibu Shinjuku Line'))).toBe(
'Say-boo Shinjuku Line'
);
expect(normalizeRomanText(normalizeRomanText('Mine Line'))).toBe(
'Me-nay Line'
);
expect(normalizeRomanText(normalizeRomanText('Takamine'))).toBe(
'Taka-me-nay'
);
});

it.each(['Tokyo', 'tOkyo'])('text: %s', (text) => {
Expand Down
13 changes: 13 additions & 0 deletions src/utils/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ const capitalizeSegment = (seg: string): string => {
: seg;
};

// Takamine / Minezaki のように語中・語頭に埋まった "mine" も読み替える。
// 前後に英字が続く場合はハイフンで区切って "Me-nay" を独立させ、
// 語頭のときだけ先頭を大文字にする(Takamine → Taka-me-nay)
const replaceMine = (match: string, offset: number, str: string): string => {
const before = offset > 0 && /[A-Za-z]/.test(str.charAt(offset - 1));
const after = /[A-Za-z]/.test(str.charAt(offset + match.length));
const head = /[A-Z]/.test(match.charAt(0)) ? 'Me' : 'me';
return `${before ? '-' : ''}${head}-nay${after ? '-' : ''}`;
};

// テキストノード(SSML タグの外側)だけに掛ける正規化。タグやその属性値
// (<sub alias="Sta."> や <phoneme ph="..."> 等)を壊さないため、タグ部分には適用しない。
const normalizeTextNode = (text: string): string =>
Expand Down Expand Up @@ -43,6 +53,9 @@ const normalizeTextNode = (text: string): string =>
// ハイフン連結の駅名も語単位で置換する
.replace(/\bKeisei\b/gi, 'Kay-say')
.replace(/\bSeibu\b/gi, 'Say-boo')
// 「mine(美祢・峰など)」は英語 TTS が英単語 "mine"(まいん)として読むため、
// 同じく辞書語 "Me" + "nay" の連結で /mi.neɪ/(みね)に寄せる
.replace(/mine/gi, replaceMine)
// 都営バスを想定
.replace(/\bSta\./gi, ' Station')
.replace(/\bUniv\./gi, ' University')
Expand Down
Loading