opencommand 0.1.3__tar.gz → 0.1.4__tar.gz
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.
- {opencommand-0.1.3 → opencommand-0.1.4}/PKG-INFO +1 -1
- {opencommand-0.1.3 → opencommand-0.1.4}/pyproject.toml +1 -1
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/cli.py +22 -4
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/core/config.py +29 -1
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/engine/__init__.py +25 -4
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/engine/runner.py +29 -1
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/system/automatic.py +23 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/system/platform.py +14 -2
- {opencommand-0.1.3 → opencommand-0.1.4}/README.md +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/__init__.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/core/agent.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/core/errors.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/core/logging.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/core/supervisor.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/core/tools.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/knowledge.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/memory/MEMORY.md +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/skills/bash.md +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/skills/desktop_linux.md +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/skills/desktop_macos.md +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/skills/desktop_windows.md +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/skills/powershell.md +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/skills/python.md +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/skills/system.md +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/system/cron.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/system/notify.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/templates.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/tools/desktop.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/tools/desktop_safety.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/tools/files.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/tools/instructions.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/tools/memory.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/tools/playwright.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/tools/research.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/tools/system.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/tools/terminal.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/tools/yara_rules/default.yar +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/providers/provider.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/swarm/agents/commander.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/swarm/agents/worker.py +0 -0
- {opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/tui/dashboard.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: opencommand
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Local-first swarm agent framework: a Commander plans and dispatches a swarm of Workers that research, code, test, and interactively drive the computer to complete long-horizon codebase goals.
|
|
5
5
|
Author: DSiENT
|
|
6
6
|
Author-email: DSiENT <w.caskey7@gmail.com>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "opencommand"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.4"
|
|
4
4
|
description = "Local-first swarm agent framework: a Commander plans and dispatches a swarm of Workers that research, code, test, and interactively drive the computer to complete long-horizon codebase goals."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -60,7 +60,7 @@ def _load_cfg(path: str | None) -> OpenCommandConfig:
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
@click.group()
|
|
63
|
-
@click.version_option(version="0.1.
|
|
63
|
+
@click.version_option(version="0.1.4")
|
|
64
64
|
@click.option("-v", "--verbose", is_flag=True, help="Enable verbose (DEBUG) logging.")
|
|
65
65
|
def cli(verbose: bool) -> None:
|
|
66
66
|
"""OpenCommand - all-in-one local model runner & command center."""
|
|
@@ -73,7 +73,7 @@ def cli(verbose: bool) -> None:
|
|
|
73
73
|
def workspace(path: str | None) -> None:
|
|
74
74
|
"""Show workspace info and embedded engine status."""
|
|
75
75
|
cfg = _load_cfg(path)
|
|
76
|
-
engine = Engine(model_dir=cfg.workspace / "models")
|
|
76
|
+
engine = Engine(model_dir=cfg.workspace / "models", device_map=cfg.device_map)
|
|
77
77
|
click.echo(f"Workspace: {cfg.workspace}")
|
|
78
78
|
click.echo(f"Platform: {describe()}")
|
|
79
79
|
click.echo(engine.status())
|
|
@@ -180,10 +180,27 @@ def config(path: str | None) -> None:
|
|
|
180
180
|
cfg.max_test_loops = click.prompt(
|
|
181
181
|
"Max test+debug fix loops / phase", type=int, default=cfg.max_test_loops)
|
|
182
182
|
cfg.n_gpu_layers = click.prompt(
|
|
183
|
-
"GPU layers to offload (0=CPU, -1=all)
|
|
183
|
+
"GPU layers to offload (0=CPU, -1=all) [legacy default for unpinned roles]",
|
|
184
|
+
type=int, default=cfg.n_gpu_layers)
|
|
184
185
|
cfg.goal_file = click.prompt(
|
|
185
186
|
"Session goal spec file name", default=cfg.goal_file)
|
|
186
187
|
|
|
188
|
+
# --- Per-role device placement ---------------------------------------
|
|
189
|
+
click.echo(click.style("\nModel device placement", fg="cyan", bold=True))
|
|
190
|
+
click.echo("Pin each model role to GPU (offload all layers) or CPU+RAM.")
|
|
191
|
+
click.echo("Example: Commander=GPU, Workers=CPU, VL model=GPU (low VRAM host).")
|
|
192
|
+
dm = dict(cfg.device_map)
|
|
193
|
+
for role in ("commander", "worker", "vision", "vision_small"):
|
|
194
|
+
cur = dm.get(role, "default")
|
|
195
|
+
choice = click.prompt(
|
|
196
|
+
f" {role} device", type=click.Choice(["gpu", "cpu", "default"]),
|
|
197
|
+
default=cur)
|
|
198
|
+
if choice == "default":
|
|
199
|
+
dm.pop(role, None)
|
|
200
|
+
else:
|
|
201
|
+
dm[role] = choice
|
|
202
|
+
cfg.device_map = dm
|
|
203
|
+
|
|
187
204
|
# --- Desktop takeover safety policy ------------------------------------
|
|
188
205
|
click.echo(click.style("\nDesktop takeover safety policy", fg="cyan", bold=True))
|
|
189
206
|
click.echo("Defines exactly what the desktop agent is allowed to do.")
|
|
@@ -421,7 +438,8 @@ def run(goal: str | None, path: str | None, goal_file: str | None, max_iter: int
|
|
|
421
438
|
click.echo(click.style(f"Loaded goal spec: {goal_path}", fg="green"))
|
|
422
439
|
|
|
423
440
|
engine = Engine(model_dir=cfg.workspace / "models",
|
|
424
|
-
pool_size=pool or cfg.max_workers
|
|
441
|
+
pool_size=pool or cfg.max_workers,
|
|
442
|
+
device_map=cfg.device_map)
|
|
425
443
|
sup = Supervisor(max_retries=cfg.max_retries)
|
|
426
444
|
tools = _build_tools(engine, cfg)
|
|
427
445
|
commander = Commander(engine, sup, tools, cfg.workspace)
|
|
@@ -22,10 +22,17 @@ class OpenCommandConfig:
|
|
|
22
22
|
max_research_loops: int = 3 # research refinement loops per phase
|
|
23
23
|
max_test_loops: int = 5 # test+debug fix loops per phase
|
|
24
24
|
batch_size: int = 4 # workers spawned per swarm batch
|
|
25
|
-
n_gpu_layers: int = 0 # 0 = CPU; -1 = all GPU layers
|
|
25
|
+
n_gpu_layers: int = 0 # 0 = CPU; -1 = all GPU layers (legacy global default)
|
|
26
26
|
goal_file: str = "Goal.md" # session goal spec file name
|
|
27
27
|
# --- Desktop takeover safety policy (see modules/tools/desktop_safety.py) -
|
|
28
28
|
desktop_policy: dict = field(default_factory=dict) # empty -> safe defaults
|
|
29
|
+
# --- Per-role device placement -----------------------------------------
|
|
30
|
+
# Maps a model role to "gpu" (offload all layers) or "cpu" (RAM only).
|
|
31
|
+
# Roles: commander, worker, vision, vision_small. Any role not present
|
|
32
|
+
# falls back to the legacy `n_gpu_layers` (GPU if -1, else CPU). This is
|
|
33
|
+
# how a low-VRAM host keeps the Commander on the GPU while Workers run in
|
|
34
|
+
# RAM, and the VL model stays on the GPU for the desktop agent.
|
|
35
|
+
device_map: dict = field(default_factory=dict) # empty -> all roles use n_gpu_layers
|
|
29
36
|
|
|
30
37
|
def save(self) -> None:
|
|
31
38
|
self._path().parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -48,6 +55,7 @@ class OpenCommandConfig:
|
|
|
48
55
|
"n_gpu_layers": self.n_gpu_layers,
|
|
49
56
|
"goal_file": self.goal_file,
|
|
50
57
|
"desktop_policy": self.desktop_policy,
|
|
58
|
+
"device_map": self.device_map,
|
|
51
59
|
}, indent=2)
|
|
52
60
|
|
|
53
61
|
@classmethod
|
|
@@ -72,11 +80,27 @@ class OpenCommandConfig:
|
|
|
72
80
|
n_gpu_layers=d.get("n_gpu_layers", 0),
|
|
73
81
|
goal_file=d.get("goal_file", "Goal.md"),
|
|
74
82
|
desktop_policy=d.get("desktop_policy", {}),
|
|
83
|
+
device_map=d.get("device_map", {}),
|
|
75
84
|
)
|
|
76
85
|
|
|
77
86
|
def _path(self) -> Path:
|
|
78
87
|
return self.workspace / ".opencommand" / "config.json"
|
|
79
88
|
|
|
89
|
+
def n_gpu_layers_for(self, role: str) -> int:
|
|
90
|
+
"""Resolve GPU offload layers for a model role.
|
|
91
|
+
|
|
92
|
+
If ``device_map`` pins the role to "gpu" -> -1 (all layers offloaded);
|
|
93
|
+
if pinned to "cpu" -> 0 (RAM only). When the role is absent from
|
|
94
|
+
``device_map`` we fall back to the legacy global ``n_gpu_layers`` so
|
|
95
|
+
existing configs keep working.
|
|
96
|
+
"""
|
|
97
|
+
dev = self.device_map.get(role)
|
|
98
|
+
if dev == "gpu":
|
|
99
|
+
return -1
|
|
100
|
+
if dev == "cpu":
|
|
101
|
+
return 0
|
|
102
|
+
return self.n_gpu_layers
|
|
103
|
+
|
|
80
104
|
@classmethod
|
|
81
105
|
def from_host(cls, workspace: Path) -> "OpenCommandConfig":
|
|
82
106
|
"""Build a config tuned to the current host via platform autodetection."""
|
|
@@ -85,4 +109,8 @@ class OpenCommandConfig:
|
|
|
85
109
|
cfg = cls(workspace=workspace)
|
|
86
110
|
for k, v in rec["config"].items():
|
|
87
111
|
setattr(cfg, k, v)
|
|
112
|
+
# device_map is a nested dict; apply it explicitly so it isn't
|
|
113
|
+
# clobbered by the flat setattr loop above.
|
|
114
|
+
if "device_map" in rec["config"]:
|
|
115
|
+
cfg.device_map = dict(rec["config"]["device_map"])
|
|
88
116
|
return cfg
|
|
@@ -18,18 +18,34 @@ class Engine:
|
|
|
18
18
|
dedicated instance per worker index for true parallelism.
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
|
-
def __init__(self, model_dir: Path | None = None, pool_size: int = 4
|
|
21
|
+
def __init__(self, model_dir: Path | None = None, pool_size: int = 4,
|
|
22
|
+
device_map: dict | None = None) -> None:
|
|
22
23
|
self.model_dir = model_dir or DEFAULT_MODEL_DIR
|
|
23
24
|
self.pool_size = max(1, pool_size)
|
|
25
|
+
# device_map pins a role to "gpu" (-1 layers) or "cpu" (0 layers);
|
|
26
|
+
# roles absent fall back to the legacy global n_gpu_layers (set per-runner
|
|
27
|
+
# via set_gpu_layers). Kept as a dict so callers can mutate it live.
|
|
28
|
+
self.device_map = dict(device_map or {})
|
|
24
29
|
self._runners: dict[str, LocalRunner] = {}
|
|
25
30
|
self._pools: dict[str, list[LocalRunner]] = {}
|
|
26
31
|
|
|
32
|
+
def _gpu_layers(self, role: str) -> int:
|
|
33
|
+
"""Resolve GPU offload layers for a role from the device map."""
|
|
34
|
+
dev = self.device_map.get(role)
|
|
35
|
+
if dev == "gpu":
|
|
36
|
+
return -1
|
|
37
|
+
if dev == "cpu":
|
|
38
|
+
return 0
|
|
39
|
+
return 0 # default: CPU/RAM unless a runner overrides via set_gpu_layers
|
|
40
|
+
|
|
27
41
|
def runner(self, role: str) -> LocalRunner:
|
|
28
42
|
if role not in self._runners:
|
|
29
43
|
spec = CATALOG.get(role)
|
|
30
44
|
if spec is None:
|
|
31
45
|
raise KeyError(f"No built-in model for role '{role}'")
|
|
32
|
-
|
|
46
|
+
r = LocalRunner(spec, self.model_dir / role)
|
|
47
|
+
r.set_gpu_layers(self._gpu_layers(role))
|
|
48
|
+
self._runners[role] = r
|
|
33
49
|
return self._runners[role]
|
|
34
50
|
|
|
35
51
|
def worker_runner(self, role: str, index: int = 0) -> LocalRunner:
|
|
@@ -40,7 +56,9 @@ class Engine:
|
|
|
40
56
|
pool = self._pools.setdefault(role, [])
|
|
41
57
|
i = index % self.pool_size
|
|
42
58
|
while len(pool) <= i:
|
|
43
|
-
|
|
59
|
+
r = LocalRunner(spec, self.model_dir / role)
|
|
60
|
+
r.set_gpu_layers(self._gpu_layers(role))
|
|
61
|
+
pool.append(r)
|
|
44
62
|
return pool[i]
|
|
45
63
|
|
|
46
64
|
def ensure_downloaded(self, role: str) -> Path:
|
|
@@ -62,5 +80,8 @@ class Engine:
|
|
|
62
80
|
state = "instantiated (lazy)"
|
|
63
81
|
else:
|
|
64
82
|
state = "loaded"
|
|
65
|
-
|
|
83
|
+
dev = self.device_map.get(role, "default")
|
|
84
|
+
dev_label = f"device={dev}" if dev != "default" else "device=default"
|
|
85
|
+
lines.append(f" - {role}: {spec.repo_id} [{spec.kind}] "
|
|
86
|
+
f"{state} ({dev_label})")
|
|
66
87
|
return "\n".join(lines)
|
|
@@ -87,6 +87,19 @@ class LocalRunner:
|
|
|
87
87
|
self.model_dir = model_dir
|
|
88
88
|
self._llm = None
|
|
89
89
|
self._lock = threading.Lock()
|
|
90
|
+
# Per-runner GPU offload override. The Engine sets this from the
|
|
91
|
+
# device_map (role -> "gpu"|"cpu"); -1 = all layers, 0 = CPU/RAM.
|
|
92
|
+
self._gpu_layers = spec.n_gpu_layers
|
|
93
|
+
|
|
94
|
+
def set_gpu_layers(self, n: int) -> None:
|
|
95
|
+
"""Override how many layers to offload to the GPU for this runner.
|
|
96
|
+
|
|
97
|
+
Must be called before the model is loaded. -1 offloads all layers
|
|
98
|
+
(GPU mode); 0 keeps everything in RAM (CPU mode).
|
|
99
|
+
"""
|
|
100
|
+
if self._llm is not None:
|
|
101
|
+
raise RuntimeError("cannot change GPU layers after the model is loaded")
|
|
102
|
+
self._gpu_layers = n
|
|
90
103
|
|
|
91
104
|
def download(self) -> Path:
|
|
92
105
|
"""Ensure weights exist locally; return the model path (no load)."""
|
|
@@ -123,6 +136,21 @@ class LocalRunner:
|
|
|
123
136
|
pass
|
|
124
137
|
return Path(path)
|
|
125
138
|
|
|
139
|
+
def unload(self) -> None:
|
|
140
|
+
"""Release the mapped weights so the RAM/VRAM is freed.
|
|
141
|
+
|
|
142
|
+
Used by the Commander to drop itself from the GPU while the VL desktop
|
|
143
|
+
agent runs, then re-load on demand. Safe to call when not loaded.
|
|
144
|
+
"""
|
|
145
|
+
with self._lock:
|
|
146
|
+
if self._llm is not None:
|
|
147
|
+
log.info("unloading model role=%s", self.spec.role)
|
|
148
|
+
try:
|
|
149
|
+
self._llm.close()
|
|
150
|
+
except Exception: # noqa: BLE001
|
|
151
|
+
pass
|
|
152
|
+
self._llm = None
|
|
153
|
+
|
|
126
154
|
def _ensure_loaded(self) -> None:
|
|
127
155
|
# Guard construction with the lock so concurrent first-use from multiple
|
|
128
156
|
# worker threads can't build two Llama instances into the same slot.
|
|
@@ -135,7 +163,7 @@ class LocalRunner:
|
|
|
135
163
|
kwargs: dict[str, Any] = {
|
|
136
164
|
"model_path": str(self._resolve_path()),
|
|
137
165
|
"n_ctx": self.spec.n_ctx,
|
|
138
|
-
"n_gpu_layers": self.
|
|
166
|
+
"n_gpu_layers": self._gpu_layers,
|
|
139
167
|
"verbose": False,
|
|
140
168
|
}
|
|
141
169
|
if self.spec.kind == "vision":
|
|
@@ -120,6 +120,12 @@ async def _live_verify(commander: Commander, goal: str) -> "LiveVerifyResult":
|
|
|
120
120
|
Returns a LiveVerifyResult. Only meaningful when the desktop tool is wired
|
|
121
121
|
and vision is enabled; otherwise reports a no-op pass so the pipeline can
|
|
122
122
|
continue without a UI target.
|
|
123
|
+
|
|
124
|
+
Device-placement behavior: by default the Commander is unloaded from the
|
|
125
|
+
GPU while the VL desktop agent runs (freeing VRAM for the vision model),
|
|
126
|
+
then re-loaded so the Commander can review the agent's actions + report and
|
|
127
|
+
continue the loop. If the Commander is pinned to the same device as the VL
|
|
128
|
+
model (both GPU) we skip the unload to avoid an unnecessary reload churn.
|
|
123
129
|
"""
|
|
124
130
|
from ...modules.tools.desktop import DesktopTool
|
|
125
131
|
|
|
@@ -128,11 +134,28 @@ async def _live_verify(commander: Commander, goal: str) -> "LiveVerifyResult":
|
|
|
128
134
|
if desktop is None or not getattr(desktop, "vision", None):
|
|
129
135
|
return LiveVerifyResult(ok=True, summary="no desktop tool/vision; skipped",
|
|
130
136
|
detail="")
|
|
137
|
+
# Unload the Commander from the GPU while the VL agent drives the desktop,
|
|
138
|
+
# unless the Commander is itself pinned to CPU (nothing to free).
|
|
139
|
+
commander_runner = commander.provider
|
|
140
|
+
unloaded = False
|
|
131
141
|
try:
|
|
142
|
+
if getattr(commander_runner, "spec", None) is not None:
|
|
143
|
+
role = getattr(commander_runner.spec, "role", None)
|
|
144
|
+
# Only unload if the Commander sits on the GPU (would compete with VL).
|
|
145
|
+
if commander.engine.device_map.get(role) == "gpu":
|
|
146
|
+
commander_runner.unload()
|
|
147
|
+
unloaded = True
|
|
132
148
|
out = desktop.run(f"Verify the goal is satisfied on screen: {goal}", steps=8)
|
|
133
149
|
except Exception as e: # noqa: BLE001
|
|
134
150
|
return LiveVerifyResult(ok=False, summary="desktop tool error",
|
|
135
151
|
detail=str(e))
|
|
152
|
+
finally:
|
|
153
|
+
# Re-load the Commander so it can review the agent's report and continue.
|
|
154
|
+
if unloaded:
|
|
155
|
+
try:
|
|
156
|
+
commander_runner._ensure_loaded()
|
|
157
|
+
except Exception: # noqa: BLE001
|
|
158
|
+
pass
|
|
136
159
|
ok = "ERROR" not in out and "done" in out.lower()
|
|
137
160
|
return LiveVerifyResult(ok=ok, summary="interactive check completed", detail=out)
|
|
138
161
|
|
|
@@ -179,7 +179,18 @@ def recommend_config(d: dict | None = None) -> dict:
|
|
|
179
179
|
d = d or detect()
|
|
180
180
|
cores = max(1, d["cores"])
|
|
181
181
|
pool = max(1, min(cores - 1, 8)) # leave cores for OS; cap to avoid RAM blowup
|
|
182
|
-
|
|
182
|
+
has_gpu = d["gpu"]["backend"] != "none"
|
|
183
|
+
n_gpu_layers = -1 if has_gpu else 0
|
|
184
|
+
# Per-role device placement heuristic. We don't know VRAM size from detect()
|
|
185
|
+
# alone, so we use a conservative split: if a GPU exists, put the small
|
|
186
|
+
# interactive models (commander planner + the VL desktop agent) on the GPU
|
|
187
|
+
# and keep the heavier worker pool in CPU+RAM (which scales with RAM, not
|
|
188
|
+
# VRAM). On a no-GPU host everything is CPU. This is the same split a
|
|
189
|
+
# low-VRAM host (e.g. 8GB VRAM / 32GB RAM) would pick by hand.
|
|
190
|
+
device_map = {}
|
|
191
|
+
if has_gpu:
|
|
192
|
+
device_map = {"commander": "gpu", "worker": "cpu", "vision": "gpu",
|
|
193
|
+
"vision_small": "gpu"}
|
|
183
194
|
build_flags = []
|
|
184
195
|
if d["isa"]["avx512"]:
|
|
185
196
|
build_flags.append("-DGGML_AVX512=ON")
|
|
@@ -188,7 +199,8 @@ def recommend_config(d: dict | None = None) -> dict:
|
|
|
188
199
|
return {
|
|
189
200
|
"config": {
|
|
190
201
|
"max_workers": pool,
|
|
191
|
-
"vision":
|
|
202
|
+
"vision": has_gpu or cores >= 4,
|
|
203
|
+
"device_map": device_map,
|
|
192
204
|
},
|
|
193
205
|
"engine": {"pool_size": pool},
|
|
194
206
|
"runner": {"n_gpu_layers": n_gpu_layers},
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opencommand-0.1.3 → opencommand-0.1.4}/src/opencommand/modules/tools/yara_rules/default.yar
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|