Skip to content

Commit 818ffc0

Browse files
authored
Example of call-back from PDL back to Python. (#136)
* Example of call-back from PDL back to Python. * Use result from callback in PDL, then return a different shape. Signed-off-by: Martin Hirzel <[email protected]> * renamed files and added more type-checking for clarity * Using TypedDict instead of Pydantic. Also, added a README. Signed-off-by: Martin Hirzel <[email protected]> * tweaks Signed-off-by: Martin Hirzel <[email protected]> --------- Signed-off-by: Martin Hirzel <[email protected]>
1 parent d38b429 commit 818ffc0

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

examples/callback/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Callback example
2+
3+
This example shows a Python program `repair_main.py` that calls a PDL program `repair_prompt.pdl` through the SDK. Then, `repair_prompt.pdl` calls a function `parse_output` defined in `repair_main.py` to obtain more information. Finally, the PDL program returns to Python an output that the Python code prints. In this example, all data is passed back and forth between Python and PDL using JSON. This JSON data is type-checked using `TypedDict` on the Python side and using `spec` on the PDL side.
4+
5+
To run:
6+
7+
```
8+
python repair_main.py
9+
```
10+
11+
Expected output:
12+
13+
```
14+
---- before call to PDL ----
15+
---- during callback from PDL ----
16+
---- after return from PDL ----
17+
{'before': "print('Hello, world!']", 'after': "print('Hello, world!')"}
18+
```

examples/callback/repair_main.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import re
2+
from typing import TypedDict, cast
3+
4+
import pdl.pdl
5+
6+
PDLScope = TypedDict("PDLScope", {"code_line": str, "error_msg": str})
7+
ParsedOutput = TypedDict("ParsedOutput", {"thought": str, "code_line": str | None})
8+
PDLResult = TypedDict("PDLResult", {"before": str, "after": str | None})
9+
10+
11+
def parse_output(raw_output: str) -> ParsedOutput:
12+
print("---- during callback from PDL ----")
13+
match_start = re.search(r"```python\s", raw_output)
14+
if not match_start:
15+
return ParsedOutput(thought=raw_output, code_line=None)
16+
thought = raw_output[: match_start.start()]
17+
rest = raw_output[match_start.end() :]
18+
match_end = re.search(r"\s```", rest)
19+
if not match_end:
20+
return ParsedOutput(thought=thought, code_line=rest)
21+
return ParsedOutput(thought=thought, code_line=rest[: match_end.start()])
22+
23+
24+
if __name__ == "__main__":
25+
pdl_input = PDLScope(
26+
code_line="print('Hello, world!']",
27+
error_msg="SyntaxError: closing parenthesis ']' does not match opening '('",
28+
)
29+
print("---- before call to PDL ----")
30+
pdl_output: PDLResult = pdl.pdl.exec_file(
31+
"./repair_prompt.pdl", scope=cast(pdl.pdl.ScopeType, pdl_input)
32+
)
33+
print("---- after return from PDL ----")
34+
print(pdl_output)

examples/callback/repair_prompt.pdl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
- |
2+
Given the following code:
3+
```python
4+
${code_line}
5+
```
6+
and the following error:
7+
${error_msg}
8+
Please repair the code!
9+
10+
- def: raw_output
11+
model: watsonx/ibm/granite-34b-code-instruct
12+
parameters:
13+
stop: ["\n\n"]
14+
15+
- lang: python
16+
def: parsed_output
17+
spec: {thought: str, code_line: str}
18+
code: |
19+
import repair_main
20+
result = repair_main.parse_output(raw_output)
21+
22+
- spec: {before: str, after: str}
23+
object:
24+
before: ${code_line}
25+
after: ${parsed_output.code_line}

0 commit comments

Comments
 (0)