Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for system prompts in runPrompt #622

Merged
merged 7 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
"millis",
"ollama",
"openai",
"promptdom",
"promptfoo",
"stringifying",
"sysr",
"treesitter",
"typecheck",
"vsix",
Expand Down
5 changes: 5 additions & 0 deletions docs/genaisrc/genaiscript.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions genaisrc/genaiscript.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion packages/core/src/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
CancellationToken,
checkCancelled,
} from "./cancellation"
import { assert, logError } from "./util"
import { assert, logError, logVerbose } from "./util"

Check failure on line 11 in packages/core/src/chat.ts

View workflow job for this annotation

GitHub Actions / build

Unused import 'logVerbose'. If it's not being used, it should be removed.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import 'logVerbose'. If it's not being used, it should be removed.

generated by pr-review-commit unused_import

import { extractFenced, findFirstDataFence } from "./fence"
import {
toStrictJSONSchema,
Expand Down Expand Up @@ -558,6 +558,7 @@
if (resp.variables)
genVars = { ...(genVars || {}), ...resp.variables }
} finally {
logVerbose("")
trace.endDetails()
}

Expand Down
44 changes: 24 additions & 20 deletions packages/core/src/expander.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@
} from "./chattypes"
import { promptParametersSchemaToJSONSchema } from "./parameters"

