Repair non-Korean reply output

This commit is contained in:
2026-05-03 01:14:16 +09:00
parent ec02943538
commit 28ffbf02e1
2 changed files with 71 additions and 2 deletions

View File

@@ -127,6 +127,7 @@ bun run test:llm
- 최신 정보, 뉴스, 사실 확인, 검색 요청일 때만 웹 도구 사용
- `test:sttllm` 에서는 먼저 "대답할 가치가 있는 텍스트인지" 판정한 뒤 필요할 때만 답변
- 웹 검색이 실제로 시작되면 결과 전에 `검색해볼게요.` 같은 진행 메시지를 먼저 출력
- 답변에 한글 외 다른 문자군이 섞이면 한국어만으로 한 번 더 교정
## Windows용 .env 예시

View File

@@ -53,7 +53,7 @@ export interface ReplyAssessment {
}
const SYSTEM_PROMPT =
"너는 한국어로 짧고 자연스럽게 답하는 로컬 음성 비서다. 사용자의 말에 바로 답하고, 군더더기 없는 1~3문장으로 답해라. 정확한 시간, 설정 확인, 계산이 필요하면 도구를 우선 사용해라. 최신 정보, 오늘/최근 정보, 뉴스, 검색 요청, 사실 확인, 외부 웹페이지 내용이 필요한 경우에만 web_search 와 fetch_url 을 사용해라. 내부 지식만으로 충분한 일반 대화에는 웹 도구를 쓰지 마라. 너는 도구 호출 루프 안에 있으며 필요하면 여러 번 도구를 호출할 수 있다.";
"너는 한국어로 짧고 자연스럽게 답하는 로컬 음성 비서다. 사용자의 말에 바로 답하고, 군더더기 없는 1~3문장으로 답해라. 반드시 한국어로만 답하고, 한자, 중국어, 일본어, 아랍어, 키릴 문자, 기타 외국 문자, 이모지는 쓰지 마라. 영어 단어도 꼭 필요한 기술명 외에는 피하고 자연스러운 한국어 표현으로 바꿔라. 정확한 시간, 설정 확인, 계산이 필요하면 도구를 우선 사용해라. 최신 정보, 오늘/최근 정보, 뉴스, 검색 요청, 사실 확인, 외부 웹페이지 내용이 필요한 경우에만 web_search 와 fetch_url 을 사용해라. 내부 지식만으로 충분한 일반 대화에는 웹 도구를 쓰지 마라. 너는 도구 호출 루프 안에 있으며 필요하면 여러 번 도구를 호출할 수 있다.";
const TOOL_DEFINITIONS: OllamaToolDefinition[] = [
{
@@ -201,7 +201,8 @@ export class OllamaLlmService {
{ role: "user", content: userText },
];
const reply = await this.runAgentLoop(messages, options);
const rawReply = await this.runAgentLoop(messages, options);
const reply = await this.repairReplyLanguageIfNeeded(rawReply, userText);
this.history.push({ role: "user", content: userText });
this.history.push({ role: "assistant", content: reply });
@@ -416,6 +417,73 @@ export class OllamaLlmService {
return fallback;
}
private async repairReplyLanguageIfNeeded(reply: string, userText: string): Promise<string> {
if (!this.needsLanguageRepair(reply)) {
return reply;
}
this.logger.warn("Reply language repair triggered", {
reply,
analysis: this.analyzeScriptUsage(reply),
});
const repaired = await this.chat(
[
{
role: "system",
content:
"다음 답변을 의미를 유지한 채 자연스러운 한국어로만 다시 써라. 한글, 숫자, 기본 문장부호 외 다른 문자와 이모지는 쓰지 마라. 설명하지 말고 최종 답변 문장만 출력해라.",
},
{
role: "user",
content: `원문 질문: ${userText}\n기존 답변: ${reply}`,
},
],
{ enableTools: false },
);
const normalized = repaired.content.trim();
if (!normalized) {
return reply;
}
return normalized;
}
private needsLanguageRepair(text: string): boolean {
const analysis = this.analyzeScriptUsage(text);
if (analysis.otherLetters > 0) {
return true;
}
if (analysis.hangul === 0 && analysis.latin > 0) {
return true;
}
return false;
}
private analyzeScriptUsage(text: string): { hangul: number; latin: number; otherLetters: number } {
let hangul = 0;
let latin = 0;
let otherLetters = 0;
for (const char of text) {
if (!/\p{Letter}/u.test(char)) {
continue;
}
if (/\p{Script=Hangul}/u.test(char)) {
hangul += 1;
continue;
}
if (/\p{Script=Latin}/u.test(char)) {
latin += 1;
continue;
}
otherLetters += 1;
}
return { hangul, latin, otherLetters };
}
private getProgressMessage(toolName: string): string | null {
switch (toolName) {
case "web_search":