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. Veľmi by sme ocenili, keby ste mohli Ak vám tento tutoriál pomôže. ⭐ star CocoIndex na GitHub CocoIndex na GitHub Použitie prípadov Akademické vyhľadávanie a vyhľadávanie, ako aj agenti AI založení na výskume Papierové odporúčacie systémy Výskumné vedomostné grafy Semantickej analýzy vedeckej literatúry Čo dosiahneme Poďme sa na to pozrieť Ako príklad PDF Tu je to, čo chceme dosiahnuť: 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 umožňuje lepšie výsledky sémantického vyhľadávania založeného na metaúdajoch. Napríklad môžete priradiť textové dotazy k názvom a abstraktom. 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 Môžete nájsť celý kód . tu Ak je tento článok pre vás užitočný, dajte nám prosím hviezdu aby nám pomohol rásť. GitHub Kľúčové komponenty 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? Predpoklady . Install PostgreSQL CocoIndex uses PostgreSQL internally for incremental processing. . Configure your OpenAI API key Alternatívne máme natívnu podporu pre Gemini, Ollama, LiteLLM, checkout . Sprievodca Môžete si vybrať svojho obľúbeného poskytovateľa LLM a môžete pracovať úplne na mieste. Definovať indexovanie toku Tento projekt demonštruje o niečo komplexnejší príklad pochopenia metaúdajov bližšie k reálnym prípadom použitia. Uvidíte, ako ľahké je dosiahnuť tento dizajn CocoIndex v rámci 100 riadkov logiky indexovania - . Kódovanie Aby sme vám lepšie pomohli navigovať, cez čo prejdeme, tu je tokový diagram. Import zoznamu dokumentov do 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. Poďme zoomovať v krokoch. Importovať dokumenty @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), ) vytvorí sa tabuľka s podpólami ( , , , že flow_builder.add_source filename content Môžeme sa odvolávať na Pre viac detailov. dokumentácia extrahovať a zhromažďovať metaúdaje Odstrániť prvú stránku pre základné informácie Definujte vlastnú funkciu na extrahovanie prvej stránky a počtu stránok PDF. @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()) Teraz ho vložte do svojho toku. Z prvej stránky extrahujeme metaúdaje, aby sme minimalizovali náklady na spracovanie, pretože celý PDF môže byť veľmi veľký. with data_scope["documents"].row() as doc: doc["basic_info"] = doc["content"].transform(extract_basic_info) Po tomto kroku by ste mali mať základné informácie o každom dokumente. Získajte základné informácie Konvertujeme prvú stránku na Markdown pomocou značky. Prípadne môžete ľahko pripojiť svoj obľúbený PDF analyzátor, ako je Docling. Definujte funkciu konvertora markerov a vyrovnajte ju, pretože jej inicializácia je náročná na zdroje. Tým sa zabezpečí, že rovnaká inštancia konvertora sa opätovne použije pre rôzne vstupné súbory. @cache def get_marker_converter() -> PdfConverter: config_parser = ConfigParser({}) return PdfConverter( create_model_dict(), config=config_parser.generate_config_dict() ) Vložte ho do bežnej funkcie. @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 Odovzdajte to vašej transformácii with data_scope["documents"].row() as doc: doc["first_page_md"] = doc["basic_info"]["first_page"].transform( pdf_to_markdown ) Po tomto kroku by ste mali mať prvú stranu každého papiera vo formáte Markdown. Získajte základné informácie s LLM Definujte schému pre extrakciu LLM. CocoIndex natívne podporuje extrakciu štruktúrovanú LLM so zložitými a nestedovými schémami. Ak máte záujem dozvedieť sa viac o hniezdených schémach, obráťte sa . Tento článok @dataclasses.dataclass class PaperMetadata: """ Metadata for a paper. """ title: str authors: list[Author] abstract: str Vložte ho do S definovanou dátovou triedou CocoIndex automaticky analyzuje odpoveď LLM do dátovej triedy. 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.", ) ) Po tomto kroku by ste mali mať metaúdaje každého dokumentu. Zhromažďovanie papierových metaúdajov 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"], ) Zbierajte len to, čo potrebujete :) zbierať Dvojica Informácie author filename Autorka filename Tu chceme zhromaždiť Autor → Papers v samostatnej tabuľke na vytvorenie funkcie vyhľadávania. Jednoducho zhromaždené autorom. 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"], ) Vypočítať a zbierať embeddings Názov doc["title_embedding"] = doc["metadata"]["title"].transform( cocoindex.functions.SentenceTransformerEmbed( model="sentence-transformers/all-MiniLM-L6-v2" ) ) abstraktné Rozdeľte abstrakt na kúsky, vložte každý kus a zhromažďujte ich vložky. Abstrakt môže byť niekedy veľmi dlhý. 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, ) Po tomto kroku by ste mali mať abstraktné kúsky každého papiera. Vložte každý kúsok a zhromažďujte ich vložky. with doc["abstract_chunks"].row() as chunk: chunk["embedding"] = chunk["text"].transform( cocoindex.functions.SentenceTransformerEmbed( model="sentence-transformers/all-MiniLM-L6-v2" ) ) Po tomto kroku by ste mali mať vložky abstraktných kúskov každého papiera. Zhromažďovanie 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"], ) Exportovať Na záver exportujeme údaje do spoločnosti 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, ) ], ) V tomto príklade používame PGVector ako vkladacie obchody / S CocoIndex, môžete urobiť jeden prepínač riadkov na iných podporovaných Vector databázy ako Qdrant, pozri toto Pre viac detailov. Sprievodca Naším cieľom je štandardizovať rozhrania a urobiť z nich stavbu LEGO. Zobrazenie v CocoInsight krok za krokom Môžete prejsť projektom krok za krokom v vidieť Kokosový pohľad presne, ako je každé pole konštruované a čo sa deje za scénami. Chcem indexovať Môžete odkazovať na túto časť približne Textové vložky Ako vytvoriť dotaz proti vkladu. Zatiaľ CocoIndex neposkytuje ďalšie rozhranie dotazu. Môžeme napísať SQL alebo sa spoliehať na motora dotazu cieľového ukladacieho priestoru. Mnohé databázy už optimalizovali implementácie dotazov s vlastnými najlepšími postupmi Priestor dotazu má vynikajúce riešenia pre dotazovanie, prehodnocovanie a ďalšie funkcie súvisiace s vyhľadávaním. Ak potrebujete pomoc s písaním dotazu, prosím, neváhajte nás kontaktovať na . nesúhlas Podporte nás Neustále sa zlepšujeme a čoskoro prídu ďalšie funkcie a príklady. Ak je tento článok pre vás užitočný, dajte nám prosím hviezdu aby nám pomohol rásť. GitHub Ďakujem za čítanie!