feat(tag-vocab): InferenceProvider.vocab + LocalOllamaProvider 전달 (#3 v0.2.3)

- GenerateInput.vocab?: string[] (optional, 미전달 시 빈 배열 처리)
- LocalOllamaProvider.generate 가 input.vocab ?? [] 를 buildPrompt 4th 인자로
- 단위 +1 case (vocab → prompt body)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
altair823
2026-05-02 12:21:24 +09:00
parent 896b374f56
commit daa8507364
3 changed files with 21 additions and 1 deletions

View File

@@ -5,6 +5,7 @@ export interface GenerateInput {
text: string;
todayKst: string; // ISO YYYY-MM-DD in KST
dueDateCandidates: ParseResult[];
vocab?: string[]; // v0.2.3 #3 — top-N kebab-case 태그. 미전달 시 빈 배열로 처리.
}
export interface HealthResult { ok: boolean; model?: string; reason?: string; }

View File

@@ -37,7 +37,7 @@ export class LocalOllamaProvider implements InferenceProvider {
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
model: this.model,
prompt: buildPrompt(input.text, input.todayKst, input.dueDateCandidates),
prompt: buildPrompt(input.text, input.todayKst, input.dueDateCandidates, input.vocab ?? []),
format: 'json',
stream: false,
options: { temperature: this.temperature, num_predict: this.numPredict }

View File

@@ -26,6 +26,25 @@ describe('LocalOllamaProvider', () => {
expect(r.title).toBe('회의');
});
it('generate passes vocab into prompt body', async () => {
let capturedBody: string = '';
mock.get('http://localhost:11434').intercept({
path: '/api/generate', method: 'POST'
}).reply((opts) => {
capturedBody = opts.body as string;
return { statusCode: 200, data: JSON.stringify({
response: JSON.stringify({ title: '회의', summary: 'a\nb\nc', tags: ['design'] })
}) };
});
await new LocalOllamaProvider().generate({
text: 'x', todayKst: '2026-05-02', dueDateCandidates: [],
vocab: ['design', 'meeting']
});
const parsed = JSON.parse(capturedBody) as { prompt: string };
expect(parsed.prompt).toContain('design, meeting');
expect(parsed.prompt).toContain('Prefer reusing');
});
it('generate throws on non-JSON', async () => {
mock.get('http://localhost:11434').intercept({ path: '/api/generate', method: 'POST' }).reply(200, {
response: 'not json'