У овом блогу ћемо проћи кроз свеобухватан пример индексирања истраживачких радова са извлачењем различитих метаподатака - изван цоннинг и уграђивање пуног текста - и изградити семантичка уграђења за индексирање и упит. Бићемо веома захвални ако бисте могли Ako vam je ovaj tutorial koristan. ⭐ star CocoIndex на GitHub-у CocoIndex на GitHub-у Користите случајеве Академска претрага и претрага, као и истраживачки засновани АИ агенти Системи препоруке за папир Графови истраживања знања Семантичка анализа научне литературе Šta ćemo postići Hajde da pogledamo ovo Kao primer. ПДФ Here’s what we want to accomplish: 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 Можете пронаћи комплетан код . ovde Ако вам је овај чланак користан, молим вас дајте нам звезду ⭐ на Da nam pomogne da rastemo. 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 Алтернативно, имамо матерњу подршку за Близанце, Оллама, ЛитеЛЛЛМ, проверите . водич Можете изабрати свог омиљеног ЛЛМ провајдера и можете радити потпуно на локацији. Дефинисање индексирања тока Ovaj projekat pokazuje malo sveobuhvatniji primer razumevanja metapodataka bliže stvarnim slučajevima korišćenja. Видећете колико је лако постићи овај дизајн од стране ЦоцоИндек-а унутар 100 линија логике индексирања - . Код Да би вам боље помогли да се крећете кроз шта ћемо проћи, ево дијаграма протока. Uvozite listu dokumenata u 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. Хајде да зумимо у корацима. uvoziti papire @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 Можемо се односити на Za više detalja. Документација Екстрацтион и прикупљање метадата Извадите прву страницу за основне информације Дефинишите прилагођену функцију за извлачење прве странице и броја страница ПДФ-а. @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()) Сада, укључите ово у свој ток. Ми извлачимо метаподатке са прве странице како бисмо минимизирали трошкове обраде, јер цео ПДФ може бити веома велики. with data_scope["documents"].row() as doc: doc["basic_info"] = doc["content"].transform(extract_basic_info) Након овог корака, требало би да имате основне информације о сваком папиру. Parse Основне информације Прву страницу претворићемо у Markdown користећи Маркер. Алтернативно, можете лако повезати свој омиљени ПДФ аналитичар, као што је Доцлинг. Дефинишите функцију конвертера маркера и кеширајте је, јер је његова иницијализација интензивна. Ово осигурава да се иста инстанца конвертера поново користи за различите улазне датотеке. @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 Пренесите га на своју трансформацију with data_scope["documents"].row() as doc: doc["first_page_md"] = doc["basic_info"]["first_page"].transform( pdf_to_markdown ) Након овог корака, требало би да имате прву страницу сваког папира у формату Markdown. Извадите основне информације са ЛЛМ КоцоИндекс натално подржава ЛЛМ-структурирану екстракцију са сложеним и уграђеним шемама. Ако сте заинтересовани да сазнате више о гнезданим шемама, погледајте . Ovaj članak @dataclasses.dataclass class PaperMetadata: """ Metadata for a paper. """ title: str authors: list[Author] abstract: str Укључите га у Са дефинисаном класом података, ЦоцоИндек ће аутоматски анализирати одговор ЛЛМ у класу података. 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"], ) Сакупите све што вам је потребно :) Колекција два информације аутор filename аутор filename Овде желимо да прикупимо Аутор → Радови у одвојеној табели да бисмо изградили функционалност претраживања. Jednostavno prikuplja 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"], ) Рачунање и прикупљање уграђивања наслов 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, ) Након овог корака, требало би да имате апстрактне комаде сваког папира. Убаците сваки комад и сакупите њихове уграђене. with doc["abstract_chunks"].row() as chunk: chunk["embedding"] = chunk["text"].transform( cocoindex.functions.SentenceTransformerEmbed( model="sentence-transformers/all-MiniLM-L6-v2" ) ) After this step, you should have the embeddings of the abstract chunks of each paper. Прикупљање уграђених 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"], ) извоз Konačno, podatke izvozimo u 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, ) ], ) In this example we use PGVector as embedding stores/ Са ЦоцоИндек-ом, можете направити један прекидач линије на другим подржаним векторским базама података као што је Кдрант, погледајте ово Za više detalja. водич Циљ нам је да стандардизујемо интерфејсе и учинимо га као да градимо Лего. Pogledajte u CocoInsight korak po korak Можете проћи кроз пројекат корак по корак у Видимо Кокосић тачно како је свако поље изграђено и шта се дешава иза сцене. Желите индекс Možete se obratiti ovom odeljku Око Текстови уграђивања Како изградити упит против уграђивања. За сада ЦоцоИндек не пружа додатни интерфејс за упит. Можемо писати СКЛ или се ослањати на мотор за упит од стране циљног складишта. Многе базе података већ имају оптимизоване имплементације упита својим најбољим праксама Простор за упит има одлична решења за упит, поновно рангирање и друге функције везане за претрагу. Ако вам је потребна помоћ у писању упита, слободно нас контактирајте на . неслагање Podržite nas Стално се побољшавамо, а ускоро долази још функција и примера. Ако вам је овај чланак користан, молим вас дајте нам звезду ⭐ на Da nam pomogne da rastemo. GitHub Hvala na čitanju!