diff --git a/pdl-live-react/src/pdl_ast.d.ts b/pdl-live-react/src/pdl_ast.d.ts index 45c3b24b8..a8d769932 100644 --- a/pdl-live-react/src/pdl_ast.d.ts +++ b/pdl-live-react/src/pdl_ast.d.ts @@ -697,7 +697,7 @@ export type Fallback5 = | EmptyBlock | null /** - * Role of associated to the message. + * Role associated to the block and sub-blocks. * Typical roles are `system`, `user`, and `assistant`, * but there may be other roles such as `available_tools`. */ @@ -716,7 +716,7 @@ export type Context5 = * */ export type PdlId5 = string | null -export type PdlIsLeaf5 = false +export type PdlIsLeaf5 = true export type Kind5 = "message" export type Content = | boolean @@ -3491,7 +3491,7 @@ export interface MessageBlock { contribute?: Contribute5 parser?: Parser5 fallback?: Fallback5 - role: Role5 + role?: Role5 context?: Context5 pdl__id?: PdlId5 pdl__result?: unknown diff --git a/src/pdl/pdl-schema.json b/src/pdl/pdl-schema.json index 334e18911..d04826128 100644 --- a/src/pdl/pdl-schema.json +++ b/src/pdl/pdl-schema.json @@ -7981,7 +7981,8 @@ "type": "null" } ], - "description": "Role of associated to the message.\nTypical roles are `system`, `user`, and `assistant`,\nbut there may be other roles such as `available_tools`.", + "default": null, + "description": "Role associated to the block and sub-blocks.\nTypical roles are `system`, `user`, and `assistant`,\nbut there may be other roles such as `available_tools`.", "title": "Role" }, "context": { @@ -8048,8 +8049,8 @@ "default": null }, "pdl__is_leaf": { - "const": false, - "default": false, + "const": true, + "default": true, "title": "Pdl Is Leaf", "type": "boolean" }, @@ -8176,7 +8177,6 @@ } }, "required": [ - "role", "content" ], "title": "MessageBlock", diff --git a/src/pdl/pdl_ast.py b/src/pdl/pdl_ast.py index 27b4f95c3..481dba588 100644 --- a/src/pdl/pdl_ast.py +++ b/src/pdl/pdl_ast.py @@ -580,15 +580,10 @@ class ObjectBlock(StructuredBlock): object: dict[str, "BlockType"] | list["BlockType"] -class MessageBlock(StructuredBlock): +class MessageBlock(LeafBlock): """Create a message.""" kind: Literal[BlockKind.MESSAGE] = BlockKind.MESSAGE - role: RoleType # pyright: ignore - """Role of associated to the message. - Typical roles are `system`, `user`, and `assistant`, - but there may be other roles such as `available_tools`. - """ # pyright: ignore content: "BlockType" """Content of the message.""" name: Optional[ExpressionType[str]] = None diff --git a/src/pdl/pdl_interpreter.py b/src/pdl/pdl_interpreter.py index 973d9eed7..f6bacc23b 100644 --- a/src/pdl/pdl_interpreter.py +++ b/src/pdl/pdl_interpreter.py @@ -570,28 +570,26 @@ def process_block_body( if state.yield_result and not iteration_state.yield_result: yield_result(result, block.kind) case MessageBlock(): - content, background, scope, trace = process_block_of( + content, _, scope, trace = process_block_of( block, "content", state, scope, loc, ) - name, block = process_expr_of( - block, "name", scope, loc # pyright: ignore - ) # pyright: ignore - tool_call_id, block = process_expr_of( - block, "tool_call_id", scope, loc # pyright: ignore - ) # pyright: ignore - result = PdlDict( - { - "role": state.role, - "content": content, - "name": name, - "tool_call_id": tool_call_id, - "defsite": block.pdl__id, - } - ) + d = { + "role": state.role, + "content": content, + "defsite": block.pdl__id, + } + if block.name is not None: + name, block = process_expr_of(block, "name", scope, loc) + d["name"] = name + if block.tool_call_id is not None: + tool_call_id, block = process_expr_of(block, "tool_call_id", scope, loc) + d["tool_call_id"] = tool_call_id + result = PdlDict(d) + background = PdlList([result]) case IfBlock(): b, if_trace = process_condition_of(block, "condition", scope, loc, "if") if b: diff --git a/tests/test_messages.py b/tests/test_messages.py index 828488435..b02badf82 100644 --- a/tests/test_messages.py +++ b/tests/test_messages.py @@ -1,7 +1,7 @@ from pdl.pdl import exec_str -def test_messages1(): +def test_message1(): prog_str = """ description: Messages block array: @@ -17,15 +17,11 @@ def test_messages1(): "role": "system", "content": "You are a helpful software engineer. You write clear, concise, well-commented code.", "defsite": "array.0.message", - "name": None, - "tool_call_id": None, }, { "role": "user", "content": "Write a Python function that implement merge sort.", "defsite": "array.1.message", - "name": None, - "tool_call_id": None, }, ] assert context == [ @@ -40,3 +36,73 @@ def test_messages1(): "defsite": "array.1.message", }, ] + + +def test_message2(): + prog_str = """ +description: Messages block +role: user +content: + array: + - Hello + - Bye +""" + result = exec_str(prog_str, output="all") + context = result["scope"]["pdl_context"] + assert result["result"] == { + "role": "user", + "content": ["Hello", "Bye"], + "defsite": "message", + } + assert context == [ + { + "role": "user", + "content": ["Hello", "Bye"], + "defsite": "message", + }, + ] + + +def test_message3(): + prog_str = """ +description: Messages block +content: + data: {"a": 1} +""" + result = exec_str(prog_str, output="all") + context = result["scope"]["pdl_context"] + assert result["result"] == { + "role": "user", + "content": {"a": 1}, + "defsite": "message", + } + assert context == [ + { + "role": "user", + "content": {"a": 1}, + "defsite": "message", + }, + ] + + +def test_message4(): + prog_str = """ +description: Messages block +content: + text: + data: {"a": 1} +""" + result = exec_str(prog_str, output="all") + context = result["scope"]["pdl_context"] + assert result["result"] == { + "role": "user", + "content": '{"a": 1}', + "defsite": "message", + } + assert context == [ + { + "role": "user", + "content": '{"a": 1}', + "defsite": "message", + }, + ]