בבלוג הזה נלך דרך דוגמה מקיפה של אינדקס מחקרים עם תמצית מטא-נתונים שונים - מעבר לחתוך טקסט מלא ולהדביק - ולבנות השבטים סמנטיים עבור אינדקס ושאלות. אשמח מאוד אם תוכל אם אתה מוצא את התרגיל הזה שימושי. ⭐ star CocoIndex באתר GitHub CocoIndex באתר GitHub שימוש במקרים חיפוש אקדמי וחיפוש, כמו גם סוכני AI מבוססי מחקר מערכות המלצות נייר גרפיקה של ידע מחקר ניתוח סמנטי של ספרות מדעית מה נשיג בואו נסתכל על זה כמו דוגמה PDF הנה מה שאנחנו רוצים להשיג: 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 האהוב עליך יכול לעבוד לחלוטין על המקום. תגית: index flow פרויקט זה מציג דוגמה קצת יותר מקיפה של הבנה של מטא-נתונים קרוב יותר למקרים של שימוש בעולם האמיתי. תראה כמה קל להשיג את העיצוב הזה על ידי 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) לאחר שלב זה, אתה צריך לקבל את המידע הבסיסי של כל נייר. עקבו אחרי basic info אנו נהפוך את הדף הראשון ל Markdown באמצעות Marker. לחלופין, באפשרותך להתחבר בקלות לנתח 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 העבירו את זה לשינוי שלכם with data_scope["documents"].row() as doc: doc["first_page_md"] = doc["basic_info"]["first_page"].transform( pdf_to_markdown ) לאחר שלב זה, אתה צריך את הדף הראשון של כל נייר בפורמט Markdown. לחלץ מידע בסיסי עם 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.", ) ) לאחר שלב זה, אתה צריך לקבל את המטא-נתונים של כל נייר. איסוף metadata נייר 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"], ) קחו את כל מה שאתם צריכים :) איסוף 2 מידע סופר Filename סופר Filename כאן אנו רוצים לאסוף Author → Papers בטבלה נפרדת כדי לבנות פונקציונליות חיפוש. פשוט לאסוף על ידי המחבר. 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" ) ) abstractעריכה לחלק את הפריטים לחתיכות, להטביע כל חתיכה ולאסוף את ההטבות שלהם. לעתים, הפרוטוקול יכול להיות ארוך מאוד. 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" ) ) לאחר שלב זה, אתה צריך להכניס את חתיכות החתיכות של כל נייר. איסוף 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"], ) ייצוא לבסוף, אנו מייצרים את הנתונים ל- 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, אתה יכול לעשות קו אחד לעבור על מסדי נתונים Vector אחרים נתמכים כגון Qdrant, ראה זה לפרטים נוספים מדריך אנו שואפים להסטנדרטיזציה של ממשקים ולהפוך את זה כמו בניית LEGO. צפייה בCocoInsight צעד אחר צעד אתה יכול ללכת דרך הפרויקט צעד אחר צעד ב לראות CocoInsight exactly how each field is constructed and what happens behind the scenes. מחפשים את האינדקס אתה יכול להתייחס לחלק זה של אודות טקסטים Embedded כיצד לבנות שאלה נגד Embeddings. נכון לעכשיו, CocoIndex אינו מספק ממשק שאילתות נוסף.אנו יכולים לכתוב SQL או לסמוך על מנוע השאילתות על ידי אחסון היעד. מסדי נתונים רבים כבר אופטימיזציה יישומים שאילתות עם שיטות הטובות שלהם לחלל השאילתה יש פתרונות מצוינים לשאילתה, לדירוג מחדש ופונקציונליות אחרת הקשורה לחיפוש. אם אתה צריך עזרה עם כתיבת השאלה, אנא תרגיש חופשי ליצור איתנו קשר ב . מחלוקת תומך בנו אנחנו משתפרים כל הזמן, ועוד תכונות ודוגמאות יגיעו בקרוב. אם המאמר הזה עוזר לך, אנא תן לנו כוכב כדי לעזור לנו לגדול. Github תודה על הקריאה!