Repair non-Korean reply output
This commit is contained in:
@@ -127,6 +127,7 @@ bun run test:llm
|
|||||||
- 최신 정보, 뉴스, 사실 확인, 검색 요청일 때만 웹 도구 사용
|
- 최신 정보, 뉴스, 사실 확인, 검색 요청일 때만 웹 도구 사용
|
||||||
- `test:sttllm` 에서는 먼저 "대답할 가치가 있는 텍스트인지" 판정한 뒤 필요할 때만 답변
|
- `test:sttllm` 에서는 먼저 "대답할 가치가 있는 텍스트인지" 판정한 뒤 필요할 때만 답변
|
||||||
- 웹 검색이 실제로 시작되면 결과 전에 `검색해볼게요.` 같은 진행 메시지를 먼저 출력
|
- 웹 검색이 실제로 시작되면 결과 전에 `검색해볼게요.` 같은 진행 메시지를 먼저 출력
|
||||||
|
- 답변에 한글 외 다른 문자군이 섞이면 한국어만으로 한 번 더 교정
|
||||||
|
|
||||||
## Windows용 .env 예시
|
## Windows용 .env 예시
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export interface ReplyAssessment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SYSTEM_PROMPT =
|
const SYSTEM_PROMPT =
|
||||||
"너는 한국어로 짧고 자연스럽게 답하는 로컬 음성 비서다. 사용자의 말에 바로 답하고, 군더더기 없는 1~3문장으로 답해라. 정확한 시간, 설정 확인, 계산이 필요하면 도구를 우선 사용해라. 최신 정보, 오늘/최근 정보, 뉴스, 검색 요청, 사실 확인, 외부 웹페이지 내용이 필요한 경우에만 web_search 와 fetch_url 을 사용해라. 내부 지식만으로 충분한 일반 대화에는 웹 도구를 쓰지 마라. 너는 도구 호출 루프 안에 있으며 필요하면 여러 번 도구를 호출할 수 있다.";
|
"너는 한국어로 짧고 자연스럽게 답하는 로컬 음성 비서다. 사용자의 말에 바로 답하고, 군더더기 없는 1~3문장으로 답해라. 반드시 한국어로만 답하고, 한자, 중국어, 일본어, 아랍어, 키릴 문자, 기타 외국 문자, 이모지는 쓰지 마라. 영어 단어도 꼭 필요한 기술명 외에는 피하고 자연스러운 한국어 표현으로 바꿔라. 정확한 시간, 설정 확인, 계산이 필요하면 도구를 우선 사용해라. 최신 정보, 오늘/최근 정보, 뉴스, 검색 요청, 사실 확인, 외부 웹페이지 내용이 필요한 경우에만 web_search 와 fetch_url 을 사용해라. 내부 지식만으로 충분한 일반 대화에는 웹 도구를 쓰지 마라. 너는 도구 호출 루프 안에 있으며 필요하면 여러 번 도구를 호출할 수 있다.";
|
||||||
|
|
||||||
const TOOL_DEFINITIONS: OllamaToolDefinition[] = [
|
const TOOL_DEFINITIONS: OllamaToolDefinition[] = [
|
||||||
{
|
{
|
||||||
@@ -201,7 +201,8 @@ export class OllamaLlmService {
|
|||||||
{ role: "user", content: userText },
|
{ 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: "user", content: userText });
|
||||||
this.history.push({ role: "assistant", content: reply });
|
this.history.push({ role: "assistant", content: reply });
|
||||||
@@ -416,6 +417,73 @@ export class OllamaLlmService {
|
|||||||
return fallback;
|
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 {
|
private getProgressMessage(toolName: string): string | null {
|
||||||
switch (toolName) {
|
switch (toolName) {
|
||||||
case "web_search":
|
case "web_search":
|
||||||
|
|||||||
Reference in New Issue
Block a user