ChatGPT Claude Codex CLI Cohere Cursor DeepSeek Gemini GitHub Copilot GLM Grok Kimi Llama MiniMax Mistral OpenAI opencode Skill

similarity-search-patterns

Implement efficient similarity search with vector databases. Use when building semantic search, implementing nearest neighbor queries, or optimizing retrieval performance.

LLM Mart · 0 points · 14 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download sickn33-agentic-awesome-skills-skills_similarity-search-patterns-286166a.zip · 5 KB
Part of sickn33/agentic-awesome-skills — 427 skills
This skill couldn't be refreshed from GitHub on the last check — you're seeing the last imported snapshot.

Install

skills CLI npx skills add https://github.com/sickn33/agentic-awesome-skills/tree/main/skills/similarity-search-patterns
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install sickn33-agentic-awesome-skills@llmmart
Git git clone https://github.com/sickn33/agentic-awesome-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole sickn33/agentic-awesome-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Similarity Search Patterns

Patterns for implementing efficient similarity search in production systems.

Use this skill when

  • Building semantic search systems
  • Implementing RAG retrieval
  • Creating recommendation engines
  • Optimizing search latency
  • Scaling to millions of vectors
  • Combining semantic and keyword search

Do not use this skill when

  • The task is unrelated to similarity search patterns
  • You need a different domain or tool outside this scope

Instructions

  • Clarify goals, constraints, and required inputs.
  • Apply relevant best practices and validate outcomes.
  • Provide actionable steps and verification.
  • If detailed examples are required, open resources/implementation-playbook.md.

Resources

  • resources/implementation-playbook.md for detailed patterns and examples.

Limitations

  • Use this skill only when the task clearly matches the scope described above.
  • Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
  • Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
