上一篇 下一篇 分享链接 返回 返回顶部

AI 搜索变快实战:从检索、重排到部署的完整优化命令包

发布人:慈云数据-客服中心 发布时间:1小时前 阅读量:2

AI搜索 性能优化教程|附完整命令

在企业知识库、智能客服、RAG 应用、站内搜索、代码搜索等场景中,“AI 搜索”已经逐渐从传统关键词检索,升级为“关键词检索 + 向量检索 + 重排序 + 大模型生成”的混合架构。

但是,很多团队在上线 AI 搜索系统后会遇到类似问题:

  • 查询速度慢,用户等待 5 秒甚至 10 秒以上;
  • 向量检索召回不稳定,结果相关性差;
  • 大模型回答延迟高,成本不可控;
  • 文档量一增长,CPU、内存、磁盘压力明显上升;
  • 并发一高,接口超时、排队、甚至服务崩溃;
  • 明明用了向量数据库,却没有达到理想性能。

本文将围绕 AI 搜索的典型架构,系统讲解如何进行性能优化,并提供一套可直接参考的完整命令,帮助你从系统层、服务层、索引层、检索层、模型层和工程层全面提升 AI 搜索性能。


一、AI 搜索的典型架构

一个常见的 AI 搜索系统通常包含以下几个模块:

用户查询
  ↓
查询预处理
  ↓
Embedding 向量化
  ↓
关键词检索 / 向量检索 / 混合检索
  ↓
结果召回
  ↓
Rerank 重排序
  ↓
上下文拼接
  ↓
大模型生成答案
  ↓
返回结果

如果拆得更细,可以分为:

  1. 数据处理层
    包括文档清洗、切分、去重、元数据提取。

  2. 向量生成层
    使用 Embedding 模型将文本转成向量。

  3. 索引存储层
    例如 Milvus、Qdrant、Weaviate、Elasticsearch、OpenSearch、pgvector 等。

  4. 检索层
    包括 BM25、ANN 向量检索、Hybrid Search、过滤查询等。

  5. 重排序层
    使用 Rerank 模型对候选结果重新排序。

  6. 生成层
    使用大语言模型根据检索内容生成最终答案。

  7. 缓存与网关层
    包括 Redis 缓存、API 限流、负载均衡、异步任务队列等。

性能优化并不是只优化某一个组件,而是要从整个链路入手。


二、先定位瓶颈:不要盲目优化

在优化之前,必须先知道慢在哪里。AI 搜索的延迟通常由以下几部分组成:

总延迟 = 查询预处理耗时
       + Embedding 耗时
       + 检索耗时
       + Rerank 耗时
       + LLM 生成耗时
       + 网络传输耗时

你可以在接口中打印每个阶段的耗时,例如:

import time

start = time.time()

t1 = time.time()
# query preprocess
print("preprocess:", time.time() - t1)

t2 = time.time()
# embedding
print("embedding:", time.time() - t2)

t3 = time.time()
# vector search
print("search:", time.time() - t3)

t4 = time.time()
# rerank
print("rerank:", time.time() - t4)

t5 = time.time()
# llm generate
print("llm:", time.time() - t5)

print("total:", time.time() - start)

也可以在 Linux 层查看资源占用:

top
htop
free -h
df -h
iostat -x 1

如果没有安装 iostat,可以执行:

sudo apt update
sudo apt install -y sysstat

查看网络连接情况:

ss -tunlp

查看某个进程资源占用:

ps aux | grep python

查看端口监听:

sudo lsof -i:8000

压测接口:

ab -n 1000 -c 50 http://127.0.0.1:8000/search?q=test

如果没有安装 Apache Bench:

sudo apt install -y apache2-utils

也可以使用 wrk

sudo apt install -y wrk
wrk -t4 -c100 -d30s "http://127.0.0.1:8000/search?q=test"

定位瓶颈之后,再进行针对性优化,才不会浪费时间。


三、系统层优化:先把服务器基础打牢

