ragleap-ops 0.1.0__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.
- ragleap_ops-0.1.0/.gitignore +1 -0
- ragleap_ops-0.1.0/PKG-INFO +44 -0
- ragleap_ops-0.1.0/README.md +32 -0
- ragleap_ops-0.1.0/k8s/app-deployment.yaml +41 -0
- ragleap_ops-0.1.0/k8s/app-service.yaml +10 -0
- ragleap_ops-0.1.0/k8s/db-deployment.yaml +52 -0
- ragleap_ops-0.1.0/k8s/db-pvc.yaml +9 -0
- ragleap_ops-0.1.0/k8s/db-schema-configmap.yaml +235 -0
- ragleap_ops-0.1.0/k8s/db-secret.yaml +9 -0
- ragleap_ops-0.1.0/k8s/db-service.yaml +10 -0
- ragleap_ops-0.1.0/k8s/neo4j-deployment.yaml +50 -0
- ragleap_ops-0.1.0/k8s/neo4j-pvc.yaml +9 -0
- ragleap_ops-0.1.0/k8s/neo4j-secret.yaml +7 -0
- ragleap_ops-0.1.0/k8s/neo4j-service.yaml +14 -0
- ragleap_ops-0.1.0/k8s/voice-deployment.yaml +34 -0
- ragleap_ops-0.1.0/k8s/voice-service.yaml +10 -0
- ragleap_ops-0.1.0/pyproject.toml +25 -0
- ragleap_ops-0.1.0/src/ragleap_ops/__init__.py +13 -0
- ragleap_ops-0.1.0/tests/test_version.py +5 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
k8s/app-env-secret.yaml
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: ragleap-ops
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Kubernetes deployment manifests for RagLeap Core, live-tested against a real cluster
|
|
5
|
+
Project-URL: Homepage, https://packages.ragleap.com/docs/ragleap-ops.html
|
|
6
|
+
Author: RagLeap Contributors
|
|
7
|
+
License: MIT
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# ragleap-ops
|
|
14
|
+
|
|
15
|
+
Kubernetes deployment manifests for RagLeap Core.
|
|
16
|
+
|
|
17
|
+
Ships Deployment + Service manifests for all four `docker-compose.yml`
|
|
18
|
+
services (`db`, `app`, `voice`, `neo4j`), translated from the real
|
|
19
|
+
compose file and live-tested end-to-end on a `kind` cluster — all four
|
|
20
|
+
pods reached `1/1 Running` with zero restarts after a probe-timing bug
|
|
21
|
+
was found and fixed via live testing.
|
|
22
|
+
|
|
23
|
+
## Contents
|
|
24
|
+
|
|
25
|
+
- `k8s/` — raw Deployment, Service, PVC, Secret, and ConfigMap manifests
|
|
26
|
+
- Apply order: Secrets/ConfigMap → PVCs → `db` → everything else
|
|
27
|
+
(`app`/`voice` depend on `db` via an init container that polls
|
|
28
|
+
`pg_isready`)
|
|
29
|
+
|
|
30
|
+
## Regenerating local-only files
|
|
31
|
+
|
|
32
|
+
Two files are intentionally **not** committed (see `.gitignore`) since
|
|
33
|
+
they'd otherwise bake real secret values into git history:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
kubectl create secret generic ragleap-app-env \
|
|
37
|
+
--from-env-file=$HOME/ragleap-core/.env \
|
|
38
|
+
--dry-run=client -o yaml > k8s/app-env-secret.yaml
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Status
|
|
42
|
+
|
|
43
|
+
Raw manifests are live-verified. A Helm chart wrapping these is not
|
|
44
|
+
yet built.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# ragleap-ops
|
|
2
|
+
|
|
3
|
+
Kubernetes deployment manifests for RagLeap Core.
|
|
4
|
+
|
|
5
|
+
Ships Deployment + Service manifests for all four `docker-compose.yml`
|
|
6
|
+
services (`db`, `app`, `voice`, `neo4j`), translated from the real
|
|
7
|
+
compose file and live-tested end-to-end on a `kind` cluster — all four
|
|
8
|
+
pods reached `1/1 Running` with zero restarts after a probe-timing bug
|
|
9
|
+
was found and fixed via live testing.
|
|
10
|
+
|
|
11
|
+
## Contents
|
|
12
|
+
|
|
13
|
+
- `k8s/` — raw Deployment, Service, PVC, Secret, and ConfigMap manifests
|
|
14
|
+
- Apply order: Secrets/ConfigMap → PVCs → `db` → everything else
|
|
15
|
+
(`app`/`voice` depend on `db` via an init container that polls
|
|
16
|
+
`pg_isready`)
|
|
17
|
+
|
|
18
|
+
## Regenerating local-only files
|
|
19
|
+
|
|
20
|
+
Two files are intentionally **not** committed (see `.gitignore`) since
|
|
21
|
+
they'd otherwise bake real secret values into git history:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
kubectl create secret generic ragleap-app-env \
|
|
25
|
+
--from-env-file=$HOME/ragleap-core/.env \
|
|
26
|
+
--dry-run=client -o yaml > k8s/app-env-secret.yaml
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Status
|
|
30
|
+
|
|
31
|
+
Raw manifests are live-verified. A Helm chart wrapping these is not
|
|
32
|
+
yet built.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
apiVersion: apps/v1
|
|
2
|
+
kind: Deployment
|
|
3
|
+
metadata:
|
|
4
|
+
name: ragleap-app
|
|
5
|
+
labels:
|
|
6
|
+
app: ragleap-app
|
|
7
|
+
spec:
|
|
8
|
+
replicas: 1
|
|
9
|
+
selector:
|
|
10
|
+
matchLabels:
|
|
11
|
+
app: ragleap-app
|
|
12
|
+
template:
|
|
13
|
+
metadata:
|
|
14
|
+
labels:
|
|
15
|
+
app: ragleap-app
|
|
16
|
+
spec:
|
|
17
|
+
imagePullSecrets:
|
|
18
|
+
- name: ghcr-pull-secret
|
|
19
|
+
initContainers:
|
|
20
|
+
- name: wait-for-db
|
|
21
|
+
image: postgres:16-alpine
|
|
22
|
+
command: ["sh", "-c", "until pg_isready -h ragleap-db -p 5432 -U ragleap; do sleep 2; done"]
|
|
23
|
+
containers:
|
|
24
|
+
- name: app
|
|
25
|
+
image: ghcr.io/antonyrag/ragleap-app:latest
|
|
26
|
+
ports:
|
|
27
|
+
- containerPort: 8000
|
|
28
|
+
envFrom:
|
|
29
|
+
- secretRef:
|
|
30
|
+
name: ragleap-app-env
|
|
31
|
+
env:
|
|
32
|
+
- name: DATABASE_URL
|
|
33
|
+
value: "postgresql://ragleap:ragleap@ragleap-db:5432/ragleap_core"
|
|
34
|
+
readinessProbe:
|
|
35
|
+
tcpSocket:
|
|
36
|
+
port: 8000
|
|
37
|
+
initialDelaySeconds: 5
|
|
38
|
+
livenessProbe:
|
|
39
|
+
tcpSocket:
|
|
40
|
+
port: 8000
|
|
41
|
+
initialDelaySeconds: 15
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
apiVersion: apps/v1
|
|
2
|
+
kind: Deployment
|
|
3
|
+
metadata:
|
|
4
|
+
name: ragleap-db
|
|
5
|
+
labels:
|
|
6
|
+
app: ragleap-db
|
|
7
|
+
spec:
|
|
8
|
+
replicas: 1
|
|
9
|
+
strategy:
|
|
10
|
+
type: Recreate
|
|
11
|
+
selector:
|
|
12
|
+
matchLabels:
|
|
13
|
+
app: ragleap-db
|
|
14
|
+
template:
|
|
15
|
+
metadata:
|
|
16
|
+
labels:
|
|
17
|
+
app: ragleap-db
|
|
18
|
+
spec:
|
|
19
|
+
containers:
|
|
20
|
+
- name: db
|
|
21
|
+
image: pgvector/pgvector:pg16
|
|
22
|
+
envFrom:
|
|
23
|
+
- secretRef:
|
|
24
|
+
name: ragleap-db-secret
|
|
25
|
+
ports:
|
|
26
|
+
- containerPort: 5432
|
|
27
|
+
volumeMounts:
|
|
28
|
+
- name: db-data
|
|
29
|
+
mountPath: /var/lib/postgresql/data
|
|
30
|
+
- name: db-schema
|
|
31
|
+
mountPath: /docker-entrypoint-initdb.d/01-schema.sql
|
|
32
|
+
subPath: schema.sql
|
|
33
|
+
readinessProbe:
|
|
34
|
+
exec:
|
|
35
|
+
command: ["pg_isready", "-U", "ragleap"]
|
|
36
|
+
initialDelaySeconds: 15
|
|
37
|
+
periodSeconds: 5
|
|
38
|
+
timeoutSeconds: 5
|
|
39
|
+
failureThreshold: 6
|
|
40
|
+
livenessProbe:
|
|
41
|
+
exec:
|
|
42
|
+
command: ["pg_isready", "-U", "ragleap"]
|
|
43
|
+
initialDelaySeconds: 45
|
|
44
|
+
periodSeconds: 10
|
|
45
|
+
failureThreshold: 6
|
|
46
|
+
volumes:
|
|
47
|
+
- name: db-data
|
|
48
|
+
persistentVolumeClaim:
|
|
49
|
+
claimName: ragleap-db-data
|
|
50
|
+
- name: db-schema
|
|
51
|
+
configMap:
|
|
52
|
+
name: ragleap-db-schema
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
apiVersion: v1
|
|
2
|
+
data:
|
|
3
|
+
schema.sql: |
|
|
4
|
+
-- RagLeap Core database schema
|
|
5
|
+
-- Requires the pgvector extension (bundled in the pgvector/pgvector Docker image)
|
|
6
|
+
|
|
7
|
+
CREATE EXTENSION IF NOT EXISTS vector;
|
|
8
|
+
|
|
9
|
+
CREATE TABLE IF NOT EXISTS documents (
|
|
10
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
11
|
+
filename TEXT NOT NULL,
|
|
12
|
+
uploaded_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE TABLE IF NOT EXISTS chunks (
|
|
16
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
17
|
+
document_id UUID NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
|
|
18
|
+
document_name TEXT NOT NULL,
|
|
19
|
+
chunk_index INTEGER NOT NULL,
|
|
20
|
+
text TEXT NOT NULL,
|
|
21
|
+
token_count INTEGER,
|
|
22
|
+
embedding vector(3072),
|
|
23
|
+
detected_language TEXT,
|
|
24
|
+
language_confidence REAL,
|
|
25
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
-- pgvector's HNSW index has a hard 2000-dimension limit for standard `vector`,
|
|
29
|
+
-- but Gemini's gemini-embedding-001 produces 3072-dim vectors. We cast to
|
|
30
|
+
-- halfvec(3072) (half-precision, pgvector >= 0.7.0) to build the index within
|
|
31
|
+
-- that limit, matching the same workaround used in RagLeap's production schema.
|
|
32
|
+
CREATE INDEX IF NOT EXISTS chunks_embedding_idx
|
|
33
|
+
ON chunks USING hnsw ((embedding::halfvec(3072)) halfvec_cosine_ops);
|
|
34
|
+
|
|
35
|
+
-- Full-text search support for hybrid (dense + sparse) retrieval.
|
|
36
|
+
-- Generated column stays in sync automatically on insert/update.
|
|
37
|
+
ALTER TABLE chunks ADD COLUMN IF NOT EXISTS text_search_vector tsvector
|
|
38
|
+
GENERATED ALWAYS AS (to_tsvector('english', text)) STORED;
|
|
39
|
+
|
|
40
|
+
CREATE INDEX IF NOT EXISTS chunks_text_search_idx
|
|
41
|
+
ON chunks USING GIN (text_search_vector);
|
|
42
|
+
|
|
43
|
+
-- Integrations: external data sources (databases, CRMs, SaaS APIs) that can
|
|
44
|
+
-- sync per-user context into RAG responses. Single-tenant — no workspace scoping.
|
|
45
|
+
CREATE TABLE IF NOT EXISTS data_sources (
|
|
46
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
47
|
+
name TEXT NOT NULL UNIQUE,
|
|
48
|
+
source_type TEXT NOT NULL,
|
|
49
|
+
|
|
50
|
+
-- Connection details (encrypted at the application layer via Fernet
|
|
51
|
+
-- before being written here — never store plaintext credentials)
|
|
52
|
+
connection_string TEXT,
|
|
53
|
+
api_endpoint TEXT,
|
|
54
|
+
api_key TEXT,
|
|
55
|
+
api_headers JSONB DEFAULT '{}',
|
|
56
|
+
|
|
57
|
+
-- Query configuration
|
|
58
|
+
query_template TEXT,
|
|
59
|
+
field_mappings JSONB DEFAULT '{}',
|
|
60
|
+
user_identifier_field TEXT NOT NULL DEFAULT 'user_id',
|
|
61
|
+
documents_table_name TEXT NOT NULL DEFAULT 'documents',
|
|
62
|
+
|
|
63
|
+
-- Sync configuration
|
|
64
|
+
sync_interval_minutes INTEGER NOT NULL DEFAULT 360,
|
|
65
|
+
last_sync_at TIMESTAMPTZ,
|
|
66
|
+
last_sync_status TEXT NOT NULL DEFAULT 'pending',
|
|
67
|
+
last_sync_error TEXT,
|
|
68
|
+
last_sync_record_count INTEGER NOT NULL DEFAULT 0,
|
|
69
|
+
|
|
70
|
+
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
71
|
+
|
|
72
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
73
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
-- Customer/user context synced from external data sources, used to
|
|
77
|
+
-- personalize RAG responses.
|
|
78
|
+
CREATE TABLE IF NOT EXISTS synced_context_data (
|
|
79
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
80
|
+
data_source_id UUID NOT NULL REFERENCES data_sources(id) ON DELETE CASCADE,
|
|
81
|
+
user_identifier TEXT NOT NULL,
|
|
82
|
+
context_data JSONB NOT NULL DEFAULT '{}',
|
|
83
|
+
synced_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
84
|
+
last_updated TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
85
|
+
source_updated_at TIMESTAMPTZ,
|
|
86
|
+
UNIQUE (data_source_id, user_identifier)
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
CREATE INDEX IF NOT EXISTS synced_context_data_lookup_idx
|
|
90
|
+
ON synced_context_data (data_source_id, user_identifier);
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
CREATE TABLE IF NOT EXISTS business_profile (
|
|
94
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
95
|
+
business_name TEXT NOT NULL DEFAULT '',
|
|
96
|
+
industry TEXT NOT NULL DEFAULT '',
|
|
97
|
+
description TEXT NOT NULL DEFAULT '',
|
|
98
|
+
products_services TEXT NOT NULL DEFAULT '',
|
|
99
|
+
target_customers TEXT NOT NULL DEFAULT '',
|
|
100
|
+
working_hours TEXT NOT NULL DEFAULT '',
|
|
101
|
+
location TEXT NOT NULL DEFAULT '',
|
|
102
|
+
tone_preference TEXT NOT NULL DEFAULT 'friendly',
|
|
103
|
+
primary_language TEXT NOT NULL DEFAULT 'en',
|
|
104
|
+
additional_languages JSONB NOT NULL DEFAULT '[]',
|
|
105
|
+
owner_instructions TEXT NOT NULL DEFAULT '',
|
|
106
|
+
auto_learned_profile TEXT NOT NULL DEFAULT '',
|
|
107
|
+
skill_version INTEGER NOT NULL DEFAULT 0,
|
|
108
|
+
is_profile_complete BOOLEAN NOT NULL DEFAULT false,
|
|
109
|
+
last_learned_at TIMESTAMPTZ,
|
|
110
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
111
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
CREATE TABLE IF NOT EXISTS employee_roles (
|
|
115
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
116
|
+
role TEXT NOT NULL UNIQUE,
|
|
117
|
+
display_name TEXT NOT NULL DEFAULT '',
|
|
118
|
+
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
119
|
+
channels JSONB NOT NULL DEFAULT '[]',
|
|
120
|
+
skill_tags JSONB NOT NULL DEFAULT '[]',
|
|
121
|
+
personality TEXT NOT NULL DEFAULT '',
|
|
122
|
+
skills_summary TEXT NOT NULL DEFAULT '',
|
|
123
|
+
last_learned_at TIMESTAMPTZ,
|
|
124
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
125
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
CREATE TABLE IF NOT EXISTS employee_memory (
|
|
129
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
130
|
+
text_content TEXT NOT NULL,
|
|
131
|
+
summary TEXT NOT NULL DEFAULT '',
|
|
132
|
+
tags JSONB NOT NULL DEFAULT '[]',
|
|
133
|
+
importance REAL NOT NULL DEFAULT 0.7,
|
|
134
|
+
source TEXT NOT NULL DEFAULT 'interaction',
|
|
135
|
+
permanent BOOLEAN NOT NULL DEFAULT false,
|
|
136
|
+
review_after_days INTEGER NOT NULL DEFAULT 180,
|
|
137
|
+
content_hash TEXT NOT NULL,
|
|
138
|
+
embedding vector(3072),
|
|
139
|
+
token_count INTEGER NOT NULL DEFAULT 0,
|
|
140
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
CREATE INDEX IF NOT EXISTS employee_memory_embedding_idx
|
|
144
|
+
ON employee_memory USING hnsw ((embedding::halfvec(3072)) halfvec_cosine_ops);
|
|
145
|
+
CREATE INDEX IF NOT EXISTS employee_memory_tags_idx
|
|
146
|
+
ON employee_memory USING GIN (tags);
|
|
147
|
+
CREATE INDEX IF NOT EXISTS employee_memory_hash_idx
|
|
148
|
+
ON employee_memory (content_hash, source);
|
|
149
|
+
|
|
150
|
+
-- n8n workflow automation. Single-tenant — no workspace scoping.
|
|
151
|
+
-- Fires a webhook after the AI replies on a matching channel; caller
|
|
152
|
+
-- (channel adapter) supplies channel/message/ai_reply, this module never
|
|
153
|
+
-- raises — a broken workflow config should never break the main chat flow.
|
|
154
|
+
CREATE TABLE IF NOT EXISTS n8n_workflows (
|
|
155
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
156
|
+
name TEXT NOT NULL,
|
|
157
|
+
description TEXT NOT NULL DEFAULT '',
|
|
158
|
+
webhook_url TEXT NOT NULL,
|
|
159
|
+
channels JSONB NOT NULL DEFAULT '[]',
|
|
160
|
+
is_active BOOLEAN NOT NULL DEFAULT false,
|
|
161
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
162
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
CREATE INDEX IF NOT EXISTS n8n_workflows_active_idx
|
|
166
|
+
ON n8n_workflows (is_active);
|
|
167
|
+
|
|
168
|
+
-- Autonomous Loop settings — single-tenant port of production's
|
|
169
|
+
-- api/autonomy_engine.py. One row (singleton, no workspace FK).
|
|
170
|
+
CREATE TABLE IF NOT EXISTS autonomy_settings (
|
|
171
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
172
|
+
mode TEXT NOT NULL DEFAULT 'off',
|
|
173
|
+
channels JSONB NOT NULL DEFAULT '[]',
|
|
174
|
+
actions JSONB NOT NULL DEFAULT '[]',
|
|
175
|
+
approval_channel TEXT NOT NULL DEFAULT 'telegram',
|
|
176
|
+
approval_target TEXT NOT NULL DEFAULT '',
|
|
177
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
-- Pending actions awaiting owner approval in "semi" mode.
|
|
181
|
+
CREATE TABLE IF NOT EXISTS autonomy_pending (
|
|
182
|
+
action_id TEXT PRIMARY KEY,
|
|
183
|
+
action_type TEXT NOT NULL,
|
|
184
|
+
channel TEXT NOT NULL,
|
|
185
|
+
target TEXT NOT NULL,
|
|
186
|
+
content TEXT NOT NULL,
|
|
187
|
+
subject TEXT NOT NULL DEFAULT '',
|
|
188
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
-- Bounded audit log of every autonomous action (executed, rejected, or errored).
|
|
192
|
+
CREATE TABLE IF NOT EXISTS autonomy_log (
|
|
193
|
+
id BIGSERIAL PRIMARY KEY,
|
|
194
|
+
action_type TEXT NOT NULL,
|
|
195
|
+
channel TEXT NOT NULL,
|
|
196
|
+
target TEXT NOT NULL,
|
|
197
|
+
content TEXT NOT NULL,
|
|
198
|
+
result TEXT NOT NULL,
|
|
199
|
+
approved BOOLEAN NOT NULL DEFAULT true,
|
|
200
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
201
|
+
);
|
|
202
|
+
CREATE INDEX IF NOT EXISTS autonomy_log_created_idx
|
|
203
|
+
ON autonomy_log (created_at DESC);
|
|
204
|
+
|
|
205
|
+
-- Tracks the most recent role-based reply per (channel, chat_id), so
|
|
206
|
+
-- an owner can send a quick feedback command (thumbs up/down,
|
|
207
|
+
-- "helpful"/"not helpful") that gets attributed to the correct
|
|
208
|
+
-- memory entries via core.employees.learning.record_role_memory_outcome().
|
|
209
|
+
-- Without this table there is no real success/failure signal available
|
|
210
|
+
-- in the channels -- see core/employees/feedback.py.
|
|
211
|
+
CREATE TABLE IF NOT EXISTS role_reply_log (
|
|
212
|
+
channel TEXT NOT NULL,
|
|
213
|
+
chat_id TEXT NOT NULL,
|
|
214
|
+
role_memory_ids JSONB NOT NULL DEFAULT '[]',
|
|
215
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
216
|
+
PRIMARY KEY (channel, chat_id)
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
-- Owner-configured default AI Employee role per channel (e.g. telegram ->
|
|
220
|
+
-- manager, whatsapp -> support). Falls back to 'support' when unset. See
|
|
221
|
+
-- core/employees/channel_roles.py for the routing logic that uses this.
|
|
222
|
+
CREATE TABLE IF NOT EXISTS channel_role_config (
|
|
223
|
+
channel TEXT PRIMARY KEY,
|
|
224
|
+
role TEXT NOT NULL DEFAULT 'support',
|
|
225
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
-- CSV connector content storage — no persistent disk volume exists in
|
|
229
|
+
-- docker-compose.yml, so CSV content lives in Postgres like everything
|
|
230
|
+
-- else in Core, rather than on the container filesystem.
|
|
231
|
+
ALTER TABLE data_sources ADD COLUMN IF NOT EXISTS csv_content TEXT;
|
|
232
|
+
ALTER TABLE data_sources ADD COLUMN IF NOT EXISTS csv_filename TEXT;
|
|
233
|
+
kind: ConfigMap
|
|
234
|
+
metadata:
|
|
235
|
+
name: ragleap-db-schema
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
apiVersion: apps/v1
|
|
2
|
+
kind: Deployment
|
|
3
|
+
metadata:
|
|
4
|
+
name: ragleap-neo4j
|
|
5
|
+
labels:
|
|
6
|
+
app: ragleap-neo4j
|
|
7
|
+
spec:
|
|
8
|
+
replicas: 1
|
|
9
|
+
strategy:
|
|
10
|
+
type: Recreate
|
|
11
|
+
selector:
|
|
12
|
+
matchLabels:
|
|
13
|
+
app: ragleap-neo4j
|
|
14
|
+
template:
|
|
15
|
+
metadata:
|
|
16
|
+
labels:
|
|
17
|
+
app: ragleap-neo4j
|
|
18
|
+
spec:
|
|
19
|
+
containers:
|
|
20
|
+
- name: neo4j
|
|
21
|
+
image: neo4j:5-community
|
|
22
|
+
envFrom:
|
|
23
|
+
- secretRef:
|
|
24
|
+
name: ragleap-neo4j-secret
|
|
25
|
+
env:
|
|
26
|
+
- name: NEO4J_PLUGINS
|
|
27
|
+
value: "[]"
|
|
28
|
+
ports:
|
|
29
|
+
- containerPort: 7474
|
|
30
|
+
- containerPort: 7687
|
|
31
|
+
volumeMounts:
|
|
32
|
+
- name: neo4j-data
|
|
33
|
+
mountPath: /data
|
|
34
|
+
readinessProbe:
|
|
35
|
+
httpGet:
|
|
36
|
+
path: /
|
|
37
|
+
port: 7474
|
|
38
|
+
initialDelaySeconds: 10
|
|
39
|
+
periodSeconds: 10
|
|
40
|
+
failureThreshold: 10
|
|
41
|
+
livenessProbe:
|
|
42
|
+
httpGet:
|
|
43
|
+
path: /
|
|
44
|
+
port: 7474
|
|
45
|
+
initialDelaySeconds: 20
|
|
46
|
+
periodSeconds: 10
|
|
47
|
+
volumes:
|
|
48
|
+
- name: neo4j-data
|
|
49
|
+
persistentVolumeClaim:
|
|
50
|
+
claimName: ragleap-neo4j-data
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
apiVersion: apps/v1
|
|
2
|
+
kind: Deployment
|
|
3
|
+
metadata:
|
|
4
|
+
name: ragleap-voice
|
|
5
|
+
labels:
|
|
6
|
+
app: ragleap-voice
|
|
7
|
+
spec:
|
|
8
|
+
replicas: 1
|
|
9
|
+
selector:
|
|
10
|
+
matchLabels:
|
|
11
|
+
app: ragleap-voice
|
|
12
|
+
template:
|
|
13
|
+
metadata:
|
|
14
|
+
labels:
|
|
15
|
+
app: ragleap-voice
|
|
16
|
+
spec:
|
|
17
|
+
imagePullSecrets:
|
|
18
|
+
- name: ghcr-pull-secret
|
|
19
|
+
initContainers:
|
|
20
|
+
- name: wait-for-db
|
|
21
|
+
image: postgres:16-alpine
|
|
22
|
+
command: ["sh", "-c", "until pg_isready -h ragleap-db -p 5432 -U ragleap; do sleep 2; done"]
|
|
23
|
+
containers:
|
|
24
|
+
- name: voice
|
|
25
|
+
image: ghcr.io/antonyrag/ragleap-app:latest
|
|
26
|
+
command: ["python3", "-m", "channels.voice.server"]
|
|
27
|
+
ports:
|
|
28
|
+
- containerPort: 8765
|
|
29
|
+
envFrom:
|
|
30
|
+
- secretRef:
|
|
31
|
+
name: ragleap-app-env
|
|
32
|
+
env:
|
|
33
|
+
- name: DATABASE_URL
|
|
34
|
+
value: "postgresql://ragleap:ragleap@ragleap-db:5432/ragleap_core"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ragleap-ops"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Kubernetes deployment manifests for RagLeap Core, live-tested against a real cluster"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "RagLeap Contributors" }
|
|
14
|
+
]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
]
|
|
19
|
+
dependencies = []
|
|
20
|
+
|
|
21
|
+
[project.urls]
|
|
22
|
+
Homepage = "https://packages.ragleap.com/docs/ragleap-ops.html"
|
|
23
|
+
|
|
24
|
+
[tool.hatchling.build.targets.wheel]
|
|
25
|
+
packages = ["src/ragleap_ops"]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""ragleap-ops: Kubernetes deployment tooling for RagLeap Core.
|
|
2
|
+
|
|
3
|
+
This package ships k8s/ Deployment and Service manifests for all four
|
|
4
|
+
docker-compose services (db, app, voice, neo4j), translated from the
|
|
5
|
+
real docker-compose.yml and live-tested end-to-end on a kind cluster.
|
|
6
|
+
|
|
7
|
+
It contains almost no importable Python — its purpose is to let the
|
|
8
|
+
existing PyPI/git-tag release automation version and ship the k8s/
|
|
9
|
+
manifests alongside this src/ tree, matching the release discipline of
|
|
10
|
+
ragleap-rag, ragleap-graph, and ragleap-vectorstores.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
__version__ = "0.1.0"
|