AI 工具开发实战(9):开发一个 AI 搜索引擎聚合器——同时查多个 AI 搜索,对比结果

日常查技术问题要开多个 AI 搜索:Perplexity 查海外、秘塔查中文、DeepSeek 验证一下。这个工具把多个 AI 搜索聚合到一个页面上,一次提问、并行调用、对比展示。

核心代码

# metasearch.py
import asyncio
import aiohttp
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, StreamingResponse
import json
import os

app = FastAPI()
API_KEY = os.getenv("DEEPSEEK_API_KEY", "")

SEARCH_ENGINES = {
    "deepseek": {
        "name": "DeepSeek",
        "url": "https://api.deepseek.com/v1/chat/completions",
        "headers": {"Authorization": f"Bearer {API_KEY}"},
        "body_template": lambda q: {
            "model": "deepseek-chat",
            "messages": [{"role": "user", "content": q}],
            "stream": True,
        },
    },
}

HTML = """
AI 聚合搜索

*{margin:0;padding:0;box-sizing:border-box}
body{font-family:sans-serif;max-width:1200px;margin:0 auto;padding:20px;background:#f8fafc}
h1{text-align:center;margin-bottom:20px;color:#1e293b}
.search-bar{display:flex;gap:8px;margin-bottom:24px}
input{flex:1;padding:12px 16px;border:2px solid #e2e8f0;border-radius:12px;font-size:16px;outline:none}
input:focus{border-color:#3b82f6}
button{padding:12px 24px;background:#3b82f6;color:#fff;border:none;border-radius:12px;font-size:16px;cursor:pointer}
button:hover{background:#2563eb}
.results{display:grid;grid-template-columns:repeat(auto-fit,minmax(350px,1fr));gap:16px}
.card{background:#fff;border:1px solid #e2e8f0;border-radius:12px;padding:16px}
.card h3{font-size:14px;color:#64748b;margin-bottom:8px;padding-bottom:8px;border-bottom:1px solid #f1f5f9}
.card .content{font-size:14px;line-height:1.6;color:#334155;white-space:pre-wrap}
.card .loading{color:#94a3b8}

🤖 AI 聚合搜索


  🔍 搜索



async function search(){
  const q=document.getElementById('q').value.trim();
  if(!q)return;
  document.getElementById('results').innerHTML='DeepSeek⏳ 搜索中...';

  const resp=await fetch('/api/search?q='+encodeURIComponent(q));
  const reader=resp.body.getReader();
  const decoder=new TextDecoder();
  let buffer='',content='';

  while(true){
    const{value,done}=await reader.read();
    if(done)break;
    buffer+=decoder.decode(value,{stream:true});
    const lines=buffer.split('\\n');
    buffer=lines.pop();
    for(const line of lines){
      if(line.startsWith('data: ')){
        const d=line.slice(6);
        if(d==='[DONE]')continue;
        content+=d;
        document.getElementById('results').innerHTML=
          'DeepSeek'+content+'';
      }
    }
  }
}
"""

@app.get("/", response_class=HTMLResponse)
async def index():
    return HTML

@app.get("/api/search")
async def search(q: str):
    async def generate():
        async with aiohttp.ClientSession() as session:
            async with session.post(
                SEARCH_ENGINES["deepseek"]["url"],
                headers=SEARCH_ENGINES["deepseek"]["headers"],
                json=SEARCH_ENGINES["deepseek"]["body_template"](q),
            ) as resp:
                async for line in resp.content:
                    text = line.decode().strip()
                    if text.startswith("data: "):
                        chunk = text[6:]
                        if chunk != "[DONE]":
                            yield f"data: {chunk}\n\n"
        yield "data: [DONE]\n\n"
    return StreamingResponse(generate(), media_type="text/event-stream")

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, port=8000)

使用方式

pip install fastapi aiohttp uvicorn
python metasearch.py
# 打开 http://localhost:8000
# 输入问题 → 流式展示结果

扩展更多引擎

SEARCH_ENGINES["perplexity"] = {
    "name": "Perplexity",
    "url": "https://api.perplexity.ai/chat/completions",
    ...
}

总结

一个轻量的 AI 聚合搜索页面,核心三步:FastAPI 做后端、SSE 流式输出、前端一个页面搞定。可以扩展接多个 AI 搜索 API 做对比展示。


本文是 《AI 开发者工具链实战》 系列的第 9 篇。
本文由 Zyentor(智元界)原创发布