Load LLM prompts from markdown files

This commit is contained in:
2026-05-03 01:24:56 +09:00
parent 28ffbf02e1
commit 3360015179
6 changed files with 66 additions and 10 deletions

20
src/prompt-loader.ts Normal file
View File

@@ -0,0 +1,20 @@
import { readFileSync } from "node:fs";
import path from "node:path";
const cache = new Map<string, string>();
export function loadPrompt(name: string): string {
const cached = cache.get(name);
if (cached) {
return cached;
}
const promptPath = path.resolve(process.cwd(), "prompts", name);
const content = readFileSync(promptPath, "utf8").trim();
if (!content) {
throw new Error(`프롬프트 파일이 비어 있습니다: ${promptPath}`);
}
cache.set(name, content);
return content;
}

View File

@@ -1,5 +1,6 @@
import type { AppConfig } from "../config.js";
import type { Logger } from "../logger.js";
import { loadPrompt } from "../prompt-loader.js";
import { webFetch, webSearch } from "./web-tools.js";
interface OllamaChatMessage {
@@ -52,8 +53,9 @@ export interface ReplyAssessment {
reason: string;
}
const SYSTEM_PROMPT =
"너는 한국어로 짧고 자연스럽게 답하는 로컬 음성 비서다. 사용자의 말에 바로 답하고, 군더더기 없는 1~3문장으로 답해라. 반드시 한국어로만 답하고, 한자, 중국어, 일본어, 아랍어, 키릴 문자, 기타 외국 문자, 이모지는 쓰지 마라. 영어 단어도 꼭 필요한 기술명 외에는 피하고 자연스러운 한국어 표현으로 바꿔라. 정확한 시간, 설정 확인, 계산이 필요하면 도구를 우선 사용해라. 최신 정보, 오늘/최근 정보, 뉴스, 검색 요청, 사실 확인, 외부 웹페이지 내용이 필요한 경우에만 web_search 와 fetch_url 을 사용해라. 내부 지식만으로 충분한 일반 대화에는 웹 도구를 쓰지 마라. 너는 도구 호출 루프 안에 있으며 필요하면 여러 번 도구를 호출할 수 있다.";
const ASSISTANT_PROMPT = loadPrompt("assistant.md");
const REPLY_GATE_PROMPT = loadPrompt("reply-gate.md");
const REWRITE_KOREAN_PROMPT = loadPrompt("rewrite-korean.md");
const TOOL_DEFINITIONS: OllamaToolDefinition[] = [
{
@@ -161,7 +163,7 @@ export class OllamaLlmService {
async warmup(): Promise<void> {
const reply = await this.chat(
[
{ role: "system", content: SYSTEM_PROMPT },
{ role: "system", content: ASSISTANT_PROMPT },
{ role: "user", content: "준비 상태 확인입니다. 한 단어로만 답하세요." },
],
);
@@ -174,11 +176,8 @@ export class OllamaLlmService {
return heuristic;
}
const prompt =
'다음 텍스트에 로컬 비서가 실제로 대답해야 하는지 판정해라. 의미 없는 감탄사, 중얼거림, 문맥 없는 짧은 파편, 노래 가사 조각, 잡음성 문장은 false. 질문, 요청, 확인, 명령, 대화 시도는 true. 최신 정보나 사실 확인이 필요하면 likely_needs_lookup 를 true 로 해라. JSON만 출력: {"should_reply":true,"likely_needs_lookup":false,"reason":"짧게"}';
const reply = await this.chat([
{ role: "system", content: prompt },
{ role: "system", content: REPLY_GATE_PROMPT },
{ role: "user", content: userText },
], { enableTools: false });
@@ -196,7 +195,7 @@ export class OllamaLlmService {
async generateReply(userText: string, options?: GenerateReplyOptions): Promise<string> {
const messages: Array<OllamaChatMessage | OllamaToolResultMessage> = [
{ role: "system", content: SYSTEM_PROMPT },
{ role: "system", content: ASSISTANT_PROMPT },
...this.history,
{ role: "user", content: userText },
];
@@ -431,8 +430,7 @@ export class OllamaLlmService {
[
{
role: "system",
content:
"다음 답변을 의미를 유지한 채 자연스러운 한국어로만 다시 써라. 한글, 숫자, 기본 문장부호 외 다른 문자와 이모지는 쓰지 마라. 설명하지 말고 최종 답변 문장만 출력해라.",
content: REWRITE_KOREAN_PROMPT,
},
{
role: "user",