Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,10 @@
},
"files.associations": {
"*.pdl": "yaml",
}
},
"python.testing.pytestArgs": [
"."
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}
1 change: 0 additions & 1 deletion examples/tutorial/parser-regex.pdl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ text:
parameters:
# Tell the LLM to stop after generating an exclamation point.
stop: ['!']
spec: {"name": string}
parser:
spec:
name: string
Expand Down
34 changes: 27 additions & 7 deletions examples/tutorial/structured_decoding.pdl
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
# Expected not to type check
description: Creating JSON Data
defs:
data:
read: type_checking_data.yaml
parser: yaml
spec: { questions: [string], answers: [object] }
text:
- role: system
text: You are an AI language model developed by IBM Research. You are a cautious assistant. You carefully follow instructions. You are helpful and harmless and you follow ethical guidelines and promote positive behavior.
contribute: [context]
- "\nWhat is the color of the sky? Write it as JSON\n"
- model: watsonx/ibm/granite-34b-code-instruct
parser: json
spec: { color: string }
- model: ollama_chat/granite3.2:2b
def: model_output
input:
array:
- role: user
content:
text:
- for:
question: ${ data.questions }
answer: ${ data.answers }
repeat: |
${ question }
${ answer }
- >
Question: Generate only a JSON object with fields 'name' and 'age' and set them appropriately. Write the age all in letters. Only generate a single JSON object and nothing else.
spec: {name: string, age: integer}
parser: json
parameters:
stop: ["Question"]
temperature: 0
3 changes: 1 addition & 2 deletions examples/tutorial/type_checking.pdl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ defs:
text:
- model: ollama_chat/granite3.2:2b
def: model_output
spec: {name: string, age: integer}
input:
array:
- role: user
Expand All @@ -22,7 +21,7 @@ text:
${ answer }
- >
Question: Generate only a JSON object with fields 'name' and 'age' and set them appropriately. Write the age all in letters. Only generate a single JSON object and nothing else.
parser: yaml
parser: json
parameters:
stop: ["Question"]
temperature: 0
Expand Down
29 changes: 29 additions & 0 deletions examples/tutorial/type_error.pdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Expected not to type check
description: Creating JSON Data
defs:
data:
read: type_checking_data.yaml
parser: yaml
spec: { questions: [string], answers: [object] }
text:
- model: ollama_chat/granite3.2:2b
def: model_output
input:
array:
- role: user
content:
text:
- for:
question: ${ data.questions }
answer: ${ data.answers }
repeat: |
${ question }
${ answer }
- >
Question: Generate only a JSON object with fields 'name' and 'age' and set them appropriately. Write the age all in letters. Only generate a single JSON object and nothing else.
spec: {name: string, age: integer}
parser: json
structuredDecoding: false
parameters:
stop: ["Question"]
temperature: 0
23 changes: 12 additions & 11 deletions pdl-live-react/src/pdl_ast.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,6 @@ export type Anyof = PatternType[]
export type Array = PatternType[]
export type Any = null
export type ExpressionBool = LocalizedExpression | boolean | string
export type PdlCaseResult = boolean | null
export type PdlIfResult = boolean | null
export type PdlMatched = boolean | null
/**
* List of cases to match.
*
Expand Down Expand Up @@ -463,7 +460,7 @@ export type Aggregator = "context" | FileAggregatorConfig
* Documentation associated to the aggregator config.
*
*/
export type Description1 = string | null
export type Description = string | null
/**
* Name of the file to which contribute.
*/
Expand Down Expand Up @@ -1015,9 +1012,9 @@ export interface RegexParser {
* Single requirement definition.
*/
export interface RequirementType {
description: unknown
evaluate: Evaluate
transformContext: Transformcontext
expect: unknown
evaluate?: Evaluate
transformContext?: Transformcontext
}
export interface LocalizedExpression {
pdl__expr: PdlExpr
Expand Down Expand Up @@ -1191,6 +1188,10 @@ export interface LitellmModelBlock {
*/
model: LocalizedExpression | string
parameters?: Parameters1
/**
* Perform structured decoding if possible (i.e., `parser` and `spec` are provided and the inference platform supports it).
*/
structuredDecoding?: boolean | null
}
/**
* Set of definitions executed before the execution of the block.
Expand Down Expand Up @@ -2068,9 +2069,9 @@ export interface MatchCase {
case?: PatternType | null
if?: ExpressionBool | null
then: BlockType
pdl__case_result?: PdlCaseResult
pdl__if_result?: PdlIfResult
pdl__matched?: PdlMatched
pdl__case_result?: boolean | null
pdl__if_result?: boolean | null
pdl__matched?: boolean | null
}
/**
* Match any of the patterns.
Expand Down Expand Up @@ -3384,7 +3385,7 @@ export interface Defs20 {
[k: string]: BlockType
}
export interface FileAggregatorConfig {
description?: Description1
description?: Description
file: File1
mode?: Mode1
encoding?: Encoding
Expand Down
51 changes: 21 additions & 30 deletions src/pdl/pdl-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2645,6 +2645,11 @@
"default": null,
"description": "Parameters to send to the model.\n ",
"title": "Parameters"
},
"structuredDecoding": {
"$ref": "#/$defs/OptionalBool",
"default": true,
"description": "Perform structured decoding if possible (i.e., `parser` and `spec` are provided and the inference platform supports it)."
}
},
"required": [
Expand Down Expand Up @@ -3430,40 +3435,16 @@
"$ref": "#/$defs/BlockType"
},
"pdl__case_result": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Pdl Case Result"
"$ref": "#/$defs/OptionalBool",
"default": null
},
"pdl__if_result": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Pdl If Result"
"$ref": "#/$defs/OptionalBool",
"default": null
},
"pdl__matched": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Pdl Matched"
"$ref": "#/$defs/OptionalBool",
"default": null
}
},
"required": [
Expand Down Expand Up @@ -3798,6 +3779,16 @@
}
]
},
"OptionalBool": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"OptionalBoolOrStr": {
"anyOf": [
{
Expand Down
10 changes: 7 additions & 3 deletions src/pdl/pdl_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ def _ensure_lower(value):
"""Optional string."""
OptionalInt = TypeAliasType("OptionalInt", Optional[int])
"""Optional integer."""
OptionalBool = TypeAliasType("OptionalBool", Optional[bool])
"""Optional Boolean."""
OptionalBoolOrStr = TypeAliasType("OptionalBoolOrStr", Optional[Union[bool, str]])
"""Optional boolean or string."""
OptionalAny = TypeAliasType("OptionalAny", Optional[Any])
Expand Down Expand Up @@ -629,6 +631,8 @@ class LitellmModelBlock(ModelBlock):
parameters: Optional[LitellmParameters | ExpressionType[dict]] = None
"""Parameters to send to the model.
"""
structuredDecoding: OptionalBool = True
"""Perform structured decoding if possible (i.e., `parser` and `spec` are provided and the inference platform supports it)."""


class GraniteioProcessor(BaseModel):
Expand Down Expand Up @@ -835,9 +839,9 @@ class MatchCase(BaseModel):
"""Branch to execute if the value is matched and the condition is satisfied.
"""
# Field for internal use
pdl__case_result: Optional[bool] = None
pdl__if_result: Optional[bool] = None
pdl__matched: Optional[bool] = None
pdl__case_result: OptionalBool = None
pdl__if_result: OptionalBool = None
pdl__matched: OptionalBool = None


class MatchBlock(StructuredBlock):
Expand Down
2 changes: 2 additions & 0 deletions src/pdl/pdl_dumper.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ def block_to_dict( # noqa: C901
d["parameters"] = expr_to_dict(block.parameters, json_compatible)
if block.modelResponse is not None:
d["modelResponse"] = block.modelResponse
if not block.structuredDecoding:
d["structuredDecoding"] = block.structuredDecoding
if block.pdl__usage is not None:
d["pdl__usage"] = usage_to_dict(block.pdl__usage)
if block.pdl__model_input is not None:
Expand Down
2 changes: 1 addition & 1 deletion src/pdl/pdl_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1923,9 +1923,9 @@ def generate_client_response_streaming(
scope.get("pdl_model_default_parameters", []),
)
msg_stream = LitellmModel.generate_text_stream(
block,
model_id=value_of_expr(block.model),
messages=model_input,
spec=block.spec,
parameters=litellm_parameters_to_dict(parameters),
)
case GraniteioModelBlock():
Expand Down
9 changes: 6 additions & 3 deletions src/pdl/pdl_llms.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ async def async_generate_text(
) -> tuple[dict[str, Any], Any]:
try:
spec = block.spec
parameters = set_structured_decoding_parameters(spec, parameters)
if block.structuredDecoding:
parameters = set_structured_decoding_parameters(spec, parameters)
if parameters.get("mock_response") is not None:
import litellm

Expand Down Expand Up @@ -140,12 +141,14 @@ def update_end_nanos(future):

@staticmethod
def generate_text_stream(
block: LitellmModelBlock,
model_id: str,
messages: ModelInput,
spec: Any,
parameters: dict[str, Any],
) -> Generator[dict[str, Any], Any, Any]:
parameters = set_structured_decoding_parameters(spec, parameters)
spec = block.spec
if block.structuredDecoding:
parameters = set_structured_decoding_parameters(spec, parameters)
from litellm import completion

response = completion(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name": "John", "age": 30}
1 change: 1 addition & 0 deletions tests/results/examples/tutorial/type_checking.0.result
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name": "John", "age": "twentyfive"}
3 changes: 1 addition & 2 deletions tests/test_examples_run.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ skip:
- examples/rag/pdf_index.pdl
- examples/rag/pdf_query.pdl
- examples/rag/rag_library1.pdl
- examples/tutorial/structured_decoding.pdl
- pdl-live-react/src-tauri/tests/cli/code-python.pdl
- pdl-live-react/demos/error.pdl
- pdl-live-react/demos/demo1.pdl
Expand Down Expand Up @@ -100,7 +99,7 @@ expected_runtime_error:
- examples/callback/repair_prompt.pdl
- examples/demos/repair_prompt.pdl
- examples/tutorial/type_list.pdl
- examples/tutorial/type_checking.pdl
- examples/tutorial/type_error.pdl
- tests/data/line/hello3.pdl
- tests/data/line/hello9.pdl
- tests/data/line/hello12.pdl
Expand Down