| from tqdm import tqdm |
| import os |
| import chardet |
| import numpy as np |
| from pinecone import Pinecone |
| from langchain.docstore.document import Document as LangchainDocument |
| from langchain_text_splitters import RecursiveCharacterTextSplitter |
| from langchain_community.embeddings import OpenAIEmbeddings |
| import spacy |
|
|
|
|
| |
| DATA_DIR = "data" |
| JOURNAL_DIR = "journals" |
|
|
| |
| OPENAI_API_KEY = os.environ["OPENAI_API_KEY"] |
| PINECONE_API_KEY = os.environ["PINECONE_API_KEY"] |
| PINECONE_INDEX = os.environ["PINECONE_INDEX"] |
|
|
| |
| pc = Pinecone(api_key=PINECONE_API_KEY) |
| index = pc.Index(PINECONE_INDEX) |
|
|
| |
| embedding_model = OpenAIEmbeddings( |
| model="text-embedding-3-small", |
| api_key=OPENAI_API_KEY |
| ) |
|
|
| nlp = spacy.load("xx_sent_ud_sm") |
|
|
| def sentence_overlap_chunks(text, chunk_size=2000): |
| doc = nlp(text) |
| sentences = [sent.text.strip() for sent in doc.sents] |
| |
| chunks = [] |
| i = 0 |
|
|
| while i < len(sentences): |
| chunk = [] |
| length = 0 |
| start_i = i |
|
|
| |
| while i < len(sentences) and length + len(sentences[i]) <= chunk_size: |
| chunk.append(sentences[i]) |
| length += len(sentences[i]) + 1 |
| i += 1 |
|
|
| |
| if chunk: |
| try: |
| chunk = " ".join(chunk) |
| chunks.append(chunk) |
| i+=1 |
| except: |
| print("can't process line.") |
| i+=4 |
|
|
| |
| i = i - 3 |
|
|
| return chunks |
|
|
|
|
| |
| for filename in os.listdir(DATA_DIR): |
| if filename.endswith(".pdf"): |
| filepath = os.path.join(DATA_DIR, filename) |
| namespace = "ns4" |
|
|
| print(f"Processing {filename} → namespace: {namespace}") |
|
|
| reader = fitz.open(filepath) |
| content = "" |
| for page in reader: |
| text = page.get_text() |
| if text: |
| content += text + "\n" |
|
|
| |
| docs_processed = sentence_overlap_chunks(content) |
| |
| |
| upsert_data = [] |
| for i, chunk in tqdm(enumerate(docs_processed), total=len(docs_processed), desc="Embedding chunks"): |
| vector = embedding_model.embed_query(chunk) |
| upsert_data.append({ |
| "id": f"{filename[:-4]}_chunk_{i}", |
| "values": vector, |
| "metadata": { |
| "text": chunk, |
| "source": filename |
| } |
| }) |
|
|
| |
| print(f"⬆️ Upserting {len(upsert_data)} vectors to namespace '{namespace}'...") |
| index.upsert(vectors=upsert_data, namespace=namespace) |
| print(f"✅ Done with {filename}\n") |
|
|
| |
| for filename in os.listdir(JOURNAL_DIR): |
| if filename.endswith(".txt"): |
| filepath = os.path.join(JOURNAL_DIR, filename) |
| namespace = filename[:-4] |
|
|
| print(f"Processing {filename} → namespace: {namespace}") |
|
|
| |
| with open(filepath, "rb") as f: |
| raw_data = f.read() |
| encoding = chardet.detect(raw_data)['encoding'] |
|
|
| |
| with open(filepath, "r", encoding=encoding) as f: |
| content = f.read() |
|
|
| |
| docs_processed = sentence_overlap_chunks(content, chunk_size=400) |
| |
| |
| upsert_data = [] |
| for i, chunk in tqdm(enumerate(docs_processed), total=len(docs_processed), desc="Embedding chunks"): |
| vector = embedding_model.embed_query(chunk) |
| upsert_data.append({ |
| "id": f"{namespace}_chunk_{i}", |
| "values": vector, |
| "metadata": { |
| "text": chunk, |
| "source": filename |
| } |
| }) |
|
|
| |
| print(f"⬆️ Upserting {len(upsert_data)} vectors to namespace '{namespace}'...") |
| index.upsert(vectors=upsert_data, namespace=namespace) |
| print(f"✅ Done with {filename}\n") |