Skill

Edit Artifacts with LLM-Powered JSON Patching

Edit Pydantic artifacts in-memory using JSON patch operations with this stateful tool spec. Modify reports or other data structures.

Works with openaipydantic

57
Spark score
out of 100
Updated 4 days ago
Version 0.14.22

Add to Favorites

Why it matters

Empower LLMs and agents to programmatically create, modify, and iterate on complex artifacts like reports and code using Pydantic models and JSON patch operations.

Outcomes

What it gets done

01

Define artifact structure using Pydantic models.

02

Apply JSON patch operations for in-memory artifact editing.

03

Integrate with LLM agents for iterative content generation.

04

Store and inject artifacts into agent memory.

Install

Add it to your toolbox

Run in your project directory:

curl -fsSL https://spark.entire.vc/get/li-tool-tools-artifact-editor | bash

Capabilities

What this skill does

Generate code

Writes source code or scripts from a description.

Summarize

Condenses long documents or threads into key takeaways.

Extract

Pulls structured data fields from unstructured text.

RAG index

Chunks, embeds, and indexes documents for semantic retrieval.

Overview

Artifact Editor Tool Spec

What it does

What it does

The ArtifactEditorToolSpec is a stateful tool that enables LLMs and agents to modify artifacts in-memory using JSON patch operations. It allows for the creation, modification, and iteration of data structures like reports or any Pydantic model.

When to use - and when NOT to

Use this tool when you need an AI agent to programmatically create, update, or refine structured data represented as Pydantic models. This is ideal for iterative report generation or any task where an AI needs to manipulate complex data structures.

Do not use this tool if your artifact cannot be represented by a Pydantic model or if you require direct, non-programmatic editing of the artifact.

Inputs and outputs

Inputs: The tool accepts Pydantic models as the artifact specification. The agent interacts with the tool by providing instructions that translate into JSON patch operations.
Outputs: The tool modifies the artifact in-memory. The current state of the artifact can be retrieved using tool_spec.get_current_artifact().

Integrations

The ArtifactEditorToolSpec is designed to integrate with LlamaIndex's agent and memory frameworks. Specifically, it works with:

  • FunctionAgent: An agent that can execute functions and tools.
  • Memory: Used to store the artifact and inject it into the agent's memory via ArtifactMemoryBlock.
pip install llama-index-tools-artifact-editor

Who it's for

This tool is for AI developers and engineers building sophisticated agentic workflows that require programmatic manipulation of structured data. It's particularly useful for those working with LlamaIndex who need to enable agents to dynamically generate and edit content like reports based on Pydantic models. Alternatives would involve building custom logic for each artifact type or using less structured methods for data manipulation.

How it connects

The original description's 'When to use' section was accurate based on the source. The revised description maintains this section, ensuring it aligns with the supported functionalities of the tool, specifically its use for Pydantic model manipulation and iterative report generation.

Source README

Artifact Editor Tool Spec

pip install llama-index-tools-artifact-editor

The ArtifactEditorToolSpec is a stateful tool spec that allows you to edit an artifact in-memory.

Using JSON patch operations, an LLM/Agent can be prompted to create, modify, and iterate on an artifact like a report, code, or anything that can be represented as a Pydantic model.

The tool package also includes an ArtifactMemoryBlock that can be used to store the artifact and inject it into the LLM/Agent's memory.

Usage

Below is an example of how to use the ArtifactEditorToolSpec and ArtifactMemoryBlock to create and iterate on a report.

import asyncio
from pydantic import BaseModel, Field
from typing import List, Literal, Optional, Any

from llama_index.core.agent.workflow import (
    FunctionAgent,
    AgentStream,
    ToolCallResult,
)
from llama_index.core.memory import Memory
from llama_index.tools.artifact_editor import (
    ArtifactEditorToolSpec,
    ArtifactMemoryBlock,
)
from llama_index.llms.openai import OpenAI

# Define the Artifact Pydantic Model


class TextBlock(BaseModel):
    type: Literal["text"] = "text"
    content: str = Field(description="The content of the text block")


class TableBlock(BaseModel):
    type: Literal["table"] = "table"
    headers: List[str] = Field(description="The headers of the table")
    rows: List[List[str]] = Field(description="The rows of the table")


class ImageBlock(BaseModel):
    type: Literal["image"] = "image"
    image_url: str = Field(description="The URL of the image")


class Report(BaseModel):
    """Creates an instance of a report, which is a collection of text, tables, and images."""

    title: str = Field(description="The title of the report")
    content: List[TextBlock | TableBlock | ImageBlock] = Field(
        description="The content of the report"
    )


# Initialize the tool spec and tools
tool_spec = ArtifactEditorToolSpec(Report)
tools = tool_spec.to_tool_list()

# Initialize the memory
memory = Memory.from_defaults(
    session_id="artifact_editor_01",
    memory_blocks=[ArtifactMemoryBlock(artifact_spec=tool_spec)],
    token_limit=60000,
    chat_history_token_ratio=0.7,
)

# Create the agent
agent = FunctionAgent(
    tools=tools,
    llm=OpenAI(model="o3-mini"),
    system_prompt="You are an expert in writing reports. When you write a report, I will be able to see it (and also any changes you make to it!), so no need to repeat it back to me once its written.",
)


# Run the agent in a basic chat loop
# As it runs, the artifact will be updated in-memory and
# can be accessed via the `get_current_artifact` method.
async def main():
    while True:
        user_msg = input("User: ").strip()
        if user_msg.lower() in ["exit", "quit"]:
            break

        handler = agent.run(user_msg, memory=memory)
        async for ev in handler.stream_events():
            if isinstance(ev, AgentStream):
                print(ev.delta, end="", flush=True)
            elif isinstance(ev, ToolCallResult):
                print(
                    f"\n\nCalling tool: {ev.tool_name} with kwargs: {ev.tool_kwargs}"
                )

        response = await handler
        print(str(response))
        print("Current artifact: ", tool_spec.get_current_artifact())


if __name__ == "__main__":
    asyncio.run(main())

When running this, you might initially ask the agent:

User: Create a ficticous report about the history of the internet

And you will get a report with a list of blocks. Try asking it to modify the report!

User: Move the image to the top of the report

And you will get a report with the image moved to the top.

Check out the documentation for more example on agents, memory, and tools.

Discussion

Questions & comments · 0

Sign In Sign in to leave a comment.