Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔍 Added Bing Search Plugin #2298

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ AZURE_AI_SEARCH_SEARCH_OPTION_SELECT=
GOOGLE_API_KEY=
GOOGLE_CSE_ID=

# Bing Search
#-----------------
BING_SEARCH_API_KEY=

# SerpAPI
#-----------------
SERPAPI_API_KEY=
Expand Down
13 changes: 13 additions & 0 deletions api/app/clients/tools/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@
}
]
},
{
"name": "Bing",
"pluginKey": "bing",
"description": "Use Bing Search to find information about the weather, news, sports, and more.",
"icon": "https://i.imgur.com/0Ly2bcl.png",
"authConfig": [
{
"authField": "BING_SEARCH_API_KEY",
"label": "Bing Search API Key",
"description": "This is your Bing Search API Key. For instructions on how to obtain this, see <a href='https://github.com/danny-avila/LibreChat/blob/main/docs/features/plugins/bing_search.md'>Our Docs</a>."
}
]
},
{
"name": "Wolfram",
"pluginKey": "wolfram",
Expand Down
94 changes: 94 additions & 0 deletions api/app/clients/tools/structured/BingSearch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
const { z } = require('zod');
const { Tool } = require('@langchain/core/tools');
const { getEnvironmentVariable } = require('@langchain/core/utils/env');

class BingSearch extends Tool {
static lc_name() {
return 'BingSearch';
}

constructor(fields = {}) {
super(fields);
this.envVarApiKey = 'BING_SEARCH_API_KEY';
this.apiKey = fields.apiKey ?? getEnvironmentVariable(this.envVarApiKey);

this.kwargs = fields?.kwargs ?? {};
this.name = 'bing';
this.description =
'A search engine optimized for comprehensive, accurate, and trusted results. Useful for when you need to answer questions about current events.';

this.schema = z.object({
query: z.string().min(1).describe('The search query string.'),
max_results: z
.number()
.min(1)
.max(50)
.optional()
.describe('The maximum number of search results to return. Defaults to 10.'),
market: z
.string()
.optional()
.describe('The market where the results come from. Defaults to "en-US".'),
});
}

async _call(input) {
const validationResult = this.schema.safeParse(input);
if (!validationResult.success) {
throw new Error(`Validation failed: ${JSON.stringify(validationResult.error.issues)}`);
}

const { query, max_results = 15 } = validationResult.data;

try {
const response = await fetch(
`https://api.bing.microsoft.com/v7.0/search?q=${encodeURIComponent(
query,
)}&count=${max_results}`,
{
method: 'GET',
headers: {
'Ocp-Apim-Subscription-Key': this.apiKey,
'Content-Type': 'application/json',
},
},
);

if (!response.ok) {
throw new Error(`Request failed with status ${response.status}: ${response.statusText}`);
}

const json = await response.json();

if (json.error) {
throw new Error(`Request failed: ${json.error.message}`);
}

const webPages = json.webPages?.value || [];
const rankingResponse = json.rankingResponse?.value || [];
const entities = json.entities?.value || [];
const news = json.news?.value || [];
const computation = json.computation?.value || [];
const timeZone = json.timeZone?.value || [];
const spellSuggestion = json.spellSuggestion?.value || '';
const translations = json.translations?.value || [];

const results = {
webPages,
entities,
news,
computation,
timeZone,
translations,
spellSuggestion,
rankingResponse,
};

return JSON.stringify(results);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The webPages object is a list of search hits with "snippets", really short extracts of the found pages [1].

It looks to me like this code will only pass back these snippets to the OpenAI Assistants API, and not the full page contents, or did I misunderstand?

Usually with the previous API, you would have to scrape each of the pages and extract important contents with readability.js before passing that back as the response.

[1] https://learn.microsoft.com/en-us/bing/search-apis/bing-web-search/search-responses#webpages-answer

} catch (error) {
throw new Error(`Request failed: ${error.message}`);
}
}
}

module.exports = BingSearch;
4 changes: 3 additions & 1 deletion api/app/clients/tools/util/handleTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const {
// Basic Tools
CodeBrew,
AzureAISearch,
GoogleSearchAPI,
WolframAlphaAPI,
OpenAICreateImage,
StableDiffusionAPI,
Expand All @@ -20,6 +19,8 @@ const {
StructuredSD,
StructuredACS,
CodeSherpaTools,
BingSearch,
GoogleSearchAPI,
TraversaalSearch,
StructuredWolfram,
TavilySearchResults,
Expand Down Expand Up @@ -160,6 +161,7 @@ const loadTools = async ({
const toolConstructors = {
tavily_search_results_json: TavilySearchResults,
calculator: Calculator,
bing: BingSearch,
google: GoogleSearchAPI,
wolfram: functions ? StructuredWolfram : WolframAlphaAPI,
'dall-e': OpenAICreateImage,
Expand Down
18 changes: 18 additions & 0 deletions api/app/clients/tools/util/handleTools.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const { validateTools, loadTools, loadToolWithAuth } = require('./handleTools');
const {
availableTools,
OpenAICreateImage,
BingSearch,
GoogleSearchAPI,
StructuredSD,
WolframAlphaAPI,
Expand Down Expand Up @@ -277,6 +278,23 @@ describe('Tool Handlers', () => {
const Tool = await toolFunctions[testPluginKey]();
expect(Tool).toBeInstanceOf(TestClass);
});
it('should initialize an authenticated tool through Environment Variables for bing', async () => {
let testPluginKey = 'bing';
let TestClass = BingSearch;
const plugin = availableTools.find((tool) => tool.pluginKey === testPluginKey);
const authConfigs = plugin.authConfig;
for (const authConfig of authConfigs) {
process.env[authConfig.authField] = mockCredential;
}
toolFunctions = await loadTools({
user: fakeUser._id,
model: BaseChatModel,
tools: [testPluginKey],
returnMap: true,
});
const Tool = await toolFunctions[testPluginKey]();
expect(Tool).toBeInstanceOf(TestClass);
});
it('returns an empty object when no tools are requested', async () => {
toolFunctions = await loadTools({
user: fakeUser._id,
Expand Down
1 change: 1 addition & 0 deletions docs/features/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ weight: 2
* 🛠️ [Make Your Own](./plugins/make_your_own.md)
* 🧑‍💼 [Official ChatGPT Plugins](./plugins/chatgpt_plugins_openapi.md)
* 🔎 [Google Search](./plugins/google_search.md)
* 🔎 [Bing Search](./plugins/bing_search.md)
* 🖌️ [Stable Diffusion](./plugins/stable_diffusion.md)
* 🧠 [Wolfram|Alpha](./plugins/wolfram.md)
* ⚡ [Azure AI Search](./plugins/azure_ai_search.md)
Expand Down
59 changes: 59 additions & 0 deletions docs/features/plugins/bing_search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
title: 🔎 Bing Search
description: How to set up and use the Bing Search Plugin, which allows you to query Bing with GPT's help.
weight: -7
---

# Bing Search Plugin
Through the plugins endpoint, you can use Bing Search for answers to your questions with assistance from GPT! To get started, you need to get a Bing Search API key. You can then define these as follows in your `.env` file:
```env
BING_SEARCH_API_KEY="...."
```

## Create or login to your account on Azure Portal

**1.** Visit [Azure Portal](https://azure.microsoft.com/en-us/) and click on `Get started` or `Try Azure for Free` to create an account and sign in.

**2.** Choose pay per use or Azure Free with $200.

![image](https://raw.githubusercontent.com/itzraiss/images/main/Captura%20de%20tela%202023-11-26%20151647.png?token=GHSAT0AAAAAACJ4TKEINPEOAV3LEPNPBDNCZLEKLAQ)

## 1\. Access your control panel & Click on `Create a Resource`..

![image](https://raw.githubusercontent.com/itzraiss/images/main/Captura%20de%20tela%202023-11-26%20151706.png?token=GHSAT0AAAAAACJ4TKEJDXD7E76YLZEV52Z4ZLEKLCQ)

## 2\. Search for `Bing Search V7` in the bar and press enter.

![image](https://raw.githubusercontent.com/itzraiss/images/main/Captura%20de%20tela%202024-04-03%20110147.png)

## 3\. Now, click on `Create` e select `Bing Search V7`.

## 4\. Configure the basics settings and click on 'Review + create'..

**Pricing Tier (F1 is FREE)' Check out the prices of the service [here](https://www.microsoft.com/en-us/bing/apis/pricing).**

![image](https://raw.githubusercontent.com/itzraiss/images/main/Captura%20de%20tela%202024-04-03%20110620.png)

## 5\. Now, click on `Create`.

![image](https://raw.githubusercontent.com/itzraiss/images/main/Captura%20de%20tela%202024-04-03%20111024.png)

## 6\. You will be redirected to the resource dashboard. Click on `Keys & Endpoint` on the **left-hand** panel.

![image](https://raw.githubusercontent.com/itzraiss/images/main/image.png)

## 7\. Now, copy your key to your .env file

![image](https://raw.githubusercontent.com/itzraiss/images/main/Captura%20de%20tela%202024-04-03%20111714.png)

# Conclusion

### Now, you will be able to conduct searches using Bing Search V7 in endpoint `Plugins & Assistants `. **Congratulations!** 🎉🎉

**Plugins:**

![image](https://raw.githubusercontent.com/itzraiss/images/main/Captura%20de%20tela%202024-04-03%20113022.png)

**Assistants:**

![image](https://raw.githubusercontent.com/itzraiss/images/main/Captura%20de%20tela%202024-04-03%20113029.png)
1 change: 1 addition & 0 deletions docs/features/plugins/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ weight: -9
* 🛠️ [Make Your Own](./make_your_own.md)
* 🧑‍💼 [Official ChatGPT Plugins](./chatgpt_plugins_openapi.md)
* 🔎 [Google Search](./google_search.md)
* 🔎 [Bing Search](./bing_search.md)
* 🖌️ [Stable Diffusion](./stable_diffusion.md)
* 🧠 [Wolfram|Alpha](./wolfram.md)
* ⚡ [Azure AI Search](./azure_ai_search.md)
1 change: 1 addition & 0 deletions docs/features/plugins/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Clicking on **"Show Agent Settings"** will allow you to modify parameters for th

### Plugins Setup Instructions
- **[Google Search](./google_search.md)**
- **[Bing Search](./bing_search.md)**
- **[Stable Diffusion](./stable_diffusion.md)**
- **[Wolfram](./wolfram.md)**
- **DALL-E** - same setup as above, you just need an OpenAI key, and it's made distinct from your main API key to make Chats but it can be the same one
Expand Down
7 changes: 7 additions & 0 deletions docs/install/configuration/dotenv.md
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,13 @@ GOOGLE_API_KEY=
GOOGLE_CSE_ID=
```

#### Bing Search
See detailed instructions here: [Bing Search](../../features/plugins/bing_search.md)

```bash
BING_SEARCH_API_KEY=
```

#### SerpAPI
SerpApi is a real-time API to access Google search results (not as performant)

Expand Down