使用Java+Qwen+SearXNG构建本地AI搜索问答

慈云数据 2024-06-15 技术支持 71 0

背景介绍

前段时间,我们使用SerpAPI+Qwen实现了网络搜索问答(参考:https://blog.csdn.net/weixin_44455388/article/details/137340000?spm=1001.2014.3001.5501),拓展大模型的网络搜索能力,但存在一个问题就是SerpAPI每月只能使用100次的免费调用。

前两天在GitHub上看到一个名叫FreeAskInternet的框架(参考:https://blog.csdn.net/weixin_44455388/article/details/137683895?spm=1001.2014.3001.5501),调用SearXNG搜索(本地运行)在多个搜索引擎上进行搜索,可以实现完全免费、私人和本地运行的搜索聚合器。

作为一个Java程序员,博主借鉴FreeAskInternet的思路,使用Java+Qwen+SearXNG构建了本地AI搜索问答,相比原来使用SerpAPI,使用上将不受限制。

SearXNG介绍

SearXNG 是一个免费的互联网元搜索引擎,它聚合了来自各种搜索服务和数据库结果,但摆脱了隐私追踪 —— 用户行为既不会被引擎跟踪也不会被分析。

在这里插入图片描述

我们可以选择搭建一个自己的搜索引擎,也可以网络找一个可以使用的站点。SearXNG的搭建也非常简单,可以采用docker进行部署,这里我就不详细展开了,大家感兴趣的可以自行去搜索教程。我这里是找的国内可用的站点。

实现思路

整体思路与FreeAskInternet框架相似:

  1. 首先是后台调用SearXNG搜索(本地运行)在多个搜索引擎上进行搜索。
  2. 抓取搜索结果链接内容并传递给LLM,让LLM根据该内容作为参考回答用户问题。
  3. 将答案以流式传输。

SearXNG提供了查询API,参考:Search API — SearXNG Documentation (2024.4.13+1746eecf2)

在这里插入图片描述

代码实现

  • 构建SearXAPI对象,实现查询方法
    /**
     * 搜索
     * @param question
     * @return
     */
    public String search(String question) {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .build();
        Request request = new Request.Builder()
                //format设置为html需要采用正则匹配中文,可以根据站点的支持情况设置为json
                .url(url+"?q=" + question + "&format=html")
                .addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0")
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new OpenAIChatException("Failed to fetch data from SearXNG: " + response);
            }
            StringBuilder stringBuilder = new StringBuilder();
            String content = response.body().string();
            //匹配中文字符
            String regex = "[\\u4e00-\\u9fa5]";
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(content);
            while (matcher.find()) {
                stringBuilder.append(content.charAt(matcher.start()));
            }
            return stringBuilder.toString();
        }catch (Exception e){
            e.printStackTrace();
            throw new OpenAIChatException("Failed to fetch data from SearXNG: " + e.getMessage());
        }
    }
    

    SearXNG的查询接口需要传入q和format两个参数。q就是你要查询的具体内容,format是返回的格式,可以选择html、json、csv、rss。最优选择肯定是json,但因为我网上找的站点,没有开放json响应的权限,因此选择json格式会出现403 forbidden错误,因此我这里就选择的html,然后在html代码中匹配中文字符。

    • 构建WebSearchChain对象,并实现查询方法:
      /**
       * 基于SearXNG搜索
       * @param question
       * @return
       */
      public String searchFromSearX(String question) {
          SearxApi searxApi = new SearxApi(searxUrl);
          String search = searxApi.search(question);
          LOG.info("Web 搜索结果:{}",search);
          return search;
      }
      
      • 测试效果:

        之前借鉴LangChain的思路,封装了一个Java版的框架,因此实际使用的时候简单调用一下以下几行代码就可以了。

        /**
         * 网络搜索问答,拓展网络搜索能力
         * 使用SearXNG进行搜索,没有使用限制
         */
        public static void test8() {
            String prompt = "吴亦凡犯了什么事";
            OpenAIChat openAIChat = OpenAIChat.builder().endpointUrl("http://192.168.xx.xx:9997/v1").model("Qwen1.5-14B-Chat").build().init();
            //查询站点
            WebSearchChain webSearchChain = WebSearchChain.fromSearXNG("http://xxxxxxx.com");
            String searchResult = webSearchChain.searchFromSearX(prompt);
            Flux stringFlux = openAIChat.streamChatWithChain("112233", "你是一个AI助手", searchResult, prompt);
            stringFlux.subscribe();
        }
        

        通过以下截图,可以看到我们使用网络搜索的内容实现了AI大模型的搜索问答:

        在这里插入图片描述

        欢迎关注我的微信公众号,一起交流一起进步。

微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon