Universal Text Translator with ChatGPT API

Precise Source Language Deduction and Translation in less than 10 steps, including tips for error handling!

Shilpa Leo
8 min readSep 3, 2023
Photo by Edurne Tx on Unsplash

Suppose this is the first post you’re reading in my series of experimentations with ChatGPT API — I strongly encourage reading my previous two posts using the same API in other popular text applications — Summarization, Sentiment inference for entire corpus, or per document.

In this post, the 3rd release in my ‘less-than-10 steps to unlock insights with ChatGPT API’, I’ll share this tool’s yet another fantastic application — in Text Transformation, which can mean many different operations, from Source Language Deduction (inferring the exact language of a given text), Translation from one to another language, Proofreading, Grammar & Spell check/correction, Tone Translation, etc.

Goal

Use ChatGPT API to deduce an input text’s source language and translate it to English. I used an open-source dataset from Kaggle with Hindi movie reviews for translation to English.

Value proposition

Consider you’re part of an organization that has operations in different geographies. In such scenarios, the text data you might be exposed to for analysis might be more than one or even two languages! An LLM like GPT could be highly efficient for translating different languages into one universal language, like English.

OpenAI claims their LLMs are trained on vast amounts of internet data and exposed to ~100 different languages! with varying degrees of proficiency so they can efficiently perform translation. So, let’s put it to the test!

Reminder: How ChatGPT API can help with turning Text into Insights

First, it is essential to understand why this article does not use ChatGPT’s web user interface and instead uses the API. Of course, the Web interactive tool is the most popular option associated with ChatGPT and is widely used by many of us. But, the API way presents some advantages, such as:

  • You can unleash the full power of ChatGPT within your Python code notebook to continue other downstream analyses with the output from your ChatGPT prompt.
  • Going the “programmatic” way is always superior after testing the waters with the “UI” way — it simply allows for scalability and automation because the same code can be recycled with just a new dataset change to get quick insights!
  • OpenAI documentation also suggests using the API for Text use cases, given its higher flexibility.

Code

# Uncomment below code and Install the OpenAI Python library (1st time use)

#!pip install openai
# Imports

import openai # LLM API for NLP tasks
import pandas as pd # handling tabular data
from tqdm import tqdm # monitor progress of task per `for` loop iteration
import json # handle conversion from JSON String to Dictionary

If you don’t already have an API key:

To use the OpenAI API, you’ll first need to create your OpenAI secret API key here.

  • Click on Login if you have an existing ChatGPT account, or click Sign Up.
  • Under API Keys, click on Create new API key and ensure to copy the created API key to proceed further.
# Pass API Key

openai.api_key = "sk-..." # insert your API key within " "

A few inferences from the dataset in the Kaggle source link:

  • Contains movie reviews in Hindi language in the text column.
  • The dataset source has train and valid (validation) datasets. For experimentation, I’ve used the smaller validation dataset.
  • There is also Sentiment information available (0: “negative”, 1: “neutral” and 2: “positive” sentiments) in the experience column for Sentiment analysis (not explored in this post)
# Load dataset onto Pandas DataFrame

df = pd.read_csv('../datasets/hindi_movie_reviews.csv') # parse csv to df
print(df.shape) # rows, columns size
df.head() # preview first 5 rows
Image by author

