diff --git a/docs/genaisrc/genaiscript.d.ts b/docs/genaisrc/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/docs/genaisrc/genaiscript.d.ts +++ b/docs/genaisrc/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/docs/src/content/docs/reference/scripts/response-priming.md b/docs/src/content/docs/reference/scripts/response-priming.md index af9bd99a04..830857b71b 100644 --- a/docs/src/content/docs/reference/scripts/response-priming.md +++ b/docs/src/content/docs/reference/scripts/response-priming.md @@ -1,27 +1,26 @@ --- title: Response Priming sidebar: - order: 100 + order: 100 description: Learn how to prime LLM responses with specific syntax or format - using the writeText function in scripts. + using the writeText function in scripts. keywords: response priming, LLM syntax, script formatting, writeText function, - assistant message + assistant message genaiscript: - model: openai:gpt-3.5-turbo - + model: openai:gpt-3.5-turbo --- It is possible to provide the start of the LLM response (`assistant` message) in the script. This allows to steer the answer of the LLM to a specify syntax or format. -Use `writeText` with the `{assistant: true}` option to provide the assistant text. +Use `assistant` function to provide the assistant text. ```js $`List 5 colors. Answer with a JSON array. Do not emit the enclosing markdown.` // help the LLM by starting the JSON array syntax // in the assistant response -writeText(`[`, { assistant: true }) +assistant(`[`) ``` @@ -29,31 +28,24 @@ writeText(`[`, { assistant: true })
👤 user - ```markdown wrap List 5 colors. Answer with a JSON array. Do not emit the enclosing markdown. ``` -
-
🤖 assistant - ```markdown wrap [ ``` -
-
🤖 assistant - ```markdown wrap "red", "blue", @@ -63,13 +55,10 @@ List 5 colors. Answer with a JSON array. Do not emit the enclosing markdown. ] ``` -
- - ### How does it work? Internally when invoking the LLM, an additional message is added to the query as if the LLM had generated this content. diff --git a/docs/src/content/docs/reference/scripts/system.mdx b/docs/src/content/docs/reference/scripts/system.mdx index 1e053595bf..618bfdcfcc 100644 --- a/docs/src/content/docs/reference/scripts/system.mdx +++ b/docs/src/content/docs/reference/scripts/system.mdx @@ -1043,6 +1043,10 @@ defTool( enum: ["success", "failure"], description: "Filter runs by completion status", }, + count: { + type: "number", + description: "Number of runs to list. Default is 20.", + }, }, }, async (args) => { @@ -1053,6 +1057,7 @@ defTool( const res = await github.listWorkflowRuns(workflow_id, { branch, status, + count: 20, }) return CSV.stringify( res.map(({ id, name, conclusion, head_sha }) => ({ diff --git a/genaisrc/genaiscript.d.ts b/genaisrc/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/genaisrc/genaiscript.d.ts +++ b/genaisrc/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/auto/genaiscript.d.ts b/packages/auto/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/auto/genaiscript.d.ts +++ b/packages/auto/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/core/src/aici.ts b/packages/core/src/aici.ts index 03af250bc6..6eacf95e30 100644 --- a/packages/core/src/aici.ts +++ b/packages/core/src/aici.ts @@ -100,7 +100,7 @@ export async function renderAICI(functionName: string, root: PromptNode) { }, // Unsupported node types image: notSupported("image"), - function: notSupported("function"), + tool: notSupported("tool"), assistant: notSupported("assistant"), schema: notSupported("schema"), // Capture output processors diff --git a/packages/core/src/chat.ts b/packages/core/src/chat.ts index 8e18a97fc7..0d24d8ce94 100644 --- a/packages/core/src/chat.ts +++ b/packages/core/src/chat.ts @@ -8,14 +8,18 @@ import { CancellationToken, checkCancelled, } from "./cancellation" -import { assert, logError, logVerbose } from "./util" +import { assert, logError, logVerbose, logWarn } from "./util" import { extractFenced, findFirstDataFence, unfence } from "./fence" import { toStrictJSONSchema, validateFencesWithSchema, validateJSONWithSchema, } from "./schema" -import { MAX_DATA_REPAIRS, MAX_TOOL_CALLS } from "./constants" +import { + MAX_DATA_REPAIRS, + MAX_TOOL_CALLS, + MAX_TOOL_CONTENT_TOKENS, +} from "./constants" import { parseAnnotations } from "./annotations" import { errorMessage, isCancelError, serializeError } from "./error" import { estimateChatTokens } from "./chatencoder" @@ -40,6 +44,8 @@ import { import { promptParametersSchemaToJSONSchema } from "./parameters" import { fenceMD, prettifyMarkdown } from "./markdown" import { YAMLStringify } from "./yaml" +import { resolveTokenEncoder } from "./encoders" +import { estimateTokens, truncateTextToTokens } from "./tokens" export function toChatCompletionUserMessage( expanded: string, @@ -125,7 +131,8 @@ async function runToolCalls( options: GenerationOptions ) { const projFolder = host.projectFolder() - const { cancellationToken, trace } = options || {} + const { cancellationToken, trace, model } = options || {} + const encoder = await resolveTokenEncoder(model) assert(!!trace) let edits: Edits[] = [] @@ -189,6 +196,9 @@ async function runToolCalls( const toolResult: string[] = [] for (const todo of todos) { const { tool, args } = todo + const { + maxTokens: maxToolContentTokens = MAX_TOOL_CONTENT_TOKENS, + } = tool.spec const context: ToolCallContext = { log: (txt: string) => { logVerbose(txt) @@ -196,10 +206,18 @@ async function runToolCalls( }, trace, } - const output = await tool.impl({ context, ...args }) + + let output: ToolCallOutput + try { + output = await tool.impl({ context, ...args }) + } catch (e) { + logWarn(`tool: ${tool.spec.name} error`) + trace.error(`tool: ${tool.spec.name} error`, e) + output = serializeError(e) + } if (output === undefined || output === null) throw new Error( - `tool ${tool.spec.name} output is undefined` + `error: tool ${tool.spec.name} raised an error` ) let toolContent: string = undefined let toolEdits: Edits[] = undefined @@ -236,7 +254,6 @@ ${fenceMD(content, " ")} if (typeof output === "object") toolEdits = (output as ToolCallContent)?.edits - if (toolContent) trace.fence(toolContent, "markdown") if (toolEdits?.length) { trace.fence(toolEdits) edits.push( @@ -251,6 +268,18 @@ ${fenceMD(content, " ")} ) } + const toolContentTokens = estimateTokens(toolContent, encoder) + if (toolContentTokens > maxToolContentTokens) { + logWarn( + `tool: ${tool.spec.name} response too long (${toolContentTokens} tokens), truncating ${maxToolContentTokens} tokens` + ) + toolContent = truncateTextToTokens( + toolContent, + maxToolContentTokens, + encoder + ) + } + trace.fence(toolContent, "markdown") toolResult.push(toolContent) } messages.push({ @@ -558,7 +587,7 @@ export async function executeChatSession( responseType, responseSchema, infoCb, - stats + stats, } = genOptions traceLanguageModelConnection(trace, genOptions, connectionToken) const tools: ChatCompletionTool[] = toolDefinitions?.length diff --git a/packages/core/src/constants.ts b/packages/core/src/constants.ts index fb30ef2093..5c01663794 100644 --- a/packages/core/src/constants.ts +++ b/packages/core/src/constants.ts @@ -253,4 +253,5 @@ export const TOKEN_TRUNCATION_THRESHOLD = 128 export const GIT_IGNORE_GENAI = ".gitignore.genai" export const CLI_ENV_VAR_RX = /^genaiscript_var_/i -export const GIT_DIFF_MAX_TOKENS = 10000 +export const GIT_DIFF_MAX_TOKENS = 8000 +export const MAX_TOOL_CONTENT_TOKENS = 2000 diff --git a/packages/core/src/genaisrc/genaiscript.d.ts b/packages/core/src/genaisrc/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/core/src/genaisrc/genaiscript.d.ts +++ b/packages/core/src/genaisrc/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/core/src/genaisrc/system.github_actions.genai.mjs b/packages/core/src/genaisrc/system.github_actions.genai.mjs index be1608a692..7bd7add02c 100644 --- a/packages/core/src/genaisrc/system.github_actions.genai.mjs +++ b/packages/core/src/genaisrc/system.github_actions.genai.mjs @@ -41,6 +41,10 @@ defTool( enum: ["success", "failure"], description: "Filter runs by completion status", }, + count: { + type: "number", + description: "Number of runs to list. Default is 20.", + }, }, }, async (args) => { @@ -51,6 +55,7 @@ defTool( const res = await github.listWorkflowRuns(workflow_id, { branch, status, + count: 20, }) return CSV.stringify( res.map(({ id, name, conclusion, head_sha }) => ({ diff --git a/packages/core/src/git.ts b/packages/core/src/git.ts index da631b283c..39b34e5aba 100644 --- a/packages/core/src/git.ts +++ b/packages/core/src/git.ts @@ -13,7 +13,7 @@ import { readText } from "./fs" import { runtimeHost } from "./host" import { shellParse } from "./shell" import { arrayify } from "./util" -import { estimateTokens } from "./tokens" +import { estimateTokens, truncateTextToTokens } from "./tokens" import { resolveTokenEncoder } from "./encoders" /** @@ -281,7 +281,7 @@ export class GitClient implements Git { res = `## Diff Truncated diff to large (${tokens} tokens). Diff files individually for details. -${res.slice(0, maxTokensFullDiff * 3)} +${truncateTextToTokens(res, maxTokensFullDiff, encoder)} ... ## Files diff --git a/packages/core/src/pricing.json b/packages/core/src/pricing.json new file mode 100644 index 0000000000..9dbc3f9bda --- /dev/null +++ b/packages/core/src/pricing.json @@ -0,0 +1,166 @@ +{ + "openai:gpt-4o": { + "price_per_million_input_tokens": 2.5, + "price_per_million_output_tokens": 10 + }, + "openai:gpt-4o-2024-08-06": { + "price_per_million_input_tokens": 2.5, + "price_per_million_output_tokens": 10 + }, + "openai:gpt-4o-2024-05-13": { + "price_per_million_input_tokens": 5, + "price_per_million_output_tokens": 15 + }, + "openai:gpt-4o-mini": { + "price_per_million_input_tokens": 0.15, + "price_per_million_output_tokens": 0.6 + }, + "openai:gpt-4o-mini-2024-07-18": { + "price_per_million_input_tokens": 0.15, + "price_per_million_output_tokens": 0.6 + }, + "openai:o1-preview": { + "price_per_million_input_tokens": 15, + "price_per_million_output_tokens": 60 + }, + "openai:o1-preview-2024-09-12": { + "price_per_million_input_tokens": 15, + "price_per_million_output_tokens": 60 + }, + "openai:o1-mini": { + "price_per_million_input_tokens": 3, + "price_per_million_output_tokens": 12 + }, + "openai:o1-mini-2024-09-12": { + "price_per_million_input_tokens": 3, + "price_per_million_output_tokens": 12 + }, + "openai:text-embedding-3-small": { + "price_per_million_input_tokens": 0.02, + "price_per_million_output_tokens": null + }, + "openai:text-embedding-3-large": { + "price_per_million_input_tokens": 0.13, + "price_per_million_output_tokens": null + }, + "openai:ada v2": { + "price_per_million_input_tokens": 0.1, + "price_per_million_output_tokens": null + }, + "openai:gpt-4o-realtime-preview": { + "price_per_million_input_tokens": 5, + "price_per_million_output_tokens": 20 + }, + "openai:gpt-4o-realtime-preview-2024-10-01": { + "price_per_million_input_tokens": 5, + "price_per_million_output_tokens": 20 + }, + "openai:chatgpt-4o-latest": { + "price_per_million_input_tokens": 5, + "price_per_million_output_tokens": 15 + }, + "openai:gpt-4-turbo": { + "price_per_million_input_tokens": 10, + "price_per_million_output_tokens": 30 + }, + "openai:gpt-4-turbo-2024-04-09": { + "price_per_million_input_tokens": 10, + "price_per_million_output_tokens": 30 + }, + "openai:gpt-4": { + "price_per_million_input_tokens": 30, + "price_per_million_output_tokens": 60 + }, + "openai:gpt-4-32k": { + "price_per_million_input_tokens": 60, + "price_per_million_output_tokens": 120 + }, + "openai:gpt-4-0125-preview": { + "price_per_million_input_tokens": 10, + "price_per_million_output_tokens": 30 + }, + "openai:gpt-4-1106-preview": { + "price_per_million_input_tokens": 10, + "price_per_million_output_tokens": 30 + }, + "openai:gpt-4-vision-preview": { + "price_per_million_input_tokens": 10, + "price_per_million_output_tokens": 30 + }, + "openai:gpt-3.5-turbo-0125": { + "price_per_million_input_tokens": 0.5, + "price_per_million_output_tokens": 1.5 + }, + "openai:gpt-3.5-turbo-instruct": { + "price_per_million_input_tokens": 1.5, + "price_per_million_output_tokens": 2 + }, + "openai:gpt-3.5-turbo-1106": { + "price_per_million_input_tokens": 1, + "price_per_million_output_tokens": 2 + }, + "openai:gpt-3.5-turbo-0613": { + "price_per_million_input_tokens": 1.5, + "price_per_million_output_tokens": 2 + }, + "openai:gpt-3.5-turbo-16k-0613": { + "price_per_million_input_tokens": 3, + "price_per_million_output_tokens": 4 + }, + "openai:gpt-3.5-turbo-0301": { + "price_per_million_input_tokens": 1.5, + "price_per_million_output_tokens": 2 + }, + "openai:davinci-002": { + "price_per_million_input_tokens": 2, + "price_per_million_output_tokens": 2 + }, + "openai:babbage-002": { + "price_per_million_input_tokens": 0.4, + "price_per_million_output_tokens": 0.4 + }, + "azure:gpt-4o-2024-08-06 global deployment": { + "price_per_million_input_tokens": 2.5, + "price_per_million_output_tokens": 10 + }, + "azure:gpt-4o global deployment": { + "price_per_million_input_tokens": 5, + "price_per_million_output_tokens": 15 + }, + "azure:gpt-4o-mini global deployment": { + "price_per_million_input_tokens": 0.15, + "price_per_million_output_tokens": 0.6 + }, + "azure:gpt-3.5-turbo-0301": { + "price_per_million_input_tokens": 2, + "price_per_million_output_tokens": 2 + }, + "azure:gpt-3.5-turbo-0613": { + "price_per_million_input_tokens": 1.5, + "price_per_million_output_tokens": 2 + }, + "azure:gpt-3.5-turbo-0613 16k": { + "price_per_million_input_tokens": 3, + "price_per_million_output_tokens": 4 + }, + "azure:gpt-3.5-turbo-1106": { + "price_per_million_input_tokens": 1, + "price_per_million_output_tokens": 2 + }, + "azure:gpt-3.5-turbo-0125": { + "price_per_million_input_tokens": 0.5, + "price_per_million_output_tokens": 1.5 + }, + "azure:gpt-3.5-turbo-instruct": { + "price_per_million_input_tokens": 1.5, + "price_per_million_output_tokens": 2 + }, + "azure:gpt-4": { + "price_per_million_input_tokens": 30, + "price_per_million_output_tokens": 60 + }, + "azure:gpt-4 32k": { + "price_per_million_input_tokens": 60, + "price_per_million_output_tokens": 120 + } +} \ No newline at end of file diff --git a/packages/core/src/promptdom.ts b/packages/core/src/promptdom.ts index e212f85158..695a22729c 100644 --- a/packages/core/src/promptdom.ts +++ b/packages/core/src/promptdom.ts @@ -3,7 +3,7 @@ import { CSVToMarkdown, CSVTryParse } from "./csv" import { renderFileContent, resolveFileContent } from "./file" import { addLineNumbers } from "./liner" import { JSONSchemaStringifyToTypeScript } from "./schema" -import { estimateTokens } from "./tokens" +import { estimateTokens, truncateTextToTokens } from "./tokens" import { MarkdownTrace, TraceOptions } from "./trace" import { arrayify, assert, toStringList, trimNewlines } from "./util" import { YAMLStringify } from "./yaml" @@ -39,7 +39,7 @@ export interface PromptNode extends ContextExpansionOptions { | "text" | "image" | "schema" - | "function" + | "tool" | "fileMerge" | "outputProcessor" | "stringTemplate" @@ -127,8 +127,8 @@ export interface PromptSchemaNode extends PromptNode { } // Interface for a function node. -export interface PromptFunctionNode extends PromptNode { - type: "function" +export interface PromptToolNode extends PromptNode, DefToolOptions { + type: "tool" name: string // Function name description: string // Description of the function parameters: JSONSchema // Parameters for the function @@ -304,18 +304,20 @@ export function createSchemaNode( } // Function to create a function node. -export function createFunctionNode( +export function createToolNode( name: string, description: string, parameters: JSONSchema, - impl: ChatFunctionHandler -): PromptFunctionNode { + impl: ChatFunctionHandler, + options?: DefToolOptions +): PromptToolNode { assert(!!name) assert(!!description) assert(parameters !== undefined) assert(impl !== undefined) return { - type: "function", + ...(options || {}), + type: "tool", name, description: dedent(description), parameters, @@ -439,7 +441,7 @@ export interface PromptNodeVisitor { def?: (node: PromptDefNode) => Awaitable // Definition node visitor image?: (node: PromptImageNode) => Awaitable // Image node visitor schema?: (node: PromptSchemaNode) => Awaitable // Schema node visitor - function?: (node: PromptFunctionNode) => Awaitable // Function node visitor + tool?: (node: PromptToolNode) => Awaitable // Function node visitor fileMerge?: (node: PromptFileMergeNode) => Awaitable // File merge node visitor stringTemplate?: (node: PromptStringTemplateNode) => Awaitable // String template node visitor outputProcessor?: (node: PromptOutputProcessorNode) => Awaitable // Output processor node visitor @@ -465,8 +467,8 @@ export async function visitNode(node: PromptNode, visitor: PromptNodeVisitor) { case "schema": await visitor.schema?.(node as PromptSchemaNode) break - case "function": - await visitor.function?.(node as PromptFunctionNode) + case "tool": + await visitor.tool?.(node as PromptToolNode) break case "fileMerge": await visitor.fileMerge?.(node as PromptFileMergeNode) @@ -695,38 +697,6 @@ async function resolvePromptNode( return { errors: err } } -// Function to truncate text based on token limits. -function truncateText( - content: string, - maxTokens: number, - encoder: TokenEncoder, - options?: { - threshold?: number - } -): string { - const tokens = estimateTokens(content, encoder) - if (tokens <= maxTokens) return content - const { threshold = TOKEN_TRUNCATION_THRESHOLD } = options || {} - - let left = 0 - let right = content.length - let result = content - - while (Math.abs(left - right) > threshold) { - const mid = Math.floor((left + right) / 2) - const truncated = content.slice(0, mid) + MAX_TOKENS_ELLIPSE - const truncatedTokens = estimateTokens(truncated, encoder) - - if (truncatedTokens > maxTokens) { - right = mid - } else { - result = truncated - left = mid + 1 - } - } - return result -} - // Function to handle truncation of prompt nodes based on token limits. async function truncatePromptNode( model: string, @@ -750,7 +720,7 @@ async function truncatePromptNode( n.maxTokens !== undefined && n.tokens > n.maxTokens ) { - n.resolved = n.preview = truncateText( + n.resolved = n.preview = truncateTextToTokens( n.resolved, n.maxTokens, encoder @@ -770,7 +740,7 @@ async function truncatePromptNode( n.maxTokens !== undefined && n.tokens > n.maxTokens ) { - n.resolved.content = n.preview = truncateText( + n.resolved.content = n.preview = truncateTextToTokens( n.resolved.content, n.maxTokens, encoder @@ -917,7 +887,7 @@ export async function renderPromptNode( const images: PromptImage[] = [] const errors: unknown[] = [] const schemas: Record = {} - const functions: ToolCallback[] = [] + const tools: ToolCallback[] = [] const fileMerges: FileMergeHandler[] = [] const outputProcessors: PromptOutputProcessorHandler[] = [] const chatParticipants: ChatParticipant[] = [] @@ -1008,9 +978,9 @@ ${trimNewlines(schemaText)} format ) }, - function: (n) => { + tool: (n) => { const { name, description, parameters, impl: fn } = n - functions.push({ + tools.push({ spec: { name, description, parameters }, impl: fn, }) @@ -1066,7 +1036,7 @@ ${fods.map((fo) => ` ${fo.pattern}: ${fo.description}`)} assistantPrompt, images, schemas, - functions, + functions: tools, fileMerges, outputProcessors, chatParticipants, diff --git a/packages/core/src/prompty.ts b/packages/core/src/prompty.ts index daee26b4c5..4a69b736b8 100644 --- a/packages/core/src/prompty.ts +++ b/packages/core/src/prompty.ts @@ -173,7 +173,7 @@ export function promptyToGenAIScript(doc: PromptyDocument) { .map((msg) => { const { role, content } = msg if (role === "assistant") { - return `writeText(parsers.jinja(${JSON.stringify(content as string)}, env.vars), { assistant: true })` + return `assistant(parsers.jinja(${JSON.stringify(content as string)}, env.vars))` } else { if (typeof content === "string") return renderJinja(content) else if (Array.isArray(content)) diff --git a/packages/core/src/runpromptcontext.ts b/packages/core/src/runpromptcontext.ts index c701d53e57..170948220f 100644 --- a/packages/core/src/runpromptcontext.ts +++ b/packages/core/src/runpromptcontext.ts @@ -7,7 +7,7 @@ import { createDefDiff, createDef, createFileOutput, - createFunctionNode, + createToolNode, createImageNode, createImportTemplate, createSchemaNode, @@ -253,13 +253,13 @@ export function createChatGenerationContext( promptParametersSchemaToJSONSchema(parameters) appendChild( node, - createFunctionNode(name, description, parameterSchema, fn) + createToolNode(name, description, parameterSchema, fn) ) } else if ((name as ToolCallback | AgenticToolCallback).impl) { const tool = name as ToolCallback | AgenticToolCallback appendChild( node, - createFunctionNode( + createToolNode( tool.spec.name, tool.spec.description, tool.spec.parameters as any, @@ -271,7 +271,7 @@ export function createChatGenerationContext( for (const tool of tools) appendChild( node, - createFunctionNode( + createToolNode( tool.spec.name, tool.spec.description, tool.spec.parameters as any, diff --git a/packages/core/src/tokens.ts b/packages/core/src/tokens.ts index d48bff8f75..fb3bdf746a 100644 --- a/packages/core/src/tokens.ts +++ b/packages/core/src/tokens.ts @@ -1,5 +1,9 @@ // Importing constants and utility functions -import { ESTIMATE_TOKEN_OVERHEAD } from "./constants" +import { + ESTIMATE_TOKEN_OVERHEAD, + MAX_TOKENS_ELLIPSE, + TOKEN_TRUNCATION_THRESHOLD, +} from "./constants" import { logVerbose } from "./util" /** @@ -24,3 +28,35 @@ export function estimateTokens(text: string, encoder: TokenEncoder) { return (text.length >> 2) + ESTIMATE_TOKEN_OVERHEAD } } + +// Function to truncate text based on token limits. +export function truncateTextToTokens( + content: string, + maxTokens: number, + encoder: TokenEncoder, + options?: { + threshold?: number + } +): string { + const tokens = estimateTokens(content, encoder) + if (tokens <= maxTokens) return content + const { threshold = TOKEN_TRUNCATION_THRESHOLD } = options || {} + + let left = 0 + let right = content.length + let result = content + + while (Math.abs(left - right) > threshold) { + const mid = Math.floor((left + right) / 2) + const truncated = content.slice(0, mid) + MAX_TOKENS_ELLIPSE + const truncatedTokens = estimateTokens(truncated, encoder) + + if (truncatedTokens > maxTokens) { + right = mid + } else { + result = truncated + left = mid + 1 + } + } + return result +} diff --git a/packages/core/src/types/prompt_template.d.ts b/packages/core/src/types/prompt_template.d.ts index 73abf8e30d..bbb870997a 100644 --- a/packages/core/src/types/prompt_template.d.ts +++ b/packages/core/src/types/prompt_template.d.ts @@ -415,7 +415,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -438,6 +438,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -509,6 +511,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2002,6 +2005,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2013,7 +2023,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, diff --git a/packages/core/src/types/prompt_type.d.ts b/packages/core/src/types/prompt_type.d.ts index 117f0bd87a..f93410b154 100644 --- a/packages/core/src/types/prompt_type.d.ts +++ b/packages/core/src/types/prompt_type.d.ts @@ -40,6 +40,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -97,13 +105,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/core/src/usage.ts b/packages/core/src/usage.ts index 17d4b999d6..0a4654476e 100644 --- a/packages/core/src/usage.ts +++ b/packages/core/src/usage.ts @@ -5,8 +5,37 @@ import { } from "./chattypes" import { MarkdownTrace } from "./trace" import { logVerbose, logWarn } from "./util" +// import pricing.json and assert json +import pricings from "./pricing.json" // Interface to hold statistics related to the generation process + +export function estimateCost(model: string, usage: ChatCompletionUsage) { + const { completion_tokens, prompt_tokens } = usage + const cost = (pricings as any)[model] as { + price_per_million_input_tokens: number + price_per_million_output_tokens: number + input_cache_token_rebate?: number + } + if (!cost) return undefined + + const { + price_per_million_output_tokens, + price_per_million_input_tokens, + input_cache_token_rebate = 0.5, + } = cost + + const cached = usage.prompt_tokens_details?.cached_tokens ?? 0 + const input = + (prompt_tokens - cached) * price_per_million_input_tokens + + cached * cost.price_per_million_input_tokens * input_cache_token_rebate + const output = completion_tokens * price_per_million_output_tokens + return (input + output) / 1e6 +} + +export function renderCost(model: string, usage: ChatCompletionUsage) { + const cost = estimateCost(model, usage) + return cost !== undefined ? `$${cost.toFixed(3)}` : "" +} -// Interface to hold statistics related to the generation process export class GenerationStats { toolCalls = 0 // Number of tool invocations repairs = 0 // Number of repairs made @@ -38,6 +67,10 @@ export class GenerationStats { } } + cost() { + return estimateCost(this.model, this.usage) + } + createChild(model: string, label?: string) { const child = new GenerationStats(model, label) this.children.push(child) @@ -57,6 +90,8 @@ export class GenerationStats { trace.itemValue("prompt", this.usage.prompt_tokens) trace.itemValue("completion", this.usage.completion_tokens) trace.itemValue("tokens", this.usage.total_tokens) + const cost = renderCost(this.model, this.usage) + if (cost) trace.itemValue("cost", cost) if (this.toolCalls) trace.itemValue("tool calls", this.toolCalls) if (this.repairs) trace.itemValue("repairs", this.repairs) if (this.turns) trace.itemValue("turns", this.turns) @@ -88,13 +123,13 @@ export class GenerationStats { private logTokens(indent: string) { if (this.model || this.usage.total_tokens) { logVerbose( - `${indent}${this.label ? `${this.label} (${this.model})` : this.model}> ${this.usage.total_tokens} tokens (${this.usage.prompt_tokens}-${this.usage.prompt_tokens_details.cached_tokens} -> ${this.usage.completion_tokens})` + `${indent}${this.label ? `${this.label} (${this.model})` : this.model}> ${this.usage.total_tokens} tokens (${this.usage.prompt_tokens}-${this.usage.prompt_tokens_details.cached_tokens} -> ${this.usage.completion_tokens}) ${renderCost(this.model, this.usage)}` ) } if (this.chatTurns.length > 1) for (const { messages, usage } of this.chatTurns) { logVerbose( - `${indent} ${messages.length} messages, ${usage.total_tokens} tokens` + `${indent} ${messages.length} messages, ${usage.total_tokens} tokens ${renderCost(this.model, usage)}` ) } for (const child of this.children) child.logTokens(indent + " ") diff --git a/packages/sample/genaisrc/assistant.genai.mjs b/packages/sample/genaisrc/assistant.genai.mjs new file mode 100644 index 0000000000..16f595916c --- /dev/null +++ b/packages/sample/genaisrc/assistant.genai.mjs @@ -0,0 +1,8 @@ +script({ + model: "openai:gpt-4o-mini", + tests: { + keywords: ["hello", "world"], + }, +}) +$`Say something.` +assistant("Hello, world!") diff --git a/packages/sample/genaisrc/blog/genaiscript.d.ts b/packages/sample/genaisrc/blog/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/sample/genaisrc/blog/genaiscript.d.ts +++ b/packages/sample/genaisrc/blog/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/sample/genaisrc/broken-tools.genai.mts b/packages/sample/genaisrc/broken-tools.genai.mts index e69de29bb2..2363a85fa6 100644 --- a/packages/sample/genaisrc/broken-tools.genai.mts +++ b/packages/sample/genaisrc/broken-tools.genai.mts @@ -0,0 +1,23 @@ +script({ + title: "stress testing tools", +}) + +$`Check the current time and weather and give a report to the user.` + +// this one always throws +defTool("weather", "Get the current weather", {}, async () => { + throw new Error("This tool throws an exception") +}) + +// massive return +defTool( + "time", + "Get the curren time", + {}, + async () => { + const crypto = await import("crypto") + const randomString = crypto.randomBytes(1024 * 1024).toString("base64") + return randomString + }, + { maxTokens: 2000 } +) diff --git a/packages/sample/genaisrc/cityinfo.genai.js b/packages/sample/genaisrc/cityinfo.genai.js index 4202f4851c..884e20f3ec 100644 --- a/packages/sample/genaisrc/cityinfo.genai.js +++ b/packages/sample/genaisrc/cityinfo.genai.js @@ -10,11 +10,17 @@ const schema = defSchema("CITY_SCHEMA", { description: "A city with population and elevation information.", properties: { name: { type: "string", description: "The name of the city." }, - population: { type: "number", description: "The population of the city." }, - url: { type: "string", description: "The URL of the city's Wikipedia page." } + population: { + type: "number", + description: "The population of the city.", + }, + url: { + type: "string", + description: "The URL of the city's Wikipedia page.", + }, }, - required: ["name", "population", "url"] - } + required: ["name", "population", "url"], + }, }) // the task` @@ -23,4 +29,4 @@ compliant with ${schema}.` $` Do not emit the enclosing markdown.` // help the LLM by starting the JSON array syntax -writeText(`[`, { assistant: true }) \ No newline at end of file +assistant(`[`) diff --git a/packages/sample/genaisrc/genaiscript.d.ts b/packages/sample/genaisrc/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/sample/genaisrc/genaiscript.d.ts +++ b/packages/sample/genaisrc/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/sample/genaisrc/node/genaiscript.d.ts b/packages/sample/genaisrc/node/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/sample/genaisrc/node/genaiscript.d.ts +++ b/packages/sample/genaisrc/node/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/sample/genaisrc/oai-pricing.genai.mts b/packages/sample/genaisrc/oai-pricing.genai.mts new file mode 100644 index 0000000000..e11bcdb86c --- /dev/null +++ b/packages/sample/genaisrc/oai-pricing.genai.mts @@ -0,0 +1,62 @@ +const urls = { + openai: { + url: "https://openai.com/api/pricing/", + text: "Skip to main content\nResearch\nProducts\nSafety\nCompany\nPricing | OpenAI\nPricing\nShow prices per 1K tokens\nPricing\n\nSimple and flexible. Only pay for what you use.\n\nContact sales\nLatest models\n\nMultiple models, each with different capabilities and price points. Prices can be viewed in units of either per 1M or 1K tokens. You can think of tokens as pieces of words, where 1,000 tokens is about 750 words.\n\nLanguage models are also available in the Batch API\n(opens in a new window)\n that returns completions within 24 hours for a 50% discount.\n\nGPT-4o\n\nGPT-4o is our most advanced multimodal model that’s faster and cheaper than GPT-4 Turbo with stronger vision capabilities. The model has 128K context and an October 2023 knowledge cutoff.\n\nLearn about GPT-4o\n(opens in a new window)\nModel\nPricing\nPricing with Batch API*\ngpt-4o\n$2.50 / 1M input tokens\n$1.25 / 1M input tokens\n$1.25 / 1M cached** input tokens\n$10.00 / 1M output tokens\n$5.00 / 1M output tokens\ngpt-4o-2024-08-06\n$2.50 / 1M input tokens\n$1.25 / 1M input tokens\n$1.25 / 1M cached** input tokens\n$10.00 / 1M output tokens\n$5.00 / 1M output tokens\ngpt-4o-2024-05-13\n$5.00 / 1M input tokens\n$2.50 / 1M input tokens\n$15.00 / 1M output tokens\n$7.50 / 1M output tokens\nVision pricing calculator\nSet model\ngpt-4o-2024-08-06\ngpt-4o-2024-05-13\ngpt-4o\nchatgpt-4o-latest\nSet width\npx\nby\nSet height\npx\n=\n$0.000638\nLow resolution\nPrice per 1M tokens (fixed)\t$2.50\n512 x 512 tiles\t1 × 1\nTotal tiles\t1\nBase tokens\t85\nTile tokens\t170 × 1 = 170\nTotal tokens\t255\nTotal price\t$0.000638\n\n*Batch API pricing requires requests to be submitted as a batch. Responses will be returned within 24 hours for a 50% discount. Learn more about Batch API ↗\n(opens in a new window)\n‎\n\n‎\n\n**Cached prompts are offered at a 50% discount compared to uncached prompts. Learn more about Prompt Caching ↗\n(opens in a new window)\n\n\n\nGPT-4o mini\n\nGPT-4o mini is our most cost-efficient small model that’s smarter and cheaper than GPT-3.5 Turbo, and has vision capabilities. The model has 128K context and an October 2023 knowledge cutoff.\n\nLearn about GPT-4o mini\n(opens in a new window)\nModel\nPricing\nPricing with Batch API*\ngpt-4o-mini\n$0.150 / 1M input tokens\n$0.075 / 1M input tokens\n$0.075 / 1M cached** input tokens\n$0.600 / 1M output tokens\n$0.300 / 1M output tokens\ngpt-4o-mini-2024-07-18\n$0.150 / 1M input tokens\n$0.075 / 1M input tokens\n$0.075 / 1M cached** input tokens\n$0.600 / 1M output tokens\n$0.300 / 1M output tokens\nVision pricing calculator\nSet width\npx\nby\nSet height\npx\n=\n$0.001275\nLow resolution\nPrice per 1M tokens (fixed)\t$0.15\n512 x 512 tiles\t1 × 1\nTotal tiles\t1\nBase tokens\t2833\nTile tokens\t5667 × 1 = 5667\nTotal tokens\t8500\nTotal price\t$0.001275\n\n*Batch API pricing requires requests to be submitted as a batch. Responses will be returned within 24 hours for a 50% discount. Learn more about Batch API ↗\n(opens in a new window)\n‎\n\n‎\n\n**Cached prompts are offered at a 50% discount compared to uncached prompts. Learn more about Prompt Caching ↗\n(opens in a new window)\n\n\n\nOpenAI o1-preview\n\no1-preview is our new reasoning model for complex tasks. The model has 128K context and an October 2023 knowledge cutoff.\n\nLearn about o1-preview\nModel\nPricing\no1-preview\n$15.00 / 1M input tokens\n$7.50 / 1M cached* input tokens\n$60.00 / 1M output** tokens\no1-preview-2024-09-12\n$15.00 / 1M input tokens\n$7.50 / 1M cached* input tokens\n$60.00 / 1M output** tokens\n\n*Output tokens include internal reasoning tokens generated by the model that are not visible in API responses.\n\nOpenAI o1-mini\n\no1-mini is a fast, cost-efficient reasoning model tailored to coding, math, and science use cases. The model has 128K context and an October 2023 knowledge cutoff.\n\nLearn about o1-mini\nModel\nPricing\no1-mini\n$3.00 / 1M input tokens\n$1.50 / 1M cached* input tokens\n$12.00 / 1M output* tokens\no1-mini-2024-09-12\n$3.00 / 1M input tokens\n$1.50 / 1M cached* input tokens\n$12.00 / 1M output* tokens\n\n*Output tokens include internal reasoning tokens generated by the model that are not visible in API responses.\n\n\nEmbedding models\n\nBuild advanced search, clustering, topic modeling, and classification functionality with our embeddings offering.\n\nLearn about embeddings\n(opens in a new window)\nModel\nPricing\nPricing with Batch API*\ntext-embedding-3-small\n$0.020 / 1M tokens\n$0.010 / 1M tokens\ntext-embedding-3-large\n$0.130 / 1M tokens\n$0.065 / 1M tokens\nada v2\n$0.100 / 1M tokens\n$0.050 / 1M tokens\n\n*Batch API pricing requires requests to be submitted as a batch. Responses will be returned within 24 hours for a 50% discount. Learn more about Batch API ↗\n(opens in a new window)\n\nFine-tuning models\n\nCreate your own custom models by fine-tuning our base models with your training data. Once you fine-tune a model, you’ll be billed only for the tokens you use in requests to that model.\n\nLearn about fine-tuning\n(opens in a new window)\nModel\nPricing\nPricing with Batch API*\ngpt-4o-2024-08-06**\n$3.750 / 1M input tokens\n$1.875 / 1M input tokens\n$15.000 / 1M output tokens\n$7.500 / 1M output tokens\n$25.000 / 1M training tokens\ngpt-4o-mini-2024-07-18**\n$0.300 / 1M input tokens\n$0.150 / 1M input tokens\n$1.200 / 1M output tokens\n$0.600 / 1M output tokens\n$3.000 / 1M training tokens\ngpt-3.5-turbo\n$3.000 / 1M input tokens\n$1.500 / 1M input tokens\n$6.000 / 1M output tokens\n$3.000 / 1M output tokens\n$8.000 / 1M training tokens\ndavinci-002\n$12.000 / 1M input tokens\n$6.000 / 1M input tokens\n$12.000 / 1M output tokens\n$6.000 / 1M output tokens\n$6.000 / 1M training tokens\nbabbage-002\n$1.600 / 1M input tokens\n$0.800 / 1M input tokens\n$1.600 / 1M output tokens\n$0.800 / 1M output tokens\n$0.400 / 1M training tokens\n\n*Batch API pricing requires requests to be submitted as a batch. Responses will be returned within 24 hours for a 50% discount. Learn more about Batch API ↗\n(opens in a new window)\n\n‎\n\n**Fine-tuning for GPT-4o and GPT-4o mini is free up to a daily token limit through October 31, 2024. For GPT-4o, each qualifying org gets up to 1M complimentary training tokens daily and any overage will be charged at the normal rate of $25.00/1M tokens. For GPT-4o mini, each qualifying org gets up to 2M complimentary training tokens daily and any overage will be charged at the normal rate of $3.00/1M tokens.\n\n\nRealtime API\n\nThe Realtime API lets developers build low-latency, multimodal experiences, including speech-to-speech capabilities. Text and audio processed by the Realtime API are priced separately.\n\nLearn about Realtime API\n(opens in a new window)\nPricing\ngpt-4o-realtime-preview\nText\n$5.00 / 1M input tokens\n$20.00 / 1M output tokens\nAudio*\n$100.00 / 1M input tokens\n$200.00 / 1M output tokens\ngpt-4o-realtime-preview-2024-10-01\nText\n$5.00 / 1M input tokens\n$20.00 / 1M output tokens\nAudio*\n$100.00 / 1M input tokens\n$200.00 / 1M output tokens\n\n*Audio input costs approximately 6¢ per minute; Audio output costs approximately 24¢ per minute\n\nAssistants API\n\nThe Assistants API and its tools make it easy for developers to build AI assistants in their applications. The tokens used for the Assistant API are billed at the chosen language model's per-token input / output rates.\n\nLearn about Assistants API\n(opens in a new window)\n\nAdditionally, we charge the following fees for tool usage:\n\nTool\nInput\nCode Interpreter\n$0.03 / session\nFile Search\n$0.10 / GB of vector-storage per day (1 GB free)\n\nGB refers to binary gigabytes (also known as gibibyte), where 1 GB is 2^30 bytes.\n\nImage models\n\nBuild DALL·E directly into your apps to generate and edit novel images and art. DALL·E 3 is the highest quality model and DALL·E 2 is optimized for lower cost.\n\nLearn about image generation\n(opens in a new window)\nModel\nQuality\nResolution\nPrice\nDALL·E 3\nStandard\n1024×1024\n$0.040 / image\nStandard\n1024×1792, 1792×1024\n$0.080 / image\nDALL·E 3\nHD\n1024×1024\n$0.080 / image\nHD\n1024×1792, 1792×1024\n$0.120 / image\nDALL·E 2\n1024×1024\n$0.020 / image\n512×512\n$0.018 / image\n256×256\n$0.016 / image\nAudio models\n\nWhisper can transcribe speech into text and translate many languages into English.\n\nText-to-speech (TTS) can convert text into spoken audio.\n\nLearn about Whisper\n(opens in a new window)\nLearn about Text-to-speech (TTS) \n(opens in a new window)\nModel\nUsage\nWhisper\n$0.006 / minute (rounded to the nearest second)\nTTS\n$15.000 / 1M characters\nTTS HD\n$30.000 / 1M characters\nOther Models\n\nWhile we continuously improve our latest models, here is a list of other models that we support.\n\nModel\nInput\nOutput\nchatgpt-4o-latest\n$5.00 / 1M tokens\n$15.00 / 1M tokens\ngpt-4-turbo\n$10.00 / 1M tokens\n$30.00 / 1M tokens\ngpt-4-turbo-2024-04-09\n$10.00 / 1M tokens\n$30.00 / 1M tokens\ngpt-4\n$30.00 / 1M tokens\n$60.00 / 1M tokens\ngpt-4-32k\n$60.00 / 1M tokens\n$120.00 / 1M tokens\ngpt-4-0125-preview\n$10.00 / 1M tokens\n$30.00 / 1M tokens\ngpt-4-1106-preview\n$10.00 / 1M tokens\n$30.00 / 1M tokens\ngpt-4-vision-preview\n$10.00 / 1M tokens\n$30.00 / 1M tokens\ngpt-3.5-turbo-0125\n$0.50 / 1M tokens\n$1.50 / 1M tokens\ngpt-3.5-turbo-instruct\n$1.50 / 1M tokens\n$2.00 / 1M tokens\ngpt-3.5-turbo-1106\n$1.00 / 1M tokens\n$2.00 / 1M tokens\ngpt-3.5-turbo-0613\n$1.50 / 1M tokens\n$2.00 / 1M tokens\ngpt-3.5-turbo-16k-0613\n$3.00 / 1M tokens\n$4.00 / 1M tokens\ngpt-3.5-turbo-0301\n$1.50 / 1M tokens\n$2.00 / 1M tokens\ndavinci-002\n$2.00 / 1M tokens\n$2.00 / 1M tokens\nbabbage-002\n$0.40 / 1M tokens\n$0.40 / 1M tokens\nSave 50% with Batch API\nFAQ\nWhat’s a token?\n\nYou can think of tokens as pieces of words used for natural language processing. For English text, 1 token is approximately 4 characters or 0.75 words. As a point of reference, the collected works of Shakespeare are about 900,000 words or 1.2M tokens.\n\nTo learn more about how tokens work and estimate your usage…\n\nExperiment with our interactive Tokenizer tool\n(opens in a new window)\n.\n\nLog in to your account and enter text into the Playground. The counter in the footer will display how many tokens are in your text.\n\nWhich model should I use?\n\nWe generally recommend that developers use either GPT-4o or GPT-4o mini, depending on the complexity of your tasks. GPT-4o generally performs better on a wide range of tasks, while GPT-4o mini is fast and inexpensive for simpler tasks. We recommend experimenting with these models in Playground\n(opens in a new window)\n to investigate which models provide the best price performance trade-off for your usage.\n\nHow will I know how many tokens I’ve used each month?\n\nLog in to your account to view your usage tracking dashboard\n(opens in a new window)\n. This page will show you how many tokens you’ve used during the current and past billing cycles.\n\nHow can I manage my spending?\n\nYou can set a monthly budget in your billing settings\n(opens in a new window)\n, after which we’ll stop serving your requests. There may be a delay in enforcing the limit, and you are responsible for any overage incurred. You can also configure an email notification threshold to receive an email alert once you cross that threshold each month. We recommend checking your usage tracking dashboard\n(opens in a new window)\n regularly to monitor your spend.\n\nFor customers managing work with Projects, you can set and manage billing restrictions per project\n(opens in a new window)\n in the Dashboard.\n\nIs the ChatGPT API included in the ChatGPT Plus, Teams, or Enterprise subscription?\n\nNo, OpenAI APIs are billed separately from ChatGPT Plus, Teams, and Enterprise. The API has its own pricing, which can be found at openai.com/pricing. ChatGPT subscription pricing can be found at openai.com/chatgpt/pricing/.\n\nDoes Playground usage count against my quota?\n\nYes, we treat Playground usage the same as regular API usage.\n\nHow is pricing calculated for Completions?\n\nChat completion\n(opens in a new window)\n requests are billed based on the number of input tokens sent plus the number of tokens in the output(s) returned by the API.\n\nYour request may use up to num_tokens(input) + [max_tokens * max(n, best_of)] tokens, which will be billed at the per-engine rates outlined at the top of this page.\n\nIn the simplest case, if your prompt contains 1500 tokens and you request a single 500 token completion from the gpt-4o-2024-05-13 API, your request will use 2000 tokens and will cost [(1500 * 5.00) + (500 * 15.00)] / 1000000 = $0.015.\n\nYou can limit costs by reducing prompt length or maximum response length, limiting usage of best_of/n , adding appropriate stop sequences, or using engines with lower per-token costs.\n\nHow is pricing calculated for Fine-tuning?\n\nThere are two components to fine-tuning pricing: training and usage.\n\nWhen training a fine-tuned model, the total tokens used will be billed according to our training rates. Note that the number of training tokens depends on the number of tokens in your training dataset and your chosen number of training epochs\n(opens in a new window)\n. The default number of epochs is 4.\n\n(Tokens in your training file * Number of training epochs) = Total training tokens\n\n\nOnce you fine-tune a model, you’ll be billed only for the tokens you use. Requests sent to fine-tuned models are billed at our usage rates.\n\nWhich models support vision capabilities and how is pricing calculated?\n\nThe following models support vision:\n\ngpt-4o\n\ngpt-4o-2024-08-06\n\ngpt-4o-2024-05-13\n\ngpt-4o-mini\n\ngpt-4o-mini-2024-07-18\n\ngpt-4-2024-04-09\n\ngpt-4-turbo\n\ngpt-4-vision-preview\n\ngpt-4-1106-vision-preview\n\nImages are converted into tokens with the specific number of tokens depending on the model used.\n\nIs there an SLA on the various models?\n\nYou can visit our Status page to monitor service availability and view historical uptime. If your company or application has specific requirements, please contact our sales team.\n\nStart creating with OpenAI’s powerful models.\nGet started\nContact sales\nOur research\nOverview\nIndex\nLatest advancements\nOpenAI o1\nGPT-4\nGPT-4o mini\nDALL·E 3\nSora\nChatGPT\nFor Everyone\nFor Teams\nFor Enterprises\nChatGPT login\n(opens in a new window)\nDownload\nAPI\nPlatform overview\nPricing\nDocumentation\n(opens in a new window)\nAPI login\n(opens in a new window)\nExplore more\nOpenAI for business\nStories\nSafety overview\nSafety overview\nCompany\nAbout us\nNews\nOur Charter\nSecurity\nResidency\nCareers\nTerms & policies\nTerms of use\nPrivacy policy\nBrand guidelines\nOther policies\nOpenAI © 2015–2024\nManage Cookies\n(opens in a new window)\n(opens in a new window)\n(opens in a new window)\n(opens in a new window)\n(opens in a new window)\n(opens in a new window)\n(opens in a new window)", + }, + azure: { + text: "", + url: "https://azure.microsoft.com/en-us/pricing/details/cognitive-services/openai-service/?msockid=33924d01e79d60ae3abd59eee6276132", + }, +} +function delay(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)) +} +let rows = [] +for (const [provider, { url, text }] of Object.entries(urls)) { + console.log(url) + let md = text + if (!md) { + const page = await host.browse(url, {}) + await delay(1000) + const html = await page.content() + const tables = await HTML.convertTablesToJSON(html, { + useFirstRowForHeadings: true, + }) + md = tables?.length + ? YAML.stringify(tables) + : await HTML.convertToMarkdown(html) + } + + const res = await prompt`Extract the LLM model pricing (in $) from the page + and export the result in CSV with model,price_per_million_input_tokens,price_per_million_output_tokens. + + - ignore regional pricing + + PRICING: + ${md}` + + const csv = await parsers.CSV(res.fences[0]?.content ?? res.text) + rows.push(...csv.map((row) => ({ provider, ...row }))) +} + +const norm = (p) => parseFloat(p.replace(/[$,]/g, "")) +// normalize +rows = rows.filter(({ model }) => !/regional/i.test(model)) +for (const row of rows) { + row.model = row.model.toLowerCase() + row.price_per_million_input_tokens = norm( + row.price_per_million_input_tokens + ) + row.price_per_million_output_tokens = norm( + row.price_per_million_output_tokens + ) +} +// turn rows into a map where key is provider:model and the value is the rest of the fields +const pricing = Object.fromEntries( + rows.map(({ provider, model, ...rest }) => [`${provider}:${model}`, rest]) +) + +await workspace.writeText( + `packages/core/src/pricing.json`, + JSON.stringify(pricing, null, 2) +) diff --git a/packages/sample/genaisrc/python/genaiscript.d.ts b/packages/sample/genaisrc/python/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/sample/genaisrc/python/genaiscript.d.ts +++ b/packages/sample/genaisrc/python/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/sample/genaisrc/style/genaiscript.d.ts b/packages/sample/genaisrc/style/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/sample/genaisrc/style/genaiscript.d.ts +++ b/packages/sample/genaisrc/style/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/sample/src/aici/genaiscript.d.ts b/packages/sample/src/aici/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/sample/src/aici/genaiscript.d.ts +++ b/packages/sample/src/aici/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/sample/src/errors/genaiscript.d.ts b/packages/sample/src/errors/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/sample/src/errors/genaiscript.d.ts +++ b/packages/sample/src/errors/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/sample/src/genaiscript.d.ts b/packages/sample/src/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/sample/src/genaiscript.d.ts +++ b/packages/sample/src/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/sample/src/makecode/genaiscript.d.ts b/packages/sample/src/makecode/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/sample/src/makecode/genaiscript.d.ts +++ b/packages/sample/src/makecode/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/sample/src/tla/genaiscript.d.ts b/packages/sample/src/tla/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/sample/src/tla/genaiscript.d.ts +++ b/packages/sample/src/tla/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/sample/src/vision/genaiscript.d.ts b/packages/sample/src/vision/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/sample/src/vision/genaiscript.d.ts +++ b/packages/sample/src/vision/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/packages/vscode/genaisrc/genaiscript.d.ts b/packages/vscode/genaisrc/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/packages/vscode/genaisrc/genaiscript.d.ts +++ b/packages/vscode/genaisrc/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /** diff --git a/slides/genaisrc/genaiscript.d.ts b/slides/genaisrc/genaiscript.d.ts index e11a3edd76..4e1671153e 100644 --- a/slides/genaisrc/genaiscript.d.ts +++ b/slides/genaisrc/genaiscript.d.ts @@ -489,7 +489,7 @@ interface WorkspaceFileWithScore extends WorkspaceFile { score?: number } -interface ToolDefinition { +interface ToolDefinition extends DefToolOptions { /** * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain * underscores and dashes, with a maximum length of 64. @@ -512,6 +512,8 @@ interface ToolDefinition { * Omitting `parameters` defines a function with an empty parameter list. */ parameters?: JSONSchema + + } interface ToolCallTrace { @@ -583,6 +585,7 @@ type ToolCallOutput = | ShellOutput | WorkspaceFile | RunPromptResult + | SerializedError | undefined interface WorkspaceFileCache { @@ -2076,6 +2079,13 @@ interface RunPromptResultPromiseWithOptions extends Promise { options(values?: PromptGeneratorOptions): RunPromptResultPromiseWithOptions } +interface DefToolOptions { + /** + * Maximum number of tokens per tool content response + */ + maxTokens?: number +} + interface ChatGenerationContext extends ChatTurnGenerationContext { defSchema( name: string, @@ -2087,7 +2097,8 @@ interface ChatGenerationContext extends ChatTurnGenerationContext { options?: DefImagesOptions ): void defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void defTool( name: string, @@ -2940,6 +2951,14 @@ declare function writeText( options?: WriteTextOptions ): void +/** + * Append given string to the prompt as an assistant mesage. + */ +declare function assistant( + text: Awaitable, + options?: Omit +): void + /** * Append given string to the prompt. It automatically appends "\n". * `` $`foo` `` is the same as `text("foo")`. @@ -2997,13 +3016,15 @@ declare function defFileOutput( * @param fn callback invoked when the LLM requests to run this function */ declare function defTool( - tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback + tool: ToolCallback | AgenticToolCallback | AgenticToolProviderCallback, + options?: DefToolOptions ): void declare function defTool( name: string, description: string, parameters: PromptParametersSchema | JSONSchema, - fn: ChatFunctionHandler + fn: ChatFunctionHandler, + options?: DefToolOptions ): void /**