AI 搜索通常对 CPU、内存、磁盘 IO、网络都有要求。如果底层系统配置不合理,再好的代码也会被拖慢。

1. 更新系统与基础工具

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget git vim htop net-tools unzip build-essential

2. 调整文件句柄限制

向量数据库、搜索引擎和高并发 API 服务都可能打开大量文件和连接。默认文件句柄数量较低,建议调大。

查看当前限制:

ulimit -n

临时调整:

ulimit -n 65535

永久调整:

sudo vim /etc/security/limits.conf

添加:

* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535

如果是 systemd 服务,还需要在服务文件中加入:

LimitNOFILE=65535

重载 systemd:

sudo systemctl daemon-reload

3. 优化内核参数

编辑配置文件:

sudo vim /etc/sysctl.conf

添加:

net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
vm.max_map_count = 262144
fs.file-max = 2097152

使配置生效:

sudo sysctl -p

其中 vm.max_map_count 对 Elasticsearch、OpenSearch 等服务尤其重要。


四、Docker 部署优化

很多 AI 搜索系统会使用 Docker 部署,例如 FastAPI、Milvus、Qdrant、Redis、Elasticsearch 等。

安装 Docker:

curl -fsSL https://get.docker.com | bash

启动 Docker:

sudo systemctl enable docker
sudo systemctl start docker

将当前用户加入 Docker 用户组:

sudo usermod -aG docker $USER

重新登录后验证:

docker version

安装 Docker Compose:

sudo apt install -y docker-compose-plugin

查看版本:

docker compose version

清理无用镜像和容器:

docker system df
docker system prune -a

如果线上环境存储敏感,请谨慎执行 docker system prune -a,避免误删未使用镜像。

Docker 容器资源限制示例

docker-compose.yml 中配置资源限制:

services:
  api:
    image: your-ai-search-api:latest
    restart: always
    ports:
      - "8000:8000"
    deploy:
      resources:
        limits:
          cpus: "4"
          memory: 8G
        reservations:
          cpus: "2"
          memory: 4G

如果不是 Docker Swarm,部分 deploy 配置不会生效,可以使用:

docker run -d \
  --name ai-search-api \
  --cpus="4" \
  --memory="8g" \
  -p 8000:8000 \
  your-ai-search-api:latest

五、Embedding 优化:减少重复计算

在 AI 搜索中,Embedding 是一个非常重要的耗时环节。常见优化方法包括:

  1. 查询向量缓存;
  2. 文档向量离线生成;
  3. 批量生成 Embedding;
  4. 使用更轻量的 Embedding 模型;
  5. 使用 GPU 或推理加速;
  6. 对短文本进行去重。

1. 使用 Redis 缓存查询向量

安装 Redis:

sudo apt install -y redis-server

启动 Redis:

sudo systemctl enable redis-server
sudo systemctl start redis-server

测试:

redis-cli ping

返回:

PONG

Python 安装依赖:

pip install redis

示例代码:

import redis
import hashlib
import json

r = redis.Redis(host="localhost", port=6379, db=0)

def cache_key(text: str):
    return "embedding:" + hashlib.md5(text.encode("utf-8")).hexdigest()

def get_embedding_with_cache(text, embed_func):
    key = cache_key(text)
    cached = r.get(key)
    if cached:
        return json.loads(cached)

    vector = embed_func(text)
    r.setex(key, 3600 * 24, json.dumps(vector))
    return vector

这样可以避免相同查询重复调用 Embedding 模型。

2. 批量生成文档向量

错误做法是每个 chunk 单独调用一次模型。更好的方式是批量处理。

def batch_embed(texts, model, batch_size=64):
    vectors = []
    for i in range(0, len(texts), batch_size):
        batch = texts[i:i + batch_size]
        batch_vectors = model.encode(batch, normalize_embeddings=True)
        vectors.extend(batch_vectors)
    return vectors

如果使用 sentence-transformers

pip install sentence-transformers

示例:

