Skip to content

Commit

Permalink
feat: add bonus endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
czaja307 committed Mar 4, 2025
1 parent e030bbf commit 1aa026f
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 60 deletions.
9 changes: 6 additions & 3 deletions app/controllers/languages_controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import type { HttpContext } from "@adonisjs/core/http";

import Language from "#models/language";
import {
createLanguageValidator,
updateLanguageValidator,
} from "#validators/language";

export default class LanguagesController {
/**
Expand All @@ -14,7 +18,7 @@ export default class LanguagesController {
* Handle form submission for the create action
*/
async store({ request, response }: HttpContext) {
const data = request.only(["isoCode"]);
const data = await request.validateUsing(createLanguageValidator);
const language = await Language.create(data);
return response.created(language);
}
Expand All @@ -30,9 +34,8 @@ export default class LanguagesController {
* Handle form submission for the edit action
*/
async update({ params, request }: HttpContext) {
const data = await request.validateUsing(updateLanguageValidator);
const language = await Language.findOrFail(params.isoCode);

const data = request.only(["isoCode"]);
language.merge(data);
await language.save();
return language;
Expand Down
118 changes: 67 additions & 51 deletions app/controllers/translations_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import logger from "@adonisjs/core/services/logger";

import Translation from "#models/translation";
import env from "#start/env";
import {
createTranslationValidator,
openaiTranslationValidator,
updateTranslationValidator,
} from "#validators/translation";

const openai = new OpenAI({
apiKey: env.get("OPENAI_API_KEY"),
Expand All @@ -23,17 +28,7 @@ export default class TranslationsController {
* Handle form submission for the create action
*/
async store({ request, response }: HttpContext) {
const data = request.only([
"originalText",
"translatedText",
"originalLanguageCode",
"translatedLanguageCode",
]) as {
originalText: string;
translatedText: string;
originalLanguageCode: string;
translatedLanguageCode: string;
};
const data = await request.validateUsing(createTranslationValidator);

const hash = createHash("sha256").update(data.originalText).digest("hex");
const existingTranslation = await Translation.find(hash);
Expand All @@ -53,35 +48,36 @@ export default class TranslationsController {
* Show individual record
*/
async show({ params }: HttpContext) {
return await Translation.findOrFail(params.hash);
const { hash, isoCode } = params as { hash: string; isoCode: string };
return await Translation.query()
.where("hash", hash)
.where("translatedLanguageCode", isoCode)
.firstOrFail();
}

/**
* Handle form submission for the edit action
*/
async update({ params, request, response }: HttpContext) {
const translation = await Translation.findOrFail(params.hash);

const data = request.only([
"originalText",
"translatedText",
"originalLanguageCode",
"translatedLanguageCode",
]) as {
originalText: string;
translatedText: string;
originalLanguageCode: string;
translatedLanguageCode: string;
};

const hash = createHash("sha256").update(data.originalText).digest("hex");
const existingTranslation = await Translation.find(hash);
async update({ params, request }: HttpContext) {
const { hash, isoCode } = params as { hash: string; isoCode: string };
const data = await request.validateUsing(updateTranslationValidator);

const translation = await Translation.query()
.where("hash", hash)
.where("translatedLanguageCode", isoCode)
.firstOrFail();

const newHash = createHash("sha256")
.update(data.originalText)
.digest("hex");
const existingTranslation = await Translation.find(newHash);
if (existingTranslation !== null) {
return response.conflict({ message: "Translation already exists." });
//TODO: check if that's the way we want to handle this
return existingTranslation;
}

translation.merge({
hash,
hash: newHash,
...data,
isApproved: false,
});
Expand All @@ -93,15 +89,23 @@ export default class TranslationsController {
* Delete record
*/
async destroy({ params }: HttpContext) {
const translation = await Translation.findOrFail(params.hash);
const { hash, isoCode } = params as { hash: string; isoCode: string };
const translation = await Translation.query()
.where("hash", hash)
.where("translatedLanguageCode", isoCode)
.firstOrFail();
await translation.delete();
}

/**
* Approve translation
*/
async approve({ params }: HttpContext) {
const translation = await Translation.findOrFail(params.hash);
const { hash, isoCode } = params as { hash: string; isoCode: string };
const translation = await Translation.query()
.where("hash", hash)
.where("translatedLanguageCode", isoCode)
.firstOrFail();
translation.isApproved = true;
await translation.save();
return translation;
Expand All @@ -111,32 +115,28 @@ export default class TranslationsController {
* Request translation by OpenAI
*/
async requestTranslationOpenAI({ request, response }: HttpContext) {
const data = request.only([
"originalText",
"originalLanguageCode",
"translatedLanguageCode",
]) as {
originalText: string;
originalLanguageCode: string;
translatedLanguageCode: string;
};

const hash = createHash("sha256").update(data.originalText).digest("hex");
const existingTranslation = await Translation.find(hash);
const { originalText, originalLanguageCode, translatedLanguageCode } =
await openaiTranslationValidator.validate(request.all());

const hash = createHash("sha256").update(originalText).digest("hex");
const existingTranslation = await Translation.query()
.where("hash", hash)
.where("translatedLanguageCode", translatedLanguageCode)
.first();
if (existingTranslation !== null) {
return response.conflict({ message: "Translation already exists." });
return existingTranslation;
}

//TODO: get someone from ML team to review this
const systemPrompt = `You are a translation tool. You receive a string written in
polish language, and solely return the same string in english language
${originalLanguageCode} language, and solely return the same string in ${translatedLanguageCode} language
without losing the original formatting. Your translations are accurate, aiming not to deviate from the original
structure, content, writing style and tone. The language were defined as ISO 639-1 codes. Do not add any additional information.`;

const aiParams: OpenAI.Chat.ChatCompletionCreateParams = {
messages: [
{ role: "developer", content: systemPrompt },
{ role: "user", content: data.originalText },
{ role: "user", content: originalText },
],
model: "gpt-4o-mini",
store: true,
Expand Down Expand Up @@ -166,12 +166,28 @@ export default class TranslationsController {

const translation = await Translation.create({
hash,
originalText: data.originalText,
originalText,
translatedText,
originalLanguageCode: data.originalLanguageCode,
translatedLanguageCode: data.translatedLanguageCode,
originalLanguageCode,
translatedLanguageCode,
isApproved: false,
});
return response.created(translation);
}

/**
* All translations for a specific language
*/
async translationsForLanguage({ params }: HttpContext) {
const { isoCode } = params as { isoCode: string };
return Translation.query().where("translatedLanguageCode", isoCode);
}

/**
* All translations for a specific text
*/
async translationsForText({ params }: HttpContext) {
const { hash } = params as { hash: string };
return Translation.query().where("hash", hash);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ export default class extends BaseSchema {

async up() {
this.schema.createTable(this.tableName, (table) => {
table.string("hash").primary(); //hashed original text
table.string("hash"); //hashed original text

table.text("original_text").unique().notNullable();
table.text("original_text").notNullable();
table.text("translated_text").notNullable();

table
Expand All @@ -27,6 +27,8 @@ export default class extends BaseSchema {

table.timestamp("created_at");
table.timestamp("updated_at");

table.primary(["hash", "translated_language_code"]);
});
}

Expand Down
16 changes: 12 additions & 4 deletions start/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,18 @@ router
.group(() => {
router.get("", [TranslationsController, "index"]);
router.post("", [TranslationsController, "store"]);
router.get("/:hash", [TranslationsController, "show"]);
router.put("/:hash", [TranslationsController, "update"]);
router.delete("/:hash", [TranslationsController, "destroy"]);
router.post("/:hash/approve", [TranslationsController, "approve"]);
router.get("/:hash", [TranslationsController, "translationsForText"]);
router.get("/:isoCode", [
TranslationsController,
"translationsForLanguage",
]);
router.get("/:hash/:isoCode", [TranslationsController, "show"]);
router.put("/:hash/:isoCode", [TranslationsController, "update"]);
router.delete("/:hash/:isoCode", [TranslationsController, "destroy"]);
router.post("/:hash/:isoCode/approve", [
TranslationsController,
"approve",
]);
router.post("/openAI", [
TranslationsController,
"requestTranslationOpenAI",
Expand Down

0 comments on commit 1aa026f

Please sign in to comment.