bini / translate.py
ObinnaOkpolu's picture
Initial commit of Bini API state
ba7290b
Raw
History Blame Contribute Delete
3.83 kB
# Generates translations
import asyncio
import ctranslate2
import time
from preprocessors.strip_split import splitAndClean
from preprocessors.tokenize import Tokenizer
from typing import List
MODEL_PATH = "/model"
translator = ctranslate2.Translator(
MODEL_PATH, device="cpu",
intra_threads=2
)
tokenizer = Tokenizer(MODEL_PATH)
async def translate_batch_async(src_lang: List[str], tgt_lang: List[str], batches_textArrArr: List[List[str]]) -> List[str]:
# e.g. batches_textArrArr =: [["I hate eggs. I love fish", "I love dogs"], ["The cat is on the table"]]
# Flatten the passed batches down to simple flat arrays
flatBatches_textArr: List[str] = []
# lang codes..
flatBatches_src_lang: List[str] = []
flatBatches_tgt_lang: List[str] = []
for i, batch_textArr in enumerate(batches_textArrArr):
for text in batch_textArr:
flatBatches_textArr.append(text)
flatBatches_src_lang.append(src_lang[i])
flatBatches_tgt_lang.append(tgt_lang[i])
# flatBatches_textArr = ["I hate eggs. I love fish", "I love dogs", "The cat is on the table"]
# Further divide each string to sentences using a sentence splitter..
sentences: List[str] = []
# How many sentences were in each passed string..
sentences_counts: List[int] = []
sentences_src_lang: List[str] = []
sentences_tgt_lang: List[str] = []
for i, thisTranslateText in enumerate(flatBatches_textArr):
thisSrcLang = flatBatches_src_lang[i]
thisTgtLang = flatBatches_tgt_lang[i]
theseSentences: List[str] = splitAndClean(
thisTranslateText, thisSrcLang)
sentences_counts.append(len(theseSentences))
sentences.extend(theseSentences)
sentences_src_lang.extend(
[thisSrcLang]*len(theseSentences))
sentences_tgt_lang.extend(
[thisTgtLang]*len(theseSentences))
# Tokenize the sentences
sentences_tokensied: List[List[str]] = []
for i, sentence in enumerate(sentences):
thisSrcLang= sentences_src_lang[i]
thisSentenceTokens = tokenizer.encode(sentence, thisSrcLang)
sentences_tokensied.extend([thisSentenceTokens])
# ok, let's translate already..
print(f"Processing batch: {len(sentences_tokensied)}")
def sync_func():
return translator.translate_batch(
sentences_tokensied,
target_prefix=[[thisDestLang]
for thisDestLang in sentences_tgt_lang],
max_batch_size=128
)
# Run sync_func asyncronously, so we don't block the event loop.
# Allows other requests to be handled meanwhile.
loop = asyncio.get_event_loop()
results = await loop.run_in_executor(None, lambda: sync_func())
targets = [result.hypotheses[0][1:] for result in results]
sentences_translations = [tokenizer.decode(target) for target in targets]
# Let's reconstruct back to where we split with the sentence splitter..
flatBatches_translations: List[str] = []
for count in sentences_counts:
# Joining with a space, ideally this would be language specific..
flatBatches_translations.append(
' '.join(sentences_translations[:count]))
# Remove these items from the list
sentences_translations[:count] = []
# Let's assemble back into the passed batches..
batches_translationsArrArr: List[List[str]] = []
# Loop over the input batches
for batch_textArr in batches_textArrArr:
batch_translationArr: List[str] = []
# loop over the strings passed in each batch
for text in batch_textArr:
batch_translationArr.append(flatBatches_translations.pop(0))
batches_translationsArrArr.append(batch_translationArr)
return batches_translationsArrArr