Dzielenie semantyczne na podstawie podobieństwa embeddingów
Zaimplementuj semantyczne dzielenie tekstu, rozdzielając go w punktach największego dystansu semantycznego między kolejnymi zdaniami i zachowując spójność tematyczną treści.
Dzielenie semantyczne na podstawie podobieństwa embeddingów to bezpłatna lekcja AI Engineering Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Engineering Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Engineering Academy zawiera 4 lekcji w sumie.
Czym jest dzielenie semantyczne?
Dzielenie semantyczne to technika rozdzielania tekstu w punktach, w których temat znacząco się zmienia, zamiast po ustalonej liczbie znaków. Zamiast pytać „czy osiągnęliśmy 500 tokenów?”, zadaje pytanie „czy następne zdanie należy do tego samego tematu co bieżący fragment?” — i wykorzystuje podobieństwo osadzeń, aby na nie odpowiedzieć.
Główna idea: odległość między osadzeniami
Algorytm działa poprzez utworzenie osadzenia dla każdego zdania (lub małej grupy zdań) i obliczenie podobieństwa cosinusowego między osadzeniami kolejnych zdań. Gdy podobieństwo gwałtownie spada — co oznacza zmianę tematu — algorytm wstawia granicę fragmentu. Zdania omawiające to samo pojęcie pozostają razem w jednym fragmencie.
Krok 1: Osadzenia na poziomie zdań
Pierwszym krokiem jest podzielenie dokumentu na pojedyncze zdania za pomocą tokenizera zdań, a następnie utworzenie osadzenia każdego zdania przy użyciu szybkiego modelu osadzeń. Potrzebujesz osadzeń na poziomie zdań, a nie dokumentów, aby wykrywać lokalne zmiany tematów podczas przechodzenia przez tekst.
from openai import OpenAI
from nltk.tokenize import sent_tokenize
import numpy as np
client = OpenAI()
def embed_sentences(text):
sentences = sent_tokenize(text)
response = client.embeddings.create(
model='text-embedding-3-small',
input=sentences
)
vectors = [item.embedding for item in response.data]
return sentences, np.array(vectors)Krok 2: Obliczanie podobieństwa sąsiednich zdań
Gdy masz już osadzenia zdań, oblicz podobieństwo cosinusowe każdej kolejnej pary: zdania i oraz zdania i+1. Wynikiem jest lista wartości podobieństwa, po jednej dla każdej granicy między zdaniami. Niskie wartości wskazują, że sąsiednie zdania dotyczą różnych tematów — są to potencjalne miejsca podziału.
def cosine_similarity_adjacent(vectors):
similarities = []
for i in range(len(vectors) - 1):
a = vectors[i]
b = vectors[i + 1]
sim = np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
similarities.append(sim)
return similaritiesKrok 3: Wykrywanie punktów podziału
Punkt podziału to granica między zdaniami, na której podobieństwo spada poniżej ustalonego progu. Możesz użyć stałego progu (np. 0,6) albo progu opartego na percentylu, który dostosowuje się do dokumentu — na przykład dzielić tekst za każdym razem, gdy podobieństwo spadnie poniżej 25. percentyla wszystkich wartości podobieństwa w tym dokumencie.
def find_breakpoints(similarities, percentile=25):
threshold = np.percentile(similarities, percentile)
breakpoints = []
for i, sim in enumerate(similarities):
if sim < threshold:
breakpoints.append(i + 1) # split AFTER sentence i
return breakpointsKrok 4: Składanie fragmentów
Po zidentyfikowaniu punktów podziału możesz złożyć fragmenty, łącząc kolejne zdania znajdujące się między punktami podziału. Każdy wynikowy fragment zawiera spójną sekwencję zdań dotyczących tego samego tematu. Granice fragmentów pokrywają się z naturalnymi zmianami tematów w oryginalnym dokumencie.
def assemble_chunks(sentences, breakpoints):
chunks = []
start = 0
for bp in breakpoints:
chunk = ' '.join(sentences[start:bp])
chunks.append(chunk)
start = bp
chunks.append(' '.join(sentences[start:])) # last chunk
return chunksPełny przykład dzielenia semantycznego
Połączmy wszystkie elementy w jedną funkcję: utwórz osadzenia zdań, oblicz podobieństwa sąsiednich zdań, znajdź punkty podziału i zbuduj fragmenty. Wynikiem jest lista semantycznie spójnych segmentów tekstu, gotowych do osadzenia jako całe fragmenty i zapisania w bazie wektorowej.
def semantic_chunk(text, percentile=25):
sentences, vectors = embed_sentences(text)
similarities = cosine_similarity_adjacent(vectors)
breakpoints = find_breakpoints(similarities, percentile)
chunks = assemble_chunks(sentences, breakpoints)
return chunks
chunks = semantic_chunk(my_document)
print(f'Produced {len(chunks)} semantic chunks')
for i, c in enumerate(chunks):
print(f'Chunk {i+1}: {len(c)} chars')Wybór progu percentylowego
Próg percentylowy określa szczegółowość podziału na fragmenty. Niski percentyl (np. 10.) oznacza, że tekst jest dzielony tylko przy dużych zmianach tematu, co prowadzi do powstania mniejszej liczby dłuższych fragmentów. Wysoki percentyl (np. 40.) powoduje bardziej intensywne dzielenie, dając wiele małych, silnie skoncentrowanych fragmentów. Dostosuj tę wartość na podstawie zestawu do oceny wskaźnika trafień wyszukiwania.
LangChain SemanticChunker
LangChain udostępnia wbudowany element SemanticChunker, który implementuje ten algorytm. Przyjmuje on model osadzeń oraz typ progu punktu podziału. Dzięki temu nie musisz implementować algorytmu od podstaw, a rozwiązanie integruje się bezpośrednio z modułami wczytywania dokumentów i bazami wektorowymi LangChain.
from langchain_experimental.text_splitter import SemanticChunker
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings(model='text-embedding-3-small')
chunker = SemanticChunker(
embeddings,
breakpoint_threshold_type='percentile',
breakpoint_threshold_amount=25
)
chunks = chunker.create_documents([long_document_text])
print(f'{len(chunks)} semantic chunks created')Kompromisy w porównaniu z dzieleniem o stałym rozmiarze
Dzielenie semantyczne tworzy fragmenty wyższej jakości i o lepszej spójności tematycznej, ale jest droższe: każde zdanie musi zostać osadzone tylko po to, aby określić granice fragmentów — zanim fragmenty zostaną w ogóle zindeksowane. W przypadku dokumentu liczącego 100 stron oznacza to tysiące wywołań modelu osadzeń wyłącznie na potrzeby dzielenia. Stosuj dzielenie semantyczne, gdy jakość wyszukiwania jest ważniejsza niż szybkość indeksowania.
Kiedy stosować dzielenie semantyczne
Dzielenie semantyczne sprawdza się szczególnie dobrze w przypadku długich treści narracyjnych — wpisów na blogach, artykułów naukowych, dokumentów prawnych i książek — w których tematy zmieniają się w sposób naturalny. Jest mniej potrzebne w przypadku silnie ustrukturyzowanych dokumentów, takich jak katalogi produktów, listy FAQ czy pliki z kodem, które lepiej obsługują dzielniki uwzględniające strukturę dokumentu.
Szybki test
Sprawdź swoją wiedzę na temat dzielenia semantycznego omówionego w tej lekcji.
Podsumowanie lekcji
W tej lekcji nauczyłeś się, że: dzielenie semantyczne wykorzystuje podobieństwo osadzeń do wykrywania zmian tematów, próg percentylowy określa szczegółowość podziału oraz SemanticChunker biblioteki LangChain implementuje tę funkcję od razu. Następnie zajmiemy się dzieleniem na fragmenty nadrzędne i podrzędne, które łączy małe, precyzyjne fragmenty z dużymi fragmentami bogatymi w kontekst.
Często zadawane pytania
Czy lekcja „Dzielenie semantyczne na podstawie podobieństwa embeddingów” jest bezpłatna?
Tak — pełny tekst „Dzielenie semantyczne na podstawie podobieństwa embeddingów” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Engineering Academy, przejdź na CoddyKit PRO. Kurs AI Engineering Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Dzielenie semantyczne na podstawie podobieństwa embeddingów”?
Zaimplementuj semantyczne dzielenie tekstu, rozdzielając go w punktach największego dystansu semantycznego między kolejnymi zdaniami i zachowując spójność tematyczną treści. Ćwiczysz AI Engineering Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć AI Engineering Academy?
Nie wymagamy żadnego doświadczenia. AI Engineering Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Dzielenie semantyczne na podstawie podobieństwa embeddingów”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji AI Engineering Academy?
Tak. Każda lekcja AI Engineering Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Dlaczego naiwne dzielenie na fragmenty pogarsza wyszukiwanie
- Dzielenie semantyczne na podstawie podobieństwa embeddingów
- Wyszukiwanie nadrzędny–podrzędny i od małego do dużego
- Strategie dopasowane do dokumentów: kod i HTML