feat(v031): buildVisionPrompt + GenerateInput.images + GenerateOptions.visionModel
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,13 +6,20 @@ export interface GenerateInput {
|
||||
todayKst: string; // ISO YYYY-MM-DD in KST
|
||||
dueDateCandidates: ParseResult[];
|
||||
vocab?: string[]; // v0.2.3 #3 — top-N kebab-case 태그. 미전달 시 빈 배열로 처리.
|
||||
// v0.3.1 Cut F — 첨부 이미지. 미전달 시 텍스트 전용 처리.
|
||||
images?: Array<{ base64: string; mime: string }>;
|
||||
}
|
||||
|
||||
export interface GenerateOptions {
|
||||
/** v0.3.1 Cut F — vision 전용 model 지정. null/미전달 시 기본 model 사용. */
|
||||
visionModel?: string | null;
|
||||
}
|
||||
|
||||
export interface HealthResult { ok: boolean; model?: string; reason?: string; }
|
||||
|
||||
export interface InferenceProvider {
|
||||
readonly name: string;
|
||||
generate(input: GenerateInput): Promise<AiResponse>;
|
||||
generate(input: GenerateInput, opts?: GenerateOptions): Promise<AiResponse>;
|
||||
healthCheck(): Promise<HealthResult>;
|
||||
/** v0.2.3.1 — 외부에서 in-flight generate 강제 중단. ProviderHolder.replace 시 사용. */
|
||||
abort?: () => void;
|
||||
|
||||
17
src/main/ai/visionPrompt.ts
Normal file
17
src/main/ai/visionPrompt.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export function buildVisionPrompt(
|
||||
text: string,
|
||||
todayKst: string,
|
||||
dueCandidates: string[],
|
||||
vocab: string[]
|
||||
): string {
|
||||
return `다음 메모와 첨부 이미지를 종합 분석해 한국어로 요약하세요.
|
||||
|
||||
메모 본문 (비어 있을 수 있음):
|
||||
${text || '(이미지만 있음)'}
|
||||
|
||||
이미지 분석 시 주요 시각적 정보 (텍스트, 사람, 장면) 도 포함해 요약하세요.
|
||||
출력 JSON: { "title": "...", "summary": "...", "tags": [...], "due_date": "..." }
|
||||
오늘: ${todayKst}
|
||||
가능한 due 후보: ${dueCandidates.join(', ')}
|
||||
빈출 태그: ${vocab.slice(0, 20).join(', ')}`;
|
||||
}
|
||||
23
tests/unit/visionPrompt.test.ts
Normal file
23
tests/unit/visionPrompt.test.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { buildVisionPrompt } from '@main/ai/visionPrompt.js';
|
||||
|
||||
describe('buildVisionPrompt', () => {
|
||||
it('includes text, todayKst, dueCandidates, and vocab slice when present', () => {
|
||||
const result = buildVisionPrompt(
|
||||
'회의 메모',
|
||||
'2026-05-09',
|
||||
['2026-05-10', '2026-05-15'],
|
||||
['work', 'meeting', 'project', 'todo']
|
||||
);
|
||||
expect(result).toContain('회의 메모');
|
||||
expect(result).toContain('2026-05-09');
|
||||
expect(result).toContain('2026-05-10, 2026-05-15');
|
||||
expect(result).toContain('work, meeting, project, todo');
|
||||
});
|
||||
|
||||
it('uses (이미지만 있음) placeholder when text is empty', () => {
|
||||
const result = buildVisionPrompt('', '2026-05-09', [], []);
|
||||
expect(result).toContain('(이미지만 있음)');
|
||||
expect(result).not.toContain('\n\n\n'); // no double-blank from empty text
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user