Open In Colab

Guardrails Output Parsing#

If you’re opening this Notebook on colab, you will probably need to install LlamaIndex 🦙.

!pip install guardrails-ai

Download Data#

!mkdir -p 'data/paul_graham/'
!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt'
Will not apply HSTS. The HSTS database must be a regular and non-world-writable file.
ERROR: could not open HSTS store at '/home/loganm/.wget-hsts'. HSTS will be disabled.
--2023-12-11 10:18:02--  https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/paul_graham/paul_graham_essay.txt
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.110.133, 185.199.109.133, 185.199.108.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.110.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 75042 (73K) [text/plain]
Saving to: ‘data/paul_graham/paul_graham_essay.txt’

data/paul_graham/pa 100%[===================>]  73.28K  --.-KB/s    in 0.04s   

2023-12-11 10:18:02 (1.70 MB/s) - ‘data/paul_graham/paul_graham_essay.txt’ saved [75042/75042]

Load documents, build the VectorStoreIndex#

import logging
import sys

logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))

from llama_index import VectorStoreIndex, SimpleDirectoryReader
from IPython.display import Markdown, display

import os

os.environ["OPENAI_API_KEY"] = "sk-..."
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/home/loganm/llama_index_proper/llama_index/docs/examples/output_parsing/GuardrailsDemo.ipynb Cell 8 line 7
      <a href='vscode-notebook-cell://wsl%2Bubuntu/home/loganm/llama_index_proper/llama_index/docs/examples/output_parsing/GuardrailsDemo.ipynb#W6sdnNjb2RlLXJlbW90ZQ%3D%3D?line=3'>4</a> logging.basicConfig(stream=sys.stdout, level=logging.INFO)
      <a href='vscode-notebook-cell://wsl%2Bubuntu/home/loganm/llama_index_proper/llama_index/docs/examples/output_parsing/GuardrailsDemo.ipynb#W6sdnNjb2RlLXJlbW90ZQ%3D%3D?line=4'>5</a> logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))
----> <a href='vscode-notebook-cell://wsl%2Bubuntu/home/loganm/llama_index_proper/llama_index/docs/examples/output_parsing/GuardrailsDemo.ipynb#W6sdnNjb2RlLXJlbW90ZQ%3D%3D?line=6'>7</a> from llama_index import VectorStoreIndex, SimpleDirectoryReader
      <a href='vscode-notebook-cell://wsl%2Bubuntu/home/loganm/llama_index_proper/llama_index/docs/examples/output_parsing/GuardrailsDemo.ipynb#W6sdnNjb2RlLXJlbW90ZQ%3D%3D?line=7'>8</a> from IPython.display import Markdown, display
     <a href='vscode-notebook-cell://wsl%2Bubuntu/home/loganm/llama_index_proper/llama_index/docs/examples/output_parsing/GuardrailsDemo.ipynb#W6sdnNjb2RlLXJlbW90ZQ%3D%3D?line=9'>10</a> import os

File ~/llama_index_proper/llama_index/llama_index/__init__.py:21
     17 from llama_index.embeddings import OpenAIEmbedding
     19 # indices
     20 # loading
---> 21 from llama_index.indices import (
     22     ComposableGraph,
     23     DocumentSummaryIndex,
     24     GPTDocumentSummaryIndex,
     25     GPTKeywordTableIndex,
     26     GPTKnowledgeGraphIndex,
     27     GPTListIndex,
     28     GPTRAKEKeywordTableIndex,
     29     GPTSimpleKeywordTableIndex,
     30     GPTTreeIndex,
     31     GPTVectorStoreIndex,
     32     KeywordTableIndex,
     33     KnowledgeGraphIndex,
     34     ListIndex,
     35     RAKEKeywordTableIndex,
     36     SimpleKeywordTableIndex,
     37     SummaryIndex,
     38     TreeIndex,
     39     VectorStoreIndex,
     40     load_graph_from_storage,
     41     load_index_from_storage,
     42     load_indices_from_storage,
     43 )
     45 # structured
     46 from llama_index.indices.common.struct_store.base import SQLDocumentContextBuilder

File ~/llama_index_proper/llama_index/llama_index/indices/__init__.py:29
     27 from llama_index.indices.list import GPTListIndex, ListIndex, SummaryIndex
     28 from llama_index.indices.list.base import GPTListIndex, ListIndex, SummaryIndex
---> 29 from llama_index.indices.loading import (
     30     load_graph_from_storage,
     31     load_index_from_storage,
     32     load_indices_from_storage,
     33 )
     34 from llama_index.indices.managed.vectara import VectaraIndex
     35 from llama_index.indices.multi_modal import MultiModalVectorStoreIndex

File ~/llama_index_proper/llama_index/llama_index/indices/loading.py:6
      4 from llama_index.indices.base import BaseIndex
      5 from llama_index.indices.composability.graph import ComposableGraph
----> 6 from llama_index.indices.registry import INDEX_STRUCT_TYPE_TO_INDEX_CLASS
      7 from llama_index.storage.storage_context import StorageContext
      9 logger = logging.getLogger(__name__)

