Во овој блог ние ќе одиме низ сеопфатен пример на индексирање на истражувачки статии со извлекување на различни метаподатоци - надвор од целосното пресекување и вградување на текст - и градење на семантички вградувања за индексирање и прашање. Ние би го цениме тоа ако можете Ако овој туториал ви е корисен. ⭐ star CocoIndex on GitHub CocoIndex на GitHub Користете случаи Академско пребарување и пребарување, како и истражувачки базирани АИ агенти Системи за препораки за хартија График на знаење за истражување Семантичка анализа на научната литература Што ќе постигнеме Ајде да погледнеме на ова Како пример ПДФ Еве што сакаме да постигнеме: 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. Ова овозможува подобри семантички резултати за пребарување базирани на метаподатоци. На пример, можете да одговарате на текстуални барања со наслови и апстракти. 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 Можете да го најдете целиот код . Овде Ако оваа статија ви е корисна, ве молиме да ни дадете ѕвезда ⭐ на Да ни помогне да растеме. GitHub Основни компоненти 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? Предуслови . Install PostgreSQL CocoIndex uses PostgreSQL internally for incremental processing. . Configure your OpenAI API key Алтернативно, имаме домашна поддршка за Gemini, Ollama, LiteLLM, . Водич Можете да изберете вашиот омилен LLM провајдер и може да работи целосно на локално ниво. Дефинирање на индексирање на протокот Овој проект демонстрира малку повеќе сеопфатен пример за разбирање на метаподатоците поблиску до реалните случаи на употреба. Ќе видите колку е лесно да се постигне овој дизајн од CocoIndex во рамките на 100 линии на логика за индексирање - . Кодот За подобро да ви помогне да се движите низ она што ќе поминеме, тука е дијаграм на протокот. Импортирајте листа на документи во 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. Ајде да се зумираме во чекорите. Увоз на документи @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), ) ќе се создаде табела со под-полети ( , на - на flow_builder.add_source filename content Можеме да се однесуваме на За повеќе детали. Документација Извлекување и собирање метаподатоци Извлечете ја првата страница за основни информации Дефинирање на прилагодена функција за извлекување на првата страница и бројот на страници на 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()) Сега вклучете го ова во вашиот тек. Ние извлекуваме метаподатоци од првата страница за да ги минимизираме трошоците за обработка, бидејќи целиот PDF може да биде многу голем. with data_scope["documents"].row() as doc: doc["basic_info"] = doc["content"].transform(extract_basic_info) По овој чекор, треба да ги имате основните информации за секој документ. Погледнете ги основните информации Ние ќе ја претвориме првата страница во Markdown со користење на Маркер. Алтернативно, можете лесно да го поврзете вашиот омилен PDF аналитичар, како што е Docling. Дефинирајте функција на конвертор на маркери и кеширајте ја, бидејќи нејзината иницијализација е ресурсна. Ова гарантира дека истата инстанца на конверторот се користи повторно за различни датотеки за влез. @cache def get_marker_converter() -> PdfConverter: config_parser = ConfigParser({}) return PdfConverter( create_model_dict(), config=config_parser.generate_config_dict() ) Вклучете го во навика функција. @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 ) По овој чекор, треба да ја имате првата страница на секој лист во формат Markdown. Извлечете основни информации со LLM Дефинирање на шема за LLM екстракција. CocoIndex природно поддржува LLM-структурирана екстракција со комплексни и вградени шеми. Ако сте заинтересирани да дознаете повеќе за гнездовите шеми, обратете се на . Оваа статија @dataclasses.dataclass class PaperMetadata: """ Metadata for a paper. """ title: str authors: list[Author] abstract: str Вклучете го во Со дефинирана класа на податоци, CocoIndex автоматски ќе го анализира одговорот на LLM во класата на податоци. 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.", ) ) По овој чекор, треба да ги имате метаподатоците на секој лист. Собирање на хартија метаподатоци 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"], ) Добијте сè што ви треба :) Колекција to Информации author filename авторот Филемеј We’ve already extracted author list. Here we want to collect Author → Papers in a separate table to build a look up functionality. Едноставно собрани од авторот. 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"], ) Пресметка и собирање на вградувања Насловна doc["title_embedding"] = doc["metadata"]["title"].transform( cocoindex.functions.SentenceTransformerEmbed( model="sentence-transformers/all-MiniLM-L6-v2" ) ) апстракција Поделете ги апстрактите во парчиња, вметнете го секој парче и собирајте ги нивните вградувања. Понекогаш апстрактот може да биде многу долг. 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, ) After this step, you should have the abstract chunks of each paper. Вметнете го секој дел и соберете ги нивните вградувања. with doc["abstract_chunks"].row() as chunk: chunk["embedding"] = chunk["text"].transform( cocoindex.functions.SentenceTransformerEmbed( model="sentence-transformers/all-MiniLM-L6-v2" ) ) По овој чекор, треба да ги имате вградувањата на апстрактните парчиња од секоја хартија. Собирање на вградувања 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"], ) извоз Конечно, ги извезуваме податоците во 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, ) ], ) Во овој пример, ние го користиме PGVector како вградување продавници / Со CocoIndex, можете да направите еден линиски прекинувач на други поддржани векторски бази на податоци како Qdrant, видете ова За повеќе детали. Водич Нашата цел е да ги стандардизираме интерфејсите и да го направиме тоа како градење на LEGO. Преглед во CocoInsight чекор по чекор Можете да одите низ проектот чекор по чекор во Да се види Кокосовото гледање Точно како е изградено секое поле и што се случува зад сцените. Погледнете го индексот Можете да го погледнете овој дел од за Текстови за вградување Како да се изгради прашање против вградувања. Засега CocoIndex не обезбедува дополнителен интерфејс за прашање. Можеме да напишеме SQL или да се потпреме на моторот за прашање од целното складирање. Многу бази на податоци веќе имаат оптимизирани имплементации на прашања со свои најдобри практики The query space has excellent solutions for querying, reranking, and other search-related functionality. Ако ви треба помош со пишување на прашањето, ве молиме да се чувствувате слободни да контактирате со нас на . Несогласување Поддржувајте нè Ние постојано се подобруваме, а повеќе карактеристики и примери доаѓаат наскоро. Ако оваа статија ви е корисна, ве молиме да ни дадете ѕвезда ⭐ на Да ни помогне да растеме. GitHub Благодарам за читањето!