Skip to content

Commit

Permalink
feat: generalization of plan/parse
Browse files Browse the repository at this point in the history
  • Loading branch information
kyr0 committed Jul 31, 2024
1 parent ed74cea commit 42cd57d
Show file tree
Hide file tree
Showing 13 changed files with 252 additions and 183 deletions.
Binary file modified bun.lockb
Binary file not shown.
7 changes: 1 addition & 6 deletions data/prompt-templates/graph/test.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ Generate a {% if max_chars < 1000 %}short{% endif %} fiction text of max. {% wor
EXAMPLES:
{{ examples }}

{% field FORMAT = "{ label: 'Format', default: 'Blog post' }" %}

--- AFTER write fiction ---
{% if prev_generation_chars > max_chars %}
{% goto shorten %}
Expand All @@ -30,12 +28,9 @@ Shorten the text following text to {% chars_to_words assign='{{ max_chars }}' %}

{{ prev_generation_text }}

{% field ASPECT = "{ label: 'Aspect', default: 'Foo' }" %}
{% field ASPECT2 = "{ label: 'Aspect2', default: 'Foo' }" %}

--- AFTER shorten ---
{% if prev_generation_chars > max_chars %}
{% goto shorten %} // FIXME: repeat!
{% goto shorten %}
{% else %}
{% done %}
{% endif %}
44 changes: 32 additions & 12 deletions examples/graph.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { plan } from "../src"
import { readFileSync } from "fs"
import prettyjson from "prettyjson"

const graphPrompt = readFileSync("data/prompt-templates/graph/test.liquid", "utf-8")

Expand All @@ -9,18 +10,37 @@ const result = await plan(graphPrompt, {
user_context: 'Foo bar',
}, {
tags: {
test: async(tagName, opts, values, instance) => {
console.log('test mocking for', opts.promptLabel)


inputMock: async(tagName, ctx, input, opts, instance) => {
console.log('input mocking for', ctx.prompt)
switch (ctx.prompt) {
case "write fiction":
ctx.input = {
...ctx.input,
LALA: 123
}
break;
}
},
chars_to_words: async(tagName, opts, values, instance) => {

console.log('tagName', tagName)
console.log('opts', opts)
console.log('values', values)
console.log('instance', instance)

return 'chars_to_words'

// provide test mode mock data for each prompt
mock: async(tagName, ctx, input, opts, instance) => {
console.log('test mocking for', ctx.prompt)
switch (ctx.prompt) {
case "write fiction":
ctx.output = {
...ctx.output,
CONTROL_FLOW_RESULT: "This is a really beautiful fictional story on how a developer saved the world from a bug by doing alot of coding, using LLMs, etc."
}
break;

case "shorten":
ctx.output = {
...ctx.output,
CONTROL_FLOW_RESULT: "Fictional Story: Developer saved the world from a bug."
}
break;
}
}
},
})
Expand All @@ -31,4 +51,4 @@ const result = await plan(graphPrompt, {
// runStep(index, { stream: true })
// runWorkflow({ stream: true })

console.log('result', result)
console.log(prettyjson.render(result))
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@biomejs/biome": "^1.6.4",
"dotenv": "^16.4.5",
"pkgroll": "^2.1.1",
"prettyjson": "^1.2.5",
"spawn-please": "^3.0.0",
"tsx": "^4.16.2",
"typescript": "^5.0.0",
Expand Down
53 changes: 34 additions & 19 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,6 @@ export type PromptInstruction = "PROMPT" | "AFTER";

export type FieldMap = Record<string, FieldParseResult>;

export type PromptStep = {
promptTemplate: string;
label?: string;
inputValues: StringMap;
outputValues: StringMap;
prompt: string;
error?: unknown;
instruction?: PromptInstruction;
};

export type PromptNodeType = "preamble" | "template";

export interface PromptNode {
Expand All @@ -38,41 +28,45 @@ export interface PromptNode {

export type PromptList = Array<PromptNode>;

export type LiquiPrompt = Array<PromptStep>;

export interface PromptContext {
promptLabel: string; // FIXME: prompt
inputValues: PromptInput; // FIXME: input
outputValues: StringMap; // FIXME: output
prompt: string;
input: PromptInput;
output: StringMap;
}

export type PromptExecutionMode = "plan" | "test" | "run";

export interface PromptOptions {
mode?: PromptExecutionMode;
tags?: TagRegistrationMap;
tags?: TagRegistrationMap<AsyncTagFn>;
syncTags?: TagRegistrationMap<SyncTagFn>;
}

export type TagRegisterFn = (
name: string,
ctx: PromptContext,
opts: PromptOptions,
tagFn: SyncTagFn | AsyncTagFn,
) => TagClass | TagImplOptions;

export type TagRegistrationMap = Record<string, TagFn>;
export type TagRegistrationMap<T> = Record<string, T>;

export interface DefaultTag {
hash: Hash;
fieldIndex: number;
}

export type TagFn = (
export type TagFn<T> = (
name: string,
ctx: PromptContext,
values: StringMap,
opts: PromptOptions,
instance: DefaultTag,
) => Promise<string> | Promise<void> | string | void;
) => T;

export type AsyncTagFn = TagFn<Promise<string> | Promise<void>>;
// biome-ignore lint/suspicious/noConfusingVoidType: necessary for tags with no return value
export type SyncTagFn = TagFn<string | void>;

export type ValueExpression = {
value?: string;
Expand All @@ -81,3 +75,24 @@ export type ValueExpression = {
};

export type TagHash = { [key: string]: string | boolean | number };

export interface PromptParsed {
name: string;
instruction?: string;
tpl: string;
input: StringMap;
output: StringMap;
prompt: string;
error?: string;
}

export type LiquiPrompt = Array<PromptParsed>;

export interface PlanModeResult {
prompts: Array<PromptParsed>;
errors: Array<string>;
/** output variables in "plan" mode aggregate (merge) all output variables of all steps that have been visited by the compiler,
* following each single prompt control flow given the initial input variables. This can be helpful for use-cases where custom tags
* add meta-data over variables used in prompts etc. (see "fields" example) */
output: StringMap;
}
Loading

0 comments on commit 42cd57d

Please sign in to comment.