File ~/llama_index_proper/llama_index/llama_index/indices/registry.py:12
     10 from llama_index.indices.knowledge_graph.base import KnowledgeGraphIndex
     11 from llama_index.indices.list.base import SummaryIndex
---> 12 from llama_index.indices.multi_modal import MultiModalVectorStoreIndex
     13 from llama_index.indices.struct_store.pandas import PandasIndex
     14 from llama_index.indices.struct_store.sql import SQLStructStoreIndex

File ~/llama_index_proper/llama_index/llama_index/indices/multi_modal/__init__.py:3
      1 """Vector-store based data structures."""
----> 3 from llama_index.indices.multi_modal.base import MultiModalVectorStoreIndex
      4 from llama_index.indices.multi_modal.retriever import MultiModalVectorIndexRetriever
      6 __all__ = [
      7     "MultiModalVectorStoreIndex",
      8     "MultiModalVectorIndexRetriever",
      9 ]

File ~/llama_index_proper/llama_index/llama_index/indices/multi_modal/base.py:19
     12 from llama_index.embeddings.utils import EmbedType, resolve_embed_model
     13 from llama_index.indices.utils import (
     14     async_embed_image_nodes,
     15     async_embed_nodes,
     16     embed_image_nodes,
     17     embed_nodes,
     18 )
---> 19 from llama_index.indices.vector_store.base import VectorStoreIndex
     20 from llama_index.schema import BaseNode, ImageNode
     21 from llama_index.service_context import ServiceContext

File ~/llama_index_proper/llama_index/llama_index/indices/vector_store/__init__.py:4
      1 """Vector-store based data structures."""
      3 from llama_index.indices.vector_store.base import GPTVectorStoreIndex, VectorStoreIndex
----> 4 from llama_index.indices.vector_store.retrievers import (
      5     VectorIndexAutoRetriever,
      6     VectorIndexRetriever,
      7 )
      9 __all__ = [
     10     "VectorStoreIndex",
     11     "VectorIndexRetriever",
   (...)
     14     "GPTVectorStoreIndex",
     15 ]

File ~/llama_index_proper/llama_index/llama_index/indices/vector_store/retrievers/__init__.py:4
      1 from llama_index.indices.vector_store.retrievers.retriever import (  # noqa: I001
      2     VectorIndexRetriever,
      3 )
----> 4 from llama_index.indices.vector_store.retrievers.auto_retriever import (
      5     VectorIndexAutoRetriever,
      6 )
      8 __all__ = [
      9     "VectorIndexRetriever",
     10     "VectorIndexAutoRetriever",
     11 ]

File ~/llama_index_proper/llama_index/llama_index/indices/vector_store/retrievers/auto_retriever/__init__.py:1
----> 1 from llama_index.indices.vector_store.retrievers.auto_retriever.auto_retriever import (
      2     VectorIndexAutoRetriever,
      3 )
      5 __all__ = [
      6     "VectorIndexAutoRetriever",
      7 ]

File ~/llama_index_proper/llama_index/llama_index/indices/vector_store/retrievers/auto_retriever/auto_retriever.py:9
      7 from llama_index.indices.vector_store.base import VectorStoreIndex
      8 from llama_index.indices.vector_store.retrievers import VectorIndexRetriever
----> 9 from llama_index.indices.vector_store.retrievers.auto_retriever.output_parser import (
     10     VectorStoreQueryOutputParser,
     11 )
     12 from llama_index.indices.vector_store.retrievers.auto_retriever.prompts import (
     13     DEFAULT_VECTOR_STORE_QUERY_PROMPT_TMPL,
     14     VectorStoreQueryPrompt,
     15 )
     16 from llama_index.output_parsers.base import OutputParserException, StructuredOutput

File ~/llama_index_proper/llama_index/llama_index/indices/vector_store/retrievers/auto_retriever/output_parser.py:3
      1 from typing import Any
----> 3 from llama_index.output_parsers.base import StructuredOutput
      4 from llama_index.output_parsers.utils import parse_json_markdown
      5 from llama_index.types import BaseOutputParser

File ~/llama_index_proper/llama_index/llama_index/output_parsers/__init__.py:3
      1 """Output parsers."""
----> 3 from llama_index.output_parsers.guardrails import GuardrailsOutputParser
      4 from llama_index.output_parsers.langchain import LangchainOutputParser
      5 from llama_index.output_parsers.pydantic import PydanticOutputParser

File ~/llama_index_proper/llama_index/llama_index/output_parsers/guardrails.py:9
      6 from deprecated import deprecated
      8 try:
----> 9     from guardrails import Guard
     10 except ImportError:
     11     Guard = None

File ~/.cache/pypoetry/virtualenvs/llama-index-4a-wkI5X-py3.11/lib/python3.11/site-packages/guardrails/__init__.py:3
      1 # Set up __init__.py so that users can do from guardrails import Response, Schema, etc.
