「Mac畅玩AIGC与多模态40」开发篇35 - 用 Python 开发服务对接 SearxNG 与本地知识库

一、概述

本篇介绍如何使用 Python 构建一个集成本地聚合搜索引擎 SearxNG 与本地知识库的双通道服务接口,返回标准结构化 JSON 数据,并用于对接智能体插件系统。该接口适用于本地 Agent 应用开发与 Dify 插件集成场景。

二、目标说明

  • 使用 Flask 实现搜索服务端接口
  • /search_web 路由封装本地 SearxNG 请求
  • /search_kb 路由封装本地知识库检索接口
  • /search 路由整合聚合结果并返回统一格式
  • 返回格式包含 titlecontenturl 字段

三、目录结构

复制代码
search_service/
├── app.py               # 主服务入口
├── kb_docs.json         # 本地知识库内容
├── kb_index.faiss       # FAISS 索引文件(由构建脚本生成)
├── build_index.py       # 索引构建脚本
└── requirements.txt     # Python 依赖清单

四、安装依赖

bash 复制代码
pip install flask requests faiss-cpu sentence-transformers

或者使用 requirements.txt 安装:

requirements.txt

复制代码
flask
requests
sentence-transformers
faiss-cpu

五、准备知识库文件(kb_docs.json)

json 复制代码
[
  {
    "title": "HarmonyOS 系统概览",
    "content": "HarmonyOS 是一个面向全场景的分布式操作系统,适用于智能手机、智能家居、车载终端等多设备融合。",
    "url": "https://example.com/harmonyos-overview"
  },
  {
    "title": "HarmonyOS 的微内核架构",
    "content": "HarmonyOS 使用微内核架构,提高系统安全性和模块独立性,支持硬件隔离和实时调度。",
    "url": "https://example.com/harmonyos-kernel"
  },
  {
    "title": "鸿蒙系统与 Android 的区别",
    "content": "HarmonyOS 与 Android 最大的区别在于系统底层架构和跨设备能力,前者强调分布式协同。",
    "url": "https://example.com/harmonyos-vs-android"
  },
  {
    "title": "分布式任务调度机制",
    "content": "HarmonyOS 支持多设备之间的任务迁移与协同执行,实现一次开发、多端部署。",
    "url": "https://example.com/harmonyos-scheduler"
  },
  {
    "title": "HarmonyOS 对开发者的影响",
    "content": "该系统为开发者提供统一 IDE、统一语言和一次编写多端运行的开发体验。",
    "url": "https://example.com/harmonyos-developers"
  }
]

六、构建向量索引(build_index.py)

python 复制代码
from sentence_transformers import SentenceTransformer
import faiss
import json
import numpy as np

# 加载文档
with open("kb_docs.json", "r", encoding="utf-8") as f:
    docs = json.load(f)

# 生成 embeddings
model = SentenceTransformer('paraphrase-MiniLM-L6-v2')
corpus = [doc["content"] for doc in docs]
embeddings = model.encode(corpus, convert_to_numpy=True)

# 构建并保存索引
index = faiss.IndexFlatL2(embeddings.shape[1])
index.add(np.array(embeddings))
faiss.write_index(index, "kb_index.faiss")

