Created
October 6, 2025 14:17
-
-
Save zbeyens/c758965d455e4a54362a947a2c868c32 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { ToolDefinition } from '@/components/ai/utils/tool-utils'; | |
| import dedent from 'dedent'; | |
| // Returns tagged markdown list items for active tools with descriptions | |
| export const listTools = (tools?: Record<string, ToolDefinition>) => { | |
| if (!tools) return ''; | |
| const items = Object.entries(tools).map(([key, tool]) => { | |
| if (!tool || tool.active === false || !tool.description) return ''; | |
| return `${key}: ${tool.description}`; | |
| }); | |
| const content = list(items); | |
| return content ? tag('tools', content) : ''; | |
| }; | |
| /** | |
| * Tag content split by newlines | |
| * | |
| * @example | |
| * <tools> | |
| * {content} | |
| * </tools> | |
| */ | |
| export const tag = (tag: string, content?: string | null) => { | |
| if (!content) return ''; | |
| return [`<${tag}>`, content, `</${tag}>`].join('\n'); | |
| }; | |
| /** | |
| * Tag content inline | |
| * | |
| * @example | |
| * <tools>{content}</tools> | |
| */ | |
| export const inlineTag = (tag: string, content?: string | null) => { | |
| if (!content) return ''; | |
| return [`<${tag}>`, content, `</${tag}>`].join(''); | |
| }; | |
| // Sections split by double newlines | |
| export const sections = (sections: (boolean | string | null | undefined)[]) => { | |
| return sections.filter(Boolean).join('\n\n'); | |
| }; | |
| // List items split by newlines | |
| export const list = (items: string[] | undefined) => { | |
| return items | |
| ? items | |
| .filter(Boolean) | |
| .map((item) => `- ${item}`) | |
| .join('\n') | |
| : ''; | |
| }; | |
| export type StructuredPromptSections = { | |
| taskContext?: string; | |
| tone?: string; | |
| backgroundData?: string; | |
| tools?: string; | |
| rules?: string; | |
| examples?: string | string[]; | |
| history?: string; | |
| question?: string; | |
| task?: string; | |
| thinking?: string; | |
| outputFormatting?: string; | |
| prefilledResponse?: string; | |
| }; | |
| /** | |
| * Build a structured prompt following best practices for AI interactions. | |
| * | |
| * @example | |
| * https://imgur.com/carbon-Db5tDUh | |
| * 1. Task context - You will be acting as an AI career coach named Joe created by the company | |
| * AdAstra Careers. Your goal is to give career advice to users. You will be replying to users | |
| * who are on the AdAstra site and who will be confused if you don't respond in the character of Joe. | |
| * 2. Tone context - You should maintain a friendly customer service tone. | |
| * 3. Background data - Here is the career guidance document you should reference when answering the user: <guide>{DOCUMENT}</guide> | |
| * 3b. Tools - Available tool descriptions | |
| * 4. Rules - Here are some important rules for the interaction: | |
| * - Always stay in character, as Joe, an AI from AdAstra careers | |
| * - If you are unsure how to respond, say "Sorry, I didn't understand that. Could you repeat the question?" | |
| * - If someone asks something irrelevant, say, "Sorry, I am Joe and I give career advice..." | |
| * 5. Examples - Here is an example of how to respond in a standard interaction: | |
| * <example> | |
| * User: Hi, how were you created and what do you do? | |
| * Joe: Hello! My name is Joe, and I was created by AdAstra Careers to give career advice... | |
| * </example> | |
| * 6. Conversation history - Here is the conversation history (between the user and you) prior to the question. <history>{HISTORY}</history> | |
| * 6b. Question - Here is the user's question: <question>{QUESTION}</question> | |
| * 7. Immediate task - How do you respond to the user's question? | |
| * 8. Thinking - Think about your answer first before you respond. | |
| * 9. Output formatting - Put your response in <response></response> tags. | |
| * 11. Prefilled response - Optional response starter | |
| */ | |
| export const buildStructuredPrompt = ({ | |
| taskContext, | |
| tone, | |
| backgroundData, | |
| tools, | |
| rules, | |
| examples, | |
| history, | |
| question, | |
| task, | |
| thinking, | |
| outputFormatting, | |
| prefilledResponse, | |
| }: StructuredPromptSections) => { | |
| const formattedExamples = Array.isArray(examples) | |
| ? examples.map((example) => tag('example', example)).join('\n') | |
| : examples; | |
| const context = sections([ | |
| taskContext, | |
| tone, | |
| backgroundData && | |
| dedent`Here is the background data you should reference when answering the user: | |
| ${backgroundData}`, | |
| tools && | |
| dedent`Here are some important rules for the interaction: | |
| ${tools}`, | |
| dedent`Here are some important rules for the interaction: | |
| ${rules}`, | |
| formattedExamples && | |
| dedent`Here are some examples of how to respond in a standard interaction: | |
| ${tag('examples', formattedExamples)}`, | |
| history && | |
| dedent`Here is the conversation history (between the user and you) prior to the question: | |
| ${tag('history', history)}`, | |
| question && | |
| dedent`Here is the user's question: | |
| ${tag('question', question)}`, | |
| ]); | |
| return sections([ | |
| tag('context', context), | |
| task, | |
| // or <reasoningSteps> | |
| thinking && tag('thinking', thinking), | |
| // Not needed with structured output | |
| outputFormatting && tag('outputFormatting', outputFormatting), | |
| // Not needed with structured output | |
| (prefilledResponse ?? null) !== null && tag('prefilledResponse', prefilledResponse ?? ''), | |
| ]); | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment