(.|\n)*)```(.|\n)*
12 | text: ${ output.code }
--------------------------------------------------------------------------------
/examples/tutorial/programs/chatbot.pdl:
--------------------------------------------------------------------------------
1 | description: Chatbot
2 | text:
3 | # Allow the user to type any question, implicitly adding the question to the context.
4 | - read:
5 | message: "What is your query?\n"
6 | - repeat:
7 | text:
8 | # Send context to Granite model hosted at ollama
9 | - model: ollama_chat/granite3.2:2b
10 | # Allow the user to type 'yes', 'no', or anything else, storing
11 | # the input into a variable named `eval`. The input is also implicitly
12 | # added to the context.
13 | - read:
14 | def: eval
15 | message: "\nIs this a good answer[yes/no]?\n"
16 | - "\n"
17 | # If the user only typed "no", prompt the user for input to add to the context.
18 | - if: ${ eval == 'no' }
19 | then:
20 | text:
21 | - read:
22 | message: "Why not?\n"
23 | # If the user typed only "yes", finish the `repeat` and end the program
24 | until: ${ eval == 'yes'}
25 |
--------------------------------------------------------------------------------
/examples/tutorial/programs/code-json.pdl:
--------------------------------------------------------------------------------
1 | description: Code explanation example
2 | defs:
3 | CODE:
4 | read: ../../code/data.yaml
5 | parser: yaml
6 | TRUTH:
7 | read: ../../code/ground_truth.txt
8 | lastOf:
9 | - model: ollama_chat/granite3.2:2b
10 | def: EXPLANATION
11 | input:
12 | |
13 | Here is some info about the location of the function in the repo.
14 | repo:
15 | ${ CODE.repo_info.repo }
16 | path: ${ CODE.repo_info.path }
17 | Function_name: ${ CODE.repo_info.function_name }
18 |
19 |
20 | Explain the following code:
21 | ```
22 | ${ CODE.source_code }```
23 | - def: EVAL
24 | lang: python
25 | code:
26 | |
27 | import textdistance
28 | expl = """
29 | ${ EXPLANATION }
30 | """
31 | truth = """
32 | ${ TRUTH }
33 | """
34 | result = textdistance.levenshtein.normalized_similarity(expl, truth)
35 | - data:
36 | input: ${ CODE }
37 | output: ${ EXPLANATION }
38 | metric: ${ EVAL }
39 |
40 |
--------------------------------------------------------------------------------
/examples/tutorial/repeat.pdl:
--------------------------------------------------------------------------------
1 | description: repeat loop with multiple conditions
2 | defs:
3 | numbers:
4 | data: [42, 2, 4012, 27]
5 | names:
6 | data: ["Bob", "Carol", "David", "Ernest"]
7 | for:
8 | number: ${ numbers }
9 | name: ${ names }
10 | index: i
11 | repeat:
12 | "${i}: ${ name }'s number is ${ number }\n"
13 | until: ${ name == "Carol"}
14 | maxIterations: 3
--------------------------------------------------------------------------------
/examples/tutorial/simple_program.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world!
2 | text:
3 | Hello, world!
--------------------------------------------------------------------------------
/examples/tutorial/structured_decoding.pdl:
--------------------------------------------------------------------------------
1 | text:
2 | - role: system
3 | 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.
4 | contribute: [context]
5 | - "\nWhat is the color of the sky? Write it as JSON\n"
6 | - model: watsonx/ibm/granite-34b-code-instruct
7 | parser: json
8 | spec: { color: string }
--------------------------------------------------------------------------------
/examples/tutorial/test.pdl:
--------------------------------------------------------------------------------
1 | description: test
2 | defs:
3 | m1:
4 | content: doc1
5 | m2:
6 | content: doc2
7 | m3:
8 | content: Compare the docs
9 |
10 | mycontext: ${ (m1 + m2) * m3 }
11 |
12 | text:
13 | - model: ollama_chat/granite3.2:2b
14 | input: ${ mycontext }
15 | - ${ mycontext }
--------------------------------------------------------------------------------
/examples/tutorial/type_checking.pdl:
--------------------------------------------------------------------------------
1 | # Expected not to type check
2 | description: Creating JSON Data
3 | defs:
4 | data:
5 | read: type_checking_data.yaml
6 | parser: yaml
7 | spec: { questions: [string], answers: [object] }
8 | text:
9 | - model: ollama_chat/granite3.2:2b
10 | def: model_output
11 | spec: {name: string, age: integer}
12 | input:
13 | array:
14 | - role: user
15 | content:
16 | text:
17 | - for:
18 | question: ${ data.questions }
19 | answer: ${ data.answers }
20 | repeat: |
21 | ${ question }
22 | ${ answer }
23 | - >
24 | 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.
25 | parser: yaml
26 | parameters:
27 | stop: ["Question"]
28 | temperature: 0
29 |
30 |
--------------------------------------------------------------------------------
/examples/tutorial/type_checking_data.yaml:
--------------------------------------------------------------------------------
1 | questions:
2 | - >
3 | Question: Write a YAML object with 2 fields 'a' and 'b' of type int and set to 0.
4 | - >
5 | Question: Write a YAML object with 3 fields 'number' and 'street' and 'town' set to '10', 'Miller Road', 'Armonk' respectively.
6 |
7 | answers:
8 | - { "a": 0, "b": 0 }
9 |
10 | - { "number": 10, "street": "miller Road", "town": "armonk" }
--------------------------------------------------------------------------------
/examples/tutorial/type_list.pdl:
--------------------------------------------------------------------------------
1 | # Expected not to type check
2 | description: test
3 | spec: {type: array, minItems: 0, maxItems: 0, items: { type: string }}
4 | data: ["hello", "world"]
5 |
--------------------------------------------------------------------------------
/examples/tutorial/variable_def_use.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world with variable def and use
2 | text:
3 | - "Hello\n"
4 | - model: ollama_chat/granite3.2:2b
5 | def: GEN
6 | parameters:
7 | stop: ['!']
8 | - "\nGEN is equal to: ${ GEN }"
--------------------------------------------------------------------------------
/examples/tutorial/while.pdl:
--------------------------------------------------------------------------------
1 | defs:
2 | i: 0
3 | while: ${ i < 3 }
4 | repeat:
5 | defs:
6 | i: ${i + 1}
7 | text: ${i}
--------------------------------------------------------------------------------
/mypy.ini:
--------------------------------------------------------------------------------
1 | [mypy]
2 | python_version = 3.12
3 | ignore_missing_imports = True
4 |
5 | [mypy-requests]
6 | ignore_missing_imports = True
7 |
--------------------------------------------------------------------------------
/pdl-live-react/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | insert_final_newline = true
9 |
--------------------------------------------------------------------------------
/pdl-live-react/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
26 | # Playwright
27 | /test-results/
28 | /playwright-report/
29 | /blob-report/
30 | /playwright/.cache/
31 |
--------------------------------------------------------------------------------
/pdl-live-react/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"]
3 | }
4 |
--------------------------------------------------------------------------------
/pdl-live-react/demos/demo1.pdl:
--------------------------------------------------------------------------------
1 | description: Simple LLM interaction
2 | text:
3 | - "write a hello world example, and explain to me how to run it"
4 | - model: ollama_chat/granite3.2:2b
5 | # - model: openai/ibm-granite_granite-3.2-2b-instruct
6 |
--------------------------------------------------------------------------------
/pdl-live-react/demos/demo2.pdl:
--------------------------------------------------------------------------------
1 | description: Model chaining
2 | text:
3 | - "write a hello world example, and explain to me how to run it"
4 | - model: ollama_chat/granite3.2:2b
5 | parameters:
6 | temperature: 0
7 | - "how about in Rust?"
8 | - model: ollama_chat/granite3.2:2b
9 | parameters:
10 | temperature: 0
11 |
--------------------------------------------------------------------------------
/pdl-live-react/demos/error.pdl:
--------------------------------------------------------------------------------
1 | description: Creating JSON Data
2 | defs:
3 | data:
4 | read: ./gen-data.yaml
5 | parser: yaml
6 | spec: { questions: [string], answers: [object] }
7 | text:
8 | - model: ollama_chat/granite3.2:2b
9 | def: model_output
10 | spec: {name: string, age: integer}
11 | input:
12 | text:
13 | - for:
14 | question: ${ data.questions }
15 | answer: ${ data.answers }
16 | repeat: |
17 | ${ question }
18 | ${ answer }
19 | - >
20 | Question: Create a JSON object with fields 'name' and 'age'
21 | and set them appropriately. Write the age in letters.
22 | parser: yaml
23 | parameters:
24 | stop_sequences: "\n"
25 | temperature: 0
--------------------------------------------------------------------------------
/pdl-live-react/demos/gen-data.yaml:
--------------------------------------------------------------------------------
1 | source_code:
2 | |
3 | @SuppressWarnings("unchecked")
4 | public static Map deserializeOffsetMap(String lastSourceOffset) throws IOException {
5 | Map offsetMap;
6 | if (lastSourceOffset == null || lastSourceOffset.isEmpty()) {
7 | offsetMap = new HashMap<>();
8 | } else {
9 | offsetMap = JSON_MAPPER.readValue(lastSourceOffset, Map.class);
10 | }
11 | return offsetMap;
12 | }
13 | repo_info:
14 | repo: streamsets/datacollector
15 | path: stagesupport/src/main/java/com/.../OffsetUtil.java
16 | function_name: OffsetUtil.deserializeOffsetMap
17 |
--------------------------------------------------------------------------------
/pdl-live-react/demos/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | SCRIPTDIR=$(cd $(dirname "$0") && pwd)
4 | UI="$SCRIPTDIR"/.. # top of react UI
5 | TOP="$UI"/.. # top of repo
6 | T="$UI"/src/demos # place to store traces
7 |
8 | pdl --trace "$T"/demo1.json "$UI"/demos/demo1.pdl
9 | pdl --trace "$T"/demo2.json "$UI"/demos/demo2.pdl
10 | pdl --trace "$T"/demo3.json "$TOP"/examples/fibonacci/fib.pdl
11 | pdl --trace "$T"/demo4.json "$TOP"/examples/chatbot/chatbot.pdl < Result {
5 | let (_, messages, _) = run_string(&program, Default::default(), Default::default())
6 | .await
7 | .map_err(|err| err.to_string())?;
8 |
9 | Ok(pretty_print(&messages))
10 | }
11 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/src/commands/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod interpreter;
2 | pub mod read_trace;
3 | pub mod replay_prep;
4 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/src/commands/read_trace.rs:
--------------------------------------------------------------------------------
1 | use std::fs::read;
2 |
3 | // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
4 | #[tauri::command]
5 | pub fn read_trace(trace_file: &str) -> Result, String> {
6 | let data = read(trace_file).map_err(|e| e.to_string())?;
7 | Ok(data)
8 | }
9 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/src/compile/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod beeai;
2 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/src/gui.rs:
--------------------------------------------------------------------------------
1 | use ::std::path::PathBuf;
2 | use tauri::WebviewWindowBuilder;
3 |
4 | pub fn new_window(
5 | app: tauri::AppHandle,
6 | path: Option,
7 | ) -> Result<(), Box> {
8 | WebviewWindowBuilder::new(
9 | &app,
10 | "main",
11 | tauri::WebviewUrl::App(path.unwrap_or("".into())),
12 | )
13 | .title("Prompt Declaration Language")
14 | .prevent_overflow()
15 | .zoom_hotkeys_enabled(true)
16 | .inner_size(1400.0, 1050.0)
17 | .build()?;
18 | Ok(())
19 | }
20 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/src/main.rs:
--------------------------------------------------------------------------------
1 | // Prevents additional console window on Windows in release, DO NOT REMOVE!!
2 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
3 |
4 | fn main() {
5 | tauri_app_lib::run()
6 | }
7 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/src/pdl/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod ast;
2 | pub mod extract;
3 | pub mod interpreter;
4 | mod interpreter_tests;
5 | pub mod pip;
6 | pub mod pull;
7 | pub mod requirements;
8 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/src/pdl/pip.rs:
--------------------------------------------------------------------------------
1 | use ::std::fs::{create_dir_all, write};
2 | use ::std::path::PathBuf;
3 |
4 | use dirs::cache_dir;
5 | use duct::cmd;
6 |
7 | use crate::util::shasum;
8 |
9 | #[cfg(desktop)]
10 | pub async fn pip_install_if_needed(
11 | requirements: &str,
12 | ) -> Result> {
13 | let Some(cache_path) = cache_dir() else {
14 | return Err(Box::from("Could not find user cache directory"));
15 | };
16 | create_dir_all(&cache_path)?;
17 |
18 | let hash = shasum::sha256sum_str(requirements);
19 | let venv_path = cache_path.join("venvs").join(hash);
20 | let bin_path = venv_path.join(if cfg!(windows) { "Scripts" } else { "bin" });
21 |
22 | if !venv_path.exists() {
23 | println!("Creating virtual environment...");
24 | let python = if cfg!(target_os = "macos") {
25 | "python3.12"
26 | } else {
27 | "python3"
28 | };
29 | cmd!(python, "-mvenv", &venv_path)
30 | .stdout_to_stderr()
31 | .run()?;
32 |
33 | cmd!(bin_path.join("pip"), "install", &requirements)
34 | .stdout_to_stderr()
35 | .run()?;
36 |
37 | let cached_requirements_path = venv_path.join("requirements.txt");
38 | write(&cached_requirements_path, requirements)?;
39 | }
40 |
41 | Ok(bin_path.to_path_buf())
42 | }
43 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/src/pdl/requirements.rs:
--------------------------------------------------------------------------------
1 | pub const BEEAI_FRAMEWORK: &str = "-e git+https://github.com/starpit/bee-agent-framework.git@nick-meta-combo#egg=beeai_framework&subdirectory=python";
2 | //pub const BEEAI_FRAMEWORK: &str = "beeai_framework==0.1";
3 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/src/util.rs:
--------------------------------------------------------------------------------
1 | pub mod shasum;
2 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/src/util/shasum.rs:
--------------------------------------------------------------------------------
1 | use base64ct::{Base64Url, Encoding};
2 | use sha2::{Digest, Sha256};
3 |
4 | /* pub fn sha256sum(path: &Path) -> Result {
5 | let mut hasher = Sha256::new();
6 | let mut file = File::open(path)?;
7 |
8 | copy(&mut file, &mut hasher)?;
9 | let hash_bytes = hasher.finalize();
10 |
11 | Ok(Base64Url::encode_string(&hash_bytes))
12 | } */
13 |
14 | pub fn sha256sum_str(s: &str) -> String {
15 | let mut hasher = Sha256::new();
16 | hasher.update(s);
17 | let hash_bytes = hasher.finalize();
18 |
19 | Base64Url::encode_string(&hash_bytes)
20 | }
21 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/call-no-args.pdl:
--------------------------------------------------------------------------------
1 | defs:
2 | foo:
3 | function: {}
4 | return:
5 | description: nullary function
6 | text:
7 | - hello world
8 | text:
9 | - call: ${ foo}
10 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/call-with-args.pdl:
--------------------------------------------------------------------------------
1 | defs:
2 | foo:
3 | function:
4 | x: integer
5 | return:
6 | description: nullary function
7 | text:
8 | - hello world ${x+1} bye
9 | text:
10 | - call: ${ foo }
11 | args:
12 | x: 3
13 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/code-python.pdl:
--------------------------------------------------------------------------------
1 | lang: python
2 | code: |
3 | import sys # test import stdlib
4 | import os # test import stdlib
5 | print(f"!!! {sys.path}")
6 | #import textdistance # test import from venv
7 | from nested_diff import diff # test import from venv
8 | #from typing import Self
9 | from pydantic import BaseModel, Field, ValidationError
10 | from pydantic_settings import BaseSettings, SettingsConfigDict
11 | # import beeai_framework
12 | # from beeai_framework.tools.search.wikipedia import WikipediaTool # type: ignore
13 | a = {'one': 1, 'two': 2, 'three': 3}
14 | b = {'one': 1, 'two': 3, 'three': 3}
15 | result = {"foo": os.getenv("FOO999999999999999999999999"), "diff": diff(a, b, O=False, U=False)}
16 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/data1.pdl:
--------------------------------------------------------------------------------
1 | lastOf:
2 | - def: x
3 | text:
4 | - xxxx
5 | - def: y
6 | data:
7 | n: 3
8 | x: ${x}
9 | b: true
10 | - ${y.x~y.n~y.b}
11 |
12 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/data2.pdl:
--------------------------------------------------------------------------------
1 | defs:
2 | x:
3 | text:
4 | - xxxx
5 | y:
6 | data:
7 | n: 3
8 | x: ${x}
9 | b: true
10 | lastOf:
11 | - ${y.x~y.n~y.b}
12 |
13 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/data3.pdl:
--------------------------------------------------------------------------------
1 | lastOf:
2 | - def: x
3 | text:
4 | - xxxx
5 | - def: y
6 | raw: true
7 | data:
8 | n: 3
9 | x: ${x}
10 | b: true
11 | - ${y.x~y.n~y.b}
12 |
13 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/data4.pdl:
--------------------------------------------------------------------------------
1 | defs:
2 | x:
3 | description: Outer x
4 | text:
5 | - xxxx
6 | y:
7 | data:
8 | n: 3
9 | x: ${x}
10 | b: true
11 | lastOf:
12 | - defs:
13 | x: yyyy
14 | description: Inner x
15 | text:
16 | - ${x~y.x~y.n~y.b}
17 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/if1.pdl:
--------------------------------------------------------------------------------
1 | if: true
2 | then: hi
3 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/if2.pdl:
--------------------------------------------------------------------------------
1 | defs:
2 | x: 5
3 | if: ${x!=5}
4 | then: bug
5 | else: good
6 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/include1.pdl:
--------------------------------------------------------------------------------
1 | include: ./call-with-args.pdl
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/json-parser-lastOf.pdl:
--------------------------------------------------------------------------------
1 | lastOf:
2 | - text:
3 | - '{"key": "value"}'
4 | parser: json
5 | def: foo
6 | - ${ foo.key }
7 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/json-parser.pdl:
--------------------------------------------------------------------------------
1 | text:
2 | - text:
3 | - '{"key": "value"}'
4 | parser: json
5 | def: foo
6 | - ${ foo.key }
7 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/jsonl-parser.pdl:
--------------------------------------------------------------------------------
1 | text:
2 | - text:
3 | - |
4 | {"key": "value"}
5 | {"key2": "value2"}
6 | parser: jsonl
7 | def: foo
8 | - ${ foo[0].key }
9 | - ${ foo[1].key2 }
10 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/model-input-array.pdl:
--------------------------------------------------------------------------------
1 | model: ollama/granite3.2:2b
2 | input:
3 | array:
4 | - role: user
5 | content: answer as if you live in europe
6 | - role: user
7 | content: what is the fastest animal where i live?
8 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/model-input-nested.pdl:
--------------------------------------------------------------------------------
1 | description: Nesting inputs to model calls
2 | text:
3 | - role: user
4 | content: answer as if you live in europe
5 | - text:
6 | - role: user
7 | content: what is the fastest animal where i live?
8 | - model: ollama/granite3.2:2b
9 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/model-input-string.pdl:
--------------------------------------------------------------------------------
1 | model: ollama/granite3.2:2b
2 | input: what is the fastest animal?
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/object1.pdl:
--------------------------------------------------------------------------------
1 | defs:
2 | obj:
3 | object:
4 | a:
5 | text:
6 | - foo
7 | text:
8 | - ${ obj.a }
9 |
10 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/object2.pdl:
--------------------------------------------------------------------------------
1 | defs:
2 | obj:
3 | object:
4 | a:
5 | object:
6 | b:
7 | text:
8 | - foo2
9 | text:
10 | - ${ obj.a.b }
11 |
12 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/read-file.pdl:
--------------------------------------------------------------------------------
1 | text:
2 | - read: ../data/struct.yaml
3 | def: struct
4 | parser: yaml
5 | - ${ struct.a.b }
6 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/read-stdin.pdl:
--------------------------------------------------------------------------------
1 | message: How are you?
2 | read: null
3 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/regex-findall.pdl:
--------------------------------------------------------------------------------
1 | data: aaa999bbb888
2 | parser:
3 | regex: '[^0-9]*(?P[0-9]+)[^0-9]*(?P[0-9]+)$'
4 | mode: findall
5 | spec:
6 | answer1: string
7 | answer2: string
8 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/repeat1.pdl:
--------------------------------------------------------------------------------
1 | for:
2 | x: [1,2,3]
3 | repeat:
4 | text:
5 | - "${ x + 1 }"
6 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/repeat2.pdl:
--------------------------------------------------------------------------------
1 | for:
2 | x: [1,2,3]
3 | y: ["a","b","c"]
4 | repeat:
5 | text:
6 | - "${ x ~ y }"
7 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/repeat3.pdl:
--------------------------------------------------------------------------------
1 | for:
2 | x:
3 | - z: 4
4 | - z: 5
5 | - z: 6
6 | y: ["a","b","c"]
7 | repeat:
8 | text:
9 | - "${ x.z ~ y }"
10 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/scoping_1.pdl:
--------------------------------------------------------------------------------
1 | text:
2 | - defs:
3 | x: 3
4 | text:
5 | - ${x~"yo"}
6 | - ${x~"mo"}
7 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/cli/scoping_1_wrapper.pdl:
--------------------------------------------------------------------------------
1 | include: ./scoping_1.pdl
2 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/data/foo.txt:
--------------------------------------------------------------------------------
1 | this should be foo
2 |
--------------------------------------------------------------------------------
/pdl-live-react/src-tauri/tests/data/struct.yaml:
--------------------------------------------------------------------------------
1 | a:
2 | b: 3
3 |
--------------------------------------------------------------------------------
/pdl-live-react/src/App.tsx:
--------------------------------------------------------------------------------
1 | import useDynamicTitle from "./title"
2 | import PdlRoutes from "./routes/PdlRoutes"
3 |
4 | import "@patternfly/react-core/dist/styles/base.css"
5 |
6 | export default function App() {
7 | useDynamicTitle()
8 | return
9 | }
10 |
--------------------------------------------------------------------------------
/pdl-live-react/src/assets/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/prompt-declaration-language/f4fbdb850c2f3374d701cce9e4abd5a69e2798a4/pdl-live-react/src/assets/404.png
--------------------------------------------------------------------------------
/pdl-live-react/src/demos/README.md:
--------------------------------------------------------------------------------
1 | # Demo Traces
2 |
3 | These demo traces were sourced as follows:
4 |
5 | - demo1: From the top-level README
6 | - demo2: [model_chaining.pdl](../../../examples/tutorial/model_chaining.pdl)
7 | - demo3: [fib.pdl](../../../examples/fibonacci/fib.pdl)
8 | - demo4: [chatbot.pdl](../../../examples/chatbot/chatbot.pdl)
9 | - demo5: [6-code-json.pdl](../../../examples/talk/6-code-json.pdl)
10 | - demo6: [error.pdl](../../demos/error.pdl)
11 | - demo7: [4-talk.pdl](../../../examples/talk/4-function.pdl)
12 | - demo8: [demo-hallucination](../../../examples/intrinsics/demo-hallucination.pdl). To run this currently requires... work. https://github.com/ibm-granite-community/granite-snack-cookbook/blob/main/recipes/Intrinsics/Granite_RAG_LoRA.ipynb
13 | - demo9: [gsm8.pdl](../../../examples/gsm8k/gsm8.pdl)
14 |
--------------------------------------------------------------------------------
/pdl-live-react/src/demos/demos.ts:
--------------------------------------------------------------------------------
1 | import demo1 from "./demo1.json"
2 | import demo2 from "./demo2.json"
3 | import demo3 from "./demo3.json"
4 | import demo4 from "./demo4.json"
5 | import demo5 from "./demo5.json"
6 | import demo6 from "./demo6.json"
7 | import demo7 from "./demo7.json"
8 | import demo8 from "./demo8.json"
9 | import demo9 from "./demo9.json"
10 |
11 | export type Demo = {
12 | name: string
13 | trace: string
14 | }
15 |
16 | const demos: Demo[] = [
17 | demo1,
18 | demo2,
19 | demo3,
20 | demo4,
21 | demo5,
22 | demo6,
23 | demo7,
24 | demo8,
25 | demo9,
26 | ].map((demo) => ({
27 | name: demo.description,
28 | trace: JSON.stringify(demo),
29 | }))
30 |
31 | export default demos
32 |
--------------------------------------------------------------------------------
/pdl-live-react/src/main.tsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from "react"
2 | import { createRoot } from "react-dom/client"
3 | import { HashRouter as Router } from "react-router"
4 | import App from "./App.tsx"
5 |
6 | createRoot(document.getElementById("root")!).render(
7 |
8 |
9 |
10 |
11 | ,
12 | )
13 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/DarkModeContext.ts:
--------------------------------------------------------------------------------
1 | const darkModeLocalStorageKey = "pdl-viewer.dark-mode"
2 |
3 | export function getDarkModeUserSetting(): boolean {
4 | return (localStorage.getItem(darkModeLocalStorageKey) || "false") == "true"
5 | }
6 |
7 | export function setDarkModeUserSetting(darkMode: boolean) {
8 | localStorage.setItem(darkModeLocalStorageKey, darkMode ? "true" : "false")
9 | }
10 |
11 | export function setDarkModeForSession(darkMode: boolean) {
12 | if (darkMode) {
13 | document.querySelector("html")?.classList.add("pf-v6-theme-dark")
14 | } else {
15 | document.querySelector("html")?.classList.remove("pf-v6-theme-dark")
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/Demo.tsx:
--------------------------------------------------------------------------------
1 | import Page from "./Page"
2 | import PageBreadcrumbDropdown from "./PageBreadcrumbDropdown"
3 | import PageBreadcrumbDropdownItem from "./PageBreadcrumbDropdownItem"
4 |
5 | import demos, { type Demo } from "../demos/demos"
6 |
7 | type Props = {
8 | name: string
9 | value: string
10 | }
11 |
12 | /** current is demo curently being shown */
13 | function DemosDropdown({ current }: { current: string }) {
14 | return (
15 |
16 | {demos.map((demo) => (
17 |
23 | ))}
24 |
25 | )
26 | }
27 |
28 | export default function Demo({ name, value }: Props) {
29 | return (
30 | }
32 | breadcrumb2={name}
33 | initialValue={value}
34 | />
35 | )
36 | }
37 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/DemoNavItems.tsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router"
2 | import { useCallback, useState, type MouseEvent } from "react"
3 | import { NavExpandable, NavItem } from "@patternfly/react-core"
4 |
5 | import demos from "../demos/demos"
6 |
7 | export default function DemoNavItems({
8 | hash,
9 | activeItem,
10 | }: {
11 | hash: string
12 | activeItem: string
13 | }) {
14 | const demosExpandedLocalStorageKey = "pdl.sidebar-nav-demos.expanded"
15 | const [isDemosExpanded, setIsDemosExpanded] = useState(
16 | !localStorage.getItem(demosExpandedLocalStorageKey) ||
17 | localStorage.getItem(demosExpandedLocalStorageKey) === "true",
18 | )
19 | const onDemosExpand = useCallback(
20 | (_evt: MouseEvent, val: boolean) => {
21 | setIsDemosExpanded(val)
22 | localStorage.setItem(demosExpandedLocalStorageKey, String(val))
23 | },
24 | [setIsDemosExpanded],
25 | )
26 |
27 | return (
28 |
34 | {demos.map((demo) => {
35 | const id = "/demos/" + encodeURIComponent(demo.name)
36 | return (
37 |
38 | {demo.name}
39 |
40 | )
41 | })}
42 |
43 | )
44 | }
45 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/Local.tsx:
--------------------------------------------------------------------------------
1 | import { invoke } from "@tauri-apps/api/core"
2 | import { useParams } from "react-router"
3 | import { useEffect, useState } from "react"
4 |
5 | import Page from "./Page"
6 |
7 | type Props = {
8 | traceFile: string
9 | }
10 |
11 | export default function Local() {
12 | const { traceFile } = useParams()
13 | const [value, setValue] = useState("")
14 |
15 | useEffect(() => {
16 | let active = true
17 | load()
18 | return () => {
19 | active = false
20 | }
21 |
22 | async function load() {
23 | if (traceFile) {
24 | const buf = (await invoke("read_trace", { traceFile })) as number[]
25 | let value = ""
26 | for (let i = 0; i < buf.length; i++) {
27 | value += String.fromCharCode(buf[i])
28 | }
29 | if (!active) {
30 | return
31 | }
32 | setValue(value)
33 | }
34 | }
35 | }, [traceFile, setValue])
36 |
37 | return (
38 |
43 | )
44 | }
45 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/Masthead.css:
--------------------------------------------------------------------------------
1 | .pf-v6-theme-dark .pdl-logo path {
2 | fill: white;
3 | }
4 | .pdl-logo {
5 | height: 2.25em;
6 | }
7 | .pdl-logo path {
8 | fill: black;
9 | }
10 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/MyTrace.tsx:
--------------------------------------------------------------------------------
1 | import Page from "./Page"
2 | import PageBreadcrumbDropdown from "./PageBreadcrumbDropdown"
3 | import PageBreadcrumbDropdownItem from "./PageBreadcrumbDropdownItem"
4 |
5 | import { getMyTraces } from "./MyTraces"
6 |
7 | type Props = {
8 | name: string
9 | value: string
10 | }
11 |
12 | /** current is demo curently being shown */
13 | function MyTracesDropdown({ current }: { current: string }) {
14 | return (
15 |
16 | {getMyTraces().map(({ title, filename }) => (
17 |
23 | ))}
24 |
25 | )
26 | }
27 |
28 | export default function MyTrace({ name, value }: Props) {
29 | return (
30 | }
32 | breadcrumb2={name}
33 | initialValue={value}
34 | />
35 | )
36 | }
37 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/Page.css:
--------------------------------------------------------------------------------
1 | html.web {
2 | font-size: 20px;
3 | }
4 |
5 | .pdl-wrap {
6 | &,
7 | & p {
8 | white-space: pre-wrap;
9 | }
10 | }
11 |
12 | .pdl-mono {
13 | font-family: var(--pf-t--global--font--family--mono);
14 | }
15 |
16 | .pf-v6-c-page__main-container {
17 | margin: 0;
18 | border-radius: 0;
19 | border-radius: none;
20 | max-height: revert;
21 | }
22 |
23 | .pf-v6-c-page__main-body {
24 | flex: 1;
25 |
26 | & > section[data-fill-height] {
27 | height: 100%;
28 | }
29 | }
30 | .pdl-viewer-tab:not([hidden]) {
31 | height: 100%;
32 | overflow: auto;
33 | }
34 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/PageBreadcrumbDropdown.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback, useState } from "react"
2 | import {
3 | Dropdown,
4 | DropdownList,
5 | MenuToggle,
6 | MenuToggleElement,
7 | } from "@patternfly/react-core"
8 |
9 | export default function PageBreadcrumbDropdown({
10 | label,
11 | children,
12 | }: {
13 | label: string
14 | children: import("react").ReactNode[]
15 | }) {
16 | const [isOpen, setIsOpen] = useState(false)
17 | const onToggle = () => setIsOpen(!isOpen)
18 | const onSelect = useCallback(() => {
19 | setIsOpen((prevIsOpen: boolean) => !prevIsOpen)
20 | }, [setIsOpen])
21 |
22 | return (
23 | setIsOpen(isOpen)}
27 | shouldFocusToggleOnSelect
28 | toggle={(toggleRef: React.Ref) => (
29 |
37 | {label}
38 |
39 | )}
40 | >
41 | {children}
42 |
43 | )
44 | }
45 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/PageBreadcrumbDropdownItem.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback } from "react"
2 | import { useNavigate, useSearchParams, useLocation } from "react-router"
3 | import { DropdownItem } from "@patternfly/react-core"
4 |
5 | export default function PageBreadcrumbDropdownItem({
6 | url,
7 | name,
8 | current,
9 | }: {
10 | url: string
11 | name: string
12 | current: string
13 | }) {
14 | const navigate = useNavigate()
15 | const { hash } = useLocation()
16 | const [searchParams] = useSearchParams()
17 | searchParams.delete("id")
18 | searchParams.delete("def")
19 | searchParams.delete("get")
20 | searchParams.delete("type")
21 | searchParams.delete("detail")
22 | const s = searchParams.toString()
23 | const search = s.length > 0 ? "?" + s : ""
24 |
25 | const onClick = useCallback(
26 | () => navigate("/" + url + "/" + name + search + hash),
27 | [name, url, hash, search, navigate],
28 | )
29 | return (
30 |
31 | {name}
32 |
33 | )
34 | }
35 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/PageBreadcrumbs.css:
--------------------------------------------------------------------------------
1 | .pf-v6-c-breadcrumb__dropdown {
2 | margin: 0;
3 | }
4 | .pdl-breadcrumb-menu-toggle {
5 | font-size: var(--pf-v6-c-breadcrumb__item--FontSize);
6 | }
7 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/Run.css:
--------------------------------------------------------------------------------
1 | @import "../view/term/RunTerminal.css";
2 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/Uploader.css:
--------------------------------------------------------------------------------
1 | .pdl-upload-form {
2 | max-width: 800px;
3 | }
4 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/welcome/Intro.tsx:
--------------------------------------------------------------------------------
1 | import { Content } from "@patternfly/react-core"
2 |
3 | export default function Intro() {
4 | return (
5 |
6 | PDL is a declarative language designed for developers to create reliable,
7 | composable LLM prompts and integrate them into software systems. It
8 | provides a structured way to specify prompt templates, enforce validation,
9 | and compose LLM calls with traditional rule-based systems.
10 |
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/welcome/Links.tsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router"
2 | import { Button, Flex } from "@patternfly/react-core"
3 |
4 | import ExternalLinkSquareAltIcon from "@patternfly/react-icons/dist/esm/icons/external-link-square-alt-icon"
5 |
6 | export default function Links() {
7 | return (
8 |
9 | }
12 | iconPosition="end"
13 | >
14 |
18 | Home Page
19 |
20 |
21 | }
24 | iconPosition="end"
25 | >
26 |
30 | GitHub
31 |
32 |
33 |
36 |
37 | )
38 | }
39 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/welcome/Tile.tsx:
--------------------------------------------------------------------------------
1 | import type { PropsWithChildren, ReactNode } from "react"
2 |
3 | import {
4 | Card,
5 | CardBody,
6 | CardFooter,
7 | CardHeader,
8 | CardTitle,
9 | Flex,
10 | } from "@patternfly/react-core"
11 |
12 | type Props = PropsWithChildren<{
13 | className?: string
14 | title: ReactNode
15 | body: ReactNode
16 | icon?: ReactNode
17 | }>
18 |
19 | const gapSm = { default: "gapSm" as const }
20 | const center = { default: "alignItemsCenter" as const }
21 |
22 | export default function Tile({
23 | className,
24 | title,
25 | body,
26 | children,
27 | icon,
28 | }: Props) {
29 | return (
30 |
31 |
32 |
33 |
34 | {icon}
35 | {title}
36 |
37 |
38 |
39 | {body}
40 |
41 | {children}
42 |
43 |
44 | )
45 | }
46 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/welcome/Tiles.tsx:
--------------------------------------------------------------------------------
1 | import { type ReactNode } from "react"
2 | import { Gallery } from "@patternfly/react-core"
3 |
4 | import Demos from "./tiles/Demos"
5 | import MyTraces from "./tiles/MyTraces"
6 |
7 | type Props = {
8 | tiles?: ReactNode | ReactNode[]
9 | }
10 |
11 | const minWidths = { default: "400px" }
12 |
13 | export default function Tiles(props: Props) {
14 | return (
15 |
16 | {props.tiles ?? (
17 | <>
18 |
19 |
20 | >
21 | )}
22 |
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/welcome/Toolbar.tsx:
--------------------------------------------------------------------------------
1 | import { Toolbar, ToolbarGroup, ToolbarContent } from "@patternfly/react-core"
2 |
3 | import DarkModeToggle from "../DarkModeToggle"
4 |
5 | const alignEnd = { default: "alignEnd" as const }
6 |
7 | export default function WelcomeToolbar() {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/welcome/Welcome.css:
--------------------------------------------------------------------------------
1 | .pdl-welcome-intro {
2 | max-width: 1200px;
3 | }
4 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/welcome/Welcome.tsx:
--------------------------------------------------------------------------------
1 | import { type ReactNode } from "react"
2 | import { Flex, FlexItem, PageSection, Title } from "@patternfly/react-core"
3 |
4 | import Page from "../Page"
5 | import Intro from "./Intro"
6 | import Links from "./Links"
7 | import Tiles from "./Tiles"
8 | import Toolbar from "./Toolbar"
9 |
10 | import "./Welcome.css"
11 |
12 | const flex1 = { default: "flex_1" as const }
13 |
14 | type Props = {
15 | breadcrumb1?: string
16 | intro?: ReactNode
17 | tiles?: ReactNode | ReactNode[]
18 | }
19 |
20 | export default function Welcome(props: Props) {
21 | return (
22 |
23 |
24 |
25 | Prompt Declaration Language (PDL) {" "}
26 |
27 |
28 |
29 |
30 | {props.intro ?? }
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | )
42 | }
43 |
--------------------------------------------------------------------------------
/pdl-live-react/src/page/welcome/tiles/Demos.tsx:
--------------------------------------------------------------------------------
1 | import { Button, Flex, Stack, StackItem } from "@patternfly/react-core"
2 | import { Link, useLocation, useSearchParams } from "react-router"
3 |
4 | import Tile from "../Tile"
5 | import demos from "../../../demos/demos"
6 |
7 | import DemoIcon from "@patternfly/react-icons/dist/esm/icons/file-code-icon"
8 |
9 | export default function Demos() {
10 | const { hash } = useLocation()
11 | const [searchParams] = useSearchParams()
12 | const s = searchParams.toString()
13 |
14 | const body = (
15 |
16 | You may view one of the built-in PDL demos.
17 |
18 |
19 | {demos.map((demo) => (
20 |
32 | ))}
33 |
34 |
35 |
36 | )
37 |
38 | return } body={body} />
39 | }
40 |
--------------------------------------------------------------------------------
/pdl-live-react/src/svg.d.ts:
--------------------------------------------------------------------------------
1 | declare module "*.svg?react" {
2 | import React from "react"
3 | const SVG: React.VFC>
4 | export default SVG
5 | }
6 |
--------------------------------------------------------------------------------
/pdl-live-react/src/title.ts:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react"
2 | import { useLocation } from "react-router"
3 |
4 | function capitalize(s: string) {
5 | return s.length === 0 ? s : s[0].toUpperCase() + s.slice(1)
6 | }
7 |
8 | export default function useDynamicTitle() {
9 | const { pathname } = useLocation()
10 |
11 | useEffect(() => {
12 | const rest = capitalize(
13 | decodeURIComponent(pathname.replace(/^\/(demos\/)?/, "")),
14 | )
15 |
16 | document.title = "PDL Viewer" + (rest ? ` - ${rest}` : "")
17 | }, [pathname])
18 | }
19 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/CopyToClipboard.css:
--------------------------------------------------------------------------------
1 | .pf-v6-c-clipboard-copy .pf-v6-c-form-control {
2 | display: none;
3 | }
4 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/CopyToClipboard.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback } from "react"
2 | import { ClipboardCopy } from "@patternfly/react-core"
3 |
4 | import "./CopyToClipboard.css"
5 |
6 | export default function CopyToClipboard(props: { children: string }) {
7 | const copy = useCallback(
8 | () => navigator.clipboard.writeText(props.children),
9 | [props.children],
10 | )
11 | return (
12 |
13 | Copy
14 |
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/Markdown.tsx:
--------------------------------------------------------------------------------
1 | import { Content } from "@patternfly/react-core"
2 | import rehypeStarryNight from "rehype-starry-night"
3 | import {
4 | MarkdownHooks as RMD,
5 | type Options as MarkdownProps,
6 | } from "react-markdown"
7 |
8 | import "./Markdown.css"
9 |
10 | /** Simple wrapper over */
11 | export default function Markdown(props: MarkdownProps) {
12 | return (
13 |
14 |
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/Result.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | DescriptionListTerm,
3 | DescriptionListGroup,
4 | DescriptionListDescription,
5 | Panel,
6 | PanelMain,
7 | } from "@patternfly/react-core"
8 |
9 | import Code from "./code/Code"
10 | import Value from "./Value"
11 |
12 | import { type SupportedLanguage } from "./code/Code"
13 |
14 | type Props = {
15 | result: number | string | unknown
16 | lang?: SupportedLanguage
17 | term?: string
18 | limitHeight?: boolean
19 | }
20 |
21 | export default function Result({
22 | result,
23 | lang,
24 | term = "Result",
25 | limitHeight = false,
26 | }: Props) {
27 | const isCode =
28 | !!lang &&
29 | lang !== "plaintext" &&
30 | !!result &&
31 | typeof result !== "number" &&
32 | typeof result !== "boolean"
33 |
34 | const innerContent = isCode ? (
35 |
36 | ) : (
37 | {result}
38 | )
39 |
40 | const content = !limitHeight ? (
41 | innerContent
42 | ) : (
43 |
44 | {innerContent}
45 |
46 | )
47 |
48 | return !term ? (
49 | content
50 | ) : (
51 | <>
52 |
53 | {term}
54 | {content}
55 |
56 | >
57 | )
58 | }
59 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/Value.tsx:
--------------------------------------------------------------------------------
1 | import Code from "./code/Code"
2 | import Markdown from "./Markdown"
3 |
4 | type Props = { children: boolean | number | string | unknown }
5 |
6 | function isJson(s: string) {
7 | try {
8 | JSON.parse(s)
9 | return true
10 | } catch (_err) {
11 | return false
12 | }
13 | }
14 |
15 | export default function Value({ children: s }: Props) {
16 | return typeof s === "number" ? (
17 | {s}
18 | ) : typeof s === "string" ? (
19 | isJson(s) ? (
20 |
21 | ) : (
22 | {s === "\n" ? "**" : s.trim()}
23 | )
24 | ) : (
25 | JSON.stringify(s, undefined, 2)
26 | )
27 | }
28 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/breadcrumbs/BreadcrumbBar.tsx:
--------------------------------------------------------------------------------
1 | import "./BreadcrumbBar.css"
2 |
3 | import { type BreadcrumbBarItemComponent } from "./BreadcrumbBarItem"
4 |
5 | type Props = {
6 | children: BreadcrumbBarItemComponent | BreadcrumbBarItemComponent[]
7 | }
8 |
9 | /** Inspiration: https://codepen.io/renaudtertrais/pen/nMGWqm */
10 | export default function BreadcrumbBar(props: Props) {
11 | return {props.children}
12 | }
13 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/breadcrumbs/BreadcrumbBarForBlock.tsx:
--------------------------------------------------------------------------------
1 | import { hasResult, type NonScalarPdlBlock as Block } from "../../helpers"
2 |
3 | import BreadcrumbBarForBlockId from "./BreadcrumbBarForBlockId"
4 |
5 | type Props = {
6 | block: Pick
7 | }
8 |
9 | export default function BreadcrumbBarForBlock({ block }: Props) {
10 | return (
11 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/breadcrumbs/BreadcrumbBarItem.tsx:
--------------------------------------------------------------------------------
1 | import type {
2 | JSXElementConstructor,
3 | PropsWithChildren,
4 | MouseEvent,
5 | ReactElement,
6 | ReactNode,
7 | } from "react"
8 | import { Tooltip } from "@patternfly/react-core"
9 |
10 | type Props = PropsWithChildren<{
11 | detail?: string
12 | className?: string
13 | onClick?: (evt: MouseEvent) => void
14 | tooltip?: ReactNode
15 | }>
16 |
17 | export type BreadcrumbBarItemComponent = ReactElement<
18 | Props,
19 | JSXElementConstructor
20 | >
21 |
22 | export default function BreadcrumbBarItem({
23 | className,
24 | children,
25 | detail,
26 | onClick,
27 | tooltip,
28 | }: Props) {
29 | const c = {children}
30 | return (
31 |
32 |
33 | {!tooltip ? c : {c} }
34 |
35 |
36 | )
37 | }
38 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/breadcrumbs/Def.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback } from "react"
2 | import { useLocation, useNavigate } from "react-router"
3 |
4 | import BreadcrumbBarItem from "../breadcrumbs/BreadcrumbBarItem"
5 |
6 | type Props = {
7 | /** Block id */
8 | id: string
9 |
10 | def: string
11 | value?: import("../../pdl_ast").PdlBlock
12 | supportsDrilldown?: boolean
13 | }
14 |
15 | /** One variable definition */
16 | export default function Def(props: Props) {
17 | const { id, def, value, supportsDrilldown = true } = props
18 |
19 | const navigate = useNavigate()
20 | const { hash } = useLocation()
21 | const drilldown = useCallback(
22 | (evt: import("react").MouseEvent) => {
23 | evt.stopPropagation()
24 | navigate(`?detail&type=def&id=${id}&def=${def}${hash}`)
25 | },
26 | [def, id, hash, navigate],
27 | )
28 |
29 | return (
30 |
34 | This block defines the variable "{def}".
35 | {value && <>Click to see details.>}
36 | >
37 | }
38 | onClick={!value || !supportsDrilldown ? undefined : drilldown}
39 | >
40 | ${def}
41 |
42 | )
43 | }
44 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/code/Code.tsx:
--------------------------------------------------------------------------------
1 | import { lazy, Suspense } from "react"
2 | import { stringify } from "yaml"
3 |
4 | import { tryJsonPrettyPrint } from "../../helpers"
5 | import { type PdlBlock } from "../../pdl_ast"
6 | import { block_code_cleanup } from "../../pdl_code_cleanup"
7 | const PreviewLight = lazy(() => import("./PreviewLight"))
8 |
9 | export type SupportedLanguage =
10 | | "yaml"
11 | | "json"
12 | | "javascript"
13 | | "python"
14 | | "plaintext"
15 | | "ipython"
16 |
17 | type Props = {
18 | block: PdlBlock
19 | language?: SupportedLanguage
20 | showLineNumbers?: boolean
21 | wrap?: boolean
22 | limitHeight?: boolean
23 | raw?: boolean
24 | }
25 |
26 | export default function Code({
27 | block,
28 | language = "yaml",
29 | showLineNumbers,
30 | wrap,
31 | raw = false,
32 | }: Props) {
33 | const value =
34 | typeof block === "string"
35 | ? language === "json"
36 | ? tryJsonPrettyPrint(block)
37 | : block
38 | : stringify(raw ? block : block_code_cleanup(block))
39 |
40 | return (
41 | }>
42 |
48 |
49 | )
50 | }
51 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/code/CodeGroup.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | DescriptionListTerm,
3 | DescriptionListGroup,
4 | DescriptionListDescription,
5 | } from "@patternfly/react-core"
6 |
7 | import Code, { type SupportedLanguage } from "./Code"
8 |
9 | type Props = {
10 | code: string
11 | lang?: SupportedLanguage
12 | term?: string
13 | }
14 |
15 | export default function CodeGroup({ code, lang, term = "Code" }: Props) {
16 | return (
17 |
18 | {term}
19 |
20 |
21 |
22 |
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/code/PreviewLight.css:
--------------------------------------------------------------------------------
1 | .pdl-preview-light {
2 | padding: 1em !important;
3 | font-size: 0.875em;
4 | }
5 | .pf-v6-theme-dark .pdl-preview-light {
6 | background-color: #01172799 !important;
7 | border: 1px solid #29292980;
8 | }
9 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/BlockNotFound.tsx:
--------------------------------------------------------------------------------
1 | export default function BlockNotFound(props: {
2 | pdl__id: string | null
3 | value: string
4 | }) {
5 | console.error("Block not found", props.pdl__id, props.value)
6 | return Block not found
7 | }
8 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/DefContent.css:
--------------------------------------------------------------------------------
1 | .pdl-variable-definition-content {
2 | height: 100%;
3 | }
4 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/DrawerContent.css:
--------------------------------------------------------------------------------
1 | .pf-v6-c-drawer__panel {
2 | padding: 0;
3 | }
4 |
5 | .pdl-drawer-content {
6 | border-radius: 0;
7 | .pdl-breadcrumb-bar {
8 | margin-top: 0.375em;
9 |
10 | .pdl-breadcrumb-bar-item--def:first-child {
11 | margin-left: 1em;
12 | }
13 | }
14 |
15 | .pf-v6-c-card__body {
16 | display: flex;
17 | flex-direction: column;
18 | overflow: hidden;
19 | padding: 0;
20 | }
21 |
22 | .pf-v6-c-tab-content {
23 | flex: 1;
24 | overflow: auto;
25 |
26 | & > .pdl-markdown,
27 | & > .pf-v6-c-description-list {
28 | padding: 1em 2em 0 2em;
29 | }
30 |
31 | & > pre {
32 | overflow-x: unset !important;
33 |
34 | & > code {
35 | white-space: pre-wrap !important;
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/Group.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | DescriptionListGroup,
3 | DescriptionListTerm,
4 | DescriptionListDescription,
5 | } from "@patternfly/react-core"
6 |
7 | import Value from "../Value"
8 |
9 | export default function Group({
10 | term,
11 | description,
12 | }: {
13 | term: string
14 | description: import("react").ReactNode
15 | }) {
16 | return (
17 |
18 | {term}
19 |
20 | {typeof description !== "object" ? (
21 | {description}
22 | ) : (
23 | description
24 | )}
25 |
26 |
27 | )
28 | }
29 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/RawTraceTabContent.tsx:
--------------------------------------------------------------------------------
1 | import Code from "../code/Code"
2 | import { type NonScalarPdlBlock as Model } from "../../helpers"
3 |
4 | export default function RawTraceTabContent({ block }: { block: Model }) {
5 | return
6 | }
7 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/ResultTabContent.tsx:
--------------------------------------------------------------------------------
1 | import Result from "../Result"
2 |
3 | import { hasParser, type PdlBlockWithResult } from "../../helpers"
4 |
5 | export default function UsageTabContent({
6 | block,
7 | }: {
8 | block: PdlBlockWithResult
9 | }) {
10 | return (
11 |
22 | )
23 | }
24 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/SourceTabContent.tsx:
--------------------------------------------------------------------------------
1 | import Code from "../code/Code"
2 | import { type NonScalarPdlBlock as Model } from "../../helpers"
3 |
4 | export default function SourceTabContent({ block }: { block: Model }) {
5 | return
6 | }
7 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/find.ts:
--------------------------------------------------------------------------------
1 | import { childrenOf } from "../timeline/model"
2 |
3 | import {
4 | isNonScalarPdlBlock,
5 | nonNullable,
6 | type NonScalarPdlBlock as Block,
7 | } from "../../helpers"
8 |
9 | /**
10 | * Traverse the tree under `block` looking for a sub-block with then
11 | * given `id`.
12 | */
13 | export default function find(
14 | block: import("../../pdl_ast").PdlBlock,
15 | id: string,
16 | ): null | Block {
17 | if (!isNonScalarPdlBlock(block)) {
18 | return null
19 | } else if (block.pdl__id === id) {
20 | return block
21 | } else {
22 | return (
23 | childrenOf(block)
24 | .map((child) => find(child, id))
25 | .filter(nonNullable)[0] || null
26 | )
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/kind/Call.tsx:
--------------------------------------------------------------------------------
1 | import Result from "../../Result"
2 |
3 | export default function ModelItems({
4 | block: { pdl__result },
5 | }: {
6 | block: import("../../../pdl_ast").CallBlock
7 | }) {
8 | return (
9 | <>
10 |
11 | >
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/kind/Code.tsx:
--------------------------------------------------------------------------------
1 | import Group from "../Group"
2 |
3 | import Code from "../../code/Code"
4 | import { isArgs, extractCode } from "../../../helpers"
5 |
6 | export default function CodeItems({
7 | block,
8 | }: {
9 | block:
10 | | import("../../../pdl_ast").ArgsBlock
11 | | import("../../../pdl_ast").CodeBlock
12 | }) {
13 | const { lang } = block
14 | const code = isArgs(block) ? block.args.join(" ") : extractCode(block)
15 |
16 | return (
17 | <>
18 |
30 | }
31 | />
32 | >
33 | )
34 | }
35 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/kind/Data.tsx:
--------------------------------------------------------------------------------
1 | import { stringify } from "yaml"
2 | import Result from "../../Result"
3 |
4 | export default function ModelItems({
5 | block: { def, pdl__result },
6 | }: {
7 | block: import("../../../pdl_ast").DataBlock
8 | }) {
9 | return (
10 |
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/kind/Error.tsx:
--------------------------------------------------------------------------------
1 | import Group from "../Group"
2 |
3 | export default function ErrorItems({
4 | block: { msg },
5 | }: {
6 | block: import("../../../pdl_ast").ErrorBlock
7 | }) {
8 | return
9 | }
10 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/kind/Function.tsx:
--------------------------------------------------------------------------------
1 | import { stringify } from "yaml"
2 |
3 | import Group from "../Group"
4 | import CodeGroup from "../../code/CodeGroup"
5 | import { block_code_cleanup } from "../../../pdl_code_cleanup"
6 |
7 | export default function FunctionItems({
8 | block: { def, function: func, return: retrn },
9 | }: {
10 | block: import("../../../pdl_ast").FunctionBlock
11 | }) {
12 | return (
13 | <>
14 | {def && }
15 |
16 |
17 | >
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/kind/If.tsx:
--------------------------------------------------------------------------------
1 | import Group from "../Group"
2 |
3 | export default function ModelItems({
4 | block: { if: condition, if_result },
5 | }: {
6 | block: import("../../../pdl_ast").IfBlock
7 | }) {
8 | return (
9 | <>
10 | {typeof condition === "string" && (
11 |
15 | )}
16 | {if_result !== undefined && (
17 |
25 | )}
26 | >
27 | )
28 | }
29 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/kind/Model.tsx:
--------------------------------------------------------------------------------
1 | import { stringify } from "yaml"
2 |
3 | import Group from "../Group"
4 | import Result from "../../Result"
5 | import {
6 | capitalizeAndUnSnakeCase,
7 | extractModel,
8 | extractStructuredModelResponse,
9 | hasInput,
10 | ModelBlock,
11 | } from "../../../helpers"
12 |
13 | export default function ModelItems({ block }: { block: ModelBlock }) {
14 | const { platform } = block
15 | const model = extractModel(block)
16 | const input = !hasInput(block)
17 | ? undefined
18 | : String(block.pdl__model_input[block.pdl__model_input.length - 1].content)
19 | const { meta } = extractStructuredModelResponse(block)
20 |
21 | const metaForDisplay = meta?.map(([k, v], idx) => (
22 |
28 | ))
29 |
30 | return (
31 | <>
32 | {typeof platform === "string" && (
33 |
34 | )}
35 | {typeof model === "string" && }
36 | {typeof input === "string" && }
37 | {metaForDisplay}
38 | >
39 | )
40 | }
41 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/kind/Read.tsx:
--------------------------------------------------------------------------------
1 | import Group from "../Group"
2 | import Result from "../../Result"
3 |
4 | export default function ModelItems({
5 | block: { message, pdl__result },
6 | }: {
7 | block: import("../../../pdl_ast").ReadBlock
8 | }) {
9 | return (
10 | <>
11 | {message && }
12 |
13 | >
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/detail/kind/Text.tsx:
--------------------------------------------------------------------------------
1 | import Result from "../../Result"
2 |
3 | export default function TextItems({
4 | block: { pdl__result },
5 | }: {
6 | block: import("../../../pdl_ast").TextBlock
7 | }) {
8 | return
9 | }
10 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/masonry/Duration.css:
--------------------------------------------------------------------------------
1 | .pdl-duration {
2 | font-size: 0.875em;
3 | cursor: default;
4 | }
5 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/masonry/Masonry.tsx:
--------------------------------------------------------------------------------
1 | import MasonryTile from "./MasonryTile"
2 |
3 | import "./Masonry.css"
4 |
5 | type Props = import("react").PropsWithChildren<{
6 | page: number
7 | perPage: number
8 | run: import("./MasonryCombo").Runner
9 | sml: import("./Toolbar").SML
10 | model: import("./Tile").default[]
11 | }>
12 |
13 | export default function Masonry({
14 | run,
15 | sml,
16 | model,
17 | children,
18 | page,
19 | perPage,
20 | }: Props) {
21 | return (
22 |
23 | {(!children ? [] : Array.isArray(children) ? children : [children])
24 | .filter(Boolean)
25 | .map((child, idx) => (
26 |
32 | {child}
33 |
34 | ))}
35 | {model.slice((page - 1) * perPage, page * perPage).map((props, idx) => (
36 |
43 | ))}
44 |
45 | )
46 | }
47 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/masonry/MasonryTileWrapper.tsx:
--------------------------------------------------------------------------------
1 | import { Card, CardBody, CardFooter, Divider } from "@patternfly/react-core"
2 |
3 | type Props = import("react").PropsWithChildren<{
4 | kind?: string
5 | variant?: "plain" | "default"
6 | sml: import("./Toolbar").SML
7 | header?: import("react").ReactNode
8 | footer?: import("react").ReactNode
9 | }>
10 |
11 | export default function MasonryTileWrapper({
12 | sml,
13 | header,
14 | footer,
15 | kind,
16 | variant = "default",
17 | children,
18 | }: Props) {
19 | return (
20 |
28 | {header}
29 | {children}
30 | {footer && (
31 | <>
32 |
33 | {footer}
34 | >
35 | )}
36 |
37 | )
38 | }
39 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/masonry/Tile.ts:
--------------------------------------------------------------------------------
1 | type Tile = {
2 | id: string
3 | def?: string | null
4 | kind?: string
5 | message?: string
6 |
7 | start_nanos?: number
8 | end_nanos?: number
9 | timezone?: string
10 |
11 | lang?: import("../code/Code").SupportedLanguage
12 | content: string | number | boolean
13 |
14 | footer1Key?: string
15 | footer1Value?: string | number | boolean
16 | footer2Key?: string
17 | footer2Value?: string | number | boolean
18 | footer3Key?: string
19 | footer3Value?: string | number | boolean
20 | stability?: import("./stability").StabilityMetric[]
21 |
22 | block?: import("../../helpers").NonScalarPdlBlock
23 | actions?: "run"[]
24 | }
25 |
26 | export default Tile
27 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/masonry/ToolbarPaginator.tsx:
--------------------------------------------------------------------------------
1 | import { Pagination, type PaginationProps } from "@patternfly/react-core"
2 |
3 | export type Props = Pick<
4 | Required,
5 | "itemCount" | "perPage" | "page"
6 | > & {
7 | setPage(n: number): void
8 | setPerPage(n: number): void
9 | }
10 |
11 | export default function ToolbarPaginator({
12 | itemCount,
13 | perPage,
14 | page,
15 | setPage,
16 | setPerPage,
17 | }: Props) {
18 | const onPerPageSelect = (
19 | _event:
20 | | import("react").MouseEvent
21 | | import("react").KeyboardEvent
22 | | MouseEvent,
23 | newPerPage: number,
24 | newPage: number,
25 | ) => {
26 | setPerPage(newPerPage)
27 | setPage(newPage)
28 | }
29 |
30 | const onSetPage = (
31 | _event:
32 | | import("react").MouseEvent
33 | | import("react").KeyboardEvent
34 | | MouseEvent,
35 | newPage: number,
36 | ) => {
37 | setPage(newPage)
38 | }
39 |
40 | return (
41 | itemCount > 1 && (
42 |
51 | )
52 | )
53 | }
54 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/masonry/ToolbarReplayButton.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback } from "react"
2 | import { Button, Tooltip } from "@patternfly/react-core"
3 |
4 | type Props = {
5 | run: import("./MasonryCombo").Runner
6 | isRunning: boolean
7 | }
8 |
9 | export default function ToolbarReplayButton({ run, isRunning }: Props) {
10 | const handleClickReplay = useCallback(() => run(), [run])
11 |
12 | const notLocal = !window.__TAURI_INTERNALS__
13 | return (
14 |
15 |
25 |
26 | )
27 | }
28 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/masonry/ToolbarShowSourceButton.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback } from "react"
2 | import { useLocation, useNavigate, useSearchParams } from "react-router"
3 |
4 | import { Button, Tooltip } from "@patternfly/react-core"
5 | import Icon from "@patternfly/react-icons/dist/esm/icons/code-icon"
6 |
7 | type Props = {
8 | /** Root of the program */
9 | root: string
10 | }
11 |
12 | export default function ToolbarShowSourceButton({ root }: Props) {
13 | const { hash } = useLocation()
14 | const navigate = useNavigate()
15 | const [searchParams] = useSearchParams()
16 |
17 | const onClick = useCallback(() => {
18 | if (searchParams.has("detail") && searchParams.get("type") === "source") {
19 | // close detail
20 | navigate(hash)
21 | } else {
22 | // open detail
23 | navigate(`?detail&type=block&id=${root}${hash}`)
24 | }
25 | }, [hash, navigate, searchParams, root])
26 |
27 | return (
28 |
29 | } onClick={onClick} />
30 |
31 | )
32 | }
33 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/masonry/View.ts:
--------------------------------------------------------------------------------
1 | export type View = "program" | "source" | "rawtrace"
2 |
3 | export function isView(v: string): v is View {
4 | return v === "program" || v === "source" || v === "rawtrace"
5 | }
6 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/masonry/condvar.ts:
--------------------------------------------------------------------------------
1 | export default class ConditionVariable {
2 | private condition: boolean = false
3 | private waitingPromises: {
4 | resolve: () => void
5 | reject: (reason?: unknown) => void
6 | }[] = []
7 |
8 | public async wait(): Promise {
9 | if (this.condition) {
10 | return Promise.resolve()
11 | }
12 |
13 | return new Promise((resolve, reject) => {
14 | this.waitingPromises.push({ resolve, reject })
15 | })
16 | }
17 |
18 | public signal(): void {
19 | if (this.waitingPromises.length > 0) {
20 | const { resolve } = this.waitingPromises.shift()!
21 | resolve()
22 | this.condition = true
23 | }
24 | }
25 |
26 | public reset(): void {
27 | this.condition = false
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/term/RunTerminal.css:
--------------------------------------------------------------------------------
1 | @import "@xterm/xterm/css/xterm.css";
2 |
3 | .pdl-run-terminal .xterm-rows {
4 | .xterm-fg-1 {
5 | color: var(--pf-t--global--color--nonstatus--red--default);
6 | }
7 | .xterm-fg-2 {
8 | color: var(--pf-t--global--color--nonstatus--green--default);
9 | }
10 | .xterm-fg-3 {
11 | color: var(--pf-t--global--color--nonstatus--yellow--default);
12 | }
13 | .xterm-fg-4 {
14 | color: var(--pf-t--global--color--nonstatus--blue--default);
15 | }
16 | .xterm-fg-5 {
17 | color: var(--pf-t--global--color--nonstatus--purple--default);
18 | }
19 | .xterm-fg-6 {
20 | color: var(--pf-t--global--color--nonstatus--teal--default);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/timeline/Timeline.tsx:
--------------------------------------------------------------------------------
1 | import { useMemo } from "react"
2 |
3 | import { computeModel } from "./model"
4 | import TimelineFromModel from "./TimelineFromModel"
5 |
6 | type Props = {
7 | block: import("../../pdl_ast").PdlBlock
8 | }
9 |
10 | export default function Timeline({ block }: Props) {
11 | const model = useMemo(() => computeModel(block), [block])
12 |
13 | return
14 | }
15 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/timeline/TimelineBar.tsx:
--------------------------------------------------------------------------------
1 | import { useMemo } from "react"
2 | import { Link, useLocation } from "react-router"
3 |
4 | type Props = import("./model").TimelineRowWithExtrema
5 |
6 | export default function TimelineBar({
7 | id,
8 | block: { kind, pdl__timing },
9 | min,
10 | max,
11 | }: Props) {
12 | const { hash } = useLocation()
13 | const style = useMemo(
14 | () => ({
15 | left: (100 * (pdl__timing.start_nanos - min)) / (max - min) + "%",
16 | width:
17 | (100 * (pdl__timing.end_nanos - pdl__timing.start_nanos)) /
18 | (max - min) +
19 | "%",
20 | }),
21 | [pdl__timing.start_nanos, pdl__timing.end_nanos, min, max],
22 | )
23 |
24 | return (
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | )
33 | }
34 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/timeline/TimelineFromModel.tsx:
--------------------------------------------------------------------------------
1 | import { useMemo } from "react"
2 |
3 | import TimelineRow from "./TimelineRow"
4 | import { pushPopsFor } from "./model"
5 |
6 | import "./Timeline.css"
7 |
8 | type Props = {
9 | model: import("./model").TimelineModel
10 |
11 | /** Block id -> ordinal */
12 | numbering?: Record
13 | }
14 |
15 | export default function TimelineFromModel({ model, numbering }: Props) {
16 | const [minStart, maxEnd] = useMemo(() => {
17 | const [minStart, maxEnd] = model.reduce(
18 | ([minStart, maxEnd], row) => [
19 | Math.min(minStart, row.block.pdl__timing.start_nanos),
20 | Math.max(
21 | maxEnd,
22 | row.block.pdl__timing.end_nanos || row.block.pdl__timing.start_nanos,
23 | ),
24 | ],
25 | [Number.MAX_VALUE, -Number.MIN_VALUE],
26 | )
27 | return [minStart, maxEnd]
28 | }, [model])
29 |
30 | const pushPops = useMemo(() => pushPopsFor(model), [model])
31 |
32 | return (
33 |
34 | {model.map((row, idx) => (
35 |
43 | ))}
44 |
45 | )
46 | }
47 |
--------------------------------------------------------------------------------
/pdl-live-react/src/view/timeline/TimelineRowKindCell.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@patternfly/react-core"
2 | import { useCallback } from "react"
3 | import { Link, useLocation } from "react-router"
4 |
5 | import { capitalizeAndUnSnakeCase } from "../../helpers"
6 |
7 | type Props = {
8 | row: import("./model").TimelineRowWithExtrema
9 | ordinal?: number
10 | }
11 |
12 | export default function TimelineRowKindCell({ row, ordinal }: Props) {
13 | const { id } = row
14 | const { hash } = useLocation()
15 |
16 | const link = useCallback(
17 | (props: object) => (
18 |
22 | ),
23 | [id, hash],
24 | )
25 |
26 | return (
27 |
28 | {ordinal && {ordinal}}
29 |
32 |
33 | )
34 | }
35 |
--------------------------------------------------------------------------------
/pdl-live-react/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/pdl-live-react/src/window.d.ts:
--------------------------------------------------------------------------------
1 | interface Window {
2 | __TAURI_INTERNALS__: Record
3 | }
4 |
--------------------------------------------------------------------------------
/pdl-live-react/tests/basics.spec.test.ts:
--------------------------------------------------------------------------------
1 | import { join } from "path"
2 | import { test, expect } from "@playwright/test"
3 | ;[
4 | { path: "#", title: /Viewer/ },
5 | { path: "#welcome", title: /Welcome/ },
6 | { path: "#about", title: /About/ },
7 | { path: "#upload", title: /Upload/ },
8 | { path: "#demos/Fibonacci", title: /Fibonacci/ },
9 | ].forEach(({ path, title }) =>
10 | test(`${path} has title ${title}`, async ({ page }) => {
11 | await page.goto(join("http://localhost:1420", path))
12 |
13 | // Expect a title "to contain" a substring.
14 | await expect(page).toHaveTitle(title)
15 | }),
16 | )
17 |
--------------------------------------------------------------------------------
/pdl-live-react/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4 | "target": "ES2020",
5 | "useDefineForClassFields": true,
6 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
7 | "module": "ESNext",
8 | "skipLibCheck": true,
9 |
10 | /* Bundler mode */
11 | "moduleResolution": "bundler",
12 | "allowImportingTsExtensions": true,
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "noEmit": true,
16 | "jsx": "react-jsx",
17 |
18 | /* Linting */
19 | "strict": true,
20 | "noUnusedLocals": true,
21 | "noUnusedParameters": true,
22 | "noFallthroughCasesInSwitch": true
23 | },
24 | "include": ["src"],
25 | }
26 |
--------------------------------------------------------------------------------
/pdl-live-react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | { "path": "./tsconfig.app.json" },
5 | { "path": "./tsconfig.node.json" }
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/pdl-live-react/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4 | "composite": true,
5 | "skipLibCheck": true,
6 | "module": "ESNext",
7 | "moduleResolution": "bundler",
8 | "noEmit": true,
9 | "allowSyntheticDefaultImports": true
10 | },
11 | "include": ["vite.config.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/pdl-live-react/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import { createHtmlPlugin } from "vite-plugin-html";
4 |
5 | const host = process.env.TAURI_DEV_HOST;
6 |
7 | // https://vitejs.dev/config/
8 | export default defineConfig(async () => ({
9 | base: "./",
10 | plugins: [
11 | react(),
12 | createHtmlPlugin({
13 | inject: {
14 | data: {
15 | htmlClassName: process.env.TAURI_ENV_FAMILY ? "tauri" : "web"
16 | }
17 | }
18 | }),
19 | ],
20 |
21 | // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
22 | //
23 | // 1. prevent vite from obscuring rust errors
24 | clearScreen: false,
25 | // 2. tauri expects a fixed port, fail if that port is not available
26 | server: {
27 | port: 1420,
28 | strictPort: true,
29 | host: host || false,
30 | hmr: host
31 | ? {
32 | protocol: "ws",
33 | host,
34 | port: 1421,
35 | }
36 | : undefined,
37 | watch: {
38 | // 3. tell vite to ignore watching `src-tauri`
39 | ignored: ["**/src-tauri/**"],
40 | },
41 | },
42 | }));
43 |
--------------------------------------------------------------------------------
/pylintrc:
--------------------------------------------------------------------------------
1 | [MAIN]
2 |
3 | disable=
4 | # Errors
5 | import-error,
6 | # Warnings
7 | exec-used,
8 | unused-argument,
9 | broad-exception-caught,
10 | fixme,
11 | # Conventions
12 | missing-module-docstring,missing-class-docstring,missing-function-docstring,
13 | use-implicit-booleaness-not-comparison,
14 | too-many-lines,
15 | line-too-long,
16 | # Refactors
17 | too-many-locals,
18 | too-many-branches,
19 | too-many-statements,
20 | too-few-public-methods,
21 | duplicate-code,
22 | wrong-import-position
23 |
24 | load-plugins=pylint.extensions.docparams,pylint.extensions.bad_builtin
25 |
--------------------------------------------------------------------------------
/scripts/generate_pdl_examples_runner.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # This script generates another script to run all PDL examples
4 | # Set the name of your pyenv virtualenv for PDL
5 | PDL_VENV=pdl
6 | OUTPUT_FILE=$(pwd)/run_pdl_examples.sh
7 |
8 | # Chdir to parent dir
9 | cd "$(dirname "$0")/.."
10 |
11 | # `set -e` exits the script on first non-zero exit code,
12 | # comment out if behavior is not desired.
13 | set -e
14 |
15 | # PyEnv setup
16 | export PYENV_ROOT="$HOME/.pyenv"
17 | [[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
18 | eval "$(pyenv init -)"
19 | eval "$(pyenv virtualenv-init -)"
20 | pyenv local "$PDL_VENV"
21 |
22 | echo "#!/usr/bin/env bash" > "$OUTPUT_FILE"
23 | echo "cd \"\$(dirname \"\$0\")/..\" || exit" >> "$OUTPUT_FILE"
24 |
25 | for example in examples/**/*.pdl; do
26 | echo "$example"
27 | printf "\necho \"Running %s\"\n" "$example" >> "$OUTPUT_FILE"
28 | printf "python -m pdl.pdl \"%s\"\n" "$example" >> "$OUTPUT_FILE"
29 | done
30 |
31 | echo "echo \"All examples have been run.\"" >> "$OUTPUT_FILE"
--------------------------------------------------------------------------------
/src/pdl/__init__.py:
--------------------------------------------------------------------------------
1 | from importlib.metadata import PackageNotFoundError, version
2 |
3 | from ._version import __version__ as hardcoded_version
4 |
5 |
6 | def _get_distribution_version(distribution_name: str) -> str:
7 | """
8 | This function attempts to retrieve the version of PDL package using
9 | importlib.metadata.
10 |
11 | When the package is not installed, importlib will raise a PackageNotFoundError.
12 | In this case, we fallback to the hardcoded version.
13 |
14 | When the package is installed, but the distribution name does not match,
15 | importlib will return the version of the package that is installed.
16 | """
17 | try:
18 | return version(distribution_name)
19 | except PackageNotFoundError:
20 | # This is a fallback for when the package is not recognized by importlib.metadata.
21 | # This can happen when the package is not installed.
22 | return (
23 | hardcoded_version
24 | if distribution_name == "pdl"
25 | else _get_distribution_version(
26 | "pdl" # This is a fallback to maintain the previous behavior.
27 | )
28 | )
29 |
30 |
31 | __version__ = _get_distribution_version("prompt-declaration-language")
32 |
--------------------------------------------------------------------------------
/src/pdl/optimize/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/prompt-declaration-language/f4fbdb850c2f3374d701cce9e4abd5a69e2798a4/src/pdl/optimize/__init__.py
--------------------------------------------------------------------------------
/src/pdl/optimize/config_parser.py:
--------------------------------------------------------------------------------
1 | from typing import Literal
2 |
3 | from pydantic import BaseModel, Field
4 |
5 |
6 | class OptimizationConfig(BaseModel):
7 | benchmark: str = Field()
8 | num_candidates: int = Field(default=30)
9 | num_demonstrations: int = Field(default=5)
10 | initial_test_set_size: int = Field(default=10)
11 | max_test_set_size: int = Field(default=1000)
12 | timeout: int = Field(default=120)
13 | budget_growth: Literal["double", "to_max"] = Field(default="double")
14 | shuffle_test: bool = Field(default=False)
15 | budget: str | None = Field(default=None)
16 | parallelism: int = Field(default=4)
17 | train_set_name: str = Field(default="train")
18 | test_set_name: str = Field(default="test")
19 | validation_set_name: str = Field(default="validation")
20 | demonstrations_variable_name: str = Field(default="demonstrations")
21 | variables: dict[str, list] = Field(default={})
22 | experiment_prefix: str = Field(default="")
23 |
24 | def get_variable_names(self) -> list[str]:
25 | return [self.demonstrations_variable_name, *self.variables.keys()]
26 |
--------------------------------------------------------------------------------
/src/pdl/pdl_analysis.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/prompt-declaration-language/f4fbdb850c2f3374d701cce9e4abd5a69e2798a4/src/pdl/pdl_analysis.py
--------------------------------------------------------------------------------
/src/pdl/pdl_compilers/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/prompt-declaration-language/f4fbdb850c2f3374d701cce9e4abd5a69e2798a4/src/pdl/pdl_compilers/__init__.py
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/prompt-declaration-language/f4fbdb850c2f3374d701cce9e4abd5a69e2798a4/tests/__init__.py
--------------------------------------------------------------------------------
/tests/data/call_expression_args.pdl:
--------------------------------------------------------------------------------
1 | defs:
2 | get_current_stock:
3 | function:
4 | product_name: string
5 | return:
6 | "FN::get_current_stock:: '${product_name}'\n"
7 | text:
8 |
9 | - def: object_example
10 | text: '{"product_name": "from_object"}'
11 | parser: json
12 | contribute: []
13 |
14 | - def: simple_call
15 | call: ${ get_current_stock }
16 | args:
17 | product_name: "Simple call!"
18 |
19 | - "${object_example}\n"
20 |
21 | - def: with_object_args
22 | call: ${ get_current_stock }
23 | args: ${object_example}
--------------------------------------------------------------------------------
/tests/data/function.pdl:
--------------------------------------------------------------------------------
1 | description: Function definition
2 | defs:
3 | template:
4 | function:
5 | preamble: string
6 | question: string
7 | notes: string
8 | return: |
9 | ${ preamble }
10 | ### Question: ${ question }
11 |
12 | ### Notes:
13 | ${ notes }
14 |
15 | ### Answer:
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/tests/data/hello.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world!
2 | text:
3 | - Hello, world!
4 | - "\n"
5 | - repeat:
6 | "This is your first PDL program\n"
7 | maxIterations: 2
8 |
--------------------------------------------------------------------------------
/tests/data/input.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Bob",
3 | "address": {
4 | "number": 87,
5 | "street": "Smith Road",
6 | "town": "Armonk",
7 | "state": "NY",
8 | "zip": 10504
9 | }
10 | }
--------------------------------------------------------------------------------
/tests/data/input1.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Carol",
3 | "address": {
4 | "number": 99,
5 | "street": "Miller Road",
6 | "town": "Armonk",
7 | "state": "NY",
8 | "zip": 10504
9 | }
10 | }
--------------------------------------------------------------------------------
/tests/data/input_data.txt:
--------------------------------------------------------------------------------
1 | Hello World!
2 | This is a prompt descriptor.
3 | Or is it?
4 |
--------------------------------------------------------------------------------
/tests/data/line/hello.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world!
2 | texts:
3 | Hello, world!
--------------------------------------------------------------------------------
/tests/data/line/hello1.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world!
2 | text:
3 | - Hello, world!
4 | - "\n"
5 | - repeat:
6 | "This is your first PDL program\n"
7 | num_iterations: 3
--------------------------------------------------------------------------------
/tests/data/line/hello10.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code with condition
2 | text:
3 | - 'Hello! '
4 | - lang: python
5 | code: |
6 | result = True
7 | defs: QUESTION
8 | contribute: []
9 | - if: '${ QUESTION }'
10 | then: How are you?
11 | spec: boolean
--------------------------------------------------------------------------------
/tests/data/line/hello11.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code with condition
2 | text:
3 | - 'Hello! '
4 | - lang: python
5 | code: |
6 | result = True
7 | defss: QUESTION
8 | contribute: []
9 | - if: '${ QUESTION }'
10 | then: How are you?
11 | spec: boolean
--------------------------------------------------------------------------------
/tests/data/line/hello12.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code with condition
2 | text:
3 | - 'Hello! '
4 | - lang: python
5 | code: |
6 | result = True
7 | def: QUESTION
8 | contribute: []
9 | - if: '${ QUESTION }'
10 | then: How are you?
11 | spec: boolean
--------------------------------------------------------------------------------
/tests/data/line/hello13.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code with condition
2 | text:
3 | - def: I
4 | lang: python
5 | code: result = 0
6 | - "\n"
7 | - repeat:
8 | text:
9 | - def: I
10 | lang: python
11 | code: result = ${ I } + 1
12 | spec: string
13 | - "\n"
14 | until: '${ I == 5 }'
15 |
--------------------------------------------------------------------------------
/tests/data/line/hello14.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world with model chaining
2 | text:
3 | - Hello,
4 | - model: watsonx_text/ibm/granite-34b-code-instruct
5 | def: GEN
6 | parameters:
7 | stop:
8 | - '!'
9 | include_stop_sequence: true
10 | mock_response: " World!"
11 | - def: translate
12 | function:
13 | sentence: string
14 | language: string
15 | spec: integer
16 | return:
17 | lastOf:
18 | - "\nTranslate the sentence '${ sentence }' to ${ language }\n"
19 | - model: watsonx_text/ibm/granite-20b-multilingual
20 | parameters:
21 | stop:
22 | - '!'
23 | include_stop_sequence: true
24 | mock_response: "Bonjour le monde!"
25 | - call: ${ translate }
26 | spec: string
27 | args:
28 | sentence: Hello,${ GEN }
29 | language: French
--------------------------------------------------------------------------------
/tests/data/line/hello15.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world
2 | text:
3 | - def: stutter
4 | function:
5 | return:
6 | lastOf:
7 | - get: boolean
8 | - ${ something }
9 | - "Hello World!\n"
10 | - call: ${ stutter }
11 |
--------------------------------------------------------------------------------
/tests/data/line/hello16.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world to call into a model
2 | text:
3 | - read: ./hello16_data.json
4 | parser: json
5 | def: data
6 | contribute: []
7 | spec: { questions: [string], answers: [object] }
8 | - model: watsonx_text/ibm/granite-20b-code-instruct
9 | def: model_output
10 | spec: {bob: integer, "carol": string}
11 | input:
12 | text:
13 | - for:
14 | question: ${ data.questions }
15 | answer: ${ data.answers }
16 | repeat:
17 | |
18 | ${ question }
19 | ${ answer }
20 | - 'Question: Write a JSON object with 2 fields "bob" and "carol" set to "20" and "30" respectively.'
21 | parser: yaml
22 | parameters:
23 | temperature: 0
24 | stop:
25 | - '}'
26 | include_stop_sequence: true
27 | mock_response: '{"bob": 20, "carol": 30}'
28 |
--------------------------------------------------------------------------------
/tests/data/line/hello16_data.json:
--------------------------------------------------------------------------------
1 | {
2 | "questions": [
3 | "Question: Write a JSON object with 2 fields 'a' and 'b' of type int and set to 0.",
4 | "Question: Write a JSON object with 3 fields 'number' and 'street' and 'town' set to '10', 'Miller Road', 'Armonk' respectively."
5 | ],
6 | "answers": [
7 | {"a": 0, "b": 0},
8 | {"number": 10, "street": "Miller Road", "town": "Armonk"}
9 | ]
10 | }
--------------------------------------------------------------------------------
/tests/data/line/hello17.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code
2 | text:
3 | - lang: python
4 | spec: integer
5 | code: |
6 | import string
7 | result = "hello"
8 |
--------------------------------------------------------------------------------
/tests/data/line/hello18.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code with condition
2 | text:
3 | - def: I
4 | lang: python
5 | code: result = 0
6 | - "\n"
7 | - repeat:
8 | text:
9 | - def: I
10 | lang: python
11 | code: result = ${ I } + 1
12 | - "\n"
13 | until: '${ J == 5 }'
14 |
--------------------------------------------------------------------------------
/tests/data/line/hello19.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world to call into a model
2 | defs:
3 | model: watsonx_text/ibm/granite-34b-code-instruct
4 | text:
5 | - Hello,
6 | - model: ${ models }
7 | spec: integer
8 | parameters:
9 | decoding_method: greedy
10 | stop:
11 | - '!'
12 | include_stop_sequence: true
13 | mock_response: " World!"
--------------------------------------------------------------------------------
/tests/data/line/hello20.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing model chaining
2 | text:
3 | - Who is${ NAME }?
4 |
--------------------------------------------------------------------------------
/tests/data/line/hello21.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code with condition
2 | text:
3 | - if: '${ QUESTION }'
4 | then: How are you?
--------------------------------------------------------------------------------
/tests/data/line/hello22.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code with condition
2 | text:
3 | - if: ${ true }
4 | then: ${ I }
--------------------------------------------------------------------------------
/tests/data/line/hello23.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code with condition
2 | text:
3 | - if: ${ false }
4 | then: "hello"
5 | else: ${ I }
--------------------------------------------------------------------------------
/tests/data/line/hello24.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world with model chaining
2 | text:
3 | - Hello,
4 | - model: watsonx_text/ibm/granite-34b-code-instruct
5 | def: GEN
6 | parameters:
7 | stop:
8 | - '!'
9 | include_stop_sequence: true
10 | mock_response: " World!"
11 | - def: translate
12 | function:
13 | sentence: string
14 | language: string
15 | spec: integer
16 | return:
17 | lastOf:
18 | - "\nTranslate the sentence '${ sentence }' to ${ language }\n"
19 | - model: watsonx_text/ibm/granite-34b-code-instruct
20 | parameters:
21 | mock_response: " World!"
22 | - call: ${ translate }
23 | spec: string
24 | args:
25 | sentence: Hello,${ GEN1 }
26 | language: ${ GEN2 }
--------------------------------------------------------------------------------
/tests/data/line/hello25.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world with model chaining
2 | text:
3 | - Hello,
4 | - model: watsonx_text/ibm/granite-34b-code-instruct
5 | def: GEN
6 | parameters:
7 | stop:
8 | - '!'
9 | include_stop_sequence: true
10 | - def: translate
11 | function:
12 | sentence: string
13 | language: string
14 | return:
15 | lastOf:
16 | - "\nTranslate the sentence '${ sentence1 }' to ${ language }\n"
17 | - model: watsonx_text/ibm/granite-20b-multilingual
18 | parameters:
19 | stop:
20 | - "!"
21 | - "\n"
22 | include_stop_sequence: true
23 | - call: ${ translate }
24 | spec: string
25 | args:
26 | sentence: Hello,${ GEN }
27 | language: French
--------------------------------------------------------------------------------
/tests/data/line/hello26.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world to call into a model
2 | text:
3 | - read: hello16_data.json
4 | parser: json
5 | def: data
6 | contribute: []
7 | spec: { questions: [string], answers: [object] }
8 | - model: watsonx_text/ibm/granite-34b-code-instruct
9 | def: model_output
10 | input:
11 | text:
12 | - for:
13 | question: "Hello"
14 | answer: ${ data.answers }
15 | repeat:
16 | text:
17 | - ${ question }
18 | - ${ answer }
19 | - 'Question: Write a JSON object with 2 fields "bob" and "carol" set to "20" and "30" respectively.'
20 | parameters:
21 | decoding_method: greedy
22 | stop:
23 | - '}'
24 | include_stop_sequence: true
25 | mock_response:
26 | |
27 | Here is the code:
28 | ```json
29 | {
30 | "bob": "20",
31 | "carol": "30"
32 | }
--------------------------------------------------------------------------------
/tests/data/line/hello27.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world to call into a model
2 | text:
3 | - read: hello16_data.json
4 | parser: json
5 | def: data
6 | contribute: []
7 | spec: { questions: [string], answers: [object] }
8 | - model: watsonx_text/ibm/granite-34b-code-instruct
9 | def: model_output
10 | input:
11 | text:
12 | - for:
13 | question: ${ [ ] }
14 | answer: ${ data.answers }
15 | repeat:
16 | text:
17 | - ${ question }
18 | - ${ answer }
19 | - 'Question: Write a JSON object with 2 fields "bob" and "carol" set to "20" and "30" respectively.'
20 | parameters:
21 | decoding_method: greedy
22 | stop:
23 | - '}'
24 | include_stop_sequence: true
25 | mock_response:
26 | |
27 | Here is the code:
28 | ```json
29 | {
30 | "bob": "20",
31 | "carol": "30"
32 | }
--------------------------------------------------------------------------------
/tests/data/line/hello28.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code with condition
2 | text:
3 | - 'Hello! '
4 | - lang: python
5 | code: |
6 | result = True
7 | def: QUESTION
8 | contribute: []
9 | - ${ QUESTION1 }
--------------------------------------------------------------------------------
/tests/data/line/hello29.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code with condition
2 | text:
3 | - 'Hello! '
4 | - lang: python
5 | code: |
6 | result = True
7 | def: QUESTION
8 | contribute: []
9 | - data:
10 | x: ${ QUESTION1 }
11 | y: ${ QUESTION2 }
12 | z:
13 | a: ${ QUESTION3 }
14 | b:
15 | c: ${ QUESTION4 }
--------------------------------------------------------------------------------
/tests/data/line/hello3.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world to call into a model
2 | defs:
3 | model: watsonx_text/ibm/granite-20b-code-instruct
4 | text:
5 | - Hello,
6 | - model: ${ model }
7 | spec: integer
8 | parameters:
9 | temperature: 0
10 | stop:
11 | - '!'
12 | mock_response: " World!"
--------------------------------------------------------------------------------
/tests/data/line/hello30.pdl:
--------------------------------------------------------------------------------
1 | description: hello with bad for loop
2 | defs:
3 | val:
4 | data:
5 | p: 1
6 | for:
7 | k: ${ val }
8 | repeat:
9 | hello
10 |
--------------------------------------------------------------------------------
/tests/data/line/hello31.pdl:
--------------------------------------------------------------------------------
1 | defs:
2 |
3 | # ... several other defs, ~85 lines
4 | get_current_weather:
5 | function:
6 | subject: string
7 | return:
8 | text: hello
9 | show_result: false
--------------------------------------------------------------------------------
/tests/data/line/hello4.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world!
2 | text:
3 | - Hello, world!
4 | - "\n"
5 | - repeats:
6 | "This is your first PDL program\n"
7 | maxIterations: 3
--------------------------------------------------------------------------------
/tests/data/line/hello7.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code
2 | text:
3 | - 'Hello, '
4 | - lans: python
5 | code: |
6 | import random
7 | import string
8 | result = random.choice(string.ascii_lowercase)
9 | - '!'
--------------------------------------------------------------------------------
/tests/data/line/hello8.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code
2 | text:
3 | - 'Hello, '
4 | - lang: python
5 | codea: |
6 | import random
7 | import string
8 | result = random.choice(string.ascii_lowercase)
9 | - '!'
--------------------------------------------------------------------------------
/tests/data/line/hello9.pdl:
--------------------------------------------------------------------------------
1 | description: Hello world showing call out to python code
2 | text:
3 | - lang: python
4 | spec: integer
5 | code: |
6 | import string
7 | result = "hello"
--------------------------------------------------------------------------------
/tests/results/contrib/prompt_library/CoT.0.result:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tests/results/contrib/prompt_library/ReAct.0.result:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tests/results/contrib/prompt_library/ReWoo.0.result:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tests/results/contrib/prompt_library/tools.0.result:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tests/results/examples/demo/1-hello.0.result:
--------------------------------------------------------------------------------
1 | Hello
2 | Hello
--------------------------------------------------------------------------------
/tests/results/examples/demo/11-repeat.0.result:
--------------------------------------------------------------------------------
1 | Bob's number is 1
2 | {"name": "Bob", "number": 1}
3 | Carol's number is 2
4 | {"name": "Carol", "number": 2}
5 | David's number is 3
6 | {"name": "David", "number": 3}
7 | Ernest's number is 4
8 | {"name": "Ernest", "number": 4}
--------------------------------------------------------------------------------
/tests/results/examples/demo/2-model-chaining.0.result:
--------------------------------------------------------------------------------
1 | Hello
2 | Hello
3 | Did you just say Hello?
4 | Yes, I did. It's a common greeting, similar to how humans might respond when they first interact with an artificial intelligence like me. How can I assist you today?
--------------------------------------------------------------------------------
/tests/results/examples/demo/3-def-use.0.result:
--------------------------------------------------------------------------------
1 | Hello
2 | Hello
3 | Hello translates to "Bonjour" in French.
--------------------------------------------------------------------------------
/tests/results/examples/demo/3-def-use.1.result:
--------------------------------------------------------------------------------
1 | Hello
2 | Hello
3 | Hello in French is "Bonjour".
--------------------------------------------------------------------------------
/tests/results/examples/demo/4-function.0.result:
--------------------------------------------------------------------------------
1 | 'J'aime Paris !'
2 | The translation of "I love Madrid!" into Spanish is: "Me encanta Madrid!"
--------------------------------------------------------------------------------
/tests/results/examples/demo/4-function.1.result:
--------------------------------------------------------------------------------
1 | 'J'aime Paris !'
2 | The translation of "I love Madrid!" into Spanish is: "Me encanta Madrid."
--------------------------------------------------------------------------------
/tests/results/examples/demo/7-chatbot-roles.0.result:
--------------------------------------------------------------------------------
1 | Type `quit` to exit this chatbot.
2 | APR stands for Annual Percentage Rate. It's a measure of the annual cost of borrowing money, expressed as a percentage. This includes not only interest but also any fees charged by lenders. APR is used for many types of loans and credit cards to help consumers compare different offers more effectively.
3 |
4 |
5 |
6 | I'm sorry for any confusion, but it seems like your message "quit" was intended as a command rather than a statement. As an AI, I don't have the capability to exit conversations or processes on my own. My purpose is to provide information and engage in text-based interactions. If you want our conversation to end, you can simply close this window or tab on your device.
7 |
8 |
--------------------------------------------------------------------------------
/tests/results/examples/demo/7-chatbot-roles.1.result:
--------------------------------------------------------------------------------
1 | Type `quit` to exit this chatbot.
2 | APR stands for Annual Percentage Rate. It's a measure of the annual cost of borrowing money, expressed as a percentage. This includes not only interest but also any fees associated with the loan. APR is used for many types of loans, including mortgages and credit cards, to help consumers compare different lending options more effectively.
3 |
4 |
5 |
6 | I'm sorry for any confusion, but as an AI, I don't have the ability to interpret "quit" as a command to end our conversation. If you want to exit, feel free to type "quit" or simply stop sending messages. I'm here to assist you until then.
7 |
8 |
--------------------------------------------------------------------------------
/tests/results/examples/demo/8-tools.0.result:
--------------------------------------------------------------------------------
1 | Out of 1400 participants, 400 passed the test. What percentage is that?
2 | [{"name": "calc", "arguments": {"expr": "(400 / 1400) * 100"}}]
3 | 28.57142857142857
--------------------------------------------------------------------------------
/tests/results/examples/demos/react_fun.0.result:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tests/results/examples/input/input_test.0.result:
--------------------------------------------------------------------------------
1 | Hello World!
--------------------------------------------------------------------------------
/tests/results/examples/input/input_test1.0.result:
--------------------------------------------------------------------------------
1 | The following will prompt the user on stdin.
2 | Hello
--------------------------------------------------------------------------------
/tests/results/examples/input/input_test2.0.result:
--------------------------------------------------------------------------------
1 | A multiline stdin input.
2 | Hello
3 |
--------------------------------------------------------------------------------
/tests/results/examples/intrinsics/demo-hallucination.0.result:
--------------------------------------------------------------------------------
1 | Did Faith Hill take a break from recording after releasing her second album, It Matters to Me?
2 |
3 | The answer is: Yes, Faith Hill took a three-year break from recording after releasing her second album, It Matters to Me.
4 | I am not hallucinating, promise!
5 | The citation is: After discovering that Hill was
6 | pregnant with their first child, the couple married on October 6, 1996. The
7 | couple have three daughters together: Gracie Katherine (born 1997), Maggie Elizabeth (born 1998)
8 | and Audrey Caroline (born 2001). Since their marriage, Hill and McGraw have endeavored
9 | never to be apart for more than three consecutive days. After the release of It Matters to Me,
10 | Hill took a three-year break from recording to give herself a rest from four years of touring
11 | and to begin a family with McGraw. During her break, she joined forces with her husband
12 | for their first duet, "It's Your Love".
13 |
--------------------------------------------------------------------------------
/tests/results/examples/prompt_library/gsm8k_cot.0.result:
--------------------------------------------------------------------------------
1 | Answer the questions to the best of your abilities.
2 |
3 | Result: {'answer': '1. Jacob earns $6 per hour.\n2. Jake earns thrice what Jacob does, so Jake earns 3 * $6 = $18 per hour.\n3. Jake works 8 hours a day, so he earns $18 * 8 = $144 per day.\n4. Jake works 5 days, so he earns $144 * 5 = $720 in 5 days.\nThe answer is $720.'}
4 |
--------------------------------------------------------------------------------
/tests/results/examples/prompt_library/gsm8k_react.0.result:
--------------------------------------------------------------------------------
1 | Result: {'answer': '$720'}
2 |
--------------------------------------------------------------------------------
/tests/results/examples/prompt_library/gsm8k_rewoo.0.result:
--------------------------------------------------------------------------------
1 | Result: {'answer': 'Jake earns $18 per hour. In 5 days, working 8 hours a day, Jake works 5 * 8 = 40 hours. Therefore, Jake earns 40 * $18 = $720 in 5 days.\n\nAnswer: $720'}
2 |
--------------------------------------------------------------------------------
/tests/results/examples/react/react_fun.0.result:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/prompt-declaration-language/f4fbdb850c2f3374d701cce9e4abd5a69e2798a4/tests/results/examples/react/react_fun.0.result
--------------------------------------------------------------------------------
/tests/results/examples/sdk/hello.0.result:
--------------------------------------------------------------------------------
1 | Hello
2 | Hello
--------------------------------------------------------------------------------
/tests/results/examples/tools/calc.0.result:
--------------------------------------------------------------------------------
1 | Out of 1400 participants, 400 passed the test. What percentage is that?
2 | [{"name": "calc", "arguments": {"expr": "(400 / 1400) * 100"}}]
3 | 28.57142857142857
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/calling_llm.0.result:
--------------------------------------------------------------------------------
1 | Hello
2 | Hello
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/calling_llm_chaining.0.result:
--------------------------------------------------------------------------------
1 | Hello
2 | Hello
3 | Did you just say Hello?
4 | Yes, I did. It's a common greeting, similar to how humans might respond when they first interact with an artificial intelligence like me. How can I assist you today?
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/calling_llm_with_input.0.result:
--------------------------------------------------------------------------------
1 | Hello
2 | The translation of "Hello" in French is "Bonjour".
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/calling_llm_with_input_messages.0.result:
--------------------------------------------------------------------------------
1 | Hello
2 | The translation of 'Hello' into French is 'Bonjour'.
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/code_command.0.result:
--------------------------------------------------------------------------------
1 | Hello World!
2 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/code_jinja.0.result:
--------------------------------------------------------------------------------
1 | Hello World!
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/code_pdl.0.result:
--------------------------------------------------------------------------------
1 | Hello
2 | Hello! How can I assist you today? Let's chat about anything you'd like. Whether it's general knowledge, explanations on various topics, or just a casual conversation, I'm here to help. What's on your mind?
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/code_python.0.result:
--------------------------------------------------------------------------------
1 | Hello, o
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/code_python.1.result:
--------------------------------------------------------------------------------
1 | Hello, r
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/data_block_raw.0.result:
--------------------------------------------------------------------------------
1 | {'name': '${ name }', 'phone': '${ phone }'}
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/defs-hello.0.result:
--------------------------------------------------------------------------------
1 | Hello World!
2 | Good bye
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/defs.0.result:
--------------------------------------------------------------------------------
1 | 'J'aime Paris !'
2 | The translation of "I love Madrid!" into Spanish is: "Me encanta Madrid!"
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/defs.1.result:
--------------------------------------------------------------------------------
1 | 'J'aime Paris !'
2 | The translation of "I love Madrid!" into Spanish is: "Me encanta Madrid."
3 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/for.0.result:
--------------------------------------------------------------------------------
1 | 1234
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/for_array.0.result:
--------------------------------------------------------------------------------
1 | [1, 2, 3, 4]
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/for_lastOf.0.result:
--------------------------------------------------------------------------------
1 | 4
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/for_multiple_lists.0.result:
--------------------------------------------------------------------------------
1 | Bob's number is 1
2 | Carol's number is 2
3 | David's number is 3
4 | Ernest's number is 4
5 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/for_object.0.result:
--------------------------------------------------------------------------------
1 | {'Bob': 1, 'Carol': 2, 'David': 3, 'Ernest': 4}
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/for_with.0.result:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 | 4
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/free_variables.0.result:
--------------------------------------------------------------------------------
1 | Hello World!
2 | ABC
3 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/function_alias.0.result:
--------------------------------------------------------------------------------
1 | Hello World!
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/function_definition.0.result:
--------------------------------------------------------------------------------
1 | 'J'aime Paris !'
2 | The translation of "I love Madrid!" into Spanish is: "Me encanta Madrid!"
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/function_definition.1.result:
--------------------------------------------------------------------------------
1 | 'J'aime Paris !'
2 | The translation of "I love Madrid!" into Spanish is: "Me encanta Madrid."
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/function_definition.2.result:
--------------------------------------------------------------------------------
1 | 'J'adore Paris !'
2 | The translation of "I love Madrid!" into Spanish is: "Me encanta Madrid!"
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/function_empty_context.0.result:
--------------------------------------------------------------------------------
1 | Hello World!Greetings! I am Granite, a language model developed by IBM in 2024. How may I assist you today?
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/function_empty_context.1.result:
--------------------------------------------------------------------------------
1 | Hello World!Hello there! How can I assist you today? If you have any questions or need information on a particular topic, feel free to ask. I'm here to help.
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/function_optional_params.0.result:
--------------------------------------------------------------------------------
1 | Hello World Universe!
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/if.0.result:
--------------------------------------------------------------------------------
1 | Hello! How are you?
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/import.0.result:
--------------------------------------------------------------------------------
1 | Bye!
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/import_lib.0.result:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/prompt-declaration-language/f4fbdb850c2f3374d701cce9e4abd5a69e2798a4/tests/results/examples/tutorial/import_lib.0.result
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/independent.0.result:
--------------------------------------------------------------------------------
1 | hello in French!Bonjour! (Hello!) en Espanol!¡Hola! ¿En qué puedo ayudarte hoy? (Hello! How can I assist you today?)Goodbye!¡Adiós! (Goodbye!)
2 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/independent.1.result:
--------------------------------------------------------------------------------
1 | hello in French!Bonjour! (Hello!) en Espanol!¡Hola! ¿En qué puedo ayudarte hoy? (Hello! How can I assist you today?)Which language did I use last?You used Spanish in your previous message. Here's a quick summary:
2 |
3 | - Your first message was in English.
4 | - The second message was in Spanish.
5 |
6 | So, the languages you've used are English and Spanish.
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/independent_docs.0.result:
--------------------------------------------------------------------------------
1 | Hello world!Goodbye world!Hello and goodbye to you too! It seems like you've just greeted the world and bid it farewell in quick succession. I'm here to help, so if you have any questions or need information on a specific topic, feel free to ask. How can I assist you today?
2 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/independent_docs.1.result:
--------------------------------------------------------------------------------
1 | Hello world!Goodbye world!Hello and goodbye! It seems like you've greeted and bid farewell in quick succession. I'm here to help with any questions or tasks you have, so feel free to ask me anything. How can I assist you today?
2 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/independent_for.0.result:
--------------------------------------------------------------------------------
1 | Hello in FrenchBonjour! (Hello!)en Espanol¡Hola! ¿En qué puedo ayudarte hoy? (Translation: Hello! How can I assist you today?)Goodbye!¡Adiós! (Goodbye!)
2 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/input_file.0.result:
--------------------------------------------------------------------------------
1 | Hello World!
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/input_file_json.0.result:
--------------------------------------------------------------------------------
1 | Bob lives at the following address:
2 | 87 Smith Road in the town of Armonk, NY
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/input_stdin.0.result:
--------------------------------------------------------------------------------
1 | The following will prompt the user on stdin.
2 | What is APR?
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/input_stdin_multiline.0.result:
--------------------------------------------------------------------------------
1 | A multiline stdin input.
2 | Hello
3 | Bye
4 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/loop_index.0.result:
--------------------------------------------------------------------------------
1 | 123
2 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/muting_block_output.0.result:
--------------------------------------------------------------------------------
1 | The french sentence was: 'J'aime Paris !'
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/muting_block_output.1.result:
--------------------------------------------------------------------------------
1 | The french sentence was: 'J'adore Paris !'
2 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/parser-regex.0.result:
--------------------------------------------------------------------------------
1 | {"name": "Hello"}
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/parser_findall.0.result:
--------------------------------------------------------------------------------
1 | ['1', '2', '3', '4']
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/parser_regex_code.0.result:
--------------------------------------------------------------------------------
1 | result = add_two_numbers(3, 5)
2 | print(result) # Output will be: 8
3 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/parser_regex_code.1.result:
--------------------------------------------------------------------------------
1 | result = add_two_numbers(3, 5)
2 | print(result) # Output: 8
3 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/programs/demo-hallucination.0.result:
--------------------------------------------------------------------------------
1 | Did Faith Hill take a break from recording after releasing her second album, It Matters to Me?
2 |
3 | The answer is: Yes, Faith Hill took a three-year break from recording after releasing her second album, It Matters to Me.
4 | I am not hallucinating, promise!
5 | The citation is: After discovering that Hill was
6 | pregnant with their first child, the couple married on October 6, 1996. The
7 | couple have three daughters together: Gracie Katherine (born 1997), Maggie Elizabeth (born 1998)
8 | and Audrey Caroline (born 2001). Since their marriage, Hill and McGraw have endeavored
9 | never to be apart for more than three consecutive days. After the release of It Matters to Me,
10 | Hill took a three-year break from recording to give herself a rest from four years of touring
11 | and to begin a family with McGraw. During her break, she joined forces with her husband
12 | for their first duet, "It's Your Love".
13 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/repeat.0.result:
--------------------------------------------------------------------------------
1 | 0: Bob's number is 42
2 | 1: Carol's number is 2
3 |
4 |
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/simple_program.0.result:
--------------------------------------------------------------------------------
1 | Hello, world!
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/variable_def_use.0.result:
--------------------------------------------------------------------------------
1 | Hello
2 | Hello
3 | GEN is equal to: Hello
--------------------------------------------------------------------------------
/tests/results/examples/tutorial/while.0.result:
--------------------------------------------------------------------------------
1 | 123
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/call-no-args.0.result:
--------------------------------------------------------------------------------
1 | hello world
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/call-with-args.0.result:
--------------------------------------------------------------------------------
1 | hello world 4 bye
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/code-python.0.result:
--------------------------------------------------------------------------------
1 | {'foo': 3}
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/data1.0.result:
--------------------------------------------------------------------------------
1 | xxxx3True
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/data2.0.result:
--------------------------------------------------------------------------------
1 | xxxx3True
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/data3.0.result:
--------------------------------------------------------------------------------
1 | ${x}3True
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/data4.0.result:
--------------------------------------------------------------------------------
1 | yyyyxxxx3True
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/if1.0.result:
--------------------------------------------------------------------------------
1 | hi
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/if2.0.result:
--------------------------------------------------------------------------------
1 | good
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/include1.0.result:
--------------------------------------------------------------------------------
1 | hello world 4 bye
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/json-parser-lastOf.0.result:
--------------------------------------------------------------------------------
1 | value
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/json-parser.0.result:
--------------------------------------------------------------------------------
1 | {"key": "value"}value
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/jsonl-parser.0.result:
--------------------------------------------------------------------------------
1 | [{"key": "value"}, {"key2": "value2"}]valuevalue2
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/model-input-array.0.result:
--------------------------------------------------------------------------------
1 | As an assistant living in Europe, I'd be happy to share that the fastest land animal native to this continent is actually the Greyhound. These dogs are renowned for their incredible speed and can reach top speeds of around 43-45 miles per hour (70 km/h). They were originally bred for hunting, particularly for their ability to chase down prey at high velocities.
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/model-input-nested.0.result:
--------------------------------------------------------------------------------
1 | {"role": "user", "content": "answer as if you live in europe", "defsite": "text.0.message"}{"role": "user", "content": "what is the fastest animal where i live?", "defsite": "text.1.text.0.message"}As an assistant living in Europe, I'd be happy to share that the fastest land animal native to this continent is actually the Greyhound dog breed. These dogs are renowned for their incredible speed and agility on the ground. They can reach top speeds of around 45-48 miles per hour (72-77 kilometers per hour), making them one of the fastest animals in Europe.
2 |
3 | However, if we consider wild animals, the Cheetah is the fastest land animal globally and can be found in parts of Africa, including regions near the European border with North African countries like Libya and Tunisia. Cheetahs typically reach speeds up to 60-70 miles per hour (97-113 kilometers per hour), but they are not native to Europe.
4 |
5 | For a truly European animal, the Greyhound remains the fastest land creature in our region.
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/model-input-nested.1.result:
--------------------------------------------------------------------------------
1 | {'role': 'user', 'content': 'answer as if you live in europe', 'defsite': 'text.0.message'}{'role': 'user', 'content': 'what is the fastest animal where i live?', 'defsite': 'text.1.text.0.message'}As an assistant living in Europe, I'd be happy to share that the fastest land animal native to this continent is actually the Greyhound dog breed. These dogs are renowned for their incredible speed and agility on the ground. They can reach top speeds of around 45-48 miles per hour (72-77 kilometers per hour), making them one of the fastest animals in Europe.
2 |
3 | However, if we consider wild animals, the Cheetah is the fastest land animal globally and can be found in parts of Africa, including regions near the European border with North African countries like Libya and Tunisia. Cheetahs typically reach speeds up to 60-70 miles per hour (97-113 kilometers per hour), but they are not native to Europe.
4 |
5 | For a truly European animal, the Greyhound remains the fastest land creature in our region.
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/object1.0.result:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/object2.0.result:
--------------------------------------------------------------------------------
1 | foo2
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/read-file.0.result:
--------------------------------------------------------------------------------
1 | {"a": {"b": 3}}3
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/regex-findall.0.result:
--------------------------------------------------------------------------------
1 | [(999, 888)]
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/regex-findall.1.result:
--------------------------------------------------------------------------------
1 | [('999', '888')]
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/repeat1.0.result:
--------------------------------------------------------------------------------
1 | 234
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/repeat2.0.result:
--------------------------------------------------------------------------------
1 | 1a2b3c
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/repeat3.0.result:
--------------------------------------------------------------------------------
1 | 4a5b6c
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/scoping_1.0.result:
--------------------------------------------------------------------------------
1 | 3yo3mo
2 |
--------------------------------------------------------------------------------
/tests/results/pdl-live-react/src-tauri/tests/cli/scoping_1_wrapper.0.result:
--------------------------------------------------------------------------------
1 | 3yo3mo
2 |
--------------------------------------------------------------------------------
/tests/results/tests/data/call_expression_args.12.result:
--------------------------------------------------------------------------------
1 | FN::get_current_stock:: 'Simple call!'
2 | {'product_name': 'from_object'}
3 | FN::get_current_stock:: 'from_object'
4 |
5 |
--------------------------------------------------------------------------------
/tests/results/tests/data/function.0.result:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tests/results/tests/data/hello.0.result:
--------------------------------------------------------------------------------
1 | Hello, world!
2 | This is your first PDL program
3 | This is your first PDL program
4 |
5 |
--------------------------------------------------------------------------------
/tests/results/tests/data/optimizer_gsm8k.0.result:
--------------------------------------------------------------------------------
1 | Answer the questions to the best of your abilities.
2 |
3 |
4 | The answer is 144
5 |
--------------------------------------------------------------------------------
/tests/test_array.py:
--------------------------------------------------------------------------------
1 | from pdl.pdl import exec_dict
2 |
3 | array_data = {"description": "Array", "array": ["1", "2", "3", "4"]}
4 |
5 |
6 | def test_array_data():
7 | result = exec_dict(array_data)
8 | assert result == ["1", "2", "3", "4"]
9 |
10 |
11 | for_data = {
12 | "description": "For block example",
13 | "for": {
14 | "i": [1, 2, 3, 4],
15 | },
16 | "repeat": "${ i }",
17 | "join": {"as": "array"},
18 | }
19 |
20 |
21 | def test_for_data():
22 | result = exec_dict(for_data)
23 | assert result == [1, 2, 3, 4]
24 |
25 |
26 | repeat_until_data = {
27 | "description": "Repeat until",
28 | "lastOf": [
29 | {
30 | "def": "I",
31 | "text": {"lang": "python", "code": "result = 0"},
32 | },
33 | {
34 | "repeat": {
35 | "def": "I",
36 | "lang": "python",
37 | "code": "result = ${ I } + 1",
38 | },
39 | "until": "${ I == 5 }",
40 | "join": {"as": "array"},
41 | },
42 | ],
43 | }
44 |
45 |
46 | def test_repeat_until():
47 | result = exec_dict(repeat_until_data)
48 | assert result == [1, 2, 3, 4, 5]
49 |
--------------------------------------------------------------------------------
/tests/test_include.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 | from pdl.pdl import InterpreterConfig, exec_dict
4 |
5 | include_data = {
6 | "description": "Include test",
7 | "text": [
8 | "Start\n",
9 | {"include": "./data/hello.pdl"},
10 | "End",
11 | ],
12 | }
13 |
14 |
15 | def test_include():
16 | config = InterpreterConfig(cwd=Path(__file__).parent)
17 | text = exec_dict(include_data, config=config)
18 | assert (
19 | text
20 | == """Start
21 | Hello, world!
22 | This is your first PDL program
23 | This is your first PDL program
24 | End"""
25 | )
26 |
27 |
28 | biz = {
29 | "description": "Include test",
30 | "text": [
31 | {"include": "data/function.pdl"},
32 | {
33 | "call": "${ template }",
34 | "args": {
35 | "preamble": "preamble data",
36 | "question": "question data",
37 | "notes": "notes data",
38 | },
39 | },
40 | ],
41 | }
42 |
43 |
44 | def test_biz():
45 | config = InterpreterConfig(cwd=Path(__file__).parent)
46 | text = exec_dict(biz, config=config)
47 | assert (
48 | text
49 | == "preamble data\n### Question: question data\n\n### Notes:\nnotes data\n\n### Answer:\n"
50 | )
51 |
--------------------------------------------------------------------------------
/tests/test_lib_version.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | import pdl
4 |
5 |
6 | def test_version():
7 | # Make sure the __version__ attribute is available.
8 | assert pdl.__version__ is not None
9 |
10 | # Since pdl is not installed, the version returned will be the dev version.
11 | # NOTE: For some reason, the version is not the same as the hardcoded version.
12 | assert pdl.__version__.startswith("0.1.dev")
13 |
14 |
15 | if __name__ == "__main__":
16 | pytest.main(["-v", "--tb=short", __file__])
17 |
--------------------------------------------------------------------------------
/tests/test_object.py:
--------------------------------------------------------------------------------
1 | from pdl.pdl import exec_str
2 |
3 |
4 | def test_direct_object():
5 | prog_str = """
6 | object:
7 | a: 1
8 | b: hello
9 | c:
10 | text:
11 | - bye
12 | - "!"
13 | """
14 | result = exec_str(prog_str)
15 | assert result == {"a": 1, "b": "hello", "c": "bye!"}
16 |
17 |
18 | def test_composed_object():
19 | prog_str = """
20 | object:
21 | - object:
22 | a: 1
23 | b: hello
24 | - data:
25 | c: "bye!"
26 | """
27 | result = exec_str(prog_str)
28 | assert result == {"a": 1, "b": "hello", "c": "bye!"}
29 |
--------------------------------------------------------------------------------
/tests/test_parse.py:
--------------------------------------------------------------------------------
1 | from pdl.pdl import exec_dict
2 |
3 | regex_data = {
4 | "description": "Parsing using regex",
5 | "text": "Malcolm Reynolds",
6 | "parser": {
7 | "spec": {"first_name": "string", "last_name": "string"},
8 | "regex": "(?P\\w+) (?P\\w+)",
9 | },
10 | }
11 |
12 |
13 | def test_model():
14 | result = exec_dict(regex_data)
15 | assert result == {"first_name": "Malcolm", "last_name": "Reynolds"}
16 |
--------------------------------------------------------------------------------
/tests/test_role.py:
--------------------------------------------------------------------------------
1 | from pdl.pdl import exec_str
2 | from pdl.pdl_context import SerializeMode
3 |
4 |
5 | def test_role1():
6 | prog_str = """
7 | description: Test role
8 | text:
9 | - defs:
10 | ctx1: ${pdl_context}
11 | text: A
12 | role: A
13 | - Hi
14 | - defs:
15 | ctx2: ${pdl_context}
16 | text: B
17 | role: B
18 | role: Top
19 | """
20 | result = exec_str(prog_str, output="all")
21 | scope = result["scope"]
22 | assert result["result"] == "AHiB"
23 | assert scope["pdl_context"].serialize(SerializeMode.LITELLM) == [
24 | {"role": "A", "content": "A", "defsite": "text.0.text"},
25 | {"role": "Top", "content": "Hi", "defsite": "text.1"},
26 | {"role": "B", "content": "B", "defsite": "text.2.text"},
27 | ]
28 | assert scope["ctx1"].serialize(SerializeMode.LITELLM) == []
29 | assert scope["ctx2"].serialize(SerializeMode.LITELLM) == [
30 | {"role": "A", "content": "A", "defsite": "text.0.text"},
31 | {"role": "Top", "content": "Hi", "defsite": "text.1"},
32 | ]
33 |
--------------------------------------------------------------------------------
/tests/test_schema.py:
--------------------------------------------------------------------------------
1 | import json
2 | from pathlib import Path
3 |
4 | from pydantic.json_schema import models_json_schema
5 |
6 | import pdl.pdl
7 | from pdl.pdl_ast import PdlBlock, Program
8 |
9 |
10 | def test_saved_schema():
11 | top, current_schema = models_json_schema(
12 | [
13 | (Program, "validation"),
14 | (PdlBlock, "validation"),
15 | ],
16 | title="PDL Schemas",
17 | )
18 | current_schema["anyOf"] = list(top.values())
19 | pdl_schema_file = Path(pdl.pdl.__file__).parent / "pdl-schema.json"
20 | with open(pdl_schema_file, "r", encoding="utf-8") as fd:
21 | saved_schema = json.load(fd)
22 | assert current_schema == saved_schema
23 |
--------------------------------------------------------------------------------