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. Moc bych to ocenil, kdybyste mohl Pokud vám tento tutoriál pomůže. ⭐ star CocoIndex on GitHub CocoIndex na Githubu Používejte případy Akademické vyhledávání a vyhledávání, stejně jako agenty AI založené na výzkumu Papírové doporučovací systémy Grafický výzkum znalostí Semantická analýza vědecké literatury Co dosáhneme Pojďme se na to podívat Jako příklad . PDF Zde je to, co chceme dosáhnout: 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ší výsledky sémantického vyhledávání založeného na metadatach. Například můžete porovnávat textové dotazy s titulky a abstrakty. 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 Celý kód naleznete zde . zde Pokud vám tento článek pomůže, dejte nám prosím hvězdičku Pomáhá nám růst. GitHub Základní 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? Předpoklady . Install PostgreSQL CocoIndex uses PostgreSQL internally for incremental processing. . Configure your OpenAI API key Alternativně máme nativní podporu pro Gemini, Ollama, LiteLLM, check-out . Průvodce Můžete si vybrat svého oblíbeného poskytovatele LLM a můžete pracovat zcela na místě. Indexování toku Tento projekt demonstruje poněkud komplexnější příklad metadatového porozumění blíže reálným případům použití. Uvidíte, jak snadné je dosáhnout tohoto návrhu CocoIndex ve 100 řádcích logiky indexování - . Kódování Abychom vám lépe pomohli navigovat přes to, co budeme procházet, zde je průtokový diagram. Import seznamu dokumentů 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. Pojďme se zoomovat v krocích. Import dokumentů @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), ) vytvoří tabulku s podpolemi ( , , • , flow_builder.add_source filename content Můžeme se zmínit o Pro více detailů. dokumentace Shromažďování a extrahování metadata Extrakt první stránky pro základní informace Definujte vlastní funkci pro extrahování první stránky a počtu stránek 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()) Připojte to do svého toku. Z první stránky extrahujeme metadata, abychom minimalizovali náklady na zpracování, protože celý PDF může být velmi velký. with data_scope["documents"].row() as doc: doc["basic_info"] = doc["content"].transform(extract_basic_info) Po tomto kroku byste měli mít základní informace o každém papíře. Přečtěte si základní info První stránku převedeme na Markdown pomocí Markeru. Alternativně můžete snadno připojit svůj oblíbený PDF analyzátor, jako je Docling. Definujte funkci konvertoru markeru a vyrovnejte ji, protože její inicializace je náročná na zdroje. Tím je zajištěno, že se stejná konvertorová instance znovu použije pro různé vstupní soubory. @cache def get_marker_converter() -> PdfConverter: config_parser = ConfigParser({}) return PdfConverter( create_model_dict(), config=config_parser.generate_config_dict() ) Připojte je k funkci custom. @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 Přejděte k vaší transformaci with data_scope["documents"].row() as doc: doc["first_page_md"] = doc["basic_info"]["first_page"].transform( pdf_to_markdown ) Po tomto kroku byste měli mít první stránku každého papíru ve formátu Markdown. Extrahovat základní informace s LLM Definujte schéma pro extrakci LLM. CocoIndex nativně podporuje extrakci strukturovanou LLM se složitými a nestedovými schématy. Pokud máte zájem dozvědět se více o hnízděných schématech, navštivte . Tento článek @dataclasses.dataclass class PaperMetadata: """ Metadata for a paper. """ title: str authors: list[Author] abstract: str Zapojte ji do S definovanou datovou třídou CocoIndex automaticky analyzuje odpověď LLM do datové třídy. 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 byste měli mít metadata každého papíru. Sběr papírových metadat 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"], ) Sbírejte vše, co potřebujete :) Kolekce Dvě Informace autorem Filatelizace autorem Filatelizace Zde chceme shromažďovat Autor → Papers v samostatné tabulce pro vytvoření funkce vyhledávání. Jednoduše shromažďuje autor. 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"], ) Počítejte a sbírejte embeddings Titulek doc["title_embedding"] = doc["metadata"]["title"].transform( cocoindex.functions.SentenceTransformerEmbed( model="sentence-transformers/all-MiniLM-L6-v2" ) ) Abstraktní Abstrakt rozdělte na kusy, vložte každý kus a sbírejte jejich vložky. Abstrakt může být někdy velmi dlouhý. 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 byste měli mít abstraktní kousky každého papíru. Sbírejte každý kousek a sbírejte jejich 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 byste měli mít vkládání abstraktních kusů každého papíru. Sbírejte 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"], ) Exportování Konečně exportujeme data do 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 příkladu používáme PGVector jako vestavěné obchody/ S CocoIndex můžete provést jeden přepínač řádků na jiných podporovaných databázích Vector, jako je Qdrant. Pro více detailů. Průvodce Cílem je standardizovat rozhraní a udělat z nich stavbu LEGO. Prohlídka v CocoInsight krok za krokem Můžete projít projektem krok za krokem vidět Kokosový pohled Přesně jak je každé pole postaveno a co se děje za scénami. Chcete indexovat Můžete se obrátit na tuto sekci Ohledně Textové vložky Jak vytvořit dotaz proti vkládání. Prozatím CocoIndex neposkytuje další rozhraní dotazu.Můžeme psát SQL nebo se spoléhat na motoru dotazu cílovým úložištěm. Mnoho databází již optimalizovalo implementace dotazů pomocí vlastních osvědčených postupů. Prostor dotazu má vynikající řešení pro dotazování, přerozdělování a další funkce související s vyhledáváním. Pokud potřebujete pomoc s psaním dotazu, prosím, neváhejte nás kontaktovat na . neshody Podpořte nás Neustále se zlepšujeme a brzy přicházejí další funkce a příklady. Pokud vám tento článek pomůže, dejte nám prosím hvězdičku Pomáhá nám růst. GitHub Díky za čtení!