在当今的 AI 应用开发领域,检索增强生成(Retrieval-Augmented Generation,RAG)已成为构建智能对话系统的核心技术架构。本文将从实战角度出发,详细讲解如何将 RAG 架构与向量数据库进行深度集成,并提供可直接运行的代码示例。作为演示平台,我将使用 HolySheep AI 作为后端推理服务。

核心概念解析

RAG 架构的核心思想是将大型语言模型(LLM)的生成能力与外部知识库的检索能力相结合。当用户提出问题时,系统首先从向量数据库中检索相关的文档片段,然后将这些片段作为上下文提供给 LLM,从而生成更加准确和基于事实的回答。

向量数据库在这一架构中扮演着至关重要的角色。它负责将文本、图像或其他形式的数据转换为高维向量表示(embeddings),并提供高效的相似性搜索能力。当用户查询时,系统会将查询转换为向量,然后在数据库中寻找与之最相似的向量,返回对应的原始数据。

服务提供商对比分析

特性HolySheep AIOpenAI API其他中转服务
Embeddings 定价¥1=$1(约 $0.15/MTok)$0.13/MTok¥8-15/百万 tokens
LLM 推理定价GPT-4.1 $8, Claude 4.5 $15, DeepSeek V3.2 $0.42/MTokGPT-4o $5/MTok浮动定价
延迟表现<50ms100-300ms200-500ms
支付方式WeChat/Alipay/银行卡国际信用卡微信/支付宝
免费额度注册即送 Credits$5 试用额度有限或无
API 稳定性企业级保障高可用参差不齐

从上述对比可以看出,HolySheep AI 在价格方面具有明显优势。以 DeepSeek V3.2 为例,其价格仅为 $0.42/MTok,相比官方渠道可节省 85% 以上的成本。同时,其 API 响应延迟控制在 50 毫秒以内,能够满足大多数实时对话系统的需求。

系统架构设计

一个完整的 RAG 系统通常包含以下几个核心组件:文档处理模块负责将原始文档分割成适合处理的文本块;向量化模块使用 embedding 模型将文本块转换为向量表示;向量数据库负责存储这些向量并提供相似性搜索能力;最后,生成模块结合检索结果和用户问题,通过 LLM 生成最终回答。

# RAG 系统核心组件实现
import httpx
import json
from typing import List, Dict, Tuple

class HolySheepEmbedding:
    """HolySheep AI Embeddings API 封装"""
    
    def __init__(self, api_key: str, base_url: str = "https://api.holysheep.ai/v1"):
        self.api_key = api_key
        self.base_url = base_url
        self.client = httpx.Client(timeout=60.0)
    
    def get_embedding(self, text: str) -> List[float]:
        """获取单条文本的向量表示"""
        response = self.client.post(
            f"{self.base_url}/embeddings",
            headers={
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            },
            json={
                "model": "text-embedding-3-small",
                "input": text
            }
        )
        response.raise_for_status()
        return response.json()["data"][0]["embedding"]
    
    def get_embeddings_batch(self, texts: List[str]) -> List[List[float]]:
        """批量获取文本向量(提升效率)"""
        response = self.client.post(
            f"{self.base_url}/embeddings",
            headers={
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            },
            json={
                "model": "text-embedding-3-small",
                "input": texts
            }
        )
        response.raise_for_status()
        return [item["embedding"] for item in response.json()["data"]]

class SimpleVectorStore:
    """简化的向量数据库实现(生产环境建议使用 Milvus/Pinecone)"""
    
    def __init__(self, dimension: int = 1536):
        self.dimension = dimension
        self.vectors: List[List[float]] = []
        self.metadata: List[Dict] = []
    
    def add_vectors(self, vectors: List[List[float]], metadata: List[Dict]):
        """添加向量及其元数据"""
        self.vectors.extend(vectors)
        self.metadata.extend(metadata)
    
    def cosine_similarity(self, a: List[float], b: List[float]) -> float:
        """计算余弦相似度"""
        dot_product = sum(x * y for x, y in zip(a, b))
        norm_a = sum(x * x for x in a) ** 0.5
        norm_b = sum(x * x for x in b) ** 0.5
        return dot_product / (norm_a * norm_b + 1e-8)
    
    def search(self, query_vector: List[float], top_k: int = 5) -> List[Tuple[Dict, float]]:
        """搜索最相似的向量"""
        similarities = [
            (meta, self.cosine_similarity(query_vector, vec))
            for vec, meta in zip(self.vectors, self.metadata)
        ]
        return sorted(similarities, key=lambda x: x[1], reverse=True)[:top_k]

class RAGSystem:
    """完整的 RAG 检索生成系统"""
    
    def __init__(self, api_key: str):
        self.embedding_client = HolySheepEmbedding(api_key)
        self.vector_store = SimpleVectorStore()
        self.client = httpx.Client(timeout=60.0)
        self.base_url = "https://api.holysheep.ai/v1"
    
    def index_documents(self, documents: List[Dict]):
        """为文档建立索引"""
        texts = [doc["content"] for doc in documents]
        embeddings = self.embedding_client.get_embeddings_batch(texts)
        self.vector_store.add_vectors(embeddings, documents)
        print(f"已索引 {len(documents)} 条文档")
    
    def retrieve(self, query: str, top_k: int = 3) -> List[Dict]:
        """检索相关文档"""
        query_vector = self.embedding_client.get_embedding(query)
        results = self.vector_store.search(query_vector, top_k)
        return [{"content": r[0]["content"], "score": r[1]} for r in results]
    
    def generate(self, query: str, context_docs: List[Dict]) -> str:
        """基于检索结果生成回答"""
        context = "\n\n".join([
            f"[文档 {i+1}] {doc['content']}"
            for i, doc in enumerate(context_docs)
        ])
        
        prompt = f"""基于以下参考资料回答用户问题。如果资料中没有相关信息,请说明"我无法从提供的资料中找到答案"。

参考资料:
{context}

用户问题:{query}

回答:"""
        
        response = self.client.post(
            f"{self.base_url}/chat/completions",
            headers={
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            },
            json={
                "model": "gpt-4.1",
                "messages": [{"role": "user", "content": prompt}],
                "temperature": 0.7,
                "max_tokens": 1000
            }
        )
        response.raise_for_status()
        return response.json()["choices"][0]["message"]["content"]
    
    def query(self, question: str) -> str:
        """完整的问答流程"""
        docs = self.retrieve(question)
        return self.generate(question, docs)

使用示例

if __name__ == "__main__": api_key = "YOUR_HOLYSHEEP_API_KEY" rag = RAGSystem(api_key) # 添加示例文档 documents = [ {"content": "RAG(检索增强生成)是一种结合检索和生成的 AI 技术架构。", "source": "tech_wiki"}, {"content": "向量数据库用于存储和搜索高维向量表示,如 Milvus、Pinecone。", "source": "tech_wiki"}, {"content": "Embeddings 是将文本转换为向量的技术,是 RAG 的核心组件。", "source": "tech_wiki"}, ] rag.index_documents(documents) # 执行查询 answer = rag.query("什么是 RAG 技术?") print(f"回答:{answer}")

上述代码展示了一个完整的 RAG 系统实现。在实际部署时,我建议将向量存储部分替换为专业的向量数据库服务,如 Milvus、Chroma 或 Pinecone,以获得更好的扩展性和性能。以下是使用 Chroma 作为向量数据库的增强版本实现。

生产级 RAG 系统实现

在生产环境中,我们需要考虑更多的因素,包括文档的智能分割、向量索引的优化、以及检索结果的重新排序(Re-ranking)。以下是一个更完整的实现方案。

# 生产级 RAG 系统(使用 Chroma 向量数据库)
import httpx
import chromadb
from chromadb.utils import embedding_functions
from bs4 import BeautifulSoup
import re
from dataclasses import dataclass
from typing import Optional

@dataclass
class Document:
    """文档数据结构"""
    content: str
    metadata: dict

