68 lines
2.2 KiB
Python
68 lines
2.2 KiB
Python
|
|
import json
|
||
|
|
import re
|
||
|
|
from typing import Any, Dict, Union
|
||
|
|
|
||
|
|
from guardrails.classes.output_type import OutputTypes
|
||
|
|
|
||
|
|
from guardrails.types.validator import ValidatorMap
|
||
|
|
from guardrails.prompt.prompt import Prompt
|
||
|
|
from guardrails.prompt.instructions import Instructions
|
||
|
|
from guardrails.types.inputs import MessageHistory
|
||
|
|
|
||
|
|
|
||
|
|
def prompt_uses_xml(prompt: str) -> bool:
|
||
|
|
xml_const_regx = re.compile(r"gr\..*xml_.*")
|
||
|
|
contains_xml_const = xml_const_regx.search(prompt) is not None
|
||
|
|
contains_xml_output = "xml_output_schema" in prompt
|
||
|
|
return contains_xml_output or contains_xml_const
|
||
|
|
|
||
|
|
|
||
|
|
def prompt_content_for_string_schema(
|
||
|
|
output_schema: Dict[str, Any], validator_map: ValidatorMap, json_path: str
|
||
|
|
) -> str:
|
||
|
|
# NOTE: Is this actually necessary?
|
||
|
|
# We should check how LLMs perform this this vs just sending the JSON Schema
|
||
|
|
prompt_content = ""
|
||
|
|
description = output_schema.get("description")
|
||
|
|
if description:
|
||
|
|
prompt_content += (
|
||
|
|
f"Here's a description of what I want you to generate: {description}"
|
||
|
|
)
|
||
|
|
validators = validator_map.get(json_path, [])
|
||
|
|
if len(validators):
|
||
|
|
prompt_content += (
|
||
|
|
"\n\nYour generated response should satisfy the following properties:"
|
||
|
|
)
|
||
|
|
for validator in validators:
|
||
|
|
prompt_content += f"\n- {validator.to_prompt()}"
|
||
|
|
|
||
|
|
prompt_content += "\n\nDon't talk; just go."
|
||
|
|
return prompt_content
|
||
|
|
|
||
|
|
|
||
|
|
# Supersedes Schema.transpile
|
||
|
|
def prompt_content_for_schema(
|
||
|
|
output_type: OutputTypes,
|
||
|
|
output_schema: Dict[str, Any],
|
||
|
|
validator_map: ValidatorMap,
|
||
|
|
json_path: str = "$",
|
||
|
|
) -> str:
|
||
|
|
if output_type == OutputTypes.STRING:
|
||
|
|
return prompt_content_for_string_schema(output_schema, validator_map, json_path)
|
||
|
|
return json.dumps(output_schema)
|
||
|
|
|
||
|
|
|
||
|
|
def messages_to_prompt_string(
|
||
|
|
messages: Union[list[dict[str, Union[str, Prompt, Instructions]]], MessageHistory],
|
||
|
|
) -> str:
|
||
|
|
messages_copy = ""
|
||
|
|
for msg in messages:
|
||
|
|
content = (
|
||
|
|
msg["content"].source # type: ignore
|
||
|
|
if isinstance(msg["content"], Prompt)
|
||
|
|
or isinstance(msg["content"], Instructions) # type: ignore
|
||
|
|
else msg["content"] # type: ignore
|
||
|
|
)
|
||
|
|
messages_copy += content
|
||
|
|
return messages_copy
|