Skip to content

Commit

Permalink
Merge pull request #118 from CZJCC/feature/extension-dev
Browse files Browse the repository at this point in the history
add bing plugin
  • Loading branch information
chickenlj authored Nov 21, 2024
2 parents c598034 + f3ff1f9 commit a6b2e35
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.cloud.ai.plugin;

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;

/**
* .
*
* @author: KrakenZJC
* @since : 2024-11-18
**/

@Configuration
@ConditionalOnClass(BingSearchService.class)
@EnableConfigurationProperties(BingSearchProperties.class)
public class BingSearchPluginConfiguration {

@Bean
@ConditionalOnMissingBean
@Description("Use bing search engine to query for the latest news.") // function
@ConditionalOnProperty(prefix = "spring.ai.alibaba.plugin.bing", name = "enabled", havingValue = "true")
public BingSearchService bingSearchService(BingSearchProperties properties) {
return new BingSearchService(properties);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.alibaba.cloud.ai.plugin;
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
* .
*
* @date: 2024-11-20
* @version: 1.0
* @author: KrakenZJC
**/

@ConfigurationProperties(prefix = "spring.ai.alibaba.plugin.bing")
public class BingSearchProperties {

public static final String OCP_APIM_SUBSCRIPTION_KEY = "Ocp-Apim-Subscription-Key";

// bing api key for Ocp-Apim-Subscription-Key
// https://learn.microsoft.com/en-us/bing/search-apis/bing-web-search/quickstarts/rest/java
private String token;

public String getToken() {
return token;
}

public void setToken(String token) {
this.token = token;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.alibaba.cloud.ai.plugin;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import com.fasterxml.jackson.annotation.JsonClassDescription;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
* .
*
* @author: KrakenZJC
* @since : 2024-11-18
**/

public class BingSearchService implements Function<BingSearchService.Request, BingSearchService.Response> {

private static final Logger logger = LoggerFactory.getLogger(BingSearchService.class);

private static final String BING_SEARCH_HOST_URL = "https://api.bing.microsoft.com";

private static final String BING_SEARCH_PATH = "/v7.0/search";

private final WebClient webClient;

public BingSearchService(BingSearchProperties properties) {
assert StringUtils.hasText(properties.getToken()) && properties.getToken().length() == 32;
this.webClient = WebClient.builder().defaultHeader(HttpHeaders.USER_AGENT,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36")
.defaultHeader(BingSearchProperties.OCP_APIM_SUBSCRIPTION_KEY, properties.getToken())
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(5 * 1024 * 1024)).build();
}

@Override
public BingSearchService.Response apply(BingSearchService.Request request) {
if (request == null || !StringUtils.hasText(request.query)) {
return null;
}

String url = BING_SEARCH_HOST_URL + BING_SEARCH_PATH + "?q=" + URLEncoder.encode(request.query,
StandardCharsets.UTF_8);

try {
Mono<String> responseMono = webClient.get().uri(url).retrieve().bodyToMono(String.class);
String responseData = responseMono.block();
assert responseData != null;
logger.info("bing search: {},result:{}", request.query, responseData);
return new Response(responseData);
} catch (Exception e) {
logger.error("failed to invoke bing search caused by:{}", e.getMessage());
return null;
}
}

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonClassDescription("Bing search API request")
public record Request(
@JsonProperty(required = true, value = "query") @JsonPropertyDescription("The query keyword e.g. Alibaba") String query) {

}

/**
* Bing search Function response.
*/
@JsonClassDescription("Bing search API response")
public record Response(String data) {

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.alibaba.cloud.plugin.BingSearchPluginConfiguration

0 comments on commit a6b2e35

Please # to comment.