- ç®åœ
- 1. æ žå¿äº§åé»èŸ (Core Product Logic)
- 2. æ¶æåŸ
- 3. æ žå¿ç»ä»¶è®Ÿè®¡
- 4. æšçæš¡åŒéå
- 5. åœä»€æ©å±
- 6. æ°æ®æš¡å
- 7. Agent æ§è¡è§çºŠ (Execution Rules)
- 8. åžžè§é·é±æ£æ¥æž å (Checklist)
- 9. éªæ¶æ å
- 10. è¿çšæšç任塿å [agent-task]
- 11. æ¶ææŒè¿è·¯çº¿åŸ
- 12. éåœïŒåèææ¡£
langchain4android Agent æ¶æè®Ÿè®¡
çæ¬ïŒ4.0ïŒåå¹¶çïŒ
ç¶æïŒå·²å®æœ / è¿ä»£äž
æåæŽæ°ïŒ2026-07-08
äž»èŠç»Žæ€è ïŒ[RD] å šæ å·¥çšåž
åå²å并诎æïŒæ¬ææ¡£ç±AGENT_ARCHITECTURE.mdäžREMOTE_INFERENCE_ARCHITECTURE.mdåå¹¶èæãè¿çšæšççžå ³ç OpenAI åè®®ãlangchain4j æ ååãDeepSeek éé ãå屿š¡åãæ§èœææ¬äžéªæ¶æ åå·²å¹¶å ¥âæšçæš¡åŒéåâäžâè¿çšæšçâç« èïŒåREMOTE_INFERENCE_ARCHITECTURE.mdå·²å é€ã
蟹ç声æïŒBoundary StatementïŒ - æ¬ææ¡£å®ä¹ Agent çè¿è¡æ¶æ¶æãCapability æš¡åäžæšçæš¡åŒéåã - 产åç®æ äžéªæ¶å£åŸä»¥
../01-PRODUCT/FEATURES.md䞺åã - 顶屿²»çè§åïŒè§è²åäœãå šå±çº¢çº¿ãææ¡£æµçšïŒä»¥æ ¹ç®åœAGENTS.md䞺åã - éèŠïŒ:agent-coreæ¯ Java åºç¡åºïŒChatModelãToolãAiServicesïŒïŒAgent çŒæå±ïŒAgentOrchestratorãCapabilityRegistryãPrivacyGuardãMemoryManagerãSceneManager çïŒåš:runtime-coreæš¡åçruntime-core/src/main/java/com/mamba/picme/agent/core/ç®åœäžã诊è§MODULE_ARCHITECTURE.mdã
æš¡åå®äœ: AI Agent è¿è¡æ¶æ¶æäžæšçæš¡åŒéåïŒåºç¡åº langchain4android + Demo å·¥çš PicMeïŒ
é
读对象: RDãAI Agent
ç®åœ
- æ žå¿äº§åé»èŸ
- æ¶æåŸ
- æ žå¿ç»ä»¶è®Ÿè®¡
- æšçæš¡åŒéå
- åœä»€æ©å±
- æ°æ®æš¡å
- æ§è¡è§çºŠ
- åžžè§é·é±æ£æ¥æž å
- éªæ¶æ å
- è¿çšæšç任塿å
- æ¶ææŒè¿è·¯çº¿åŸ
- éåœïŒåèææ¡£
1. æ žå¿äº§åé»èŸ (Core Product Logic)
1.1 红线纊æ
| 纊æ | å®ä¹ | éªè¯æ¹åŒ |
|---|---|---|
| [PRIVACY] | æææ°æ®äŒå æ¬å°æšçïŒç¡®éäºç«¯å€çæ¶ïŒå¿ é¡»è·åŸçšæ·ææäžäžåŸçå | PrivacyGuard æŠæªæ°æ®æµ + æææµçšå®¡è®¡ |
| [PERF] | 亀äºåéŠ < 100msïŒLLM æšçåå°å®æ | 端䟧 Qwen3.5-2B éŠ token ç®æ < 600ms |
| [I18N] | System Prompt åçšæ·å¯è§åå€çŠæ¢ç¡¬çŒç äžæ | æ¥å ¥ string èµæº |
| [OFFLINE] | æ¬å°æš¡åæªäžèœœæ¶æäŸæç¡®åŒå¯Œ | ééé»å€±èŽ¥ |
| [TYPE_SAFE] | AgentCommand / AgentAction å¿ é¡»äœ¿çš Sealed Class | çŠæ¢åç¬Šäž²éæ³åŒ |
1.2 åœåæ¶ææš¡åŒïŒADR-005 åïŒ
æ¬å°éŸè·¯ïŒå蜮 Function CallingïŒèªå®ä¹ JSON æ°ç»åè®®ïŒ
è¿çšéŸè·¯ïŒæ å OpenAI Chat Completions APIïŒåç tool_calls + æµåŒ + å€èœ®å¯¹è¯ïŒ
䞀æ¡éŸè·¯å®å šç¬ç«ïŒæ å ±äº«è·¯ç±é»èŸã
çšæ·èŸå
¥ â AgentOrchestrator.dispatch() â æš¡åŒéæ©
âââ LOCAL â LocalInferencePipeline â LocalLlmEngine â JSON æ°ç»è§£æ â Capability æ§è¡
âââ REMOTE â RemoteInferencePipeline â RemoteOrchestrator â OpenAI tool_calls â Capability æ§è¡
æ žå¿ç»ä»¶ç¶æ:
| ç»ä»¶ | è莣 | ç¶æ |
|---|---|---|
AgentOrchestrator |
ç»äžå ¥å£ïŒç®¡çæ¬å°/è¿çšäž€æ¡ç¬ç«æšçéŸè·¯ | â å·²èœå° |
LocalInferencePipeline |
æ¬å°æšçéŸè·¯ïŒL1 Cache + L2 BatchïŒèªå®ä¹ JSON æ°ç»åè®®ïŒ | â å·²èœå° |
RemoteInferencePipeline |
è¿çšæšçéŸè·¯ïŒOpenAI Chat Completions APIïŒtool_calls·æµåŒÂ·å€èœ®ïŒ | â å·²èœå° |
LocalLlmEngine |
å°è£ MNN-LLM 客æ·ç«¯ïŒQwen3.5-2B æ¬å°æšç | â å·²èœå° |
RemoteOrchestrator |
è¿çšæšççŒæïŒ:agent-core OpenAiChatModel + ChatMemory | â å·²èœå° |
:agent-core (æš¡å) |
Java Android LibraryïŒæäŸ LangChain4j 飿 Œ APIïŒChatModelã@ToolãAiServicesãChatMemoryãOpenAiChatModelãOkHttp SSE æµåŒå®¢æ·ç«¯ | â å·²èœå° |
CapabilityRegistry |
Capability 泚åäžåœä»€åå | â å·²èœå° |
PrivacyGuard |
èŸå ¥å 容éç§åçº§äžæ¬å°äŒå 纊æ | â å·²èœå° |
MemoryManager |
DataStore æä¹ å对è¯åå²ïŒæ session é犻 | â å·²èœå° |
KeywordSpotterEngine |
KWS åžžé©»äœåèå€éè¯æ£æµïŒSherpa-ONNXïŒ~14MBïŒ | â å·²èœå° |
SherpaOnnxAsrEngine |
ASR æéå 蜜è¯é³èœ¬åœïŒSherpa-ONNXïŒ~282MBïŒ | â å·²èœå° |
FeishuRemoteChannel |
é£ä¹Š WebSocket çŽè¿ïŒIM è¿çšæ§å¶å ¥å£ | ð è¿ä»£äž |
IntentCache |
L1 è¿çšæåŸçŒåïŒé«é¢æä»€çŽæ¥è¿å | â å·²èœå° |
已移é€ç»ä»¶ïŒADR-005/006ïŒ2026-06ïŒïŒ - InferenceRouter â æå䞺 LocalInferencePipeline + RemoteInferencePipeline 䞀æ¡ç¬ç«éŸè·¯ - ToolCallingChatLanguageModel â è¿çšçŽæ¥äœ¿çš langchain4j åç OpenAiChatModel - ToolCallingOutputParser â è¿çšäœ¿çšæ å OpenAI tool_calls ååºæ ŒåŒ - ToolPromptBuilder â æå䞺 LocalPromptBuilder + RemotePromptBuilder - AdaptiveStrategySelector â æ¬å°äžåéèŠçç¥å级 - ToolOrchestrator â çŒæé»èŸåå¹¶å
¥ RemoteOrchestrator - SherpaMnnAsrEngine + com.k2fsa.sherpa.mnn.* â å·²è¿ç§»è³ Sherpa-ONNXïŒSherpaOnnxAsrEngineïŒ - MnnAsrClient â å äœæ»ä»£ç ïŒåæ¥ç§»é€ - å
±æž
ç ~2,600 è¡åäœä»£ç
2. æ¶æåŸ
2.1 ç³»ç»å 𿝿¶æ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â UI Layer (Compose) â
â â
â âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ â
â â ChatScreen â â GalleryScreen â â CameraScreen â â
â â ð é»è®€éŠé¡µ â â ðž æºèœçžå â â ð· èŸ
å©å
¥å£ â â
â â AI对è¯Â·æš¡å忢 â â åªäœæµè§Â·AIæçŽ¢ â â çŸé¢Â·æ»€é·è¯é³ â â
â ââââââââââ¬âââââââââ ââââââââââ¬âââââââââ ââââââââââ¬âââââââââ â
â â â â â
â ââââââââââââââââââââââŒâââââââââââââââââââââ â
â ⌠â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â GlobalAgentPanel / AiAgentUseCase (Facade) â â
â â ââââââââââââ ââââââââââââ ââââââââââââ ââââââââââââ ââââââââââââ â â
â â â Chat UI â âVoice Btn â âQuickActs â âModel Sel â âStatusBar â â â
â â â(å€çº¿çš) â â(KWSå€é) â â(å¿«æ·å
¥å£) â â(æ¬å°/è¿çš)â â(æšçç¶æ) â â â
â â ââââââââââââ ââââââââââââ ââââââââââââ ââââââââââââ ââââââââââââ â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âŒ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Agent Orchestration Layer (:app · Kotlin) â
â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â AgentOrchestrator (çŒæåš) â â
â â ââââââââââââââ ââââââââââââââ ââââââââââââââ ââââââââââââââ â â
â â âSceneManagerâ âPrivacyGuardâ âMemoryManagerâ âIntentCache â â â
â â â(åºæ¯æç¥) â â(éç§å级) â â(å¯¹è¯æä¹
å) â â(L1è¿çšçŒå) â â â
â â ââââââââââââââ ââââââââââââââ ââââââââââââââ ââââââââââââââ â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â â â
â LOCAL modeâ âREMOTE mode â
â ⌠⌠â
â ââââââââââââââââââââââââââââââ ââââââââââââââââââââââââââââââââââââââââ â
â â LocalInferencePipeline â â RemoteInferencePipeline â â
â â ââââââââââââââââââââââââ â â ââââââââââââââââââââââââââââââââââ â â
â â â LocalLlmEngine â â â â RemoteOrchestrator â â â
â â â Qwen3.5-2B (MNN) â â â â :agent-core OpenAiChatModel â â â
â â â L1 Cache â L2 Batch â â â â OpenAI Chat Completions API â â â
â â ââââââââââââââââââââââââ â â â DeepSeek V4 éé
â â â
â ââââââââââââââââââââââââââââââ â â L2 Batch / L3 Plan / L4 Chat â â â
â â ââââââââââââââââââââââââââââââââââ â â
â ââââââââââââââââââââââââââââ â â â
â â Voice Pipeline (ONNX) â â ââââââââââââââââââââââââââââââââââ â â
â â ââââââââââââââââââââââ â â â FeishuRemoteChannel â â â
â â âKeywordSpotterEngineâ â â â é£ä¹Š WebSocket çŽè¿ â â â
â â â KWS always-on â â â â IMæ¶æ¯âAgentCommand â â â
â â â ~14MB · 50mW â â â â æç
§åäŒ Â·è®Ÿå€ç»å®Â·ç¡®è®€æºå¶ â â â
â â âââââââââââ¬âââââââââââ â â ââââââââââââââââââââââââââââââââââ â â
â â â å€é â â â â
â â âââââââââââŒâââââââââââ â â ââââââââââââââââââââââââââââââââââ â â
â â âSherpaOnnxAsrEngine â â â â Cloudflare AI Gateway â â â
â â â ASR on-demand â â â â API Key ä¿æ€ · éçéå¶ â â â
â â â ~282MB · æéå 蜜 â â â â DeepSeek / Claude 倿š¡åè·¯ç± â â â
â â ââââââââââââââââââââââ â â ââââââââââââââââââââââââââââââââââ â â
â ââââââââââââââââââââââââââââ ââââââââââââââââââââââââââââââââââââââââ â
â â â
â ⌠â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â CapabilityRegistry (èœå泚å衚) â â
â â â â
â â ââââââââââââ ââââââââââââ ââââââââââââ ââââââââââââ ââââââââââââ â â
â â â Camera â â Gallery â â Settings â â Navigate â â Editor â â â
â â âæç
§/åœå â âæ¥ç/å é€ â âäž»é¢/è¯èš â â页é¢åæ¢ â âåŸççŒèŸ â â â
â â âçŸé¢/滀é â âå享/æçŽ¢ â âæš¡å管ç â âè¿å/éåº â âAI äŒå â â â
â â âåçŠ/æå
â âæ¹éæäœ â âè¯é³é
眮 â â â â â â â
â â ââââââââââââ ââââââââââââ ââââââââââââ ââââââââââââ ââââââââââââ â â
â â ââââââââââââ â â
â â â IMRemote â é£ä¹Šè¿çšæ§å¶ · 讟å€ç»å® · åœä»€ç¡®è®€ â â
â â ââââââââââââ â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âŒ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Domain / Data / Infra â
â â
â ââââââââââââââ ââââââââââââââââ ââââââââââââââââ ââââââââââââââââââââââââ â
â âMediaRepo â âSettingsRepo â â BeautyEngine â â MNN-LLM (æ¬å°æš¡å) â â
â â(Room DB) â â(DataStore) â â (OpenGL ES) â â Qwen3.5-2B · 端䟧æšç â â
â ââââââââââââââ ââââââââââââââââ ââââââââââââââââ ââââââââââââââââââââââââ â
â â
â ââââââââââââââââââââââââ ââââââââââââââââââââââââ ââââââââââââââââââââââââ â
â â :agent-core (SDK) â âLlmModelDownloadManagerâ â FaceDetect Pipeline â â
â â Java Library â âåå°æå¡Â·æç¹ç»äŒ â â MediaPipe·MNN â â
â â ChatModel·@Tool â ââââââââââââââââââââââââ ââââââââââââââââââââââââ â
â â AiServices·SSE â ââââââââââââââââââââââââ â
â ââââââââââââââââââââââââ â Network Monitor â â
â â é£ä¹Šéè¿Â·å¿è·³ä¿æ â â
â ââââââââââââââââââââââââ â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
2.2 æšçéŸè·¯æ°æ®æµïŒADR-005 åïŒ
çšæ·èŸå
¥ "æŸåºå»å¹Žå€å€©çç
§ç" / "磚ç®50"
â
âŒ
AgentOrchestrator.dispatch(input)
â
âââ PrivacyGuard.assess(input) â ææ? â åŒºå¶ LOCAL
â
âââ LOCAL mode (é»è®€ç«¯äŸ§æš¡å)
â â
â âââ IntentCache.lookup(input) â HIT? â çŽæ¥è¿å (L1)
â â
â âââ LocalLlmEngine.generate(messages)
â âââ MNN-LLM (Qwen3.5-2B) â JSON æ°ç»è§£æ â Capability æ§è¡
â
âââ REMOTE mode (çšæ·æåšåæ¢æéç§å
讞)
â
âââ IntentCache.lookup(input) â HIT? â çŽæ¥è¿å (L1)
â
âââ RemoteOrchestrator.chat(messages, tools)
âââ :agent-core (Java Library)
âââ OpenAiChatModel (ChatLanguageModel)
âââ ToolSpecification (tool_calls æå»º)
âââ OkHttp SSE Streaming (æµåŒååº)
âââ Cloudflare Gateway â DeepSeek / Claude API
â tool_calls è§£æ â Capability æ§è¡
2.3 è¯é³äº€äºç®¡çº¿ïŒSherpa-ONNX ååŒæïŒ
[äŒç æ] Always-on KWS (~14MB · 50mW)
â
â çšæ·è¯Ž"å°è§
æåŒ ç
§"
âŒ
KWS æ£æµå°å€éè¯ â æå KWS
â
âŒ
å 蜜 ASR (~282MB · ~500mW) â èœ¬åœ "æåŒ ç
§"
â
âŒ
AgentOrchestrator.dispatch("æåŒ ç
§") â Capability æ§è¡
â
âŒ
éæŸ ASR â æ¢å€ KWS always-on
3. æ žå¿ç»ä»¶è®Ÿè®¡
3.1 SceneManager åºæ¯ç®¡çåš
/**
* åºæ¯ç®¡çåš
*
* èŽèŽ£ïŒ
* 1. è·èžªåœå掻è·åºæ¯
* 2. æ ¹æ®åºæ¯è·å对åºç Capability éå
* 3. åšææå»ºåºæ¯çžå
³ç system prompt
*/
class SceneManager {
enum class Scene {
GALLERY, // çžåéŠé¡µïŒé»è®€ïŒ
CHAT, // AI 对è¯äºçº§é¡µ
CAMERA, // çžæºé¡µ
SETTINGS, // 讟眮页
EDITOR, // çŒèŸé¡µ
DEBUG // è°è¯é¡µ
}
private val _currentScene = MutableStateFlow(Scene.GALLERY)
val currentScene: StateFlow<Scene> = _currentScene.asStateFlow()
fun transitionTo(scene: Scene) {
_currentScene.value = scene
}
/**
* è·ååºæ¯å¯¹åºç Capability å衚
*/
fun getCapabilitiesForScene(scene: Scene): List<String> = when (scene) {
Scene.GALLERY -> listOf("gallery", "editor", "navigation")
Scene.CHAT -> listOf("chat", "navigation", "gallery", "editor")
Scene.CAMERA -> listOf("camera", "navigation")
Scene.SETTINGS -> listOf("settings", "navigation")
Scene.EDITOR -> listOf("edit", "navigation")
Scene.DEBUG -> listOf("navigation")
}
}3.2 åå± Prompt æå»ºåšïŒADR-005 åïŒ
æ¬å°åè¿çšäœ¿çšç¬ç«ç Prompt æå»ºåšïŒ
// æ¬å° Prompt â 粟ç®ãç»æå
class LocalPromptBuilder {
fun buildSystemPrompt(capabilities: List<Capability>, context: AgentContext): String = """
äœ æ¯ PicMe AI 婿ïŒè¿è¡åšç«¯äŸ§è®Ÿå€ã
è¯·æ ¹æ®çšæ·èŸå
¥ïŒèŸåº JSON æ°ç»æ ŒåŒçåœä»€ã
å¯çšåœä»€ïŒ
${capabilities.joinToString("\n") { "- ${it.name}: ${it.description}" }}
èŸåºæ ŒåŒïŒ
[{"method":"åœä»€åç§°","args":{"åæ°å":åŒ}}]
åŠææ æ³çè§£ïŒèŸåºïŒ{"method":"text_reply","args":{"text":"åå€å
容"}}
""".trimIndent()
}
// è¿çš Prompt â æ å OpenAI åè®®æ ŒåŒ
// éè¿ langchain4j æå»º ChatRequestïŒSDK èªåšåºåå䞺 OpenAI Chat Completions 请æ±äœ
class RemotePromptBuilder {
fun buildChatRequest(
systemPrompt: String,
userInput: String,
capabilities: List<Capability>
): ChatRequest {
val toolSpecs = capabilities.map { cap ->
ToolSpecification.builder()
.name(cap.name)
.description(cap.description)
.build()
}
return ChatRequest.builder()
.messages(
SystemMessage(systemPrompt),
UserMessage(userInput)
)
.toolSpecifications(toolSpecs)
.build()
// langchain4j èªåšåºåå䞺:
// POST /v1/chat/completions
// {"model":"...","messages":[...],"tools":[...]}
}
}3.3 Capability æ¥å£æ©å±
/**
* Capability æ¥å£ V2
*
* æ°å¢ïŒ
* - åºæ¯ç»å®ïŒå£°æè¯¥ Capability 掻è·çåºæ¯
* - äžäžææç¥ïŒæ¥æ¶é¡µé¢ç¹å®çäžäžææ°æ®
*/
interface Capability {
val name: String
val description: String
/**
* 该 Capability åšåªäºåºæ¯äžå¯çš
*/
fun activeScenes(): List<SceneManager.Scene>
fun supportedCommands(): List<String>
/**
* æ§è¡åœä»€
* @param command è§£æåçåœä»€
* @param context åœåäžäžæ
* @param pageContext 页é¢ç¹å®äžäžæïŒåŠ Gallery åœåéäžçç
§çïŒ
*/
suspend fun execute(
command: AgentCommand,
context: AgentContext,
pageContext: PageContext? = null
): Result<AgentAction>
}
/**
* 页é¢äžäžæïŒé¡µé¢ç¹å®ç¶æïŒ
*/
sealed class PageContext {
data class GalleryContext(
val currentMedia: MediaAsset?,
val selectedItems: List<MediaAsset>,
val isSelectionMode: Boolean
) : PageContext()
data class SettingsContext(
val currentCategory: String?
) : PageContext()
data class EditorContext(
val editingMedia: MediaAsset,
val hasUnsavedChanges: Boolean
) : PageContext()
object None : PageContext()
}3.4 GalleryCapability 瀺äŸ
/**
* çžåæ§å¶ Capability
*/
class GalleryCapability(
private val onViewMedia: ((MediaAsset) -> Unit)? = null,
private val onDeleteMedia: ((List<MediaAsset>) -> Unit)? = null,
private val onShareMedia: ((List<MediaAsset>) -> Unit)? = null,
private val onSelectMedia: ((MediaAsset, Boolean) -> Unit)? = null,
private val onSearch: ((String) -> Unit)? = null,
private val onSwitchViewMode: ((ViewMode) -> Unit)? = null
) : Capability {
override val name = "gallery"
override val description = "æ¥çãå é€ãå享ãæçŽ¢ç
§çåè§é¢"
override fun activeScenes() = listOf(SceneManager.Scene.GALLERY, SceneManager.Scene.CHAT)
override fun supportedCommands() = listOf(
"view_media",
"delete_media",
"share_media",
"select_media",
"search_media",
"switch_view",
"text_reply"
)
override suspend fun execute(
command: AgentCommand,
context: AgentContext,
pageContext: PageContext?
): Result<AgentAction> {
val galleryContext = pageContext as? PageContext.GalleryContext
return when (command) {
is AgentCommand.ViewMedia -> {
val media = command.mediaId?.let { findMediaById(it) }
?: galleryContext?.currentMedia
media?.let { onViewMedia?.invoke(it) }
Result.success(AgentAction.Success(command))
}
is AgentCommand.DeleteMedia -> {
val items = command.mediaIds.mapNotNull { findMediaById(it) }
.ifEmpty { galleryContext?.selectedItems ?: emptyList() }
onDeleteMedia?.invoke(items)
Result.success(AgentAction.Success(command))
}
else -> Result.success(AgentAction.Error("äžæ¯æçåœä»€"))
}
}
}3.5 NavigationCapability 瀺äŸ
/**
* å¯Œèª Capability
*
* åšææåºæ¯éœå¯çšïŒèŽèޣ页é¢åæ¢
*/
class NavigationCapability(
private val onNavigate: (Screen) -> Unit,
private val onBack: () -> Unit
) : Capability {
override val name = "navigation"
override val description = "页é¢å¯ŒèªïŒåæ¢é¡µé¢ãè¿åäžäžé¡µ"
override fun activeScenes() = SceneManager.Scene.entries.toList()
override fun supportedCommands() = listOf(
"navigate_to",
"go_back",
"text_reply"
)
override suspend fun execute(
command: AgentCommand,
context: AgentContext,
pageContext: PageContext?
): Result<AgentAction> {
return when (command) {
is AgentCommand.NavigateTo -> {
val screen = when (command.destination.lowercase()) {
"camera", "çžæº" -> Screen.Camera
"gallery", "çžå" -> Screen.Gallery
"settings", "讟眮" -> Screen.Settings
"editor", "çŒèŸ" -> Screen.Editor
"chat", "è倩" -> Screen.Chat
else -> return Result.success(AgentAction.Error("æªç¥é¡µé¢ïŒ${command.destination}"))
}
onNavigate(screen)
Result.success(AgentAction.Success(command))
}
is AgentCommand.GoBack -> {
onBack()
Result.success(AgentAction.Success(command))
}
else -> Result.success(AgentAction.Error("äžæ¯æç富èªåœä»€"))
}
}
}4. æšçæš¡åŒéå
4.1 æ¬å° vs è¿çšæšç
| 绎床 | æ¬å°æšç | è¿çšæšç |
|---|---|---|
| åè®® | èªå®ä¹ JSON æ°ç» | æ å OpenAI Chat Completions API |
| Library | æ ç¬¬äžæ¹äŸèµ | :agent-core (OpenAiChatModel) |
| Prompt | 粟ç®ãç»æå | èªç¶è¯èš + Tool Schema |
| èŸåºè§£æ | ç®å JSON æ°ç»è§£æ | æ å JSON ååºååïŒtool_callsïŒ |
| çºŠææ¹åŒ | JSON æ°ç»æ ŒåŒ Prompt 纊æ | OpenAI åçå议纊æ |
| è倩/é²è | éè¿ text_reply åœä»€å åº | åçæ¯æïŒæµåŒ + å€èœ®ïŒ |
| Strategy | L1 Cache / L2 Batch | L2 Batch / L3 Plan / L4 Chat |
| å»¶è¿ | < 600ms | 500ms-2s |
| éç§ | æææ°æ®æ¬å°å€çïŒå€ææšçå¯ç»çšæ·ææåäžäº | éæææ°æ®å 讞äžäº |
4.2 端䟧æšçæš¡åŒéåïŒQwen3.5-2BïŒ
äžæšèå®æŽ ReActïŒåå ïŒ - 2B æš¡å COTïŒéŸåŒæèïŒèœå匱ïŒThought 莚éäžçš³å® - AI 对è¯é¡µèŠæ± < 500ms éŠåå»¶è¿ïŒå€èœ®æšçæ æ³æ»¡è¶³ [PERF] 红线 - ç«¯äŸ§çµæ± /åçææ
端䟧èœå蟹çïŒ2026-06-12 éªè¯ïŒïŒ | èœå | ç«¯äŸ§æ¯æ | 诎æ | |ââ|âââ-|ââ| | åæ¡ Function Calling | å·²éªè¯ | æç¡®æåŸâJSON åœä»€ïŒåç¡®ç > 90% | | ç®å Batch FCïŒ2-3 æ¡ïŒ | éšåæ¯æ | JSON æ°ç»æ ŒåŒé区 prompt 纊æïŒå¶ææ ŒåŒé误 | | 倿ç»åæä»€ïŒå«æ¡ä»¶/å»¶è¿ïŒ | äžæ¯æ | è¶ åº 2B æš¡åçè§£èåŽïŒæç¡®èµ°è¿çš | | äžäžææšçïŒéåŒåŒçšïŒ | äžæ¯æ | âå亮äžç¹âç±»æä»€éè§åå åº | | åŒæŸåŒé²è | äžæ¯æ | çæèŽšéå·®ïŒåºè·¯ç±å°è¿çš L4 |
4.3 è¿çšæšçæš¡åŒéå
è¿çšæš¡åŒäžåå° LLM è°çšæ¬¡æ°æ¯ç«¯äŸ§æŽéèŠïŒRTT ææ¬äž»å¯ŒïŒã
æšèåå±èªéåºæš¡åŒïŒ
| å±çº§ | æš¡åŒ | éçšåºæ¯ | åè®® | èŸåºæ ŒåŒ | æ§è¡äœçœ® |
|---|---|---|---|---|---|
| Layer 1 | æ¬å°è§åçŒå | é«é¢æä»€åœäžçŒå | äžèµ° LLM | é¢å®ä¹åœä»€ | 端䟧 |
| Layer 2 | Batch Function Calling | ç®åè¿ç»åšäœæä»€ïŒ2-3 æ¥ïŒ | OpenAI Chat Completions + tool_calls | ToolExecutionRequest[] â AgentCommand[] |
è¿çš |
| Layer 3 | Plan-and-Execute | æ¡ä»¶/äŸèµ/倿¥éª€ | OpenAI Chat Completions + tool_calls | ExecutionPlan (å« command åæ®µ) |
è¿çšè§å + æ¬å°æ§è¡ |
| Layer 4 | æµåŒ Chat | åŒæŸåŒå¯¹è¯ãé²è | OpenAI Chat Completions (stream=true) | ææ¬æµ + å¯é tool_calls | è¿çš |
è¿çšäŒåçç¥ïŒ - è¿æ¥æ± + Keep-Alive å€çš TCP - 100ms 鲿çªå£åå¹¶è¯·æ± - 2s è¶ æ¶éçº§å°æ¬å°è§åæææ¬æç€º - åžžè§æåŸååºçŒåïŒLruCacheïŒ - éç§åçº§ïŒæææ°æ®ïŒäººèž/对è¯å 容ïŒåŒºå¶æ¬å°ïŒéæææä»€ïŒå€©æ°/éçšé²èïŒå 讞è¿çš
4.4 è¿çšæšçåè®®å®ç°
è¿çšæšçäœ¿çšæ å OpenAI Chat Completions API æ ŒåŒïŒ
è¯·æ±æ ŒåŒïŒ
POST /v1/chat/completions
{
"model": "deepseek-chat",
"messages": [
{"role": "system", "content": "..."},
{"role": "user", "content": "åž®æäŒåè¿åŒ ç
§ç"}
],
"tools": [
{
"type": "function",
"function": {
"name": "ai_optimize",
"description": "AI äžé®äŒååŸç",
"parameters": {
"type": "object",
"properties": {...},
"required": [...],
"additionalProperties": false
}
}
}
],
"tool_choice": "required",
"stream": false
}ååºæ ŒåŒïŒtool_callsïŒïŒ
{
"choices": [{
"message": {
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call_xxx",
"type": "function",
"function": {
"name": "ai_optimize",
"arguments": "{\"image_id\": \"img_123\"}"
}
}]
}
}]
}å
³é®è§åïŒ - tool_calls æ¯ message 对象çç¬ç«å段ïŒäž content äºæ¥ - åœååš tool_calls æ¶ïŒcontent å¿
须䞺 null - åæ°éè¿ function.arguments äŒ éïŒäžºæ å JSON å笊䞲
langchain4j æ ååå®ç°ïŒ
class RemoteOrchestrator(config: RemoteModelConfig) {
private val openAiChatModel = OpenAiChatModel.builder() // :agent-core
.baseUrl(config.baseUrl)
.apiKey(config.apiKey)
.modelName(config.modelId)
.temperature(config.temperature)
.maxTokens(config.maxTokens)
.build()
fun chat(request: ChatRequest): ChatResponse {
// çŽæ¥äœ¿çš :agent-core OpenAiChatModelïŒæ¯æ tool_callsãæµåŒãå€èœ®
}
}è¿çšæšççŽæ¥äœ¿çš :agent-core OpenAiChatModelïŒæ¯æææå
Œå®¹ OpenAI API çæå¡ïŒDeepSeekãéä¹åé®çïŒïŒéè¿ AiServices 代çæå»ºåš + ChatMemory å®ç°å€èœ®å¯¹è¯ã
åœä»€è§£æïŒToolCallCommandParserïŒïŒ
object ToolCallCommandParser {
fun parse(request: ToolExecutionRequest, context: AgentContext): AgentCommand {
val name = request.name() // å·¥å
·å â åœä»€ç±»åæ å°
val args = request.arguments() // æ å JSON åæ°
return when (name) {
"switch_filter" -> AgentCommand.SwitchFilter(filterType = parseFilterType(args))
"adjust_beauty" -> AgentCommand.AdjustBeauty(settings = parseBeautySettings(args))
// ... å
¶ä»åœä»€
else -> AgentCommand.TextReply("æªç¥åœä»€: $name")
}
}
}è¿çšè§£æåšäžæ¬å°è§£æåšå®å
šéçŠ»ïŒ - è¿çšïŒToolCallCommandParser â è§£æ name + arguments â AgentCommand - æ¬å°ïŒLocalCommandParser â è§£æ method + params â AgentCommand
4.5 DeepSeek éé
| éé 项 | å®ç° | äœçœ® |
|---|---|---|
| çŠçš thinking | API 请æ±èªåšéå thinking: {"type": "disabled"} |
OpenAiChatModel å
éšå€ç |
| strict æš¡åŒå Œå®¹ | ToolSpec èªåšæ·»å additionalProperties: false |
OpenAiChatModel å
éšå€ç |
| tool_choice ä¿®å€ | REQUIRED æ£ç¡®æ å°äžº "required"ïŒé "auto"ïŒ |
OpenAiChatModel å
éšå€ç |
| content åéè§£æ | åœ API æªè¿å tool_calls äœ content å« tool_calls JSON æ¶ïŒæ£åæåè§£æ | RemoteOrchestrator.parseFallbackToolCalls() |
| Prompt è§è | çŠæ¢åš Prompt äžæäŸå ·äœ tool_calls JSON 瀺äŸïŒé¿å æš¡åèŸåºå° content | RemotePromptBuilder |
4.6 æ§èœäžææ¬èé
Token æ¶è䌰ç®ïŒ
| æš¡åŒ | System Prompt | User Input | Output | 忬¡æ» Token |
|---|---|---|---|---|
| L1 Cache | 0 | 0 | 0 | 0 |
| L2 Batch | ~800 | ~50 | ~200 | ~1050 |
| L3 Plan | ~1000 | ~100 | ~500 | ~1600 |
| L4 Chat | ~800 | ~50 | ~300 | ~1150 |
å»¶è¿äŒ°ç®ïŒ
| æš¡åŒ | çœç» RTT | LLM çæ | è§£æ | æ»å»¶è¿ |
|---|---|---|---|---|
| L1 | 0 | 0 | 0 | < 10ms |
| L2 | 200-500ms | 200-500ms | 50ms | 450-1050ms |
| L3 | 200-500ms | 500-1000ms | 100ms | 800-1600ms |
| L4 (æµåŒ) | 200-500ms | éŠ token 50-200ms | 50ms | 250-750ms |
äŒåçç¥ïŒ 1. L1 çŒåé¢çïŒå¯åšæ¶é¢çœ® 50+ é«é¢æåŸ 2. L2 é»è®€åïŒ80% åºæ¯èµ° L2ïŒä¿æç®å髿 3. L3 åŒæ¥æ§è¡ïŒè®¡åçæååŒæ¥æ§è¡ïŒäžé»å¡ UI 4. L4 æµåŒïŒéŠ token äœå»¶è¿ïŒæå对è¯äœéª 5. è¿æ¥æ± + Keep-AliveïŒå€çš TCP è¿æ¥
5. åœä»€æ©å±
/**
* Agent åœä»€ V2
*
* æ°å¢ GalleryãSettingsãNavigationãEdit çžå
³åœä»€
*/
sealed class AgentCommand {
// ===== çžæºåœä»€ïŒå·²æïŒ=====
data class AdjustBeauty(val settings: BeautySettings) : AgentCommand()
data class SwitchFilter(val filterType: FilterType) : AgentCommand()
// ... å
¶ä»çžæºåœä»€
// ===== Gallery åœä»€ïŒæ°å¢ïŒ=====
data class ViewMedia(val mediaId: String? = null) : AgentCommand()
data class DeleteMedia(val mediaIds: List<String> = emptyList()) : AgentCommand()
data class ShareMedia(val mediaIds: List<String> = emptyList()) : AgentCommand()
data class SelectMedia(val mediaId: String, val selected: Boolean) : AgentCommand()
data class SearchMedia(val query: String) : AgentCommand()
data class SwitchViewMode(val mode: ViewMode) : AgentCommand()
// ===== 讟眮åœä»€ïŒæ°å¢ïŒ=====
data class ChangeTheme(val theme: ThemeMode) : AgentCommand()
data class ChangeLanguage(val language: AppLanguage) : AgentCommand()
data class DownloadModel(val modelId: String) : AgentCommand()
data class SwitchFaceEngine(val engine: FaceDetectionEngineMode) : AgentCommand()
data class ToggleSetting(val settingKey: String, val enabled: Boolean) : AgentCommand()
// ===== 富èªåœä»€ïŒæ°å¢ïŒ=====
data class NavigateTo(val destination: String) : AgentCommand()
object GoBack : AgentCommand()
// ===== çŒèŸåœä»€ïŒæ°å¢ïŒ=====
data class ApplyEdit(val editType: String, val params: Map<String, Any>) : AgentCommand()
object SaveEdit : AgentCommand()
object UndoEdit : AgentCommand()
// ===== éçšåœä»€ =====
data class TextReply(val message: String) : AgentCommand()
data class Unknown(val raw: String) : AgentCommand()
data class Error(val reason: String) : AgentCommand()
}5.1 åèœèŠçç©éµ
åœåå·²æ¥å ¥åèœïŒå·²éªè¯ïŒ
| åèœå | å ·äœåèœ | åœä»€ç±»å | Capability | ç¶æ |
|---|---|---|---|---|
| çžæºæ§å¶ | æç § | CapturePhoto |
CameraCapability | å·²éªè¯ |
| åŒå§/忢åœå | ToggleRecording |
CameraCapability | å·²éªè¯ | |
| 翻蜬æå倎 | FlipCamera |
CameraCapability | å·²éªè¯ | |
| åçŠè°è | AdjustZoom |
CameraCapability | å·²éªè¯ | |
| æå è°è | AdjustExposure |
CameraCapability | å·²éªè¯ | |
| åæ¢æææš¡åŒ | SwitchMode |
CameraCapability | å·²éªè¯ | |
| çŸé¢ | 磚ç®/çŸçœè°è | AdjustBeauty |
CameraCapability | å·²éªè¯ |
| çŠèž/倧çŒè°è | AdjustBeauty |
CameraCapability | å·²éªè¯ | |
| åè²/è ®çº¢è°è | AdjustBeauty |
CameraCapability | å·²éªè¯ | |
| 滀é/飿 Œ | åæ¢æ»€é | SwitchFilter |
CameraCapability | å·²éªè¯ |
| 忢飿 Œç¹æ | SwitchStyle |
CameraCapability | å·²éªè¯ | |
| åæ¢åºæ¯æš¡åŒ | SwitchScene |
CameraCapability | å·²éªè¯ | |
| 忢ç»å¹ æ¯äŸ | SwitchRatio |
CameraCapability | å·²éªè¯ | |
| å¯¹è¯ | ææ¬åå€/è倩 | TextReply |
CameraCapability | å·²éªè¯ |
| è¿çšæ§å¶ | é£ä¹Šæ¶æ¯å€ç | å€ç§ | RemoteControlCapability | åŒåäž |
V2 æ°å¢åèœïŒåŒåäžïŒ
| åèœå | å ·äœåèœ | åœä»€ç±»å | Capability | äŒå 级 |
|---|---|---|---|---|
| Gallery | æ¥çç §ç | ViewMedia |
GalleryCapability | P0 |
| å é€ç §ç | DeleteMedia |
GalleryCapability | P0 | |
| åäº«ç §ç | ShareMedia |
GalleryCapability | P1 | |
| ç §çæçŽ¢ | SearchMedia |
GalleryCapability | P2 | |
| 讟眮 | åæ¢äž»é¢ | ChangeTheme |
SettingsCapability | P1 |
| 忢è¯èš | ChangeLanguage |
SettingsCapability | P1 | |
| å¯Œèª | åæ¢é¡µé¢ | NavigateTo |
NavigationCapability | P0 |
| è¿åäžäžé¡µ | GoBack |
NavigationCapability | P0 | |
| çŒèŸ | è¿å ¥çŒèŸ | é¢ç | EditorCapability | P2 |
6. æ°æ®æš¡å
6.1 AgentCommand å¯å°ç±»
è§ ç¬¬ 5 ç« ã
6.2 æšçç»æå è£
sealed class InferenceResult {
data class Local(val command: AgentCommand) : InferenceResult()
data class Remote(val commands: List<AgentCommand>) : InferenceResult()
data class Text(val message: String) : InferenceResult()
data class Plan(val plan: ExecutionPlan) : InferenceResult()
data class Error(val reason: String) : InferenceResult()
}6.3 ExecutionPlanïŒL3 Plan æš¡åŒïŒ
{
"plan_id": "uuid",
"steps": [
{
"step": 1,
"condition": "currentCamera == BACK",
"command": {
"name": "flip_camera",
"arguments": "{}"
},
"description": "忢å°å眮æå倎"
}
]
}6.4 AiAgentUseCaseïŒFacadeïŒ
class AiAgentUseCase(
context: Context,
agentMode: AiAgentMode = AiAgentMode.REMOTE, // é»è®€ REMOTEïŒè¿çšäŒå
ïŒ
privacyLevel: AiAgentPrivacyLevel = AiAgentPrivacyLevel.STRICT,
localModelId: String = "qwen3_5_2b",
remoteConfig: RemoteModelConfig? = null,
forceRemote: Boolean = false
) {
private val orchestrator = AgentOrchestrator(
localPipeline = LocalInferencePipeline(...),
remotePipeline = RemoteInferencePipeline(...)
)
suspend fun processInput(userInput: String, context: AgentContext): InferenceResult {
return when (configurator.getAgentMode()) {
AiAgentMode.LOCAL -> localPipeline.process(input)
AiAgentMode.REMOTE -> remotePipeline.process(input)
AiAgentMode.OFF -> Result.failure(AgentDisabledException())
}
}
}6.5 IM è¿çšæ§å¶éæ
é£ä¹Šè¿çšæ§å¶å€çšåäž RemoteOrchestrator å RemoteInferencePipelineïŒ
é£ä¹Šæ¶æ¯ â FeishuChannelHandler â RemoteCommandDispatcher
â LLM è§£ææåŸïŒå€çš RemoteOrchestratorïŒç¬ç« System PromptïŒ
â CapabilityRegistry.dispatch()
â ç»æ â FeishuChannelHandler.sendMessage/sendImage
7. Agent æ§è¡è§çºŠ (Execution Rules)
- JSON è§£æ: å¿
须䜿çš
kotlinx.serialization.jsonïŒäž¥çŠæ£åæååæ®µ - System Prompt: çŠæ¢ç¡¬çŒç åš
AgentOrchestratorå ïŒéæœè±¡äžºPromptBuilderçç¥æ¥å£ - Capability 泚å: æ°å¢ Capability å¿
é¡»åæ¥æŽæ°
CapabilityRegistryçåœä»€æ å°ïŒçŠæ¢éæŒ - Memory æä¹
å:
appendConversationéåŒå ¥å åçŒå + æ¹éå·çïŒçŠæ¢æ¯æ¡æ¶æ¯ 2 次 DataStore IO - ChatML æ ŒåŒ:
LocalLlmEngineçŠæ¢ç¡¬çŒç Qwen ChatMLïŒéæœè±¡ChatFormatæ¥å£ææš¡å泚å - 线çšå®å
š:
AgentOrchestratorçagentMode/currentModelIdé忥æ§å¶ïŒçŠæ¢å¹¶åä¿®æ¹ - æš¡åå 蜜: å¿«éè¿ç»è°çšéå å¹¶åéïŒé¿å è§Šå倿¬¡å 蜜
- éç§æŠæª:
PrivacyGuardå¿ é¡»æ¥å ¥ LLM èŸå ¥èŸåºæµå Capability æ§è¡éŸè·¯ïŒçŠæ¢ä» åæèš - æ¥å¿è§è: ç»äžäœ¿çš
PicMe:[Module]åçŒïŒçŠæ¢åç»ä»¶æ çŸäžäžèŽ - åè®®é犻: è¿çš tool_calls äžæ¬å° method/params å¿ é¡»åœ»åºé犻ïŒçŠæ¢æ··çš
8. åžžè§é·é±æ£æ¥æž å (Checklist)
9. éªæ¶æ å
| ID | éªæ¶é¡¹ | äŒå 级 |
|---|---|---|
| AC-1 | è¿çšæš¡åŒäžïŒâç£šç® 60 ç¶åæç §â èœè§£æäžºäž€äžª tool_calls å¹¶äŸæ¬¡æ§è¡ | P0 |
| AC-2 | è¿çšæš¡åŒäžïŒâåŠææ¯å眮就åå眮åæâ èœæ£ç¡®æ§è¡æ¡ä»¶å€æ | P0 |
| AC-3 | æ¬å°æš¡åŒäžïŒææç°æåèœä¿æ 100% å Œå®¹ | P0 |
| AC-4 | L1 çŒååœäžç > 60%ïŒé«é¢æä»€ïŒ | P1 |
| AC-5 | è¿çšæšçå¹³åå»¶è¿ < 1.5s | P1 |
| AC-6 | æ¯æå¯¹è¯åŒè®°å¿ïŒå€èœ®äžäžæïŒ | P2 |
| AC-7 | DeepSeek æš¡å tool_calls æåç > 95% | P0 |
| AC-8 | æµåŒèå€©éŠ token å»¶è¿ < 500ms | P1 |
10. è¿çšæšç任塿å [agent-task]
Phase 1: åºç¡è®Ÿæœ (RD) â 已宿
Phase 2: L2 Batch æš¡åŒ (RD) â 已宿
Phase 3: L3 Plan æš¡åŒ (RD) â 已宿
Phase 4: L4 æµåŒ Chat (RD) â 已宿
Phase 5: DeepSeek éé (RD) â 已宿
Phase 6: éæäžæµè¯ (QA)
11. æ¶ææŒè¿è·¯çº¿åŸ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â 端䟧æšçæŒè¿è·¯çº¿ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ€
â P0ïŒå·²å®æïŒ: â
â 1. JSON è§£ææ¹çš kotlinx.serialization â
â 2. System Prompt æå䞺 LocalPromptBuilder / RemotePromptBuilder â
â 3. MemoryManager åŒå
¥å
åçŒå + æ¹éå·ç â
â 4. æ¬å°/è¿çšå议圻åºå犻ïŒADR-005ïŒ â
â 5. è¿çšæšçåŒå
¥ langchain4j æ åå â
â 6. DeepSeek éé
ïŒthinking çŠçšãstrict å
Œå®¹ïŒ â
â 7. Sherpa-MNN è¯é³æ æž
çïŒè¿è³ Sherpa-ONNX â
â 8. å€éè¯åŒæ Phase 1 宿ïŒ21 è¯ + åšæèœ®è¯¢ + VAD çš³å®æ§ïŒ â
â â
â P1ïŒè¿è¡äžïŒ: â
â 9. KWS always-on è¿ç§»ïŒSherpa-ONNX KWSïŒPhase 2ïŒ â
â 10. æ¯æ Batch Function CallingïŒtool_calls æ°ç»ïŒ â
â 11. ChatFormat æœè±¡ïŒæ¯æå€æš¡å忢 â
â 12. Capability åœä»€æ å°æ¹äžºæ³šè§£é©±åšæå±æ§å£°æ â
â 13. IM è¿çšæ§å¶ïŒé£ä¹Š WebSocketïŒå
šéŸè·¯æé â
â â
â P2ïŒäžæïŒ: â
â 14. Plan-and-Execute è§åæš¡æ¿åŒæïŒç«¯äŸ§äžçš LLM åè§åïŒ â
â 15. Token é¢ç®ç®¡çäžäžäžæå猩 â
â 16. éç§å级路ç±å®åïŒææåŒºå¶æ¬å°ïŒéææå
讞è¿çš â
â â
â P3ïŒè¿æïŒ: â
â 17. è®°å¿æèŠïŒé¿æå¯¹è¯äžäž¢å€±äžäžæïŒ â
â 18. å€äŒè¯ç®¡ç â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
12. éåœïŒåèææ¡£
- AGENTS.md â 顶屿²»çè§å
- FEATURES.md â åèœäº€äºç»è
- COMMAND_REFERENCE.md â åœä»€åèæå
- AI_OPTIMIZATION.md â AI äžé®äŒå
- TAG_GENERATION.md â TAG çæ
- MNN_LLM_OPERATIONS.md â MNN LLM è¿ç»Ž
- VOICE_STACK.md â è¯é³æ
- IM_REMOTE_CONTROL_TECH_SPEC.md â IM è¿çšæ§å¶ææ¯è§è
runtime-core/src/main/java/com/mamba/picme/agent/core/â æºç ç®åœïŒAgent çŒæå±ïŒAgentOrchestratorãCapabilityRegistryãPrivacyGuardãMemoryManagerãSceneManager çïŒagent-core/src/main/java/com/mamba/â æºç ç®åœïŒJava åºç¡åºïŒChatModelãOpenAiChatModelãToolãAiServices çïŒapp/src/main/java/com/mamba/picme/domain/usecase/AiAgentUseCase.ktâ Facade æ¡¥æ¥å±