from sentence_transformers import SentenceTransformer

model = SentenceTransformer("BAAI/bge-small-zh-v1.5")

texts = ["人工智能是什么", "向量数据库如何优化", "RAG 系统如何提升速度"]
vectors = model.encode(
    texts,
    batch_size=64,
    normalize_embeddings=True,
    show_progress_bar=True
)

print(vectors.shape)

六、向量数据库优化:索引参数决定性能

不同向量数据库参数不同,但核心思想类似:在召回率和速度之间做平衡。

下面以 Qdrant 为例。

1. 使用 Docker 启动 Qdrant

docker run -d \
  --name qdrant \
  -p 6333:6333 \
  -p 6334:6334 \
  -v $(pwd)/qdrant_storage:/qdrant/storage \
  qdrant/qdrant

查看状态:

docker ps

测试接口:

curl http://localhost:6333

2. 创建集合

假设向量维度为 512:

curl -X PUT "http://localhost:6333/collections/docs" \
  -H "Content-Type: application/json" \
  -d '{
    "vectors": {
      "size": 512,
      "distance": "Cosine"
    },
    "optimizers_config": {
      "default_segment_number": 4
    },
    "hnsw_config": {
      "m": 32,
      "ef_construct": 200,
      "full_scan_threshold": 10000
    }
  }'

参数说明:

  • size:向量维度,必须和 Embedding 模型输出一致;
  • distance:相似度计算方式,常见为 Cosine、Dot、Euclid;
  • m:HNSW 图中每个节点的连接数,越大召回率越高,但内存占用越高;
  • ef_construct:构建索引时的搜索宽度,越大索引质量越好,但构建更慢;
  • full_scan_threshold:低于该数量时可能使用全量扫描。

3. 插入数据

curl -X PUT "http://localhost:6333/collections/docs/points?wait=true" \
  -H "Content-Type: application/json" \
  -d '{
    "points": [
      {
        "id": 1,
        "vector": [0.01, 0.02, 0.03, 0.04],
        "payload": {
          "title": "AI 搜索优化",
          "content": "本文介绍 AI 搜索系统性能优化方法"
        }
      }
    ]
  }'

注意:上面的 vector 只是示例。实际维度必须和集合设置一致,否则会报错。

4. 查询时调整 ef 参数

curl -X POST "http://localhost:6333/collections/docs/points/search" \
  -H "Content-Type: application/json" \
  -d '{
    "vector": [0.01, 0.02, 0.03, 0.04],
    "limit": 10,
    "params": {
      "hnsw_ef": 128,
      "exact": false
    },
    "with_payload": true
  }'

优化建议:

  • 如果追求速度,可以降低 hnsw_ef,例如 64;
  • 如果追求召回率,可以提高到 128、256;
  • limit 不要设置过大,通常召回 20 到 100 条再进入 Rerank;
  • 对有明确业务条件的数据,应先使用过滤条件减少候选集。

七、关键词检索优化:BM25 仍然很重要

AI 搜索不等于只做向量检索。对于产品编号、错误码、函数名、人名、专有名词等场景,BM25 往往比向量检索更准确。

可以使用 Elasticsearch 或 OpenSearch。

1. 启动 Elasticsearch

docker network create search-net
docker run -d \
  --name elasticsearch \
  --network search-net \
  -p 9200:9200 \
  -e "discovery.type=single-node" \
  -e "xpack.security.enabled=false" \
  -e "ES_JAVA_OPTS=-Xms2g -Xmx2g" \
  elasticsearch:8.12.2

检查状态:

curl http://localhost:9200

2. 创建索引

curl -X PUT "http://localhost:9200/docs" \
  -H "Content-Type: application/json" \
  -d '{
    "settings": {
      "number_of_shards": 1,
      "number_of_replicas": 0,
      "refresh_interval": "30s"
    },
    "mappings": {
      "properties": {
        "title": {
          "type": "text"
        },
        "content": {
          "type": "text"
        },
        "doc_id": {
          "type": "keyword"
        },
        "created_at": {
          "type": "date"
        }
      }
    }
  }'