class ProductionRAGSystem:
    """生产级 RAG 系统 - 集成 Chroma 向量数据库"""
    
    def __init__(self, api_key: str, collection_name: str = "knowledge_base"):
        self.api_key = api_key
        self.base_url = "https://api.holysheep.ai/v1"
        self.client = httpx.Client(timeout=120.0)
        
        # 初始化 Chroma 客户端(使用内存模式,生产环境建议持久化)
        self.chroma_client = chromadb.Client()
        
        # 配置 embedding 函数
        self.embedding_fn = embedding_functions.HuggingFaceEmbeddingFunction(
            api_key=api_key,
            model_name="sentence-transformers/all-MiniLM-L6-v2"
        )
        
        # 获取或创建集合
        try:
            self.collection = self.chroma_client.get_collection(
                name=collection_name,
                embedding_function=self.embedding_fn
            )
        except:
            self.collection = self.chroma_client.create_collection(
                name=collection_name,
                embedding_function=self.embedding_fn,
                metadata={"description": "知识库向量集合"}
            )
    
    def chunk_text(self, text: str, chunk_size: int = 500, overlap: int = 50) -> List[str]:
        """智能文本分割 - 保持语义完整性"""
        # 清理文本
        text = re.sub(r'\s+', ' ', text).strip()
        
        # 按句子分割
        sentences = re.split(r'[。!?\n]', text)
        chunks = []
        current_chunk = ""
        
        for sentence in sentences:
            sentence = sentence.strip()
            if not sentence:
                continue
                
            if len(current_chunk) + len(sentence) <= chunk_size:
                current_chunk += sentence + "。"
            else:
                if current_chunk:
                    chunks.append(current_chunk.strip())
                # 保留重叠部分
                current_chunk = current_chunk[-overlap:] + sentence + "。"
        
        if current_chunk.strip():
            chunks.append(current_chunk.strip())
        
        return chunks
    
    def load_documents(self, file_path: str) -> List[Document]:
        """加载并解析文档(支持多种格式)"""
        docs = []
        
        if file_path.endswith('.txt'):
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
                chunks = self.chunk_text(content)
                for i, chunk in enumerate(chunks):
                    docs.append(Document(
                        content=chunk,
                        metadata={"source": file_path, "chunk_id": i}
                    ))
        
        elif file_path.endswith('.html'):
            with open(file_path, 'r', encoding='utf-8') as f:
                soup = BeautifulSoup(f.read(), 'html.parser')
                text = soup.get_text(separator=' ', strip=True)
                chunks = self.chunk_text(text)
                for i, chunk in enumerate(chunks):
                    docs.append(Document(
                        content=chunk,
                        metadata={"source": file_path, "chunk_id": i, "type": "html"}
                    ))
        
        return docs
    
    def index_documents(self, documents: List[Document]):
        """批量索引文档到向量数据库"""
        ids = [f"doc_{doc.metadata.get('chunk_id', i)}" for i, doc in enumerate(documents)]
        contents = [doc.content for doc in documents]
        metadatas = [doc.metadata for doc in documents]
        
        self.collection.add(
            ids=ids,
            documents=contents,
            metadatas=metadatas
        )
        print(f"成功索引 {len(documents)} 个文档块")
    
    def query(self, question: str, top_k: int = 5, model: str = "gpt-4.1") -> dict:
        """执行完整的 RAG 查询"""
        # 第一阶段:向量检索
        results = self.collection.query(
            query_texts=[question],
            n_results=top_k
        )
        
        # 整理检索结果
        retrieved_docs = []
        for i in range(len(results['documents'][0])):
            retrieved_docs.append({
                "content": results['documents'][0][i],
                "metadata": results['metadatas'][0][i],
                "distance": results['distances'][0][i]
            })
        
        # 构建上下文
        context = "\n\n".join([
            f"[来源 {doc['metadata'].get('source', 'unknown')}] {doc['content']}"
            for doc in retrieved_docs
        ])
        
        # 构建提示词
        prompt = f"""你是一个专业的知识库助手。请根据以下参考资料,准确回答用户的问题。

参考资料:
---
{context}
---

用户问题:{question}

请注意:
1. 只根据提供的参考资料回答问题
2. 如果资料中没有相关信息,诚实地说明"我无法从提供的资料中找到答案"
3. 如果资料中的信息不完整,可以基于现有信息给出合理的推测,但需说明这是推测
4. 回答要清晰、有条理,适当引用参考资料"""
        
        # 调用 LLM 生成回答
        try:
            response = self.client.post(
                f"{self.base_url}/chat/completions",
                headers={
                    "Authorization": f"Bearer {self.api_key}",
                    "Content-Type": "application/json"
                },
                json={
                    "model": model,
                    "messages": [
                        {"role": "system", "content": "你是一个有帮助的 AI 助手。"},
                        {"role": "user", "content": prompt}
                    ],
                    "temperature": 0.3,
                    "max_tokens": 1500
                }
            )
            response.raise_for_status()
            answer = response.json()["choices"][0]["message"]["content"]
        except httpx.HTTPStatusError as e:
            answer = f"API 请求失败:{e.response.status_code}"
        
        return {
            "question": question,
            "answer": answer,
            "sources": retrieved_docs
        }

性能监控装饰器

import time from functools import wraps def monitor_performance(func): """监控函数执行性能""" @wraps(func) def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) elapsed = (time.time() - start_time) * 1000 print(f"[性能] {func.__name__} 执行耗时: {elapsed:.2f}ms") return result return wrapper

