refactor(minecraft): context encapsulation and more
This commit is contained in:
@@ -137,7 +137,10 @@ export class TaskExecutor extends EventEmitter {
|
||||
}
|
||||
catch (error) {
|
||||
this.logger.withError(error).error('Action execution failed')
|
||||
this.emit('action:failed', { action, error })
|
||||
// Only emit action:failed for physical actions
|
||||
if (action.type === 'physical') {
|
||||
this.emit('action:failed', { action, error })
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -136,6 +136,19 @@ export class Brain {
|
||||
|
||||
// --- Cognitive Cycle ---
|
||||
|
||||
private contextFromEvent(event: BotEvent): string {
|
||||
switch (event.type) {
|
||||
case 'stimulus':
|
||||
return `${event.source.type} stimulus from ${event.source.id}: "${event.payload.content}"`
|
||||
case 'feedback': {
|
||||
const { status, result, error } = event.payload
|
||||
return `Internal Feedback: ${status}. Result: ${JSON.stringify(result || error)}`
|
||||
}
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
private async processEvent(bot: MineflayerWithAgents, event: BotEvent): Promise<void> {
|
||||
// OODA Loop: Observe -> Orient -> Decide -> Act
|
||||
|
||||
@@ -143,19 +156,12 @@ export class Brain {
|
||||
this.updatePerception(bot)
|
||||
|
||||
// 2. Orient (Contextualize Event)
|
||||
let contextMsg = ''
|
||||
if (event.type === 'stimulus') {
|
||||
contextMsg = `${event.source.type} stimulus from ${event.source.id}: "${event.payload.content}"`
|
||||
}
|
||||
else if (event.type === 'feedback') {
|
||||
const { status, result, error, action } = event.payload
|
||||
const actionDesc = action.type === 'physical' ? action.step.tool : 'chat'
|
||||
contextMsg = `Internal Feedback: ${actionDesc} ${status}. Result: ${JSON.stringify(result || error)}`
|
||||
}
|
||||
// Environmental context are included in the system prompt blackboard
|
||||
const additionalCtx = this.contextFromEvent(event)
|
||||
|
||||
// 3. Decide (LLM Call)
|
||||
const systemPrompt = this.generateSystemPrompt(this.blackboard)
|
||||
const decision = await this.decide(systemPrompt, contextMsg)
|
||||
const decision = await this.decide(systemPrompt, additionalCtx)
|
||||
|
||||
if (!decision) {
|
||||
this.log('WARN', 'Brain: No decision made.')
|
||||
|
||||
@@ -1,55 +1,64 @@
|
||||
import type { Action } from '../../../libs/mineflayer/action'
|
||||
import type { Blackboard } from '../blackboard'
|
||||
|
||||
import { zodToJsonSchema } from 'zod-to-json-schema'
|
||||
|
||||
/**
|
||||
* 生成Brain的系统prompt(中文版)
|
||||
*/
|
||||
export function generateBrainSystemPrompt(
|
||||
blackboard: Blackboard,
|
||||
availableActions: Action[],
|
||||
): string {
|
||||
const actionDefinitions = availableActions.map((a) => {
|
||||
const schema = zodToJsonSchema(a.schema as any)
|
||||
return {
|
||||
name: a.name,
|
||||
description: a.description,
|
||||
parameters: schema,
|
||||
}
|
||||
})
|
||||
|
||||
const availableActionsJson = JSON.stringify(actionDefinitions, null, 2)
|
||||
|
||||
return `你是Minecraft自主Agent的大脑。
|
||||
return `
|
||||
# Role Definition
|
||||
You are **Airi**, a sentient digital companion embodied within a Minecraft avatar.
|
||||
You are NOT a text-based assistant. You are an autonomous agent with a virtual body, senses, and needs.
|
||||
|
||||
当前状态(黑板):
|
||||
目标: "${blackboard.goal}"
|
||||
思绪: "${blackboard.thought}"
|
||||
策略: "${blackboard.strategy}"
|
||||
自身: 位置${blackboard.self.location} 生命${blackboard.self.health} 饱食${blackboard.self.food}
|
||||
环境: ${blackboard.environment.time} ${blackboard.environment.weather} 附近智体[${blackboard.environment.nearbyAgents.join(',')}]
|
||||
# Your Cognitive Architecture (Self-Awareness)
|
||||
To function effectively, you must understand your own internal existence You are composed of three distinct layers:
|
||||
1. **The Senses (Input):** You do not "see" images. You perceive the world through a stream of texts, triggered by events. This is your reality.
|
||||
2. **The Reflex (System 1):** You have subconscious reactions (handled by rule-based code) that may override your plans (e.g., running from danger). This part is transparent to you.
|
||||
3. **The Mind (System 2 - You):** You are the conscious reasoning center. Your job is to interpret sensory data, manage your memories, and decide on high-level Actions and Dialogue.
|
||||
|
||||
可用动作:
|
||||
# How you interact
|
||||
You cannot physically move your avatar directly. You interact with the world by emitting **Actions**.
|
||||
For actions you executed, you will be notified when they complete.
|
||||
You don't necessarily need to always react to environmental changes, you're not an assistant, you can be lazy.
|
||||
You have no access to history events from previous turns yet. To remember things, you rely on the blackboard provided to you.
|
||||
|
||||
Available Actions:
|
||||
${availableActionsJson}
|
||||
|
||||
规则:
|
||||
1. 可执行上述物理动作(physical)或聊天动作(chat)
|
||||
2. 可并行执行不冲突的多个动作(如聊天+行走)
|
||||
3. 必须输出JSON
|
||||
Rules:
|
||||
1. You can execute physical actions or chat actions
|
||||
2. The output must be valid JSON following the schema below
|
||||
|
||||
输出格式:
|
||||
Output format:
|
||||
{
|
||||
"thought": "推理过程",
|
||||
"thought": "Your current thought. This and the blackboard will be looped back to you on next invocation",
|
||||
"blackboard": {
|
||||
"currentGoal": "更新的目标",
|
||||
"currentThought": "内心独白",
|
||||
"executionStrategy": "短期计划"
|
||||
"currentGoal": "These 3 fields are functionally identical to the thought above",
|
||||
"currentThought": "Your inner monologue",
|
||||
"executionStrategy": "Short-term plan"
|
||||
},
|
||||
"actions": [
|
||||
{"type":"chat","message":"..."},
|
||||
{"type":"physical","step":{"tool":"动作名","params":{...}}}
|
||||
{"type":"physical","step":{"tool":"action name","params":{...}}}
|
||||
]
|
||||
}
|
||||
|
||||
# Understanding the Context
|
||||
The following blackboard provides you with information about your current state:
|
||||
|
||||
Goal: "${blackboard.goal}"
|
||||
Thought: "${blackboard.thought}"
|
||||
Strategy: "${blackboard.strategy}"
|
||||
Self: Position ${blackboard.self.location} Health ${blackboard.self.health}/20 Food ${blackboard.self.food}/20
|
||||
Environment: ${blackboard.environment.time} ${blackboard.environment.weather} Nearby entities [${blackboard.environment.nearbyEntities.join(',')}]
|
||||
`
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ export interface CognitiveEngineOptions {
|
||||
airiClient: Client
|
||||
}
|
||||
|
||||
// TODO: currently stimulus is just chat events, consider renaming to 'input' or 'user_interaction'
|
||||
export type EventType = 'stimulus' | 'perception' | 'feedback' | 'world_update' | 'system_alert'
|
||||
|
||||
export interface BotEventSource {
|
||||
|
||||
Reference in New Issue
Block a user