humex 0.2.0__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.
- humex/__init__.py +50 -0
- humex/api/__init__.py +28 -0
- humex/api/ai_api/__init__.py +18 -0
- humex/api/ai_api/chat.py +91 -0
- humex/api/ai_api/models/__init__.py +6 -0
- humex/api/ai_api/models/_claude_cli.py +109 -0
- humex/api/ai_api/models/_qwen.py +124 -0
- humex/api/ai_api/prompts/__init__.py +5 -0
- humex/api/ai_api/prompts/dag_preprompt.txt +413 -0
- humex/api/ai_api/prompts/system_monitor_operator_dag.txt +596 -0
- humex/api/ai_api/translate_metrics.py +371 -0
- humex/api/core_apis.py +121 -0
- humex/api/metrics_api/__init__.py +19 -0
- humex/api/metrics_api/_metrics_result_utils.py +44 -0
- humex/api/metrics_api/compute_analyzer_metrics_api.py +307 -0
- humex/api/metrics_api/compute_dag_metrics_api.py +255 -0
- humex/api/metrics_api/convert_analyzer_metrics_api.py +211 -0
- humex/api/metrics_api/monitor_discovery_api.py +212 -0
- humex/api/metrics_api/operator_discovery_api.py +269 -0
- humex/api/metrics_api/test_dag_metrics_api.py +153 -0
- humex/api/metrics_api/visualize_dag_api.py +132 -0
- humex/api/preview_api/__init__.py +5 -0
- humex/api/preview_api/keyframe_preview_api.py +194 -0
- humex/api/scenario_api/__init__.py +5 -0
- humex/api/scenario_api/load_scenario_api.py +643 -0
- humex/api/simulation_api/__init__.py +17 -0
- humex/api/simulation_api/run_simulation_api.py +434 -0
- humex/api/simulation_api/run_simulation_with_analyzer_metrics_api.py +92 -0
- humex/api/simulation_api/run_simulation_with_dag_metrics_api.py +88 -0
- humex/cli/__init__.py +1 -0
- humex/cli/convert.py +340 -0
- humex/cli/evaluate.py +60 -0
- humex/cli/lane_map.py +42 -0
- humex/cli/main.py +29 -0
- humex/cli/package.py +45 -0
- humex/cli/plugins.py +77 -0
- humex/components/__init__.py +18 -0
- humex/components/frame.py +152 -0
- humex/components/object.py +521 -0
- humex/components/perception.py +49 -0
- humex/components/scenario.py +128 -0
- humex/components/statepoint.py +316 -0
- humex/components/trajectory.py +260 -0
- humex/convert/__init__.py +28 -0
- humex/convert/enhance.py +212 -0
- humex/convert/lane_map.py +41 -0
- humex/convert/pipeline.py +156 -0
- humex/convert/role.py +54 -0
- humex/converters/__init__.py +18 -0
- humex/converters/base.py +163 -0
- humex/converters/humex_packager.py +102 -0
- humex/converters/registry.py +110 -0
- humex/converters/testing.py +118 -0
- humex/hmap/__init__.py +22 -0
- humex/hmap/hmap.py +156 -0
- humex/hmap/lane_map.py +669 -0
- humex/hmap/lane_map_builder.py +576 -0
- humex/hmap/lane_map_geometry.py +287 -0
- humex/hmap/road_map.py +743 -0
- humex/hmap/road_map_builder.py +140 -0
- humex/hmap/road_map_loader.py +407 -0
- humex/hmap/role_table.py +286 -0
- humex/hmap/role_table_builder.py +652 -0
- humex/metrics/__init__.py +5 -0
- humex/metrics/analyzer/__init__.py +25 -0
- humex/metrics/analyzer/analyzer_converter.py +305 -0
- humex/metrics/analyzer/common.py +211 -0
- humex/metrics/analyzer/dag_builder.py +368 -0
- humex/metrics/analyzer/dag_converter.py +148 -0
- humex/metrics/analyzer/logic_converter.py +266 -0
- humex/metrics/dag/__init__.py +34 -0
- humex/metrics/dag/dag.py +133 -0
- humex/metrics/dag/dag_evaluator.py +699 -0
- humex/metrics/dag/dag_evaluator_test.py +329 -0
- humex/metrics/dag/dag_node.py +34 -0
- humex/metrics/dag/dag_visualizer.py +357 -0
- humex/metrics/dag/mock_dag_evaluator.py +98 -0
- humex/metrics/metric_trace.py +123 -0
- humex/metrics/monitors/__init__.py +52 -0
- humex/metrics/monitors/catalog/__init__.py +0 -0
- humex/metrics/monitors/catalog/_front_vehicle_utils.py +147 -0
- humex/metrics/monitors/catalog/ego_acceleration.py +32 -0
- humex/metrics/monitors/catalog/ego_center_offset.py +89 -0
- humex/metrics/monitors/catalog/ego_collision.py +93 -0
- humex/metrics/monitors/catalog/ego_heading.py +44 -0
- humex/metrics/monitors/catalog/ego_lane_speed_limit.py +74 -0
- humex/metrics/monitors/catalog/ego_lat_accel.py +54 -0
- humex/metrics/monitors/catalog/ego_lon_accel.py +53 -0
- humex/metrics/monitors/catalog/ego_lon_jerk.py +124 -0
- humex/metrics/monitors/catalog/ego_out_of_map.py +126 -0
- humex/metrics/monitors/catalog/ego_speed.py +30 -0
- humex/metrics/monitors/catalog/ego_speed_excess.py +80 -0
- humex/metrics/monitors/catalog/ego_yaw_rate.py +88 -0
- humex/metrics/monitors/catalog/frame_interval.py +43 -0
- humex/metrics/monitors/catalog/front_vehicle_distance.py +46 -0
- humex/metrics/monitors/catalog/front_vehicle_id.py +40 -0
- humex/metrics/monitors/catalog/lane_change_state.py +19 -0
- humex/metrics/monitors/catalog/lateral_distance.py +102 -0
- humex/metrics/monitors/catalog/lon_dist.py +16 -0
- humex/metrics/monitors/catalog/mock_monitor.py +30 -0
- humex/metrics/monitors/catalog/object_within_ego_buffer.py +105 -0
- humex/metrics/monitors/catalog/stop_line_crossed.py +148 -0
- humex/metrics/monitors/catalog/time_headway.py +50 -0
- humex/metrics/monitors/catalog/ttc_front_vehicle.py +104 -0
- humex/metrics/monitors/monitor_base.py +185 -0
- humex/metrics/monitors/monitor_evaluator.py +84 -0
- humex/metrics/operators/__init__.py +265 -0
- humex/metrics/operators/aggregate.py +119 -0
- humex/metrics/operators/arithmetic.py +97 -0
- humex/metrics/operators/chain_result.py +37 -0
- humex/metrics/operators/compare.py +126 -0
- humex/metrics/operators/compare_test.py +641 -0
- humex/metrics/operators/duration.py +168 -0
- humex/metrics/operators/logic.py +68 -0
- humex/metrics/operators/mask.py +128 -0
- humex/metrics/operators/observe.py +35 -0
- humex/metrics/operators/operator_base.py +176 -0
- humex/metrics/operators/reduce.py +119 -0
- humex/metrics/operators/scenario_window.py +46 -0
- humex/metrics/operators/transform.py +67 -0
- humex/metrics/operators/within.py +154 -0
- humex/metrics/operators/within_test.py +217 -0
- humex/proto/__init__.py +18 -0
- humex/proto/lane_map_pb2.py +40 -0
- humex/proto/map_pb2.py +43 -0
- humex/proto/map_pb2.pyi +84 -0
- humex/proto/metric_dag_pb2.py +41 -0
- humex/proto/metric_dag_pb2.pyi +55 -0
- humex/proto/metric_result_pb2.py +39 -0
- humex/proto/metric_result_pb2.pyi +59 -0
- humex/proto/proto_utils.py +32 -0
- humex/proto/py.typed +0 -0
- humex/proto/robot_pb2.py +53 -0
- humex/proto/role_pb2.py +41 -0
- humex/proto/scenario_pb2.py +55 -0
- humex/proto/scenario_pb2.pyi +107 -0
- humex/proto/service_pb2.py +55 -0
- humex/proto/service_pb2.pyi +84 -0
- humex/proto/signal_pb2.py +35 -0
- humex/proto/signal_pb2.pyi +52 -0
- humex/simulator/__init__.py +6 -0
- humex/simulator/behavior/__init__.py +11 -0
- humex/simulator/behavior/behavior_base.py +56 -0
- humex/simulator/behavior/keyframe.py +367 -0
- humex/simulator/behavior/smartkeyframe.py +610 -0
- humex/simulator/simulator.py +293 -0
- humex/simulator/vehicle/__init__.py +6 -0
- humex/simulator/vehicle/controllers.py +286 -0
- humex/simulator/vehicle/models.py +91 -0
- humex/simulator/visualizer/__init__.py +23 -0
- humex/simulator/visualizer/video_renderer.py +431 -0
- humex/simulator/visualizer/visualizer_3d.py +583 -0
- humex/utils/__init__.py +14 -0
- humex/utils/data_loader.py +220 -0
- humex/utils/dubins_utils.py +231 -0
- humex/utils/math_helper.py +397 -0
- humex/utils/paths.py +88 -0
- humex/utils/physics_helper.py +340 -0
- humex/utils/timestamp.py +109 -0
- humex-0.2.0.dist-info/METADATA +69 -0
- humex-0.2.0.dist-info/RECORD +166 -0
- humex-0.2.0.dist-info/WHEEL +5 -0
- humex-0.2.0.dist-info/entry_points.txt +2 -0
- humex-0.2.0.dist-info/licenses/LICENSE +201 -0
- humex-0.2.0.dist-info/licenses/NOTICE +27 -0
- humex-0.2.0.dist-info/top_level.txt +1 -0
humex/__init__.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""humex — behavioral metrics for autonomous-vehicle and physical-AI scenarios.
|
|
2
|
+
|
|
3
|
+
High-level Python APIs for:
|
|
4
|
+
- Loading and preparing scenarios
|
|
5
|
+
- Analyzing scenarios with metrics
|
|
6
|
+
- Converting and computing metric DAGs
|
|
7
|
+
- Natural language interaction via LLM
|
|
8
|
+
|
|
9
|
+
See ``humex.api.core_apis`` for a comprehensive facade listing all public APIs
|
|
10
|
+
with full signatures, parameter descriptions, and usage examples::
|
|
11
|
+
|
|
12
|
+
import humex.api.core_apis
|
|
13
|
+
help(humex.api.core_apis)
|
|
14
|
+
|
|
15
|
+
from humex.api.core_apis import (
|
|
16
|
+
analyze,
|
|
17
|
+
ScenarioAPI,
|
|
18
|
+
ConvertAnalyzerMetricsAPI,
|
|
19
|
+
ComputeAnalyzerMetricsAPI,
|
|
20
|
+
)
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from .api import (
|
|
24
|
+
Chat,
|
|
25
|
+
ScenarioAPI,
|
|
26
|
+
ConvertAnalyzerMetricsAPI,
|
|
27
|
+
ComputeAnalyzerMetricsAPI,
|
|
28
|
+
)
|
|
29
|
+
from .hmap import HMap, LaneMap, RoadMap, RoleTable, build_lane_map, build_role_table
|
|
30
|
+
|
|
31
|
+
__version__ = "0.2.0"
|
|
32
|
+
|
|
33
|
+
# Plugin-API version. Converter plugins may declare a ``MIN_HUMEX_API_VERSION``
|
|
34
|
+
# class attr; the registry skips converters whose minimum exceeds this value
|
|
35
|
+
# instead of letting an incompatible plugin crash the host. Bump on breaking
|
|
36
|
+
# changes to BaseConverter / ConversionResult / registry contracts.
|
|
37
|
+
__api_version__ = 1
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
"ScenarioAPI",
|
|
41
|
+
"ConvertAnalyzerMetricsAPI",
|
|
42
|
+
"ComputeAnalyzerMetricsAPI",
|
|
43
|
+
"Chat",
|
|
44
|
+
"HMap",
|
|
45
|
+
"LaneMap",
|
|
46
|
+
"RoadMap",
|
|
47
|
+
"RoleTable",
|
|
48
|
+
"build_lane_map",
|
|
49
|
+
"build_role_table",
|
|
50
|
+
]
|
humex/api/__init__.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""High-level API for humex framework.
|
|
2
|
+
|
|
3
|
+
This module provides convenient Python functions and classes for analyzing scenarios,
|
|
4
|
+
loading scenarios, converting metrics configs, and interacting with humex via natural language.
|
|
5
|
+
|
|
6
|
+
Classes:
|
|
7
|
+
- ScenarioAPI: Load scenarios from various sources
|
|
8
|
+
- ConvertAnalyzerMetricsAPI: Convert analyzer configs to DAG format
|
|
9
|
+
- ComputeAnalyzerMetricsAPI: End-to-end metrics computation
|
|
10
|
+
- Chat: LLM chat interface
|
|
11
|
+
- TranslateMetrics: Natural language to metrics config translator
|
|
12
|
+
|
|
13
|
+
Functions (for backward compatibility):
|
|
14
|
+
- chat(): Functional chat interface
|
|
15
|
+
- translate_metrics(): Functional metrics translation interface
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from .scenario_api import ScenarioAPI
|
|
19
|
+
from .metrics_api import ConvertAnalyzerMetricsAPI, ComputeAnalyzerMetricsAPI
|
|
20
|
+
from .ai_api import Chat, TranslateMetrics
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
'ScenarioAPI',
|
|
24
|
+
'ConvertAnalyzerMetricsAPI',
|
|
25
|
+
'ComputeAnalyzerMetricsAPI',
|
|
26
|
+
'Chat',
|
|
27
|
+
'TranslateMetrics',
|
|
28
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""AI API module providing LLM integration with pluggable model support.
|
|
2
|
+
|
|
3
|
+
This module provides interfaces to various AI models (currently Claude via Claude CLI)
|
|
4
|
+
for tasks like chat interactions and metrics requirement translation.
|
|
5
|
+
|
|
6
|
+
Classes:
|
|
7
|
+
- Chat: Class-based chat interface
|
|
8
|
+
- TranslateMetrics: Class-based metrics translation interface
|
|
9
|
+
|
|
10
|
+
Functions (for backward compatibility):
|
|
11
|
+
- chat(): Functional chat interface
|
|
12
|
+
- translate_metrics(): Functional metrics translation interface
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from humex.api.ai_api.chat import Chat
|
|
16
|
+
from humex.api.ai_api.translate_metrics import TranslateMetrics
|
|
17
|
+
|
|
18
|
+
__all__ = ["Chat", "TranslateMetrics"]
|
humex/api/ai_api/chat.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Chat API for humex framework interactions."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from humex.api.ai_api.models._claude_cli import ClaudeCLIModel
|
|
6
|
+
from humex.api.ai_api.models._qwen import QwenModel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Chat:
|
|
10
|
+
"""Chat interface for humex-related queries.
|
|
11
|
+
|
|
12
|
+
Provides a conversational interface for asking questions and getting advice
|
|
13
|
+
about humex framework, scenarios, metrics, and analysis.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, model: str = "claude_cli", qwen_model: Optional[str] = None):
|
|
17
|
+
"""Initialize Chat with specified model.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
model: Model to use for chat. Supports "claude_cli" (default) or "qwen".
|
|
21
|
+
qwen_model: Ollama model name when using "qwen" (default: "qwen2.5:0.5b").
|
|
22
|
+
Examples: "qwen2.5:0.5b", "qwen2.5:7b", "qwen2.5-coder:7b"
|
|
23
|
+
|
|
24
|
+
Raises:
|
|
25
|
+
ValueError: If an unsupported model is specified
|
|
26
|
+
"""
|
|
27
|
+
if model not in ("claude_cli", "qwen"):
|
|
28
|
+
raise ValueError(
|
|
29
|
+
f"Unsupported model: {model}. Supported models: 'claude_cli', 'qwen'"
|
|
30
|
+
)
|
|
31
|
+
self.model = model
|
|
32
|
+
self._qwen_instance = QwenModel(qwen_model) if model == "qwen" else None
|
|
33
|
+
|
|
34
|
+
def send(self, message: str, context: Optional[str] = None) -> str:
|
|
35
|
+
"""Send a chat message and get a response.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
message: User's question or message
|
|
39
|
+
context: Optional context about what the user is working on
|
|
40
|
+
(e.g., "scenario analysis", "metric configuration")
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Plain text response string from the selected model
|
|
44
|
+
|
|
45
|
+
Raises:
|
|
46
|
+
FileNotFoundError: If Claude CLI is not installed (when using claude_cli)
|
|
47
|
+
Exception: If the model call fails
|
|
48
|
+
|
|
49
|
+
Example:
|
|
50
|
+
>>> chat_api = Chat()
|
|
51
|
+
>>> response = chat_api.send("How do I analyze a scenario?")
|
|
52
|
+
>>> print(response)
|
|
53
|
+
# Returns helpful response about analyzing scenarios
|
|
54
|
+
|
|
55
|
+
>>> response = chat_api.send("What metrics should I track?", context="vehicle safety")
|
|
56
|
+
>>> print(response)
|
|
57
|
+
# Returns response tailored to vehicle safety metrics
|
|
58
|
+
"""
|
|
59
|
+
if self.model == "claude_cli":
|
|
60
|
+
return ClaudeCLIModel.chat(message, context)
|
|
61
|
+
elif self.model == "qwen":
|
|
62
|
+
return self._qwen_instance.chat(message, context)
|
|
63
|
+
else:
|
|
64
|
+
raise ValueError(
|
|
65
|
+
f"Unsupported model: {self.model}. Supported models: 'claude_cli', 'qwen'"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# Convenience function for backward compatibility
|
|
70
|
+
def chat(
|
|
71
|
+
message: str,
|
|
72
|
+
model: str = "claude_cli",
|
|
73
|
+
context: Optional[str] = None,
|
|
74
|
+
qwen_model: Optional[str] = None
|
|
75
|
+
) -> str:
|
|
76
|
+
"""Convenience function for chat interactions.
|
|
77
|
+
|
|
78
|
+
This function provides backward compatibility with the functional API.
|
|
79
|
+
For new code, consider using the Chat class directly.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
message: User's question or message
|
|
83
|
+
model: Model to use for chat (default: "claude_cli"). Supports "claude_cli" or "qwen".
|
|
84
|
+
context: Optional context about what the user is working on
|
|
85
|
+
qwen_model: Ollama model name when using "qwen" (default: "qwen2.5:0.5b")
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Plain text response string from the selected model
|
|
89
|
+
"""
|
|
90
|
+
chat_api = Chat(model=model, qwen_model=qwen_model)
|
|
91
|
+
return chat_api.send(message, context=context)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Claude CLI model implementation for AI API."""
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ClaudeCLIModel:
|
|
8
|
+
"""Interface to Claude AI via Claude Code CLI.
|
|
9
|
+
|
|
10
|
+
This class provides methods to interact with Claude through the Claude Code CLI.
|
|
11
|
+
It handles subprocess management, error handling, and response parsing.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
@staticmethod
|
|
15
|
+
def _call_claude(prompt: str) -> str:
|
|
16
|
+
"""Call Claude CLI with a prompt and return the response.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
prompt: The full prompt to send to Claude (including system instructions if needed)
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
The text response from Claude
|
|
23
|
+
|
|
24
|
+
Raises:
|
|
25
|
+
FileNotFoundError: If Claude CLI is not installed
|
|
26
|
+
subprocess.CalledProcessError: If the Claude CLI command fails
|
|
27
|
+
"""
|
|
28
|
+
try:
|
|
29
|
+
result = subprocess.run(
|
|
30
|
+
["claude", "--print", prompt],
|
|
31
|
+
capture_output=True,
|
|
32
|
+
text=True,
|
|
33
|
+
stdin=subprocess.DEVNULL,
|
|
34
|
+
timeout=120
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
if result.returncode != 0:
|
|
38
|
+
error_msg = result.stderr if result.stderr else result.stdout
|
|
39
|
+
raise subprocess.CalledProcessError(
|
|
40
|
+
result.returncode,
|
|
41
|
+
"claude --print",
|
|
42
|
+
output=result.stdout,
|
|
43
|
+
stderr=result.stderr
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
return result.stdout.strip()
|
|
47
|
+
|
|
48
|
+
except FileNotFoundError:
|
|
49
|
+
raise FileNotFoundError(
|
|
50
|
+
"Claude CLI not found. Please ensure Claude Code CLI is installed and available in PATH. "
|
|
51
|
+
"Install with: npm install -g @anthropic-ai/claude"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
@classmethod
|
|
55
|
+
def chat(cls, message: str, context: Optional[str] = None) -> str:
|
|
56
|
+
"""Send a chat message to Claude and get a response.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
message: User's question or message
|
|
60
|
+
context: Optional context about what the user is working on
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
Plain text response from Claude
|
|
64
|
+
|
|
65
|
+
Raises:
|
|
66
|
+
FileNotFoundError: If Claude CLI is not installed
|
|
67
|
+
Exception: If Claude CLI call fails
|
|
68
|
+
"""
|
|
69
|
+
context_msg = ""
|
|
70
|
+
if context:
|
|
71
|
+
context_msg = f"(Context: {context}) "
|
|
72
|
+
|
|
73
|
+
prompt = f"{context_msg}{message}"
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
reply = cls._call_claude(prompt)
|
|
77
|
+
return reply
|
|
78
|
+
except Exception as e:
|
|
79
|
+
raise Exception(f"Chat failed: {str(e)}")
|
|
80
|
+
|
|
81
|
+
@classmethod
|
|
82
|
+
def translate_metrics(cls, prompt: str) -> str:
|
|
83
|
+
"""Translate requirement to metrics YAML configuration using a complete prompt.
|
|
84
|
+
|
|
85
|
+
This method accepts a full prompt that combines system knowledge with user requirements.
|
|
86
|
+
The prompt should be properly formatted and include all necessary context about
|
|
87
|
+
monitors, operators, and DAG structure.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
prompt: Complete prompt for translation, combining system context and user requirement
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
YAML formatted string containing the configuration. Can be directly used
|
|
94
|
+
with humex's analyzer or logic systems.
|
|
95
|
+
|
|
96
|
+
Raises:
|
|
97
|
+
FileNotFoundError: If Claude CLI is not installed
|
|
98
|
+
Exception: If Claude CLI call fails
|
|
99
|
+
"""
|
|
100
|
+
try:
|
|
101
|
+
yaml_config = cls._call_claude(prompt)
|
|
102
|
+
return yaml_config
|
|
103
|
+
except Exception as e:
|
|
104
|
+
raise Exception(f"Failed to translate requirement: {str(e)}")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
if __name__=='__main__':
|
|
108
|
+
x = ClaudeCLIModel.chat(message="hi, what question did i just ask you")
|
|
109
|
+
print(x)
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""Qwen model implementation for AI API via local Ollama.
|
|
2
|
+
|
|
3
|
+
The Ollama endpoint defaults to ``http://localhost:11434``. Override with the
|
|
4
|
+
``HUMEX_LLM_BASE_URL`` env var to point at a remote Ollama instance.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import requests
|
|
9
|
+
from typing import Optional
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class QwenModel:
|
|
13
|
+
"""Interface to Qwen AI via local Ollama API.
|
|
14
|
+
|
|
15
|
+
This class provides methods to interact with Qwen through a locally running
|
|
16
|
+
Ollama server. It handles HTTP requests, error handling, and response parsing.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
BASE_URL = os.environ.get("HUMEX_LLM_BASE_URL", "http://localhost:11434")
|
|
20
|
+
DEFAULT_MODEL = "qwen2.5:0.5b"
|
|
21
|
+
|
|
22
|
+
def __init__(self, model_name: Optional[str] = None):
|
|
23
|
+
"""Initialize QwenModel with specified model.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
model_name: Ollama model name to use (default: "qwen2.5:0.5b").
|
|
27
|
+
Examples: "qwen2.5:0.5b", "qwen2.5:7b", "qwen2.5-coder:7b"
|
|
28
|
+
"""
|
|
29
|
+
self.model_name = model_name or self.DEFAULT_MODEL
|
|
30
|
+
|
|
31
|
+
def _call_qwen(self, prompt: str) -> str:
|
|
32
|
+
"""Call Qwen via Ollama HTTP API and return the response.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
prompt: The full prompt to send to Qwen (including system instructions if needed)
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
The text response from Qwen
|
|
39
|
+
|
|
40
|
+
Raises:
|
|
41
|
+
ConnectionError: If cannot connect to Ollama server
|
|
42
|
+
requests.exceptions.RequestException: If the API request fails
|
|
43
|
+
"""
|
|
44
|
+
url = f"{self.BASE_URL}/api/generate"
|
|
45
|
+
payload = {
|
|
46
|
+
"model": self.model_name,
|
|
47
|
+
"prompt": prompt,
|
|
48
|
+
"stream": False,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
response = requests.post(url, json=payload, timeout=120)
|
|
53
|
+
response.raise_for_status()
|
|
54
|
+
|
|
55
|
+
result = response.json()
|
|
56
|
+
return result.get("response", "").strip()
|
|
57
|
+
|
|
58
|
+
except requests.exceptions.ConnectionError:
|
|
59
|
+
raise ConnectionError(
|
|
60
|
+
f"Cannot connect to Ollama server at {QwenModel.BASE_URL}. "
|
|
61
|
+
"Please ensure Ollama is running with: ollama serve"
|
|
62
|
+
)
|
|
63
|
+
except requests.exceptions.Timeout:
|
|
64
|
+
raise TimeoutError(
|
|
65
|
+
f"Request to Qwen timed out after 120 seconds. "
|
|
66
|
+
"The model may be overloaded or the prompt too complex."
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def chat(self, message: str, context: Optional[str] = None) -> str:
|
|
70
|
+
"""Send a chat message to Qwen and get a response.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
message: User's question or message
|
|
74
|
+
context: Optional context about what the user is working on
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Plain text response from Qwen
|
|
78
|
+
|
|
79
|
+
Raises:
|
|
80
|
+
ConnectionError: If cannot connect to Ollama server
|
|
81
|
+
Exception: If Qwen API call fails
|
|
82
|
+
"""
|
|
83
|
+
context_msg = ""
|
|
84
|
+
if context:
|
|
85
|
+
context_msg = f"(Context: {context}) "
|
|
86
|
+
|
|
87
|
+
prompt = f"{context_msg}{message}"
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
reply = self._call_qwen(prompt)
|
|
91
|
+
return reply
|
|
92
|
+
except Exception as e:
|
|
93
|
+
raise Exception(f"Chat failed: {str(e)}")
|
|
94
|
+
|
|
95
|
+
def translate_metrics(self, prompt: str) -> str:
|
|
96
|
+
"""Translate requirement to metrics YAML configuration using a complete prompt.
|
|
97
|
+
|
|
98
|
+
This method accepts a full prompt that combines system knowledge with user requirements.
|
|
99
|
+
The prompt should be properly formatted and include all necessary context about
|
|
100
|
+
monitors, operators, and DAG structure.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
prompt: Complete prompt for translation, combining system context and user requirement
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
YAML formatted string containing the configuration. Can be directly used
|
|
107
|
+
with humex's analyzer or logic systems.
|
|
108
|
+
|
|
109
|
+
Raises:
|
|
110
|
+
ConnectionError: If cannot connect to Ollama server
|
|
111
|
+
Exception: If Qwen API call fails
|
|
112
|
+
"""
|
|
113
|
+
try:
|
|
114
|
+
yaml_config = self._call_qwen(prompt)
|
|
115
|
+
return yaml_config
|
|
116
|
+
except Exception as e:
|
|
117
|
+
raise Exception(f"Failed to translate requirement: {str(e)}")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
if __name__ == '__main__':
|
|
122
|
+
model = QwenModel()
|
|
123
|
+
response = model.chat("Hello, world!")
|
|
124
|
+
print(response)
|