----> 3 from guardrails.guard import Guard
      4 from guardrails.llm_providers import PromptCallableBase
      5 from guardrails.logging_utils import configure_logging

File ~/.cache/pypoetry/virtualenvs/llama-index-4a-wkI5X-py3.11/lib/python3.11/site-packages/guardrails/guard.py:10
      7 from eliot import add_destinations, start_action
      8 from pydantic import BaseModel
---> 10 from guardrails.llm_providers import get_async_llm_ask, get_llm_ask
     11 from guardrails.prompt import Instructions, Prompt
     12 from guardrails.rail import Rail

File ~/.cache/pypoetry/virtualenvs/llama-index-4a-wkI5X-py3.11/lib/python3.11/site-packages/guardrails/llm_providers.py:24
     19 except ImportError:
     20     cohere = None
     23 OPENAI_RETRYABLE_ERRORS = [
---> 24     openai.error.APIConnectionError,
     25     openai.error.APIError,
     26     openai.error.TryAgain,
     27     openai.error.Timeout,
     28     openai.error.RateLimitError,
     29     openai.error.ServiceUnavailableError,
     30 ]
     31 RETRYABLE_ERRORS = tuple(OPENAI_RETRYABLE_ERRORS)
     34 class PromptCallableException(Exception):

AttributeError: module 'openai' has no attribute 'error'
# load documents
documents = SimpleDirectoryReader("./data/paul_graham/").load_data()
index = VectorStoreIndex.from_documents(documents, chunk_size=512)
INFO:llama_index.token_counter.token_counter:> [build_index_from_documents] Total LLM token usage: 0 tokens
> [build_index_from_documents] Total LLM token usage: 0 tokens
INFO:llama_index.token_counter.token_counter:> [build_index_from_documents] Total embedding token usage: 18579 tokens
> [build_index_from_documents] Total embedding token usage: 18579 tokens

Define Query + Guardrails Spec#

from llama_index.output_parsers import GuardrailsOutputParser

Define custom QA and Refine Prompts

Define Guardrails Spec

# You can either define a RailSpec and initialise a Guard object from_rail_string()
# OR define Pydantic classes and initialise a Guard object from_pydantic()
# For more info: https://docs.guardrailsai.com/defining_guards/pydantic/
# Guardrails recommends Pydantic

from pydantic import BaseModel, Field
from typing import List
import guardrails as gd


class Point(BaseModel):
    # In all the fields below, you can define validators as well
    # Left out for brevity
    explanation: str = Field()
    explanation2: str = Field()
    explanation3: str = Field()


class BulletPoints(BaseModel):
    points: List[Point] = Field(
        description="Bullet points regarding events in the author's life."
    )


# Define the prompt
prompt = """
Query string here.

${gr.xml_prefix_prompt}

${output_schema}

${gr.json_suffix_prompt_v2_wo_none}
"""
from llama_index.llms import OpenAI

# Create a guard object
guard = gd.Guard.from_pydantic(output_class=BulletPoints, prompt=prompt)

# Create output parse object
output_parser = GuardrailsOutputParser(guard, llm=OpenAI())

# attach to an llm object
llm = OpenAI(output_parser=output_parser)
from llama_index.prompts.default_prompts import (
    DEFAULT_TEXT_QA_PROMPT_TMPL,
)

# take a look at the new QA template!
fmt_qa_tmpl = output_parser.format(DEFAULT_TEXT_QA_PROMPT_TMPL)
print(fmt_qa_tmpl)
Context information is below.
---------------------
{context_str}
---------------------
Given the context information and not prior knowledge, answer the query.
Query: {query_str}
Answer: 


Given below is XML that describes the information to extract from this document and the tags to extract it into.


<output>
    <list name="points" description="Bullet points regarding events in the author's life.">
        <object>
            <string name="explanation"/>
            <string name="explanation2"/>
            <string name="explanation3"/>
        </object>
    </list>
</output>



ONLY return a valid JSON object (no other text is necessary). The JSON MUST conform to the XML format, including any types and format requests e.g. requests for lists, objects and specific types. Be correct and concise.

Query Index#

from llama_index import ServiceContext

ctx = ServiceContext.from_defaults(llm=llm)

query_engine = index.as_query_engine(
    service_context=ctx,
)
response = query_engine.query(
    "What are the three items the author did growing up?",
)
INFO:llama_index.token_counter.token_counter:> [query] Total LLM token usage: 754 tokens
> [query] Total LLM token usage: 754 tokens
INFO:llama_index.token_counter.token_counter:> [query] Total embedding token usage: 11 tokens
> [query] Total embedding token usage: 11 tokens
print(response)
{
  "output": {
    "list": {
      "name": "points",
      "description": "Bullet points regarding events in the author's life.",
      "object": {
        "string": [
          {
            "name": "explanation",
            "content": "Writing short stories"
          },
          {
            "name": "explanation2",
            "content": "Programming on the IBM 1401"
          },
          {
            "name": "explanation3",
            "content": "Building a microcomputer"
          }
        ]
      }
    }
  }
}