async function callExpander(
export async function callExpander(

Check failure on line 30 in packages/core/src/expander.ts

View workflow job for this annotation

GitHub Actions / build

The function 'callExpander' was changed from private to public. If this function is not intended to be used outside of this module, it should remain private.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The visibility of the function 'callExpander' has been changed from private to public. This could potentially expose internal logic and should be reviewed.

generated by pr-review-commit function_visibility_change

prj: Project,
r: PromptScript,
vars: ExpansionVariables,
trace: MarkdownTrace,
options: GenerationOptions
) {
assert(!!options.model)
const { provider, model } = parseModelIdentifier(r.model ?? options.model)
const ctx = await createPromptContext(vars, trace, options, model)
const ctx = await createPromptContext(prj, vars, trace, options, model)

let status: GenerationStatus = undefined
let statusText: string = undefined
Expand Down Expand Up @@ -190,7 +191,7 @@
normalizeInt(env.vars["maxToolCalls"]) ??
normalizeInt(env.vars["max_tool_calls"]) ??
template.maxToolCalls ??
MAX_TOOL_CALLS
MAX_TOOL_CALLS
let seed = options.seed ?? normalizeInt(env.vars["seed"]) ?? template.seed
if (seed !== undefined) seed = seed >> 0

Expand All @@ -206,7 +207,7 @@
trace.startDetails("🧬 prompt")
trace.detailsFenced("📓 script source", template.jsSource, "js")

const prompt = await callExpander(template, env, trace, options)
const prompt = await callExpander(prj, template, env, trace, options)

const images = prompt.images
const schemas = prompt.schemas
Expand All @@ -223,7 +224,11 @@

if (prompt.status !== "success" || prompt.text === "")
// cancelled
return { status: prompt.status, statusText: prompt.statusText, messages }
return {
status: prompt.status,
statusText: prompt.statusText,
messages,
}

if (cancellationToken?.isCancellationRequested)
return { status: "cancelled", statusText: "user cancelled", messages }
Expand All @@ -238,21 +243,17 @@

for (let i = 0; i < systems.length; ++i) {
if (cancellationToken?.isCancellationRequested)
return { status: "cancelled", statusText: "user cancelled", messages }

let systemTemplate = systems[i]
let system = prj.getTemplate(systemTemplate)
if (!system) {
if (systemTemplate) trace.error(`\`${systemTemplate}\` not found\n`)
if (i > 0) continue
systemTemplate = "system"
system = prj.getTemplate(systemTemplate)
assert(!!system)
}
return {
status: "cancelled",
statusText: "user cancelled",
messages,
}

trace.startDetails(`👾 ${systemTemplate}`)
const system = prj.getTemplate(systems[i])
if (!system) throw new Error(`system template ${systems[i]} not found`)

const sysr = await callExpander(system, env, trace, options)
trace.startDetails(`👾 ${system.id}`)
const sysr = await callExpander(prj, system, env, trace, options)

if (sysr.images) images.push(...sysr.images)
if (sysr.schemas) Object.assign(schemas, sysr.schemas)
Expand All @@ -272,12 +273,15 @@
trace.fence(sysr.aici, "yaml")
messages.push(sysr.aici)
}

trace.detailsFenced("js", system.jsSource, "js")
trace.endDetails()

if (sysr.status !== "success")
return { status: sysr.status, statusText: sysr.statusText, messages }
return {
status: sysr.status,
statusText: sysr.statusText,
messages,
}
}

const responseSchema = promptParametersSchemaToJSONSchema(
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/genaisrc/genaiscript.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

76 changes: 71 additions & 5 deletions packages/core/src/promptcontext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import { createParsers } from "./parsers"
import { readText } from "./fs"
import {
PromptImage,
PromptNode,
appendChild,
createFileMergeNode,
Expand All @@ -32,30 +33,42 @@
} from "./runpromptcontext"
import { CSVParse, CSVToMarkdown } from "./csv"
import { INIParse, INIStringify } from "./ini"
import { CancelError, isCancelError, serializeError } from "./error"
import {
CancelError,

Check failure on line 37 in packages/core/src/promptcontext.ts

View workflow job for this annotation

GitHub Actions / build

Unused import 'NotSupportedError'. If it's not being used, it should be removed.
isCancelError,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import 'ChatCompletionMessageParam'. If it's not being used, it should be removed.

generated by pr-review-commit unused_import

NotSupportedError,
serializeError,
} from "./error"
import { createFetch } from "./fetch"
import { XMLParse } from "./xml"
import { GenerationOptions } from "./generation"
import { fuzzSearch } from "./fuzzsearch"
import { parseModelIdentifier } from "./models"
import { renderAICI } from "./aici"
import { MODEL_PROVIDER_AICI } from "./constants"
import { MODEL_PROVIDER_AICI, SYSTEM_FENCE } from "./constants"
import { JSONLStringify, JSONLTryParse } from "./jsonl"
import { grepSearch } from "./grep"
import { resolveFileContents, toWorkspaceFile } from "./file"
import { vectorSearch } from "./vectorsearch"
import { ChatCompletionMessageParam } from "./chattypes"
import {
ChatCompletionMessageParam,
ChatCompletionSystemMessageParam,
} from "./chattypes"
import { resolveModelConnectionInfo } from "./models"
import { resolveLanguageModel } from "./lm"
import { callExpander } from "./expander"
import { Project } from "./ast"

export async function createPromptContext(
prj: Project,
vars: ExpansionVariables,
trace: MarkdownTrace,
options: GenerationOptions,
model: string
) {
const { cancellationToken, infoCb } = options || {}
const env = structuredClone(vars)
const { generator, ...varsNoGenerator } = vars
const env = { generator, ...structuredClone(varsNoGenerator) }
const parsers = await createParsers({ trace, model })
const YAML = Object.freeze<YAML>({
stringify: YAMLStringify,
Expand Down Expand Up @@ -246,7 +259,7 @@
},
runPrompt: async (generator, runOptions): Promise<RunPromptResult> => {
try {
const { label } = runOptions || {}
const { label, system = [] } = runOptions || {}
trace.startDetails(`🎁 run prompt ${label || ""}`)
infoCb?.({ text: `run prompt ${label || ""}` })

Expand All @@ -263,6 +276,7 @@
let tools: ToolCallback[] = undefined
let schemas: Record<string, JSONSchema> = undefined
let chatParticipants: ChatParticipant[] = undefined

// expand template
const { provider } = parseModelIdentifier(genOptions.model)
if (provider === MODEL_PROVIDER_AICI) {
Expand All @@ -289,17 +303,69 @@
throw new Error("errors while running prompt")
}

const systemMessage: ChatCompletionSystemMessageParam = {
role: "system",
content: "",
}
for (const systemId of system) {
checkCancelled(cancellationToken)

const system = prj.getTemplate(systemId)
if (!system)
throw new Error(`system template ${systemId} not found`)
trace.startDetails(`👾 ${system.id}`)
const sysr = await callExpander(
prj,
system,
env,
trace,
options
)
if (sysr.images?.length)
throw new NotSupportedError("images")
if (sysr.schemas) Object.assign(schemas, sysr.schemas)
if (sysr.functions) tools.push(...sysr.functions)
if (sysr.fileMerges?.length)
throw new NotSupportedError("fileMerges")
if (sysr.outputProcessors?.length)
throw new NotSupportedError("outputProcessors")
if (sysr.chatParticipants)
chatParticipants.push(...sysr.chatParticipants)
if (sysr.fileOutputs?.length)
throw new NotSupportedError("fileOutputs")
if (sysr.logs?.length)
trace.details("📝 console.log", sysr.logs)
if (sysr.text) {
systemMessage.content +=
SYSTEM_FENCE + "\n" + sysr.text + "\n"
trace.fence(sysr.text, "markdown")
}
if (sysr.aici) {
trace.fence(sysr.aici, "yaml")
messages.push(sysr.aici)
}
trace.detailsFenced("js", system.jsSource, "js")
trace.endDetails()
if (sysr.status !== "success")
throw new Error(
`system ${system.id} failed ${sysr.status} ${sysr.statusText}`
)
}
if (systemMessage.content) messages.unshift(systemMessage)

const connection = await resolveModelConnectionInfo(
genOptions,
{ trace, token: true }
)
checkCancelled(cancellationToken)
if (!connection.configuration)
throw new Error(
"model connection error " + connection.info?.model
)
const { completer } = await resolveLanguageModel(
connection.configuration.provider
)
checkCancelled(cancellationToken)
if (!completer)
throw new Error(
"model driver not found for " + connection.info
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/runpromptcontext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
import { MarkdownTrace } from "./trace"
import { GenerationOptions } from "./generation"
import { promptParametersSchemaToJSONSchema } from "./parameters"
import { isJSONSchema } from "./schema"
import { consoleLogFormat } from "./logging"
import { resolveFileDataUri } from "./file"
import { isGlobMatch } from "./glob"
Expand Down
14 changes: 8 additions & 6 deletions packages/core/src/systems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,24 @@ export function resolveSystems(prj: Project, template: PromptScript) {
const systems = Array.from(template.system ?? []).slice(0)

if (template.system === undefined) {
const useSchema = /defschema/i.test(jsSource)
const useSchema = /\Wdefschema\W/i.test(jsSource)
if (!template.responseType) {
systems.push("system")
systems.push("system.explanations")
}
// select file expansion type
if (/diff/i.test(jsSource)) systems.push("system.diff")
else if (/changelog/i.test(jsSource)) systems.push("system.changelog")
else if (/file/i.test(jsSource)) {
if (/\Wdiff\W/i.test(jsSource)) systems.push("system.diff")
else if (/\Wchangelog\W/i.test(jsSource))
systems.push("system.changelog")
else if (/\Wfile\W/i.test(jsSource)) {
systems.push("system.files")
if (useSchema) systems.push("system.files_schema")
}
if (useSchema) systems.push("system.schema")
if (/annotation|warning|error/i.test(jsSource))
if (/\W(annotation|warning|error)\W/i.test(jsSource))
systems.push("system.annotations")
if (/diagram|chart/i.test(jsSource)) systems.push("system.diagrams")
if (/\W(diagram|chart)\W/i.test(jsSource))
systems.push("system.diagrams")
}

if (template.tools?.length)
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/types/prompt_template.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,11 @@ interface PromptGeneratorOptions extends ModelOptions {
* Label for trace
*/
label?: string

/**
* List of system prompts if any
*/
system?: SystemPromptId[]
}

interface FileOutputOptions {
Expand Down
5 changes: 5 additions & 0 deletions packages/sample/genaisrc/genaiscript.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions packages/sample/genaisrc/node/genaiscript.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions packages/sample/genaisrc/python/genaiscript.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading