In this blog we will walk through a comprehensive example of indexing research papers with extracting different metadata — beyond full text chunking and embedding — and build semantic embeddings for indexing and querying. Bili bismo zahvalni ako biste mogli Ako vam je ovaj tutorial koristan. ⭐ star CocoIndex on GitHub CocoIndex na Githubu Koristite slučajeve Akademsko pretraživanje i pronalaženje, kao i agenti AI-a koji se temelje na istraživanju Papirni sustavi preporuke Grafički istraživanje znanja Semantička analiza znanstvene literature Što ćemo postići Hajde da pogledamo ovo Kao primjer. PDF Evo što želimo postići: Extract the paper metadata, including file name, title, author information, abstract, and number of pages. Build vector embeddings for the metadata, such as the title and abstract, for semantic search. To omogućuje bolje rezultate semantičkog pretraživanja utemeljenog na metapodatcima.Na primjer, možete uskladiti tekstualne upite s naslovima i abstraktima. Build an index of authors and all the file names associated with each author to answer questions like "Give me all the papers by Jeff Dean." If you want to perform full PDF embedding for the paper, you can also refer to . this article Možete pronaći cijeli kod . ovdje Ako vam je ovaj članak koristan, molimo dajte nam zvijezdu ⭐ na Da nam pomogne rasti. GitHub Osnovne komponente PDF Preprocessing Reads PDFs using and extracts: pypdf Total number of pages First page content (used as a proxy for metadata-rich information) Markdown Conversion Converts the first page to Markdown using . Marker LLM-Powered Metadata Extraction Sends the first-page Markdown to GPT-4o using CocoIndex's function. ExtractByLlm Extracted metadata includes and more. (string) title (with name, email, and affiliation) authors (string) abstract Semantic Embedding The title is embedded directly using the model by the SentenceTransformer. all-MiniLM-L6-v2 Abstracts are chunked based on semantic punctuation and token count, then each chunk is embedded individually. Relational Data Collection Authors are unrolled and collected into an relation, enabling queries like: author_papers Show all papers by X Which co-authors worked with Y? Preduvjeti . Install PostgreSQL CocoIndex uses PostgreSQL internally for incremental processing. . Configure your OpenAI API key Alternativno, imamo domaću potporu za Gemini, Ollama, LiteLLM, provjerite . Vodič Možete odabrati svog omiljenog pružatelja LLM-a i moći ćete raditi potpuno na licu mjesta. Definicija indeksa Ovaj projekt pokazuje malo sveobuhvatniji primjer razumijevanja metapodataka bliže stvarnim slučajevima korištenja. Vidjet ćete kako je lako postići ovaj dizajn od strane CocoIndexa unutar 100 linija logike indeksiranja - . Kodeks Da biste vam bolje pomogli u navigaciji kroz što ćemo proći, ovdje je dijagram protoka. Uvoziti popis dokumenata u PDF. For each file: Extract the first page of the paper. Convert the first page to Markdown. Extract metadata (title, authors, abstract) from the first page. Split the abstract into chunks, and compute embeddings for each chunk. Export to the following tables in Postgres with PGVector: Metadata (title, authors, abstract) for each paper. Author-to-paper mapping, for author-based query. Embeddings for titles and abstract chunks, for semantic search. Zamotajmo se u koracima. Uvoz dokumenata @cocoindex.flow_def(name="PaperMetadata") def paper_metadata_flow( flow_builder: cocoindex.FlowBuilder, data_scope: cocoindex.DataScope ) -> None: data_scope["documents"] = flow_builder.add_source( cocoindex.sources.LocalFile(path="papers", binary=True), refresh_interval=datetime.timedelta(seconds=10), ) će stvoriti tablicu s podpoljima ( , , u flow_builder.add_source filename content Možemo se odnositi na Za više detalja. Dokumentacija Izdvajanje i prikupljanje metapodataka Izvadite prvu stranicu za osnovne informacije Definicija prilagođene funkcije za izvlačenje prve stranice i broja stranica PDF-a. @dataclasses.dataclass class PaperBasicInfo: num_pages: int first_page: bytes @cocoindex.op.function() def extract_basic_info(content: bytes) -> PaperBasicInfo: """Extract the first pages of a PDF.""" reader = PdfReader(io.BytesIO(content)) output = io.BytesIO() writer = PdfWriter() writer.add_page(reader.pages[0]) writer.write(output) return PaperBasicInfo(num_pages=len(reader.pages), first_page=output.getvalue()) Uključite ih u svoj tok. Metapodatke izlažemo s prve stranice kako bismo smanjili troškove obrade, jer cijeli PDF može biti vrlo velik. with data_scope["documents"].row() as doc: doc["basic_info"] = doc["content"].transform(extract_basic_info) Nakon ovog koraka, trebali biste imati osnovne informacije o svakom papiru. Pronađi osnovne informacije Prvu stranicu pretvorit ćemo u Markdown koristeći Marker. Alternativno, možete lako priključiti svoj omiljeni PDF analizator, kao što je Docling. Definirajte funkciju pretvarača markera i cache je, jer je inicijaliziranje resursno intenzivno. To osigurava da se isti primjerak pretvarača ponovno koristi za različite ulazne datoteke. @cache def get_marker_converter() -> PdfConverter: config_parser = ConfigParser({}) return PdfConverter( create_model_dict(), config=config_parser.generate_config_dict() ) Uključite ga u običnu funkciju. @cocoindex.op.function(gpu=True, cache=True, behavior_version=1) def pdf_to_markdown(content: bytes) -> str: """Convert to Markdown.""" with tempfile.NamedTemporaryFile(delete=True, suffix=".pdf") as temp_file: temp_file.write(content) temp_file.flush() text, _, _ = text_from_rendered(get_marker_converter()(temp_file.name)) return text Pronađite ga u vašoj transformaciji with data_scope["documents"].row() as doc: doc["first_page_md"] = doc["basic_info"]["first_page"].transform( pdf_to_markdown ) Nakon ovog koraka, trebali biste imati prvu stranicu svakog papira u formatu Markdown. Extract basic info with LLM CocoIndex nativno podržava LLM strukturiranu ekstrakciju s složenim i ugrađenim shemama. Ako ste zainteresirani za učenje više o gnijezdanim shemama, obratite se . Ovaj članak @dataclasses.dataclass class PaperMetadata: """ Metadata for a paper. """ title: str authors: list[Author] abstract: str Uključite ga u S definiranom klasom podataka, CocoIndex će automatski analizirati odgovor LLM-a u klasu podataka. ExtractByLlm doc["metadata"] = doc["first_page_md"].transform( cocoindex.functions.ExtractByLlm( llm_spec=cocoindex.LlmSpec( api_type=cocoindex.LlmApiType.OPENAI, model="gpt-4o" ), output_type=PaperMetadata, instruction="Please extract the metadata from the first page of the paper.", ) ) Nakon ovog koraka, trebali biste imati metapodatke svakog papira. Prikupljanje papirnih metapodataka paper_metadata = data_scope.add_collector() with data_scope["documents"].row() as doc: # ... process # Collect metadata paper_metadata.collect( filename=doc["filename"], title=doc["metadata"]["title"], authors=doc["metadata"]["authors"], abstract=doc["metadata"]["abstract"], num_pages=doc["basic_info"]["num_pages"], ) Pronađite sve što vam treba :) Kolekcija dva Informacije author filename autorica Filename Ovdje želimo prikupiti Autor → Papiri u zasebnoj tablici kako bismo izgradili funkciju pretraživanja. Jednostavno prikupljanje od strane autora. author_papers = data_scope.add_collector() with data_scope["documents"].row() as doc: with doc["metadata"]["authors"].row() as author: author_papers.collect( author_name=author["name"], filename=doc["filename"], ) Izračunavanje i prikupljanje embeddings naslovnica doc["title_embedding"] = doc["metadata"]["title"].transform( cocoindex.functions.SentenceTransformerEmbed( model="sentence-transformers/all-MiniLM-L6-v2" ) ) Abstrakcija Podijelite abstrakt u komadiće, ugradite svaki komad i prikupite njihove ugradnje. Ponekad abstrakt može biti vrlo dug. doc["abstract_chunks"] = doc["metadata"]["abstract"].transform( cocoindex.functions.SplitRecursively( custom_languages=[ cocoindex.functions.CustomLanguageSpec( language_name="abstract", separators_regex=[r"[.?!]+\s+", r"[:;]\s+", r",\s+", r"\s+"], ) ] ), language="abstract", chunk_size=500, min_chunk_size=200, chunk_overlap=150, ) Nakon ovog koraka, trebali biste imati apstraktne komadiće svakog papira. Uključite svaki komad i prikupite njihove ugradnje. with doc["abstract_chunks"].row() as chunk: chunk["embedding"] = chunk["text"].transform( cocoindex.functions.SentenceTransformerEmbed( model="sentence-transformers/all-MiniLM-L6-v2" ) ) Nakon ovog koraka, trebali biste imati ugrađivanja abstraktnih komada svakog papira. Prikupljanje embeddings metadata_embeddings = data_scope.add_collector() with data_scope["documents"].row() as doc: # ... process # collect title embedding metadata_embeddings.collect( id=cocoindex.GeneratedField.UUID, filename=doc["filename"], location="title", text=doc["metadata"]["title"], embedding=doc["title_embedding"], ) with doc["abstract_chunks"].row() as chunk: # ... process # collect abstract chunks embeddings metadata_embeddings.collect( id=cocoindex.GeneratedField.UUID, filename=doc["filename"], location="abstract", text=chunk["text"], embedding=chunk["embedding"], ) izvoz Naposljetku, podatke izvozimo u Postgres. paper_metadata.export( "paper_metadata", cocoindex.targets.Postgres(), primary_key_fields=["filename"], ) author_papers.export( "author_papers", cocoindex.targets.Postgres(), primary_key_fields=["author_name", "filename"], ) metadata_embeddings.export( "metadata_embeddings", cocoindex.targets.Postgres(), primary_key_fields=["id"], vector_indexes=[ cocoindex.VectorIndexDef( field_name="embedding", metric=cocoindex.VectorSimilarityMetric.COSINE_SIMILARITY, ) ], ) U ovom primjeru koristimo PGVector kao ugrađene trgovine/ Uz CocoIndex, možete napraviti jedan prebacivanje linije na drugim podržanim vektorskim bazama podataka kao što je Qdrant, pogledajte ovo Za više detalja. Vodič Cilj nam je standardizirati sučelje i učiniti ih poput izgradnje LEGO-a. Pogled u CocoInsight korak po korak Možete prošetati kroz projekt korak po korak u Vidjeti CocoInsight Točno kako je svako polje konstruirano i što se događa iza pozornice. Želite indeks Možete se obratiti ovom odjeljku Oko tekstualni embeddings Kako izgraditi upit protiv ugrađivanja Za sada CocoIndex ne pruža dodatni interfejs upita. možemo napisati SQL ili se osloniti na motor upita od ciljanog skladišta. Mnoge baze podataka već su optimizirale implementacije upita s vlastitim najboljim praksama Prostor upita ima izvrsna rješenja za upite, preraspodjelu i druge funkcije povezane s pretraživanjem. Ako trebate pomoć s pisanjem upita, slobodno nas kontaktirajte na . neslaganje Podržite nas Stalno se poboljšavamo, a uskoro stižu još značajki i primjeri. Ako vam je ovaj članak koristan, molimo dajte nam zvijezdu ⭐ na Da nam pomogne rasti. GitHub Hvala na čitanju!