使用示例

if __name__ == "__main__": API_KEY = "YOUR_HOLYSHEEP_API_KEY" rag = ProductionRAGSystem(API_KEY) # 加载文档并索引 docs = rag.load_documents("knowledge_base.txt") rag.index_documents(docs) # 执行查询 result = rag.query("RAG 系统的核心组件有哪些?") print(f"\n问题:{result['question']}") print(f"回答:{result['answer']}") print(f"\n参考来源:{len(result['sources'])} 条")

系统优化策略

在实际应用中,我总结了以下几种优化 RAG 系统性能的方法。首先是混合检索策略,结合稠密向量检索(Dense Retrieval)和稀疏向量检索(Sparse Retrieval),如 BM25 算法,能够显著提升检索的召回率和准确性。其次是查询改写(Query Rewrite),通过 LLM 对用户问题进行预处理,使其更适合检索。

第三种优化方法是引入重排序模型(Re-ranker),如 Cohere 的 Rerank API 或 BGE-Reranker,在初次检索后对结果进行二次排序,确保最相关的文档排在最前面。第四种优化是缓存机制,对频繁查询的向量和检索结果进行缓存,减少 API 调用次数和响应延迟。

# RAG 系统优化 - 混合检索与查询改写
import httpx
import hashlib
from collections import OrderedDict
from typing import List, Dict, Optional
import json

class LRUCache:
    """LRU 缓存实现"""
    def __init__(self, capacity: int = 100):
        self.cache = OrderedDict()
        self.capacity = capacity
    
    def get(self, key: str) -> Optional[any]:
        if key in self.cache:
            self.cache.move_to_end(key)
            return self.cache[key]
        return None
    
    def put(self, key: str, value: any):
        if key in self.cache:
            self.cache.move_to_end(key)
        self.cache[key] = value
        if len(self.cache) > self.capacity:
            self.cache.popitem(last=False)

