Tässä blogissa käymme läpi kattavan esimerkin tutkimuspapereiden indeksoinnista erilaisten metatietojen poiminnalla - täyden tekstin puristamisen ja upottamisen ulkopuolella - ja semanttisten upotusten rakentamiseksi indeksointiin ja kyselyyn. Arvostamme suuresti, jos voit Jos tämä tutoriali on hyödyllinen. ⭐ star CocoIndex on GitHub CocoIndex Githubissa Käytä tapauksia Akateeminen haku ja haku sekä tutkimukseen perustuva AI-agentit Paperin suositusjärjestelmät Tietämyksen grafiikka Tieteellisen kirjallisuuden semanttinen analyysi Mitä saavutamme Katsotaanpa tätä kuin esimerkkinä Pdf mukaan Tässä mitä haluamme saavuttaa: 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. Tämä mahdollistaa paremmat metatietopohjaiset semanttiset hakutulokset. Esimerkiksi voit vastata tekstin kyselyihin otsikoiden ja abstraktien kanssa. 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 You can find the full code . Täällä Jos tämä artikkeli on hyödyllinen sinulle, anna meille tähti auttaa meitä kasvamaan. Githubissa Keskeiset komponentit 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? Edellytykset . Install PostgreSQL CocoIndex uses PostgreSQL internally for incremental processing. . Configure your OpenAI API key Vaihtoehtoisesti meillä on native tuki Gemini, Ollama, LiteLLM, check out . oppaasta Voit valita suosikki LLM tarjoaja ja voi työskennellä täysin paikan päällä. Indeksointi Flow Tämä hanke osoittaa hieman kattavamman esimerkin metatietojen ymmärtämisestä lähempänä todellisia käyttötapauksia. You’ll see how easy it is to achieve this design by CocoIndex within 100 lines of indexing logic - . koodiin Jotta voisit paremmin navigoida, mitä kävelemme läpi, tässä on virtauskaavio. Tuoda luettelo papereista PDF-muodossa. 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. Zoomaamme askeleet eteenpäin. Papereiden tuonti @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), ) luodaan taulukko alaryhmien kanssa ( ja • , flow_builder.add_source filename content Voimme viitata siihen Lisää yksityiskohtia varten. Dokumentaatio Extract and collect metadata Poista ensimmäinen sivu perustiedot Määritä mukautettu toiminto PDF-tiedoston ensimmäisen sivun ja sivujen määrän poistamiseksi. @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()) Liitä tämä nyt virtaan. Poistamme metatiedot ensimmäiseltä sivulta käsittelykustannusten minimoimiseksi, koska koko PDF voi olla hyvin suuri. with data_scope["documents"].row() as doc: doc["basic_info"] = doc["content"].transform(extract_basic_info) Tämän vaiheen jälkeen sinulla pitäisi olla kunkin paperin perustiedot. Näytä perustiedot Muunnamme ensimmäisen sivun Markdowniksi Markerin avulla. Vaihtoehtoisesti voit helposti liittää suosikki PDF-analyysiohjelmasi, kuten Docling. Määrittele merkki-muunninfunktio ja välitä se välimuistiin, koska sen aloittaminen on resurssiintensivistä. Näin varmistetaan, että samaa muunnininstanssia käytetään uudelleen eri syöttötiedostoihin. @cache def get_marker_converter() -> PdfConverter: config_parser = ConfigParser({}) return PdfConverter( create_model_dict(), config=config_parser.generate_config_dict() ) Liitä se tavanomaiseen toimintoon. @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 Pass it to your transform with data_scope["documents"].row() as doc: doc["first_page_md"] = doc["basic_info"]["first_page"].transform( pdf_to_markdown ) Tämän vaiheen jälkeen sinun pitäisi olla kunkin paperin ensimmäinen sivu Markdown-muodossa. Extract basic info with LLM CocoIndex tukee natiivisesti LLM-rakennettua uuttamista monimutkaisilla ja solmituilla järjestelmillä. Jos olet kiinnostunut oppimaan lisää nestemäisistä järjestelmistä, ota yhteyttä . Tämä artikkeli @dataclasses.dataclass class PaperMetadata: """ Metadata for a paper. """ title: str authors: list[Author] abstract: str Liitä se sisään Kun tietoluokka on määritelty, CocoIndex analysoi automaattisesti LLM-vastauksen tietoluokkaan. 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.", ) ) Tämän vaiheen jälkeen sinulla pitäisi olla kunkin paperin metatiedot. Collect paper metadata 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"], ) Just collect anything you need :) Kerääminen Kaksi information author Filosofiaa author Filosofiaa Tässä haluamme kerätä Author → Papers erilliseen taulukkoon, jotta voimme rakentaa hakutoiminnon. Kerää vain kirjailija. 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"], ) Compute and collect embeddings Title doc["title_embedding"] = doc["metadata"]["title"].transform( cocoindex.functions.SentenceTransformerEmbed( model="sentence-transformers/all-MiniLM-L6-v2" ) ) abstrakti Jaa abstrakti palasiksi, liitä jokainen palas ja kerää niiden upotukset. Joskus abstrakti voi olla hyvin pitkä. 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, ) Tämän vaiheen jälkeen sinun pitäisi olla kunkin paperin abstraktit palaset. Sekoita jokainen kappale ja kerää niiden sisäänrakennukset. with doc["abstract_chunks"].row() as chunk: chunk["embedding"] = chunk["text"].transform( cocoindex.functions.SentenceTransformerEmbed( model="sentence-transformers/all-MiniLM-L6-v2" ) ) Tämän vaiheen jälkeen sinun pitäisi olla kunkin paperin abstraktien kappaleiden upotukset. Collect 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"], ) vientiä Lopuksi viedään tiedot Postgresiin. 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, ) ], ) Tässä esimerkissä käytämme PGVectoria sisäänrakennettuina myymälöinä/ CocoIndexin avulla voit vaihtaa yhden rivin muissa tuetuissa Vector-tietokannoissa, kuten Qdrantissa, katso tämä Lisää yksityiskohtia varten. oppaasta Tavoitteenamme on standardoida rajapinnat ja tehdä siitä kuin Lego. CocoInsightin näkymä askel askeleelta Voit kävellä projektin läpi askel askeleelta to see Kokkolähetys Täsmälleen miten jokainen kenttä on rakennettu ja mitä tapahtuu näyttämöjen takana. Query the index Voit viitata tähän osaan about Sisäänrakennettu teksti how to build query against embeddings. Tällä hetkellä CocoIndex ei tarjoa lisäkyselyliittymää. Voimme kirjoittaa SQL: n tai luottaa kohdevarastoon kyselymoottoriin. Monet tietokannat ovat jo optimoineet kyselyn toteutukset omilla parhailla käytännöillään. Kyselyalueella on erinomaiset ratkaisut kyselyyn, uudelleenjärjestelyyn ja muihin hakuun liittyviin toimintoihin. Jos tarvitset apua kyselyn kirjoittamisessa, ota meihin yhteyttä . Discord Tue meitä Olemme jatkuvasti parantamassa, ja lisää ominaisuuksia ja esimerkkejä tulossa pian. Jos tämä artikkeli on hyödyllinen sinulle, anna meille tähti auttaa meitä kasvamaan. Githubissa Kiitos lukemisesta !