| /** | |
| * Defines prompts sent to AI language models. | |
| * | |
| * A prompt is an ordered list of messages. Messages can use roles such as | |
| * system, user, assistant, and tool, and their content can be split into typed | |
| * parts such as text, files, reasoning, tool calls, tool results, and approval | |
| * messages. This module helps build prompts, combine them, and convert raw | |
| * input or response parts into the shared prompt shape. | |
| * | |
| * @since 4.0.0 | |
| */ | |
| import * as Arr from "../../Array.js"; | |
| import * as Effect from "../../Effect.js"; | |
| import { dual } from "../../Function.js"; | |
| import * as Option from "../../Option.js"; | |
| import { pipeArguments } from "../../Pipeable.js"; | |
| import * as Predicate from "../../Predicate.js"; | |
| import * as Schema from "../../Schema.js"; | |
| import * as SchemaIssue from "../../SchemaIssue.js"; | |
| import * as SchemaParser from "../../SchemaParser.js"; | |
| import * as SchemaTransformation from "../../SchemaTransformation.js"; | |
| // ============================================================================= | |
| // Options | |
| // ============================================================================= | |
| /** | |
| * Schema for provider-specific options that can be attached to content parts | |
| * and messages. | |
| * | |
| * **Details** | |
| * | |
| * Provider-specific options are keyed by provider-specific names, and each | |
| * value is JSON or `null`. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export const ProviderOptions = /*#__PURE__*/Schema.Record(Schema.String, /*#__PURE__*/Schema.NullOr(Schema.Json)); | |
| // ============================================================================= | |
| // Base Part | |
| // ============================================================================= | |
| const PartTypeId = "~effect/ai/Prompt/Part"; | |
| /** | |
| * Type guard to check if a value is a Part. | |
| * | |
| * @category guards | |
| * @since 4.0.0 | |
| */ | |
| export const isPart = u => Predicate.hasProperty(u, PartTypeId); | |
| const BasePart = /*#__PURE__*/Schema.Struct({ | |
| [PartTypeId]: /*#__PURE__*/Schema.Literal(PartTypeId).pipe(/*#__PURE__*/Schema.withDecodingDefaultKey(/*#__PURE__*/Effect.succeed(PartTypeId), { | |
| encodingStrategy: "omit" | |
| })), | |
| options: /*#__PURE__*/ProviderOptions.pipe(/*#__PURE__*/Schema.withDecodingDefault(/*#__PURE__*/Effect.succeed({}))) | |
| }); | |
| /** | |
| * Creates a new content part of the specified type. | |
| * | |
| * **Example** (Creating content parts) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const textPart = Prompt.makePart("text", { | |
| * text: "Hello, world!" | |
| * }) | |
| * | |
| * const filePart = Prompt.makePart("file", { | |
| * mediaType: "image/png", | |
| * fileName: "screenshot.png", | |
| * data: new Uint8Array([1, 2, 3]) | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const makePart = ( | |
| /** | |
| * The type of part to create. | |
| */ | |
| type, | |
| /** | |
| * Parameters specific to the part type being created. | |
| */ | |
| params) => ({ | |
| ...params, | |
| [PartTypeId]: PartTypeId, | |
| type, | |
| options: params.options ?? {} | |
| }); | |
| /** | |
| * Schema for validation and encoding of text parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const TextPart = /*#__PURE__*/Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("text"), | |
| text: Schema.String | |
| }).annotate({ | |
| identifier: "TextPart" | |
| }); | |
| /** | |
| * Constructs a new text part. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const textPart = params => makePart("text", params); | |
| /** | |
| * Schema for validation and encoding of reasoning parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ReasoningPart = /*#__PURE__*/Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("reasoning"), | |
| text: Schema.String | |
| }).annotate({ | |
| identifier: "ReasoningPart" | |
| }); | |
| /** | |
| * Constructs a new reasoning part. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const reasoningPart = params => makePart("reasoning", params); | |
| /** | |
| * Schema for validation and encoding of file parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const FilePart = /*#__PURE__*/Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("file"), | |
| mediaType: Schema.String, | |
| fileName: Schema.optional(Schema.String), | |
| data: Schema.Union([Schema.String, Schema.Uint8Array, Schema.URL]) | |
| }).annotate({ | |
| identifier: "FilePart" | |
| }); | |
| /** | |
| * Constructs a `FilePart` for prompt file attachments. | |
| * | |
| * **When to use** | |
| * | |
| * Use to create the file-attachment part of a prompt from typed file part | |
| * parameters. | |
| * | |
| * @see {@link makePart} for the generic part constructor | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const filePart = params => makePart("file", params); | |
| /** | |
| * Schema for validation and encoding of tool call parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ToolCallPart = /*#__PURE__*/Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("tool-call"), | |
| id: Schema.String, | |
| name: Schema.String, | |
| params: Schema.Unknown, | |
| providerExecuted: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))) | |
| }).annotate({ | |
| identifier: "ToolCallPart" | |
| }); | |
| /** | |
| * Constructs a new tool call part. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const toolCallPart = params => makePart("tool-call", params); | |
| /** | |
| * Schema for validation and encoding of tool result parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ToolResultPart = /*#__PURE__*/Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("tool-result"), | |
| id: Schema.String, | |
| name: Schema.String, | |
| isFailure: Schema.Boolean, | |
| result: Schema.Unknown | |
| }).annotate({ | |
| identifier: "ToolResultPart" | |
| }); | |
| /** | |
| * Constructs a new tool result part. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const toolResultPart = params => makePart("tool-result", params); | |
| /** | |
| * Schema for validation and encoding of tool approval response parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ToolApprovalResponsePart = /*#__PURE__*/Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("tool-approval-response"), | |
| approvalId: Schema.String, | |
| approved: Schema.Boolean, | |
| reason: Schema.optional(Schema.String) | |
| }).annotate({ | |
| identifier: "ToolApprovalResponsePart" | |
| }); | |
| /** | |
| * Constructs a new tool approval response part. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const toolApprovalResponsePart = params => makePart("tool-approval-response", params); | |
| /** | |
| * Schema for validation and encoding of tool approval request parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ToolApprovalRequestPart = /*#__PURE__*/Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("tool-approval-request"), | |
| approvalId: Schema.String, | |
| toolCallId: Schema.String | |
| }).annotate({ | |
| identifier: "ToolApprovalRequestPart" | |
| }); | |
| /** | |
| * Constructs a new tool approval request part. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const toolApprovalRequestPart = params => makePart("tool-approval-request", params); | |
| // ============================================================================= | |
| // Base Message | |
| // ============================================================================= | |
| const MessageTypeId = "~effect/ai/Prompt/Message"; | |
| /** | |
| * Type guard to check if a value is a Message. | |
| * | |
| * @category guards | |
| * @since 4.0.0 | |
| */ | |
| export const isMessage = u => Predicate.hasProperty(u, MessageTypeId); | |
| const BaseMessage = /*#__PURE__*/Schema.Struct({ | |
| [MessageTypeId]: /*#__PURE__*/Schema.Literal(MessageTypeId).pipe(/*#__PURE__*/Schema.withDecodingDefaultKey(/*#__PURE__*/Effect.succeed(MessageTypeId), { | |
| encodingStrategy: "omit" | |
| })), | |
| options: /*#__PURE__*/ProviderOptions.pipe(/*#__PURE__*/Schema.withDecodingDefault(/*#__PURE__*/Effect.succeed({}))) | |
| }); | |
| /** | |
| * Creates a new message with the specified role. | |
| * | |
| * **Example** (Creating messages) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const textPart = Prompt.makePart("text", { | |
| * text: "Hello, world!" | |
| * }) | |
| * | |
| * const userMessage = Prompt.makeMessage("user", { | |
| * content: [textPart] | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const makeMessage = (role, params) => ({ | |
| ...params, | |
| [MessageTypeId]: MessageTypeId, | |
| role, | |
| options: params.options ?? {} | |
| }); | |
| /** | |
| * Schema that decodes a string into content containing a single `TextPart` and, | |
| * when encoding, emits the `text` value of the first part. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ContentFromString = /*#__PURE__*/Schema.String.pipe(/*#__PURE__*/Schema.decodeTo(/*#__PURE__*/Schema.NonEmptyArray(/*#__PURE__*/Schema.toType(TextPart)), /*#__PURE__*/SchemaTransformation.transform({ | |
| decode: text => Arr.of(makePart("text", { | |
| text | |
| })), | |
| encode: content => content[0].text | |
| }))); | |
| /** | |
| * Schema for validation and encoding of system messages. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const SystemMessage = /*#__PURE__*/Schema.Struct({ | |
| ...BaseMessage.fields, | |
| role: Schema.Literal("system"), | |
| content: Schema.String | |
| }).annotate({ | |
| identifier: "SystemMessage" | |
| }); | |
| /** | |
| * Constructs a new system message. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const systemMessage = params => makeMessage("system", params); | |
| /** | |
| * Schema for validation and encoding of user messages. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const UserMessage = /*#__PURE__*/Schema.Struct({ | |
| ...BaseMessage.fields, | |
| role: Schema.Literal("user"), | |
| content: Schema.Union([ContentFromString, Schema.Array(Schema.Union([TextPart, FilePart]))]) | |
| }).annotate({ | |
| identifier: "UserMessage" | |
| }); | |
| /** | |
| * Constructs a new user message. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const userMessage = params => makeMessage("user", params); | |
| /** | |
| * Schema for validation and encoding of assistant messages. | |
| * | |
| * **Details** | |
| * | |
| * Assistant content can be a string decoded through `ContentFromString` or an | |
| * array of text, file, reasoning, tool-call, tool-result, and | |
| * tool-approval-request parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const AssistantMessage = /*#__PURE__*/Schema.Struct({ | |
| ...BaseMessage.fields, | |
| role: Schema.Literal("assistant"), | |
| content: Schema.Union([ContentFromString, Schema.Array(Schema.Union([TextPart, FilePart, ReasoningPart, ToolCallPart, ToolResultPart, ToolApprovalRequestPart]))]) | |
| }).annotate({ | |
| identifier: "AssistantMessage" | |
| }); | |
| /** | |
| * Constructs a new assistant message. | |
| * | |
| * **When to use** | |
| * | |
| * Use to add assistant-role prompt history or model responses. | |
| * | |
| * **Details** | |
| * | |
| * This is the role-specific wrapper around `makeMessage("assistant", params)`. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const assistantMessage = params => makeMessage("assistant", params); | |
| /** | |
| * Schema for validation and encoding of tool messages. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ToolMessage = /*#__PURE__*/Schema.Struct({ | |
| ...BaseMessage.fields, | |
| role: Schema.Literal("tool"), | |
| content: Schema.Array(Schema.Union([ToolResultPart, ToolApprovalResponsePart])) | |
| }).annotate({ | |
| identifier: "ToolMessage" | |
| }); | |
| /** | |
| * Constructs a new tool message. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const toolMessage = params => makeMessage("tool", params); | |
| /** | |
| * Schema for validation and encoding of messages. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const Message = /*#__PURE__*/Schema.Union([SystemMessage, UserMessage, AssistantMessage, ToolMessage]); | |
| // ============================================================================= | |
| // Prompt | |
| // ============================================================================= | |
| const TypeId = "~effect/unstable/ai/Prompt"; | |
| /** | |
| * Type guard to check if a value is a Prompt. | |
| * | |
| * @category guards | |
| * @since 4.0.0 | |
| */ | |
| export const isPrompt = u => Predicate.hasProperty(u, TypeId); | |
| const $Prompt = /*#__PURE__*/Schema.declare(u => isPrompt(u), { | |
| identifier: "Prompt" | |
| }); | |
| // TODO: is the type annotation necessary? | |
| // TODO: shoudn't the name be `PromptFrom...`? | |
| // TODO: is the explicit encoding necessary? maybe use the default JSON serializer? | |
| /** | |
| * Schema for AI prompt instances. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const Prompt = /*#__PURE__*/Schema.Struct({ | |
| content: Schema.Array(Schema.toEncoded(Message)) | |
| }).pipe(/*#__PURE__*/Schema.decodeTo($Prompt, /*#__PURE__*/SchemaTransformation.transformOrFail({ | |
| decode: input => Effect.mapBothEager(SchemaParser.decodeEffect(Schema.Array(Message))(input.content), { | |
| onSuccess: makePrompt, | |
| onFailure: () => new SchemaIssue.InvalidValue(Option.some(input.content), { | |
| message: "Invalid Prompt messages" | |
| }) | |
| }), | |
| encode: prompt => Effect.mapBothEager(SchemaParser.encodeEffect(Schema.Array(Message))(prompt.content), { | |
| onSuccess: messages => ({ | |
| content: messages | |
| }), | |
| onFailure: () => new SchemaIssue.InvalidValue(Option.some(prompt.content), { | |
| message: "Invalid Prompt messages" | |
| }) | |
| }) | |
| }))); | |
| const Proto = { | |
| [TypeId]: TypeId, | |
| pipe() { | |
| return pipeArguments(this, arguments); | |
| } | |
| }; | |
| const makePrompt = content => Object.assign(Object.create(Proto), { | |
| content | |
| }); | |
| const decodeMessagesSync = /*#__PURE__*/Schema.decodeSync(/*#__PURE__*/Schema.Array(Message)); | |
| /** | |
| * An empty prompt with no messages. | |
| * | |
| * **Example** (Creating an empty prompt) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const emptyPrompt = Prompt.empty | |
| * console.log(emptyPrompt.content) // [] | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const empty = /*#__PURE__*/makePrompt([]); | |
| /** | |
| * Creates a `Prompt` from an input. | |
| * | |
| * **Details** | |
| * | |
| * This is the primary constructor for creating prompts, supporting multiple | |
| * input formats for convenience and flexibility. | |
| * | |
| * **Example** (Creating prompts from inputs) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * // From string - creates a user message | |
| * const textPrompt = Prompt.make("Hello, how are you?") | |
| * | |
| * // From messages array | |
| * const structuredPrompt = Prompt.make([ | |
| * { role: "system", content: "You are a helpful assistant." }, | |
| * { role: "user", content: [{ type: "text", text: "Hi!" }] } | |
| * ]) | |
| * | |
| * // From existing prompt | |
| * declare const existingPrompt: Prompt.Prompt | |
| * const copiedPrompt = Prompt.make(existingPrompt) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const make = input => { | |
| if (typeof input === "string") { | |
| const part = makePart("text", { | |
| text: input | |
| }); | |
| const message = makeMessage("user", { | |
| content: [part] | |
| }); | |
| return makePrompt([message]); | |
| } | |
| if (Predicate.isIterable(input)) { | |
| return makePrompt(decodeMessagesSync(Arr.fromIterable(input), { | |
| errors: "all" | |
| })); | |
| } | |
| return input; | |
| }; | |
| /** | |
| * Creates a Prompt from an array of messages. | |
| * | |
| * **Example** (Creating prompts from messages) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const messages: ReadonlyArray<Prompt.Message> = [ | |
| * Prompt.makeMessage("system", { | |
| * content: "You are a coding assistant." | |
| * }), | |
| * Prompt.makeMessage("user", { | |
| * content: [Prompt.makePart("text", { text: "Help me with TypeScript" })] | |
| * }) | |
| * ] | |
| * | |
| * const prompt = Prompt.fromMessages(messages) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromMessages = messages => makePrompt(messages); | |
| /** | |
| * Creates a `Prompt` from response parts by folding completed text and | |
| * reasoning streams into assistant parts, placing tool calls and approval | |
| * requests in an assistant message, and placing non-preliminary tool results | |
| * in a tool message using their encoded results. | |
| * | |
| * **Example** (Creating prompts from response parts) | |
| * | |
| * ```ts | |
| * import { Prompt, Response } from "effect/unstable/ai" | |
| * | |
| * const responseParts: ReadonlyArray<Response.AnyPart> = [ | |
| * Response.makePart("text", { | |
| * text: "Hello there!" | |
| * }), | |
| * Response.makePart("tool-call", { | |
| * id: "call_1", | |
| * name: "get_time", | |
| * params: {}, | |
| * providerExecuted: false | |
| * }), | |
| * Response.makePart("tool-result", { | |
| * id: "call_1", | |
| * name: "get_time", | |
| * isFailure: false, | |
| * result: "10:30 AM", | |
| * encodedResult: "10:30 AM", | |
| * providerExecuted: false, | |
| * preliminary: false | |
| * }) | |
| * ] | |
| * | |
| * const prompt = Prompt.fromResponseParts(responseParts) | |
| * // Creates an assistant message with the response content | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromResponseParts = parts => { | |
| if (parts.length === 0) { | |
| return empty; | |
| } | |
| const assistantParts = []; | |
| const toolParts = []; | |
| const activeTextDeltas = new Map(); | |
| const activeReasoningDeltas = new Map(); | |
| for (const part of parts) { | |
| switch (part.type) { | |
| // Text Parts | |
| case "text": | |
| { | |
| assistantParts.push(makePart("text", { | |
| text: part.text | |
| })); | |
| break; | |
| } | |
| // Text Parts (streaming) | |
| case "text-start": | |
| { | |
| activeTextDeltas.set(part.id, { | |
| text: "" | |
| }); | |
| break; | |
| } | |
| case "text-delta": | |
| { | |
| if (activeTextDeltas.has(part.id)) { | |
| activeTextDeltas.get(part.id).text += part.delta; | |
| } | |
| break; | |
| } | |
| case "text-end": | |
| { | |
| if (activeTextDeltas.has(part.id)) { | |
| assistantParts.push(makePart("text", activeTextDeltas.get(part.id))); | |
| } | |
| break; | |
| } | |
| // Reasoning Parts | |
| case "reasoning": | |
| { | |
| assistantParts.push(makePart("reasoning", { | |
| text: part.text | |
| })); | |
| break; | |
| } | |
| // Reasoning Parts (streaming) | |
| case "reasoning-start": | |
| { | |
| activeReasoningDeltas.set(part.id, { | |
| text: "" | |
| }); | |
| break; | |
| } | |
| case "reasoning-delta": | |
| { | |
| if (activeReasoningDeltas.has(part.id)) { | |
| activeReasoningDeltas.get(part.id).text += part.delta; | |
| } | |
| break; | |
| } | |
| case "reasoning-end": | |
| { | |
| if (activeReasoningDeltas.has(part.id)) { | |
| assistantParts.push(makePart("reasoning", activeReasoningDeltas.get(part.id))); | |
| } | |
| break; | |
| } | |
| // Tool Call Parts | |
| case "tool-call": | |
| { | |
| assistantParts.push(makePart("tool-call", { | |
| id: part.id, | |
| name: part.name, | |
| params: part.params, | |
| providerExecuted: part.providerExecuted ?? false | |
| })); | |
| break; | |
| } | |
| // Tool Result Parts (skip preliminary results) | |
| case "tool-result": | |
| { | |
| if (part.preliminary !== true) { | |
| toolParts.push(makePart("tool-result", { | |
| id: part.id, | |
| name: part.name, | |
| isFailure: part.isFailure, | |
| result: part.encodedResult | |
| })); | |
| } | |
| break; | |
| } | |
| // Tool Approval Request Parts | |
| case "tool-approval-request": | |
| { | |
| assistantParts.push(makePart("tool-approval-request", { | |
| approvalId: part.approvalId, | |
| toolCallId: part.toolCallId | |
| })); | |
| break; | |
| } | |
| } | |
| } | |
| if (assistantParts.length === 0 && toolParts.length === 0) { | |
| return empty; | |
| } | |
| const messages = []; | |
| if (assistantParts.length > 0) { | |
| messages.push(makeMessage("assistant", { | |
| content: assistantParts | |
| })); | |
| } | |
| if (toolParts.length > 0) { | |
| messages.push(makeMessage("tool", { | |
| content: toolParts | |
| })); | |
| } | |
| return makePrompt(messages); | |
| }; | |
| // ============================================================================= | |
| // Merging Prompts | |
| // ============================================================================= | |
| /** | |
| * Concatenates a prompt with additional raw input by concatenating messages. | |
| * | |
| * **Details** | |
| * | |
| * The returned prompt contains all messages from the original prompt followed | |
| * by the provided raw input, preserving message order. | |
| * | |
| * **Example** (Concatenating prompts) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are a helpful assistant." | |
| * }]) | |
| * | |
| * const merged = Prompt.concat(systemPrompt, "Hello, world!") | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| export const concat = /*#__PURE__*/dual(2, (self, input) => { | |
| const other = make(input); | |
| if (self.content.length === 0) { | |
| return other; | |
| } | |
| if (other.content.length === 0) { | |
| return self; | |
| } | |
| return fromMessages([...self.content, ...other.content]); | |
| }); | |
| // ============================================================================= | |
| // Manipulating Prompts | |
| // ============================================================================= | |
| /** | |
| * Creates a new prompt from the specified prompt with the system message set | |
| * to the specified text content. | |
| * | |
| * **Gotchas** | |
| * | |
| * This method removes and replaces any previous system message from the | |
| * prompt. | |
| * | |
| * **Example** (Replacing system instructions) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are a helpful assistant." | |
| * }]) | |
| * | |
| * const userPrompt = Prompt.make("Hello, world!") | |
| * | |
| * const prompt = Prompt.concat(systemPrompt, userPrompt) | |
| * | |
| * const replaced = Prompt.setSystem( | |
| * prompt, | |
| * "You are an expert in programming" | |
| * ) | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| export const setSystem = /*#__PURE__*/dual(2, (self, content) => { | |
| const messages = [makeMessage("system", { | |
| content | |
| })]; | |
| for (const message of self.content) { | |
| if (message.role !== "system") { | |
| messages.push(message); | |
| } | |
| } | |
| return makePrompt(messages); | |
| }); | |
| /** | |
| * Creates a new prompt with a leading system message. If the prompt already has | |
| * a system message, the new message uses the provided content prepended to the | |
| * first existing system message's content; the original messages remain after | |
| * it. | |
| * | |
| * **Example** (Prepending system instructions) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are an expert in programming." | |
| * }]) | |
| * | |
| * const userPrompt = Prompt.make("Hello, world!") | |
| * | |
| * const prompt = Prompt.concat(systemPrompt, userPrompt) | |
| * | |
| * const replaced = Prompt.prependSystem( | |
| * prompt, | |
| * "You are a helpful assistant. " | |
| * ) | |
| * // result content: "You are a helpful assistant. You are an expert in programming." | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| export const prependSystem = /*#__PURE__*/dual(2, (self, content) => { | |
| let system = undefined; | |
| for (const message of self.content) { | |
| if (message.role === "system") { | |
| system = makeMessage("system", { | |
| content: content + message.content | |
| }); | |
| break; | |
| } | |
| } | |
| if (Predicate.isUndefined(system)) { | |
| system = makeMessage("system", { | |
| content | |
| }); | |
| } | |
| return makePrompt([system, ...self.content]); | |
| }); | |
| /** | |
| * Creates a new prompt with a leading system message. If the prompt already has | |
| * a system message, the new message uses the provided content appended to the | |
| * first existing system message's content; the original messages remain after | |
| * it. | |
| * | |
| * **Example** (Appending system instructions) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are an expert in programming." | |
| * }]) | |
| * | |
| * const userPrompt = Prompt.make("Hello, world!") | |
| * | |
| * const prompt = Prompt.concat(systemPrompt, userPrompt) | |
| * | |
| * const replaced = Prompt.appendSystem( | |
| * prompt, | |
| * " You are a helpful assistant." | |
| * ) | |
| * // result content: "You are an expert in programming. You are a helpful assistant." | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| export const appendSystem = /*#__PURE__*/dual(2, (self, content) => { | |
| let system = undefined; | |
| for (const message of self.content) { | |
| if (message.role === "system") { | |
| system = makeMessage("system", { | |
| content: message.content + content | |
| }); | |
| break; | |
| } | |
| } | |
| if (Predicate.isUndefined(system)) { | |
| system = makeMessage("system", { | |
| content | |
| }); | |
| } | |
| return makePrompt([system, ...self.content]); | |
| }); | |
| //# sourceMappingURL=Prompt.js.map |
Xet Storage Details
- Size:
- 24.2 kB
- Xet hash:
- 9e6278d49835b2ef615bb99637b4760ca7fcf008b0791eb751a68e1d6d636b53
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.