class OptimizedRAG:
    """优化版 RAG 系统 - 包含混合检索与查询改写"""
    
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.base_url = "https://api.holysheep.ai/v1"
        self.client = httpx.Client(timeout=120.0)
        
        # 初始化缓存
        self.vector_cache = LRUCache(capacity=200)
        self.search_cache = LRUCache(capacity=100)
    
    def _cache_key(self, text: str) -> str:
        """生成缓存键"""
        return hashlib.md5(text.encode()).hexdigest()
    
    def rewrite_query(self, query: str, style: str = "detailed") -> str:
        """使用 LLM 改写查询,提升检索效果"""
        prompts = {
            "detailed": f"""将以下问题改写为一个更详细、更适合检索的查询。
要求:
1. 展开缩写和简称
2. 添加相关领域的术语
3. 保持原意不变
4. 只输出改写后的查询,不要其他解释

问题:{query}

改写后的查询:""",
            "multiple": f"""为以下问题生成 3 个不同的表述版本,用于多路召回检索。
输出格式:每行一个版本

问题:{query}

版本:"""
        }
        
        response = self.client.post(
            f"{self.base_url}/chat/completions",
            headers={
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            },
            json={
                "model": "gpt-4.1",
                "messages": [{"role": "user", "content": prompts[style]}],
                "temperature": 0.7,
                "max_tokens": 300
            }
        )
        response.raise_for_status()
        result = response.json()["choices"][0]["message"]["content"]
        
        if style == "multiple":
            return [line.strip() for line in result.split('\n') if line.strip()]
        return result
    
    def get_embedding_with_cache(self, text: str) -> List[float]:
        """带缓存的向量获取"""
        cache_key = self._cache_key(text)
        
        cached = self.vector_cache.get(cache_key)
        if cached:
            return cached
        
        response = self.client.post(
            f"{self.base_url}/embeddings",
            headers={
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            },
            json={
                "model": "text-embedding-3-small",
                "input": text
            }
        )
        response.raise_for_status()
        embedding = response.json()["data"][0]["embedding"]
        
        self.vector_cache.put(cache_key, embedding)
        return embedding
    
    def hybrid_search(
        self,
        query: str,
        vector_store,
        bm25_index,
        top_k: int = 10,
        alpha: float = 0.7
    ) -> List[Dict]:
        """混合搜索 - 结合向量相似度和 BM25 分数"""
        # 获取向量
        query_vector = self.get_embedding_with_cache(query)
        
        # 向量检索
        vector_results = vector_store.search(query_vector, top_k * 2)
        
        # BM25 检索
        bm25_results = bm25_index.search(query, top_k * 2)
        
        # 融合分数
        combined_scores = {}
        
        # 归一化向量分数
        max_vector_score = max(r[1] for r in vector_results) if vector_results else 1
        for doc, score in vector_results:
            doc_id = doc.get('id', doc.get('content', ''))
            combined_scores[doc_id] = alpha * (score / max_vector_score)
        
        # 归一化 BM25 分数
        max_bm25_score = max(r[1] for r in bm25_results) if bm25_results else 1
        for doc, score in bm25_results:
            doc_id = doc.get('id', doc.get('content', ''))
            if doc_id in combined_scores:
                combined_scores[doc_id] += (1 - alpha) * (score / max_bm25_score)
            else:
                combined_scores[doc_id] = (1 - alpha) * (score / max_bm25_score)
        
        # 排序返回
        sorted_results = sorted(
            combined_scores.items(),
            key=lambda x: x[1],
            reverse=True
        )[:top_k]
        
        # 重建结果列表
        doc_map = {r[0].get('id', r[0].get('content', '')): r[0] for r in vector_results}
        doc_map.update({r[0].get('id', r[0].get('content', '')): r[0] for r in bm25_results})
        
        return [
            {"document": doc_map[doc_id], "score": score}
            for doc_id, score in sorted_results
            if doc_id in doc_map
        ]
    
    def rerank_results(
        self,
        query: str,
        documents: List[Dict],
        top_n: int = 5
    ) -> List[Dict]:
        """使用交叉编码器对结果进行重排序"""
        # 构建重排序提示
        doc_contents = "\n---\n".join([
            f"文档 {i+1}:\n{doc['content'] if isinstance(doc, dict) else doc}"
            for i, doc in enumerate(documents)
        ])
        
        rerank_prompt = f"""请根据问题评估每个文档的相关性,给出 1-10 的评分。

问题:{query}

{doc_contents}

输出格式(每行一个评分):
文档 1: [分数]
文档 2: [分数]
..."""
        
        try:
            response = self.client.post(
                f"{self.base_url}/chat/completions",
                headers={
                    "Authorization": f"Bearer {self.api_key}",
                    "Content-Type": "application/json"
                },
                json={
                    "model": "gpt-4.1",
                    "messages": [{"role": "user", "content": rerank_prompt}],
                    "temperature": 0,
                    "max_tokens": 200
                }
            )
            response.raise_for_status()
            scores_text = response.json()["choices"][0]["message"]["content"]
            
            # 解析评分
            scores = []
            for line in scores_text.split('\n'):
                if ':' in line:
                    score_str = line.split(':')[-1].strip()
                    try:
                        scores.append(float(score_str))
                    except ValueError:
                        scores.append(5.0)  # 默认分数
            
            # 更新文档分数并排序
            for i, doc in enumerate(documents):
                if i < len(scores):
                    doc['rerank_score'] = scores[i]
                else:
                    doc['rerank_score'] = 5.0
            
            return sorted(documents, key=lambda x: x.get('rerank_score', 0), reverse=True)[:top_n]
        
        except Exception as e:
            print(f"重排序失败:{e}")
            return documents[:top_n]

BM25 实现(简化版)

class SimpleBM25: """简化的 BM25 搜索引擎""" def __init__(self, k1: float = 1.5, b: float = 0.75): self.k1 = k1 self.b = b self.documents = [] self.avgdl = 0 self.doc_freqs = {} self.idf = {} self.doc_lengths = [] def index(self, documents: List[Dict]): """构建 BM25 索引""" self.documents = documents N = len(documents) # 计算文档长度 self.doc_lengths = [len(doc.get('content', '').split()) for doc in documents] self.avgdl = sum(self.doc_lengths) / N if N > 0 else 0 # 统计词频和文档频率 for doc in documents: words = set(doc.get('content', '').lower().split()) for word in words: self.doc_freqs[word] = self.doc_freqs.get(word, 0) + 1 # 计算 IDF for word, df in self.doc_freqs.items(): self.idf[word] = (N - df + 0.5) / (df + 0.5) def search(self, query: str, top_k: int = 10) -> List[tuple]: """搜索相关文档""" query_words = query.lower().split() scores = [] for i, doc in enumerate(self.documents): score = 0 doc_words = doc.get('content', '').lower().split() word_freq = {} for word in doc_words: word_freq[word] = word_freq.get(word, 0) + 1 dl = self.doc_lengths[i] for word in query_words: if word in word_freq: tf = word_freq[word] idf = self.idf.get(word, 0) # BM25 公式 numerator = tf * (self.k1 + 1) denominator = tf + self.k1 * (1 - self.b + self.b * dl / self.avgdl) score += idf * numerator / denominator scores.append((doc, score)) return sorted(scores, key=lambda x: x[1], reverse=True)[:top_k]

