Merge pull request #97 from alibaba/feat/instructions
feat: custom instructions
This commit is contained in:
@@ -361,9 +361,50 @@ export class PageAgent extends EventTarget {
|
|||||||
return systemPrompt
|
return systemPrompt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get instructions from config and format as XML block
|
||||||
|
*/
|
||||||
|
async #getInstructions(): Promise<string> {
|
||||||
|
const { instructions } = this.config
|
||||||
|
if (!instructions) return ''
|
||||||
|
|
||||||
|
const systemInstructions = instructions.system?.trim()
|
||||||
|
const url = await this.pageController.getCurrentUrl()
|
||||||
|
let pageInstructions: string | undefined
|
||||||
|
|
||||||
|
if (instructions.getPageInstructions) {
|
||||||
|
try {
|
||||||
|
pageInstructions = instructions.getPageInstructions(url)?.trim()
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
chalk.red('[PageAgent] Failed to execute getPageInstructions callback:'),
|
||||||
|
error
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!systemInstructions && !pageInstructions) return ''
|
||||||
|
|
||||||
|
let result = '<instructions>\n'
|
||||||
|
|
||||||
|
if (systemInstructions) {
|
||||||
|
result += `<system_instructions>\n${systemInstructions}\n</system_instructions>\n`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pageInstructions) {
|
||||||
|
result += `<page_instructions>\n${pageInstructions}\n</page_instructions>\n`
|
||||||
|
}
|
||||||
|
|
||||||
|
result += '</instructions>\n\n'
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
async #assembleUserPrompt(): Promise<string> {
|
async #assembleUserPrompt(): Promise<string> {
|
||||||
let prompt = ''
|
let prompt = ''
|
||||||
|
|
||||||
|
// <instructions> (optional)
|
||||||
|
prompt += await this.#getInstructions()
|
||||||
|
|
||||||
// <agent_state>
|
// <agent_state>
|
||||||
// - <user_request>
|
// - <user_request>
|
||||||
// - <step_info>
|
// - <step_info>
|
||||||
|
|||||||
@@ -42,6 +42,24 @@ export interface AgentConfig {
|
|||||||
*/
|
*/
|
||||||
customTools?: Record<string, PageAgentTool | null>
|
customTools?: Record<string, PageAgentTool | null>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instructions to guide the agent's behavior
|
||||||
|
*/
|
||||||
|
instructions?: {
|
||||||
|
/**
|
||||||
|
* Global system-level instructions, applied to all tasks
|
||||||
|
*/
|
||||||
|
system?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamic page-level instructions callback
|
||||||
|
* Called before each step to get instructions for the current page
|
||||||
|
* @param url - Current page URL (window.location.href)
|
||||||
|
* @returns Instructions string, or undefined/null to skip
|
||||||
|
*/
|
||||||
|
getPageInstructions?: (url: string) => string | undefined | null
|
||||||
|
}
|
||||||
|
|
||||||
// lifecycle hooks
|
// lifecycle hooks
|
||||||
// @todo: use event instead of hooks
|
// @todo: use event instead of hooks
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export default function DocsLayout({ children }: DocsLayoutProps) {
|
|||||||
items: [
|
items: [
|
||||||
{ title: t('nav.model_integration'), path: '/docs/features/model-integration' },
|
{ title: t('nav.model_integration'), path: '/docs/features/model-integration' },
|
||||||
{ title: t('nav.custom_tools'), path: '/docs/features/custom-tools' },
|
{ title: t('nav.custom_tools'), path: '/docs/features/custom-tools' },
|
||||||
{ title: t('nav.knowledge_injection'), path: '/docs/features/knowledge-injection' },
|
{ title: t('nav.knowledge_injection'), path: '/docs/features/custom-instructions' },
|
||||||
{ title: t('nav.security_permissions'), path: '/docs/features/security-permissions' },
|
{ title: t('nav.security_permissions'), path: '/docs/features/security-permissions' },
|
||||||
{ title: t('nav.data_masking'), path: '/docs/features/data-masking' },
|
{ title: t('nav.data_masking'), path: '/docs/features/data-masking' },
|
||||||
],
|
],
|
||||||
|
|||||||
135
packages/website/src/docs/features/custom-instructions/page.tsx
Normal file
135
packages/website/src/docs/features/custom-instructions/page.tsx
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
import CodeEditor from '@/components/CodeEditor'
|
||||||
|
|
||||||
|
export default function Instructions() {
|
||||||
|
const { i18n } = useTranslation()
|
||||||
|
const isZh = i18n.language === 'zh-CN'
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="text-4xl font-bold mb-6">{isZh ? '知识注入' : 'Instructions'}</h1>
|
||||||
|
|
||||||
|
<p className="text-xl text-gray-600 dark:text-gray-300 mb-8 leading-relaxed">
|
||||||
|
{isZh
|
||||||
|
? '通过 instructions 配置,为 AI 注入系统级指导和页面级上下文,让它更好地理解你的业务场景。'
|
||||||
|
: 'Use the instructions config to inject system-level directives and page-specific context, helping the AI better understand your application.'}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* System Instructions */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold mb-6">
|
||||||
|
{isZh ? '系统级指导 (System Instructions)' : 'System Instructions'}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
{isZh
|
||||||
|
? '全局提示词,应用于所有任务。定义 AI 的角色、工作风格和行为边界。'
|
||||||
|
: "Global directives applied to all tasks. Define the AI's role, working style, and behavioral boundaries."}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeEditor
|
||||||
|
className="mb-6"
|
||||||
|
code={`const agent = new PageAgent({
|
||||||
|
// ...other config
|
||||||
|
instructions: {
|
||||||
|
system: \`
|
||||||
|
You are a professional e-commerce assistant.
|
||||||
|
|
||||||
|
Guidelines:
|
||||||
|
- Always confirm before submitting orders
|
||||||
|
- Double-check prices and quantities
|
||||||
|
- Report errors immediately instead of retrying blindly
|
||||||
|
\`
|
||||||
|
}
|
||||||
|
})`}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Page Instructions */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold mb-6">
|
||||||
|
{isZh ? '页面级指导 (Page Instructions)' : 'Page Instructions'}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
{isZh
|
||||||
|
? '动态回调函数,在每个 step 执行前调用,根据当前页面 URL 返回特定提示词。适用于为不同页面提供针对性的操作引导。'
|
||||||
|
: 'A dynamic callback invoked before each step. Returns page-specific instructions based on the current URL. Useful for providing targeted guidance on different pages.'}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeEditor
|
||||||
|
className="mb-6"
|
||||||
|
code={`const agent = new PageAgent({
|
||||||
|
// ...other config
|
||||||
|
instructions: {
|
||||||
|
system: 'You are an order management assistant.',
|
||||||
|
|
||||||
|
getPageInstructions: (url) => {
|
||||||
|
if (url.includes('/checkout')) {
|
||||||
|
return \`
|
||||||
|
This is the checkout page.
|
||||||
|
- Verify shipping address before proceeding
|
||||||
|
- Check if any discounts are applied
|
||||||
|
- Confirm the total amount with the user
|
||||||
|
\`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.includes('/products')) {
|
||||||
|
return \`
|
||||||
|
This is the product listing page.
|
||||||
|
- Use filters to narrow down search results
|
||||||
|
- Check stock availability before adding to cart
|
||||||
|
\`
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined // No special instructions for other pages
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})`}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* How It Works */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold mb-6">{isZh ? '工作原理' : 'How It Works'}</h2>
|
||||||
|
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
{isZh
|
||||||
|
? '在每个执行步骤之前,page-agent 会将 instructions 拼接到用户提示词中:'
|
||||||
|
: 'Before each execution step, page-agent prepends the instructions to the user prompt:'}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeEditor
|
||||||
|
language="xml"
|
||||||
|
className="mb-6"
|
||||||
|
code={`<instructions>
|
||||||
|
<system_instructions>
|
||||||
|
You are a professional e-commerce assistant.
|
||||||
|
...
|
||||||
|
</system_instructions>
|
||||||
|
<page_instructions>
|
||||||
|
This is the checkout page.
|
||||||
|
...
|
||||||
|
</page_instructions>
|
||||||
|
</instructions>
|
||||||
|
|
||||||
|
<!-- followed by agent state, history, and browser state -->`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ul className="list-disc list-inside space-y-2 text-gray-600 dark:text-gray-400">
|
||||||
|
<li>
|
||||||
|
{isZh
|
||||||
|
? '如果 system 为空,则不输出 <system_instructions> 标签'
|
||||||
|
: 'If system is empty, the <system_instructions> tag is omitted'}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
{isZh
|
||||||
|
? '如果 getPageInstructions 返回空值,则不输出 <page_instructions> 标签'
|
||||||
|
: 'If getPageInstructions returns empty, the <page_instructions> tag is omitted'}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
import BetaNotice from '@/components/BetaNotice'
|
|
||||||
import CodeEditor from '@/components/CodeEditor'
|
|
||||||
|
|
||||||
export default function KnowledgeInjection() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h1 className="text-4xl font-bold mb-6">知识库注入</h1>
|
|
||||||
|
|
||||||
<BetaNotice />
|
|
||||||
|
|
||||||
<p className="text-xl text-gray-600 dark:text-gray-300 mb-8 leading-relaxed">
|
|
||||||
通过多层次的知识注入,让 AI 深度理解你的业务场景和应用逻辑,实现更精准的自动化操作。
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{/* Custom Instruction */}
|
|
||||||
<section className="mb-12">
|
|
||||||
<h2 className="text-3xl font-bold mb-6">Instruction - 系统指令</h2>
|
|
||||||
|
|
||||||
<div className="p-6 bg-purple-50 dark:bg-purple-900/20 rounded-lg mb-6">
|
|
||||||
<h3 className="text-xl font-semibold mb-3 text-purple-900 dark:text-purple-300">
|
|
||||||
🎯 系统级指令
|
|
||||||
</h3>
|
|
||||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
|
||||||
为 AI 设定全局行为准则和工作风格。
|
|
||||||
</p>
|
|
||||||
<ul className="list-disc list-inside space-y-2 text-gray-500 dark:text-gray-400">
|
|
||||||
<li>定义 AI 的工作风格和交互方式</li>
|
|
||||||
<li>设置安全边界和操作限制</li>
|
|
||||||
<li>指定错误处理和异常情况的应对策略</li>
|
|
||||||
<li>配置输出格式和反馈机制</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<CodeEditor
|
|
||||||
className="mb-6"
|
|
||||||
code={`// 构造函数中设置系统指令
|
|
||||||
const pageAgent = new PageAgent({
|
|
||||||
instruction: \`
|
|
||||||
# 角色定义
|
|
||||||
你是专业的电商运营助手。
|
|
||||||
|
|
||||||
# 工作风格
|
|
||||||
- 谨慎:操作前确认
|
|
||||||
- 准确:确保正确性
|
|
||||||
- 高效:优化流程
|
|
||||||
|
|
||||||
# 错误处理
|
|
||||||
遇到错误时暂停并报告。
|
|
||||||
\`
|
|
||||||
});`}
|
|
||||||
/>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* App Knowledge */}
|
|
||||||
<section className="mb-12">
|
|
||||||
<h2 className="text-3xl font-bold mb-6">App Knowledge - 应用知识</h2>
|
|
||||||
|
|
||||||
<div className="p-6 bg-blue-50 dark:bg-blue-900/20 rounded-lg mb-6">
|
|
||||||
<h3 className="text-xl font-semibold mb-3 text-blue-900 dark:text-blue-300">
|
|
||||||
<EFBFBD> 业务领域知识
|
|
||||||
</h3>
|
|
||||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
|
||||||
注入应用的核心业务知识,包括产品介绍、操作流程、术语定义等,让 AI 理解业务上下文。
|
|
||||||
</p>
|
|
||||||
<div className="grid md:grid-cols-2 gap-4">
|
|
||||||
<div className="space-y-2">
|
|
||||||
<h4 className="font-semibold text-blue-800 dark:text-blue-200">产品知识</h4>
|
|
||||||
<ul className="list-disc list-inside text-sm text-gray-500 dark:text-gray-400 space-y-1">
|
|
||||||
<li>产品功能和特性介绍</li>
|
|
||||||
<li>用户角色和权限体系</li>
|
|
||||||
<li>业务规则和约束条件</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2">
|
|
||||||
<h4 className="font-semibold text-blue-800 dark:text-blue-200">操作指南</h4>
|
|
||||||
<ul className="list-disc list-inside text-sm text-gray-500 dark:text-gray-400 space-y-1">
|
|
||||||
<li>标准操作流程定义</li>
|
|
||||||
<li>异常情况处理方案</li>
|
|
||||||
<li>术语和概念解释</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<CodeEditor
|
|
||||||
className="mb-6"
|
|
||||||
code={`// 应用知识
|
|
||||||
pageAgent.knowledge.setAppKnowledge(\`
|
|
||||||
# 产品介绍
|
|
||||||
电商管理系统:面向中小企业的一站式解决方案。
|
|
||||||
|
|
||||||
# 操作流程
|
|
||||||
## 商品上架
|
|
||||||
1. 进入商品管理页面 2. 点击新增商品 3. 填写基本信息 4. 设置库存 5. 提交审核
|
|
||||||
|
|
||||||
# 术语解释
|
|
||||||
- SKU:库存量单位
|
|
||||||
- SPU:标准产品单位
|
|
||||||
- 运费模板:物流费用计算规则
|
|
||||||
|
|
||||||
# 业务规则
|
|
||||||
- 库存为0时自动下架
|
|
||||||
- VIP会员享9.5折
|
|
||||||
\`);`}
|
|
||||||
/>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Page Knowledge */}
|
|
||||||
<section className="mb-12">
|
|
||||||
<h2 className="text-3xl font-bold mb-6">Page Knowledge - 页面知识</h2>
|
|
||||||
|
|
||||||
<div className="p-6 bg-green-50 dark:bg-green-900/20 rounded-lg mb-6">
|
|
||||||
<h3 className="text-xl font-semibold mb-3 text-green-900 dark:text-green-300">
|
|
||||||
📄 页面级精准指导
|
|
||||||
</h3>
|
|
||||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
|
||||||
为特定页面提供精确的操作指导和元素说明,让 AI 准确理解页面结构和交互逻辑。
|
|
||||||
</p>
|
|
||||||
<div className="grid md:grid-cols-3 gap-4">
|
|
||||||
<div className="space-y-2">
|
|
||||||
<h4 className="font-semibold text-green-800 dark:text-green-200">元素标注</h4>
|
|
||||||
<p className="text-sm text-gray-500 dark:text-gray-400">为页面元素添加语义化描述</p>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2">
|
|
||||||
<h4 className="font-semibold text-green-800 dark:text-green-200">交互说明</h4>
|
|
||||||
<p className="text-sm text-gray-500 dark:text-gray-400">
|
|
||||||
定义元素的交互行为和预期结果
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2">
|
|
||||||
<h4 className="font-semibold text-green-800 dark:text-green-200">页面逻辑</h4>
|
|
||||||
<p className="text-sm text-gray-500 dark:text-gray-400">
|
|
||||||
说明页面的业务逻辑和状态变化
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<CodeEditor
|
|
||||||
className="mb-6"
|
|
||||||
code={`// 页面知识库
|
|
||||||
// 添加页面知识
|
|
||||||
pageAgent.knowledge.addPageKnowledge("/products", \`
|
|
||||||
商品列表页面,包含搜索、筛选、批量操作功能。
|
|
||||||
#add-product-btn:新增商品按钮
|
|
||||||
.product-item:商品列表项
|
|
||||||
#search-input:搜索框,最少2个字符
|
|
||||||
\`);
|
|
||||||
|
|
||||||
pageAgent.knowledge.addPageKnowledge("/orders/*", \`
|
|
||||||
订单详情页面。
|
|
||||||
.order-status:订单状态标签
|
|
||||||
#update-status-btn:状态更新按钮
|
|
||||||
\`);
|
|
||||||
|
|
||||||
// 移除页面知识
|
|
||||||
pageAgent.knowledge.removePageKnowledge("/products");`}
|
|
||||||
/>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -29,7 +29,7 @@ export default {
|
|||||||
limitations: 'Limitations',
|
limitations: 'Limitations',
|
||||||
model_integration: 'Model Integration',
|
model_integration: 'Model Integration',
|
||||||
custom_tools: 'Custom Tools',
|
custom_tools: 'Custom Tools',
|
||||||
knowledge_injection: 'Knowledge Injection',
|
knowledge_injection: 'Instructions',
|
||||||
security_permissions: 'Security & Permissions',
|
security_permissions: 'Security & Permissions',
|
||||||
data_masking: 'Data Masking',
|
data_masking: 'Data Masking',
|
||||||
cdn_setup: 'CDN Setup',
|
cdn_setup: 'CDN Setup',
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export default {
|
|||||||
limitations: '使用限制',
|
limitations: '使用限制',
|
||||||
model_integration: '模型接入',
|
model_integration: '模型接入',
|
||||||
custom_tools: '自定义工具',
|
custom_tools: '自定义工具',
|
||||||
knowledge_injection: '知识库注入',
|
knowledge_injection: '知识注入',
|
||||||
security_permissions: '安全与权限',
|
security_permissions: '安全与权限',
|
||||||
data_masking: '数据脱敏',
|
data_masking: '数据脱敏',
|
||||||
cdn_setup: 'CDN 引入',
|
cdn_setup: 'CDN 引入',
|
||||||
|
|||||||
@@ -64,6 +64,15 @@ export default function HomePage() {
|
|||||||
interactiveBlacklist: [document.getElementById('root')!],
|
interactiveBlacklist: [document.getElementById('root')!],
|
||||||
language: i18n.language as any,
|
language: i18n.language as any,
|
||||||
|
|
||||||
|
instructions: {
|
||||||
|
system: 'You are a helpful assistant on PageAgent website.',
|
||||||
|
getPageInstructions: (url) => {
|
||||||
|
const hint = url.includes('page-agent') ? 'This is PageAgent demo page.' : undefined
|
||||||
|
console.log('[instructions] getPageInstructions:', url, '->', hint)
|
||||||
|
return hint
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
// experimentalScriptExecutionTool: true,
|
// experimentalScriptExecutionTool: true,
|
||||||
|
|
||||||
// testing server
|
// testing server
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import { Route, Switch } from 'wouter'
|
|||||||
|
|
||||||
import DocsLayout from './components/DocsLayout'
|
import DocsLayout from './components/DocsLayout'
|
||||||
import Header from './components/Header'
|
import Header from './components/Header'
|
||||||
|
import Instructions from './docs/features/custom-instructions/page'
|
||||||
// Features pages
|
// Features pages
|
||||||
import CustomTools from './docs/features/custom-tools/page'
|
import CustomTools from './docs/features/custom-tools/page'
|
||||||
import DataMasking from './docs/features/data-masking/page'
|
import DataMasking from './docs/features/data-masking/page'
|
||||||
import KnowledgeInjection from './docs/features/knowledge-injection/page'
|
|
||||||
import ModelIntegration from './docs/features/model-integration/page'
|
import ModelIntegration from './docs/features/model-integration/page'
|
||||||
import SecurityPermissions from './docs/features/security-permissions/page'
|
import SecurityPermissions from './docs/features/security-permissions/page'
|
||||||
import BestPractices from './docs/integration/best-practices/page'
|
import BestPractices from './docs/integration/best-practices/page'
|
||||||
@@ -80,11 +80,11 @@ export default function Router() {
|
|||||||
</div>
|
</div>
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path="/docs/features/knowledge-injection">
|
<Route path="/docs/features/custom-instructions">
|
||||||
<div className="min-h-screen bg-white dark:bg-gray-900">
|
<div className="min-h-screen bg-white dark:bg-gray-900">
|
||||||
<Header />
|
<Header />
|
||||||
<DocsLayout>
|
<DocsLayout>
|
||||||
<KnowledgeInjection />
|
<Instructions />
|
||||||
</DocsLayout>
|
</DocsLayout>
|
||||||
</div>
|
</div>
|
||||||
</Route>
|
</Route>
|
||||||
|
|||||||
Reference in New Issue
Block a user