ワンクリックで
engineering-ai-pipelines
AI/ML production workflows: embedding generation, vector storage, RAG patterns, LLM monitoring, and batch inference.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
AI/ML production workflows: embedding generation, vector storage, RAG patterns, LLM monitoring, and batch inference.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Access cloud storage (S3, GCS, Azure) in Python using fsspec, pyarrow.fs, or obstore. Includes DataFrame integrations (Polars, DuckDB, Pandas, PyArrow), performance optimization, patterns for incremental loading, partitioned writes, and cross-cloud copy.
Exploratory data analysis and visualization: profiling datasets, choosing appropriate charts, applying statistical tests, and creating effective visualizations for insight communication. Use when understanding data structure, exploring distributions and relationships, selecting visualization libraries, or producing analysis-ready charts.
Data quality validation and observability for data pipelines. Combines Great Expectations and Pandera for data validation with OpenTelemetry and Prometheus for monitoring and alerting.
File formats and lakehouse table formats for data lakes: Parquet, Arrow, Lance, Zarr, Avro, ORC, Delta Lake, Apache Iceberg, and Apache Hudi. Covers compression, partitioning, ACID transactions, schema evolution, and format selection.
Feature engineering for machine learning: encoding categorical variables, scaling numeric features, datetime transformations, text features, and leakage-safe preprocessing pipelines. Use when preparing data for modeling or improving model performance through better representations.
Model evaluation and validation: cross-validation strategies, metrics selection, hyperparameter tuning, experiment tracking, and model comparison. Use when assessing model performance, diagnosing issues, selecting models, or optimizing hyperparameters.
| name | engineering-ai-pipelines |
| description | AI/ML production workflows: embedding generation, vector storage, RAG patterns, LLM monitoring, and batch inference. |
| dependsOn | ["@building-data-pipelines","@designing-data-storage"] |
Production-ready patterns for AI/ML data pipelines: generating embeddings, selecting vector databases, building RAG systems, and monitoring LLM usage. Covers local and cloud-based approaches with cost and performance considerations.
| Approach | Provider | Dimensions | Cost | Speed | Best For |
|---|---|---|---|---|---|
| OpenAI 3-small | OpenAI | 1536 | $0.00002/1K tokens | ⚡⚡⚡ Fast | Production, convenience |
| OpenAI 3-large | OpenAI | 3072 | $0.00013/1K tokens | ⚡⚡ | Higher quality needs |
| MiniLM-L6 | Local (sentence-transformers) | 384 | Free | ⚡⚡ | Privacy, offline, cost control |
| MPNet-base | Local (sentence-transformers) | 768 | Free | ⚡⚡ | Better quality than MiniLM |
| OpenAI ada-002 | OpenAI | 1536 | $0.00010/1K tokens | ⚡⚡⚡ | Legacy compatibility |
| Feature | LanceDB | pgvector | DuckDB | Pinecone/Weaviate |
|---|---|---|---|---|
| Deployment | Embedded file | PostgreSQL | Embedded | Managed service |
| Scale | Millions | Tens of millions | <100K | Billions |
| Index Types | IVF_PQ, HNSW | HNSW, IVFFlat | None | HNSW, IVF |
| Cloud Native | ✅ S3/GCS/Azure | Via RDS | ❌ | ✅ |
| ACID | ✅ | ✅ ✅ | ✅ | Varies |
| Cost | Free | Postgres cost | Free | Usage-based |
| Best For | RAG apps, prototyping | Production + existing PG | Quick experiments | Enterprise scale |
Choose OpenAI API when:
Choose Local Models (sentence-transformers) when:
Choose OpenAI 3-small vs 3-large:
Choose LanceDB when:
Choose pgvector when:
Choose DuckDB when:
Choose Managed Services (Pinecone, Weaviate) when:
Simple RAG (single stage):
Query → Embedding → Vector Search → Context → LLM → Answer
Advanced RAG (multi-stage):
Query → Embedding → Vector Search → Re-ranking → Context → LLM → Answer
Hybrid RAG:
Query → [Vector Search + Keyword/BM25] → Fusion → Context → LLM → Answer
| Use Case | Embedding | Vector DB | RAG Pattern | Monitoring |
|---|---|---|---|---|
| Internal knowledge base | OpenAI 3-small | LanceDB | Simple RAG | Basic cost tracking |
| Customer-facing chatbot | OpenAI 3-large | pgvector | Advanced (re-ranking) | Full observability |
| Healthcare (HIPAA) | Local MiniLM | LanceDB (on-prem) | Simple RAG | Local logging only |
| Financial documents | OpenAI 3-small | pgvector | Hybrid RAG | Cost + audit logs |
| Research paper search | Local MPNet | LanceDB | Advanced RAG | Basic metrics |
| High-volume (>10M docs) | OpenAI 3-small | Managed (Pinecone) | Simple RAG | Full observability |
| Multi-modal (text + images) | CLIP/Local | LanceDB | Simple RAG | Basic tracking |
references/embeddings.md - OpenAI API, sentence-transformers, batch processing, model selectionreferences/vector-stores.md - LanceDB, pgvector, DuckDB comparison and selectionreferences/rag-pipelines.md - Chunking strategies, context assembly, retrieval patternsreferences/monitoring.md - Cost tracking, retry logic, OpenTelemetry, quality evaluationimport openai
import polars as pl
import tiktoken
class OpenAIEmbeddingPipeline:
def __init__(self, model: str = "text-embedding-3-small"):
self.client = openai.OpenAI()
self.model = model
self.encoding = tiktoken.encoding_for_model(model)
def generate_embeddings(self, texts: list[str]) -> list[list[float]]:
"""Generate embeddings in batches of 100."""
all_embeddings = []
batch_size = 100
for i in range(0, len(texts), batch_size):
batch = texts[i:i + batch_size]
response = self.client.embeddings.create(
model=self.model,
input=batch
)
all_embeddings.extend([e.embedding for e in response.data])
return all_embeddings
def process_dataframe(self, df: pl.DataFrame, text_col: str) -> pl.DataFrame:
"""Add embeddings column to Polars DataFrame."""
texts = df[text_col].to_list()
embeddings = self.generate_embeddings(texts)
return df.with_columns(pl.Series("embedding", embeddings))
# Usage
pipeline = OpenAIEmbeddingPipeline()
df = pl.DataFrame({"text": ["Hello world", "Goodbye world"]})
df_with_embeddings = pipeline.process_dataframe(df, "text")
from sentence_transformers import SentenceTransformer
import polars as pl
model = SentenceTransformer('all-MiniLM-L6-v2') # 384 dimensions
texts = ["Hello world", "Goodbye world"]
embeddings = model.encode(texts, show_progress_bar=True)
df = pl.DataFrame({
"text": texts,
"embedding": embeddings.tolist()
})
import lancedb
import polars as pl
# Connect and create table
db = lancedb.connect("./.lancedb")
df = pl.DataFrame({
"id": [1, 2, 3],
"text": ["Machine learning basics", "Deep learning intro", "Neural networks"],
"embedding": [[0.1] * 384, [0.2] * 384, [0.3] * 384]
})
table = db.create_table("documents", df.to_arrow())
# Create index for faster search
table.create_index(
vector_column_name="embedding",
metric="cosine",
index_type="IVF_PQ",
num_partitions=256,
num_sub_vectors=96
)
# Search with filtering
query_embedding = [0.15] * 384
results = (
table.search(query_embedding)
.where("id > 1")
.limit(5)
.to_pandas()
)
import lancedb
from sentence_transformers import SentenceTransformer
import openai
class RAGPipeline:
def __init__(self, db_path: str, embedding_model: str = "all-MiniLM-L6-v2"):
self.embedder = SentenceTransformer(embedding_model)
self.db = lancedb.connect(db_path)
self.table = self.db.open_table("documents")
self.openai_client = openai.OpenAI()
def retrieve(self, query: str, k: int = 5) -> list[dict]:
"""Retrieve relevant documents."""
query_embedding = self.embedder.encode([query])[0].tolist()
results = self.table.search(query_embedding).limit(k).to_pandas()
return results.to_dict('records')
def generate(self, query: str, context_docs: list[dict]) -> str:
"""Generate answer with LLM."""
context_text = "\n\n---\n\n".join([doc['text'] for doc in context_docs])
response = self.openai_client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "Answer based on the provided context. Cite sources using [1], [2], etc."},
{"role": "user", "content": f"Context:\n{context_text}\n\nQuestion: {query}\n\nAnswer:"}
],
temperature=0.1
)
return response.choices[0].message.content
def run(self, query: str, k: int = 5) -> dict:
"""Full RAG pipeline."""
docs = self.retrieve(query, k)
answer = self.generate(query, docs)
return {
"answer": answer,
"sources": [{"id": d['id'], "text": d['text'][:200]} for d in docs],
"source_count": len(docs)
}
# Usage
rag = RAGPipeline("./.lancedb")
result = rag.run("What is machine learning?")
print(result["answer"])
import duckdb
from datetime import datetime
import time
class LLMMonitor:
def __init__(self, db_path: str = "llm_monitoring.db"):
self.conn = duckdb.connect(db_path)
self._init_tables()
def _init_tables(self):
self.conn.sql("""
CREATE TABLE IF NOT EXISTS llm_calls (
call_id VARCHAR PRIMARY KEY,
timestamp TIMESTAMP,
model VARCHAR,
prompt_tokens INTEGER,
completion_tokens INTEGER,
total_tokens INTEGER,
cost_usd DOUBLE,
latency_ms INTEGER,
status VARCHAR
)
""")
def log_call(self, model: str, prompt_tokens: int, completion_tokens: int, latency_ms: int):
# Approximate cost (update with current pricing)
cost_per_1k = {
"gpt-4o": 0.0025,
"gpt-4o-mini": 0.00015,
"text-embedding-3-small": 0.00002
}.get(model, 0.001)
total_tokens = prompt_tokens + completion_tokens
cost = total_tokens / 1000 * cost_per_1k
call_id = f"{datetime.now().timestamp():.6f}"
self.conn.execute("""
INSERT INTO llm_calls VALUES (?, NOW(), ?, ?, ?, ?, ?, ?, ?)
""", [call_id, model, prompt_tokens, completion_tokens, total_tokens, cost, latency_ms, "success"])
def get_usage_stats(self, days: int = 7) -> dict:
result = self.conn.sql(f"""
SELECT
COUNT(*) as total_calls,
SUM(total_tokens) as total_tokens,
SUM(cost_usd) as total_cost,
AVG(latency_ms) as avg_latency
FROM llm_calls
WHERE timestamp > NOW() - INTERVAL '{days} days'
""").fetchone()
return {
'total_calls': result[0],
'total_tokens': result[1],
'total_cost_usd': result[2],
'avg_latency_ms': result[3]
}
# Usage with retry pattern
import openai
from tenacity import retry, stop_after_attempt, wait_exponential
monitor = LLMMonitor()
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
def monitored_llm_call(prompt: str, model: str = "gpt-4o") -> str:
client = openai.OpenAI()
start = time.time()
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}]
)
latency_ms = int((time.time() - start) * 1000)
usage = response.usage
monitor.log_call(model, usage.prompt_tokens, usage.completion_tokens, latency_ms)
return response.choices[0].message.content
@designing-data-storage - File formats (Parquet, Lance) and lakehouse formats for storing embeddings@building-data-pipelines - Polars, DuckDB for data processing in pipelines@orchestrating-data-pipelines - Scheduling and batch processing for embedding generation@assuring-data-pipelines - Data validation and quality checks for ML pipelines@assuring-data-pipelines - General pipeline monitoring with OpenTelemetry