This commit is contained in:
lila 2026-07-06 14:41:30 +02:00
parent 2a6c56ed23
commit 1c4dcdd108
4 changed files with 25 additions and 28 deletions

View file

@ -12,3 +12,5 @@ export const POS_MAP: Record<string, string> = {
adverbs: "adverb", adverbs: "adverb",
adjectives: "adjective", adjectives: "adjective",
}; };
export const ALL_LANGUAGES = ["en", "de", "it", "es", "fr"];

View file

@ -1,6 +1,11 @@
export const ENRICHMENT_SYSTEM_PROMPT = `You are a multilingual dictionary engine. Output ONLY a JSON object. No markdown, no explanations. export function buildSystemPrompt(
sourceLanguage: string,
pos: string,
targetLanguages: string[],
): string {
return `You are a multilingual dictionary engine. Output ONLY a JSON object. No markdown, no explanations.
For each English noun provided, generate 1-2 distinct senses. For each ${sourceLanguage} ${pos} provided, generate 1-2 distinct senses.
CEFR difficulty mapping: CEFR difficulty mapping:
- A1/A2 easy - A1/A2 easy
@ -11,7 +16,7 @@ Each sense must have:
- sense: student-friendly definition, max 15 words - sense: student-friendly definition, max 15 words
- example: natural sentence using the word - example: natural sentence using the word
- difficulty_level: easy, medium, or hard - difficulty_level: easy, medium, or hard
- translations: object with keys de, it, es, fr; each value is an array of {word, gender} where gender MUST be masculine, feminine, or neuter. Use null ONLY if the language has no grammatical gender for that word. - translations: object with keys ${targetLanguages.join(", ")}; each value is an array of {word, gender} where gender MUST be masculine, feminine, or neuter. Use null ONLY if the language has no grammatical gender for that word.
Output format: JSON object where keys are the input words, values are arrays of sense objects. Output format: JSON object where keys are the input words, values are arrays of sense objects.
@ -32,3 +37,4 @@ Example for ["house"]:
] ]
} }
`; `;
}

View file

@ -1,22 +1,8 @@
import { ENRICHMENT_SYSTEM_PROMPT } from "../config/prompt.js"; import { buildSystemPrompt } from "../config/prompt.js";
import { createAdapter } from "./llm-adapters/factory.js"; import { createAdapter } from "./llm-adapters/factory.js";
import { BATCH_CONFIG } from "../config/batch.js"; import { BATCH_CONFIG } from "../config/batch.js";
import type { Language, Pos, EnrichedSense } from "./merge-enriched-data.js"; import type { Language, Pos, EnrichedSense } from "./merge-enriched-data.js";
import { LANG_MAP, POS_MAP, ALL_LANGUAGES } from "../config/constants.js";
const LANG_MAP: Record<string, string> = {
english: "en",
italian: "it",
german: "de",
french: "fr",
spanish: "es",
};
const POS_MAP: Record<string, string> = {
nouns: "noun",
verbs: "verb",
adverbs: "adverb",
adjectives: "adjective",
};
interface LlmResponse { interface LlmResponse {
content: string; content: string;
@ -42,9 +28,16 @@ export interface EnrichmentResult {
* Calls the LLM with the enrichment prompt. * Calls the LLM with the enrichment prompt.
* Returns the response content and timing metrics. * Returns the response content and timing metrics.
*/ */
async function callLlm(words: string[]): Promise<LlmResponse> { async function callLlm(
words: string[],
rawLanguage: string,
rawPos: string,
): Promise<LlmResponse> {
const adapter = createAdapter(); const adapter = createAdapter();
return adapter.call(words, ENRICHMENT_SYSTEM_PROMPT); const sourceCode = LANG_MAP[rawLanguage] || rawLanguage;
const targetLanguages = ALL_LANGUAGES.filter((lang) => lang !== sourceCode);
const prompt = buildSystemPrompt(rawLanguage, rawPos, targetLanguages);
return adapter.call(words, prompt);
} }
/** /**
@ -140,7 +133,7 @@ export async function enrichWord(
rawLanguage: string, rawLanguage: string,
rawPos: string, rawPos: string,
): Promise<EnrichmentResult> { ): Promise<EnrichmentResult> {
const llmResponse = await callLlm(words); const llmResponse = await callLlm(words, rawLanguage, rawPos);
const parsed = parseLlmResponse(llmResponse.content, words); const parsed = parseLlmResponse(llmResponse.content, words);
const results = buildEnrichedData(parsed, rawLanguage, rawPos); const results = buildEnrichedData(parsed, rawLanguage, rawPos);

View file

@ -32,13 +32,9 @@ export class GeminiAdapter implements LlmAdapter {
const url = `https://generativelanguage.googleapis.com/v1beta/models/${this.model}:generateContent?key=${this.apiKey}`; const url = `https://generativelanguage.googleapis.com/v1beta/models/${this.model}:generateContent?key=${this.apiKey}`;
const payload = { const payload = {
systemInstruction: { parts: [{ text: systemPrompt }] },
contents: [ contents: [
{ { role: "user", parts: [{ text: "Words: " + JSON.stringify(words) }] },
role: "user",
parts: [
{ text: systemPrompt + "\n\nWords: " + JSON.stringify(words) },
],
},
], ],
generationConfig: { generationConfig: {
temperature: 0.1, temperature: 0.1,