فهرست منبع

【新增】bing、google search

cherishsince 8 ماه پیش
والد
کامیت
86801517d1

+ 29 - 0
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/WebSearchService.java

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.ai.service.websearch;
+
+import cn.iocoder.yudao.module.ai.service.websearch.vo.WebSearchRespVO;
+
+import java.util.List;
+
+/**
+ * Web 搜索 Service 接口
+ */
+public interface WebSearchService {
+
+    /**
+     * bing 搜索
+     *
+     * @param query 搜索关键词
+     * @param count 返回结果数量
+     * @return 搜索结果列表
+     */
+    List<WebSearchRespVO> bingSearch(String query, Integer count);
+    
+    /**
+     * Google 搜索
+     *
+     * @param query 搜索关键词
+     * @param count 返回结果数量
+     * @return 搜索结果列表
+     */
+    List<WebSearchRespVO> googleSearch(String query, Integer count);
+}

+ 139 - 0
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/WebSearchServiceImpl.java

@@ -0,0 +1,139 @@
+package cn.iocoder.yudao.module.ai.service.websearch;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import cn.iocoder.yudao.module.ai.service.websearch.vo.WebSearchRespVO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Bing Web 搜索实现类
+ */
+@Service
+@Slf4j
+public class WebSearchServiceImpl implements WebSearchService {
+
+    /**
+     * google url
+     */
+    private static final String GOOGLE_URL = "https://google.serper.dev/search";
+    /**
+     * bing url
+     */
+    private static final String BING_URL = "https://api.bing.microsoft.com/v7.0/search";
+    /**
+     * 腾讯搜索 url
+     */
+    private static final String TENCENT_URL = "tms.tencentcloudapi.com";
+
+    @Value("${yudao.web-search.api-key:}")
+    private String bingApiKey;
+
+    @Value("${yudao.web-search.api-key:}")
+    private String googleApiKey;
+
+    /**
+     * bing 搜索
+     *
+     * @param query 搜索关键词
+     * @param count 返回结果数量
+     * @return 搜索结果列表
+     */
+    @Override
+    public List<WebSearchRespVO> bingSearch(String query, Integer count) {
+        if (query == null || query.isEmpty()) {
+            return CollUtil.newArrayList();
+        }
+        
+        try {
+            // 发送请求
+            HttpResponse response = HttpRequest.get(BING_URL)
+                    .header("Ocp-Apim-Subscription-Key", bingApiKey)
+                    .form("q", query)
+                    .form("count", String.valueOf(count))
+                    .form("responseFilter", "Webpages")
+                    .form("textFormat", "Raw")
+                    .execute();
+            
+            // 解析响应
+            String body = response.body();
+            JSONObject json = JSONUtil.parseObj(body);
+            
+            // 处理结果
+            List<WebSearchRespVO> results = new ArrayList<>();
+            if (json.containsKey("webPages") && json.getJSONObject("webPages").containsKey("value")) {
+                JSONArray items = json.getJSONObject("webPages").getJSONArray("value");
+                for (int i = 0; i < items.size(); i++) {
+                    JSONObject item = items.getJSONObject(i);
+                    WebSearchRespVO result = new WebSearchRespVO()
+                            .setTitle(item.getStr("name"))
+                            .setUrl(item.getStr("url"))
+                            .setSnippet(item.getStr("snippet"));
+                    results.add(result);
+                }
+            }
+            
+            return results;
+        } catch (Exception e) {
+            log.error("[bingSearch][查询({}) 发生异常]", query, e);
+            return CollUtil.newArrayList();
+        }
+    }
+    
+    /**
+     * Google 搜索(使用Serper API)
+     *
+     * @param query 搜索关键词
+     * @param count 返回结果数量
+     * @return 搜索结果列表
+     */
+    @Override
+    public List<WebSearchRespVO> googleSearch(String query, Integer count) {
+        if (query == null || query.isEmpty()) {
+            return CollUtil.newArrayList();
+        }
+
+        try {
+            // 构建请求体
+            JSONObject payload = new JSONObject();
+            payload.set("q", query);
+            payload.set("gl", "cn");
+            payload.set("num", count);
+            
+            // 发送请求
+            HttpResponse response = HttpRequest.post(GOOGLE_URL)
+                    .header("X-API-KEY", googleApiKey)
+                    .header("Content-Type", "application/json")
+                    .body(payload.toString())
+                    .execute();
+            
+            // 解析响应
+            String body = response.body();
+            JSONObject json = JSONUtil.parseObj(body);
+            JSONArray organicResults = json.getJSONArray("organic");
+            
+            // 处理结果
+            List<WebSearchRespVO> results = new ArrayList<>();
+            for (int i = 0; i < organicResults.size(); i++) {
+                JSONObject item = organicResults.getJSONObject(i);
+                WebSearchRespVO result = new WebSearchRespVO()
+                        .setTitle(item.getStr("title"))
+                        .setUrl(item.getStr("link"))
+                        .setSnippet(item.containsKey("snippet") ? item.getStr("snippet") : "");
+                results.add(result);
+            }
+            return results;
+        } catch (Exception e) {
+            log.error("[googleSearch][查询({}) 发生异常]", query, e);
+            return CollUtil.newArrayList();
+        }
+    }
+}

+ 25 - 0
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/vo/WebSearchRespVO.java

@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.ai.service.websearch.vo;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * 搜索结果
+ */
+@Data
+@Accessors(chain = true)
+public class WebSearchRespVO {
+
+    /**
+     * 标题
+     */
+    private String title;
+    /**
+     * URL
+     */
+    private String url;
+    /**
+     * 摘要
+     */
+    private String snippet;
+}