Files (agentic-awesome-skills)
  • resources
    • implementation-playbook.md 17.5 KB
      # Similarity Search Patterns Implementation Playbook
      
      This file contains detailed patterns, checklists, and code samples referenced by the skill.
      
      # Similarity Search Patterns
      
      Patterns for implementing efficient similarity search in production systems.
      
      ## When to Use This Skill
      
      - Building semantic search systems
      - Implementing RAG retrieval
      - Creating recommendation engines
      - Optimizing search latency
      - Scaling to millions of vectors
      - Combining semantic and keyword search
      
      ## Core Concepts
      
      ### 1. Distance Metrics
      
      | Metric | Formula | Best For |
      |--------|---------|----------|
      | **Cosine** | 1 - (A·B)/(‖A‖‖B‖) | Normalized embeddings |
      | **Euclidean (L2)** | √Σ(a-b)² | Raw embeddings |
      | **Dot Product** | A·B | Magnitude matters |
      | **Manhattan (L1)** | Σ|a-b| | Sparse vectors |
      
      ### 2. Index Types
      
      ```
      ┌─────────────────────────────────────────────────┐
      │                 Index Types                      │
      ├─────────────┬───────────────┬───────────────────┤
      │    Flat     │     HNSW      │    IVF+PQ         │
      │ (Exact)     │ (Graph-based) │ (Quantized)       │
      ├─────────────┼───────────────┼───────────────────┤
      │ O(n) search │ O(log n)      │ O(√n)             │
      │ 100% recall │ ~95-99%       │ ~90-95%           │
      │ Small data  │ Medium-Large  │ Very Large        │
      └─────────────┴───────────────┴───────────────────┘
      ```
      
      ## Templates
      
      ### Template 1: Pinecone Implementation
      
      ```python
      from pinecone import Pinecone, ServerlessSpec
      from typing import List, Dict, Optional
      import hashlib
      
      class PineconeVectorStore:
          def __init__(
              self,
              api_key: str,
              index_name: str,
              dimension: int = 1536,
              metric: str = "cosine"
          ):
              self.pc = Pinecone(api_key=api_key)
      
              # Create index if not exists
              if index_name not in self.pc.list_indexes().names():
                  self.pc.create_index(
                      name=index_name,
                      dimension=dimension,
                      metric=metric,
                      spec=ServerlessSpec(cloud="aws", region="us-east-1")
                  )
      
              self.index = self.pc.Index(index_name)
      
          def upsert(
              self,
              vectors: List[Dict],
              namespace: str = ""
          ) -> int:
              """
              Upsert vectors.
              vectors: [{"id": str, "values": List[float], "metadata": dict}]
              """
              # Batch upsert
              batch_size = 100
              total = 0
      
              for i in range(0, len(vectors), batch_size):
                  batch = vectors[i:i + batch_size]
                  self.index.upsert(vectors=batch, namespace=namespace)
                  total += len(batch)
      
              return total
      
          def search(
              self,
              query_vector: List[float],
              top_k: int = 10,
              namespace: str = "",
              filter: Optional[Dict] = None,
              include_metadata: bool = True
          ) -> List[Dict]:
              """Search for similar vectors."""
              results = self.index.query(
                  vector=query_vector,
                  top_k=top_k,
                  namespace=namespace,
                  filter=filter,
                  include_metadata=include_metadata
              )
      
              return [
                  {
                      "id": match.id,
                      "score": match.score,
                      "metadata": match.metadata
                  }
                  for match in results.matches
              ]
      
          def search_with_rerank(
              self,
              query: str,
              query_vector: List[float],
              top_k: int = 10,
              rerank_top_n: int = 50,
              namespace: str = ""
          ) -> List[Dict]:
              """Search and rerank results."""
              # Over-fetch for reranking
              initial_results = self.search(
                  query_vector,
                  top_k=rerank_top_n,
                  namespace=namespace
              )
      
              # Rerank with cross-encoder or LLM
              reranked = self._rerank(query, initial_results)
      
              return reranked[:top_k]
      
          def _rerank(self, query: str, results: List[Dict]) -> List[Dict]:
              """Rerank results using cross-encoder."""
              from sentence_transformers import CrossEncoder
      
              model = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
      
              pairs = [(query, r["metadata"]["text"]) for r in results]
              scores = model.predict(pairs)
      
              for result, score in zip(results, scores):
                  result["rerank_score"] = float(score)
      
              return sorted(results, key=lambda x: x["rerank_score"], reverse=True)
      
          def delete(self, ids: List[str], namespace: str = ""):
              """Delete vectors by ID."""
              self.index.delete(ids=ids, namespace=namespace)
      
          def delete_by_filter(self, filter: Dict, namespace: str = ""):
              """Delete vectors matching filter."""
              self.index.delete(filter=filter, namespace=namespace)
      ```
      
      ### Template 2: Qdrant Implementation
      
      ```python
      from qdrant_client import QdrantClient
      from qdrant_client.http import models
      from typing import List, Dict, Optional
      
      class QdrantVectorStore:
          def __init__(
              self,
              url: str = "localhost",
              port: int = 6333,
              collection_name: str = "documents",
              vector_size: int = 1536
          ):
              self.client = QdrantClient(url=url, port=port)
              self.collection_name = collection_name
      
              # Create collection if not exists
              collections = self.client.get_collections().collections
              if collection_name not in [c.name for c in collections]:
                  self.client.create_collection(
                      collection_name=collection_name,
                      vectors_config=models.VectorParams(
                          size=vector_size,
                          distance=models.Distance.COSINE
                      ),
                      # Optional: enable quantization for memory efficiency
                      quantization_config=models.ScalarQuantization(
                          scalar=models.ScalarQuantizationConfig(
                              type=models.ScalarType.INT8,
                              quantile=0.99,
                              always_ram=True
                          )
                      )
                  )
      
          def upsert(self, points: List[Dict]) -> int:
              """
              Upsert points.
              points: [{"id": str/int, "vector": List[float], "payload": dict}]
              """
              qdrant_points = [
                  models.PointStruct(
                      id=p["id"],
                      vector=p["vector"],
                      payload=p.get("payload", {})
                  )
                  for p in points
              ]
      
              self.client.upsert(
                  collection_name=self.collection_name,
                  points=qdrant_points
              )
              return len(points)
      
          def search(
              self,
              query_vector: List[float],
              limit: int = 10,
              filter: Optional[models.Filter] = None,
              score_threshold: Optional[float] = None
          ) -> List[Dict]:
              """Search for similar vectors."""
              results = self.client.search(
                  collection_name=self.collection_name,
                  query_vector=query_vector,
                  limit=limit,
                  query_filter=filter,
                  score_threshold=score_threshold
              )
      
              return [
                  {
                      "id": r.id,
                      "score": r.score,
                      "payload": r.payload
                  }
                  for r in results
              ]
      
          def search_with_filter(
              self,
              query_vector: List[float],
              must_conditions: List[Dict] = None,
              should_conditions: List[Dict] = None,
              must_not_conditions: List[Dict] = None,
              limit: int = 10
          ) -> List[Dict]:
              """Search with complex filters."""
              conditions = []
      
              if must_conditions:
                  conditions.extend([
                      models.FieldCondition(
                          key=c["key"],
                          match=models.MatchValue(value=c["value"])
                      )
                      for c in must_conditions
                  ])
      
              filter = models.Filter(must=conditions) if conditions else None
      
              return self.search(query_vector, limit=limit, filter=filter)
      
          def search_with_sparse(
              self,
              dense_vector: List[float],
              sparse_vector: Dict[int, float],
              limit: int = 10,
              dense_weight: float = 0.7
          ) -> List[Dict]:
              """Hybrid search with dense and sparse vectors."""
              # Requires collection with named vectors
              results = self.client.search(
                  collection_name=self.collection_name,
                  query_vector=models.NamedVector(
                      name="dense",
                      vector=dense_vector
                  ),
                  limit=limit
              )
              return [{"id": r.id, "score": r.score, "payload": r.payload} for r in results]
      ```
      
      ### Template 3: pgvector with PostgreSQL
      
      ```python
      import asyncpg
      from typing import List, Dict, Optional
      import numpy as np
      
      class PgVectorStore:
          def __init__(self, connection_string: str):
              self.connection_string = connection_string
      
          async def init(self):
              """Initialize connection pool and extension."""
              self.pool = await asyncpg.create_pool(self.connection_string)
      
              async with self.pool.acquire() as conn:
                  # Enable extension
                  await conn.execute("CREATE EXTENSION IF NOT EXISTS vector")
      
                  # Create table
                  await conn.execute("""
                      CREATE TABLE IF NOT EXISTS documents (
                          id TEXT PRIMARY KEY,
                          content TEXT,
                          metadata JSONB,
                          embedding vector(1536)
                      )
                  """)
      
                  # Create index (HNSW for better performance)
                  await conn.execute("""
                      CREATE INDEX IF NOT EXISTS documents_embedding_idx
                      ON documents
                      USING hnsw (embedding vector_cosine_ops)
                      WITH (m = 16, ef_construction = 64)
                  """)
      
          async def upsert(self, documents: List[Dict]):
              """Upsert documents with embeddings."""
              async with self.pool.acquire() as conn:
                  await conn.executemany(
                      """
                      INSERT INTO documents (id, content, metadata, embedding)
                      VALUES ($1, $2, $3, $4)
                      ON CONFLICT (id) DO UPDATE SET
                          content = EXCLUDED.content,
                          metadata = EXCLUDED.metadata,
                          embedding = EXCLUDED.embedding
                      """,
                      [
                          (
                              doc["id"],
                              doc["content"],
                              doc.get("metadata", {}),
                              np.array(doc["embedding"]).tolist()
                          )
                          for doc in documents
                      ]
                  )
      
          async def search(
              self,
              query_embedding: List[float],
              limit: int = 10,
              filter_metadata: Optional[Dict] = None
          ) -> List[Dict]:
              """Search for similar documents."""
              query = """
                  SELECT id, content, metadata,
                         1 - (embedding <=> $1::vector) as similarity
                  FROM documents
              """
      
              params = [query_embedding]
      
              if filter_metadata:
                  conditions = []
                  for key, value in filter_metadata.items():
                      params.append(value)
                      conditions.append(f"metadata->>'{key}' = ${len(params)}")
                  query += " WHERE " + " AND ".join(conditions)
      
              query += f" ORDER BY embedding <=> $1::vector LIMIT ${len(params) + 1}"
              params.append(limit)
      
              async with self.pool.acquire() as conn:
                  rows = await conn.fetch(query, *params)
      
              return [
                  {
                      "id": row["id"],
                      "content": row["content"],
                      "metadata": row["metadata"],
                      "score": row["similarity"]
                  }
                  for row in rows
              ]
      
          async def hybrid_search(
              self,
              query_embedding: List[float],
              query_text: str,
              limit: int = 10,
              vector_weight: float = 0.5
          ) -> List[Dict]:
              """Hybrid search combining vector and full-text."""
              async with self.pool.acquire() as conn:
                  rows = await conn.fetch(
                      """
                      WITH vector_results AS (
                          SELECT id, content, metadata,
                                 1 - (embedding <=> $1::vector) as vector_score
                          FROM documents
                          ORDER BY embedding <=> $1::vector
                          LIMIT $3 * 2
                      ),
                      text_results AS (
                          SELECT id, content, metadata,
                                 ts_rank(to_tsvector('english', content),
                                         plainto_tsquery('english', $2)) as text_score
                          FROM documents
                          WHERE to_tsvector('english', content) @@ plainto_tsquery('english', $2)
                          LIMIT $3 * 2
                      )
                      SELECT
                          COALESCE(v.id, t.id) as id,
                          COALESCE(v.content, t.content) as content,
                          COALESCE(v.metadata, t.metadata) as metadata,
                          COALESCE(v.vector_score, 0) * $4 +
                          COALESCE(t.text_score, 0) * (1 - $4) as combined_score
                      FROM vector_results v
                      FULL OUTER JOIN text_results t ON v.id = t.id
                      ORDER BY combined_score DESC
                      LIMIT $3
                      """,
                      query_embedding, query_text, limit, vector_weight
                  )
      
              return [dict(row) for row in rows]
      ```
      
      ### Template 4: Weaviate Implementation
      
      ```python
      import weaviate
      from weaviate.util import generate_uuid5
      from typing import List, Dict, Optional
      
      class WeaviateVectorStore:
          def __init__(
              self,
              url: str = "http://localhost:8080",
              class_name: str = "Document"
          ):
              self.client = weaviate.Client(url=url)
              self.class_name = class_name
              self._ensure_schema()
      
          def _ensure_schema(self):
              """Create schema if not exists."""
              schema = {
                  "class": self.class_name,
                  "vectorizer": "none",  # We provide vectors
                  "properties": [
                      {"name": "content", "dataType": ["text"]},
                      {"name": "source", "dataType": ["string"]},
                      {"name": "chunk_id", "dataType": ["int"]}
                  ]
              }
      
              if not self.client.schema.exists(self.class_name):
                  self.client.schema.create_class(schema)
      
          def upsert(self, documents: List[Dict]):
              """Batch upsert documents."""
              with self.client.batch as batch:
                  batch.batch_size = 100
      
                  for doc in documents:
                      batch.add_data_object(
                          data_object={
                              "content": doc["content"],
                              "source": doc.get("source", ""),
                              "chunk_id": doc.get("chunk_id", 0)
                          },
                          class_name=self.class_name,
                          uuid=generate_uuid5(doc["id"]),
                          vector=doc["embedding"]
                      )
      
          def search(
              self,
              query_vector: List[float],
              limit: int = 10,
              where_filter: Optional[Dict] = None
          ) -> List[Dict]:
              """Vector search."""
              query = (
                  self.client.query
                  .get(self.class_name, ["content", "source", "chunk_id"])
                  .with_near_vector({"vector": query_vector})
                  .with_limit(limit)
                  .with_additional(["distance", "id"])
              )
      
              if where_filter:
                  query = query.with_where(where_filter)
      
              results = query.do()
      
              return [
                  {
                      "id": item["_additional"]["id"],
                      "content": item["content"],
                      "source": item["source"],
                      "score": 1 - item["_additional"]["distance"]
                  }
                  for item in results["data"]["Get"][self.class_name]
              ]
      
          def hybrid_search(
              self,
              query: str,
              query_vector: List[float],
              limit: int = 10,
              alpha: float = 0.5  # 0 = keyword, 1 = vector
          ) -> List[Dict]:
              """Hybrid search combining BM25 and vector."""
              results = (
                  self.client.query
                  .get(self.class_name, ["content", "source"])
                  .with_hybrid(query=query, vector=query_vector, alpha=alpha)
                  .with_limit(limit)
                  .with_additional(["score"])
                  .do()
              )
      
              return [
                  {
                      "content": item["content"],
                      "source": item["source"],
                      "score": item["_additional"]["score"]
                  }
                  for item in results["data"]["Get"][self.class_name]
              ]
      ```
      
      ## Best Practices
      
      ### Do's
      - **Use appropriate index** - HNSW for most cases
      - **Tune parameters** - ef_search, nprobe for recall/speed
      - **Implement hybrid search** - Combine with keyword search
      - **Monitor recall** - Measure search quality
      - **Pre-filter when possible** - Reduce search space
      
      ### Don'ts
      - **Don't skip evaluation** - Measure before optimizing
      - **Don't over-index** - Start with flat, scale up
      - **Don't ignore latency** - P99 matters for UX
      - **Don't forget costs** - Vector storage adds up
      
      ## Resources
      
      - [Pinecone Docs](https://docs.pinecone.io/)
      - [Qdrant Docs](https://qdrant.tech/documentation/)
      - [pgvector](https://github.com/pgvector/pgvector)
      - [Weaviate Docs](https://weaviate.io/developers/weaviate)
      
  • SKILL.md 1.4 KB
    ---
    name: similarity-search-patterns
    description: "Implement efficient similarity search with vector databases. Use when building semantic search, implementing nearest neighbor queries, or optimizing retrieval performance."
    risk: safe
    source: community
    date_added: "2026-02-27"
    ---
    
    # Similarity Search Patterns
    
    Patterns for implementing efficient similarity search in production systems.
    
    ## Use this skill when
    
    - Building semantic search systems
    - Implementing RAG retrieval
    - Creating recommendation engines
    - Optimizing search latency
    - Scaling to millions of vectors
    - Combining semantic and keyword search
    
    ## Do not use this skill when
    
    - The task is unrelated to similarity search patterns
    - You need a different domain or tool outside this scope
    
    ## Instructions
    
    - Clarify goals, constraints, and required inputs.
    - Apply relevant best practices and validate outcomes.
    - Provide actionable steps and verification.
    - If detailed examples are required, open `resources/implementation-playbook.md`.
    
    ## Resources
    
    - `resources/implementation-playbook.md` for detailed patterns and examples.
    
    ## Limitations
    - Use this skill only when the task clearly matches the scope described above.
    - Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
    - Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related