Palimpzest (PZ)

repository·main·Indexed 42 days ago

https://github.com/mitdbg/palimpzest

A system for processing AI-powered analytical queries using a declarative language. It features a cost-based optimizer called Abacus for semantic operator systems and supports a lazy execution model via pz.Dataset. The system includes tools for PDF processing and equation extraction, as well as a ContextManager for persistent storage and vector indexing using ChromaDB.

Tokens
33.6K
Snippets
101
Records
141
Agent score
54%

What's inside Palimpzest

  1. Overview of Palimpzest (PZ)

    main

    Palimpzest (PZ) is a declarative system designed to optimize AI workloads, specifically Semantic Analytics Applications (SAPPs). Instead of manually orchestrating models, prompts, and data operations, developers define their queries in a declarative language.

    Palimpzest's core value proposition is its ability to automatically explore the search space of AI models, prompting techniques, and foundation model optimizations to implement a query plan with the best trade-offs between:

    • Runtime: Execution speed.
    • Financial Cost: The monetary expense of inference.
    • Output Data Quality: The accuracy and reliability of the results.

    By using Palimpzest, developers can achieve significant performance gains (e.g., up to 90.3x speedup and 9.1x lower cost compared to a single-threaded GPT-4 baseline) without manual tuning of the underlying execution strategy.

  2. Explore available semantic operators in PZ

    main

    PZ provides several semantic operators for LLM-powered data processing. You can find detailed guides for each below:

    • Semantic Map and Flat Map: Transform data using LLM reasoning.
    • Semantic Filter: Filter datasets based on semantic criteria.
    • Semantic Join: Join datasets based on semantic relationships rather than exact key matches.
    • Semantic Aggregate: Perform aggregations using semantic logic.
    • Semantic Top-K: Retrieve the top-K most relevant items based on semantic similarity.
  3. Available Palimpsest Tools

    main

    Palimpsest provides specialized tools for document processing and equation extraction. The catalog is divided into two main categories:

    PDF Processing Tools

    • Papermage lambda service: Supports parallel processing for PDF documents.
    • Cosmos literature pdf processing service: Extracts paper text, tables, plots, diagrams, and equation images from literature PDFs.

    Equation Extraction Tools (Image to LaTeX)

    • GPT4V equation extraction service: High-fidelity extraction using GPT-4V.
    • SKEMA equation extraction service: An alternative service, noted to have lower accuracy.
  4. How the Palimpzest optimization lifecycle works

    main

    Palimpzest transforms a high-level declarative program into an optimized physical execution plan through several stages:

    1. Logical Plan Compilation: The user's Python code is compiled into an initial logical plan.
    2. Logical Optimization: The system transforms the initial plan into a set of optimized logical plans.
    3. Physical Optimization: The system generates a large set of candidate physical plans from the logical plans.
    4. Sentinel Execution: Palimpzest executes "sentinel plans" (small samples) to gather real-world execution data.
    5. Cost Estimation: The sample data is used to improve the accuracy of cost, time, and quality estimates for the candidate physical plans.
    6. Policy-based Selection: The system selects the best plan based on the user's specified policy (e.g., minimizing cost while maintaining a quality threshold).
    7. Final Execution: The selected plan is executed on the full dataset to yield results.
  5. How semantic operators and declarative programming work in Palimpzest

    main

    Palimpzest (PZ) uses a declarative programming model. Instead of specifying how to perform a computation, you declare what you want to achieve using semantic operators.

    Core semantic operators include:

    • sem_filter(): Selects data that satisfies a natural language predicate.
    • sem_map(): Specifies a set of fields (with names, types, and descriptions) that PZ must compute for each item.
    • sem_join(): Performs a semantic join between two datasets.
    • sem_aggregate(): Performs semantic aggregation over a dataset.
    • sem_flat_map(): Produces multiple outputs per input (e.g., extracting multiple authors).
    • sem_topk(): Retrieves the top-k relevant entries from a vector database using a search string.

    Because the program is declarative, PZ's optimizer can automatically select the best execution strategy (model selection, ensemble methods, refinement strategies, etc.) to meet your constraints.

  6. What are Semantic Analytics Applications (SAPPs)?

    main

    Semantic Analytics Applications (SAPPs) are a class of complex AI-powered workloads that interleave traditional data processing with AI-driven semantic reasoning. They are characterized by three main traits:

    1. Interleaved Processing: They combine conventional data processing (like regular expressions, UDFs, or distance calculations) with semantic reasoning (like LLM-based classification or image analysis).
    2. Data Intensity: They operate on large datasets, often ranging from hundreds to millions of records.
    3. Decomposable Structure: They can be broken down into an execution tree of distinct operations performed over sets of data objects.

    Examples include Legal Discovery (filtering emails based on semantic intent), Real Estate Search (combining image analysis with geographic calculations), and Medical Schema Matching (parsing research papers to extract and integrate datasets).

  7. How to create a custom dataset by subclassing pz.IterDataset

    main

    To support heterogeneous file types or complex input fields, you can create a custom dataset by subclassing pz.IterDataset.

    An IterDataset provides an interface for iterating over records, where each record is a dictionary mapping column names to data values. To implement a custom dataset, you must:

    1. Initialize with id and schema: The id must be a unique string across your program. The schema is a list of dictionaries defining the columns. Each dictionary in the schema must contain:
      • name: The column name (string).
      • type: The data type (e.g., str, int, float).
      • desc: A brief description (string).
    2. Implement __len__(): Return the total number of records in the dataset.
    3. Implement __getitem__(idx): Return a dictionary for the record at idx. The keys must match the schema names, and values must match the specified types.

    Once implemented, you can use standard PZ operations like .sem_filter(), .sem_map(), or .filter() on the dataset instance.

    import palimpzest as pz
    
    # 1. Define the schema
    animal_schema = [
        {"name": "age", "type": int, "desc": "The animal's age in years"},
        {"name": "animal", "type": str, "desc": "The type of animal (dog, cat, etc.)"},
        {"name": "name", "type": str, "desc": "The name of the animal"},
    ]
    
    # 2. Subclass IterDataset
    class AnimalDataset(pz.IterDataset):
        def __init__(self, ages: list[int], animals: list[str], names: list[str]) -> None:
            super().__init__(id="zoo-animals", schema=animal_schema)
            self.ages = ages
            self.animals = animals
            self.names = names
    
        def __len__(self) -> int:
            return len(self.names)
    
        def __getitem__(self, idx: int) -> dict:
            return {
                "age": self.ages[idx], 
                "animal": self.animals[idx], 
                "name": self.names[idx]
            }
    
    # 3. Usage
    ages = [5, 3, 8, 2, 4]
    animals = ["dog", "cat", "parrot", "rabbit", "hamster"]
    names = ["Buddy", "Whiskers", "Polly", "Thumper", "Nibbles"]
    dataset = AnimalDataset(ages, animals, names)
    
    # Apply PZ operations
    dataset = dataset.sem_filter("The animal has four legs and is younger than five years old.")
    output = dataset.run(max_quality=True)
    print(output.to_df())
  8. Manage LLM context in `sem_join()` using `depends_on`

    main

    By default, sem_join() passes all fields from both the left and right datasets into the LLM prompt to evaluate the join condition. To optimize performance or ensure the LLM only sees specific data, use the depends_on parameter.

    When using depends_on, you must refer to the right dataset's fields using the _right suffix if they overlap with the left dataset's field names (e.g., contents_right).

    Note: Fields not listed in depends_on are not dropped from the resulting dataset; they are simply excluded from the prompt sent to the LLM.

    # Only the 'contents' fields are sent to the LLM for the join predicate
    joined_ds = text_ds.sem_join(
        image_ds,
        "The description matches the animal in the image",
        depends_on=["contents", "contents_right"],
    )
  9. Manage LLM context with `depends_on` in `sem_agg()`

    main

    When using sem_agg(), the operator by default includes all fields from the input dataset in the prompt sent to the LLM. To optimize token usage and focus the model's attention, use the depends_on parameter to explicitly specify which input fields are necessary for the aggregation.

    For example, if you are using a pz.TextFileDataset, each record contains filename and contents. If the aggregation only requires the text, you should pass depends_on=["contents"] to avoid sending unnecessary metadata like the filename to the LLM.

    ds = ds.sem_agg(
        col={'name': 'summary', 'type': str, 'desc': 'A summary of the text'},
        agg="Summarize the text",
        depends_on=["contents"],
    )
  10. Understand the difference between semantic and relational operators in PZ

    main

    Palimpzest (PZ) operators are categorized into two main types based on how they process data:

    1. Semantic Operators: These leverage Large Language Models (LLMs) to perform data processing tasks that require understanding meaning, context, or reasoning (e.g., mapping, filtering, or joining based on semantic similarity).
    2. Relational (Non-semantic) Operators: These perform standard data manipulation tasks that do not require LLM reasoning, typically following traditional relational algebra or data processing logic.

    Use semantic operators when the task requires 'understanding' the content of the data, and relational operators for structured data transformations.