Currently, the reviews are stored in the rows of the DataFrame df above. We’ll pack the individual reviews as items in a Python List to loop through and perform the Translation task using the LLM API. `

# Pack text reviews into Python List for API predictions

reviews_list = df['text'].to_list() # convert series of text to list items
print(len(reviews_list)) # confirm length of list is same as rows in df
reviews_list[:2] # preview a snapshot of list format
Image by author

OpenAI’s gpt-3.5-turbo model will be used, and the chat completions endpoint.

  • The documentation shows what an example API call looks like (the function and the parameter calls necessary to pass)
  • It also outlines how the Chat completions API response looks like, which can be treated as a Python (nested) dictionary
  • The chat assistant’s reply can be extracted with response['choices'][0]['message'][content]

Note: The API is non-deterministic by default. This means you might get a slightly different completion every time you call it, even if your prompt stays the same. Setting temperature = 0 will make the outputs mostly deterministic, but a small amount of variability will remain.

# Create helper function for task

def text_analysis(prompt, model="gpt-3.5-turbo"):
messages = [{"role": "user", "content": prompt}]
response = openai.ChatCompletion.create(
model=model,
messages=messages,
temperature=0, # this is the degree of randomness of the model's output
)
return response.choices[0].message["content"]
# Loop through all text reviews and run text analysis

response_summary = [] # declare empty list to store all API responses

for review in tqdm(reviews_list): # loop through few text reviews to perform actions in prompt
try: # try translation and sentiment inference based on prompt until an error is encountered
prompt = f"""

Perform the following actions on the given text delimited by triple backticks:

1. Deduce the source language, translate the text from the source language into English language.
2. Infer the sentiment of text and report strictly in a single word out of [positive, negative, neutral].
2. If a sentiment cannot be inferred due to lack of meaningful text, infer sentiment as "neutral".

Return the output in the following format:
{{"source_language": string,
"translated_review": string,
"sentiment_review": string}}

Text to perform actions: ```{review}```
"""

response = text_analysis(prompt) # call helper function to perform tasks in prompt
response = json.loads(response) # convert JSON String to Python dictionary

except: # once an error is encountered, record empty string and move on to next text
response = {"source_language": "",
"translated_review": "",
"sentiment_review": ""}

response_summary.append(response) # append all responses for every `for` loop iteration

print(len(response_summary))
response_summary[:5]

Given the availability of sentiments in the original dataset, I had included Sentiment inference as part of my prompt. But, to keep this post digestible, will focus on the Translation performance of the LLM.

The output of the above code yielded something like below. I had a list of dictionaries, each with three 'key': value pairs to hold the Deduced source language, English translated review, and a Sentiment inference of every review in the dataset.

Image by author

The prompt and the json.loads() operations have been packaged into a try code block as part of error handling to skip input texts when encountering errors by storing empty values for the same dictionary keys. Based on my trials, some of the errors I was running into, which broke the API flow, were:

  1. InvalidRequestError when hit into the model’s maximum context length of 4097 tokens. I discovered this the hard way by prompting the API to return input text + translated text, which ended up eating into the tokens limit — best practice tip: only get the LLM to return what it is specialized at. Sticking the original text can be handled external to the API call.
  2. JSONDecodeError: Unterminated stringwhile attempting to do JSON String to Python Dictionary conversion because of an incomplete/open string in the input text.

Note: Here, a blanket exceptblock has been used to skip any encountered errors, which can be modified to perform different actions for different types of errors by substituting multiple exceptblocks for individual error handling.

# Storing API responses in a DataFrame for further analysis

response_df = pd.DataFrame(response_summary)
print(response_df.shape)
response_df.head()

# Export DataFrame with API responses for retrieval and analysis

response_df.to_csv('../datasets/translations_sent_output.csv')

The last step, exporting the DataFrame storing all API responses, is a safe practice to keep the valuable outputs in a safe house until ready for further use/processing. Since the API operations are paid, we want to avoid repeatedly calling it to perform the same task. Thus, saving outputs to some location is crucial — you could save to AWS S3 location, etc. I’ve just saved it locally on my code.

# Load API response csv for translation examination

response_df = pd.read_csv('../datasets/translations_sent_output.csv')
print(response_df.shape)
response_df.head()
Image by author

The column ‘Unnamed: 0’ here stores the index and is redundant (holds the same information as the current DataFrame index). This could easily be excluded while exporting the csv file by setting a parameter index = False in the DataFrame export step to_csv().

The output above confirms the column headers ‘source_language,’ ‘translated_review,’ and ‘sentiment_review’ are keys requested in the API prompt earlier to format the response per text for the task on hand. The nulls returned resulted from errors on input texts or due to the token length cap.

After dropping the nulls, I confirmed first how accurate ChatGPT’s Language Detection capabilities were.

# Dropping nulls to work with clean dataset with no missing values

response_df.dropna(inplace = True)

# Drop redundant column

response_df.drop(columns=['Unnamed: 0'], inplace=True)

# Examine deduced source language

response_df['source_language'].value_counts(normalize=True)
Image by author

The output above confirms a staggering 92% accuracy on language detection — most comments were correctly detected as of Hindi origin!

Next, I wanted to sample some comments to review side by side the original review in Hindi vs. the English translation to see how well the LLM did. For this, I had to join back the response_df with the original df that had the Hindi language reviews.

# Perform index join on original data <> API response for translation examination

compare_df = df.join(response_df, how='inner')
print(compare_df.shape)
compare_df.head()
Image by author
# Review translation 

print(f"hindi review: {compare_df['text'][1]}\n")
print(f"translated review: {compare_df['translated_review'][1]}")
Image by author
Image by author

I found the translation to be spot on!

Conclusion

This post explored using ChatGPT API for yet another popular NLP use case in the industry — Translation and Language detection. Additionally, edge case handling was illustrated when running into errors in the API call process due to input text limitations.

More such experimentations are underway; stay tuned!

Inspired by knowledge gained from this awesome DeepLearning.AI tutorial.

--

--

Shilpa Leo

Data Scientist| EdTech Instructor| Data Analytics| AWS| Public Speaker| Python| ML| NLP| Power BI | SQL| RPA| https://www.linkedin.com/in/shilpa-sindhe/