使用示例

if __name__ == "__main__": API_KEY = "YOUR_HOLYSHEEP_API_KEY" rag = OptimizedRAG(API_KEY) # 查询改写示例 rewritten = rag.rewrite_query("RAG 是什么", style="multiple") print("查询改写结果:") for version in rewritten: print(f" - {version}") # 构建 BM25 索引 bm25 = SimpleBM25() bm25.index([ {"id": "1", "content": "RAG 是检索增强生成技术"}, {"id": "2", "content": "向量数据库用于存储向量"}, {"id": "3", "content": "Embeddings 将文本转为向量"}, ])

常见错误与解决方案

在开发 RAG 系统时,开发者经常会遇到一些典型问题。以下是我总结的三个最常见的错误及其解决方案。

错误一:API 密钥未正确配置

# ❌ 错误示例:API 密钥硬编码在代码中
client = httpx.Client()
response = client.post(
    "https://api.holysheep.ai/v1/embeddings",
    headers={
        "Authorization": "Bearer YOUR_HOLYSHEEP_API_KEY",  # 直接暴露密钥
        "Content-Type": "application/json"
    },
    json={"model": "text-embedding-3-small", "input": "text"}
)

✅ 正确示例:从环境变量读取密钥

import os from dotenv import load_dotenv load_dotenv() # 加载 .env 文件 API_KEY = os.getenv("HOLYSHEEP_API_KEY") if not API_KEY: raise ValueError("未设置 HOLYSHEEP_API_KEY 环境变量") client = httpx.Client() response = client.post( "https://api.holysheep.ai/v1/embeddings", headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" }, json={"model": "text-embedding-3-small", "input": "text"} )

.env 文件内容:

HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY

错误二:向量维度不匹配

# ❌ 错误示例:未指定 embedding 模型,导致维度不一致
class VectorStore:
    def __init__(self):
        self.vectors = []
    
    def add(self, vector, metadata):
        self.vectors.append({"vector": vector, "metadata": metadata})
    
    def search(self, query_vector, top_k=5):
        # 假设所有向量都是 1536 维,但实际可能不同
        return sorted(
            self.vectors,
            key=lambda x: self._cosine_similarity(x["vector"], query_vector),
            reverse=True
        )[:top_k]

✅ 正确示例:使用固定的 embedding 模型并验证维度

import httpx class VectorStore: def __init__(self, api_key: str, model: str = "text-embedding-3-small"): self.api_key = api_key self.model = model self.expected_dimensions = self._get_embedding_dimensions() self.vectors = [] def _get_embedding_dimensions(self) -> int: """获取模型的向量维度""" client = httpx.Client() response = client.post( "https://api.holysheep.ai/v1/embeddings", headers={ "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json" }, json={ "model": self.model, "input": "dimension test" } ) return len(response.json()["data"][0]["embedding"]) def add(self, vector, metadata): """添加向量,带维度验证""" if len(vector) != self.expected_dimensions: raise ValueError( f"向量维度不匹配:期望 {self.expected_dimensions} 维," f"实际 {len(vector)} 维" ) self.vectors.append({"vector": vector, "metadata": metadata}) def search(self, query_vector, top_k=5): """搜索,验证查询向量维度""" if len(query_vector) != self.expected_dimensions: raise ValueError( f"查询向量维度不匹配:期望 {self.expected_dimensions} 维," f"实际 {len(query_vector)} 维" ) scored = [ (item, self._cosine_similarity(item["vector"], query_vector)) for item in self.vectors ] return sorted(scored, key=lambda x: x[1], reverse=True)[:top_k]

使用示例

API_KEY = "YOUR_HOLYSHEEP_API_KEY" store = VectorStore(API_KEY) print(f"Embedding 模型维度:{store.expected_dimensions}")

错误三:批量处理时超出速率限制

# ❌ 错误示例:无限制批量请求,导致限流
import httpx

def batch_embed(texts, api_key):
    client = httpx.Client()
    results = []
    for text in texts:  # 10000 条文本
        response = client.post(
            "https://api.holysheep.ai/v1/embeddings",
            headers={
                "Authorization": f"Bearer {api_key}",
                "Content-Type": "application/json"
            },
            json