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. Ne do të vlerësojmë shumë nëse ju mund të Nëse e gjeni këtë tutorial të dobishëm ⭐ star CocoIndex on GitHub CocoIndex në GitHub Përdorimi i rastit Kërkimi dhe kërkimi akademik, si dhe agjentët e AI të bazuar në kërkime Sistemi i rekomandimit të letrës Kërkimi i njohurive grafike Analizë semantike e letërsisë shkencore Çfarë do të arrijmë Le të hedhim një sy në këtë Si një shembull PDF të Ja çfarë duam të arrijmë: 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. Kjo mundëson rezultate më të mira të kërkimit semantik të drejtuar nga metadata. për shembull, ju mund të krahasoni pyetjet e tekstit me titujt dhe abstraktet. 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 Ju mund të gjeni kodin e plotë . Këtu Nëse ky artikull është i dobishëm për ju, ju lutemi na jepni një yll Për të na ndihmuar të rritemi. Github Komponentët kryesorë 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? Parashikimet . Install PostgreSQL CocoIndex uses PostgreSQL internally for incremental processing. . Configure your OpenAI API key Alternativisht, ne kemi mbështetje native për Gemini, Ollama, LiteLLM, kontrolloni . Udhëzues Ju mund të zgjidhni ofruesin tuaj të preferuar LLM dhe mund të punoni plotësisht në vend. Përcaktimi i indeksimit të rrjedhës Ky projekt demonstron një shembull pak më të plotë të kuptimit të metadata më afër rastet e përdorimit të botës reale. Ju do të shihni se sa e lehtë është për të arritur këtë dizajn nga CocoIndex brenda 100 linjave të logjikës së indeksimit - . Kodi Për t'ju ndihmuar më mirë të lundroni nëpër atë që do të ecim, këtu është një diagram i rrjedhës. Importoni një listë të dokumenteve në 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. Le të zoom në hapat. Importi i dokumenteve @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), ) do të krijojë një tabelë me fusha nën ( të , të flow_builder.add_source filename content Ne mund të referohemi për Për më shumë detaje. Dokumentacioni Të nxjerrë dhe të mbledhë metadata Shkarko faqen e parë për info themelore Definoni një funksion të përshtatur për të nxjerrë faqen e parë dhe numrin e faqeve të 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()) Tani lidheni këtë në rrjedhën tuaj. Ne nxjerrim metadata nga faqja e parë për të minimizuar koston e përpunimit, pasi e gjithë PDF mund të jetë shumë e madhe. with data_scope["documents"].row() as doc: doc["basic_info"] = doc["content"].transform(extract_basic_info) Pas këtij hapi, ju duhet të keni informacionin bazë të çdo letre. Shkarko Info bazë Ne do të konvertojmë faqen e parë në Markdown duke përdorur Marker. Përndryshe, mund të lidhni lehtësisht analizuesin tuaj të preferuar PDF, si Docling. Përcakto një funksion konvertues markeri dhe cache atë, pasi fillimi i tij është burim-intensive. Kjo siguron që e njëjta instancë e konvertuesit të ri-përdoret për fotografi të ndryshme të hyrjes. @cache def get_marker_converter() -> PdfConverter: config_parser = ConfigParser({}) return PdfConverter( create_model_dict(), config=config_parser.generate_config_dict() ) Lidheni atë në një funksion të zakonshëm. @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 Dërgojeni atë në transformimin tuaj with data_scope["documents"].row() as doc: doc["first_page_md"] = doc["basic_info"]["first_page"].transform( pdf_to_markdown ) Pas këtij hapi, ju duhet të keni faqen e parë të çdo letre në formatin Markdown. Të nxjerrë informacion bazë me LLM Definoni një skemë për nxjerrjen LLM. CocoIndex mbështet nativisht nxjerrjen e strukturuar LLM me skema komplekse dhe të ngulitura. Nëse jeni të interesuar të mësoni më shumë rreth skemave të fshehura, referojuni . Ky artikull @dataclasses.dataclass class PaperMetadata: """ Metadata for a paper. """ title: str authors: list[Author] abstract: str Plotësoni atë në Me një klasë të dhënash të përcaktuar, CocoIndex automatikisht do të analizojë përgjigjen LLM në klasën e të dhënave. 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.", ) ) Pas këtij hapi, ju duhet të keni metadat e secilës letër. Mbledhja e metadatave në letër 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"], ) Mblidhni gjithçka që ju nevojitet :) mbledhje dy informacioneve Autorë filename Autorë Filemë Këtu duam të mbledhim Author → Papers në një tabelë të veçantë për të ndërtuar një funksionalitet kërkimi. Vetëm të mbledhur nga autori. 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"], ) Llogaritja dhe mbledhja e embeddings Titulli doc["title_embedding"] = doc["metadata"]["title"].transform( cocoindex.functions.SentenceTransformerEmbed( model="sentence-transformers/all-MiniLM-L6-v2" ) ) abstraktë Ndajeni abstraktet në copa, futni çdo copë dhe mblidhni embeddings e tyre. Abstrakti ndonjëherë mund të jetë shumë i gjatë. 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, ) Pas këtij hapi, ju duhet të keni copa abstrakte të çdo letre. Përzieni çdo copë dhe mblidhni embeddings e tyre. with doc["abstract_chunks"].row() as chunk: chunk["embedding"] = chunk["text"].transform( cocoindex.functions.SentenceTransformerEmbed( model="sentence-transformers/all-MiniLM-L6-v2" ) ) Pas këtij hapi, ju duhet të keni embeddings e copa abstrakte të çdo letre. Mbledhja e 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"], ) Eksportet Së fundi, ne eksportojmë të dhënat në 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, ) ], ) Në këtë shembull ne përdorim PGVector si dyqane embedding / Me CocoIndex, ju mund të bëni një ndërrimin e linjës në bazat e të dhënave të tjera të mbështetura Vector si Qdrant, shih këtë Për më shumë detaje. Udhëzues Ne synojmë të standardizojmë ndërfaqet dhe ta bëjmë atë si ndërtimin e Lego. Shihni në CocoInsight hap pas hapi Ju mund të ecni përmes projektit hap pas hapi në Të shohësh Kokëdhima saktësisht se si është ndërtuar secili fushë dhe çfarë ndodh prapa skenave. Përdorni indeksin Ju mund të referoheni në këtë seksion rreth Tekste të përfshira Si të ndërtoni një pyetje kundër embeddings Për momentin CocoIndex nuk ofron ndërfaqe shtesë të pyetjeve. ne mund të shkruajmë SQL ose të mbështetemi në motorin e pyetjeve nga ruajtja e synuar. Shumë baza të dhënash tashmë kanë optimizuar zbatimet e pyetjeve me praktikat e tyre më të mira Hapësira e pyetjeve ka zgjidhje të shkëlqyera për pyetje, reranking dhe funksione të tjera të lidhura me kërkimin. Nëse keni nevojë për ndihmë me shkrimin e pyetjes, ju lutemi të ndjeheni të lirë të na kontaktoni në . mosmarrëveshje Na mbështet Ne jemi vazhdimisht duke u përmirësuar, dhe më shumë karakteristika dhe shembuj do të vijnë së shpejti. Nëse ky artikull është i dobishëm për ju, ju lutemi na jepni një yll Për të na ndihmuar të rritemi. Github Faleminderit për leximin!