feat: add support for searxng (#1814)
* Add support for searxng * body.results not body.web * type annotation * update docs
This commit is contained in:
@@ -810,12 +810,13 @@ Avante's tools include some web search engines, currently support:
|
|||||||
- Google's [Programmable Search Engine](https://developers.google.com/custom-search/v1/overview)
|
- Google's [Programmable Search Engine](https://developers.google.com/custom-search/v1/overview)
|
||||||
- [Kagi](https://help.kagi.com/kagi/api/search.html)
|
- [Kagi](https://help.kagi.com/kagi/api/search.html)
|
||||||
- [Brave Search](https://api-dashboard.search.brave.com/app/documentation/web-search/get-started)
|
- [Brave Search](https://api-dashboard.search.brave.com/app/documentation/web-search/get-started)
|
||||||
|
- [SearXNG](https://searxng.github.io/searxng/)
|
||||||
|
|
||||||
The default is Tavily, and can be changed through configuring `Config.web_search_engine.provider`:
|
The default is Tavily, and can be changed through configuring `Config.web_search_engine.provider`:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
web_search_engine = {
|
web_search_engine = {
|
||||||
provider = "tavily", -- tavily, serpapi, searchapi, google or kagi
|
provider = "tavily", -- tavily, serpapi, searchapi, google, kagi, brave, or searxng
|
||||||
proxy = nil, -- proxy support, e.g., http://127.0.0.1:7890
|
proxy = nil, -- proxy support, e.g., http://127.0.0.1:7890
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -830,6 +831,7 @@ Environment variables required for providers:
|
|||||||
- `GOOGLE_SEARCH_ENGINE_ID` as the [search engine](https://programmablesearchengine.google.com) ID
|
- `GOOGLE_SEARCH_ENGINE_ID` as the [search engine](https://programmablesearchengine.google.com) ID
|
||||||
- Kagi: `KAGI_API_KEY` as the [API Token](https://kagi.com/settings?p=api)
|
- Kagi: `KAGI_API_KEY` as the [API Token](https://kagi.com/settings?p=api)
|
||||||
- Brave Search: `BRAVE_API_KEY` as the [API key](https://api-dashboard.search.brave.com/app/keys)
|
- Brave Search: `BRAVE_API_KEY` as the [API key](https://api-dashboard.search.brave.com/app/keys)
|
||||||
|
- SearXNG: `SEARXNG_API_URL` as the [API URL](https://docs.searxng.org/dev/search_api.html)
|
||||||
|
|
||||||
## Disable Tools
|
## Disable Tools
|
||||||
|
|
||||||
|
|||||||
@@ -807,14 +807,14 @@ Avante 的工具包括一些 Web 搜索引擎,目前支持:
|
|||||||
- Google's [Programmable Search Engine](https://developers.google.com/custom-search/v1/overview)
|
- Google's [Programmable Search Engine](https://developers.google.com/custom-search/v1/overview)
|
||||||
- [Kagi](https://help.kagi.com/kagi/api/search.html)
|
- [Kagi](https://help.kagi.com/kagi/api/search.html)
|
||||||
- [Brave Search](https://api-dashboard.search.brave.com/app/documentation/web-search/get-started)
|
- [Brave Search](https://api-dashboard.search.brave.com/app/documentation/web-search/get-started)
|
||||||
|
- [SearXNG](https://searxng.github.io/searxng/)
|
||||||
|
|
||||||
默认是 Tavily,可以通过配置 `Config.web_search_engine.provider` 进行更改:
|
默认是 Tavily,可以通过配置 `Config.web_search_engine.provider` 进行更改:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
web_search_engine = {
|
web_search_engine = {
|
||||||
provider = "tavily", -- tavily, serpapi, searchapi, google 或 kagi
|
provider = "tavily", -- tavily, serpapi, searchapi, google, kagi, brave 或 searxng
|
||||||
proxy = nil, -- proxy support, e.g., http://127.0.0.1:7890
|
proxy = nil, -- proxy support, e.g., http://127.0.0.1:7890
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -828,6 +828,7 @@ web_search_engine = {
|
|||||||
- `GOOGLE_SEARCH_ENGINE_ID` 作为 [搜索引擎](https://programmablesearchengine.google.com) ID
|
- `GOOGLE_SEARCH_ENGINE_ID` 作为 [搜索引擎](https://programmablesearchengine.google.com) ID
|
||||||
- Kagi: `KAGI_API_KEY` 作为 [API 令牌](https://kagi.com/settings?p=api)
|
- Kagi: `KAGI_API_KEY` 作为 [API 令牌](https://kagi.com/settings?p=api)
|
||||||
- Brave Search: `BRAVE_API_KEY` 作为 [API 密钥](https://api-dashboard.search.brave.com/app/keys)
|
- Brave Search: `BRAVE_API_KEY` 作为 [API 密钥](https://api-dashboard.search.brave.com/app/keys)
|
||||||
|
- SearXNG: `SEARXNG_API_URL` 作为 [API URL](https://docs.searxng.org/dev/search_api.html)
|
||||||
|
|
||||||
## 禁用工具
|
## 禁用工具
|
||||||
|
|
||||||
|
|||||||
@@ -186,6 +186,28 @@ M._defaults = {
|
|||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return vim.json.encode(jsn), nil
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
searxng = {
|
||||||
|
api_url_name = "SEARXNG_API_URL",
|
||||||
|
extra_request_body = {
|
||||||
|
format = "json",
|
||||||
|
},
|
||||||
|
---@type WebSearchEngineProviderResponseBodyFormatter
|
||||||
|
format_response_body = function(body)
|
||||||
|
if body.results == nil then return "", nil end
|
||||||
|
|
||||||
|
local jsn = vim.iter(body.results):map(
|
||||||
|
function(result)
|
||||||
|
return {
|
||||||
|
title = result.title,
|
||||||
|
url = result.url,
|
||||||
|
snippet = result.content,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
return vim.json.encode(jsn), nil
|
return vim.json.encode(jsn), nil
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -218,9 +218,9 @@ function M.web_search(opts, on_log)
|
|||||||
if on_log then on_log("query: " .. opts.query) end
|
if on_log then on_log("query: " .. opts.query) end
|
||||||
local search_engine = Config.web_search_engine.providers[provider_type]
|
local search_engine = Config.web_search_engine.providers[provider_type]
|
||||||
if search_engine == nil then return nil, "No search engine found: " .. provider_type end
|
if search_engine == nil then return nil, "No search engine found: " .. provider_type end
|
||||||
if search_engine.api_key_name == "" then return nil, "No API key provided" end
|
if provider_type ~= "searxng" and search_engine.api_key_name == "" then return nil, "No API key provided" end
|
||||||
local api_key = Utils.environment.parse(search_engine.api_key_name)
|
local api_key = provider_type ~= "searxng" and Utils.environment.parse(search_engine.api_key_name) or nil
|
||||||
if api_key == nil or api_key == "" then
|
if provider_type ~= "searxng" and api_key == nil or api_key == "" then
|
||||||
return nil, "Environment variable " .. search_engine.api_key_name .. " is not set"
|
return nil, "Environment variable " .. search_engine.api_key_name .. " is not set"
|
||||||
end
|
end
|
||||||
if provider_type == "tavily" then
|
if provider_type == "tavily" then
|
||||||
@@ -338,6 +338,26 @@ function M.web_search(opts, on_log)
|
|||||||
if resp.status ~= 200 then return nil, "Error: " .. resp.body end
|
if resp.status ~= 200 then return nil, "Error: " .. resp.body end
|
||||||
local jsn = vim.json.decode(resp.body)
|
local jsn = vim.json.decode(resp.body)
|
||||||
return search_engine.format_response_body(jsn)
|
return search_engine.format_response_body(jsn)
|
||||||
|
elseif provider_type == "searxng" then
|
||||||
|
local searxng_api_url = Utils.environment.parse(search_engine.api_url_name)
|
||||||
|
if searxng_api_url == nil or searxng_api_url == "" then
|
||||||
|
return nil, "Environment variable " .. search_engine.api_url_name .. " is not set"
|
||||||
|
end
|
||||||
|
local query_params = vim.tbl_deep_extend("force", {
|
||||||
|
q = opts.query,
|
||||||
|
}, search_engine.extra_request_body)
|
||||||
|
local query_string = ""
|
||||||
|
for key, value in pairs(query_params) do
|
||||||
|
query_string = query_string .. key .. "=" .. vim.uri_encode(value) .. "&"
|
||||||
|
end
|
||||||
|
local resp = curl.get(searxng_api_url .. "?" .. query_string, {
|
||||||
|
headers = {
|
||||||
|
["Content-Type"] = "application/json",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if resp.status ~= 200 then return nil, "Error: " .. resp.body end
|
||||||
|
local jsn = vim.json.decode(resp.body)
|
||||||
|
return search_engine.format_response_body(jsn)
|
||||||
end
|
end
|
||||||
return nil, "Error: No search engine found"
|
return nil, "Error: No search engine found"
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user