七、主服务接口实现(app.py

python 复制代码
from flask import Flask, request, jsonify
import requests
import json
import faiss
import numpy as np
from sentence_transformers import SentenceTransformer

app = Flask(__name__)

# 初始化知识库模型和索引
model = SentenceTransformer('paraphrase-MiniLM-L6-v2')
index = faiss.read_index("kb_index.faiss")
with open("kb_docs.json", "r", encoding="utf-8") as f:
    kb_docs = json.load(f)

@app.route("/search_web", methods=["GET"])
def search_web():
    q = request.args.get("q", "")
    if not q:
        return jsonify({"error": "Missing query"}), 400
    try:
        resp = requests.get("http://localhost:8090/search", params={"q": q, "format": "json"})
        raw = resp.json()
        results = []
        for item in raw.get("results", [])[:3]:
            results.append({
                "title": item.get("title", ""),
                "content": item.get("content", ""),
                "url": item.get("url", "")
            })
        return jsonify({"results": results})
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@app.route("/search_kb", methods=["GET"])
def search_kb():
    q = request.args.get("q", "").strip()
    if not q:
        return jsonify({"results": [], "error": "Missing query"})
    try:
        vec = model.encode([q])
        D, I = index.search(np.array(vec), k=3)
        results = []
        for idx in I[0]:
            doc = kb_docs[idx]
            results.append({
                "title": doc.get("title", "Untitled"),
                "content": doc.get("content", ""),
                "url": doc.get("url", "")
            })
        return jsonify({"results": results})
    except Exception as e:
        return jsonify({"results": [], "error": str(e)})

@app.route("/search", methods=["GET"])
def search_combined():
    q = request.args.get("q", "")
    if not q:
        return jsonify({"error": "Missing query"}), 400
    try:
        from concurrent.futures import ThreadPoolExecutor

        def get_web():
            resp = requests.get("http://localhost:5001/search_web", params={"q": q})
            return resp.json().get("results", [])

        def get_kb():
            resp = requests.get("http://localhost:5001/search_kb", params={"q": q})
            return resp.json().get("results", [])

        with ThreadPoolExecutor() as pool:
            web_future = pool.submit(get_web)
            kb_future = pool.submit(get_kb)
            web_results = web_future.result()
            kb_results = kb_future.result()

        return jsonify({"results": web_results + kb_results})
    except Exception as e:
        return jsonify({"error": str(e)}), 500

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5001)

八、启动服务

bash 复制代码
python app.py

九、接口测试示例

bash 复制代码
curl "http://localhost:5001/search?q=HarmonyOS"

返回格式:

json 复制代码
{
  "results": [
    { "title": "HarmonyOS 系统概览", "content": "...", "url": "..." },
    { "title": "HarmonyOS 的微内核架构", "content": "...", "url": "..." },
    { "title": "SearxNG 聚合结果", "content": "...", "url": "..." }
  ]
}

十、总结

本篇通过 Flask 实现了面向 SearxNG 与本地知识库的双通道搜索接口服务,并新增 /search 路由聚合两类结果,统一格式输出,便于构建插件描述文件,接入 Dify Agent 应用并实现智能体插件能力扩展。

相关推荐
Turnsole_y1 小时前
pycharm自动化测试初始化
python·selenium
weixin-a153003083162 小时前
[数据抓取-1]beautifulsoup
开发语言·python·beautifulsoup
AI量化投资实验室2 小时前
15年122倍,年化43.58%,回撤才20%,Optuna机器学习多目标调参backtrader,附python代码
人工智能·python·机器学习
倔强青铜三2 小时前
苦练Python第67天:光速读取任意行,linecache模块解锁文件处理新姿势
人工智能·python·面试
我是华为OD~HR~栗栗呀3 小时前
华为od-21届考研-C++面经
java·c语言·c++·python·华为od·华为·面试
明月(Alioo)3 小时前
机器学习入门,无监督学习之K-Means聚类算法完全指南:面向Java开发者的Python实现详解
python·算法·机器学习
墨风如雪3 小时前
告别无声AI视频!谷歌Veo 3.1打造沉浸式视听盛宴
aigc
鱼鱼说测试3 小时前
Linux下运行Jmeter
开发语言·python
CodeCraft Studio4 小时前
国产化Excel开发组件Spire.XLS教程:将Python列表转换为Excel表格(3种实用场景)
开发语言·python·excel·spire.xls·python列表转excel·国产化文档开发
企鹅侠客4 小时前
基于python写的PDF表格提取到excel文档
python·pdf·excel·pdf文档表格转excel