优化建议:

  • 单机小数据量不要盲目增加 shard;
  • 批量写入时调大 refresh_interval
  • 不需要聚合的字段不要设置过多 keyword;
  • 对经常过滤的字段使用 keywordintegerdate 等结构化类型。

3. 批量写入

创建 bulk.json

{ "index": { "_index": "docs", "_id": "1" } }
{ "title": "AI 搜索优化", "content": "本文介绍 AI 搜索系统的性能优化方案", "doc_id": "doc_1", "created_at": "2025-01-01" }
{ "index": { "_index": "docs", "_id": "2" } }
{ "title": "RAG 系统实践", "content": "RAG 系统需要结合向量检索和大模型生成", "doc_id": "doc_2", "created_at": "2025-01-02" }

执行:

curl -X POST "http://localhost:9200/_bulk" \
  -H "Content-Type: application/x-ndjson" \
  --data-binary @bulk.json

手动刷新:

curl -X POST "http://localhost:9200/docs/_refresh"

4. BM25 查询

curl -X GET "http://localhost:9200/docs/_search" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "multi_match": {
        "query": "AI 搜索 性能优化",
        "fields": ["title^2", "content"]
      }
    },
    "size": 10
  }'

八、混合检索优化:向量 + 关键词

单纯向量检索可能会忽略精确词;单纯关键词检索又无法理解语义。因此生产环境更推荐混合检索。

常见策略:

最终候选 = BM25 TopK + Vector TopK
去重
归一化打分
加权融合
Rerank

一个简单融合公式:

score = alpha * vector_score + beta * bm25_score

例如:

score = 0.6 * vector_score + 0.4 * bm25_score

如果用户查询中包含产品型号、错误码、订单号、精确术语,可以适当提高 BM25 权重。

示例伪代码:

def hybrid_search(query):
    vector_results = vector_search(query, top_k=50)
    bm25_results = bm25_search(query, top_k=50)

    merged = {}

    for item in vector_results:
        doc_id = item["doc_id"]
        merged[doc_id] = {
            "doc": item,
            "vector_score": item["score"],
            "bm25_score": 0
        }

    for item in bm25_results:
        doc_id = item["doc_id"]
        if doc_id not in merged:
            merged[doc_id] = {
                "doc": item,
                "vector_score": 0,
                "bm25_score": item["score"]
            }
        else:
            merged[doc_id]["bm25_score"] = item["score"]

    results = []
    for doc_id, item in merged.items():
        score = 0.6 * item["vector_score"] + 0.4 * item["bm25_score"]
        item["score"] = score
        results.append(item)

    results.sort(key=lambda x: x["score"], reverse=True)
    return results[:20]

性能建议:

  • 向量召回 TopK 不宜过大,通常 30 到 100;
  • BM25 召回 TopK 可以设置为 20 到 50;
  • Rerank 前必须去重;
  • 对同一个文档的多个 chunk,可以限制最多进入 2 到 3 个;
  • 如果用户问题很短,可以提高关键词权重;
  • 如果用户问题很长,可以提高向量权重。

九、Rerank 优化:不要对太多候选重排序

Rerank 模型可以显著提升搜索相关性,但它通常比向量检索更耗时。很多系统慢,就是因为把几百条候选全部送去 Rerank。

合理做法:

向量 / BM25 召回 50 条
↓
去重与过滤后保留 20 条
↓
Rerank 20 条
↓
取前 5 条给大模型

如果使用本地 Rerank 模型,可以安装:

pip install FlagEmbedding

示例代码:

from FlagEmbedding import FlagReranker

reranker = FlagReranker(
    "BAAI/bge-reranker-base",
    use_fp16=True
)

pairs = [
    ["AI 搜索如何优化性能?", "AI 搜索性能优化包括缓存、索引、批处理和模型加速。"],
    ["AI 搜索如何优化性能?", "今天天气很好,适合出门。"]
]

