Skip to content

Commit 22bd108

Browse files
authored
Merge pull request #885 from QwenLM/web-search
chore: Web Search Tool Refactoring with Multi-Provider Support
2 parents 7e82783 + 7ff07fd commit 22bd108

File tree

20 files changed

+1684
-429
lines changed

20 files changed

+1684
-429
lines changed

docs/cli/configuration-v1.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,8 @@ If you are experiencing performance issues with file searching (e.g., with `@` c
309309
```
310310

311311
- **`tavilyApiKey`** (string):
312-
- **Description:** API key for Tavily web search service. Required to enable the `web_search` tool functionality. If not configured, the web search tool will be disabled and skipped.
312+
- **Description:** API key for Tavily web search service. Used to enable the `web_search` tool functionality.
313+
- **Note:** This is a legacy configuration format. For Qwen OAuth users, DashScope provider is automatically available without any configuration. For other authentication types, configure Tavily or Google providers using the new `webSearch` configuration format.
313314
- **Default:** `undefined` (web search disabled)
314315
- **Example:** `"tavilyApiKey": "tvly-your-api-key-here"`
315316
- **`chatCompression`** (object):
@@ -465,8 +466,8 @@ The CLI automatically loads environment variables from an `.env` file. The loadi
465466
- This is useful for development and testing.
466467
- **`TAVILY_API_KEY`**:
467468
- Your API key for the Tavily web search service.
468-
- Required to enable the `web_search` tool functionality.
469-
- If not configured, the web search tool will be disabled and skipped.
469+
- Used to enable the `web_search` tool functionality.
470+
- **Note:** For Qwen OAuth users, DashScope provider is automatically available without any configuration. For other authentication types, configure Tavily or Google providers to enable web search.
470471
- Example: `export TAVILY_API_KEY="tvly-your-api-key-here"`
471472

472473
## Command-Line Arguments

docs/cli/configuration.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,8 @@ Settings are organized into categories. All settings should be placed within the
305305
- **Default:** `undefined`
306306

307307
- **`advanced.tavilyApiKey`** (string):
308-
- **Description:** API key for Tavily web search service. Required to enable the `web_search` tool functionality. If not configured, the web search tool will be disabled and skipped.
308+
- **Description:** API key for Tavily web search service. Used to enable the `web_search` tool functionality.
309+
- **Note:** This is a legacy configuration format. For Qwen OAuth users, DashScope provider is automatically available without any configuration. For other authentication types, configure Tavily or Google providers using the new `webSearch` configuration format.
309310
- **Default:** `undefined`
310311

311312
#### `mcpServers`
@@ -474,8 +475,8 @@ The CLI automatically loads environment variables from an `.env` file. The loadi
474475
- Set to a string to customize the title of the CLI.
475476
- **`TAVILY_API_KEY`**:
476477
- Your API key for the Tavily web search service.
477-
- Required to enable the `web_search` tool functionality.
478-
- If not configured, the web search tool will be disabled and skipped.
478+
- Used to enable the `web_search` tool functionality.
479+
- **Note:** For Qwen OAuth users, DashScope provider is automatically available without any configuration. For other authentication types, configure Tavily or Google providers to enable web search.
479480
- Example: `export TAVILY_API_KEY="tvly-your-api-key-here"`
480481

481482
## Command-Line Arguments

docs/tools/web-search.md

Lines changed: 162 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,186 @@
11
# Web Search Tool (`web_search`)
22

3-
This document describes the `web_search` tool.
3+
This document describes the `web_search` tool for performing web searches using multiple providers.
44

55
## Description
66

7-
Use `web_search` to perform a web search using the Tavily API. The tool returns a concise answer with sources when possible.
7+
Use `web_search` to perform a web search and get information from the internet. The tool supports multiple search providers and returns a concise answer with source citations when available.
8+
9+
### Supported Providers
10+
11+
1. **DashScope** (Official, Free) - Automatically available for Qwen OAuth users (200 requests/minute, 2000 requests/day)
12+
2. **Tavily** - High-quality search API with built-in answer generation
13+
3. **Google Custom Search** - Google's Custom Search JSON API
814

915
### Arguments
1016

11-
`web_search` takes one argument:
17+
`web_search` takes two arguments:
18+
19+
- `query` (string, required): The search query
20+
- `provider` (string, optional): Specific provider to use ("dashscope", "tavily", "google")
21+
- If not specified, uses the default provider from configuration
22+
23+
## Configuration
24+
25+
### Method 1: Settings File (Recommended)
26+
27+
Add to your `settings.json`:
28+
29+
```json
30+
{
31+
"webSearch": {
32+
"provider": [
33+
{ "type": "dashscope" },
34+
{ "type": "tavily", "apiKey": "tvly-xxxxx" },
35+
{
36+
"type": "google",
37+
"apiKey": "your-google-api-key",
38+
"searchEngineId": "your-search-engine-id"
39+
}
40+
],
41+
"default": "dashscope"
42+
}
43+
}
44+
```
45+
46+
**Notes:**
47+
48+
- DashScope doesn't require an API key (official, free service)
49+
- **Qwen OAuth users:** DashScope is automatically added to your provider list, even if not explicitly configured
50+
- Configure additional providers (Tavily, Google) if you want to use them alongside DashScope
51+
- Set `default` to specify which provider to use by default (if not set, priority order: Tavily > Google > DashScope)
52+
53+
### Method 2: Environment Variables
54+
55+
Set environment variables in your shell or `.env` file:
56+
57+
```bash
58+
# Tavily
59+
export TAVILY_API_KEY="tvly-xxxxx"
60+
61+
# Google
62+
export GOOGLE_API_KEY="your-api-key"
63+
export GOOGLE_SEARCH_ENGINE_ID="your-engine-id"
64+
```
65+
66+
### Method 3: Command Line Arguments
1267

13-
- `query` (string, required): The search query.
68+
Pass API keys when running Qwen Code:
1469

15-
## How to use `web_search`
70+
```bash
71+
# Tavily
72+
qwen --tavily-api-key tvly-xxxxx
1673

17-
`web_search` calls the Tavily API directly. You must configure the `TAVILY_API_KEY` through one of the following methods:
74+
# Google
75+
qwen --google-api-key your-key --google-search-engine-id your-id
1876

19-
1. **Settings file**: Add `"tavilyApiKey": "your-key-here"` to your `settings.json`
20-
2. **Environment variable**: Set `TAVILY_API_KEY` in your environment or `.env` file
21-
3. **Command line**: Use `--tavily-api-key your-key-here` when running the CLI
77+
# Specify default provider
78+
qwen --web-search-default tavily
79+
```
2280

23-
If the key is not configured, the tool will be disabled and skipped.
81+
### Backward Compatibility (Deprecated)
2482

25-
Usage:
83+
⚠️ **DEPRECATED:** The legacy `tavilyApiKey` configuration is still supported for backward compatibility but is deprecated:
2684

85+
```json
86+
{
87+
"advanced": {
88+
"tavilyApiKey": "tvly-xxxxx" // ⚠️ Deprecated
89+
}
90+
}
2791
```
28-
web_search(query="Your query goes here.")
92+
93+
**Important:** This configuration is deprecated and will be removed in a future version. Please migrate to the new `webSearch` configuration format shown above. The old configuration will automatically configure Tavily as a provider, but we strongly recommend updating your configuration.
94+
95+
## Disabling Web Search
96+
97+
If you want to disable the web search functionality, you can exclude the `web_search` tool in your `settings.json`:
98+
99+
```json
100+
{
101+
"tools": {
102+
"exclude": ["web_search"]
103+
}
104+
}
29105
```
30106

31-
## `web_search` examples
107+
**Note:** This setting requires a restart of Qwen Code to take effect. Once disabled, the `web_search` tool will not be available to the model, even if web search providers are configured.
108+
109+
## Usage Examples
32110

33-
Get information on a topic:
111+
### Basic search (using default provider)
34112

35113
```
36-
web_search(query="latest advancements in AI-powered code generation")
114+
web_search(query="latest advancements in AI")
115+
```
116+
117+
### Search with specific provider
118+
37119
```
120+
web_search(query="latest advancements in AI", provider="tavily")
121+
```
122+
123+
### Real-world examples
124+
125+
```
126+
web_search(query="weather in San Francisco today")
127+
web_search(query="latest Node.js LTS version", provider="google")
128+
web_search(query="best practices for React 19", provider="dashscope")
129+
```
130+
131+
## Provider Details
132+
133+
### DashScope (Official)
134+
135+
- **Cost:** Free
136+
- **Authentication:** Automatically available when using Qwen OAuth authentication
137+
- **Configuration:** No API key required, automatically added to provider list for Qwen OAuth users
138+
- **Quota:** 200 requests/minute, 2000 requests/day
139+
- **Best for:** General queries, always available as fallback for Qwen OAuth users
140+
- **Auto-registration:** If you're using Qwen OAuth, DashScope is automatically added to your provider list even if you don't configure it explicitly
141+
142+
### Tavily
143+
144+
- **Cost:** Requires API key (paid service with free tier)
145+
- **Sign up:** https://tavily.com
146+
- **Features:** High-quality results with AI-generated answers
147+
- **Best for:** Research, comprehensive answers with citations
148+
149+
### Google Custom Search
150+
151+
- **Cost:** Free tier available (100 queries/day)
152+
- **Setup:**
153+
1. Enable Custom Search API in Google Cloud Console
154+
2. Create a Custom Search Engine at https://programmablesearchengine.google.com
155+
- **Features:** Google's search quality
156+
- **Best for:** Specific, factual queries
157+
158+
## Important Notes
159+
160+
- **Response format:** Returns a concise answer with numbered source citations
161+
- **Citations:** Source links are appended as a numbered list: [1], [2], etc.
162+
- **Multiple providers:** If one provider fails, manually specify another using the `provider` parameter
163+
- **DashScope availability:** Automatically available for Qwen OAuth users, no configuration needed
164+
- **Default provider selection:** The system automatically selects a default provider based on availability:
165+
1. Your explicit `default` configuration (highest priority)
166+
2. CLI argument `--web-search-default`
167+
3. First available provider by priority: Tavily > Google > DashScope
168+
169+
## Troubleshooting
170+
171+
**Tool not available?**
172+
173+
- **For Qwen OAuth users:** The tool is automatically registered with DashScope provider, no configuration needed
174+
- **For other authentication types:** Ensure at least one provider (Tavily or Google) is configured
175+
- For Tavily/Google: Verify your API keys are correct
176+
177+
**Provider-specific errors?**
178+
179+
- Use the `provider` parameter to try a different search provider
180+
- Check your API quotas and rate limits
181+
- Verify API keys are properly set in configuration
38182

39-
## Important notes
183+
**Need help?**
40184

41-
- **Response returned:** The `web_search` tool returns a concise answer when available, with a list of source links.
42-
- **Citations:** Source links are appended as a numbered list.
43-
- **API key:** Configure `TAVILY_API_KEY` via settings.json, environment variables, .env files, or command line arguments. If not configured, the tool is not registered.
185+
- Check your configuration: Run `qwen` and use the settings dialog
186+
- View your current settings in `~/.qwen-code/settings.json` (macOS/Linux) or `%USERPROFILE%\.qwen-code\settings.json` (Windows)

integration-tests/web_search.test.ts

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,53 @@ import { TestRig, printDebugInfo, validateModelOutput } from './test-helper.js';
99

1010
describe('web_search', () => {
1111
it('should be able to search the web', async () => {
12-
// Skip if Tavily key is not configured
13-
if (!process.env['TAVILY_API_KEY']) {
14-
console.warn('Skipping web search test: TAVILY_API_KEY not set');
12+
// Check if any web search provider is available
13+
const hasTavilyKey = !!process.env['TAVILY_API_KEY'];
14+
const hasGoogleKey =
15+
!!process.env['GOOGLE_API_KEY'] &&
16+
!!process.env['GOOGLE_SEARCH_ENGINE_ID'];
17+
18+
// Skip if no provider is configured
19+
// Note: DashScope provider is automatically available for Qwen OAuth users,
20+
// but we can't easily detect that in tests without actual OAuth credentials
21+
if (!hasTavilyKey && !hasGoogleKey) {
22+
console.warn(
23+
'Skipping web search test: No web search provider configured. ' +
24+
'Set TAVILY_API_KEY or GOOGLE_API_KEY+GOOGLE_SEARCH_ENGINE_ID environment variables.',
25+
);
1526
return;
1627
}
1728

1829
const rig = new TestRig();
19-
await rig.setup('should be able to search the web');
30+
// Configure web search in settings if provider keys are available
31+
const webSearchSettings: Record<string, unknown> = {};
32+
const providers: Array<{
33+
type: string;
34+
apiKey?: string;
35+
searchEngineId?: string;
36+
}> = [];
37+
38+
if (hasTavilyKey) {
39+
providers.push({ type: 'tavily', apiKey: process.env['TAVILY_API_KEY'] });
40+
}
41+
if (hasGoogleKey) {
42+
providers.push({
43+
type: 'google',
44+
apiKey: process.env['GOOGLE_API_KEY'],
45+
searchEngineId: process.env['GOOGLE_SEARCH_ENGINE_ID'],
46+
});
47+
}
48+
49+
if (providers.length > 0) {
50+
webSearchSettings.webSearch = {
51+
provider: providers,
52+
default: providers[0]?.type,
53+
};
54+
}
55+
56+
await rig.setup('should be able to search the web', {
57+
settings: webSearchSettings,
58+
});
2059

2160
let result;
2261
try {

packages/cli/src/config/config.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import { mcpCommand } from '../commands/mcp.js';
4242

4343
import { isWorkspaceTrusted } from './trustedFolders.js';
4444
import type { ExtensionEnablementManager } from './extensions/extensionEnablement.js';
45+
import { buildWebSearchConfig } from './webSearch.js';
4546

4647
// Simple console logger for now - replace with actual logger if available
4748
const logger = {
@@ -116,6 +117,9 @@ export interface CliArgs {
116117
proxy: string | undefined;
117118
includeDirectories: string[] | undefined;
118119
tavilyApiKey: string | undefined;
120+
googleApiKey: string | undefined;
121+
googleSearchEngineId: string | undefined;
122+
webSearchDefault: string | undefined;
119123
screenReader: boolean | undefined;
120124
vlmSwitchMode: string | undefined;
121125
useSmartEdit: boolean | undefined;
@@ -323,7 +327,20 @@ export async function parseArguments(settings: Settings): Promise<CliArgs> {
323327
})
324328
.option('tavily-api-key', {
325329
type: 'string',
326-
description: 'Tavily API key for web search functionality',
330+
description: 'Tavily API key for web search',
331+
})
332+
.option('google-api-key', {
333+
type: 'string',
334+
description: 'Google Custom Search API key',
335+
})
336+
.option('google-search-engine-id', {
337+
type: 'string',
338+
description: 'Google Custom Search Engine ID',
339+
})
340+
.option('web-search-default', {
341+
type: 'string',
342+
description:
343+
'Default web search provider (dashscope, tavily, google)',
327344
})
328345
.option('screen-reader', {
329346
type: 'boolean',
@@ -749,10 +766,11 @@ export async function loadCliConfig(
749766
: argv.openaiLogging) ?? false,
750767
},
751768
cliVersion: await getCliVersion(),
752-
tavilyApiKey:
753-
argv.tavilyApiKey ||
754-
settings.advanced?.tavilyApiKey ||
755-
process.env['TAVILY_API_KEY'],
769+
webSearch: buildWebSearchConfig(
770+
argv,
771+
settings,
772+
settings.security?.auth?.selectedType,
773+
),
756774
summarizeToolOutput: settings.model?.summarizeToolOutput,
757775
ideMode,
758776
chatCompression: settings.model?.chatCompression,

0 commit comments

Comments
 (0)