@archetypeai/ds-cli 0.3.9 ā 0.3.11
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.
- package/bin.js +4 -0
- package/commands/create.js +76 -33
- package/commands/init.js +49 -19
- package/files/AGENTS.md +19 -3
- package/files/CLAUDE.md +21 -3
- package/files/rules/accessibility.md +49 -0
- package/files/rules/frontend-architecture.md +77 -0
- package/files/skills/apply-ds/SKILL.md +86 -82
- package/files/skills/apply-ds/scripts/audit.sh +169 -0
- package/files/skills/apply-ds/scripts/setup.sh +48 -166
- package/files/skills/create-dashboard/SKILL.md +12 -0
- package/files/skills/embedding-from-file/SKILL.md +415 -0
- package/files/skills/embedding-from-sensor/SKILL.md +406 -0
- package/files/skills/embedding-upload/SKILL.md +414 -0
- package/files/skills/fix-accessibility/SKILL.md +57 -9
- package/files/skills/newton-activity-monitor-lens-on-video/SKILL.md +817 -0
- package/files/skills/newton-camera-frame-analysis/SKILL.md +611 -0
- package/files/skills/newton-camera-frame-analysis/scripts/activity-monitor-frame.py +165 -0
- package/files/skills/newton-camera-frame-analysis/scripts/captures/logs/api_responses_20260206_105610.json +62 -0
- package/files/skills/newton-camera-frame-analysis/scripts/continuous_monitor.py +119 -0
- package/files/skills/newton-direct-query/SKILL.md +212 -0
- package/files/skills/newton-direct-query/scripts/direct_query.py +129 -0
- package/files/skills/newton-machine-state-from-file/SKILL.md +545 -0
- package/files/skills/newton-machine-state-from-sensor/SKILL.md +707 -0
- package/files/skills/newton-machine-state-upload/SKILL.md +986 -0
- package/lib/add-ds-config-codeagent.js +5 -1
- package/lib/is-interactive.js +19 -0
- package/lib/scaffold-ds-svelte-project.js +117 -0
- package/package.json +1 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Simplified webcam capture and analysis using ArchetypeAI Newton model
|
|
4
|
+
"""
|
|
5
|
+
import cv2
|
|
6
|
+
import base64
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import json
|
|
10
|
+
import time
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from archetypeai.api_client import ArchetypeAI
|
|
14
|
+
from archetypeai.utils import base64_encode
|
|
15
|
+
|
|
16
|
+
# Model configuration - defined once and reused
|
|
17
|
+
MODEL_CONFIG = {
|
|
18
|
+
"model_version": "Newton::c2_4_7b_251215a172f6d7",
|
|
19
|
+
"template_name": "image_qa_template_task",
|
|
20
|
+
"instruction": "Answer the following question about the image:",
|
|
21
|
+
"max_new_tokens": 512
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
def capture_webcam_image(camera_index=0, output_dir="captures"):
|
|
25
|
+
"""Capture image from webcam and save it"""
|
|
26
|
+
Path(output_dir).mkdir(exist_ok=True)
|
|
27
|
+
|
|
28
|
+
cap = cv2.VideoCapture(camera_index)
|
|
29
|
+
ret, frame = cap.read()
|
|
30
|
+
cap.release()
|
|
31
|
+
|
|
32
|
+
if not ret:
|
|
33
|
+
raise Exception("Failed to capture image from webcam")
|
|
34
|
+
|
|
35
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
36
|
+
filename = f"{output_dir}/webcam_{timestamp}.jpg"
|
|
37
|
+
cv2.imwrite(filename, frame)
|
|
38
|
+
print(f"šø Captured: {filename}")
|
|
39
|
+
return filename
|
|
40
|
+
|
|
41
|
+
def analyze_webcam_image(api_key, image_path, question="Describe what you see"):
|
|
42
|
+
"""Analyze captured image using Newton model"""
|
|
43
|
+
|
|
44
|
+
client = ArchetypeAI(api_key)
|
|
45
|
+
|
|
46
|
+
# Lens configuration with model parameters
|
|
47
|
+
lens_config = {
|
|
48
|
+
"lens_name": f"webcam-analysis-{int(time.time())}",
|
|
49
|
+
"lens_config": {
|
|
50
|
+
"model_pipeline": [{
|
|
51
|
+
"processor_name": "lens_camera_processor",
|
|
52
|
+
"processor_config": {}
|
|
53
|
+
}],
|
|
54
|
+
"model_parameters": {
|
|
55
|
+
**MODEL_CONFIG,
|
|
56
|
+
"focus": question,
|
|
57
|
+
"camera_buffer_size": 1,
|
|
58
|
+
"min_replicas": 1,
|
|
59
|
+
"max_replicas": 1
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
lens_id = None
|
|
65
|
+
session_id = None
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
# 1. Register lens
|
|
69
|
+
print("š§ Setting up analysis...")
|
|
70
|
+
lens = client.lens.register(lens_config)
|
|
71
|
+
lens_id = lens['lens_id']
|
|
72
|
+
|
|
73
|
+
# 2. Create session
|
|
74
|
+
session = client.lens.sessions.create(lens_id)
|
|
75
|
+
session_id = session['session_id']
|
|
76
|
+
|
|
77
|
+
# 3. Wait for session ready
|
|
78
|
+
print("ā³ Initializing...")
|
|
79
|
+
for _ in range(30):
|
|
80
|
+
try:
|
|
81
|
+
status = client.lens.sessions.process_event(
|
|
82
|
+
session_id, {"type": "session.status"}
|
|
83
|
+
)
|
|
84
|
+
if status.get('session_status') in ['3', 'LensSessionStatus.SESSION_STATUS_RUNNING']:
|
|
85
|
+
break
|
|
86
|
+
except:
|
|
87
|
+
pass
|
|
88
|
+
time.sleep(0.5)
|
|
89
|
+
|
|
90
|
+
# 4. Initialize processor
|
|
91
|
+
client.lens.sessions.process_event(session_id, {
|
|
92
|
+
"type": "session.modify",
|
|
93
|
+
"event_data": {"camera_buffer_size": 1}
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
# 5. Prepare image
|
|
97
|
+
base64_img = base64_encode(image_path).replace("data:image/jpeg;base64,", "")
|
|
98
|
+
|
|
99
|
+
# 6. Query with image
|
|
100
|
+
print("š Analyzing image...")
|
|
101
|
+
event = {
|
|
102
|
+
"type": "model.query",
|
|
103
|
+
"event_data": {
|
|
104
|
+
**MODEL_CONFIG,
|
|
105
|
+
"focus": question,
|
|
106
|
+
"data": [{
|
|
107
|
+
"type": "base64_img",
|
|
108
|
+
"base64_img": base64_img
|
|
109
|
+
}]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
response = client.lens.sessions.process_event(session_id, event)
|
|
114
|
+
|
|
115
|
+
# 7. Extract result
|
|
116
|
+
if response.get('type') == 'model.query.response':
|
|
117
|
+
result = response.get('event_data', {}).get('response', '')
|
|
118
|
+
if isinstance(result, list):
|
|
119
|
+
result = result[0] if result else "No response"
|
|
120
|
+
print(f"\nš Answer: {result}")
|
|
121
|
+
return result
|
|
122
|
+
else:
|
|
123
|
+
print(f"Unexpected response: {json.dumps(response, indent=2)}")
|
|
124
|
+
return None
|
|
125
|
+
|
|
126
|
+
finally:
|
|
127
|
+
# Cleanup
|
|
128
|
+
if session_id:
|
|
129
|
+
try:
|
|
130
|
+
client.lens.sessions.destroy(session_id)
|
|
131
|
+
except:
|
|
132
|
+
pass
|
|
133
|
+
if lens_id:
|
|
134
|
+
try:
|
|
135
|
+
client.lens.delete(lens_id)
|
|
136
|
+
except:
|
|
137
|
+
pass
|
|
138
|
+
|
|
139
|
+
def main():
|
|
140
|
+
# Get API key
|
|
141
|
+
api_key = os.environ.get("ARCHETYPE_API_KEY") or os.environ.get("ATAI_API_KEY")
|
|
142
|
+
|
|
143
|
+
if not api_key:
|
|
144
|
+
print("Error: Please set ARCHETYPE_API_KEY or ATAI_API_KEY environment variable")
|
|
145
|
+
sys.exit(1)
|
|
146
|
+
|
|
147
|
+
# Parse arguments
|
|
148
|
+
question = sys.argv[1] if len(sys.argv) > 1 else "Describe what you see"
|
|
149
|
+
camera_index = int(sys.argv[2]) if len(sys.argv) > 2 else 0
|
|
150
|
+
|
|
151
|
+
print(f"š· Camera: {camera_index}")
|
|
152
|
+
print(f"ā Question: {question}")
|
|
153
|
+
print("-" * 40)
|
|
154
|
+
|
|
155
|
+
try:
|
|
156
|
+
# Capture and analyze
|
|
157
|
+
image_path = capture_webcam_image(camera_index)
|
|
158
|
+
analyze_webcam_image(api_key, image_path, question)
|
|
159
|
+
|
|
160
|
+
except Exception as e:
|
|
161
|
+
print(f"ā Error: {e}")
|
|
162
|
+
sys.exit(1)
|
|
163
|
+
|
|
164
|
+
if __name__ == "__main__":
|
|
165
|
+
main()
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"timestamp": "2026-02-06T10:57:17.747432",
|
|
4
|
+
"frame_number": 1,
|
|
5
|
+
"response_time_seconds": 63.071,
|
|
6
|
+
"request": {
|
|
7
|
+
"type": "model.query",
|
|
8
|
+
"event_data": {
|
|
9
|
+
"model_version": "Newton::c2_3_7b_2508014e10af56",
|
|
10
|
+
"template_name": "image_qa_template_task",
|
|
11
|
+
"instruction": "Answer the following question about the image:",
|
|
12
|
+
"focus": "webcam_frame.py",
|
|
13
|
+
"max_new_tokens": 512,
|
|
14
|
+
"data": "[IMAGE DATA OMITTED]"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"response": {
|
|
18
|
+
"type": "model.query.response",
|
|
19
|
+
"message": "Response timed out for query"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"timestamp": "2026-02-06T10:57:26.154989",
|
|
24
|
+
"frame_number": 2,
|
|
25
|
+
"response_time_seconds": 1.968,
|
|
26
|
+
"request": {
|
|
27
|
+
"type": "model.query",
|
|
28
|
+
"event_data": {
|
|
29
|
+
"model_version": "Newton::c2_3_7b_2508014e10af56",
|
|
30
|
+
"template_name": "image_qa_template_task",
|
|
31
|
+
"instruction": "Answer the following question about the image:",
|
|
32
|
+
"focus": "webcam_frame.py",
|
|
33
|
+
"max_new_tokens": 512,
|
|
34
|
+
"data": "[IMAGE DATA OMITTED]"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"response": {
|
|
38
|
+
"type": "error",
|
|
39
|
+
"message": "Unknown session id: lsn-26020627e21501c0bdb5a9082b8cdd"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"timestamp": "2026-02-06T10:57:42.701721",
|
|
44
|
+
"frame_number": 3,
|
|
45
|
+
"response_time_seconds": 10.079,
|
|
46
|
+
"request": {
|
|
47
|
+
"type": "model.query",
|
|
48
|
+
"event_data": {
|
|
49
|
+
"model_version": "Newton::c2_3_7b_2508014e10af56",
|
|
50
|
+
"template_name": "image_qa_template_task",
|
|
51
|
+
"instruction": "Answer the following question about the image:",
|
|
52
|
+
"focus": "webcam_frame.py",
|
|
53
|
+
"max_new_tokens": 512,
|
|
54
|
+
"data": "[IMAGE DATA OMITTED]"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"response": {
|
|
58
|
+
"type": "error",
|
|
59
|
+
"message": "Unknown session id: lsn-26020627e21501c0bdb5a9082b8cdd"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
]
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Continuous monitoring script that captures and analyzes frames every 5 seconds."""
|
|
3
|
+
|
|
4
|
+
import sys
|
|
5
|
+
import os
|
|
6
|
+
import time
|
|
7
|
+
import signal
|
|
8
|
+
import argparse
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
sys.path.append('skills/activity-monitor-frame-query/scripts')
|
|
13
|
+
from webcam_analyze import capture_webcam_image, analyze_image
|
|
14
|
+
|
|
15
|
+
class ContinuousMonitor:
|
|
16
|
+
def __init__(self, camera_index=0, output_dir="captures", interval=5, focus="Describe what you see"):
|
|
17
|
+
self.camera_index = camera_index
|
|
18
|
+
self.output_dir = output_dir
|
|
19
|
+
self.interval = interval
|
|
20
|
+
self.focus = focus
|
|
21
|
+
self.running = True
|
|
22
|
+
self.frame_count = 0
|
|
23
|
+
|
|
24
|
+
signal.signal(signal.SIGINT, self.signal_handler)
|
|
25
|
+
signal.signal(signal.SIGTERM, self.signal_handler)
|
|
26
|
+
|
|
27
|
+
Path(output_dir).mkdir(exist_ok=True)
|
|
28
|
+
|
|
29
|
+
self.api_key = os.environ.get("ATAI_API_KEY")
|
|
30
|
+
if not self.api_key:
|
|
31
|
+
raise RuntimeError("ATAI_API_KEY environment variable not set")
|
|
32
|
+
|
|
33
|
+
def signal_handler(self, signum, frame):
|
|
34
|
+
print("\n\nStopping continuous monitoring...")
|
|
35
|
+
self.running = False
|
|
36
|
+
|
|
37
|
+
def run(self):
|
|
38
|
+
"""Run continuous monitoring loop."""
|
|
39
|
+
print(f"Starting continuous monitoring (Ctrl+C to stop)")
|
|
40
|
+
print(f"Camera: {self.camera_index}, Interval: {self.interval}s")
|
|
41
|
+
print(f"Output directory: {self.output_dir}")
|
|
42
|
+
print(f"Analysis focus: {self.focus}")
|
|
43
|
+
print("-" * 60)
|
|
44
|
+
|
|
45
|
+
while self.running:
|
|
46
|
+
try:
|
|
47
|
+
self.frame_count += 1
|
|
48
|
+
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
49
|
+
print(f"\n[Frame {self.frame_count}] {timestamp}")
|
|
50
|
+
|
|
51
|
+
image_path = capture_webcam_image(self.camera_index, self.output_dir)
|
|
52
|
+
|
|
53
|
+
analyze_image(self.api_key, image_path, self.focus)
|
|
54
|
+
|
|
55
|
+
if self.running:
|
|
56
|
+
print(f"Waiting {self.interval} seconds...")
|
|
57
|
+
time.sleep(self.interval)
|
|
58
|
+
|
|
59
|
+
except KeyboardInterrupt:
|
|
60
|
+
self.running = False
|
|
61
|
+
break
|
|
62
|
+
except Exception as e:
|
|
63
|
+
print(f"Error during capture/analysis: {e}")
|
|
64
|
+
if self.running:
|
|
65
|
+
print(f"Retrying in {self.interval} seconds...")
|
|
66
|
+
time.sleep(self.interval)
|
|
67
|
+
|
|
68
|
+
print(f"\nMonitoring complete. Captured {self.frame_count} frames.")
|
|
69
|
+
print(f"Images saved in: {self.output_dir}/")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def main():
|
|
73
|
+
parser = argparse.ArgumentParser(
|
|
74
|
+
description="Continuously capture and analyze webcam frames at regular intervals"
|
|
75
|
+
)
|
|
76
|
+
parser.add_argument(
|
|
77
|
+
"focus",
|
|
78
|
+
nargs="?",
|
|
79
|
+
default="Describe what you see and any changes from the previous frame",
|
|
80
|
+
help="Question or focus for analysis (default: describe changes)"
|
|
81
|
+
)
|
|
82
|
+
parser.add_argument(
|
|
83
|
+
"--camera", "-c",
|
|
84
|
+
type=int,
|
|
85
|
+
default=0,
|
|
86
|
+
help="Camera index (0 for built-in, 1+ for external)"
|
|
87
|
+
)
|
|
88
|
+
parser.add_argument(
|
|
89
|
+
"--interval", "-i",
|
|
90
|
+
type=float,
|
|
91
|
+
default=5.0,
|
|
92
|
+
help="Capture interval in seconds (default: 5)"
|
|
93
|
+
)
|
|
94
|
+
parser.add_argument(
|
|
95
|
+
"--output-dir", "-o",
|
|
96
|
+
default="captures",
|
|
97
|
+
help="Directory for saved captures (default: captures)"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
args = parser.parse_args()
|
|
101
|
+
|
|
102
|
+
monitor = ContinuousMonitor(
|
|
103
|
+
camera_index=args.camera,
|
|
104
|
+
output_dir=args.output_dir,
|
|
105
|
+
interval=args.interval,
|
|
106
|
+
focus=args.focus
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
monitor.run()
|
|
111
|
+
except Exception as e:
|
|
112
|
+
print(f"Fatal error: {e}")
|
|
113
|
+
return 1
|
|
114
|
+
|
|
115
|
+
return 0
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
if __name__ == "__main__":
|
|
119
|
+
exit(main())
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: newton-direct-query
|
|
3
|
+
description: Simple direct query to Newton model using the /query API endpoint. Test API connectivity, run text queries, or post-process results from other lenses. No lens registration or session needed.
|
|
4
|
+
argument-hint: [query]
|
|
5
|
+
allowed-tools: Bash(python *), Read
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Newton Direct Query (Newton /query endpoint)
|
|
9
|
+
|
|
10
|
+
Send a text query directly to Newton via `POST /v0.5/query`. No lens registration, no session, no SSE ā just a simple request/response. Use for API testing, text Q&A, or post-processing results from other lenses.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## API Endpoint
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
POST https://api.u1.archetypeai.app/v0.5/query
|
|
18
|
+
Authorization: Bearer {apiKey}
|
|
19
|
+
Content-Type: application/json
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Request Body
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"query": "Your question or prompt here",
|
|
27
|
+
"system_prompt": "System-level instruction",
|
|
28
|
+
"instruction_prompt": "System-level instruction",
|
|
29
|
+
"file_ids": [],
|
|
30
|
+
"model": "Newton::c2_4_7b_251215a172f6d7",
|
|
31
|
+
"max_new_tokens": 1024,
|
|
32
|
+
"sanitize": false
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
| Field | Type | Description |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `query` | string | The user prompt / question (required) |
|
|
39
|
+
| `system_prompt` | string | System-level instruction guiding the model |
|
|
40
|
+
| `instruction_prompt` | string | Same as `system_prompt` ā set both to the same value |
|
|
41
|
+
| `file_ids` | string[] | File IDs to include as context (empty for text-only) |
|
|
42
|
+
| `model` | string | Model ID (default: `Newton::c2_4_7b_251215a172f6d7`) |
|
|
43
|
+
| `max_new_tokens` | number | Max response length (default: 1024) |
|
|
44
|
+
| `sanitize` | boolean | Whether to sanitize input (default: false) |
|
|
45
|
+
|
|
46
|
+
**IMPORTANT:** The body uses `model` (not `model_version`) and `system_prompt` + `instruction_prompt` (not `instruction`). Both `system_prompt` and `instruction_prompt` should be set to the same value.
|
|
47
|
+
|
|
48
|
+
## Response Structure
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"response": {
|
|
53
|
+
"response": ["The model's answer text here"]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Extract the text using this priority chain:
|
|
59
|
+
1. `data.response.response[0]` (most common)
|
|
60
|
+
2. `data.response[0]` (fallback)
|
|
61
|
+
3. `data.response` as string (fallback)
|
|
62
|
+
4. `data.text` (fallback)
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Web / JavaScript Implementation
|
|
67
|
+
|
|
68
|
+
Uses a config object pattern with `systemPrompt` (optional, defaults to `''`) and `fileIds` (optional, defaults to `[]`). Timeout is 120s since Newton queries can be slow for long prompts.
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
/**
|
|
72
|
+
* @param {Object} config
|
|
73
|
+
* @param {string} config.apiKey
|
|
74
|
+
* @param {string} config.query - The user prompt to send
|
|
75
|
+
* @param {string} [config.systemPrompt=''] - Optional system/instruction prompt
|
|
76
|
+
* @param {string[]} [config.fileIds=[]] - Optional file IDs to include as context
|
|
77
|
+
* @param {number} [config.maxNewTokens=1024]
|
|
78
|
+
* @returns {Promise<string>} The model's text response
|
|
79
|
+
*/
|
|
80
|
+
async function runDirectQuery(config) {
|
|
81
|
+
const { apiKey, query, systemPrompt = '', fileIds = [], maxNewTokens = 1024 } = config
|
|
82
|
+
|
|
83
|
+
const response = await fetch('https://api.u1.archetypeai.app/v0.5/query', {
|
|
84
|
+
method: 'POST',
|
|
85
|
+
headers: {
|
|
86
|
+
Authorization: `Bearer ${apiKey}`,
|
|
87
|
+
'Content-Type': 'application/json',
|
|
88
|
+
},
|
|
89
|
+
body: JSON.stringify({
|
|
90
|
+
query,
|
|
91
|
+
system_prompt: systemPrompt,
|
|
92
|
+
instruction_prompt: systemPrompt,
|
|
93
|
+
file_ids: fileIds,
|
|
94
|
+
model: 'Newton::c2_4_7b_251215a172f6d7',
|
|
95
|
+
max_new_tokens: maxNewTokens,
|
|
96
|
+
sanitize: false,
|
|
97
|
+
}),
|
|
98
|
+
signal: AbortSignal.timeout(120000),
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
if (!response.ok) {
|
|
102
|
+
const errorBody = await response.json().catch(() => ({}))
|
|
103
|
+
throw new Error(`Query failed: ${response.status} - ${JSON.stringify(errorBody)}`)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const data = await response.json()
|
|
107
|
+
|
|
108
|
+
// Extract response text ā nested response.response[0] is most common
|
|
109
|
+
if (data.response?.response && Array.isArray(data.response.response)) {
|
|
110
|
+
return data.response.response[0] || ''
|
|
111
|
+
}
|
|
112
|
+
if (data.response && Array.isArray(data.response)) {
|
|
113
|
+
return data.response[0] || ''
|
|
114
|
+
}
|
|
115
|
+
if (data.response && typeof data.response === 'string') {
|
|
116
|
+
return data.response
|
|
117
|
+
}
|
|
118
|
+
if (data.text) {
|
|
119
|
+
return data.text
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return JSON.stringify(data)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Usage
|
|
126
|
+
const answer = await runDirectQuery({
|
|
127
|
+
apiKey,
|
|
128
|
+
query: 'What is the capital of France?',
|
|
129
|
+
systemPrompt: 'Answer the question concisely.',
|
|
130
|
+
})
|
|
131
|
+
console.log(answer) // "Paris"
|
|
132
|
+
|
|
133
|
+
// With file context
|
|
134
|
+
const summary = await runDirectQuery({
|
|
135
|
+
apiKey,
|
|
136
|
+
query: 'Summarize the sensor data patterns.',
|
|
137
|
+
systemPrompt: 'You are a sensor data analyst.',
|
|
138
|
+
fileIds: ['file-abc123'],
|
|
139
|
+
})
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Python Implementation
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
import os
|
|
148
|
+
import requests
|
|
149
|
+
|
|
150
|
+
API_URL = "https://api.u1.archetypeai.app/v0.5/query"
|
|
151
|
+
|
|
152
|
+
def query_newton(query: str, system_prompt: str, api_key: str, max_new_tokens: int = 1024) -> str:
|
|
153
|
+
"""Send a direct text query to Newton."""
|
|
154
|
+
response = requests.post(
|
|
155
|
+
API_URL,
|
|
156
|
+
headers={
|
|
157
|
+
"Authorization": f"Bearer {api_key}",
|
|
158
|
+
"Content-Type": "application/json",
|
|
159
|
+
},
|
|
160
|
+
json={
|
|
161
|
+
"query": query,
|
|
162
|
+
"system_prompt": system_prompt,
|
|
163
|
+
"instruction_prompt": system_prompt,
|
|
164
|
+
"file_ids": [],
|
|
165
|
+
"model": "Newton::c2_4_7b_251215a172f6d7",
|
|
166
|
+
"max_new_tokens": max_new_tokens,
|
|
167
|
+
"sanitize": False,
|
|
168
|
+
},
|
|
169
|
+
timeout=60,
|
|
170
|
+
)
|
|
171
|
+
response.raise_for_status()
|
|
172
|
+
data = response.json()
|
|
173
|
+
|
|
174
|
+
# Extract response text (multiple possible shapes)
|
|
175
|
+
resp = data.get("response")
|
|
176
|
+
if isinstance(resp, dict) and isinstance(resp.get("response"), list):
|
|
177
|
+
return resp["response"][0] or ""
|
|
178
|
+
if isinstance(resp, list):
|
|
179
|
+
return resp[0] or ""
|
|
180
|
+
if isinstance(resp, str):
|
|
181
|
+
return resp
|
|
182
|
+
if data.get("text"):
|
|
183
|
+
return data["text"]
|
|
184
|
+
|
|
185
|
+
return str(data)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
# Usage
|
|
189
|
+
api_key = os.getenv("ATAI_API_KEY") or os.getenv("ARCHETYPE_API_KEY")
|
|
190
|
+
answer = query_newton(
|
|
191
|
+
"What is the capital of France?",
|
|
192
|
+
"Answer the question concisely.",
|
|
193
|
+
api_key,
|
|
194
|
+
)
|
|
195
|
+
print(answer) # "Paris"
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Use Cases
|
|
201
|
+
|
|
202
|
+
- **API connectivity testing**: Verify your API key works
|
|
203
|
+
- **Quick text Q&A**: Get answers without lens/session setup
|
|
204
|
+
- **Post-processing**: Send results from other lenses (activity monitor, machine state) to Newton for summarization or comparison
|
|
205
|
+
- **Debugging**: Verify the `/query` endpoint behavior
|
|
206
|
+
|
|
207
|
+
## Troubleshooting
|
|
208
|
+
|
|
209
|
+
- **"Failed to fetch"**: Check the request body format ā use `model` (not `model_version`), `system_prompt` + `instruction_prompt` (not `instruction`), and `query` (not `focus`)
|
|
210
|
+
- **Empty response**: Check the response extraction chain ā the text is typically in `data.response.response[0]`
|
|
211
|
+
- **Authentication error**: Verify API key is correct and has the `Bearer ` prefix
|
|
212
|
+
- **Timeout**: Newton queries can take 10-30s for long prompts; use a 60s timeout
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Simple direct query to Newton model using the /query API endpoint
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import json
|
|
9
|
+
|
|
10
|
+
# Install requests if not available
|
|
11
|
+
try:
|
|
12
|
+
import requests
|
|
13
|
+
except ImportError:
|
|
14
|
+
print("Installing requests library...")
|
|
15
|
+
import subprocess
|
|
16
|
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "requests"])
|
|
17
|
+
import requests
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def query_archetype_ai(
|
|
21
|
+
api_key: str,
|
|
22
|
+
system_prompt: str = "Answer the question",
|
|
23
|
+
user_prompt: str = "What's the capital of France?",
|
|
24
|
+
api_endpoint: str = "https://api.u1.archetypeai.app/v0.5"
|
|
25
|
+
) -> dict:
|
|
26
|
+
"""
|
|
27
|
+
Query ArchetypeAI Newton model
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
api_key: Your ArchetypeAI API key
|
|
31
|
+
system_prompt: The system instruction (default: "Answer the question")
|
|
32
|
+
user_prompt: The user query (default: "What's the capital of France?")
|
|
33
|
+
api_endpoint: API endpoint URL
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Dictionary with the API response
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
# Exact API URL
|
|
40
|
+
api_url = f"{api_endpoint}/query"
|
|
41
|
+
|
|
42
|
+
# Request payload
|
|
43
|
+
request_data = {
|
|
44
|
+
"query": user_prompt,
|
|
45
|
+
"system_prompt": system_prompt,
|
|
46
|
+
"instruction_prompt": system_prompt,
|
|
47
|
+
"file_ids": [],
|
|
48
|
+
"model": "Newton::c2_4_7b_251215a172f6d7",
|
|
49
|
+
"max_new_tokens": 1024,
|
|
50
|
+
"sanitize": False
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
headers = {
|
|
54
|
+
"Authorization": f"Bearer {api_key}",
|
|
55
|
+
"Content-Type": "application/json"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
response = requests.post(api_url, headers=headers, json=request_data, timeout=30)
|
|
60
|
+
response.raise_for_status()
|
|
61
|
+
|
|
62
|
+
data = response.json()
|
|
63
|
+
|
|
64
|
+
# Extract response text
|
|
65
|
+
response_text = ''
|
|
66
|
+
if data.get('response') and data['response'].get('response') and isinstance(data['response']['response'], list):
|
|
67
|
+
response_text = data['response']['response'][0] or ''
|
|
68
|
+
elif data.get('response') and isinstance(data.get('response'), list):
|
|
69
|
+
response_text = data['response'][0] or ''
|
|
70
|
+
elif data.get('response') and isinstance(data.get('response'), str):
|
|
71
|
+
response_text = data['response']
|
|
72
|
+
elif data.get('text'):
|
|
73
|
+
response_text = data['text']
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
"success": True,
|
|
77
|
+
"response": response_text,
|
|
78
|
+
"full_response": data
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
except requests.exceptions.RequestException as e:
|
|
82
|
+
return {
|
|
83
|
+
"success": False,
|
|
84
|
+
"error": str(e),
|
|
85
|
+
"response": None
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def main():
|
|
90
|
+
"""Main function to run the query"""
|
|
91
|
+
|
|
92
|
+
# Get API key from environment
|
|
93
|
+
api_key = os.environ.get("ARCHETYPE_API_KEY") or os.environ.get("ATAI_API_KEY")
|
|
94
|
+
|
|
95
|
+
# Allow API key as first argument
|
|
96
|
+
if not api_key and len(sys.argv) > 1:
|
|
97
|
+
api_key = sys.argv[1]
|
|
98
|
+
|
|
99
|
+
if not api_key:
|
|
100
|
+
print("Error: Please provide API key either as:")
|
|
101
|
+
print(" 1. Environment variable: export ARCHETYPE_API_KEY=your_key")
|
|
102
|
+
print(" 2. Command line argument: python direct_query.py your_key")
|
|
103
|
+
sys.exit(1)
|
|
104
|
+
|
|
105
|
+
print("=" * 60)
|
|
106
|
+
print("ArchetypeAI Direct Query Test")
|
|
107
|
+
print("=" * 60)
|
|
108
|
+
|
|
109
|
+
system_prompt = "Answer the question"
|
|
110
|
+
user_prompt = "What's the capital of France?"
|
|
111
|
+
|
|
112
|
+
print(f"System Prompt: {system_prompt}")
|
|
113
|
+
print(f"User Prompt: {user_prompt}")
|
|
114
|
+
print("-" * 40)
|
|
115
|
+
|
|
116
|
+
result = query_archetype_ai(api_key, system_prompt, user_prompt)
|
|
117
|
+
|
|
118
|
+
if result["success"]:
|
|
119
|
+
print(f"Response: {result['response']}")
|
|
120
|
+
print("\nā API connection successful!")
|
|
121
|
+
else:
|
|
122
|
+
print(f"Error: {result['error']}")
|
|
123
|
+
print("\nā API connection failed!")
|
|
124
|
+
|
|
125
|
+
return 0 if result["success"] else 1
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
if __name__ == "__main__":
|
|
129
|
+
sys.exit(main())
|