Skip to content

Commit a2e951a

Browse files
committed
feat: add TranslationJobViewComponent and integrate with background jobs for translation tasks
1 parent 27a4dd2 commit a2e951a

4 files changed

Lines changed: 82 additions & 29 deletions

File tree

custom/JobViewComponent.vue

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<template>
2+
<div class="flex flex-col w-full min-w-96">
3+
<p>{{ t('Total tokens will be used for translation:') }} <span class="font-bold"> {{ props.job.state?.totalTranslationTokenCost || 0 }}</span></p>
4+
<p>{{ t('Total translation token used:') }} <span class="font-bold"> {{ props.job.state?.totalUsedTokens || 0 }}</span></p>
5+
</div>
6+
</template>
7+
8+
9+
10+
<script setup lang="ts">
11+
import { useI18n } from 'vue-i18n'
12+
const { t } = useI18n();
13+
14+
const props = defineProps<{
15+
meta: any;
16+
getJobTasks: (limit?: number, offset?: number) => Promise<{state: Record<string, any>, status: string}[]>;
17+
job: {
18+
id: string;
19+
name: string;
20+
status: 'IN_PROGRESS' | 'DONE' | 'DONE_WITH_ERRORS' | 'CANCELLED';
21+
state: {
22+
totalTranslationTokenCost: number;
23+
totalUsedTokens: number;
24+
};
25+
progress: number; // 0 to 100
26+
createdAt: Date;
27+
customComponent?: AdminForthComponentDeclarationFull;
28+
};
29+
}>();
30+
31+
</script>