scores = reranker.compute_score(pairs)
print(scores)

优化建议:

  • Rerank 数量控制在 10 到 30;
  • 使用 base 或更小模型,而不是盲目使用大模型;
  • 开启 FP16;
  • 对高频查询进行缓存;
  • 如果延迟要求极高,可以在低价值请求中跳过 Rerank;
  • 对候选文本进行截断,避免输入过长。

十、大模型生成优化:降低最终回答延迟

在 RAG 系统中,LLM 生成通常是最慢的一环。优化方向主要有:

  1. 减少上下文长度;
  2. 控制输出长度;
  3. 使用流式输出;
  4. 使用更小模型;
  5. 缓存高频问答;
  6. 对不需要生成的搜索请求直接返回结果;
  7. 设置超时和降级策略。

1. 控制上下文数量

不要把几十个 chunk 都塞给大模型。一般取前 3 到 8 个即可。

top_contexts = rerank_results[:5]

2. 控制 Prompt 长度

示例 Prompt:

你是企业知识库助手。请只根据给定资料回答问题。
如果资料中没有答案,请回答“根据现有资料无法确定”。

问题:
{question}

资料:
{context}

请用简洁、准确的中文回答。

3. 控制输出长度

如果调用 OpenAI 兼容接口,可以设置:

payload = {
    "model": "your-model",
    "messages": [
        {"role": "user", "content": prompt}
    ],
    "temperature": 0.2,
    "max_tokens": 512,
    "stream": True
}

max_tokens 不要无脑设置为 4096。对于搜索问答,很多场景 300 到 800 tokens 已经足够。

4. 使用 Nginx 支持流式输出

安装 Nginx:

sudo apt install -y nginx

配置:

sudo vim /etc/nginx/sites-available/ai-search

写入:

server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Connection "";

        proxy_buffering off;
        proxy_cache off;
        chunked_transfer_encoding on;

        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }
}

启用配置:

sudo ln -s /etc/nginx/sites-available/ai-search /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

十一、API 服务优化:FastAPI + Gunicorn

如果你的 AI 搜索服务使用 FastAPI,不建议直接用开发模式运行。

安装依赖:

pip install fastapi uvicorn gunicorn

启动命令:

gunicorn main:app \
  -k uvicorn.workers.UvicornWorker \
  -w 4 \
  -b 0.0.0.0:8000 \
  --timeout 120 \
  --keep-alive 30

参数说明:

  • -w 4:worker 数量,通常可以设置为 CPU 核数的 1 到 2 倍;
  • --timeout 120:避免大模型请求被过早杀掉;
  • --keep-alive 30:保持连接,减少频繁建立连接的开销。

如果服务器是 8 核,可以尝试:

gunicorn main:app \
  -k uvicorn.workers.UvicornWorker \
  -w 8 \
  -b 0.0.0.0:8000 \
  --timeout 120 \
  --keep-alive 30

后台运行可以使用 systemd。

创建服务文件:

sudo vim /etc/systemd/system/ai-search.service

写入:

[Unit]
Description=AI Search API Service
After=network.target

