claude-code-pack 1.0.0
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/README.md +120 -0
- package/assets/statusline-command.sh +116 -0
- package/bin/claude-pack.mjs +48 -0
- package/claude-pack.config.json +37 -0
- package/package.json +31 -0
- package/skills/cloud-devops/SKILL.md +235 -0
- package/skills/fastapi/SKILL.md +436 -0
- package/skills/fastapi/references/dependencies.md +142 -0
- package/skills/fastapi/references/other-tools.md +76 -0
- package/skills/fastapi/references/streaming.md +105 -0
- package/skills/senior-ml-engineer/SKILL.md +304 -0
- package/skills/senior-ml-engineer/references/llm_integration_guide.md +317 -0
- package/skills/senior-ml-engineer/references/mlops_production_patterns.md +265 -0
- package/skills/senior-ml-engineer/references/rag_system_architecture.md +371 -0
- package/skills/senior-ml-engineer/scripts/ml_monitoring_suite.py +100 -0
- package/skills/senior-ml-engineer/scripts/model_deployment_pipeline.py +100 -0
- package/skills/senior-ml-engineer/scripts/rag_system_builder.py +100 -0
- package/skills/technical-writer/technical-writer/SKILL.md +351 -0
- package/src/install.mjs +391 -0
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
# RAG System Architecture
|
|
2
|
+
|
|
3
|
+
Retrieval-Augmented Generation patterns for production applications.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [RAG Pipeline Architecture](#rag-pipeline-architecture)
|
|
10
|
+
- [Vector Database Selection](#vector-database-selection)
|
|
11
|
+
- [Chunking Strategies](#chunking-strategies)
|
|
12
|
+
- [Embedding Models](#embedding-models)
|
|
13
|
+
- [Retrieval Optimization](#retrieval-optimization)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## RAG Pipeline Architecture
|
|
18
|
+
|
|
19
|
+
### Basic RAG Flow
|
|
20
|
+
|
|
21
|
+
1. Receive user query
|
|
22
|
+
2. Generate query embedding
|
|
23
|
+
3. Search vector database for relevant chunks
|
|
24
|
+
4. Rerank retrieved chunks by relevance
|
|
25
|
+
5. Format context with retrieved chunks
|
|
26
|
+
6. Send prompt to LLM with context
|
|
27
|
+
7. Return generated response
|
|
28
|
+
8. **Validation:** Response references retrieved context, no hallucinations
|
|
29
|
+
|
|
30
|
+
### Pipeline Components
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from dataclasses import dataclass
|
|
34
|
+
from typing import List
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class Document:
|
|
38
|
+
content: str
|
|
39
|
+
metadata: dict
|
|
40
|
+
embedding: List[float] = None
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class RetrievalResult:
|
|
44
|
+
document: Document
|
|
45
|
+
score: float
|
|
46
|
+
|
|
47
|
+
class RAGPipeline:
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
embedder: Embedder,
|
|
51
|
+
vector_store: VectorStore,
|
|
52
|
+
llm: LLMProvider,
|
|
53
|
+
reranker: Reranker = None
|
|
54
|
+
):
|
|
55
|
+
self.embedder = embedder
|
|
56
|
+
self.vector_store = vector_store
|
|
57
|
+
self.llm = llm
|
|
58
|
+
self.reranker = reranker
|
|
59
|
+
|
|
60
|
+
def query(self, question: str, top_k: int = 5) -> str:
|
|
61
|
+
# 1. Embed query
|
|
62
|
+
query_embedding = self.embedder.embed(question)
|
|
63
|
+
|
|
64
|
+
# 2. Retrieve relevant documents
|
|
65
|
+
results = self.vector_store.search(query_embedding, top_k=top_k * 2)
|
|
66
|
+
|
|
67
|
+
# 3. Rerank if available
|
|
68
|
+
if self.reranker:
|
|
69
|
+
results = self.reranker.rerank(question, results)[:top_k]
|
|
70
|
+
else:
|
|
71
|
+
results = results[:top_k]
|
|
72
|
+
|
|
73
|
+
# 4. Build context
|
|
74
|
+
context = self._build_context(results)
|
|
75
|
+
|
|
76
|
+
# 5. Generate response
|
|
77
|
+
prompt = self._build_prompt(question, context)
|
|
78
|
+
return self.llm.complete(prompt)
|
|
79
|
+
|
|
80
|
+
def _build_context(self, results: List[RetrievalResult]) -> str:
|
|
81
|
+
return "\n\n".join([
|
|
82
|
+
f"[Source {i+1}]: {r.document.content}"
|
|
83
|
+
for i, r in enumerate(results)
|
|
84
|
+
])
|
|
85
|
+
|
|
86
|
+
def _build_prompt(self, question: str, context: str) -> str:
|
|
87
|
+
return f"""Answer the question based on the context provided.
|
|
88
|
+
|
|
89
|
+
Context:
|
|
90
|
+
{context}
|
|
91
|
+
|
|
92
|
+
Question: {question}
|
|
93
|
+
|
|
94
|
+
Answer:"""
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Vector Database Selection
|
|
100
|
+
|
|
101
|
+
### Comparison Matrix
|
|
102
|
+
|
|
103
|
+
| Database | Hosting | Scale | Latency | Cost | Best For |
|
|
104
|
+
|----------|---------|-------|---------|------|----------|
|
|
105
|
+
| Pinecone | Managed | High | Low | $$ | Production, managed |
|
|
106
|
+
| Weaviate | Both | High | Low | $ | Hybrid search |
|
|
107
|
+
| Qdrant | Both | High | Very Low | $ | Performance-critical |
|
|
108
|
+
| Chroma | Self-hosted | Medium | Low | Free | Prototyping |
|
|
109
|
+
| pgvector | Self-hosted | Medium | Medium | Free | Existing Postgres |
|
|
110
|
+
| Milvus | Both | Very High | Low | $ | Large-scale |
|
|
111
|
+
|
|
112
|
+
### Pinecone Integration
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
import pinecone
|
|
116
|
+
|
|
117
|
+
class PineconeVectorStore:
|
|
118
|
+
def __init__(self, api_key: str, environment: str, index_name: str):
|
|
119
|
+
pinecone.init(api_key=api_key, environment=environment)
|
|
120
|
+
self.index = pinecone.Index(index_name)
|
|
121
|
+
|
|
122
|
+
def upsert(self, documents: List[Document], batch_size: int = 100):
|
|
123
|
+
"""Upsert documents in batches."""
|
|
124
|
+
vectors = [
|
|
125
|
+
(doc.metadata["id"], doc.embedding, doc.metadata)
|
|
126
|
+
for doc in documents
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
for i in range(0, len(vectors), batch_size):
|
|
130
|
+
batch = vectors[i:i + batch_size]
|
|
131
|
+
self.index.upsert(vectors=batch)
|
|
132
|
+
|
|
133
|
+
def search(self, embedding: List[float], top_k: int = 5) -> List[RetrievalResult]:
|
|
134
|
+
"""Search for similar vectors."""
|
|
135
|
+
results = self.index.query(
|
|
136
|
+
vector=embedding,
|
|
137
|
+
top_k=top_k,
|
|
138
|
+
include_metadata=True
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
return [
|
|
142
|
+
RetrievalResult(
|
|
143
|
+
document=Document(
|
|
144
|
+
content=match.metadata.get("content", ""),
|
|
145
|
+
metadata=match.metadata
|
|
146
|
+
),
|
|
147
|
+
score=match.score
|
|
148
|
+
)
|
|
149
|
+
for match in results.matches
|
|
150
|
+
]
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Chunking Strategies
|
|
156
|
+
|
|
157
|
+
### Strategy Comparison
|
|
158
|
+
|
|
159
|
+
| Strategy | Chunk Size | Overlap | Best For |
|
|
160
|
+
|----------|------------|---------|----------|
|
|
161
|
+
| Fixed | 500-1000 tokens | 50-100 | General text |
|
|
162
|
+
| Sentence | 3-5 sentences | 1 sentence | Structured text |
|
|
163
|
+
| Paragraph | Natural breaks | None | Documents with clear structure |
|
|
164
|
+
| Semantic | Variable | Based on meaning | Research papers |
|
|
165
|
+
| Recursive | Hierarchical | Parent-child | Long documents |
|
|
166
|
+
|
|
167
|
+
### Recursive Character Splitter
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|
171
|
+
|
|
172
|
+
def create_chunks(
|
|
173
|
+
text: str,
|
|
174
|
+
chunk_size: int = 1000,
|
|
175
|
+
chunk_overlap: int = 100
|
|
176
|
+
) -> List[str]:
|
|
177
|
+
"""Split text using recursive character splitting."""
|
|
178
|
+
splitter = RecursiveCharacterTextSplitter(
|
|
179
|
+
chunk_size=chunk_size,
|
|
180
|
+
chunk_overlap=chunk_overlap,
|
|
181
|
+
separators=["\n\n", "\n", ". ", " ", ""]
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
return splitter.split_text(text)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Semantic Chunking
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
from sentence_transformers import SentenceTransformer
|
|
191
|
+
import numpy as np
|
|
192
|
+
|
|
193
|
+
def semantic_chunk(
|
|
194
|
+
sentences: List[str],
|
|
195
|
+
embedder: SentenceTransformer,
|
|
196
|
+
threshold: float = 0.7
|
|
197
|
+
) -> List[List[str]]:
|
|
198
|
+
"""Group sentences by semantic similarity."""
|
|
199
|
+
embeddings = embedder.encode(sentences)
|
|
200
|
+
|
|
201
|
+
chunks = []
|
|
202
|
+
current_chunk = [sentences[0]]
|
|
203
|
+
current_embedding = embeddings[0]
|
|
204
|
+
|
|
205
|
+
for i in range(1, len(sentences)):
|
|
206
|
+
similarity = np.dot(current_embedding, embeddings[i]) / (
|
|
207
|
+
np.linalg.norm(current_embedding) * np.linalg.norm(embeddings[i])
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
if similarity >= threshold:
|
|
211
|
+
current_chunk.append(sentences[i])
|
|
212
|
+
current_embedding = np.mean(
|
|
213
|
+
[current_embedding, embeddings[i]], axis=0
|
|
214
|
+
)
|
|
215
|
+
else:
|
|
216
|
+
chunks.append(current_chunk)
|
|
217
|
+
current_chunk = [sentences[i]]
|
|
218
|
+
current_embedding = embeddings[i]
|
|
219
|
+
|
|
220
|
+
chunks.append(current_chunk)
|
|
221
|
+
return chunks
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Embedding Models
|
|
227
|
+
|
|
228
|
+
### Model Comparison
|
|
229
|
+
|
|
230
|
+
| Model | Dimensions | Quality | Speed | Cost |
|
|
231
|
+
|-------|------------|---------|-------|------|
|
|
232
|
+
| text-embedding-3-large | 3072 | Excellent | Medium | $0.13/1M |
|
|
233
|
+
| text-embedding-3-small | 1536 | Good | Fast | $0.02/1M |
|
|
234
|
+
| BGE-large | 1024 | Excellent | Medium | Free |
|
|
235
|
+
| all-MiniLM-L6-v2 | 384 | Good | Very Fast | Free |
|
|
236
|
+
| Cohere embed-v3 | 1024 | Excellent | Medium | $0.10/1M |
|
|
237
|
+
|
|
238
|
+
### Embedding with Caching
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
import hashlib
|
|
242
|
+
from functools import lru_cache
|
|
243
|
+
|
|
244
|
+
class CachedEmbedder:
|
|
245
|
+
def __init__(self, model_name: str = "text-embedding-3-small"):
|
|
246
|
+
self.client = OpenAI()
|
|
247
|
+
self.model = model_name
|
|
248
|
+
self._cache = {}
|
|
249
|
+
|
|
250
|
+
def embed(self, text: str) -> List[float]:
|
|
251
|
+
"""Embed text with caching."""
|
|
252
|
+
cache_key = hashlib.md5(text.encode()).hexdigest()
|
|
253
|
+
|
|
254
|
+
if cache_key in self._cache:
|
|
255
|
+
return self._cache[cache_key]
|
|
256
|
+
|
|
257
|
+
response = self.client.embeddings.create(
|
|
258
|
+
model=self.model,
|
|
259
|
+
input=text
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
embedding = response.data[0].embedding
|
|
263
|
+
self._cache[cache_key] = embedding
|
|
264
|
+
|
|
265
|
+
return embedding
|
|
266
|
+
|
|
267
|
+
def embed_batch(self, texts: List[str]) -> List[List[float]]:
|
|
268
|
+
"""Embed multiple texts efficiently."""
|
|
269
|
+
response = self.client.embeddings.create(
|
|
270
|
+
model=self.model,
|
|
271
|
+
input=texts
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
return [item.embedding for item in response.data]
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Retrieval Optimization
|
|
280
|
+
|
|
281
|
+
### Hybrid Search
|
|
282
|
+
|
|
283
|
+
Combine dense (vector) and sparse (keyword) retrieval:
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
from rank_bm25 import BM25Okapi
|
|
287
|
+
|
|
288
|
+
class HybridRetriever:
|
|
289
|
+
def __init__(
|
|
290
|
+
self,
|
|
291
|
+
vector_store: VectorStore,
|
|
292
|
+
documents: List[Document],
|
|
293
|
+
alpha: float = 0.5
|
|
294
|
+
):
|
|
295
|
+
self.vector_store = vector_store
|
|
296
|
+
self.alpha = alpha # Weight for vector search
|
|
297
|
+
|
|
298
|
+
# Build BM25 index
|
|
299
|
+
tokenized = [doc.content.lower().split() for doc in documents]
|
|
300
|
+
self.bm25 = BM25Okapi(tokenized)
|
|
301
|
+
self.documents = documents
|
|
302
|
+
|
|
303
|
+
def search(self, query: str, query_embedding: List[float], top_k: int = 5):
|
|
304
|
+
# Vector search
|
|
305
|
+
vector_results = self.vector_store.search(query_embedding, top_k=top_k * 2)
|
|
306
|
+
|
|
307
|
+
# BM25 search
|
|
308
|
+
tokenized_query = query.lower().split()
|
|
309
|
+
bm25_scores = self.bm25.get_scores(tokenized_query)
|
|
310
|
+
|
|
311
|
+
# Combine scores
|
|
312
|
+
combined = {}
|
|
313
|
+
for result in vector_results:
|
|
314
|
+
doc_id = result.document.metadata["id"]
|
|
315
|
+
combined[doc_id] = self.alpha * result.score
|
|
316
|
+
|
|
317
|
+
for i, score in enumerate(bm25_scores):
|
|
318
|
+
doc_id = self.documents[i].metadata["id"]
|
|
319
|
+
if doc_id in combined:
|
|
320
|
+
combined[doc_id] += (1 - self.alpha) * score
|
|
321
|
+
else:
|
|
322
|
+
combined[doc_id] = (1 - self.alpha) * score
|
|
323
|
+
|
|
324
|
+
# Sort and return top_k
|
|
325
|
+
sorted_ids = sorted(combined.keys(), key=lambda x: combined[x], reverse=True)
|
|
326
|
+
return sorted_ids[:top_k]
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Reranking
|
|
330
|
+
|
|
331
|
+
```python
|
|
332
|
+
from sentence_transformers import CrossEncoder
|
|
333
|
+
|
|
334
|
+
class Reranker:
|
|
335
|
+
def __init__(self, model_name: str = "cross-encoder/ms-marco-MiniLM-L-12-v2"):
|
|
336
|
+
self.model = CrossEncoder(model_name)
|
|
337
|
+
|
|
338
|
+
def rerank(
|
|
339
|
+
self,
|
|
340
|
+
query: str,
|
|
341
|
+
results: List[RetrievalResult],
|
|
342
|
+
top_k: int = 5
|
|
343
|
+
) -> List[RetrievalResult]:
|
|
344
|
+
"""Rerank results using cross-encoder."""
|
|
345
|
+
pairs = [(query, r.document.content) for r in results]
|
|
346
|
+
scores = self.model.predict(pairs)
|
|
347
|
+
|
|
348
|
+
# Update scores and sort
|
|
349
|
+
for i, score in enumerate(scores):
|
|
350
|
+
results[i].score = float(score)
|
|
351
|
+
|
|
352
|
+
return sorted(results, key=lambda x: x.score, reverse=True)[:top_k]
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Query Expansion
|
|
356
|
+
|
|
357
|
+
```python
|
|
358
|
+
def expand_query(query: str, llm: LLMProvider) -> List[str]:
|
|
359
|
+
"""Generate query variations for better retrieval."""
|
|
360
|
+
prompt = f"""Generate 3 alternative phrasings of this question for search.
|
|
361
|
+
Return only the questions, one per line.
|
|
362
|
+
|
|
363
|
+
Original: {query}
|
|
364
|
+
|
|
365
|
+
Alternatives:"""
|
|
366
|
+
|
|
367
|
+
response = llm.complete(prompt, max_tokens=150)
|
|
368
|
+
alternatives = [q.strip() for q in response.strip().split("\n") if q.strip()]
|
|
369
|
+
|
|
370
|
+
return [query] + alternatives[:3]
|
|
371
|
+
```
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Ml Monitoring Suite
|
|
4
|
+
Production-grade tool for senior ml/ai engineer
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import json
|
|
10
|
+
import logging
|
|
11
|
+
import argparse
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Dict, List, Optional
|
|
14
|
+
from datetime import datetime
|
|
15
|
+
|
|
16
|
+
logging.basicConfig(
|
|
17
|
+
level=logging.INFO,
|
|
18
|
+
format='%(asctime)s - %(levelname)s - %(message)s'
|
|
19
|
+
)
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
class MlMonitoringSuite:
|
|
23
|
+
"""Production-grade ml monitoring suite"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, config: Dict):
|
|
26
|
+
self.config = config
|
|
27
|
+
self.results = {
|
|
28
|
+
'status': 'initialized',
|
|
29
|
+
'start_time': datetime.now().isoformat(),
|
|
30
|
+
'processed_items': 0
|
|
31
|
+
}
|
|
32
|
+
logger.info(f"Initialized {self.__class__.__name__}")
|
|
33
|
+
|
|
34
|
+
def validate_config(self) -> bool:
|
|
35
|
+
"""Validate configuration"""
|
|
36
|
+
logger.info("Validating configuration...")
|
|
37
|
+
# Add validation logic
|
|
38
|
+
logger.info("Configuration validated")
|
|
39
|
+
return True
|
|
40
|
+
|
|
41
|
+
def process(self) -> Dict:
|
|
42
|
+
"""Main processing logic"""
|
|
43
|
+
logger.info("Starting processing...")
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
self.validate_config()
|
|
47
|
+
|
|
48
|
+
# Main processing
|
|
49
|
+
result = self._execute()
|
|
50
|
+
|
|
51
|
+
self.results['status'] = 'completed'
|
|
52
|
+
self.results['end_time'] = datetime.now().isoformat()
|
|
53
|
+
|
|
54
|
+
logger.info("Processing completed successfully")
|
|
55
|
+
return self.results
|
|
56
|
+
|
|
57
|
+
except Exception as e:
|
|
58
|
+
self.results['status'] = 'failed'
|
|
59
|
+
self.results['error'] = str(e)
|
|
60
|
+
logger.error(f"Processing failed: {e}")
|
|
61
|
+
raise
|
|
62
|
+
|
|
63
|
+
def _execute(self) -> Dict:
|
|
64
|
+
"""Execute main logic"""
|
|
65
|
+
# Implementation here
|
|
66
|
+
return {'success': True}
|
|
67
|
+
|
|
68
|
+
def main():
|
|
69
|
+
"""Main entry point"""
|
|
70
|
+
parser = argparse.ArgumentParser(
|
|
71
|
+
description="Ml Monitoring Suite"
|
|
72
|
+
)
|
|
73
|
+
parser.add_argument('--input', '-i', required=True, help='Input path')
|
|
74
|
+
parser.add_argument('--output', '-o', required=True, help='Output path')
|
|
75
|
+
parser.add_argument('--config', '-c', help='Configuration file')
|
|
76
|
+
parser.add_argument('--verbose', '-v', action='store_true', help='Verbose output')
|
|
77
|
+
|
|
78
|
+
args = parser.parse_args()
|
|
79
|
+
|
|
80
|
+
if args.verbose:
|
|
81
|
+
logging.getLogger().setLevel(logging.DEBUG)
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
config = {
|
|
85
|
+
'input': args.input,
|
|
86
|
+
'output': args.output
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
processor = MlMonitoringSuite(config)
|
|
90
|
+
results = processor.process()
|
|
91
|
+
|
|
92
|
+
print(json.dumps(results, indent=2))
|
|
93
|
+
sys.exit(0)
|
|
94
|
+
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logger.error(f"Fatal error: {e}")
|
|
97
|
+
sys.exit(1)
|
|
98
|
+
|
|
99
|
+
if __name__ == '__main__':
|
|
100
|
+
main()
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Model Deployment Pipeline
|
|
4
|
+
Production-grade tool for senior ml/ai engineer
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import json
|
|
10
|
+
import logging
|
|
11
|
+
import argparse
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Dict, List, Optional
|
|
14
|
+
from datetime import datetime
|
|
15
|
+
|
|
16
|
+
logging.basicConfig(
|
|
17
|
+
level=logging.INFO,
|
|
18
|
+
format='%(asctime)s - %(levelname)s - %(message)s'
|
|
19
|
+
)
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
class ModelDeploymentPipeline:
|
|
23
|
+
"""Production-grade model deployment pipeline"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, config: Dict):
|
|
26
|
+
self.config = config
|
|
27
|
+
self.results = {
|
|
28
|
+
'status': 'initialized',
|
|
29
|
+
'start_time': datetime.now().isoformat(),
|
|
30
|
+
'processed_items': 0
|
|
31
|
+
}
|
|
32
|
+
logger.info(f"Initialized {self.__class__.__name__}")
|
|
33
|
+
|
|
34
|
+
def validate_config(self) -> bool:
|
|
35
|
+
"""Validate configuration"""
|
|
36
|
+
logger.info("Validating configuration...")
|
|
37
|
+
# Add validation logic
|
|
38
|
+
logger.info("Configuration validated")
|
|
39
|
+
return True
|
|
40
|
+
|
|
41
|
+
def process(self) -> Dict:
|
|
42
|
+
"""Main processing logic"""
|
|
43
|
+
logger.info("Starting processing...")
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
self.validate_config()
|
|
47
|
+
|
|
48
|
+
# Main processing
|
|
49
|
+
result = self._execute()
|
|
50
|
+
|
|
51
|
+
self.results['status'] = 'completed'
|
|
52
|
+
self.results['end_time'] = datetime.now().isoformat()
|
|
53
|
+
|
|
54
|
+
logger.info("Processing completed successfully")
|
|
55
|
+
return self.results
|
|
56
|
+
|
|
57
|
+
except Exception as e:
|
|
58
|
+
self.results['status'] = 'failed'
|
|
59
|
+
self.results['error'] = str(e)
|
|
60
|
+
logger.error(f"Processing failed: {e}")
|
|
61
|
+
raise
|
|
62
|
+
|
|
63
|
+
def _execute(self) -> Dict:
|
|
64
|
+
"""Execute main logic"""
|
|
65
|
+
# Implementation here
|
|
66
|
+
return {'success': True}
|
|
67
|
+
|
|
68
|
+
def main():
|
|
69
|
+
"""Main entry point"""
|
|
70
|
+
parser = argparse.ArgumentParser(
|
|
71
|
+
description="Model Deployment Pipeline"
|
|
72
|
+
)
|
|
73
|
+
parser.add_argument('--input', '-i', required=True, help='Input path')
|
|
74
|
+
parser.add_argument('--output', '-o', required=True, help='Output path')
|
|
75
|
+
parser.add_argument('--config', '-c', help='Configuration file')
|
|
76
|
+
parser.add_argument('--verbose', '-v', action='store_true', help='Verbose output')
|
|
77
|
+
|
|
78
|
+
args = parser.parse_args()
|
|
79
|
+
|
|
80
|
+
if args.verbose:
|
|
81
|
+
logging.getLogger().setLevel(logging.DEBUG)
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
config = {
|
|
85
|
+
'input': args.input,
|
|
86
|
+
'output': args.output
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
processor = ModelDeploymentPipeline(config)
|
|
90
|
+
results = processor.process()
|
|
91
|
+
|
|
92
|
+
print(json.dumps(results, indent=2))
|
|
93
|
+
sys.exit(0)
|
|
94
|
+
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logger.error(f"Fatal error: {e}")
|
|
97
|
+
sys.exit(1)
|
|
98
|
+
|
|
99
|
+
if __name__ == '__main__':
|
|
100
|
+
main()
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Rag System Builder
|
|
4
|
+
Production-grade tool for senior ml/ai engineer
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import json
|
|
10
|
+
import logging
|
|
11
|
+
import argparse
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Dict, List, Optional
|
|
14
|
+
from datetime import datetime
|
|
15
|
+
|
|
16
|
+
logging.basicConfig(
|
|
17
|
+
level=logging.INFO,
|
|
18
|
+
format='%(asctime)s - %(levelname)s - %(message)s'
|
|
19
|
+
)
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
class RagSystemBuilder:
|
|
23
|
+
"""Production-grade rag system builder"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, config: Dict):
|
|
26
|
+
self.config = config
|
|
27
|
+
self.results = {
|
|
28
|
+
'status': 'initialized',
|
|
29
|
+
'start_time': datetime.now().isoformat(),
|
|
30
|
+
'processed_items': 0
|
|
31
|
+
}
|
|
32
|
+
logger.info(f"Initialized {self.__class__.__name__}")
|
|
33
|
+
|
|
34
|
+
def validate_config(self) -> bool:
|
|
35
|
+
"""Validate configuration"""
|
|
36
|
+
logger.info("Validating configuration...")
|
|
37
|
+
# Add validation logic
|
|
38
|
+
logger.info("Configuration validated")
|
|
39
|
+
return True
|
|
40
|
+
|
|
41
|
+
def process(self) -> Dict:
|
|
42
|
+
"""Main processing logic"""
|
|
43
|
+
logger.info("Starting processing...")
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
self.validate_config()
|
|
47
|
+
|
|
48
|
+
# Main processing
|
|
49
|
+
result = self._execute()
|
|
50
|
+
|
|
51
|
+
self.results['status'] = 'completed'
|
|
52
|
+
self.results['end_time'] = datetime.now().isoformat()
|
|
53
|
+
|
|
54
|
+
logger.info("Processing completed successfully")
|
|
55
|
+
return self.results
|
|
56
|
+
|
|
57
|
+
except Exception as e:
|
|
58
|
+
self.results['status'] = 'failed'
|
|
59
|
+
self.results['error'] = str(e)
|
|
60
|
+
logger.error(f"Processing failed: {e}")
|
|
61
|
+
raise
|
|
62
|
+
|
|
63
|
+
def _execute(self) -> Dict:
|
|
64
|
+
"""Execute main logic"""
|
|
65
|
+
# Implementation here
|
|
66
|
+
return {'success': True}
|
|
67
|
+
|
|
68
|
+
def main():
|
|
69
|
+
"""Main entry point"""
|
|
70
|
+
parser = argparse.ArgumentParser(
|
|
71
|
+
description="Rag System Builder"
|
|
72
|
+
)
|
|
73
|
+
parser.add_argument('--input', '-i', required=True, help='Input path')
|
|
74
|
+
parser.add_argument('--output', '-o', required=True, help='Output path')
|
|
75
|
+
parser.add_argument('--config', '-c', help='Configuration file')
|
|
76
|
+
parser.add_argument('--verbose', '-v', action='store_true', help='Verbose output')
|
|
77
|
+
|
|
78
|
+
args = parser.parse_args()
|
|
79
|
+
|
|
80
|
+
if args.verbose:
|
|
81
|
+
logging.getLogger().setLevel(logging.DEBUG)
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
config = {
|
|
85
|
+
'input': args.input,
|
|
86
|
+
'output': args.output
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
processor = RagSystemBuilder(config)
|
|
90
|
+
results = processor.process()
|
|
91
|
+
|
|
92
|
+
print(json.dumps(results, indent=2))
|
|
93
|
+
sys.exit(0)
|
|
94
|
+
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logger.error(f"Fatal error: {e}")
|
|
97
|
+
sys.exit(1)
|
|
98
|
+
|
|
99
|
+
if __name__ == '__main__':
|
|
100
|
+
main()
|