index.ts

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,14 @@ export default class I18nPlugin extends AdminForthPlugin {
174174
async modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
175175
super.modifyResourceConfig(adminforth, resourceConfig);
176176

177-
this.componentPath('JobViewComponent.vue')
177+
if (!this.adminforth.config.componentsToExplicitRegister) {
178+
this.adminforth.config.componentsToExplicitRegister = [];
179+
}
180+
this.adminforth.config.componentsToExplicitRegister.push(
181+
{
182+
file: this.componentPath('TranslationJobViewComponent.vue')
183+
}
184+
);
178185

179186
// validate each supported language: ISO 639-1 or BCP-47 with region (e.g., en-GB)
180187
this.options.supportedLanguages.forEach((lang) => {
@@ -513,6 +520,8 @@ export default class I18nPlugin extends AdminForthPlugin {
513520
lang: string,
514521
failedToTranslate: IFailedTranslation[],
515522
needToTranslateByLang: Record<string, any> = {},
523+
jobId: string,
524+
promptCost: number,
516525
): Promise<void>{
517526

518527
// return [];
@@ -563,6 +572,18 @@ export default class I18nPlugin extends AdminForthPlugin {
563572
return null;
564573
}
565574

575+
const backgroundJobsPlugin = this.adminforth.getPluginByClassName<any>('BackgroundJobsPlugin');
576+
577+
let totalUsedTokens = await backgroundJobsPlugin.getJobField(jobId, 'totalUsedTokens');
578+
console.log(`Prompt cost for ${lang} is ${promptCost}, total used tokens before adding this prompt cost: ${totalUsedTokens}`);
579+
580+
totalUsedTokens += promptCost || 0;
581+
console.log(`Total used tokens after adding prompt cost: ${totalUsedTokens}`);
582+
583+
await backgroundJobsPlugin.setJobField(jobId, 'totalUsedTokens', totalUsedTokens);
584+
585+
586+
566587
try {
567588
res = JSON.parse(res);
568589
} catch (e) {
@@ -732,7 +753,6 @@ export default class I18nPlugin extends AdminForthPlugin {
732753
stringBanch.map(s => `"${s}": ""`)
733754
}
734755
\`\`\``;
735-
// await new Promise(resolve => setTimeout(resolve, 1000));
736756
const stringBanchCopy = [...stringBanch];
737757
generationTasksInitialData.push(
738758
{
@@ -743,20 +763,13 @@ export default class I18nPlugin extends AdminForthPlugin {
743763
updateStrings,
744764
lang,
745765
failedToTranslate,
746-
needToTranslateByLang
766+
needToTranslateByLang,
767+
promptCost: basePromptTokenLength + banchTokens,
747768
}
748769
}
749770
)
750771
}
751772

752-
// const backgroundJobsPlugin = this.adminforth.getPluginByClassName<any>('BackgroundJobsPlugin');
753-
// backgroundJobsPlugin.startNewJob(
754-
// `Translate ${strings.length} items`, //job name
755-
// adminUser, // adminuser
756-
// generationTasksInitialData, //initial tasks
757-
// 'translation_job_handler', //job handler name
758-
// );
759-
760773
return generationTasksInitialData;
761774
}
762775

@@ -824,13 +837,18 @@ export default class I18nPlugin extends AdminForthPlugin {
824837
);
825838

826839

840+
const totalTranslationTokenCost = generationTasksInitialData.reduce((a, b) => a + (b.state?.promptCost || 0), 0);
827841
const backgroundJobsPlugin = this.adminforth.getPluginByClassName<any>('BackgroundJobsPlugin');
828-
backgroundJobsPlugin.startNewJob(
842+
const jobId = await backgroundJobsPlugin.startNewJob(
829843
`Translate ${selectedIds.length} items`, //job name
830844
adminUser, // adminuser
831845
generationTasksInitialData, //initial tasks
832846
'translation_job_handler', //job handler name
833847
);
848+
849+
afLogger.info(`Started background job with ID ${jobId} `);
850+
await backgroundJobsPlugin.setJobField(jobId, 'totalTranslationTokenCost', totalTranslationTokenCost);
851+
await backgroundJobsPlugin.setJobField(jobId, 'totalUsedTokens', 0);
834852
}
835853

836854

@@ -895,7 +913,7 @@ export default class I18nPlugin extends AdminForthPlugin {
895913
// job handler name
896914
jobHandlerName: 'translation_job_handler',
897915
//handler function
898-
handler: async ({ setTaskStateField, getTaskStateField }) => {
916+
handler: async ({ jobId, setTaskStateField, getTaskStateField }) => {
899917
const initialState: {
900918
prompt?: string,
901919
strings?: { en_string: string, category: string }[],
@@ -904,6 +922,7 @@ export default class I18nPlugin extends AdminForthPlugin {
904922
lang?: string,
905923
failedToTranslate?: IFailedTranslation[],
906924
needToTranslateByLang?: Record<string, any>,
925+
promptCost?: number,
907926
} = await getTaskStateField();
908927

909928
if ( initialState.prompt && initialState.strings && initialState.translations && initialState.updateStrings && initialState.lang && initialState.failedToTranslate && initialState.needToTranslateByLang) {
@@ -915,13 +934,14 @@ export default class I18nPlugin extends AdminForthPlugin {
915934
initialState.lang,
916935
initialState.failedToTranslate,
917936
initialState.needToTranslateByLang,
937+
jobId,
938+
initialState.promptCost
918939
);
919940
}
920-
921-
if (initialState.failedToTranslate) {
941+
afLogger.debug(`Translation task for language ${initialState.lang} completed.`);
942+
if (initialState.failedToTranslate.length > 0) {
922943
afLogger.error(`Failed to translate some strings for language ${initialState.lang} in plugin ${this.constructor.name}:, ${initialState.failedToTranslate}`);
923944
}
924-
925945
const stateToSave = {
926946
strings: initialState.strings,
927947
lang: initialState.lang,
@@ -931,7 +951,14 @@ export default class I18nPlugin extends AdminForthPlugin {
931951
await setTaskStateField(stateToSave);
932952
},
933953
//limit of tasks, that are running in parallel
934-
parallelLimit: 1
954+
parallelLimit: this.options.parallelTranslationLimit || 20,
955+
})
956+
957+
backgroundJobsPlugin.registerTaskDetailsComponent({
958+
jobHandlerName: 'translation_job_handler', // Handler name
959+
component: {
960+
file: this.componentPath('TranslationJobViewComponent.vue') //custom component for the job details
961+
},
935962
})
936963

937964

types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,11 @@ export interface PluginOptions {
8181
* Default value is 30000 tokens
8282
*/
8383
inputTokensPerBatch?: number;
84+
85+
/**
86+
* Limit of parallel translation generation requests.
87+
* This is an optional parameter that can be used to control the number of concurrent requests sent to the completion adapter.
88+
* Default value is 20
89+
*/
90+
parallelTranslationLimit?: number;
8491
}

0 commit comments

Comments
 (0)