You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/tutorial.md
+70-42
Original file line number
Diff line number
Diff line change
@@ -46,7 +46,7 @@ text:
46
46
```
47
47
48
48
In this program ([file](https://github.com/IBM/prompt-declaration-language//blob/main/examples/tutorial/calling_llm.pdl)), the `text` starts with the word `Hello,`, and we call a model (`watsonx/ibm/granite-34b-code-instruct`) with this as input prompt. Notice the Watsonx model id on LiteLLM.
49
-
The model is passed some parameters including the `decoding_method` and `stop`, which corresponds to the `stop_sequences` parameter in Watsonx. The stop sequences are to be included in the output. Since the `input` field is not specified in the model call, the entire document up that point is passed to the model as input context.
49
+
The model is passed some parameters including the `decoding_method` and `stop`, which corresponds to the `stop_sequences` parameter in Watsonx. The stop sequences are to be included in the output. Since the `input` field is not specified in the model call, the entire document up that point is passed to the model as input context.
50
50
51
51
A PDL program computes 2 data structures. The first is a JSON corresponding to the result of the overall program, obtained by aggregating the results of each block. This is what is printed by default when we run the interpreter. The second is a conversational background context, which is a list of role/content pairs, where we implicitly keep track of roles and content for the purpose of communicating with models that support chat APIs. The contents in the latter correspond to the results of each block. The conversational background context is what is used to make calls to LLMs via LiteLLM.
52
52
@@ -64,7 +64,7 @@ description: Hello world calling a model
64
64
text:
65
65
- "Hello,"
66
66
- model: watsonx/ibm/granite-20b-multilingual
67
-
input:
67
+
input:
68
68
Translate the word 'world' to French
69
69
```
70
70
@@ -95,7 +95,7 @@ The user can override these defaults by explicitly including them in the model c
95
95
96
96
## Variable Definition and Use
97
97
98
-
Any block can have a variable definition using a `def: <var>` field. This means that the output of that block is assigned to the variable `<var>`, which may be reused at a later point in the document.
98
+
Any block can have a variable definition using a `def: <var>` field. This means that the output of that block is assigned to the variable `<var>`, which may be reused at a later point in the document.
99
99
100
100
Consider the following example ([file](https://github.com/IBM/prompt-declaration-language//blob/main/examples/tutorial/variable_def_use.pdl)):
101
101
@@ -127,7 +127,7 @@ In PDL, we can declaratively chain models together as in the following example (
127
127
128
128
```yaml
129
129
description: Model chaining
130
-
text:
130
+
text:
131
131
- Hello,
132
132
- model: watsonx/ibm/granite-34b-code-instruct
133
133
parameters:
@@ -189,7 +189,7 @@ The translation of 'I love Paris!' to French is 'J'aime Paris!'.
189
189
The translation of 'I love Madrid!' to Spanish is 'Me encanta Madrid!'.
190
190
```
191
191
192
-
A function only contributes to the output document when it is called. So the definition itself results in `""`. When we call a function, we implicitly pass the current background context, and this is used as input to model calls inside the function body. In the above example, since the `input` field is omitted, the entire document produced at that point is passed as input to the granite model.
192
+
A function only contributes to the output document when it is called. So the definition itself results in `""`. When we call a function, we implicitly pass the current background context, and this is used as input to model calls inside the function body. In the above example, since the `input` field is omitted, the entire document produced at that point is passed as input to the granite model.
193
193
194
194
## Grouping Variable Definitions in Defs
195
195
@@ -264,7 +264,7 @@ Here are its possible values:
264
264
- `[result]`: contribute to the final result but not the background context
265
265
266
266
- `[context]`: contribute to the background context but not the final result
267
-
267
+
268
268
- `[result, context]`: contribute to both, which is also the default setting.
269
269
270
270
## Input from File or Stdin
@@ -301,7 +301,7 @@ text:
301
301
multiline: true
302
302
```
303
303
304
-
Finally, the following example shows reading content in JSON format.
304
+
Finally, the following example shows reading content in JSON format.
305
305
306
306
Consider the JSON content in this [file](https://github.com/IBM/prompt-declaration-language//blob/main/examples/tutorial/input.json):
307
307
```json
@@ -310,7 +310,7 @@ Consider the JSON content in this [file](https://github.com/IBM/prompt-declarati
310
310
"address": {
311
311
"number": 87,
312
312
"street": "Smith Road",
313
-
"town": "Armonk",
313
+
"town": "Armonk",
314
314
"state": "NY",
315
315
"zip": 10504
316
316
}
@@ -350,7 +350,7 @@ description: Hello world showing call to python code
Here is some info about the location of the function in the repo.
430
-
repo:
430
+
repo:
431
431
${ CODE.repo_info.repo }
432
432
path: ${ CODE.repo_info.path }
433
433
Function_name: ${ CODE.repo_info.function_name }
@@ -449,7 +449,7 @@ text:
449
449
${ TRUTH }
450
450
"""
451
451
result = textdistance.levenshtein.normalized_similarity(expl, truth)
452
-
- data:
452
+
- data:
453
453
input: ${ CODE }
454
454
output: ${ EXPLANATION }
455
455
metric: ${ EVAL }
@@ -564,9 +564,9 @@ The first two blocks read math problem examples and include them in the document
564
564
565
565
In the body of the `repeat` block, the program first asks granite to generate a question and add it to the document. Next we print `Answer: Let's think step by step.\n`. The following block is a repeat-until: the text in `repeat` is repeated until the condition in the `until` field becomes true. Here the condition states that we stop the iteration when variable `REASON_OR_CALC` contains `<<`. That variable is defined in the first block of the repeat-until -- we prompt a granite model and stop at the character `<<`.
566
566
567
-
The next block is an if-then-else. We check if `REASON_OR_CALC` ends with `<<` and if so we prepare for the python call to perform the arithmetic calculation. First, we have the granite model generate an `EXPR` variable, which we then use inside the `code` of the following Python block.
567
+
The next block is an if-then-else. We check if `REASON_OR_CALC` ends with `<<` and if so we prepare for the python call to perform the arithmetic calculation. First, we have the granite model generate an `EXPR` variable, which we then use inside the `code` of the following Python block.
568
568
569
-
When we execute this program, we obtain 3 math problems like the ones in the [examples](https://github.com/IBM/prompt-declaration-language//blob/main/examples/arith/).
569
+
When we execute this program, we obtain 3 math problems like the ones in the [examples](https://github.com/IBM/prompt-declaration-language//blob/main/examples/arith/).
570
570
571
571
Notice that the `repeat` and `then` blocks are followed by `text`. This is because of the semantics of lists in PDL. If we want to aggregate the result by stringifying every element in the list and collating them together (which is the case of top-level programs in general), then we need the keyword `text` to precede a list. If this is omitted then the list is treated as a programmatic sequence where all the blocks are executed in sequence but result of the overall list is the result of the {\em last} block in the sequence. This behavior can be marked explicitly with a `lastOf` block.
572
572
@@ -581,7 +581,7 @@ The following [example](https://github.com/IBM/prompt-declaration-language//blob
581
581
description: for loop
582
582
for:
583
583
i: [1, 2, 3, 4]
584
-
repeat:
584
+
repeat:
585
585
${ i }
586
586
```
587
587
@@ -595,7 +595,7 @@ To output a number of each line, we can specify which string to use to join the
595
595
description: for loop
596
596
for:
597
597
i: [1, 2, 3, 4]
598
-
repeat:
598
+
repeat:
599
599
${ i }
600
600
join:
601
601
with: "\n"
@@ -614,7 +614,7 @@ To creates an array as a result of iteration, we would write:
614
614
description: for loop
615
615
for:
616
616
i: [1, 2, 3, 4]
617
-
repeat:
617
+
repeat:
618
618
- ${ i }
619
619
join:
620
620
as: array
@@ -671,15 +671,15 @@ text:
671
671
spec: {name: str, age: int}
672
672
input:
673
673
text:
674
-
- for:
674
+
- for:
675
675
question: ${ data.questions }
676
676
answer: ${ data.answers }
677
677
repeat:
678
678
- |
679
679
${ question }
680
680
${ answer }
681
-
- >
682
-
Question: Create a JSON object with fields 'name' and 'age'
681
+
- >
682
+
Question: Create a JSON object with fields 'name' and 'age'
683
683
and set them appropriately. Write the age in letters.
684
684
parser: yaml
685
685
parameters:
@@ -689,7 +689,7 @@ text:
689
689
```
690
690
691
691
Upon reading the data we use a parser to parse it into a YAML. The `spec` field indicates the expected type for the
692
-
data, which is an object with 2 fields: `questions` and `answers` that are a list of string and a list of objects,
692
+
data, which is an object with 2 fields: `questions` and `answers` that are a list of string and a list of objects,
693
693
respectively. When the interpreter is executed, it checks this type dynamically and throws errors if necessary.
694
694
695
695
Similarly, the output of the model call is parsed as YAML, and the `spec` indicates that we expect an object with
@@ -754,8 +754,8 @@ To produce an execution trace consumable by the Live Document, you can run the i
754
754
pdl --trace <my-example_trace.json> <my-example>
755
755
```
756
756
757
-
This produces an additional file named `my-example_trace.json` that can be uploaded to the [Live Document](https://ibm.github.io/prompt-declaration-language/viewer/) visualizer tool. Clicking on different parts of the Live Document will show the PDL code that produced that part
758
-
in the right pane.
757
+
This produces an additional file named `my-example_trace.json` that can be uploaded to the [Live Document](https://ibm.github.io/prompt-declaration-language/viewer/) visualizer tool. Clicking on different parts of the Live Document will show the PDL code that produced that part
758
+
in the right pane.
759
759
760
760
This is similar to a spreadsheet for tabular data, where data is in the forefront and the user can inspect the formula that generates the data in each cell. In the Live Document, cells are not uniform but can take arbitrary extents. Clicking on them similarly reveals the part of the code that produced them.
761
761
@@ -774,13 +774,13 @@ text:
774
774
Several lines of text,
775
775
with some "quotes" of various 'types',
776
776
and also a blank line:
777
-
777
+
778
778
and some text with
779
779
extra indentation
780
780
on the next line,
781
781
plus another line at the end.
782
-
783
-
782
+
783
+
784
784
- "End."
785
785
```
786
786
@@ -806,13 +806,13 @@ text:
806
806
Several lines of text,
807
807
with some "quotes" of various 'types',
808
808
and also a blank line:
809
-
809
+
810
810
and some text with
811
811
extra indentation
812
812
on the next line,
813
813
plus another line at the end.
814
-
815
-
814
+
815
+
816
816
- "End."
817
817
```
818
818
@@ -834,13 +834,13 @@ text:
834
834
Several lines of text,
835
835
with some "quotes" of various 'types',
836
836
and also a blank line:
837
-
837
+
838
838
and some text with
839
839
extra indentation
840
840
on the next line,
841
841
plus another line at the end.
842
-
843
-
842
+
843
+
844
844
- "End."
845
845
```
846
846
@@ -863,13 +863,13 @@ text:
863
863
Several lines of text,
864
864
with some "quotes" of various 'types',
865
865
and also a blank line:
866
-
866
+
867
867
and some text with
868
868
extra indentation
869
869
on the next line,
870
870
plus another line at the end.
871
-
872
-
871
+
872
+
873
873
- "End."
874
874
```
875
875
@@ -895,13 +895,13 @@ text:
895
895
Several lines of text,
896
896
with some "quotes" of various 'types',
897
897
and also a blank line:
898
-
898
+
899
899
and some text with
900
900
extra indentation
901
901
on the next line,
902
902
plus another line at the end.
903
-
904
-
903
+
904
+
905
905
- "\n\n\n\n"
906
906
- "End."
907
907
```
@@ -931,7 +931,7 @@ text:
931
931
Several lines of text,
932
932
with some "quotes" of various 'types',
933
933
and also a blank line:
934
-
934
+
935
935
and some text with
936
936
extra indentation
937
937
on the next line.
@@ -957,7 +957,7 @@ PDL:
957
957
```
958
958
text: 'Several lines of text,
959
959
containing ''single quotes''. Escapes (like \n) don''t do anything.
2. Run a model e.g., `ollama run granite-code:34b-instruct-q5_K_M`. See [the Ollama library for more models](https://ollama.com/library/granite-code/tags)
1018
+
3. An OpenAI style server is running locally at [http://localhost:11434/](http://localhost:11434/), see [the Ollama blog](https://ollama.com/blog/openai-compatibility) for more details.
Alternatively, one could also use Ollama's OpenAI-style endpoint using the `openai/` prefix instead of `ollama_chat/`. In this case, set the `OPENAI_API_BASE`, `OPENAI_API_KEY`, and `OPENAI_ORGANIZATION` (if necessary) environment variables. If you were using the official OpenAI API, you would only have to set the api key and possibly the organization. For local use e.g., using Ollama, this could look like so:
1035
+
1036
+
```bash
1037
+
export OPENAI_API_BASE=http://localhost:11434/v1
1038
+
export OPENAI_API_KEY=ollama # required, but unused
0 commit comments