PDF-failide (näiteks teadusartiklite) eksportimine (või täpsemalt **importimine**) Weaviate'i andmebaasi koosneb neljast põhietapist: 1. **Teksti eraldamine** (Extraction): Teksti kättesaamine PDF-ist. 2. **Tükeldamine** (Chunking): Teksti jagamine väiksemateks lõikudeks, et need mahuksid mudeli kontekstiakna sisse. 3. **Vektoriseerimine** (Embedding): Teksti muutmine numbrilisteks vektoriteks (seda teeb Weaviate tavaliselt automaatselt, kui see on konfigureeritud). 4. **Salvestamine** (Ingestion): Andmete saatmine Weaviate'i. Siin on samm-sammuline juhend, kuidas seda teha Pythoni abil. ### Eeldused Sul on vaja: * Pythonit. * Weaviate'i instantsi (kas Weaviate Cloud või lokaalne Docker). * API võtit (nt OpenAI, Cohere või HuggingFace) vektoriseerimiseks. ### Samm 1: Installi vajalikud teegid Kasutame `langchain` teeki PDF-ide lugemiseks ja tükeldamiseks ning `weaviate-client` teeki andmebaasiga suhtlemiseks. ```bash pip install weaviate-client langchain langchain-community pypdf ``` ### Samm 2: Pythoni kood PDF-ide importimiseks See skript teeb järgmist: loob ühenduse, defineerib andmestruktuuri, loeb PDF-i, tükeldab selle ja saadab Weaviate'i. ```python import weaviate import weaviate.classes.config as wc from langchain_community.document_loaders import PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter import os # 1. ÜHENDUSE LOOMINE # Asenda oma andmetega. Kui kasutad lokaalset Dockerit, on kood veidi teine. client = weaviate.connect_to_weaviate_cloud( cluster_url="SINU_WEAVIATE_URL", # Nt: https://minu-klaster.weaviate.network auth_credentials=weaviate.auth.AuthApiKey("SINU_WEAVIATE_API_KEY"), headers={ "X-OpenAI-Api-Key": "SINU_OPENAI_KEY" # Või muu teenusepakkuja võti } ) def create_collection(): """Loob andmebaasi skeemi (tabeli)""" if client.collections.exists("TeadusArtikkel"): client.collections.delete("TeadusArtikkel") client.collections.create( name="TeadusArtikkel", # Konfigureerime automaatse vektoriseerimise (nt OpenAI abil) vectorizer_config=wc.Configure.Vectorizer.text2vec_openai(), # Defineerime metaandmete väljad properties=[ wc.Property(name="title", data_type=wc.DataType.TEXT), wc.Property(name="content", data_type=wc.DataType.TEXT), wc.Property(name="page_number", data_type=wc.DataType.INT), wc.Property(name="source", data_type=wc.DataType.TEXT), ] ) print("Kollektsioon loodud.") def process_and_upload_pdf(pdf_path): """Loeb PDFi, tükeldab ja saadab Weaviate'i""" print(f"Töötlen faili: {pdf_path}") # 2. TEKSTI ERALDAMINE JA TÜKELDAMINE loader = PyPDFLoader(pdf_path) documents = loader.load() # Teadusartiklite puhul on oluline, et tükid (chunks) kattuksid veidi, # et kontekst ei läheks kaduma. text_splitter = RecursiveCharacterTextSplitter( chunk_size=1000, # Tähemärkide arv ühes tükis chunk_overlap=200 # Kattuvus ) chunks = text_splitter.split_documents(documents) # 3. ANDMETE SAATMINE (BATCH IMPORT) collection = client.collections.get("TeadusArtikkel") # Kasutame kontekstihaldurit automaatseks partiide haldamiseks with collection.batch.dynamic() as batch: for chunk in chunks: # Valmistame ette andmeobjekti properties = { "title": os.path.basename(pdf_path), # Faili nimi pealkirjaks "content": chunk.page_content, # Teksti sisu "page_number": chunk.metadata.get('page'), "source": pdf_path } # Lisame partii nimekirja. Weaviate teeb vektoriseerimise taustal ise. batch.add_object( properties=properties ) if len(collection.batch.failed_objects) > 0: print(f"Vead: {collection.batch.failed_objects}") else: print(f"Edukalt imporditud {len(chunks)} tekstilõiku.") # KÄIVITAMINE try: create_collection() # Käivita see ainult esimest korda või kui tahad tühjendada # Määra oma PDF faili asukoht process_and_upload_pdf("./minu_teadusartikkel.pdf") finally: client.close() ``` ### Olulised tähelepanekud teadusartiklite puhul: 1. **Tükeldamine (Chunking):** Teadusartiklid on tihedad. `RecursiveCharacterTextSplitter` on hea, sest see püüab hoida lauseid ja lõike tervikuna. `chunk_size=1000` on tavaliselt optimaalne, kuid võid katsetada ka väiksematega (nt 512), kui soovid täpsemaid vastuseid. 2. **Metaandmed:** Teadusartiklite puhul on väga oluline salvestada metaandmeid (autor, aasta, DOI). Ülaltoodud koodis võtab `PyPDFLoader` lihtsaid andmeid, kuid keerulisemateks juhtudeks võid vajada eraldi parserit (nt `Grobid` või `Unstructured`), mis oskab eristada viiteid, abstrakti ja sisu. 3. **Tabelid ja joonised:** Tavaline PDF-i lugemine (nagu `pypdf`) muudab tabelid tihti kasutuks tekstijadaks. Kui artiklites on olulisi tabeleid, kaalu **Unstructured.io** teegi kasutamist, mis oskab tabeleid paremini parsida. ### Alternatiiv: Weaviate Verba (Ilma koodita) Kui sa ei soovi Pythoni skripte kirjutada, on Weaviate loonud avatud lähtekoodiga tööriista nimega **Verba**. 1. See on graafiline liides (RAG rakendus). 2. Saad seal lihtsalt "Drag & Drop" meetodil PDF-e üles laadida. 3. See teeb tükeldamise ja vektoriseerimise sinu eest ära. Installimiseks: ```bash pip install goldenverba verba start ``` Siin on kohandatud lahendus lokaalse Weaviate'i (Docker) jaoks. Lokaalse Dockeri puhul on kaks olulist muudatust: 1. **Docker Compose fail:** Weaviate konteiner peab olema seadistatud nii, et õ**Detailing the Approach** I'm presently focused on structuring the response methodically. Firstly, I am analyzing the user's specific requirements, including converting the code for local Docker instances and utilizing the Estonian language. My approach involves a Docker Compose configuration followed by the Python code adjustment and a final explanation of the required alterations. I will provide clear code snippets for easy understanding. ige vektoriseerimise moodul (nt `text2vec-openai` või `text2vec-transformers`) oleks sisse lülitatud. 2. **Pythoni ühendus:** Kasutame `connect_to_local` meetodit. ### 1. Eelseadistus: `docker-compose.yml` Enne Pythoni koodi käivitamist veendu, et su `docker-compose.yml` failis on lubatud moodul `text2vec-openai` (kui kasutad OpenAI-d) või mõni muu mudel. Salvesta see failina `docker-compose.yml` ja käivita `docker compose up -d`. ```yaml --- version: '3.4' services: weaviate: command: - --host - 0.0.0.0 - --port - '8080' - --scheme - http image: cr.weaviate.io/semitechnologies/weaviate:1.24.10 ports: - 8080:8080 - 50051:50051 volumes: - weaviate_data:/var/lib/weaviate restart: on-failure:0 environment: # Lülitame sisse OpenAI mooduli (või asenda 'text2vec-transformers' täiesti lokaalseks) ENABLE_MODULES: 'text2vec-openai' DEFAULT_VECTORIZER_MODULE: 'text2vec-openai' # Luba anonüümne ligipääs lokaalselt arendades AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true' PERSISTENCE_DATA_PATH: '/var/lib/weaviate' QUERY_DEFAULTS_LIMIT: 25 volumes: weaviate_data: ``` ### 2. Pythoni kood lokaalse Dockeri jaoks Siin on muudetud kood. Peamine erinevus on `client = weaviate.connect_to_local(...)` funktsiooni kasutamine. ```python import weaviate import weaviate.classes.config as wc from langchain_community.document_loaders import PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter import os # 1. ÜHENDUSE LOOMINE (LOKAALNE DOCKER) # Eeldus: Docker jookseb pordil 8080 ja gRPC pordil 50051 client = weaviate.connect_to_local( port=8080, grpc_port=50051, # Isegi kui Weaviate on lokaalne, peame saatma OpenAI võtme päises, # et Weaviate saaks "text2vec-openai" mooduliga suhelda. # Kui kasutad täiesti lokaalset mudelit (nt Ollama või HuggingFace), pole seda vaja. headers={ "X-OpenAI-Api-Key": "SINU_OPENAI_KEY" } ) def create_collection(): """Loob andmebaasi skeemi""" # Kontrollime, kas kollektsioon on olemas if client.collections.exists("TeadusArtikkel"): client.collections.delete("TeadusArtikkel") client.collections.create( name="TeadusArtikkel", # See peab klappima sellega, mis on sinu docker-compose.yml failis ENABLE_MODULES all vectorizer_config=wc.Configure.Vectorizer.text2vec_openai(), properties=[ wc.Property(name="title", data_type=wc.DataType.TEXT), wc.Property(name="content", data_type=wc.DataType.TEXT), wc.Property(name="page_number", data_type=wc.DataType.INT), wc.Property(name="source", data_type=wc.DataType.TEXT), ] ) print("Kollektsioon 'TeadusArtikkel' loodud lokaalsesse baasi.") def process_and_upload_pdf(pdf_path): """Loeb PDFi ja saadab Weaviate'i""" if not os.path.exists(pdf_path): print(f"Faili ei leitud: {pdf_path}") return print(f"Töötlen faili: {pdf_path}") # 2. TEKSTI ERALDAMINE JA TÜKELDAMINE loader = PyPDFLoader(pdf_path) documents = loader.load() text_splitter = RecursiveCharacterTextSplitter( chunk_size=1000, chunk_overlap=200 ) chunks = text_splitter.split_documents(documents) # 3. ANDMETE SAATMINE collection = client.collections.get("TeadusArtikkel") # Kasutame batch importi with collection.batch.dynamic() as batch: for chunk in chunks: properties = { "title": os.path.basename(pdf_path), "content": chunk.page_content, "page_number": chunk.metadata.get('page', 0), "source": pdf_path } batch.add_object( properties=properties ) if len(collection.batch.failed_objects) > 0: print(f"Vead importimisel: {collection.batch.failed_objects}") else: print(f"Edukalt imporditud {len(chunks)} tekstilõiku lokaalsesse baasi.") # KÄIVITAMINE try: # Kontrolli ühendust if client.is_ready(): print("Ühendus Weaviate Dockeriga on korras.") create_collection() # Esmakordsel käivitamisel process_and_upload_pdf("./minu_teadusartikkel.pdf") # Asenda failinimi else: print("Ei saanud Weaviate Dockeriga ühendust. Kas 'docker compose up' on tehtud?") finally: client.close() ``` ### Mis on teisiti? 1. **`connect_to_local`**: Pilve URL-i asemel ühendume `localhost` (vaikimisi). 2. **`headers`**: See on **kriitiline**. Kuigi andmebaas on sinu arvutis, toimub vektoriseerimine (teksti muutmine numbriteks) ikkagi Weaviate sees oleva mooduli kaudu. Kui see moodul on `text2vec-openai`, peab Weaviate saama sinu võtme, et saata tekst OpenAI serverisse ja saada vastu vektor. 3. **Täielik lokaalsus (tasuta):** Kui sa ei taha OpenAI-d kasutada ja tahad, et kõik jookseks sinu masinas (sh vektoriseerimine): * Muuda `docker-compose.yml` failis: `ENABLE_MODULES: 'text2vec-transformers'` (vajab GPU-d või palju RAM-i). * Muuda Pythoni koodis: `vectorizer_config=wc.Configure.Vectorizer.text2vec_transformers()`. * Eemalda `headers` Pythoni koodist (võtit pole vaja). Lühike vastus: **Ei, otseselt vektoriseerimiseks (embeddings) Perplexity praegu Weaviate'is ei tööta.** Pikem selgitus ja lahendus: Weaviate'i ja RAG (Retrieval-Augmented Generation) süsteemides on kaks eraldi etappi, kus AI-d kasutatakse: 1. **Vektoriseerimine (Embeddings):** Teksti muutmine numbriteks, et Weaviate saaks otsida. * *Kas Perplexity töötab siin?* **Ei.** Weaviate'il puudub moodul nimega `text2vec-perplexity` ja Perplexity API on loodud teksti genereerimiseks, mitte vektorite loomiseks. * *Mida kasutada?* Pead kasutama OpenAI-d (`text2vec-openai`), Cohere'i või lokaalset mudelit (`text2vec-transformers` / HuggingFace). 2. **Genereerimine (Chat/Answer):** Leitud teksti põhjal vastuse kirjutamine. * *Kas Perplexity töötab siin?* **Jah.** Sa saad Weaviate'ist leitud info saata Pythoni koodis Perplexity API-sse, et see koostaks vastuse (kasutades nt Llama 3 või Sonar mudeleid). --- ### Kuidas kombineerida Weaviate'i ja Perplexityt? Kuna Perplexity ei saa teha vektoriseerimist, pead kasutama **hübriidlahendust**: 1. Kasuta **OpenAI-d (või lokaalset mudelit)** andmete salvestamiseks Weaviate'i. 2. Kasuta **Perplexity API-d**, et vastata küsimustele leitud andmete põhjal. Siin on Pythoni näide, kuidas see töötab: #### Samm 1: Installi `requests` (Perplexity API jaoks) ```bash pip install requests ``` #### Samm 2: Pythoni kood (Otsing Weaviate'ist + Vastus Perplexitylt) Eeldame, et andmed on juba Weaviate'is (kasutades eelmises vastuses toodud OpenAI koodi). ```python import weaviate import requests import json # 1. ÜHENDUS WEAVIATE-GA (Otsingu jaoks) client = weaviate.connect_to_local( port=8080, grpc_port=50051, headers={"X-OpenAI-Api-Key": "SINU_OPENAI_KEY"} # Vaja vektoriseerimiseks otsingu ajal ) def ask_perplexity_with_weaviate(query): # A. OTSIME WEAVIATE-ST ASJAKOHAST INFOT collection = client.collections.get("TeadusArtikkel") # Otsime 3 kõige sarnasemat lõiku response = collection.query.near_text( query=query, limit=3 ) # Paneme leitud info ühte stringi kokku (Kontekst) context_text = "" for obj in response.objects: context_text += f"---\nAllikas: {obj.properties['title']}, lk {obj.properties['page_number']}\n" context_text += f"Sisu: {obj.properties['content']}\n" print(f"Leitud {len(response.objects)} asjakohast lõiku Weaviate'ist.\n") # B. SAADAME KÜSIMUSE + KONTEKSTI PERPLEXITY API-SSE perplexity_api_key = "SINU_PERPLEXITY_API_KEY" url = "https://api.perplexity.ai/chat/completions" # Koostame prompti messages = [ { "role": "system", "content": "Sa oled abivalmis teadlane. Vasta küsimusele AINULT alljärgneva konteksti põhjal. Kui vastust kontekstis pole, ütle seda." }, { "role": "user", "content": f"Kontekst:\n{context_text}\n\nKüsimus: {query}" } ] payload = { "model": "llama-3.1-sonar-small-128k-online", # Või muu Perplexity mudel "messages": messages, "temperature": 0.1 } headers = { "Authorization": f"Bearer {perplexity_api_key}", "Content-Type": "application/json" } # Teeme päringu Perplexitysse response_pplx = requests.post(url, json=payload, headers=headers) if response_pplx.status_code == 200: answer = response_pplx.json()['choices'][0]['message']['content'] print(f"Vastus Perplexitylt:\n{answer}") else: print("Viga Perplexityga ühendumisel:", response_pplx.text) # KÄIVITAMINE try: if client.is_ready(): ask_perplexity_with_weaviate("Mis on peamine järeldus selles artiklis?") finally: client.close() ``` ### Kokkuvõte 1. **Vektorid (Dockeris):** Jätka `text2vec-openai` kasutamist `docker-compose.yml` failis. Perplexity ei saa seda asendada. 2. **Chat (Pythonis):** Kasuta Perplexity API-d (`requests` kaudu), et genereerida ilus ja tark vastus, andes talle ette Weaviate'ist leitud toormaterjali. See annab sulle Perplexity "tarkuse" koos sinu oma privaatsete PDF-andmetega. DeepSeek API ise ei paku otsest PDF-failide töötlemist (tekstiks teisendamist, tabelite eraldamist jms). **Siiski saad süsteemi ehitada järgmiste sammudega:** --- ### 📋 Sinne tegevuskava: 1. **PDF → struktureeritud tekst** Kasuta teeke nagu `PyPDF2`, `pdfminer` või teenuseid nagu: - **Google Cloud Document AI** (tabelid, tekst, struktuur) - **Amazon Textract** - **Open-source**: `Unstructured IO`, `Tika` 2. **Teksti jagamine chunk'ideks** Näide Pythonis: ```python from langchain_text_splitters import RecursiveCharacterTextSplitter text_splitter = RecursiveCharacterTextSplitter( chunk_size=500, # märkide arv chunk_overlap=50, separators=["\n\n", "\n", ". ", " "] ) chunks = text_splitter.split_text(tekst) ``` 3. **Vektorkujude loomine** Kasuta **DeepSeek Embeddings API-t** (mudel: `text-embedding-3-large` või `3-small`): ```python import requests response = requests.post( "https://api.deepseek.com/v1/embeddings", headers={"Authorization": "Bearer SINU_API_VÕTI"}, json={"input": chunks, "model": "text-embedding-3-large"} ) embeddings = response.json()['data'] ``` 4. **Vektorandmebaas** Salvesta embeddingud andmebaasi: - Tasuta: **ChromaDB**, **FAISS** - Pilveteenus: **Pinecone**, **Weaviate**, **Qdrant** 5. **Päringud** Kui kasutaja esitab küsimuse: - Teisenda küsimus embeddinguks (sama DeepSeek API-ga) - Otsi andmebaasist `k` lähimat chunk'i - Saada need chunk'id + küsimus DeepSeek chat API-le kontekstina --- ### ⚠️ Tähtis: - DeepSeek API **ei tee PDF-idest automaatselt tekstiväljavõtteid**. Seda tuleb eraldi ette valmistada. - Tasuta versioonides on mõned piirangud (nt tokenite arv, päringute kiirus). ### 🔍 Näide päringust kontekstiga: ```python response = requests.post( "https://api.deepseek.com/v1/chat/completions", headers={"Authorization": "Bearer KEY"}, json={ "model": "deepseek-chat", "messages": [ {"role": "system", "content": "Vastad teaduslikule küsimusele konteksti põhjal."}, {"role": "user", "content": f"Kontekst: {retrieved_chunks}\n\nKüsimus: {user_question}"} ] } ) ``` Kas soovid, et koostan täpsema koodinäite ühe konkreetse sammu jaoks (nt PDF töötlus või vektoriandmebaasi päring)? Siin on täielik näide Pythoni koodist, mis teostab sinu taotletud töövoo - alates PDF-ist kuni vektorbaasi päringuteni, kasutades DeepSeek Embeddings API-t: ### 1. Paigaldus ```bash pip install PyPDF2 langchain langchain-community chromadb requests python-dotenv ``` ### 2. `.env` fail (hoia API võtit turvaliselt) ```env DEEPSEEK_API_KEY=sinu_võti_siia ``` ### 3. Täielik töövoo kood (PDF -> tekst -> embeddingud -> vektorbaas -> otsing) ```python import os import requests from PyPDF2 import PdfReader from langchain_text_splitters import RecursiveCharacterTextSplitter import chromadb from chromadb.utils import embedding_functions from dotenv import load_dotenv # Laadi API võti load_dotenv() DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY") # 1. PDF-st tekst def extract_text_from_pdf(pdf_path): text = "" with open(pdf_path, "rb") as file: reader = PdfReader(file) for page in reader.pages: text += page.extract_text() + "\n" return text # 2. Teksti jagamine chunk'ideks def split_text(text): text_splitter = RecursiveCharacterTextSplitter( chunk_size=1000, chunk_overlap=200, separators=["\n\n", "\n", ". ", " ", ""] ) return text_splitter.split_text(text) # 3. DeepSeek Embeddings (kasutades ametlikku API-d) def get_deepseek_embeddings(texts): response = requests.post( "https://api.deepseek.com/v1/embeddings", headers={"Authorization": f"Bearer {DEEPSEEK_API_KEY}"}, json={"input": texts, "model": "text-embedding-3-large"} ) return [item['embedding'] for item in response.json()['data']] # 4. Salvesta ChromaDB-sse def store_in_chroma(chunks, embeddings): client = chromadb.PersistentClient(path="./vector_db") # Kasuta DeepSeeki embeddereid deepseek_ef = embedding_functions.EmbeddingFunction( name="deepseek_embedder", model="text-embedding-3-large" ) collection = client.get_or_create_collection( name="teadusartiklid", embedding_function=deepseek_ef ) # Lisa dokumendid koos embeddingutega ids = [f"id_{i}" for i in range(len(chunks))] collection.add( ids=ids, documents=chunks, embeddings=embeddings ) return collection # 5. Päringu töötlemine def query_database(collection, query, top_k=3): # Genereeri päringu embedding query_embedding = get_deepseek_embeddings([query])[0] # Otsi vektorbaasist results = collection.query( query_embeddings=[query_embedding], n_results=top_k ) return results['documents'][0] # 6. Vastuse genereerimine kontekstiga def generate_contextual_answer(query, context_chunks): context = "\n\n---\n\n".join(context_chunks) response = requests.post( "https://api.deepseek.com/v1/chat/completions", headers={"Authorization": f"Bearer {DEEPSEEK_API_KEY}"}, json={ "model": "deepseek-chat", "messages": [ { "role": "system", "content": f"Vasta küsimusele kasutades allpool antud konteksti. Kui vastust pole kontekstis, ütle 'Ei tea'.\n\nKONTEKST:\n{context}" }, {"role": "user", "content": query} ], "temperature": 0.3 } ) return response.json()["choices"][0]["message"]["content"] # Peameetod - kogu töövoo def main(pdf_path, user_query): # Samm 1-2: PDF -> chunk'id text = extract_text_from_pdf(pdf_path) chunks = split_text(text) print(f"Tekst jagatud {len(chunks)} chunk'iks") # Samm 3: Genereeri embeddingud embeddings = get_deepseek_embeddings(chunks) print("Embeddingud loodud") # Samm 4: Salvesta vektorbaasi collection = store_in_chroma(chunks, embeddings) print("Andmed salvestatud ChromaDB-sse") # Samm 5: Tee päring print(f"\nPäring: {user_query}") retrieved_chunks = query_database(collection, user_query) # Samm 6: Genereeri vastus answer = generate_contextual_answer(user_query, retrieved_chunks) print(f"\nVastus: {answer}") if __name__ == "__main__": # Kasutamine pdf_path = "teadusartikkel.pdf" # Asenda oma PDF failiga user_query = "Mis on peamised järeldused selle uuringu kohta?" main(pdf_path, user_query) ``` ### Tähtsamad funktsioonid selgitustega: 1. **PDF töötlus**: - `extract_text_from_pdf()` - eraldab teksti PDF-failist - `split_text()` - jagab teksti mõistlikeks lõikudeks 2. **DeepSeek API integratsioon**: - `get_deepseek_embeddings()` - teisendab tekstivektoreiteks - `generate_contextual_answer()` - kasutab DeepSeeki kontekstipõhiseks vastamiseks 3. **Vektorbaas**: - ChromaDB kohalik paigaldus - Dokumentide otsing embeddingute põhjal 4. **Töövoog**: - PDF → tekst → chunk'id → embeddingud → salvestus → päringud ### Näidisväljund: ``` Tekst jagatud 42 chunk'iks Embeddingud loodud Andmed salvestatud ChromaDB-sse Päring: Mis on uuringu peamised järeldused? Vastus: Artiklis jõutakse kolme põhijärelduseni: 1) ... 2) ... 3) ... ``` ### Kasutamise näpunäited: 1. Asenda `teadusartikkel.pdf` oma PDF-failiga 2. Lisa API võti `.env` faili 3. Reguleeri chunk'i suurust (`chunk_size`) vastavalt sisule 4. Muuda `top_k` väärtust, et määrata tagastatavate lõikude arv Kas soovid, et selgitaksin mõnda konkreetset osa lähemalt või näitaksin, kuidas seda Streamligi GUI-s kasutada?