aiforge-engine 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aiforge/__init__.py +64 -0
- aiforge/adapters/__init__.py +5 -0
- aiforge/adapters/input/__init__.py +0 -0
- aiforge/adapters/input/cli_input_adapter.py +45 -0
- aiforge/adapters/input/gui_input_adapter.py +40 -0
- aiforge/adapters/input/input_adapter.py +67 -0
- aiforge/adapters/input/input_adapter_manager.py +101 -0
- aiforge/adapters/input/input_processors.py +48 -0
- aiforge/adapters/input/mobile_input_adapter.py +48 -0
- aiforge/adapters/input/voice_input_adapter.py +44 -0
- aiforge/adapters/input/web_input_adapter.py +48 -0
- aiforge/adapters/output/__init__.py +5 -0
- aiforge/adapters/output/ai_ui_adapter.py +120 -0
- aiforge/adapters/output/enhanced_hybrid_adapter.py +82 -0
- aiforge/adapters/output/learning_Interface.py +190 -0
- aiforge/adapters/output/rule_based_adapter.py +464 -0
- aiforge/adapters/output/task_type_detector.py +143 -0
- aiforge/adapters/output/ui_type_recommender.py +72 -0
- aiforge/api/__init__.py +0 -0
- aiforge/api/middleware/auth.py +0 -0
- aiforge/api/middleware/rate_limit.py +0 -0
- aiforge/api/routes/execution.py +0 -0
- aiforge/api/routes/llm.py +0 -0
- aiforge/api/routes/tasks.py +0 -0
- aiforge/api/server.py +0 -0
- aiforge/cache/__init__.py +3 -0
- aiforge/cache/action_matcher.py +318 -0
- aiforge/cache/code_cache.py +369 -0
- aiforge/cache/dynamic_task_type_manager.py +143 -0
- aiforge/cache/semantic_cache.py +839 -0
- aiforge/cli/__init__.py +0 -0
- aiforge/cli/cli.py +87 -0
- aiforge/cli/commands/manager.py +73 -0
- aiforge/cli/wizard.py +116 -0
- aiforge/config/__init__.py +3 -0
- aiforge/config/config.py +185 -0
- aiforge/config/config_sync.py +0 -0
- aiforge/config/default.toml +97 -0
- aiforge/config/extension_config.py +46 -0
- aiforge/config/extensions.toml +45 -0
- aiforge/config/remote_config.py +20 -0
- aiforge/core/__init__.py +9 -0
- aiforge/core/engine.py +149 -0
- aiforge/core/helpers/__init__.py +3 -0
- aiforge/core/helpers/cache_helper.py +53 -0
- aiforge/core/managers/__init__.py +4 -0
- aiforge/core/managers/config_manager.py +75 -0
- aiforge/core/managers/execution_manager.py +530 -0
- aiforge/core/managers/search_manager.py +402 -0
- aiforge/core/orchestrator.py +301 -0
- aiforge/core/prompt.py +345 -0
- aiforge/core/runner.py +154 -0
- aiforge/core/task/__init__.py +5 -0
- aiforge/core/task/executor.py +271 -0
- aiforge/core/task/manager.py +62 -0
- aiforge/core/task/task.py +147 -0
- aiforge/deployment/__init__.py +0 -0
- aiforge/deployment/cloud/aws_deploy.py +0 -0
- aiforge/deployment/cloud/azure_deploy.py +0 -0
- aiforge/deployment/docker/Dockerfile +0 -0
- aiforge/deployment/docker/docker-compose.yml +0 -0
- aiforge/deployment/kubernetes/deployment.yaml +0 -0
- aiforge/deployment/kubernetes/service.yaml +0 -0
- aiforge/enterprise/__init__.py +0 -0
- aiforge/enterprise/audit/audit_logger.py +0 -0
- aiforge/enterprise/audit/compliance_checker.py +0 -0
- aiforge/enterprise/auth/permission_manager.py +0 -0
- aiforge/enterprise/auth/user_manager.py +0 -0
- aiforge/enterprise/monitoring/alert_manager.py +0 -0
- aiforge/enterprise/monitoring/metrics_collector.py +0 -0
- aiforge/execution/__init__.py +16 -0
- aiforge/execution/analyzer.py +297 -0
- aiforge/execution/code_blocks.py +88 -0
- aiforge/execution/engine.py +667 -0
- aiforge/execution/executor_interface.py +16 -0
- aiforge/execution/result_formatter.py +81 -0
- aiforge/execution/result_processor.py +289 -0
- aiforge/execution/runtimes/__init__.py +0 -0
- aiforge/execution/runtimes/javascript_runtime.py +0 -0
- aiforge/execution/runtimes/python_runtime.py +0 -0
- aiforge/execution/runtimes/shell_runtime.py +0 -0
- aiforge/execution/unified_executor.py +28 -0
- aiforge/extensions/__init__.py +0 -0
- aiforge/extensions/extension_manager.py +48 -0
- aiforge/extensions/loader.py +115 -0
- aiforge/extensions/marketplace.py +23 -0
- aiforge/extensions/plugin_installer.py +0 -0
- aiforge/extensions/template_extension.py +90 -0
- aiforge/instruction/__init__.py +11 -0
- aiforge/instruction/analyzer.py +539 -0
- aiforge/instruction/classifier.py +268 -0
- aiforge/instruction/extractor.py +253 -0
- aiforge/instruction/parser.py +47 -0
- aiforge/llm/__init__.py +8 -0
- aiforge/llm/conversation_manager.py +115 -0
- aiforge/llm/llm_client.py +240 -0
- aiforge/llm/llm_manager.py +150 -0
- aiforge/llm/providers/__init__.py +0 -0
- aiforge/llm/providers/deepseek_client.py +0 -0
- aiforge/llm/providers/ollama_client.py +0 -0
- aiforge/llm/providers/openai_client.py +0 -0
- aiforge/models/__init__.py +0 -0
- aiforge/models/model_manager.py +141 -0
- aiforge/multimodal/__init__.py +0 -0
- aiforge/multimodal/audio/speech_to_text.py +0 -0
- aiforge/multimodal/audio/text_to_speech.py +0 -0
- aiforge/multimodal/document/pdf_parser.py +0 -0
- aiforge/multimodal/document/word_parser.py +0 -0
- aiforge/multimodal/vision/image_processor.py +0 -0
- aiforge/multimodal/vision/video_processor.py +0 -0
- aiforge/optimization/code_optimizer.py +163 -0
- aiforge/optimization/feedback_optimizer.py +42 -0
- aiforge/plugins/__init__.py +0 -0
- aiforge/plugins/builtin/data_analysis.py +0 -0
- aiforge/plugins/builtin/file_processing.py +0 -0
- aiforge/plugins/builtin/web_scraping.py +0 -0
- aiforge/plugins/plugin_interface.py +0 -0
- aiforge/plugins/plugin_manager.py +0 -0
- aiforge/strategies/__init__.py +41 -0
- aiforge/strategies/execution_strategy.py +106 -0
- aiforge/strategies/execution_strategy_manager.py +44 -0
- aiforge/strategies/parameter_mapping_service.py +895 -0
- aiforge/strategies/search_template_strategy.py +108 -0
- aiforge/strategies/semantic_field_strategy.py +257 -0
- aiforge/strategies/strategy/__init__.py +0 -0
- aiforge/strategies/strategy/class_instantiation.py +68 -0
- aiforge/strategies/strategy/direct_result.py +33 -0
- aiforge/strategies/strategy/file_operation.py +832 -0
- aiforge/strategies/strategy/file_operation_safety.py +317 -0
- aiforge/strategies/strategy/parameterized_function.py +168 -0
- aiforge/strategies/validation_strategy.py +125 -0
- aiforge/templates/__init__.py +9 -0
- aiforge/templates/builtin/automation.json +0 -0
- aiforge/templates/builtin/data_analysis.json +0 -0
- aiforge/templates/builtin/web_api.json +0 -0
- aiforge/templates/search_template.py +1311 -0
- aiforge/templates/template_manager.py +331 -0
- aiforge/utils/__init__.py +0 -0
- aiforge/utils/helpers.py +0 -0
- aiforge/utils/sentence_transformers_downloader.py +44 -0
- aiforge/utils/utils.py +290 -0
- aiforge/validation/code_validator.py +33 -0
- aiforge/validation/result_validator.py +260 -0
- aiforge/workflow/__init__.py +0 -0
- aiforge/workflow/nodes/data_node.py +0 -0
- aiforge/workflow/nodes/execution_node.py +0 -0
- aiforge/workflow/nodes/llm_node.py +0 -0
- aiforge/workflow/workflow_designer.py +0 -0
- aiforge/workflow/workflow_engine.py +0 -0
- aiforge_engine-0.0.1.dist-info/METADATA +11 -0
- aiforge_engine-0.0.1.dist-info/RECORD +153 -0
- aiforge_engine-0.0.1.dist-info/WHEEL +4 -0
- aiforge_engine-0.0.1.dist-info/licenses/LICENSE +201 -0
aiforge/__init__.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# 核心模块导入
|
|
2
|
+
from .core.engine import AIForgeEngine
|
|
3
|
+
from .core.task.manager import AIForgeTaskManager
|
|
4
|
+
from .core.task.task import AIForgeTask
|
|
5
|
+
from .execution.result_processor import AIForgeResultProcessor
|
|
6
|
+
|
|
7
|
+
# LLM模块导入
|
|
8
|
+
from .llm.llm_client import AIForgeLLMClient, AIForgeOllamaClient
|
|
9
|
+
from .llm.llm_manager import AIForgeLLMManager
|
|
10
|
+
|
|
11
|
+
# 执行引擎导入
|
|
12
|
+
from .execution.engine import AIForgeExecutionEngine
|
|
13
|
+
|
|
14
|
+
# 配置管理导入
|
|
15
|
+
from .config.config import AIForgeConfig
|
|
16
|
+
|
|
17
|
+
# 数据获取相关导入
|
|
18
|
+
from .templates.template_manager import TemplateManager
|
|
19
|
+
from .strategies.search_template_strategy import (
|
|
20
|
+
StandardTemplateStrategy,
|
|
21
|
+
TemplateGenerationStrategy,
|
|
22
|
+
)
|
|
23
|
+
from .strategies.semantic_field_strategy import SemanticFieldStrategy, FieldProcessorManager
|
|
24
|
+
|
|
25
|
+
# 其他相关导入
|
|
26
|
+
from .execution.result_formatter import AIForgeResultFormatter
|
|
27
|
+
from .execution.code_blocks import CodeBlockManager, CodeBlock
|
|
28
|
+
from .core.prompt import AIForgePrompt
|
|
29
|
+
from .cli.wizard import create_config_wizard
|
|
30
|
+
from .cache.semantic_cache import EnhancedStandardizedCache
|
|
31
|
+
|
|
32
|
+
# 指令分析导入
|
|
33
|
+
from .instruction.analyzer import AIForgeInstructionAnalyzer
|
|
34
|
+
|
|
35
|
+
__all__ = [
|
|
36
|
+
# 核心组件
|
|
37
|
+
"AIForgeEngine",
|
|
38
|
+
"AIForgeTaskManager",
|
|
39
|
+
"AIForgeTask",
|
|
40
|
+
"AIForgeResultProcessor",
|
|
41
|
+
"AIForgeConfig",
|
|
42
|
+
# LLM组件
|
|
43
|
+
"AIForgeLLMClient",
|
|
44
|
+
"AIForgeOllamaClient",
|
|
45
|
+
"AIForgeLLMManager",
|
|
46
|
+
# 执行组件
|
|
47
|
+
"AIForgeExecutionEngine",
|
|
48
|
+
"EnhancedStandardizedCache",
|
|
49
|
+
# 数据获取组件
|
|
50
|
+
"TemplateManager",
|
|
51
|
+
"StandardTemplateStrategy",
|
|
52
|
+
"TemplateGenerationStrategy",
|
|
53
|
+
"SemanticFieldStrategy",
|
|
54
|
+
"FieldProcessorManager",
|
|
55
|
+
"AIForgeInstructionAnalyzer",
|
|
56
|
+
# 工具组件
|
|
57
|
+
"create_config_wizard",
|
|
58
|
+
"AIForgeResultFormatter",
|
|
59
|
+
"CodeBlockManager",
|
|
60
|
+
"CodeBlock",
|
|
61
|
+
"AIForgePrompt",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
__version__ = "0.0.1"
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
from .input_adapter import InputAdapter, InputSource, InputContext, StandardizedInput
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CLIInputAdapter(InputAdapter):
|
|
6
|
+
"""CLI输入适配器"""
|
|
7
|
+
|
|
8
|
+
def can_handle(self, raw_input: Any, source: InputSource) -> bool:
|
|
9
|
+
return source == InputSource.CLI and isinstance(raw_input, (str, dict))
|
|
10
|
+
|
|
11
|
+
def adapt(self, raw_input: Any, context: InputContext) -> StandardizedInput:
|
|
12
|
+
"""适配CLI输入"""
|
|
13
|
+
if isinstance(raw_input, str):
|
|
14
|
+
# 简单字符串指令
|
|
15
|
+
instruction = raw_input
|
|
16
|
+
metadata = {"input_type": "simple_command"}
|
|
17
|
+
elif isinstance(raw_input, dict):
|
|
18
|
+
# 结构化CLI参数
|
|
19
|
+
instruction = raw_input.get("instruction", "")
|
|
20
|
+
metadata = {
|
|
21
|
+
"input_type": "structured_command",
|
|
22
|
+
"args": raw_input.get("args", {}),
|
|
23
|
+
"flags": raw_input.get("flags", {}),
|
|
24
|
+
"options": raw_input.get("options", {}),
|
|
25
|
+
}
|
|
26
|
+
else:
|
|
27
|
+
raise ValueError(f"Unsupported CLI input type: {type(raw_input)}")
|
|
28
|
+
|
|
29
|
+
# CLI特定的元数据
|
|
30
|
+
metadata.update(
|
|
31
|
+
{
|
|
32
|
+
"terminal_width": context.device_info.get("terminal_width", 80),
|
|
33
|
+
"supports_color": context.device_info.get("supports_color", True),
|
|
34
|
+
"shell_type": context.device_info.get("shell", "bash"),
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
return StandardizedInput(instruction=instruction, context=context, metadata=metadata)
|
|
39
|
+
|
|
40
|
+
def validate(self, standardized_input: StandardizedInput) -> bool:
|
|
41
|
+
"""验证CLI输入"""
|
|
42
|
+
return (
|
|
43
|
+
bool(standardized_input.instruction.strip())
|
|
44
|
+
and len(standardized_input.instruction) <= 10000 # CLI输入长度限制
|
|
45
|
+
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from .input_adapter import InputAdapter, InputSource, InputContext, StandardizedInput
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class GUIInputAdapter(InputAdapter):
|
|
7
|
+
"""GUI输入适配器"""
|
|
8
|
+
|
|
9
|
+
def can_handle(self, raw_input: Any, source: InputSource) -> bool:
|
|
10
|
+
return source == InputSource.GUI and isinstance(raw_input, dict)
|
|
11
|
+
|
|
12
|
+
def adapt(self, raw_input: Any, context: InputContext) -> StandardizedInput:
|
|
13
|
+
"""适配GUI输入"""
|
|
14
|
+
instruction = raw_input.get("text", "")
|
|
15
|
+
|
|
16
|
+
# GUI特定的元数据
|
|
17
|
+
metadata = {
|
|
18
|
+
"input_type": "gui_text",
|
|
19
|
+
"widget_id": raw_input.get("widget_id"),
|
|
20
|
+
"cursor_position": raw_input.get("cursor_position", 0),
|
|
21
|
+
"selection": raw_input.get("selection", {}),
|
|
22
|
+
"input_method": raw_input.get("input_method", "keyboard"),
|
|
23
|
+
"screen_size": context.device_info.get("screen_size", {}),
|
|
24
|
+
"theme": context.preferences.get("theme", "default"),
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
# 处理附件(如果有)
|
|
28
|
+
attachments = {}
|
|
29
|
+
if "files" in raw_input:
|
|
30
|
+
attachments["files"] = raw_input["files"]
|
|
31
|
+
if "images" in raw_input:
|
|
32
|
+
attachments["images"] = raw_input["images"]
|
|
33
|
+
|
|
34
|
+
return StandardizedInput(
|
|
35
|
+
instruction=instruction, context=context, metadata=metadata, attachments=attachments
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
def validate(self, standardized_input: StandardizedInput) -> bool:
|
|
39
|
+
"""验证GUI输入"""
|
|
40
|
+
return bool(standardized_input.instruction.strip())
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Dict, Any, Optional
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class InputSource(Enum):
|
|
7
|
+
"""输入源类型"""
|
|
8
|
+
|
|
9
|
+
CLI = "cli"
|
|
10
|
+
GUI = "gui"
|
|
11
|
+
WEB = "web"
|
|
12
|
+
MOBILE = "mobile"
|
|
13
|
+
API = "api"
|
|
14
|
+
VOICE = "voice"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class InputContext:
|
|
18
|
+
"""输入上下文信息"""
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
source: InputSource,
|
|
23
|
+
user_id: Optional[str] = None,
|
|
24
|
+
session_id: Optional[str] = None,
|
|
25
|
+
device_info: Optional[Dict[str, Any]] = None,
|
|
26
|
+
preferences: Optional[Dict[str, Any]] = None,
|
|
27
|
+
):
|
|
28
|
+
self.source = source
|
|
29
|
+
self.user_id = user_id
|
|
30
|
+
self.session_id = session_id
|
|
31
|
+
self.device_info = device_info or {}
|
|
32
|
+
self.preferences = preferences or {}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class StandardizedInput:
|
|
36
|
+
"""标准化输入结构"""
|
|
37
|
+
|
|
38
|
+
def __init__(
|
|
39
|
+
self,
|
|
40
|
+
instruction: str,
|
|
41
|
+
context: InputContext,
|
|
42
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
43
|
+
attachments: Optional[Dict[str, Any]] = None,
|
|
44
|
+
):
|
|
45
|
+
self.instruction = instruction
|
|
46
|
+
self.context = context
|
|
47
|
+
self.metadata = metadata or {}
|
|
48
|
+
self.attachments = attachments or {}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class InputAdapter(ABC):
|
|
52
|
+
"""输入适配器基类"""
|
|
53
|
+
|
|
54
|
+
@abstractmethod
|
|
55
|
+
def can_handle(self, raw_input: Any, source: InputSource) -> bool:
|
|
56
|
+
"""检查是否能处理特定类型的输入"""
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
@abstractmethod
|
|
60
|
+
def adapt(self, raw_input: Any, context: InputContext) -> StandardizedInput:
|
|
61
|
+
"""将原始输入适配为标准化输入"""
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
@abstractmethod
|
|
65
|
+
def validate(self, standardized_input: StandardizedInput) -> bool:
|
|
66
|
+
"""验证标准化输入的有效性"""
|
|
67
|
+
pass
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from typing import List, Dict, Any, Optional
|
|
2
|
+
from .input_adapter import InputAdapter, InputSource, InputContext, StandardizedInput
|
|
3
|
+
from .cli_input_adapter import CLIInputAdapter
|
|
4
|
+
from .gui_input_adapter import GUIInputAdapter
|
|
5
|
+
from .web_input_adapter import WebInputAdapter
|
|
6
|
+
from .mobile_input_adapter import MobileInputAdapter
|
|
7
|
+
from .voice_input_adapter import VoiceInputAdapter
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class InputAdapterManager:
|
|
11
|
+
"""输入适配管理器"""
|
|
12
|
+
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self.adapters: List[InputAdapter] = [
|
|
15
|
+
CLIInputAdapter(),
|
|
16
|
+
GUIInputAdapter(),
|
|
17
|
+
WebInputAdapter(),
|
|
18
|
+
MobileInputAdapter(),
|
|
19
|
+
VoiceInputAdapter(),
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
# 输入预处理器
|
|
23
|
+
self.preprocessors = []
|
|
24
|
+
|
|
25
|
+
# 输入后处理器
|
|
26
|
+
self.postprocessors = []
|
|
27
|
+
|
|
28
|
+
def register_adapter(self, adapter: InputAdapter):
|
|
29
|
+
"""注册自定义适配器"""
|
|
30
|
+
self.adapters.append(adapter)
|
|
31
|
+
|
|
32
|
+
def adapt_input(
|
|
33
|
+
self, raw_input: Any, source: InputSource, context_data: Optional[Dict[str, Any]] = None
|
|
34
|
+
) -> StandardizedInput:
|
|
35
|
+
"""适配输入"""
|
|
36
|
+
# 创建输入上下文
|
|
37
|
+
context = self._create_context(source, context_data or {})
|
|
38
|
+
|
|
39
|
+
# 预处理
|
|
40
|
+
processed_input = self._preprocess(raw_input, context)
|
|
41
|
+
|
|
42
|
+
# 找到合适的适配器
|
|
43
|
+
adapter = self._find_adapter(processed_input, source)
|
|
44
|
+
if not adapter:
|
|
45
|
+
raise ValueError(f"No adapter found for source: {source}")
|
|
46
|
+
|
|
47
|
+
# 执行适配
|
|
48
|
+
standardized_input = adapter.adapt(processed_input, context)
|
|
49
|
+
|
|
50
|
+
# 验证
|
|
51
|
+
if not adapter.validate(standardized_input):
|
|
52
|
+
raise ValueError("Input validation failed")
|
|
53
|
+
|
|
54
|
+
# 后处理
|
|
55
|
+
final_input = self._postprocess(standardized_input)
|
|
56
|
+
|
|
57
|
+
return final_input
|
|
58
|
+
|
|
59
|
+
def _create_context(self, source: InputSource, context_data: Dict[str, Any]) -> InputContext:
|
|
60
|
+
"""创建输入上下文"""
|
|
61
|
+
return InputContext(
|
|
62
|
+
source=source,
|
|
63
|
+
user_id=context_data.get("user_id"),
|
|
64
|
+
session_id=context_data.get("session_id"),
|
|
65
|
+
device_info=context_data.get("device_info", {}),
|
|
66
|
+
preferences=context_data.get("preferences", {}),
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def _find_adapter(self, raw_input: Any, source: InputSource) -> Optional[InputAdapter]:
|
|
70
|
+
"""找到合适的适配器"""
|
|
71
|
+
for adapter in self.adapters:
|
|
72
|
+
if adapter.can_handle(raw_input, source):
|
|
73
|
+
return adapter
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
def _preprocess(self, raw_input: Any, context: InputContext) -> Any:
|
|
77
|
+
"""预处理输入"""
|
|
78
|
+
processed = raw_input
|
|
79
|
+
for preprocessor in self.preprocessors:
|
|
80
|
+
processed = preprocessor.process(processed, context)
|
|
81
|
+
return processed
|
|
82
|
+
|
|
83
|
+
def _postprocess(self, standardized_input: StandardizedInput) -> StandardizedInput:
|
|
84
|
+
"""后处理标准化输入"""
|
|
85
|
+
processed = standardized_input
|
|
86
|
+
for postprocessor in self.postprocessors:
|
|
87
|
+
processed = postprocessor.process(processed)
|
|
88
|
+
return processed
|
|
89
|
+
|
|
90
|
+
def get_supported_sources(self) -> List[InputSource]:
|
|
91
|
+
"""获取支持的输入源"""
|
|
92
|
+
return list(InputSource)
|
|
93
|
+
|
|
94
|
+
def get_adapter_stats(self) -> Dict[str, Any]:
|
|
95
|
+
"""获取适配器统计信息"""
|
|
96
|
+
return {
|
|
97
|
+
"total_adapters": len(self.adapters),
|
|
98
|
+
"supported_sources": [source.value for source in self.get_supported_sources()],
|
|
99
|
+
"preprocessors": len(self.preprocessors),
|
|
100
|
+
"postprocessors": len(self.postprocessors),
|
|
101
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any
|
|
3
|
+
from .input_adapter import InputContext, StandardizedInput
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class InputPreprocessor(ABC):
|
|
7
|
+
"""输入预处理器基类"""
|
|
8
|
+
|
|
9
|
+
@abstractmethod
|
|
10
|
+
def process(self, raw_input: Any, context: InputContext) -> Any:
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class InputPostprocessor(ABC):
|
|
15
|
+
"""输入后处理器基类"""
|
|
16
|
+
|
|
17
|
+
@abstractmethod
|
|
18
|
+
def process(self, standardized_input: StandardizedInput) -> StandardizedInput:
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TextCleanupPreprocessor(InputPreprocessor):
|
|
23
|
+
"""文本清理预处理器"""
|
|
24
|
+
|
|
25
|
+
def process(self, raw_input: Any, context: InputContext) -> Any:
|
|
26
|
+
if isinstance(raw_input, str):
|
|
27
|
+
# 清理多余空白字符
|
|
28
|
+
return raw_input.strip()
|
|
29
|
+
elif isinstance(raw_input, dict) and "text" in raw_input:
|
|
30
|
+
raw_input["text"] = raw_input["text"].strip()
|
|
31
|
+
return raw_input
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class SecurityValidationPostprocessor(InputPostprocessor):
|
|
35
|
+
"""安全验证后处理器"""
|
|
36
|
+
|
|
37
|
+
def process(self, standardized_input: StandardizedInput) -> StandardizedInput:
|
|
38
|
+
# 检查指令长度
|
|
39
|
+
if len(standardized_input.instruction) > 100000:
|
|
40
|
+
raise ValueError("Instruction too long")
|
|
41
|
+
|
|
42
|
+
# 检查恶意内容(简单示例)
|
|
43
|
+
dangerous_patterns = ["rm -rf", "del /", "format c:"]
|
|
44
|
+
for pattern in dangerous_patterns:
|
|
45
|
+
if pattern.lower() in standardized_input.instruction.lower():
|
|
46
|
+
raise ValueError(f"Potentially dangerous instruction detected: {pattern}")
|
|
47
|
+
|
|
48
|
+
return standardized_input
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from .input_adapter import InputAdapter, InputSource, InputContext, StandardizedInput
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class MobileInputAdapter(InputAdapter):
|
|
7
|
+
"""移动端输入适配器"""
|
|
8
|
+
|
|
9
|
+
def can_handle(self, raw_input: Any, source: InputSource) -> bool:
|
|
10
|
+
return source == InputSource.MOBILE and isinstance(raw_input, dict)
|
|
11
|
+
|
|
12
|
+
def adapt(self, raw_input: Any, context: InputContext) -> StandardizedInput:
|
|
13
|
+
"""适配移动端输入"""
|
|
14
|
+
instruction = raw_input.get("text", "")
|
|
15
|
+
|
|
16
|
+
# 移动端特定的元数据
|
|
17
|
+
metadata = {
|
|
18
|
+
"input_type": "mobile_input",
|
|
19
|
+
"input_method": raw_input.get("input_method", "touch"), # touch, voice, gesture
|
|
20
|
+
"orientation": context.device_info.get("orientation", "portrait"),
|
|
21
|
+
"device_type": context.device_info.get("device_type", "phone"), # phone, tablet
|
|
22
|
+
"os": context.device_info.get("os", "unknown"),
|
|
23
|
+
"app_version": context.device_info.get("app_version", ""),
|
|
24
|
+
"network_type": context.device_info.get("network", "wifi"),
|
|
25
|
+
"battery_level": context.device_info.get("battery", 100),
|
|
26
|
+
"location": raw_input.get("location", {}) if raw_input.get("location_enabled") else {},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# 处理移动端特有的输入
|
|
30
|
+
attachments = {}
|
|
31
|
+
if "photos" in raw_input:
|
|
32
|
+
attachments["photos"] = raw_input["photos"]
|
|
33
|
+
if "voice_recording" in raw_input:
|
|
34
|
+
attachments["voice"] = raw_input["voice_recording"]
|
|
35
|
+
if "camera_capture" in raw_input:
|
|
36
|
+
attachments["camera"] = raw_input["camera_capture"]
|
|
37
|
+
|
|
38
|
+
return StandardizedInput(
|
|
39
|
+
instruction=instruction, context=context, metadata=metadata, attachments=attachments
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def validate(self, standardized_input: StandardizedInput) -> bool:
|
|
43
|
+
"""验证移动端输入"""
|
|
44
|
+
# 移动端输入可能更简短
|
|
45
|
+
return (
|
|
46
|
+
bool(standardized_input.instruction.strip())
|
|
47
|
+
and len(standardized_input.instruction) <= 5000
|
|
48
|
+
)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from .input_adapter import InputAdapter, InputSource, InputContext, StandardizedInput
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class VoiceInputAdapter(InputAdapter):
|
|
7
|
+
"""语音输入适配器"""
|
|
8
|
+
|
|
9
|
+
def can_handle(self, raw_input: Any, source: InputSource) -> bool:
|
|
10
|
+
return source == InputSource.VOICE and isinstance(raw_input, dict)
|
|
11
|
+
|
|
12
|
+
def adapt(self, raw_input: Any, context: InputContext) -> StandardizedInput:
|
|
13
|
+
"""适配语音输入"""
|
|
14
|
+
# 语音转文字后的指令
|
|
15
|
+
instruction = raw_input.get("transcribed_text", "")
|
|
16
|
+
|
|
17
|
+
# 语音特定的元数据
|
|
18
|
+
metadata = {
|
|
19
|
+
"input_type": "voice_input",
|
|
20
|
+
"audio_format": raw_input.get("audio_format", "wav"),
|
|
21
|
+
"sample_rate": raw_input.get("sample_rate", 16000),
|
|
22
|
+
"duration": raw_input.get("duration", 0),
|
|
23
|
+
"confidence_score": raw_input.get("confidence", 0.0),
|
|
24
|
+
"language": raw_input.get("detected_language", "zh-CN"),
|
|
25
|
+
"speaker_id": raw_input.get("speaker_id"),
|
|
26
|
+
"noise_level": raw_input.get("noise_level", "low"),
|
|
27
|
+
"transcription_engine": raw_input.get("engine", "default"),
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# 保存原始音频数据
|
|
31
|
+
attachments = {}
|
|
32
|
+
if "audio_data" in raw_input:
|
|
33
|
+
attachments["audio"] = raw_input["audio_data"]
|
|
34
|
+
|
|
35
|
+
return StandardizedInput(
|
|
36
|
+
instruction=instruction, context=context, metadata=metadata, attachments=attachments
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def validate(self, standardized_input: StandardizedInput) -> bool:
|
|
40
|
+
"""验证语音输入"""
|
|
41
|
+
confidence = standardized_input.metadata.get("confidence_score", 0.0)
|
|
42
|
+
return (
|
|
43
|
+
bool(standardized_input.instruction.strip()) and confidence >= 0.6 # 语音识别置信度阈值
|
|
44
|
+
)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from .input_adapter import InputAdapter, InputSource, InputContext, StandardizedInput
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class WebInputAdapter(InputAdapter):
|
|
7
|
+
"""Web输入适配器"""
|
|
8
|
+
|
|
9
|
+
def can_handle(self, raw_input: Any, source: InputSource) -> bool:
|
|
10
|
+
return source == InputSource.WEB and isinstance(raw_input, dict)
|
|
11
|
+
|
|
12
|
+
def adapt(self, raw_input: Any, context: InputContext) -> StandardizedInput:
|
|
13
|
+
"""适配Web输入"""
|
|
14
|
+
instruction = raw_input.get("instruction", "")
|
|
15
|
+
|
|
16
|
+
# Web特定的元数据
|
|
17
|
+
metadata = {
|
|
18
|
+
"input_type": "web_request",
|
|
19
|
+
"http_method": raw_input.get("method", "POST"),
|
|
20
|
+
"user_agent": raw_input.get("user_agent", ""),
|
|
21
|
+
"ip_address": raw_input.get("ip_address", ""),
|
|
22
|
+
"referrer": raw_input.get("referrer", ""),
|
|
23
|
+
"browser_info": context.device_info.get("browser", {}),
|
|
24
|
+
"viewport": context.device_info.get("viewport", {}),
|
|
25
|
+
"request_id": raw_input.get("request_id"),
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# 处理Web特有的参数
|
|
29
|
+
if "form_data" in raw_input:
|
|
30
|
+
metadata["form_data"] = raw_input["form_data"]
|
|
31
|
+
if "query_params" in raw_input:
|
|
32
|
+
metadata["query_params"] = raw_input["query_params"]
|
|
33
|
+
|
|
34
|
+
# 处理文件上传
|
|
35
|
+
attachments = {}
|
|
36
|
+
if "uploaded_files" in raw_input:
|
|
37
|
+
attachments["files"] = raw_input["uploaded_files"]
|
|
38
|
+
|
|
39
|
+
return StandardizedInput(
|
|
40
|
+
instruction=instruction, context=context, metadata=metadata, attachments=attachments
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def validate(self, standardized_input: StandardizedInput) -> bool:
|
|
44
|
+
"""验证Web输入"""
|
|
45
|
+
return (
|
|
46
|
+
bool(standardized_input.instruction.strip())
|
|
47
|
+
and len(standardized_input.instruction) <= 50000 # Web输入可以更长
|
|
48
|
+
)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import hashlib
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
from ...llm.llm_client import AIForgeLLMClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AIUIAdapter:
|
|
8
|
+
"""AI驱动的UI适配器"""
|
|
9
|
+
|
|
10
|
+
def __init__(self, llm_client: AIForgeLLMClient):
|
|
11
|
+
self.llm_client = llm_client
|
|
12
|
+
self.cache = {} # 简单的内存缓存
|
|
13
|
+
|
|
14
|
+
def adapt_for_display(self, data: Dict[str, Any], ui_context: str) -> Dict[str, Any]:
|
|
15
|
+
"""根据UI上下文需求,让AI分析并转换数据格式"""
|
|
16
|
+
# 生成缓存键
|
|
17
|
+
cache_key = self._generate_cache_key(data, ui_context)
|
|
18
|
+
|
|
19
|
+
# 检查缓存
|
|
20
|
+
if cache_key in self.cache:
|
|
21
|
+
return self.cache[cache_key]
|
|
22
|
+
|
|
23
|
+
# AI分析
|
|
24
|
+
prompt = self._build_adaptation_prompt(data, ui_context)
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
response = self.llm_client.generate_code(prompt, "")
|
|
28
|
+
adapted_result = self._parse_adaptation_result(response)
|
|
29
|
+
|
|
30
|
+
# 缓存结果
|
|
31
|
+
self.cache[cache_key] = adapted_result
|
|
32
|
+
|
|
33
|
+
return adapted_result
|
|
34
|
+
except Exception:
|
|
35
|
+
# 失败时返回基础格式
|
|
36
|
+
return self._create_fallback_format(data, ui_context)
|
|
37
|
+
|
|
38
|
+
def _build_adaptation_prompt(self, data: Dict[str, Any], ui_context: str) -> str:
|
|
39
|
+
"""构建适配提示词"""
|
|
40
|
+
return f"""
|
|
41
|
+
# 任务:数据格式适配
|
|
42
|
+
你需要将原始数据转换为适合特定界面展示的格式。
|
|
43
|
+
|
|
44
|
+
## 原始数据
|
|
45
|
+
{json.dumps(data, ensure_ascii=False, indent=2)}
|
|
46
|
+
|
|
47
|
+
## 目标界面类型
|
|
48
|
+
{ui_context}
|
|
49
|
+
|
|
50
|
+
## 输出要求
|
|
51
|
+
请返回以下JSON格式:
|
|
52
|
+
{{
|
|
53
|
+
"display_items": [
|
|
54
|
+
{{
|
|
55
|
+
"type": "text|table|card|list|chart",
|
|
56
|
+
"title": "显示标题",
|
|
57
|
+
"content": "具体内容",
|
|
58
|
+
"priority": 1-10
|
|
59
|
+
}}
|
|
60
|
+
],
|
|
61
|
+
"layout_hints": {{
|
|
62
|
+
"layout_type": "vertical|horizontal|grid",
|
|
63
|
+
"columns": 1-4,
|
|
64
|
+
"spacing": "compact|normal|loose"
|
|
65
|
+
}},
|
|
66
|
+
"actions": [
|
|
67
|
+
{{
|
|
68
|
+
"label": "操作名称",
|
|
69
|
+
"action": "refresh|export|detail",
|
|
70
|
+
"data": {{}}
|
|
71
|
+
}}
|
|
72
|
+
],
|
|
73
|
+
"summary_text": "数据摘要文本"
|
|
74
|
+
}}
|
|
75
|
+
|
|
76
|
+
请严格按照JSON格式返回,不要包含其他解释文字。
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
def _parse_adaptation_result(self, response: str) -> Dict[str, Any]:
|
|
80
|
+
"""解析AI适配结果"""
|
|
81
|
+
# 提取JSON内容
|
|
82
|
+
import re
|
|
83
|
+
|
|
84
|
+
json_match = re.search(r"\{.*\}", response, re.DOTALL)
|
|
85
|
+
if json_match:
|
|
86
|
+
try:
|
|
87
|
+
return json.loads(json_match.group(0))
|
|
88
|
+
except json.JSONDecodeError:
|
|
89
|
+
pass
|
|
90
|
+
|
|
91
|
+
# 解析失败时返回默认结构
|
|
92
|
+
return {
|
|
93
|
+
"display_items": [
|
|
94
|
+
{"type": "text", "title": "数据", "content": str(response)[:200], "priority": 5}
|
|
95
|
+
],
|
|
96
|
+
"layout_hints": {"layout_type": "vertical", "columns": 1, "spacing": "normal"},
|
|
97
|
+
"actions": [],
|
|
98
|
+
"summary_text": "AI适配解析失败",
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
def _generate_cache_key(self, data: Dict[str, Any], ui_context: str) -> str:
|
|
102
|
+
"""生成缓存键"""
|
|
103
|
+
content = f"{json.dumps(data, sort_keys=True)}_{ui_context}"
|
|
104
|
+
return hashlib.md5(content.encode()).hexdigest()[:16]
|
|
105
|
+
|
|
106
|
+
def _create_fallback_format(self, data: Dict[str, Any], ui_context: str) -> Dict[str, Any]:
|
|
107
|
+
"""创建回退格式"""
|
|
108
|
+
return {
|
|
109
|
+
"display_items": [
|
|
110
|
+
{
|
|
111
|
+
"type": "text",
|
|
112
|
+
"title": "原始数据",
|
|
113
|
+
"content": json.dumps(data, ensure_ascii=False, indent=2),
|
|
114
|
+
"priority": 5,
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
"layout_hints": {"layout_type": "vertical", "columns": 1, "spacing": "normal"},
|
|
118
|
+
"actions": [{"label": "刷新", "action": "refresh", "data": {}}],
|
|
119
|
+
"summary_text": f"显示原始数据 ({ui_context})",
|
|
120
|
+
}
|