[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/ai-search
Environment="PATH=/home/ubuntu/ai-search/venv/bin"
ExecStart=/home/ubuntu/ai-search/venv/bin/gunicorn main:app -k uvicorn.workers.UvicornWorker -w 4 -b 0.0.0.0:8000 --timeout 120 --keep-alive 30
Restart=always
RestartSec=5
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target

启动服务:

sudo systemctl daemon-reload
sudo systemctl enable ai-search
sudo systemctl start ai-search

查看状态:

sudo systemctl status ai-search

查看日志:

journalctl -u ai-search -f

十二、缓存策略:让高频请求更快

缓存是 AI 搜索性能优化中性价比最高的手段之一。

可以缓存:

  1. 查询 Embedding;
  2. 搜索结果;
  3. Rerank 结果;
  4. LLM 最终回答;
  5. 热门文档内容;
  6. 用户权限信息。

Redis 缓存搜索结果示例:

import hashlib
import json
import redis

r = redis.Redis(host="localhost", port=6379, db=1)

def make_search_key(query, user_id=None):
    raw = f"{user_id}:{query}"
    return "search:" + hashlib.md5(raw.encode("utf-8")).hexdigest()

def search_with_cache(query, user_id=None):
    key = make_search_key(query, user_id)
    cached = r.get(key)

    if cached:
        return json.loads(cached)

    result = real_search(query)

    r.setex(key, 300, json.dumps(result, ensure_ascii=False))
    return result

缓存时间建议:

  • Embedding 缓存:1 天到 7 天;
  • 搜索结果缓存:1 分钟到 10 分钟;
  • 最终问答缓存:5 分钟到 1 小时;
  • 权限缓存:几分钟,避免权限变更后数据泄漏。

注意:如果搜索结果和用户权限相关,缓存 key 必须包含用户身份或权限版本号。


十三、文档切分优化:Chunk 太大太小都不好

很多 AI 搜索效果差,不是模型问题,而是文档切分不合理。

1. Chunk 太大

问题:

  • Embedding 表达不够精确;
  • Rerank 和 LLM 输入变长;
  • 检索结果噪声大;
  • 成本增加。

2. Chunk 太小

问题:

  • 语义不完整;
  • 召回结果缺乏上下文;
  • chunk 数量暴增,索引变大;
  • 检索和存储成本增加。

3. 推荐参数

中文知识库可以参考:

chunk_size: 300 到 800 中文字
chunk_overlap: 50 到 150 中文字

技术文档可以稍大:

chunk_size: 500 到 1200 中文字
chunk_overlap: 100 到 200 中文字

示例切分代码:

def split_text(text, chunk_size=600, overlap=100):
    chunks = []
    start = 0

    while start < len(text):
        end = start + chunk_size
        chunk = text[start:end]
        chunks.append(chunk)
        start = end - overlap

        if start < 0:
            start = 0

        if start >= len(text):
            break

    return chunks

更好的方式是按标题、段落、句子进行结构化切分,而不是简单按长度硬切。


十四、索引写入优化:批量、异步、延迟刷新

大量文档入库时,性能瓶颈常常出现在写入阶段。

优化原则:

  1. 批量写入;
  2. 异步队列;
  3. 文档先清洗再入库;
  4. 避免重复向量化;
  5. 写入期间降低刷新频率;
  6. 建索引和查询分离。

Qdrant 批量写入示例

from qdrant_client import QdrantClient
from qdrant_client.models import PointStruct

client = QdrantClient(host="localhost", port=6333)

points = []
for i, item in enumerate(data):
    points.append(
        PointStruct(
            id=i,
            vector=item["vector"],
            payload={
                "title": item["title"],
                "content": item["content"],
                "doc_id": item["doc_id"]
            }
        )
    )

client.upsert(
    collection_name="docs",
    points=points,
    wait=True
)

安装客户端:

pip install qdrant-client

如果数据量很大,可以分批:

def chunks(lst, size):
    for i in range(0, len(lst), size):
        yield lst[i:i + size]

for batch in chunks(points, 500):
    client.upsert(
        collection_name="docs",
        points=batch,
        wait=True
    )

十五、监控与日志:没有监控就没有优化

生产环境必须监控以下指标:

  • API 请求 QPS;
  • P50、P90、P99 延迟;
  • Embedding 耗时;
  • 向量检索耗时;
  • BM25 检索耗时;
  • Rerank 耗时;
  • LLM 首 token 延迟;
  • LLM 总生成耗时;
  • CPU、内存、磁盘 IO;
  • Redis 命中率;
  • 错误率和超时率。

查看服务日志:

journalctl -u ai-search -f

查看最近 100 行:

journalctl -u ai-search -n 100

查看 Docker 日志:

docker logs -f qdrant

查看 Elasticsearch 日志:

docker logs -f elasticsearch

查看 Redis 状态:

redis-cli info

查看 Redis 内存:

redis-cli info memory

查看 Redis key 数量:

redis-cli dbsize

十六、完整优化命令清单

下面整理一份从服务器初始化到服务部署的参考命令。

1. 系统初始化

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget git vim htop net-tools unzip build-essential sysstat apache2-utils wrk nginx redis-server

2. Docker 安装

curl -fsSL https://get.docker.com | bash
sudo systemctl enable docker
sudo systemctl start docker
sudo usermod -aG docker $USER
sudo apt install -y docker-compose-plugin

3. 系统参数优化

cat <

4. 启动 Redis

sudo systemctl enable redis-server
sudo systemctl start redis-server
redis-cli ping

5. 启动 Qdrant

docker run -d \
  --name qdrant \
  -p 6333:6333 \
  -p 6334:6334 \
  -v $(pwd)/qdrant_storage:/qdrant/storage \
  qdrant/qdrant

6. 启动 Elasticsearch

docker network create search-net

docker run -d \
  --name elasticsearch \
  --network search-net \
  -p 9200:9200 \
  -e "discovery.type=single-node" \
  -e "xpack.security.enabled=false" \
  -e "ES_JAVA_OPTS=-Xms2g -Xmx2g" \
  elasticsearch:8.12.2

7. Python 环境

python3 -m venv venv
source venv/bin/activate

pip install --upgrade pip
pip install fastapi uvicorn gunicorn redis qdrant-client sentence-transformers FlagEmbedding

8. 启动 API

gunicorn main:app \
  -k uvicorn.workers.UvicornWorker \
  -w 4 \
  -b 0.0.0.0:8000 \
  --timeout 120 \
  --keep-alive 30

9. 压测

ab -n 1000 -c 50 "http://127.0.0.1:8000/search?q=AI搜索性能优化"
wrk -t4 -c100 -d30s "http://127.0.0.1:8000/search?q=AI搜索性能优化"

十七、推荐优化顺序

如果你不知道从哪里开始,可以按照下面顺序执行:

  1. 先打点统计每个阶段耗时
    不要猜瓶颈。

  2. 先做缓存
    Embedding 缓存、搜索结果缓存、问答缓存通常收益明显。

  3. 优化 TopK 和 Rerank 数量
    很多系统慢是因为召回太多、重排太多。

  4. 优化文档切分
    Chunk 合理后,召回质量和速度都会提升。

  5. 调整向量索引参数
    例如 HNSW 的 mef_constructhnsw_ef

  6. 使用混合检索
    向量检索解决语义,BM25 解决精确匹配。

  7. 控制 LLM 上下文和输出长度
    避免把 AI 搜索变成“长上下文暴力生成”。

  8. 优化 API 部署方式
    使用 Gunicorn、多 Worker、Nginx、连接复用。

  9. 持续压测和监控
    关注 P95、P99,而不只是平均响应时间。


十八、总结

AI 搜索性能优化不是单点优化,而是一套系统工程。一个高性能的 AI 搜索系统,通常具备以下特征:

  • 文档切分合理;
  • Embedding 支持批量处理和缓存;
  • 向量索引参数经过调优;
  • 同时使用向量检索和 BM25 检索;
  • Rerank 候选数量可控;
  • LLM 上下文长度和输出长度可控;
  • API 服务支持并发和超时控制;
  • Redis、Nginx、Docker、系统参数配置合理;
  • 有完善的日志、压测和监控体系。

实际落地时,不建议一开始就追求复杂架构。你可以先用 Redis + Qdrant + FastAPI + Nginx 搭建基础版本,再逐步加入 Elasticsearch、Rerank、异步队列、监控系统和多节点部署。

最终目标不是“用最复杂的技术”,而是用合适的架构,在可接受的成本下,提供稳定、快速、准确的 AI 搜索体验。

目录结构
全文