Media and entertainment companies offer multilingual audiences a wide range of content targeted at diverse audience segments. These companies have access to massive amounts of data collected over their many years of operations. Much of this data is unstructured text and images. Conventional approaches to analyzing unstructured data to generate new content rely on keyword or synonym matching. These approaches do not capture the full semantic context of a document, making them less effective for user search, content creation, and other downstream tasks.
Text embeddings use machine learning (ML) capabilities to capture the essence of unstructured data. These embeddings are generated by language models that map natural language text to its numerical representations, and in the process, encode contextual information in the natural language document. Generating text embeddings is the first step for many natural language processing (NLP) applications powered by large language models (LLMs), such as Recovery Augmented Generation (RAG)text generation, entity extraction and various other downstream business processes.
<img style="margin: 10px 0px 10px 0px;border: 1px solid #CCCCCC" src="https://aws.amazon.com/blogs/machine-learning/indian-language-rag-with-cohere-multilingual-embeddings-and-anthropic-claude-3-on-amazon-bedrock/Aspose.Words.b6c282f3-e579-4cfb-8ec6-ac28aad892e2.001.png” alt=””/>Despite the growing popularity and capabilities of LLMs, the language most often used to converse with them, often via a chat-like interface, is English. And while progress has been made in adapting open-source models to understand and respond in Indian languagesThese efforts are not on par with the English language capabilities displayed among larger, state-of-the-art LLMs. This makes it difficult to adopt these models for RAG applications based on Indian languages.
In this post, we showcase a RAG app that can search and query in multiple Indian languages using the Cohere Embed – Multilingual model and amazon-bedrock-anthropic-ai-claude-3″ target=”_blank” rel=”noopener”>Claude 3 anthropic on amazon Bedrock. This post focuses on Indian languages, but you can use the approach with other languages that are supported by the LLM.
Solution Overview
We use the Flowers dataset (1), a benchmark dataset for machine translation between English and other resource-poor languages. It also serves as a parallel corpus, which is a collection of texts that have been translated into one or more languages.
Using the Flores dataset, we can show that the embeddings and subsequently the documents retrieved from the retriever are relevant to the same question asked in multiple languages. However, given the sparsity of the dataset (approximately 1000 lines per language from over 200 languages), the nature and number of questions that can be asked against the dataset is limited.
After you have downloaded the data, load it into the pandas dataframe for processing. For this demonstration, we are limiting ourselves to Bengali, Kannada, Malayalam, Tamil, Telugu, Hindi, Marathi, and English. If you want to adopt this approach for other languages, make sure that the language is supported by both languages. embedding model and the LLM used in the RAG configuration.
Load the data with the following code:
import pandas as pd
df_ben = pd.read_csv('./data/Flores/dev/dev.ben_Beng', sep='\t')
df_kan = pd.read_csv('./data/Flores/dev/dev.kan_Knda', sep='\t')
df_mal = pd.read_csv('./data/Flores/dev/dev.mal_Mlym', sep='\t')
df_tam = pd.read_csv('./data/Flores/dev/dev.tam_Taml', sep='\t')
df_tel = pd.read_csv('./data/Flores/dev/dev.tel_Telu', sep='\t')
df_hin = pd.read_csv('./data/Flores/dev/dev.hin_Deva', sep='\t')
df_mar = pd.read_csv('./data/Flores/dev/dev.mar_Deva', sep='\t')
df_eng = pd.read_csv('./data/Flores/dev/dev.eng_Latn', sep='\t')
# Choose fewer/more languages if needed
df_all_Langs = pd.concat((df_ben, df_kan, df_mal, df_tam, df_tel, df_hin, df_mar,df_eng), axis=1)
df_all_Langs.columns = ('Bengali', 'Kannada', 'Malayalam', 'Tamil', 'Telugu', 'Hindi', 'Marathi','English')
df_all_Langs.shape #(996,8)
df = df_all_Langs
stacked_df = df.stack().reset_index() # for ease of handling
# select only the required columns, rename them
stacked_df = stacked_df.iloc(:,(1,2))
stacked_df.columns = ('language','text')
Cohere's multilingual integration model
Cohere is a leading enterprise artificial intelligence (ai) platform that creates world-class LLM and LLM-powered solutions that enable computers to search, capture meaning, and converse in text. They offer ease of use and strong security and privacy controls.
The Cohere Embed – Multilingual model generates vector representations of documents in over 100 languages and is available on amazon Bedrock. With amazon Bedrock, you can access the embed model through an API call, eliminating the need to manage the underlying infrastructure and ensuring that sensitive information remains securely managed and protected.
The multilingual embedding model groups texts with similar meanings by assigning them positions close to each other in the semantic vector space. Developers can process text in multiple languages without switching between different models. This makes processing more efficient and improves the performance of multilingual applications.
Text embeddings convert unstructured data into a structured format. This allows you to objectively compare, analyze, and extract insights from all these documents. Cohere's new embedding models have a new mandatory input parameter, input_type
which should be set for each API call and include one of the following four values, which align with the most common use cases for text embeddings:
- input_type=”search_document” – Use this for texts (documents) that you want to store in your vector database
- input_type=”search_query” – Use this to perform search queries to find the most relevant documents in your vector database
- input_type=”classification” – Use this if you use the embeddings as input to a classification system
- input_type=”grouping” – Use this if you use embeds to group text
Using these input types provides the highest possible quality for the respective tasks. If you want to use the embeddings for multiple use cases, we recommend using input_type="search_document"
.
Prerequisites
To use the Claude 3 Sonnet LLM and Cohere multilingual embeddings model on this dataset, ensure that you have access to the models in your AWS account in amazon Bedrock, Model Access section and then proceed to install the following packages. The following code has been tested to work with the amazon SageMaker Data Science 3.0 image, backed by a ml.t3.medium instance.
! apt-get update
! apt-get install build-essential -y # for the hnswlib package below
! pip install hnswlib
Create a search index
Once all the prerequisites are met, you can now convert the multilingual corpus into embeddings and store them in hnswliba C++ hierarchical navigable small worlds (HNSW) implementation with just header and Python links, inserts and updates. HNSWLib is an in-memory vector store that can be saved to a file, which should be sufficient for the small dataset we are working with. Use the following code:
import hnswlib
import os
import json
import botocore
import boto3
boto3_bedrock = boto3.client('bedrock')
bedrock_runtime = boto3.client('bedrock-runtime')
# Create a search index
index = hnswlib.Index(space="ip", dim=1024)
index.init_index(max_elements=10000, ef_construction=512, M=64)
all_text = stacked_df('text').to_list()
all_text_lang = stacked_df('language').to_list()
Embedding and indexing documents
To embed and store the small multilingual data set, use Cohere embed-multilingual-v3.0
model, which creates embeddings with 1024 dimensions, using the amazon Bedrock runtime API:
modelId="cohere.embed-multilingual-v3"
contentType= "application/json"
accept = "*/*"
df_chunk_size = 80
chunk_embeddings = ()
for i in range(0,len(all_text), df_chunk_size):
chunk = all_text(i:i+df_chunk_size)
body=json.dumps(
{"texts":chunk,"input_type":"search_document"} # search documents
)
response = bedrock_runtime.invoke_model(body=body,
modelId=modelId,
accept=accept,
contentType=contentType)
response_body = json.loads(response.get('body').read())
index.add_items(response_body('embeddings'))
Check that the inlays work
To test the solution, write a function that takes a query as input, ingests it, and finds the top N documents most closely related to it:
# Retrieval of closest N docs to query
def retrieval(query, num_docs_to_return=10):
modelId="cohere.embed-multilingual-v3"
contentType= "application/json"
accept = "*/*"
body=json.dumps(
{"texts":(query),"input_type":"search_query"} # search query
)
response = bedrock_runtime.invoke_model(body=body,
modelId=modelId,
accept=accept,
contentType=contentType)
response_body = json.loads(response.get('body').read())
doc_ids = index.knn_query(response_body('embeddings'),
k=num_docs_to_return)(0)(0)
print(f"Query: {query} \n")
retrieved_docs = ()
for doc_id in doc_ids:
# Append results
retrieved_docs.append(all_text(doc_id)) # original vernacular language docs
# Print results
print(f"Original Flores Text {all_text(doc_id)}")
print("-"*30)
print("END OF RESULTS \n\n")
return retrieved_docs
You can explore what the RAG stack does with a couple of queries in different languages, such as Hindi:
queries = (
"मुझे सिंधु नदी घाटी सभ्यता के बारे में बताइए","
)
# translation: tell me about Indus Valley Civilization
for query in queries:
retrieval(query)
The index returns documents relevant to the search query in all languages:
Query: मुझे सिंधु नदी घाटी सभ्यता के बारे में बताइए
Original Flores Text सिंधु घाटी सभ्यता उत्तर-पश्चिम भारतीय उपमहाद्वीप में कांस्य युग की सभ्यता थी जिसमें आस-पास के आधुनिक पाकिस्तान और उत्तर पश्चिम भारत और उत्तर-पूर्व अफ़गानिस्तान के कुछ क्षेत्र शामिल थे.
------------------------------
Original Flores Text सिंधु नदी के घाटों में पनपी सभ्यता के कारण यह इसके नाम पर बनी है.
------------------------------
Original Flores Text यद्यपि कुछ विद्वानों का अनुमान है कि चूंकि सभ्यता अब सूख चुकी सरस्वती नदी के घाटियों में विद्यमान थी, इसलिए इसे सिंधु-सरस्वती सभ्यता कहा जाना चाहिए, जबकि 1920 के दशक में हड़प्पा की पहली खुदाई के बाद से कुछ इसे हड़प्पा सभ्यता कहते हैं।
------------------------------
Original Flores Text సింధు నది పరీవాహక ప్రాంతాల్లో నాగరికత విలసిల్లింది.
------------------------------
Original Flores Text सिंधू संस्कृती ही वायव्य भारतीय उपखंडातील कांस्य युग संस्कृती होती ज्यामध्ये आधुनिक काळातील पाकिस्तान, वायव्य भारत आणि ईशान्य अफगाणिस्तानातील काही प्रदेशांचा समावेश होता.
------------------------------
Original Flores Text সিন্ধু সভ্যতা হল উত্তর-পশ্চিম ভারতীয় উপমহাদেশের একটি তাম্রযুগের সভ্যতা যা আধুনিক-পাকিস্তানের অধিকাংশ ও উত্তর-পশ্চিম ভারত এবং উত্তর-পূর্ব আফগানিস্তানের কিছু অঞ্চলকে ঘিরে রয়েছে।
-------------------------
.....
You can now use these documents retrieved from the index as context when calling the Anthropic Claude 3 Sonnet model on amazon Bedrock. In production environments with datasets that are several orders of magnitude larger than the Flores dataset, we can make the index search results even more relevant by using Cohere's Rerank models.
Use the system message to describe how you want the LLM to process your inquiry:
# Retrieval of docs relevant to the query
def context_retrieval(query, num_docs_to_return=10):
modelId="cohere.embed-multilingual-v3"
contentType= "application/json"
accept = "*/*"
body=json.dumps(
{"texts":(query),"input_type":"search_query"} # search query
)
response = bedrock_runtime.invoke_model(body=body,
modelId=modelId,
accept=accept,
contentType=contentType)
response_body = json.loads(response.get('body').read())
doc_ids = index.knn_query(response_body('embeddings'),
k=num_docs_to_return)(0)(0)
retrieved_docs = ()
for doc_id in doc_ids:
retrieved_docs.append(all_text(doc_id))
return " ".join(retrieved_docs)
def query_rag_bedrock(query, model_id = 'anthropic.claude-3-sonnet-20240229-v1:0'):
system_prompt=""'
You are a helpful emphathetic multilingual assitant.
Identify the language of the user query, and respond to the user query in the same language.
For example
if the user query is in English your response will be in English,
if the user query is in Malayalam, your response will be in Malayalam,
if the user query is in Tamil, your response will be in Tamil
and so on...
if you cannot identify the language: Say you cannot idenitify the language
You will use only the data provided within the tags, that matches the user's query's language, to answer the user's query
If there is no data provided within the tags, Say that you do not have enough information to answer the question
Restrict your response to a paragraph of less than 400 words avoid bullet points
'''
max_tokens = 1000
messages = ({"role": "user", "content": f'''
query : {query}
{context_retrieval(query)}
'''})
body=json.dumps(
{
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": max_tokens,
"system": system_prompt,
"messages": messages
}
)
response = bedrock_runtime.invoke_model(body=body, modelId=model_id)
response_body = json.loads(response.get('body').read())
return response_body('content')(0)('text')
Let us pass the same query in various Indian languages:
queries = ("tell me about the indus river valley civilization",
"मुझे सिंधु नदी घाटी सभ्यता के बारे में बताइए",
"मला सिंधू नदीच्या संस्कृतीबद्दल सांगा",
"సింధు నది నాగరికత గురించి చెప్పండి",
"ಸಿಂಧೂ ನದಿ ಕಣಿವೆ ನಾಗರಿಕತೆಯ ಬಗ್ಗೆ ಹೇಳಿ",
"সিন্ধু নদী উপত্যকা সভ্যতা সম্পর্কে বলুন",
"சிந்து நதி பள்ளத்தாக்கு நாகரிகத்தைப் பற்றி சொல்",
"സിന്ധു നദീതാഴ്വര നാഗരികതയെക്കുറിച്ച് പറയുക")
for query in queries:
print(query_rag_bedrock(query))
print('_'*20)
The query is in English, so I will respond in English.
The Indus Valley Civilization, also known as the Harappan Civilization, was a Bronze Age civilization that flourished in the northwestern regions of the Indian subcontinent, primarily in the basins of the Indus River and its tributaries. It encompassed parts of modern-day Pakistan, northwest India, and northeast Afghanistan. While some scholars suggest calling it the Indus-Sarasvati Civilization due to its presence in the now-dried-up Sarasvati River basin, the name "Indus Valley Civilization" is derived from its development along the Indus River valley. This ancient civilization dates back to around 3300–1300 BCE and was one of the earliest urban civilizations in the world. It was known for its well-planned cities, advanced drainage systems, and a writing system that has not yet been deciphered.
____________________
सिंधु घाटी सभ्यता एक प्राचीन नगर सभ्यता थी जो उत्तर-पश्चिम भारतीय उपमहाद्वीप में फैली हुई थी। यह लगभग 3300 से 1300 ईसा पूर्व की अवधि तक विकसित रही। इस सभ्यता के केंद्र वर्तमान पाकिस्तान के सिंध और पंजाब प्रांतों में स्थित थे, लेकिन इसके अवशेष भारत के राजस्थान, गुजरात, मध्य प्रदेश, महाराष्ट्र और उत्तर प्रदेश में भी मिले हैं। सभ्यता का नाम सिंधु नदी से लिया गया है क्योंकि इसके प्रमुख स्थल इस नदी के किनारे स्थित थे। हालांकि, कुछ विद्वानों का अनुमान है कि सरस्वती नदी के किनारे भी इस सभ्यता के स्थल विद्यमान थे इसलिए इसे सिंधु-सरस्वती सभ्यता भी कहा जाता है। यह एक महत्वपूर्ण शहरी समाज था जिसमें विकसित योजना बनाने की क्षमता, नगरीय संरचना और स्वच्छ जलापूर्ति आदि प्रमुख विशेषताएं थीं।
____________________
सिंधू संस्कृती म्हणजे सिंधू नदीच्या पट्टीकेतील प्राचीन संस्कृती होती. ही संस्कृती सुमारे ई.पू. ३३०० ते ई.पू. १३०० या कालखंडात फुलणारी होती. ती भारतातील कांस्ययुगीन संस्कृतींपैकी एक मोठी होती. या संस्कृतीचे अवशेष आजच्या पाकिस्तान, भारत आणि अफगाणिस्तानमध्ये आढळून आले आहेत. या संस्कृतीत नगररचना, नागरी सोयी सुविधांचा विकास झाला होता. जलवाहिनी, नगरदेवालय इत्यादी अद्भुत बाबी या संस्कृतीत होत्या. सिंधू संस्कृतीत लिपीसुद्धा विकसित झाली होती परंतु ती अजूनही वाचण्यास आलेली नाही. सिंधू संस्कृती ही भारतातील पहिली शहरी संस्कृती मानली जाते.
____________________
సింధు నది నాగరికత గురించి చెప్పుతూ, ఈ నాగరికత సింధు నది పరిసర ప్రాంతాల్లో ఉన్నదని చెప్పవచ్చు. దీనిని సింధు-సరస్వతి నాగరికత అనీ, హరప్ప నాగరికత అనీ కూడా పిలుస్తారు. ఇది ఉత్తర-ఆర్య భారతదేశం, ఆధునిక పాకిస్తాన్, ఉత్తర-పశ్చిమ భారతదేశం మరియు ఉత్తర-ఆర్థిక అఫ్గానిస్తాన్ కు చెందిన తామ్రయుగపు నాగరికత. సరస్వతి నది పరీవాహక ప్రాంతాల్లోనూ నాగరికత ఉందని కొందరు పండితులు అభిప్రాయపడ్డారు. దీని మొదటి స్థలాన్ని 1920లలో హరప్పాలో త్రవ్వారు. ఈ నాగరికతలో ప్రశస్తమైన బస్తీలు, నగరాలు, మలిచ్చి రంగులతో నిర్మించిన భవనాలు, పట్టణ నిర్మాణాలు ఉన్నాయి.
____________________
ಸಿಂಧೂ ಕಣಿವೆ ನಾಗರಿಕತೆಯು ವಾಯುವ್ಯ ಭಾರತದ ಉಪಖಂಡದಲ್ಲಿ ಕಂಚಿನ ಯುಗದ ನಾಗರಿಕತೆಯಾಗಿದ್ದು, ಪ್ರಾಚೀನ ಭಾರತದ ಇತಿಹಾಸದಲ್ಲಿ ಮುಖ್ಯವಾದ ಪಾತ್ರವನ್ನು ವಹಿಸಿದೆ. ಈ ನಾಗರಿಕತೆಯು ಆಧುನಿಕ-ದಿನದ ಪಾಕಿಸ್ತಾನ ಮತ್ತು ವಾಯುವ್ಯ ಭಾರತದ ಭೂಪ್ರದೇಶಗಳನ್ನು ಹಾಗೂ ಈಶಾನ್ಯ ಅಫ್ಘಾನಿಸ್ತಾನದ ಕೆಲವು ಪ್ರದೇಶಗಳನ್ನು ಒಳಗೊಂಡಿರುವುದರಿಂದ ಅದಕ್ಕೆ ಸಿಂಧೂ ನಾಗರಿಕತೆ ಎಂದು ಹೆಸರಿಸಲಾಗಿದೆ. ಸಿಂಧೂ ನದಿಯ ಪ್ರದೇಶಗಳಲ್ಲಿ ಈ ನಾಗರಿಕತೆಯು ವಿಕಸಿತಗೊಂಡಿದ್ದರಿಂದ ಅದಕ್ಕೆ ಸಿಂಧೂ ನಾಗರಿಕತೆ ಎಂದು ಹೆಸರಿಸಲಾಗಿದೆ. ಈಗ ಬತ್ತಿ ಹೋದ ಸರಸ್ವತಿ ನದಿಯ ಪ್ರದೇಶಗಳಲ್ಲಿ ಸಹ ನಾಗರೀಕತೆಯ ಅಸ್ತಿತ್ವವಿದ್ದಿರಬಹುದೆಂದು ಕೆಲವು ಪ್ರಾಜ್ಞರು ಶಂಕಿಸುತ್ತಾರೆ. ಆದ್ದರಿಂದ ಈ ನಾಗರಿಕತೆಯನ್ನು ಸಿಂಧೂ-ಸರಸ್ವತಿ ನಾಗರಿಕತೆ ಎಂದು ಸೂಕ್ತವಾಗಿ ಕರೆ
____________________
সিন্ধু নদী উপত্যকা সভ্যতা ছিল একটি প্রাচীন তাম্রযুগীয় সভ্যতা যা বর্তমান পাকিস্তান এবং উত্তর-পশ্চিম ভারত ও উত্তর-পূর্ব আফগানিস্তানের কিছু অঞ্চলকে নিয়ে গঠিত ছিল। এই সভ্যতার নাম সিন্ধু নদীর অববাহিকা অঞ্চলে এটির বিকাশের কারণে এরকম দেওয়া হয়েছে। কিছু পণ্ডিত মনে করেন যে সরস্বতী নদীর ভূমি-প্রদেশেও এই সভ্যতা বিদ্যমান ছিল, তাই এটিকে সিন্ধু-সরস্বতী সভ্যতা বলা উচিত। আবার কেউ কেউ এই সভ্যতাকে হরপ্পা পরবর্তী হরপ্পান সভ্যতা নামেও অবিহিত করেন। যাই হোক, সিন্ধু সভ্যতা ছিল প্রাচীন তাম্রযুগের এক উল্লেখযোগ্য সভ্যতা যা সিন্ধু নদী উপত্যকার এলাকায় বিকশিত হয়েছিল।
____________________
சிந்து நதிப் பள்ளத்தாக்கில் தோன்றிய நாகரிகம் சிந்து நாகரிகம் என்றழைக்கப்படுகிறது. சிந்து நதியின் படுகைகளில் இந்த நாகரிகம் மலர்ந்ததால் இப்பெயர் வழங்கப்பட்டது. ஆனால், தற்போது வறண்டுபோன சரஸ்வதி நதிப் பகுதியிலும் இந்நாகரிகம் இருந்திருக்கலாம் என சில அறிஞர்கள் கருதுவதால், சிந்து சரஸ்வதி நாகரிகம் என்று அழைக்கப்பட வேண்டும் என்று வாதிடுகின்றனர். மேலும், இந்நாகரிகத்தின் முதல் தளமான ஹரப்பாவின் பெயரால் ஹரப்பா நாகரிகம் என்றும் அழைக்கப்படுகிறது. இந்த நாகரிகம் வெண்கலயுக நாகரிகமாக கருதப்படுகிறது. இது தற்கால பாகிஸ்தானின் பெரும்பகுதி, வடமேற்கு இந்தியா மற்றும் வடகிழக்கு ஆப்கானிஸ்தானின் சில பகுதிகளை உள்ளடக்கியது.
____________________
സിന്ധു നദീതട സംസ്കാരം അഥവാ ഹാരപ്പൻ സംസ്കാരം ആധുനിക പാകിസ്ഥാൻ, വടക്ക് പടിഞ്ഞാറൻ ഇന്ത്യ, വടക്ക് കിഴക്കൻ അഫ്ഗാനിസ്ഥാൻ എന്നിവിടങ്ങളിൽ നിലനിന്ന ഒരു വെങ്കല യുഗ സംസ്കാരമായിരുന്നു. ഈ സംസ്കാരത്തിന്റെ അടിസ്ഥാനം സിന്ധു നദിയുടെ തടങ്ങളായതിനാലാണ് ഇതിന് സിന്ധു നദീതട സംസ്കാരം എന്ന പേര് ലഭിച്ചത്. ചില പണ്ഡിതർ ഇപ്പോൾ വറ്റിപ്പോയ സരസ്വതി നദിയുടെ തടങ്ങളിലും ഈ സംസ്കാരം നിലനിന്നിരുന്നതിനാൽ സിന്ധു-സരസ്വതി നദീതട സംസ്കാരമെന്ന് വിളിക്കുന്നത് ശരിയായിരിക്കുമെന്ന് അഭിപ്രായപ്പെടുന്നു. എന്നാൽ ചിലർ 1920കളിൽ ആദ്യമായി ഉത്ഖനനം നടത്തിയ ഹാരപ്പ എന്ന സ്ഥലത്തെ പേര് പ്രകാരം ഈ സംസ്കാരത്തെ ഹാരപ്പൻ സംസ്കാരമെന്ന് വിളിക്കുന്നു.
Conclusion
This post presented a tutorial on how to use Cohere’s multilingual embedding model along with Anthropic Claude 3 Sonnet on amazon Bedrock. In particular, we showed how the same question asked in multiple Indian languages is answered using relevant documents retrieved from a vector store.
Cohere’s multilingual integration model supports over 100 languages. It eliminates the complexity of creating applications that require working with a corpus of documents in different languages. Cohere Embed Model It is capable of delivering results in real-world applications. It handles noisy data as inputs, scales to complex RAG systems, and offers cost-effectiveness thanks to its compression-aware training method.
Start building with Cohere and Anthropic Claude 3 Sonnet's multilingual integration template on amazon Bedrock today.
References
(1) Flores dataset: https://github.com/facebookresearch/flores/tree/main/flores200
About the Author
Rony K. Roy is a Senior Solutions Architect specializing in ai and ML. Rony helps partners build ai and ML solutions on AWS.