Vektorinės duomenų bazės dažniausiai naudojamos vektoriniams įterpimams saugoti tokioms užduotims kaip panašumų paieška, siekiant sukurti rekomendacijų ir atsakymų į klausimus sistemas. „Milvus“ yra viena iš atvirojo kodo duomenų bazių, kurioje saugomi įterpimai vektorinių duomenų pavidalu. Ji puikiai tinka, nes turi indeksavimo funkcijas, tokias kaip apytikslis artimiausias kaimynas (ANN), leidžiantis gauti greitus ir tikslius rezultatus.
Šiame straipsnyje parodysime, kaip naudoti HuggingFace duomenų rinkinį, sukurti įterpimus iš duomenų rinkinio ir padalinti duomenų rinkinį į dvi dalis (testavimas ir mokymas). Taip pat sužinosite, kaip išsaugoti visus sukurtus įterpimus į įdiegtą Milvus duomenų bazę, sukuriant kolekciją, tada atlikti paieškos operaciją pateikiant klausimą ir sugeneruojant panašiausius atsakymus.
Serverio diegimas Vultr
- Užsiregistruokite ir prisijunkite prie Vultr klientų portalas.
- Eikite į Produktai puslapį.
- Šoniniame meniu pasirinkite Apskaičiuokite.
- Spustelėkite Įdiegti serverį mygtuką centre.
- Pasirinkite Debesis GPU kaip serverio tipą.
- Pasirinkite A100 kaip GPU tipas.
- Skiltyje „Serverio vieta“ pasirinkite norimą regioną.
- Skiltyje „Operacinė sistema“ pasirinkite Vultr GPU Stack kaip operacinė sistema.Vultr GPU Stack sukurta siekiant supaprastinti dirbtinio intelekto (AI) ir mašininio mokymosi (ML) projektų kūrimo procesą, teikiant išsamų iš anksto įdiegtos programinės įrangos rinkinį, įskaitant NVIDIA CUDA Toolkit, NVIDIA cuDNN, TensorFlow, PyTorch ir pan.
- Skiltyje „Serverio dydis“ pasirinkite 80 GB variantas.
- Skiltyje „Papildomos funkcijos“ pasirinkite daugiau funkcijų.
- Spustelėkite Įdiegti dabar mygtuką apatiniame dešiniajame kampe.
- Eikite į Produktai puslapį.
- Šoniniame meniu pasirinkite Kubernetes.
- Spustelėkite Pridėti klasterį mygtuką centre.
- Įveskite a Klasterio pavadinimas.
- Skiltyje „Klasterio vieta“ pasirinkite norimą regioną.
- Įveskite a Etiketė klasterio baseinui.
- Padidinkite Mazgų skaičius iki 5.
- Spustelėkite Įdiegti dabar mygtuką apatiniame dešiniajame kampe.
Serverio paruošimas
Reikiamų paketų įdiegimas
Nustačius Vultr serverį ir Vultr Kubernetes klasterį, kaip aprašyta anksčiau, šiame skyriuje sužinosite, kaip įdiegti priklausomybės Python paketus, reikalingus Milvus duomenų bazei sukurti ir reikalingų modulių importavimui į Python konsolę.
- Įdiekite reikiamas priklausomybes
pip install transformers datasets pymilvus torch
Štai ką reiškia kiekvienas paketas:
transformers
: Suteikia prieigą ir leidžia dirbti su iš anksto paruoštais LLM modeliais atliekant tokias užduotis kaip teksto klasifikavimas ir generavimas.datasets
: Suteikia prieigą ir leidžia dirbti su paruoštais naudoti duomenų rinkiniais NLP užduotims atlikti.pymilvus
: Python klientas, skirtas Milvus, leidžiantis ieškoti vektorių panašumo, saugoti ir valdyti dideles vektorių kolekcijas.torch
: mašininio mokymosi biblioteka, naudojama mokymui ir gilaus mokymosi modeliams kurti.
- Pasiekite python konsolę
python3
- Importuokite reikiamus modulius
from pymilvus import connections, FieldSchema, CollectionSchema, DataType, Collection, utility from datasets import load_dataset_builder, load_dataset, Dataset from transformers import AutoTokenizer, AutoModel from torch import clamp, sum
Štai ką reiškia kiekvienas paketas:
pymilvus
moduliai:connections
: Suteikia funkcijas, skirtas valdyti ryšius su Milvus duomenų baze.FieldSchema
: apibrėžia laukų schemą Milvus duomenų bazėje.CollectionSchema
: apibrėžia kolekcijos schemą.DataType
: išvardija duomenų tipus, kurie gali būti naudojami Milvus kolekcijoje.Collection
: suteikia galimybę sąveikauti su Milvus kolekcijomis, kad būtų galima kurti, įterpti ir ieškoti vektorių.utility
: Teikia išankstinio duomenų apdorojimo ir užklausų optimizavimo funkcijas darbui su Milvus
datasets
moduliai:load_dataset_builder
: įkelia ir grąžina duomenų rinkinio objektą, kad pasiektų duomenų bazės informaciją ir jos metaduomenis.load_dataset
: įkelia duomenų rinkinį iš duomenų rinkinio kūrimo priemonės ir grąžina duomenų rinkinio objektą, kad būtų galima pasiekti duomenis.Dataset
: reiškia duomenų rinkinį, suteikiantį prieigą prie su duomenimis susijusių operacijų.
transformers
moduliai:AutoTokenizer
: įkelia iš anksto paruoštus NLP užduočių atpažinimo modelius.AutoModel
: Tai modelių įkėlimo klasė, skirta automatiškai įkelti iš anksto paruoštus modelius NLP užduotims atlikti.
torch
moduliai:clamp
: Teikia tenzoriaus reikšmių elementų ribojimo funkcijas.sum
: apskaičiuoja tenzoriaus elementų sumą pagal nurodytus matmenis.
Atsakymų į klausimus architektūros kūrimas
Šiame skyriuje sužinosite, kaip sukurti rinkinį, į kolekciją įterpti duomenis ir atlikti paieškos operacijas pateikiant įvestį klausimų-atsakymų formatu.
- Deklaruokite parametrus, būtinai pakeiskite
EXTERNAL_IP_ADDRESS
su faktine verte.DATASET = 'squad' MODEL = 'bert-base-uncased' TOKENIZATION_BATCH_SIZE = 1000 INFERENCE_BATCH_SIZE = 64 INSERT_RATIO = .001 COLLECTION_NAME = 'huggingface_db' DIMENSION = 768 LIMIT = 10 MILVUS_HOST = "EXTERNAL_IP_ADDRESS" MILVUS_PORT = "19530"
Štai ką reiškia kiekvienas parametras:
DATASET
: apibrėžia Huggingface duomenų rinkinį, kuris naudojamas ieškant atsakymų.MODEL
: apibrėžia transformatorių, naudojamą kuriant įterpimus.TOKENIZATION_BATCH_SIZE
: nustato, kiek tekstų vienu metu apdorojama tokenizacijos metu, ir padeda pagreitinti prieigos raktą naudojant paralelizmą.INFERENCE_BATCH_SIZE
: nustato numatymo paketo dydį, turintį įtakos teksto klasifikavimo užduočių efektyvumui. Jei naudojate mažesnį GPU dydį, partijos dydį galite sumažinti iki 32 arba 18.INSERT_RATIO
: valdo teksto duomenų dalį, kuri turi būti konvertuojama į įterpimus, tvarko duomenų, kurie turi būti indeksuojami atliekant vektorinę paiešką, apimtį.COLLECTION_NAME
: nustato kolekcijos, kurią ketinate sukurti, pavadinimą.DIMENSION
: nustato atskiro įterpimo, kurį ketinate saugoti kolekcijoje, dydį.LIMIT
: nustato rezultatų, kurių reikia ieškoti ir kurie turi būti rodomi išvestyje, skaičių.MILVUS_HOST
: nustato išorinį IP prieigai prie įdiegtos Milvus duomenų bazės.MILVUS_PORT
: nustato prievadą, kuriame yra įdiegta Milvus duomenų bazė.
- Prisijunkite prie išorinės Milvus duomenų bazės, kurią įdiegėte naudodami išorinį IP adresą ir prievadą, kuriame yra Milvus. Būtinai pakeiskite
user
irpassword
lauko reikšmės su atitinkamomis reikšmėmis.Jei prie duomenų bazės prisijungiate pirmą kartą, tadauser
= šaknis irpassword
= Milvus.connections.connect(host="MILVUS_HOST", port="MILVUS_PORT", user="USER", password="PASSWORD")
Kolekcijos kūrimas
Šiame skyriuje sužinosite, kaip sukurti kolekciją ir apibrėžti jos schemą, kad būtų tinkamai saugomas duomenų rinkinio turinys. Taip pat sužinosite, kaip kurti indeksus ir įkelti kolekciją.
- Patikrinkite kolekcijos egzistavimą, jei kolekcija yra, ji ištrinama, kad būtų išvengta konfliktų.
if utility.has_collection(COLLECTION_NAME): utility.drop_collection(COLLECTION_NAME)
- Sukurkite kolekciją pavadinimu
huggingface_db
ir apibrėžti kolekcijos schemą.fields = [ FieldSchema(name='id', dtype=DataType.INT64, is_primary=True, auto_id=True), FieldSchema(name='original_question', dtype=DataType.VARCHAR, max_length=1000), FieldSchema(name='answer', dtype=DataType.VARCHAR, max_length=1000), FieldSchema(name='original_question_embedding', dtype=DataType.FLOAT_VECTOR, dim=DIMENSION) ] schema = CollectionSchema(fields=fields) collection = Collection(name=COLLECTION_NAME, schema=schema)
Toliau pateikiami laukai, naudojami kolekcijos schemai apibrėžti:
id
: pirminis laukas, kuriame reikia identifikuoti visus duomenų bazės įrašus.original_question
: Tai laukas, kuriame saugomas pradinis klausimas, iš kurio bus suderintas jūsų užduotas klausimas.answer
: Tai laukas, kuriame yra atsakymas į kiekvienąoriginal_quesition
.original_question_embedding
: yra kiekvieno įrašo įterpimaioriginal_question
kad atliktumėte panašumo paiešką su klausimu, kurį nurodėte kaip įvestį.
- Sukurkite indeksą
original_question_embedding
lauke, kad atliktumėte panašumo paiešką.index_params = { 'metric_type':'L2', 'index_type':"IVF_FLAT", 'params':{"nlist":1536} }
collection.create_index(field_name="original_question_embedding", index_params=index_params)
Sėkmingai sukūrus nurodyto lauko indeksą, bus rodoma toliau pateikta išvestis:
Status(code=0, message=)
- Įkelkite kolekciją, kad įsitikintumėte, jog kolekcija yra paruošta atlikti paieškos operaciją.
collection.load()
Duomenų įterpimas į rinkinį
Šiame skyriuje sužinosite, kaip padalinti duomenų rinkinį į rinkinius, suskirstyti visus duomenų rinkinio klausimus, sukurti įterpimus ir įterpti juos į rinkinį.
- Įkelkite duomenų rinkinį, padalykite duomenų rinkinį į mokymo ir bandymo rinkinius ir apdorokite bandymo rinkinį, kad pašalintumėte visus kitus stulpelius, išskyrus atsakymo tekstą.
data_dataset = load_dataset(DATASET, split='all') data_dataset = data_dataset.train_test_split(test_size=INSERT_RATIO, seed=42)['test'] data_dataset = data_dataset.map(lambda val: {'answer': val['answers']['text'][0]}, remove_columns=['answers'])
- Inicijuokite tokenizatorių.
tokenizer = AutoTokenizer.from_pretrained(MODEL)
- Apibrėžkite klausimų žymėjimo funkciją.
def tokenize_question(batch): results = tokenizer(batch['question'], add_special_tokens = True, truncation = True, padding = "max_length", return_attention_mask = True, return_tensors = "pt") batch['input_ids'] = results['input_ids'] batch['token_type_ids'] = results['token_type_ids'] batch['attention_mask'] = results['attention_mask'] return batch
- Pažymėkite kiekvieną klausimo įrašą naudodami
tokenize_question
anksčiau apibrėžtą funkciją ir nustatykite išvestį įtorch
suderinamas PyTorch pagrindu veikiančių mašininio mokymosi modelių formatas.data_dataset = data_dataset.map(tokenize_question, batch_size=TOKENIZATION_BATCH_SIZE, batched=True) data_dataset.set_format('torch', columns=['input_ids', 'token_type_ids', 'attention_mask'], output_all_columns=True)
- Įkelkite iš anksto paruoštą modelį, perduokite žetonų klausimus, sugeneruokite įterpimus iš klausimų ir įdėkite juos į duomenų rinkinį kaip
question_embeddings
.model = AutoModel.from_pretrained(MODEL)
def embed(batch): sentence_embs = model( input_ids=batch['input_ids'], token_type_ids=batch['token_type_ids'], attention_mask=batch['attention_mask'] )[0] input_mask_expanded = batch['attention_mask'].unsqueeze(-1).expand(sentence_embs.size()).float() batch['question_embedding'] = sum(sentence_embs * input_mask_expanded, 1) / clamp(input_mask_expanded.sum(1), min=1e-9) return batch
data_dataset = data_dataset.map(embed, remove_columns=['input_ids', 'token_type_ids', 'attention_mask'], batched = True, batch_size=INFERENCE_BATCH_SIZE)
- Įtraukite klausimus į kolekciją.
def insert_function(batch): insertable = [ batch['question'], [x[:995] + '...' if len(x) > 999 else x for x in batch['answer']], batch['question_embedding'].tolist() ] collection.insert(insertable)
data_dataset.map(insert_function, batched=True, batch_size=64) collection.flush()
Išvestis atrodys taip:
Dataset({ features: ['id', 'title', 'context', 'question', 'answer', 'input_ids', 'token_type_ids', 'attention_mask', 'question_embedding'], num_rows: 99 })
Atsakymų generavimas
Šiame skyriuje sužinosite, kaip pateikti raginimą, suaktyvinti ir įterpti raginimą, kad būtų galima atlikti panašumo paiešką, ir sugeneruoti tinkamiausius atsakymus.
- Sukurkite raginimų duomenų rinkinį, galite pakeisti klausimą bet kokiu tinkintu raginimu, taip pat galite pateikti klausimų skaičių raginimui.
questions = {'question':['When was maths invented?']} question_dataset = Dataset.from_dict(questions)
- Pažymėkite ir įdėkite raginimą.
question_dataset = question_dataset.map(tokenize_question, batched = True, batch_size=TOKENIZATION_BATCH_SIZE)
question_dataset.set_format('torch', columns=['input_ids', 'token_type_ids', 'attention_mask'], output_all_columns=True)
question_dataset = question_dataset.map(embed, remove_columns=['input_ids', 'token_type_ids', 'attention_mask'], batched = True, batch_size=INFERENCE_BATCH_SIZE)
- Apibrėžkite
search
funkcija, kuri atlieka paieškos operacijas naudodama anksčiau sukurtus įterpimus. Gauta informacija suskirstyta į sąrašus ir grąžinama kaip žodynas.def search(batch): res = collection.search(batch['question_embedding'].tolist(), anns_field='original_question_embedding', param = {}, output_fields=['answer', 'original_question'], limit = LIMIT) overall_id = [] overall_distance = [] overall_answer = [] overall_original_question = [] for hits in res: ids = [] distance = [] answer = [] original_question = [] for hit in hits: ids.append(hit.id) distance.append(hit.distance) answer.append(hit.entity.get('answer')) original_question.append(hit.entity.get('original_question')) overall_id.append(ids) overall_distance.append(distance) overall_answer.append(answer) overall_original_question.append(original_question) return { 'id': overall_id, 'distance': overall_distance, 'answer': overall_answer, 'original_question': overall_original_question }
- Atlikite paieškos operaciją taikydami anksčiau apibrėžtą
search
funkcijaquestion_dataset
.question_dataset = question_dataset.map(search, batched=True, batch_size = 1) for x in question_dataset: print() print('Question:') print(x['question']) print('Answer, Distance, Original Question') for x in zip(x['answer'], x['distance'], x['original_question']): print(x)
Išvestis atrodys taip:
Question: When was maths invented? Answer, Distance, Original Question ('until 1870', tensor(33.3018), 'When did the Papal States exist?') ('October 1992', tensor(34.8276), 'When were free elections held?') ('1787', tensor(36.0596), 'When was the Tower constructed?') ('Poland, Bulgaria, the Czech Republic, Slovakia, Hungary, Albania, former East Germany and Cuba', tensor(38.3254), 'Where was Russian schooling mandatory in the 20th century?') ('6,000 years', tensor(41.9444), 'How old did biblical scholars think the Earth was?') ('1992', tensor(42.2079), 'In what year was the Premier League created?') ('1981', tensor(44.7781), "When was ZE's Mutant Disco released?") ('Medieval Latin', tensor(46.9699), "What was the Latin of Charlemagne's era later known as?") ('taxation', tensor(49.2372), 'How did Hobson argue to rid the world of imperialism?') ('light weight, relative unbreakability and low surface noise', tensor(49.5037), "What were advantages of vinyl in the 1930's?")
Aukščiau pateiktoje išvestyje 10 artimiausių atsakymų atspausdinami mažėjančia tvarka pagal jūsų užduotą klausimą kartu su pradiniais klausimais, kuriems tie atsakymai priklauso, išvestis taip pat rodo tenzoriaus reikšmes su kiekvienu atsakymu, mažesnė tenzoriaus reikšmė reiškia, kad atsakymas yra tikslesnis už tavo užduotą klausimą.
Išvada
Šiame straipsnyje sužinojote, kaip sukurti atsakymų į klausimus sistemą naudojant HuggingFace duomenų rinkinį ir Milvus duomenų bazę. Vadovėlyje buvo nurodyta, kaip atlikti įterpimus iš duomenų rinkinio, saugoti juos į rinkinį ir atlikti panašumų paiešką, kad surastumėte tinkamiausius raginimo atsakymus, sukurdami pateikto klausimo įterpimą ir apskaičiuodami tenzorius.
Tai yra Vultr remiamas straipsnis. Vultr yra didžiausia pasaulyje privati debesų kompiuterijos platforma. Kūrėjų pamėgta „Vultr“ aptarnavo daugiau nei 1,5 mln. klientų 185 šalyse, naudodama lanksčius, keičiamo dydžio, pasaulinius „Cloud Compute“, „Cloud GPU“, „Bare Metal“ ir „Cloud Storage“ sprendimus. Išmokti daugiau apie Vultr.