strapi-llm-translator 0.9.6 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/server/index.js +54 -43
- package/dist/server/index.mjs +53 -42
- package/dist/server/src/config/constants.d.ts +3 -0
- package/dist/server/src/config/index.d.ts +7 -5
- package/dist/server/src/controllers/admin.controller.d.ts +1 -1
- package/dist/server/src/index.d.ts +7 -5
- package/dist/server/src/types/controllers.d.ts +1 -1
- package/dist/server/src/types/index.d.ts +5 -0
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ The Strapi LLM Translator plugin enhances your localization workflow by utilisin
|
|
|
7
7
|
## 🚀 Key Features
|
|
8
8
|
|
|
9
9
|
- 🌍 **Multi-field Support** - Translates all text-based fields (string, text, richtext) and JSON/Blocks content, including Strapi 5 structured rich text
|
|
10
|
-
- 🔌 **LLM Agnostic** - Works with any OpenAI-compatible API (your choice of provider)
|
|
10
|
+
- 🔌 **LLM Agnostic** - Works with any OpenAI-compatible API (your choice of provider or local)
|
|
11
11
|
- 📝 **Format Preservation** - Maintains markdown formatting during translation
|
|
12
12
|
- 🔗 **Smart UUID Handling** - Auto-translates slugs when i18n is enabled with relative fields
|
|
13
13
|
- ⚡ **Auto-fill** - Instantly populates generated translations
|
|
@@ -21,17 +21,18 @@ The Strapi LLM Translator plugin enhances your localization workflow by utilisin
|
|
|
21
21
|
|
|
22
22
|
## ✅ Tested With
|
|
23
23
|
|
|
24
|
-
- **Strapi**: v5.12.x
|
|
24
|
+
- **Strapi**: v5.12.x, v5.15.x
|
|
25
25
|
- **LLM Providers**:
|
|
26
26
|
- OpenAI: `gpt-4o`
|
|
27
27
|
- Groq: `meta-llama/llama-4-scout-17b-16e-instruct`
|
|
28
|
+
- Local: `Ollama`, e.g. `phi4-mini`
|
|
28
29
|
|
|
29
30
|
## 🛠️ Installation & Setup
|
|
30
31
|
|
|
31
32
|
### Prerequisites
|
|
32
33
|
|
|
33
34
|
- Strapi project (v5+)
|
|
34
|
-
- API key for your preferred LLM provider,
|
|
35
|
+
- API key for your preferred LLM provider, Base Url + Model Name
|
|
35
36
|
- Configured internationalization with at least two languages in your Strapi application
|
|
36
37
|
|
|
37
38
|
### Installation
|
|
@@ -45,7 +46,7 @@ npm install strapi-llm-translator
|
|
|
45
46
|
2. Configure environment variables:
|
|
46
47
|
|
|
47
48
|
```
|
|
48
|
-
#
|
|
49
|
+
# Optional - Your LLM provider API key (Can be left empty if there is no API Key needed)
|
|
49
50
|
LLM_TRANSLATOR_LLM_API_KEY=
|
|
50
51
|
|
|
51
52
|
# Optional - Defaults to OpenAI's endpoint
|
package/dist/server/index.js
CHANGED
|
@@ -1,42 +1,47 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const openai
|
|
2
|
+
const openai = require("openai");
|
|
3
3
|
const bootstrap = ({ strapi: strapi2 }) => {
|
|
4
4
|
};
|
|
5
5
|
const destroy = ({ strapi: strapi2 }) => {
|
|
6
6
|
};
|
|
7
7
|
const register = ({ strapi: strapi2 }) => {
|
|
8
8
|
};
|
|
9
|
+
const DEFAULT_SYSTEM_PROMPT = "You are a professional translator. Your task is to translate the provided content accurately while preserving the original meaning and tone.";
|
|
10
|
+
const SYSTEM_PROMPT_APPENDIX = `The user asks you to translate the text to a specific language, the language is provided via short code like "en", "fr", "de", etc.`;
|
|
11
|
+
const DEFAULT_LLM_TEMPERATURE = 0.3;
|
|
12
|
+
const DEFAULT_LLM_MODEL = "gpt-4o";
|
|
13
|
+
const DEFAULT_LLM_BASE_URL = "https://api.openai.com/v1";
|
|
14
|
+
const SYSTEM_PROMPT_FIX = `You are a JSON correction assistant. Only return valid, corrected JSON.`;
|
|
15
|
+
const USER_PROMPT_FIX_PREFIX = "Fix this invalid JSON and return ONLY the corrected JSON. No explanations allowed. The JSON is:";
|
|
9
16
|
const config = {
|
|
10
|
-
default: {
|
|
11
|
-
llmApiKey:
|
|
12
|
-
llmEndpoint:
|
|
13
|
-
llmModel:
|
|
14
|
-
},
|
|
15
|
-
validator() {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
default: ({ env }) => ({
|
|
18
|
+
llmApiKey: env("LLM_TRANSLATOR_LLM_API_KEY"),
|
|
19
|
+
llmEndpoint: env("STRAPI_ADMIN_LLM_TRANSLATOR_LLM_BASE_URL"),
|
|
20
|
+
llmModel: env("STRAPI_ADMIN_LLM_TRANSLATOR_LLM_MODEL")
|
|
21
|
+
}),
|
|
22
|
+
validator(config2) {
|
|
23
|
+
const PLUGIN_NAME = "Strapi LLM Translator";
|
|
24
|
+
console.info(`
|
|
25
|
+
==== ${PLUGIN_NAME} Configuration Validation ====`);
|
|
26
|
+
if (!config2?.llmApiKey) {
|
|
27
|
+
console.warn("⚠️ LLM API Key: Missing");
|
|
28
|
+
console.info(" → Translation features requiring API keys will be disabled");
|
|
29
|
+
} else {
|
|
30
|
+
console.info("✅ LLM API Key: Configured");
|
|
23
31
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
);
|
|
32
|
+
const endpoint = config2?.llmEndpoint || DEFAULT_LLM_BASE_URL;
|
|
33
|
+
if (!config2?.llmEndpoint) {
|
|
34
|
+
console.warn(`⚠️ API Endpoint: Using default (${DEFAULT_LLM_BASE_URL})`);
|
|
28
35
|
} else {
|
|
29
|
-
console.info(
|
|
30
|
-
`STRAPI_ADMIN_LLM_TRANSLATOR_LLM_BASE_URL is set to: ${STRAPI_ADMIN_LLM_TRANSLATOR_LLM_BASE_URL}`
|
|
31
|
-
);
|
|
36
|
+
console.info(`✅ API Endpoint: Configured (${endpoint})`);
|
|
32
37
|
}
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
const model = config2?.llmModel || DEFAULT_LLM_MODEL;
|
|
39
|
+
if (!config2?.llmModel) {
|
|
40
|
+
console.warn(`⚠️ LLM Model: Using default (${DEFAULT_LLM_MODEL})`);
|
|
35
41
|
} else {
|
|
36
|
-
console.info(
|
|
37
|
-
`STRAPI_ADMIN_LLM_TRANSLATOR_LLM_MODEL is set to: ${STRAPI_ADMIN_LLM_TRANSLATOR_LLM_MODEL}`
|
|
38
|
-
);
|
|
42
|
+
console.info(`✅ LLM Model: Configured (${model})`);
|
|
39
43
|
}
|
|
44
|
+
console.info("========================================================\n");
|
|
40
45
|
}
|
|
41
46
|
};
|
|
42
47
|
const contentTypes = {};
|
|
@@ -126,10 +131,6 @@ const routes = {
|
|
|
126
131
|
routes: adminRoutes
|
|
127
132
|
}
|
|
128
133
|
};
|
|
129
|
-
const DEFAULT_SYSTEM_PROMPT = "You are a professional translator. Your task is to translate the provided content accurately while preserving the original meaning and tone.";
|
|
130
|
-
const SYSTEM_PROMPT_APPENDIX = `The user asks you to translate the text to a specific language, the language is provided via short code like "en", "fr", "de", etc.`;
|
|
131
|
-
const SYSTEM_PROMPT_FIX = `You are a JSON correction assistant. Only return valid, corrected JSON.`;
|
|
132
|
-
const USER_PROMPT_FIX_PREFIX = "Fix this invalid JSON and return ONLY the corrected JSON. No explanations allowed. The JSON is:";
|
|
133
134
|
const cleanJSONString = (content) => {
|
|
134
135
|
return content.replace(/^```json\s*\n/, "").replace(/^```\s*\n/, "").replace(/\n\s*```$/, "").replace(/\u200B/g, "").replace(/[\u2018\u2019]/g, "'").replace(/[\u201C\u201D]/g, '"').trim();
|
|
135
136
|
};
|
|
@@ -167,11 +168,11 @@ const safeJSONParse = (content) => {
|
|
|
167
168
|
}
|
|
168
169
|
throw new Error("Invalid response format - not an object");
|
|
169
170
|
};
|
|
170
|
-
const
|
|
171
|
-
baseURL: process.env.STRAPI_ADMIN_LLM_TRANSLATOR_LLM_BASE_URL,
|
|
172
|
-
apiKey: process.env.LLM_TRANSLATOR_LLM_API_KEY
|
|
171
|
+
const llmClient = new openai.OpenAI({
|
|
172
|
+
baseURL: process.env.STRAPI_ADMIN_LLM_TRANSLATOR_LLM_BASE_URL ?? DEFAULT_LLM_BASE_URL,
|
|
173
|
+
apiKey: process.env.LLM_TRANSLATOR_LLM_API_KEY ?? "not_set"
|
|
173
174
|
});
|
|
174
|
-
const
|
|
175
|
+
const LLM_MODEL = process.env.STRAPI_ADMIN_LLM_TRANSLATOR_LLM_MODEL ?? DEFAULT_LLM_MODEL;
|
|
175
176
|
const extractTranslatableFields = (contentType, fields, components = {}) => {
|
|
176
177
|
const translatableFields = [];
|
|
177
178
|
const isTranslatableFieldSchema = (schema, value) => {
|
|
@@ -206,7 +207,12 @@ const extractTranslatableFields = (contentType, fields, components = {}) => {
|
|
|
206
207
|
if (!componentSchema) return;
|
|
207
208
|
if (fieldSchema.repeatable && Array.isArray(value)) {
|
|
208
209
|
value.forEach(
|
|
209
|
-
(item, index2) => traverse(
|
|
210
|
+
(item, index2) => traverse(
|
|
211
|
+
componentSchema,
|
|
212
|
+
item,
|
|
213
|
+
[...path, fieldName, String(index2)],
|
|
214
|
+
[...originalPath, fieldName, String(index2)]
|
|
215
|
+
)
|
|
210
216
|
);
|
|
211
217
|
} else if (typeof value === "object") {
|
|
212
218
|
traverse(componentSchema, value, [...path, fieldName], [...originalPath, fieldName]);
|
|
@@ -215,7 +221,12 @@ const extractTranslatableFields = (contentType, fields, components = {}) => {
|
|
|
215
221
|
value.forEach((item, index2) => {
|
|
216
222
|
const compSchema = components[item.__component];
|
|
217
223
|
if (compSchema) {
|
|
218
|
-
traverse(
|
|
224
|
+
traverse(
|
|
225
|
+
compSchema,
|
|
226
|
+
item,
|
|
227
|
+
[...path, fieldName, String(index2)],
|
|
228
|
+
[...originalPath, fieldName, String(index2)]
|
|
229
|
+
);
|
|
219
230
|
}
|
|
220
231
|
});
|
|
221
232
|
}
|
|
@@ -310,7 +321,7 @@ const llmService = ({ strapi: strapi2 }) => ({
|
|
|
310
321
|
const translationPayload = prepareTranslationPayload(translatableFields);
|
|
311
322
|
const prompt = buildPrompt(translationPayload, config2.targetLanguage);
|
|
312
323
|
const systemPrompt = await buildSystemPrompt(userConfig);
|
|
313
|
-
const response = await callLLMProvider(prompt, systemPrompt,
|
|
324
|
+
const response = await callLLMProvider(prompt, systemPrompt, userConfig);
|
|
314
325
|
const translatedData = await parseLLMResponse(response);
|
|
315
326
|
const mergedContent = mergeTranslatedContent(fields, translatedData, translatableFields);
|
|
316
327
|
const uidFields = findUIDFields(contentType);
|
|
@@ -371,18 +382,18 @@ const getUserConfig = async () => {
|
|
|
371
382
|
const config2 = await pluginStore.get({ key: "configuration" });
|
|
372
383
|
return config2;
|
|
373
384
|
};
|
|
374
|
-
const buildSystemPrompt = async (
|
|
375
|
-
return `${
|
|
385
|
+
const buildSystemPrompt = async (userConfig) => {
|
|
386
|
+
return `${userConfig?.systemPrompt || DEFAULT_SYSTEM_PROMPT} ${SYSTEM_PROMPT_APPENDIX}`;
|
|
376
387
|
};
|
|
377
388
|
const createLLMRequest = (messages, temperature = 0.1) => {
|
|
378
|
-
return
|
|
379
|
-
model,
|
|
389
|
+
return llmClient.chat.completions.create({
|
|
390
|
+
model: LLM_MODEL,
|
|
380
391
|
messages,
|
|
381
392
|
temperature,
|
|
382
393
|
response_format: { type: "json_object" }
|
|
383
394
|
});
|
|
384
395
|
};
|
|
385
|
-
const callLLMProvider = async (prompt, systemPrompt,
|
|
396
|
+
const callLLMProvider = async (prompt, systemPrompt, userConfig) => {
|
|
386
397
|
return createLLMRequest(
|
|
387
398
|
[
|
|
388
399
|
{
|
|
@@ -394,7 +405,7 @@ const callLLMProvider = async (prompt, systemPrompt, model2, config2) => {
|
|
|
394
405
|
content: prompt
|
|
395
406
|
}
|
|
396
407
|
],
|
|
397
|
-
|
|
408
|
+
userConfig?.temperature ?? DEFAULT_LLM_TEMPERATURE
|
|
398
409
|
);
|
|
399
410
|
};
|
|
400
411
|
const requestJSONCorrection = async (invalidJson) => {
|
package/dist/server/index.mjs
CHANGED
|
@@ -5,37 +5,42 @@ const destroy = ({ strapi: strapi2 }) => {
|
|
|
5
5
|
};
|
|
6
6
|
const register = ({ strapi: strapi2 }) => {
|
|
7
7
|
};
|
|
8
|
+
const DEFAULT_SYSTEM_PROMPT = "You are a professional translator. Your task is to translate the provided content accurately while preserving the original meaning and tone.";
|
|
9
|
+
const SYSTEM_PROMPT_APPENDIX = `The user asks you to translate the text to a specific language, the language is provided via short code like "en", "fr", "de", etc.`;
|
|
10
|
+
const DEFAULT_LLM_TEMPERATURE = 0.3;
|
|
11
|
+
const DEFAULT_LLM_MODEL = "gpt-4o";
|
|
12
|
+
const DEFAULT_LLM_BASE_URL = "https://api.openai.com/v1";
|
|
13
|
+
const SYSTEM_PROMPT_FIX = `You are a JSON correction assistant. Only return valid, corrected JSON.`;
|
|
14
|
+
const USER_PROMPT_FIX_PREFIX = "Fix this invalid JSON and return ONLY the corrected JSON. No explanations allowed. The JSON is:";
|
|
8
15
|
const config = {
|
|
9
|
-
default: {
|
|
10
|
-
llmApiKey:
|
|
11
|
-
llmEndpoint:
|
|
12
|
-
llmModel:
|
|
13
|
-
},
|
|
14
|
-
validator() {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
default: ({ env }) => ({
|
|
17
|
+
llmApiKey: env("LLM_TRANSLATOR_LLM_API_KEY"),
|
|
18
|
+
llmEndpoint: env("STRAPI_ADMIN_LLM_TRANSLATOR_LLM_BASE_URL"),
|
|
19
|
+
llmModel: env("STRAPI_ADMIN_LLM_TRANSLATOR_LLM_MODEL")
|
|
20
|
+
}),
|
|
21
|
+
validator(config2) {
|
|
22
|
+
const PLUGIN_NAME = "Strapi LLM Translator";
|
|
23
|
+
console.info(`
|
|
24
|
+
==== ${PLUGIN_NAME} Configuration Validation ====`);
|
|
25
|
+
if (!config2?.llmApiKey) {
|
|
26
|
+
console.warn("⚠️ LLM API Key: Missing");
|
|
27
|
+
console.info(" → Translation features requiring API keys will be disabled");
|
|
28
|
+
} else {
|
|
29
|
+
console.info("✅ LLM API Key: Configured");
|
|
22
30
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
);
|
|
31
|
+
const endpoint = config2?.llmEndpoint || DEFAULT_LLM_BASE_URL;
|
|
32
|
+
if (!config2?.llmEndpoint) {
|
|
33
|
+
console.warn(`⚠️ API Endpoint: Using default (${DEFAULT_LLM_BASE_URL})`);
|
|
27
34
|
} else {
|
|
28
|
-
console.info(
|
|
29
|
-
`STRAPI_ADMIN_LLM_TRANSLATOR_LLM_BASE_URL is set to: ${STRAPI_ADMIN_LLM_TRANSLATOR_LLM_BASE_URL}`
|
|
30
|
-
);
|
|
35
|
+
console.info(`✅ API Endpoint: Configured (${endpoint})`);
|
|
31
36
|
}
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
const model = config2?.llmModel || DEFAULT_LLM_MODEL;
|
|
38
|
+
if (!config2?.llmModel) {
|
|
39
|
+
console.warn(`⚠️ LLM Model: Using default (${DEFAULT_LLM_MODEL})`);
|
|
34
40
|
} else {
|
|
35
|
-
console.info(
|
|
36
|
-
`STRAPI_ADMIN_LLM_TRANSLATOR_LLM_MODEL is set to: ${STRAPI_ADMIN_LLM_TRANSLATOR_LLM_MODEL}`
|
|
37
|
-
);
|
|
41
|
+
console.info(`✅ LLM Model: Configured (${model})`);
|
|
38
42
|
}
|
|
43
|
+
console.info("========================================================\n");
|
|
39
44
|
}
|
|
40
45
|
};
|
|
41
46
|
const contentTypes = {};
|
|
@@ -125,10 +130,6 @@ const routes = {
|
|
|
125
130
|
routes: adminRoutes
|
|
126
131
|
}
|
|
127
132
|
};
|
|
128
|
-
const DEFAULT_SYSTEM_PROMPT = "You are a professional translator. Your task is to translate the provided content accurately while preserving the original meaning and tone.";
|
|
129
|
-
const SYSTEM_PROMPT_APPENDIX = `The user asks you to translate the text to a specific language, the language is provided via short code like "en", "fr", "de", etc.`;
|
|
130
|
-
const SYSTEM_PROMPT_FIX = `You are a JSON correction assistant. Only return valid, corrected JSON.`;
|
|
131
|
-
const USER_PROMPT_FIX_PREFIX = "Fix this invalid JSON and return ONLY the corrected JSON. No explanations allowed. The JSON is:";
|
|
132
133
|
const cleanJSONString = (content) => {
|
|
133
134
|
return content.replace(/^```json\s*\n/, "").replace(/^```\s*\n/, "").replace(/\n\s*```$/, "").replace(/\u200B/g, "").replace(/[\u2018\u2019]/g, "'").replace(/[\u201C\u201D]/g, '"').trim();
|
|
134
135
|
};
|
|
@@ -166,11 +167,11 @@ const safeJSONParse = (content) => {
|
|
|
166
167
|
}
|
|
167
168
|
throw new Error("Invalid response format - not an object");
|
|
168
169
|
};
|
|
169
|
-
const
|
|
170
|
-
baseURL: process.env.STRAPI_ADMIN_LLM_TRANSLATOR_LLM_BASE_URL,
|
|
171
|
-
apiKey: process.env.LLM_TRANSLATOR_LLM_API_KEY
|
|
170
|
+
const llmClient = new OpenAI({
|
|
171
|
+
baseURL: process.env.STRAPI_ADMIN_LLM_TRANSLATOR_LLM_BASE_URL ?? DEFAULT_LLM_BASE_URL,
|
|
172
|
+
apiKey: process.env.LLM_TRANSLATOR_LLM_API_KEY ?? "not_set"
|
|
172
173
|
});
|
|
173
|
-
const
|
|
174
|
+
const LLM_MODEL = process.env.STRAPI_ADMIN_LLM_TRANSLATOR_LLM_MODEL ?? DEFAULT_LLM_MODEL;
|
|
174
175
|
const extractTranslatableFields = (contentType, fields, components = {}) => {
|
|
175
176
|
const translatableFields = [];
|
|
176
177
|
const isTranslatableFieldSchema = (schema, value) => {
|
|
@@ -205,7 +206,12 @@ const extractTranslatableFields = (contentType, fields, components = {}) => {
|
|
|
205
206
|
if (!componentSchema) return;
|
|
206
207
|
if (fieldSchema.repeatable && Array.isArray(value)) {
|
|
207
208
|
value.forEach(
|
|
208
|
-
(item, index2) => traverse(
|
|
209
|
+
(item, index2) => traverse(
|
|
210
|
+
componentSchema,
|
|
211
|
+
item,
|
|
212
|
+
[...path, fieldName, String(index2)],
|
|
213
|
+
[...originalPath, fieldName, String(index2)]
|
|
214
|
+
)
|
|
209
215
|
);
|
|
210
216
|
} else if (typeof value === "object") {
|
|
211
217
|
traverse(componentSchema, value, [...path, fieldName], [...originalPath, fieldName]);
|
|
@@ -214,7 +220,12 @@ const extractTranslatableFields = (contentType, fields, components = {}) => {
|
|
|
214
220
|
value.forEach((item, index2) => {
|
|
215
221
|
const compSchema = components[item.__component];
|
|
216
222
|
if (compSchema) {
|
|
217
|
-
traverse(
|
|
223
|
+
traverse(
|
|
224
|
+
compSchema,
|
|
225
|
+
item,
|
|
226
|
+
[...path, fieldName, String(index2)],
|
|
227
|
+
[...originalPath, fieldName, String(index2)]
|
|
228
|
+
);
|
|
218
229
|
}
|
|
219
230
|
});
|
|
220
231
|
}
|
|
@@ -309,7 +320,7 @@ const llmService = ({ strapi: strapi2 }) => ({
|
|
|
309
320
|
const translationPayload = prepareTranslationPayload(translatableFields);
|
|
310
321
|
const prompt = buildPrompt(translationPayload, config2.targetLanguage);
|
|
311
322
|
const systemPrompt = await buildSystemPrompt(userConfig);
|
|
312
|
-
const response = await callLLMProvider(prompt, systemPrompt,
|
|
323
|
+
const response = await callLLMProvider(prompt, systemPrompt, userConfig);
|
|
313
324
|
const translatedData = await parseLLMResponse(response);
|
|
314
325
|
const mergedContent = mergeTranslatedContent(fields, translatedData, translatableFields);
|
|
315
326
|
const uidFields = findUIDFields(contentType);
|
|
@@ -370,18 +381,18 @@ const getUserConfig = async () => {
|
|
|
370
381
|
const config2 = await pluginStore.get({ key: "configuration" });
|
|
371
382
|
return config2;
|
|
372
383
|
};
|
|
373
|
-
const buildSystemPrompt = async (
|
|
374
|
-
return `${
|
|
384
|
+
const buildSystemPrompt = async (userConfig) => {
|
|
385
|
+
return `${userConfig?.systemPrompt || DEFAULT_SYSTEM_PROMPT} ${SYSTEM_PROMPT_APPENDIX}`;
|
|
375
386
|
};
|
|
376
387
|
const createLLMRequest = (messages, temperature = 0.1) => {
|
|
377
|
-
return
|
|
378
|
-
model,
|
|
388
|
+
return llmClient.chat.completions.create({
|
|
389
|
+
model: LLM_MODEL,
|
|
379
390
|
messages,
|
|
380
391
|
temperature,
|
|
381
392
|
response_format: { type: "json_object" }
|
|
382
393
|
});
|
|
383
394
|
};
|
|
384
|
-
const callLLMProvider = async (prompt, systemPrompt,
|
|
395
|
+
const callLLMProvider = async (prompt, systemPrompt, userConfig) => {
|
|
385
396
|
return createLLMRequest(
|
|
386
397
|
[
|
|
387
398
|
{
|
|
@@ -393,7 +404,7 @@ const callLLMProvider = async (prompt, systemPrompt, model2, config2) => {
|
|
|
393
404
|
content: prompt
|
|
394
405
|
}
|
|
395
406
|
],
|
|
396
|
-
|
|
407
|
+
userConfig?.temperature ?? DEFAULT_LLM_TEMPERATURE
|
|
397
408
|
);
|
|
398
409
|
};
|
|
399
410
|
const requestJSONCorrection = async (invalidJson) => {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export declare const DEFAULT_SYSTEM_PROMPT = "You are a professional translator. Your task is to translate the provided content accurately while preserving the original meaning and tone.";
|
|
2
2
|
export declare const SYSTEM_PROMPT_APPENDIX = "The user asks you to translate the text to a specific language, the language is provided via short code like \"en\", \"fr\", \"de\", etc.";
|
|
3
|
+
export declare const DEFAULT_LLM_TEMPERATURE = 0.3;
|
|
4
|
+
export declare const DEFAULT_LLM_MODEL = "gpt-4o";
|
|
5
|
+
export declare const DEFAULT_LLM_BASE_URL = "https://api.openai.com/v1";
|
|
3
6
|
export declare const SYSTEM_PROMPT_FIX = "You are a JSON correction assistant. Only return valid, corrected JSON.";
|
|
4
7
|
export declare const USER_PROMPT_FIX_PREFIX = "Fix this invalid JSON and return ONLY the corrected JSON. No explanations allowed. The JSON is:";
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
declare const _default: {
|
|
2
|
-
default: {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
default: ({ env }: {
|
|
3
|
+
env: any;
|
|
4
|
+
}) => {
|
|
5
|
+
llmApiKey: any;
|
|
6
|
+
llmEndpoint: any;
|
|
7
|
+
llmModel: any;
|
|
6
8
|
};
|
|
7
|
-
validator(): void;
|
|
9
|
+
validator(config: any): void;
|
|
8
10
|
};
|
|
9
11
|
export default _default;
|
|
@@ -10,12 +10,14 @@ declare const _default: {
|
|
|
10
10
|
strapi: import("@strapi/types/dist/core").Strapi;
|
|
11
11
|
}) => void;
|
|
12
12
|
config: {
|
|
13
|
-
default: {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
default: ({ env }: {
|
|
14
|
+
env: any;
|
|
15
|
+
}) => {
|
|
16
|
+
llmApiKey: any;
|
|
17
|
+
llmEndpoint: any;
|
|
18
|
+
llmModel: any;
|
|
17
19
|
};
|
|
18
|
-
validator(): void;
|
|
20
|
+
validator(config: any): void;
|
|
19
21
|
};
|
|
20
22
|
controllers: {
|
|
21
23
|
admin: ({ strapi }: import("./types").StrapiContext) => {
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.10.0",
|
|
3
3
|
"keywords": [
|
|
4
4
|
"strapi",
|
|
5
5
|
"plugin",
|
|
@@ -39,20 +39,20 @@
|
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@strapi/design-system": "^2.0.0-rc.21",
|
|
41
41
|
"@strapi/icons": "^2.0.0-rc.21",
|
|
42
|
-
"openai": "^
|
|
43
|
-
"react-intl": "^7.1.
|
|
42
|
+
"openai": "^5.3.0",
|
|
43
|
+
"react-intl": "^7.1.11"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@strapi/sdk-plugin": "^5.3.2",
|
|
47
|
-
"@strapi/strapi": "^5.
|
|
48
|
-
"@strapi/typescript-utils": "^5.
|
|
49
|
-
"@types/react": "^19.1.
|
|
50
|
-
"@types/react-dom": "^19.1.
|
|
47
|
+
"@strapi/strapi": "^5.15.1",
|
|
48
|
+
"@strapi/typescript-utils": "^5.15.1",
|
|
49
|
+
"@types/react": "^19.1.8",
|
|
50
|
+
"@types/react-dom": "^19.1.6",
|
|
51
51
|
"prettier": "^3.5.3",
|
|
52
|
-
"react": "^
|
|
53
|
-
"react-dom": "^
|
|
54
|
-
"react-router-dom": "^6.
|
|
55
|
-
"styled-components": "^6.1.
|
|
52
|
+
"react": "^19.1.0",
|
|
53
|
+
"react-dom": "^19.1.0",
|
|
54
|
+
"react-router-dom": "^7.6.2",
|
|
55
|
+
"styled-components": "^6.1.18",
|
|
56
56
|
"typescript": "^5.8.3"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|