web-search
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWeb Search Skill
网页搜索技能
This skill guides the implementation of web search functionality using the z-ai-web-dev-sdk package, enabling applications to search the web and retrieve current information.
本技能指导如何使用z-ai-web-dev-sdk包实现网页搜索功能,让应用能够进行网页搜索并获取实时信息。
Installation Path
安装路径
Recommended Location:
{project_path}/skills/web-searchExtract this skill package to the above path in your project.
Reference Scripts: Example test scripts are available in the directory for quick testing and reference. See for a working example.
{project_path}/skills/web-search/scripts/{project_path}/skills/web-search/scripts/web_search.ts推荐路径:
{project_path}/skills/web-search将此技能包解压到项目中的上述路径。
参考脚本:在目录下提供了示例测试脚本,可用于快速测试和参考。工作示例请查看。
{project_path}/skills/web-search/scripts/{project_path}/skills/web-search/scripts/web_search.tsOverview
概述
The Web Search skill allows you to build applications that can search the internet, retrieve current information, and access real-time data from web sources.
IMPORTANT: z-ai-web-dev-sdk MUST be used in backend code only. Never use it in client-side code.
网页搜索技能允许你构建可搜索互联网、获取实时信息并从网络来源访问实时数据的应用。
重要提示:z-ai-web-dev-sdk仅可用于后端代码,切勿在客户端代码中使用。
Prerequisites
前置条件
The z-ai-web-dev-sdk package is already installed. Import it as shown in the examples below.
z-ai-web-dev-sdk包已安装。请按照以下示例导入它。
CLI Usage (For Simple Tasks)
CLI使用(适用于简单任务)
For simple web search queries, you can use the z-ai CLI instead of writing code. This is ideal for quick information retrieval, testing search functionality, or command-line automation.
对于简单的网页搜索查询,你可以使用z-ai CLI而无需编写代码。这非常适合快速信息检索、测试搜索功能或命令行自动化。
Basic Web Search
基础网页搜索
bash
undefinedbash
undefinedSimple search query
Simple search query
z-ai function --name "web_search" --args '{"query": "artificial intelligence"}'
z-ai function --name "web_search" --args '{"query": "artificial intelligence"}'
Using short options
Using short options
z-ai function -n web_search -a '{"query": "latest tech news"}'
undefinedz-ai function -n web_search -a '{"query": "latest tech news"}'
undefinedSearch with Custom Parameters
带自定义参数的搜索
bash
undefinedbash
undefinedLimit number of results
Limit number of results
z-ai function
-n web_search
-a '{"query": "machine learning", "num": 5}'
-n web_search
-a '{"query": "machine learning", "num": 5}'
z-ai function
-n web_search
-a '{"query": "machine learning", "num": 5}'
-n web_search
-a '{"query": "machine learning", "num": 5}'
Search with recency filter (results from last N days)
Search with recency filter (results from last N days)
z-ai function
-n web_search
-a '{"query": "cryptocurrency news", "num": 10, "recency_days": 7}'
-n web_search
-a '{"query": "cryptocurrency news", "num": 10, "recency_days": 7}'
undefinedz-ai function
-n web_search
-a '{"query": "cryptocurrency news", "num": 10, "recency_days": 7}'
-n web_search
-a '{"query": "cryptocurrency news", "num": 10, "recency_days": 7}'
undefinedSave Search Results
保存搜索结果
bash
undefinedbash
undefinedSave results to JSON file
Save results to JSON file
z-ai function
-n web_search
-a '{"query": "climate change research", "num": 5}'
-o search_results.json
-n web_search
-a '{"query": "climate change research", "num": 5}'
-o search_results.json
z-ai function
-n web_search
-a '{"query": "climate change research", "num": 5}'
-o search_results.json
-n web_search
-a '{"query": "climate change research", "num": 5}'
-o search_results.json
Recent news with file output
Recent news with file output
z-ai function
-n web_search
-a '{"query": "AI breakthroughs", "num": 3, "recency_days": 1}'
-o ai_news.json
-n web_search
-a '{"query": "AI breakthroughs", "num": 3, "recency_days": 1}'
-o ai_news.json
undefinedz-ai function
-n web_search
-a '{"query": "AI breakthroughs", "num": 3, "recency_days": 1}'
-o ai_news.json
-n web_search
-a '{"query": "AI breakthroughs", "num": 3, "recency_days": 1}'
-o ai_news.json
undefinedAdvanced Search Examples
高级搜索示例
bash
undefinedbash
undefinedSearch for specific topics
Search for specific topics
z-ai function
-n web_search
-a '{"query": "quantum computing applications", "num": 8}'
-o quantum.json
-n web_search
-a '{"query": "quantum computing applications", "num": 8}'
-o quantum.json
z-ai function
-n web_search
-a '{"query": "quantum computing applications", "num": 8}'
-o quantum.json
-n web_search
-a '{"query": "quantum computing applications", "num": 8}'
-o quantum.json
Find recent scientific papers
Find recent scientific papers
z-ai function
-n web_search
-a '{"query": "genomics research", "num": 5, "recency_days": 30}'
-o genomics.json
-n web_search
-a '{"query": "genomics research", "num": 5, "recency_days": 30}'
-o genomics.json
z-ai function
-n web_search
-a '{"query": "genomics research", "num": 5, "recency_days": 30}'
-o genomics.json
-n web_search
-a '{"query": "genomics research", "num": 5, "recency_days": 30}'
-o genomics.json
Technology news from last 24 hours
Technology news from last 24 hours
z-ai function
-n web_search
-a '{"query": "tech industry updates", "recency_days": 1}'
-o today_tech.json
-n web_search
-a '{"query": "tech industry updates", "recency_days": 1}'
-o today_tech.json
undefinedz-ai function
-n web_search
-a '{"query": "tech industry updates", "recency_days": 1}'
-o today_tech.json
-n web_search
-a '{"query": "tech industry updates", "recency_days": 1}'
-o today_tech.json
undefinedCLI Parameters
CLI参数
- : Required - Function name (use "web_search")
--name, -n - : Required - JSON arguments object with:
--args, -a- (string, required): Search keywords
query - (number, optional): Number of results (default: 10)
num - (number, optional): Filter results from last N days
recency_days
- : Optional - Output file path (JSON format)
--output, -o <path>
- :必填 - 函数名称(使用"web_search")
--name, -n - :必填 - JSON参数对象,包含:
--args, -a- (字符串,必填):搜索关键词
query - (数字,可选):结果数量(默认值:10)
num - (数字,可选):过滤最近N天的结果
recency_days
- :可选 - 输出文件路径(JSON格式)
--output, -o <path>
Search Result Structure
搜索结果结构
Each result contains:
- : Full URL of the result
url - : Title of the page
name - : Preview text/description
snippet - : Domain name
host_name - : Result ranking
rank - : Publication/update date
date - : Favicon URL
favicon
每个结果包含:
- :结果的完整URL
url - :页面标题
name - :预览文本/描述
snippet - :域名
host_name - :结果排名
rank - :发布/更新日期
date - :网站图标URL
favicon
When to Use CLI vs SDK
CLI与SDK的使用场景对比
Use CLI for:
- Quick information lookups
- Testing search queries
- Simple automation scripts
- One-off research tasks
Use SDK for:
- Dynamic search in applications
- Multi-step search workflows
- Custom result processing and filtering
- Production applications with complex logic
使用CLI的场景:
- 快速信息查询
- 测试搜索查询
- 简单自动化脚本
- 一次性研究任务
使用SDK的场景:
- 应用中的动态搜索
- 多步骤搜索工作流
- 自定义结果处理和过滤
- 具有复杂逻辑的生产应用
Search Result Type
搜索结果类型
Each search result is a with the following structure:
SearchFunctionResultItemtypescript
interface SearchFunctionResultItem {
url: string; // Full URL of the result
name: string; // Title of the page
snippet: string; // Preview text/description
host_name: string; // Domain name
rank: number; // Result ranking
date: string; // Publication/update date
favicon: string; // Favicon URL
}每个搜索结果都是类型,结构如下:
SearchFunctionResultItemtypescript
interface SearchFunctionResultItem {
url: string; // Full URL of the result
name: string; // Title of the page
snippet: string; // Preview text/description
host_name: string; // Domain name
rank: number; // Result ranking
date: string; // Publication/update date
favicon: string; // Favicon URL
}Basic Web Search
基础网页搜索
Simple Search Query
简单搜索查询
javascript
import ZAI from 'z-ai-web-dev-sdk';
async function searchWeb(query) {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
return results;
}
// Usage
const searchResults = await searchWeb('What is the capital of France?');
console.log('Search Results:', searchResults);javascript
import ZAI from 'z-ai-web-dev-sdk';
async function searchWeb(query) {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
return results;
}
// Usage
const searchResults = await searchWeb('What is the capital of France?');
console.log('Search Results:', searchResults);Search with Custom Result Count
带自定义结果数量的搜索
javascript
import ZAI from 'z-ai-web-dev-sdk';
async function searchWithLimit(query, numberOfResults) {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: numberOfResults
});
return results;
}
// Usage - Get top 5 results
const topResults = await searchWithLimit('artificial intelligence news', 5);
// Usage - Get top 20 results
const moreResults = await searchWithLimit('JavaScript frameworks', 20);javascript
import ZAI from 'z-ai-web-dev-sdk';
async function searchWithLimit(query, numberOfResults) {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: numberOfResults
});
return results;
}
// Usage - Get top 5 results
const topResults = await searchWithLimit('artificial intelligence news', 5);
// Usage - Get top 20 results
const moreResults = await searchWithLimit('JavaScript frameworks', 20);Formatted Search Results
格式化搜索结果
javascript
import ZAI from 'z-ai-web-dev-sdk';
async function getFormattedResults(query) {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
// Format results for display
const formatted = results.map((item, index) => ({
position: index + 1,
title: item.name,
url: item.url,
description: item.snippet,
domain: item.host_name,
publishDate: item.date
}));
return formatted;
}
// Usage
const results = await getFormattedResults('climate change solutions');
results.forEach(result => {
console.log(`${result.position}. ${result.title}`);
console.log(` ${result.url}`);
console.log(` ${result.description}`);
console.log('');
});javascript
import ZAI from 'z-ai-web-dev-sdk';
async function getFormattedResults(query) {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
// Format results for display
const formatted = results.map((item, index) => ({
position: index + 1,
title: item.name,
url: item.url,
description: item.snippet,
domain: item.host_name,
publishDate: item.date
}));
return formatted;
}
// Usage
const results = await getFormattedResults('climate change solutions');
results.forEach(result => {
console.log(`${result.position}. ${result.title}`);
console.log(` ${result.url}`);
console.log(` ${result.description}`);
console.log('');
});Advanced Use Cases
高级使用场景
Search with Result Processing
带结果处理的搜索
javascript
import ZAI from 'z-ai-web-dev-sdk';
class SearchProcessor {
constructor() {
this.zai = null;
}
async initialize() {
this.zai = await ZAI.create();
}
async search(query, options = {}) {
const {
num = 10,
filterDomain = null,
minSnippetLength = 0
} = options;
const results = await this.zai.functions.invoke('web_search', {
query: query,
num: num
});
// Filter results
let filtered = results;
if (filterDomain) {
filtered = filtered.filter(item =>
item.host_name.includes(filterDomain)
);
}
if (minSnippetLength > 0) {
filtered = filtered.filter(item =>
item.snippet.length >= minSnippetLength
);
}
return filtered;
}
extractDomains(results) {
return [...new Set(results.map(item => item.host_name))];
}
groupByDomain(results) {
const grouped = {};
results.forEach(item => {
if (!grouped[item.host_name]) {
grouped[item.host_name] = [];
}
grouped[item.host_name].push(item);
});
return grouped;
}
sortByDate(results, ascending = false) {
return results.sort((a, b) => {
const dateA = new Date(a.date);
const dateB = new Date(b.date);
return ascending ? dateA - dateB : dateB - dateA;
});
}
}
// Usage
const processor = new SearchProcessor();
await processor.initialize();
const results = await processor.search('machine learning tutorials', {
num: 15,
minSnippetLength: 50
});
console.log('Domains found:', processor.extractDomains(results));
console.log('Grouped by domain:', processor.groupByDomain(results));
console.log('Sorted by date:', processor.sortByDate(results));javascript
import ZAI from 'z-ai-web-dev-sdk';
class SearchProcessor {
constructor() {
this.zai = null;
}
async initialize() {
this.zai = await ZAI.create();
}
async search(query, options = {}) {
const {
num = 10,
filterDomain = null,
minSnippetLength = 0
} = options;
const results = await this.zai.functions.invoke('web_search', {
query: query,
num: num
});
// Filter results
let filtered = results;
if (filterDomain) {
filtered = filtered.filter(item =>
item.host_name.includes(filterDomain)
);
}
if (minSnippetLength > 0) {
filtered = filtered.filter(item =>
item.snippet.length >= minSnippetLength
);
}
return filtered;
}
extractDomains(results) {
return [...new Set(results.map(item => item.host_name))];
}
groupByDomain(results) {
const grouped = {};
results.forEach(item => {
if (!grouped[item.host_name]) {
grouped[item.host_name] = [];
}
grouped[item.host_name].push(item);
});
return grouped;
}
sortByDate(results, ascending = false) {
return results.sort((a, b) => {
const dateA = new Date(a.date);
const dateB = new Date(b.date);
return ascending ? dateA - dateB : dateB - dateA;
});
}
}
// Usage
const processor = new SearchProcessor();
await processor.initialize();
const results = await processor.search('machine learning tutorials', {
num: 15,
minSnippetLength: 50
});
console.log('Domains found:', processor.extractDomains(results));
console.log('Grouped by domain:', processor.groupByDomain(results));
console.log('Sorted by date:', processor.sortByDate(results));News Search
新闻搜索
javascript
import ZAI from 'z-ai-web-dev-sdk';
async function searchNews(topic, timeframe = 'recent') {
const zai = await ZAI.create();
// Add time-based keywords to query
const timeKeywords = {
recent: 'latest news',
today: 'today news',
week: 'this week news',
month: 'this month news'
};
const query = `${topic} ${timeKeywords[timeframe] || timeKeywords.recent}`;
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
// Sort by date (most recent first)
const sortedResults = results.sort((a, b) => {
return new Date(b.date) - new Date(a.date);
});
return sortedResults;
}
// Usage
const aiNews = await searchNews('artificial intelligence', 'today');
const techNews = await searchNews('technology', 'week');
console.log('Latest AI News:');
aiNews.forEach(item => {
console.log(`${item.name} (${item.date})`);
console.log(`${item.snippet}\n`);
});javascript
import ZAI from 'z-ai-web-dev-sdk';
async function searchNews(topic, timeframe = 'recent') {
const zai = await ZAI.create();
// Add time-based keywords to query
const timeKeywords = {
recent: 'latest news',
today: 'today news',
week: 'this week news',
month: 'this month news'
};
const query = `${topic} ${timeKeywords[timeframe] || timeKeywords.recent}`;
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
// Sort by date (most recent first)
const sortedResults = results.sort((a, b) => {
return new Date(b.date) - new Date(a.date);
});
return sortedResults;
}
// Usage
const aiNews = await searchNews('artificial intelligence', 'today');
const techNews = await searchNews('technology', 'week');
console.log('Latest AI News:');
aiNews.forEach(item => {
console.log(`${item.name} (${item.date})`);
console.log(`${item.snippet}\n`);
});Research Assistant
研究助手
javascript
import ZAI from 'z-ai-web-dev-sdk';
class ResearchAssistant {
constructor() {
this.zai = null;
}
async initialize() {
this.zai = await ZAI.create();
}
async researchTopic(topic, depth = 'standard') {
const numResults = {
quick: 5,
standard: 10,
deep: 20
};
const results = await this.zai.functions.invoke('web_search', {
query: topic,
num: numResults[depth] || 10
});
// Analyze results
const analysis = {
topic: topic,
totalResults: results.length,
sources: this.extractDomains(results),
topResults: results.slice(0, 5).map(r => ({
title: r.name,
url: r.url,
summary: r.snippet
})),
dateRange: this.getDateRange(results)
};
return analysis;
}
extractDomains(results) {
const domains = {};
results.forEach(item => {
domains[item.host_name] = (domains[item.host_name] || 0) + 1;
});
return domains;
}
getDateRange(results) {
const dates = results
.map(r => new Date(r.date))
.filter(d => !isNaN(d));
if (dates.length === 0) return null;
return {
earliest: new Date(Math.min(...dates)),
latest: new Date(Math.max(...dates))
};
}
async compareTopics(topic1, topic2) {
const [results1, results2] = await Promise.all([
this.zai.functions.invoke('web_search', { query: topic1, num: 10 }),
this.zai.functions.invoke('web_search', { query: topic2, num: 10 })
]);
const domains1 = new Set(results1.map(r => r.host_name));
const domains2 = new Set(results2.map(r => r.host_name));
const commonDomains = [...domains1].filter(d => domains2.has(d));
return {
topic1: {
name: topic1,
results: results1.length,
uniqueDomains: domains1.size
},
topic2: {
name: topic2,
results: results2.length,
uniqueDomains: domains2.size
},
commonDomains: commonDomains
};
}
}
// Usage
const assistant = new ResearchAssistant();
await assistant.initialize();
const research = await assistant.researchTopic('quantum computing', 'deep');
console.log('Research Analysis:', research);
const comparison = await assistant.compareTopics(
'renewable energy',
'solar power'
);
console.log('Topic Comparison:', comparison);javascript
import ZAI from 'z-ai-web-dev-sdk';
class ResearchAssistant {
constructor() {
this.zai = null;
}
async initialize() {
this.zai = await ZAI.create();
}
async researchTopic(topic, depth = 'standard') {
const numResults = {
quick: 5,
standard: 10,
deep: 20
};
const results = await this.zai.functions.invoke('web_search', {
query: topic,
num: numResults[depth] || 10
});
// Analyze results
const analysis = {
topic: topic,
totalResults: results.length,
sources: this.extractDomains(results),
topResults: results.slice(0, 5).map(r => ({
title: r.name,
url: r.url,
summary: r.snippet
})),
dateRange: this.getDateRange(results)
};
return analysis;
}
extractDomains(results) {
const domains = {};
results.forEach(item => {
domains[item.host_name] = (domains[item.host_name] || 0) + 1;
});
return domains;
}
getDateRange(results) {
const dates = results
.map(r => new Date(r.date))
.filter(d => !isNaN(d));
if (dates.length === 0) return null;
return {
earliest: new Date(Math.min(...dates)),
latest: new Date(Math.max(...dates))
};
}
async compareTopics(topic1, topic2) {
const [results1, results2] = await Promise.all([
this.zai.functions.invoke('web_search', { query: topic1, num: 10 }),
this.zai.functions.invoke('web_search', { query: topic2, num: 10 })
]);
const domains1 = new Set(results1.map(r => r.host_name));
const domains2 = new Set(results2.map(r => r.host_name));
const commonDomains = [...domains1].filter(d => domains2.has(d));
return {
topic1: {
name: topic1,
results: results1.length,
uniqueDomains: domains1.size
},
topic2: {
name: topic2,
results: results2.length,
uniqueDomains: domains2.size
},
commonDomains: commonDomains
};
}
}
// Usage
const assistant = new ResearchAssistant();
await assistant.initialize();
const research = await assistant.researchTopic('quantum computing', 'deep');
console.log('Research Analysis:', research);
const comparison = await assistant.compareTopics(
'renewable energy',
'solar power'
);
console.log('Topic Comparison:', comparison);Search Result Validation
搜索结果验证
javascript
import ZAI from 'z-ai-web-dev-sdk';
async function validateSearchResults(query) {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
// Validate and score results
const validated = results.map(item => {
let score = 0;
let flags = [];
// Check snippet quality
if (item.snippet && item.snippet.length > 50) {
score += 20;
} else {
flags.push('short_snippet');
}
// Check date availability
if (item.date && item.date !== 'N/A') {
score += 20;
} else {
flags.push('no_date');
}
// Check URL validity
try {
new URL(item.url);
score += 20;
} catch (e) {
flags.push('invalid_url');
}
// Check domain quality (not perfect, but basic check)
if (!item.host_name.includes('spam') &&
!item.host_name.includes('ads')) {
score += 20;
} else {
flags.push('suspicious_domain');
}
// Check title quality
if (item.name && item.name.length > 10) {
score += 20;
} else {
flags.push('short_title');
}
return {
...item,
qualityScore: score,
validationFlags: flags,
isHighQuality: score >= 80
};
});
// Sort by quality score
return validated.sort((a, b) => b.qualityScore - a.qualityScore);
}
// Usage
const validated = await validateSearchResults('best programming practices');
console.log('High quality results:',
validated.filter(r => r.isHighQuality).length
);javascript
import ZAI from 'z-ai-web-dev-sdk';
async function validateSearchResults(query) {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
// Validate and score results
const validated = results.map(item => {
let score = 0;
let flags = [];
// Check snippet quality
if (item.snippet && item.snippet.length > 50) {
score += 20;
} else {
flags.push('short_snippet');
}
// Check date availability
if (item.date && item.date !== 'N/A') {
score += 20;
} else {
flags.push('no_date');
}
// Check URL validity
try {
new URL(item.url);
score += 20;
} catch (e) {
flags.push('invalid_url');
}
// Check domain quality (not perfect, but basic check)
if (!item.host_name.includes('spam') &&
!item.host_name.includes('ads')) {
score += 20;
} else {
flags.push('suspicious_domain');
}
// Check title quality
if (item.name && item.name.length > 10) {
score += 20;
} else {
flags.push('short_title');
}
return {
...item,
qualityScore: score,
validationFlags: flags,
isHighQuality: score >= 80
};
});
// Sort by quality score
return validated.sort((a, b) => b.qualityScore - a.qualityScore);
}
// Usage
const validated = await validateSearchResults('best programming practices');
console.log('High quality results:',
validated.filter(r => r.isHighQuality).length
);Best Practices
最佳实践
1. Query Optimization
1. 查询优化
javascript
// Bad: Too vague
const bad = await searchWeb('information');
// Good: Specific and targeted
const good = await searchWeb('JavaScript async/await best practices 2024');
// Good: Include context
const goodWithContext = await searchWeb('React hooks tutorial for beginners');javascript
// Bad: Too vague
const bad = await searchWeb('information');
// Good: Specific and targeted
const good = await searchWeb('JavaScript async/await best practices 2024');
// Good: Include context
const goodWithContext = await searchWeb('React hooks tutorial for beginners');2. Error Handling
2. 错误处理
javascript
import ZAI from 'z-ai-web-dev-sdk';
async function safeSearch(query, retries = 3) {
let lastError;
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
if (!Array.isArray(results) || results.length === 0) {
throw new Error('No results found or invalid response');
}
return {
success: true,
results: results,
attempts: attempt
};
} catch (error) {
lastError = error;
console.error(`Attempt ${attempt} failed:`, error.message);
if (attempt < retries) {
// Wait before retry (exponential backoff)
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
}
return {
success: false,
error: lastError.message,
attempts: retries
};
}javascript
import ZAI from 'z-ai-web-dev-sdk';
async function safeSearch(query, retries = 3) {
let lastError;
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const zai = await ZAI.create();
const results = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
if (!Array.isArray(results) || results.length === 0) {
throw new Error('No results found or invalid response');
}
return {
success: true,
results: results,
attempts: attempt
};
} catch (error) {
lastError = error;
console.error(`Attempt ${attempt} failed:`, error.message);
if (attempt < retries) {
// Wait before retry (exponential backoff)
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
}
return {
success: false,
error: lastError.message,
attempts: retries
};
}3. Result Caching
3. 结果缓存
javascript
import ZAI from 'z-ai-web-dev-sdk';
class CachedSearch {
constructor(cacheDuration = 3600000) { // 1 hour default
this.cache = new Map();
this.cacheDuration = cacheDuration;
this.zai = null;
}
async initialize() {
this.zai = await ZAI.create();
}
getCacheKey(query, num) {
return `${query}_${num}`;
}
async search(query, num = 10) {
const cacheKey = this.getCacheKey(query, num);
const cached = this.cache.get(cacheKey);
// Check if cached and not expired
if (cached && Date.now() - cached.timestamp < this.cacheDuration) {
console.log('Returning cached results');
return {
...cached.data,
cached: true
};
}
// Perform fresh search
const results = await this.zai.functions.invoke('web_search', {
query: query,
num: num
});
// Cache results
this.cache.set(cacheKey, {
data: results,
timestamp: Date.now()
});
return {
results: results,
cached: false
};
}
clearCache() {
this.cache.clear();
}
getCacheSize() {
return this.cache.size;
}
}
// Usage
const search = new CachedSearch(1800000); // 30 minutes cache
await search.initialize();
const result1 = await search.search('TypeScript tutorial');
console.log('Cached:', result1.cached); // false
const result2 = await search.search('TypeScript tutorial');
console.log('Cached:', result2.cached); // truejavascript
import ZAI from 'z-ai-web-dev-sdk';
class CachedSearch {
constructor(cacheDuration = 3600000) { // 1 hour default
this.cache = new Map();
this.cacheDuration = cacheDuration;
this.zai = null;
}
async initialize() {
this.zai = await ZAI.create();
}
getCacheKey(query, num) {
return `${query}_${num}`;
}
async search(query, num = 10) {
const cacheKey = this.getCacheKey(query, num);
const cached = this.cache.get(cacheKey);
// Check if cached and not expired
if (cached && Date.now() - cached.timestamp < this.cacheDuration) {
console.log('Returning cached results');
return {
...cached.data,
cached: true
};
}
// Perform fresh search
const results = await this.zai.functions.invoke('web_search', {
query: query,
num: num
});
// Cache results
this.cache.set(cacheKey, {
data: results,
timestamp: Date.now()
});
return {
results: results,
cached: false
};
}
clearCache() {
this.cache.clear();
}
getCacheSize() {
return this.cache.size;
}
}
// Usage
const search = new CachedSearch(1800000); // 30 minutes cache
await search.initialize();
const result1 = await search.search('TypeScript tutorial');
console.log('Cached:', result1.cached); // false
const result2 = await search.search('TypeScript tutorial');
console.log('Cached:', result2.cached); // true4. Rate Limiting
4. 速率限制
javascript
class RateLimitedSearch {
constructor(requestsPerMinute = 60) {
this.zai = null;
this.requestsPerMinute = requestsPerMinute;
this.requests = [];
}
async initialize() {
this.zai = await ZAI.create();
}
async search(query, num = 10) {
await this.checkRateLimit();
const results = await this.zai.functions.invoke('web_search', {
query: query,
num: num
});
this.requests.push(Date.now());
return results;
}
async checkRateLimit() {
const now = Date.now();
const oneMinuteAgo = now - 60000;
// Remove requests older than 1 minute
this.requests = this.requests.filter(time => time > oneMinuteAgo);
if (this.requests.length >= this.requestsPerMinute) {
const oldestRequest = this.requests[0];
const waitTime = 60000 - (now - oldestRequest);
console.log(`Rate limit reached. Waiting ${waitTime}ms`);
await new Promise(resolve => setTimeout(resolve, waitTime));
// Recheck after waiting
return this.checkRateLimit();
}
}
}javascript
class RateLimitedSearch {
constructor(requestsPerMinute = 60) {
this.zai = null;
this.requestsPerMinute = requestsPerMinute;
this.requests = [];
}
async initialize() {
this.zai = await ZAI.create();
}
async search(query, num = 10) {
await this.checkRateLimit();
const results = await this.zai.functions.invoke('web_search', {
query: query,
num: num
});
this.requests.push(Date.now());
return results;
}
async checkRateLimit() {
const now = Date.now();
const oneMinuteAgo = now - 60000;
// Remove requests older than 1 minute
this.requests = this.requests.filter(time => time > oneMinuteAgo);
if (this.requests.length >= this.requestsPerMinute) {
const oldestRequest = this.requests[0];
const waitTime = 60000 - (now - oldestRequest);
console.log(`Rate limit reached. Waiting ${waitTime}ms`);
await new Promise(resolve => setTimeout(resolve, waitTime));
// Recheck after waiting
return this.checkRateLimit();
}
}
}Common Use Cases
常见使用场景
- Real-time Information Retrieval: Get current news, stock prices, weather
- Research & Analysis: Gather information on specific topics
- Content Discovery: Find articles, tutorials, documentation
- Competitive Analysis: Research competitors and market trends
- Fact Checking: Verify information against web sources
- SEO & Content Research: Analyze search results for content strategy
- News Aggregation: Collect news from various sources
- Academic Research: Find papers, studies, and academic content
- 实时信息检索:获取最新新闻、股票价格、天气情况
- 研究与分析:收集特定主题的相关信息
- 内容发现:查找文章、教程、文档
- 竞品分析:研究竞争对手和市场趋势
- 事实核查:通过网络来源验证信息
- SEO与内容研究:分析搜索结果以制定内容策略
- 新闻聚合:从多个来源收集新闻
- 学术研究:查找论文、研究报告和学术内容
Integration Examples
集成示例
Express.js Search API
Express.js搜索API
javascript
import express from 'express';
import ZAI from 'z-ai-web-dev-sdk';
const app = express();
app.use(express.json());
let zaiInstance;
async function initZAI() {
zaiInstance = await ZAI.create();
}
app.get('/api/search', async (req, res) => {
try {
const { q: query, num = 10 } = req.query;
if (!query) {
return res.status(400).json({ error: 'Query parameter "q" is required' });
}
const numResults = Math.min(parseInt(num) || 10, 20);
const results = await zaiInstance.functions.invoke('web_search', {
query: query,
num: numResults
});
res.json({
success: true,
query: query,
totalResults: results.length,
results: results
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
app.get('/api/search/news', async (req, res) => {
try {
const { topic, timeframe = 'recent' } = req.query;
if (!topic) {
return res.status(400).json({ error: 'Topic parameter is required' });
}
const timeKeywords = {
recent: 'latest news',
today: 'today news',
week: 'this week news'
};
const query = `${topic} ${timeKeywords[timeframe] || timeKeywords.recent}`;
const results = await zaiInstance.functions.invoke('web_search', {
query: query,
num: 15
});
// Sort by date
const sortedResults = results.sort((a, b) => {
return new Date(b.date) - new Date(a.date);
});
res.json({
success: true,
topic: topic,
timeframe: timeframe,
results: sortedResults
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
initZAI().then(() => {
app.listen(3000, () => {
console.log('Search API running on port 3000');
});
});javascript
import express from 'express';
import ZAI from 'z-ai-web-dev-sdk';
const app = express();
app.use(express.json());
let zaiInstance;
async function initZAI() {
zaiInstance = await ZAI.create();
}
app.get('/api/search', async (req, res) => {
try {
const { q: query, num = 10 } = req.query;
if (!query) {
return res.status(400).json({ error: 'Query parameter "q" is required' });
}
const numResults = Math.min(parseInt(num) || 10, 20);
const results = await zaiInstance.functions.invoke('web_search', {
query: query,
num: numResults
});
res.json({
success: true,
query: query,
totalResults: results.length,
results: results
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
app.get('/api/search/news', async (req, res) => {
try {
const { topic, timeframe = 'recent' } = req.query;
if (!topic) {
return res.status(400).json({ error: 'Topic parameter is required' });
}
const timeKeywords = {
recent: 'latest news',
today: 'today news',
week: 'this week news'
};
const query = `${topic} ${timeKeywords[timeframe] || timeKeywords.recent}`;
const results = await zaiInstance.functions.invoke('web_search', {
query: query,
num: 15
});
// Sort by date
const sortedResults = results.sort((a, b) => {
return new Date(b.date) - new Date(a.date);
});
res.json({
success: true,
topic: topic,
timeframe: timeframe,
results: sortedResults
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
initZAI().then(() => {
app.listen(3000, () => {
console.log('Search API running on port 3000');
});
});Search with AI Summary
带AI摘要的搜索
javascript
import ZAI from 'z-ai-web-dev-sdk';
async function searchAndSummarize(query) {
const zai = await ZAI.create();
// Step 1: Search the web
const searchResults = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
// Step 2: Create summary using chat completions
const searchContext = searchResults
.slice(0, 5)
.map((r, i) => `${i + 1}. ${r.name}\n${r.snippet}`)
.join('\n\n');
const completion = await zai.chat.completions.create({
messages: [
{
role: 'assistant',
content: 'You are a research assistant. Summarize search results clearly and concisely.'
},
{
role: 'user',
content: `Query: "${query}"\n\nSearch Results:\n${searchContext}\n\nProvide a comprehensive summary of these results.`
}
],
thinking: { type: 'disabled' }
});
const summary = completion.choices[0]?.message?.content;
return {
query: query,
summary: summary,
sources: searchResults.slice(0, 5).map(r => ({
title: r.name,
url: r.url
})),
totalResults: searchResults.length
};
}
// Usage
const result = await searchAndSummarize('benefits of renewable energy');
console.log('Summary:', result.summary);
console.log('Sources:', result.sources);javascript
import ZAI from 'z-ai-web-dev-sdk';
async function searchAndSummarize(query) {
const zai = await ZAI.create();
// Step 1: Search the web
const searchResults = await zai.functions.invoke('web_search', {
query: query,
num: 10
});
// Step 2: Create summary using chat completions
const searchContext = searchResults
.slice(0, 5)
.map((r, i) => `${i + 1}. ${r.name}\n${r.snippet}`)
.join('\n\n');
const completion = await zai.chat.completions.create({
messages: [
{
role: 'assistant',
content: 'You are a research assistant. Summarize search results clearly and concisely.'
},
{
role: 'user',
content: `Query: "${query}"\n\nSearch Results:\n${searchContext}\n\nProvide a comprehensive summary of these results.`
}
],
thinking: { type: 'disabled' }
});
const summary = completion.choices[0]?.message?.content;
return {
query: query,
summary: summary,
sources: searchResults.slice(0, 5).map(r => ({
title: r.name,
url: r.url
})),
totalResults: searchResults.length
};
}
// Usage
const result = await searchAndSummarize('benefits of renewable energy');
console.log('Summary:', result.summary);
console.log('Sources:', result.sources);Troubleshooting
故障排除
Issue: "SDK must be used in backend"
- Solution: Ensure z-ai-web-dev-sdk is only imported and used in server-side code
Issue: Empty or no results returned
- Solution: Try different query terms, check internet connectivity, verify API status
Issue: Unexpected response format
- Solution: Verify the response is an array, check for API changes, add type validation
Issue: Rate limiting errors
- Solution: Implement request throttling, add delays between searches, use caching
Issue: Low quality search results
- Solution: Refine query terms, filter results by domain or date, validate result quality
问题:"SDK must be used in backend"
- 解决方案:确保仅在服务器端代码中导入和使用z-ai-web-dev-sdk
问题:返回空结果或无结果
- 解决方案:尝试使用不同的查询词,检查网络连接,验证API状态
问题:响应格式不符合预期
- 解决方案:验证响应是否为数组,检查是否有API变更,添加类型验证
问题:速率限制错误
- 解决方案:实现请求限流,在搜索之间添加延迟,使用缓存
问题:搜索结果质量低
- 解决方案:优化查询词,按域名或日期过滤结果,验证结果质量
Performance Tips
性能优化技巧
- Reuse SDK Instance: Create ZAI instance once and reuse across searches
- Implement Caching: Cache search results to reduce API calls
- Optimize Query Terms: Use specific, targeted queries for better results
- Limit Result Count: Request only the number of results you need
- Parallel Searches: Use Promise.all for multiple independent searches
- Result Filtering: Filter results on client side when possible
- 复用SDK实例:创建一次ZAI实例并在多次搜索中复用
- 实现缓存:缓存搜索结果以减少API调用
- 优化查询词:使用具体、针对性的查询词以获得更好的结果
- 限制结果数量:仅请求所需数量的结果
- 并行搜索:使用Promise.all处理多个独立搜索
- 结果过滤:尽可能在客户端过滤结果
Security Considerations
安全注意事项
- Input Validation: Sanitize and validate user search queries
- Rate Limiting: Implement rate limits to prevent abuse
- API Key Protection: Never expose SDK credentials in client-side code
- Result Filtering: Filter potentially harmful or inappropriate content
- URL Validation: Validate URLs before redirecting users
- Privacy: Don't log sensitive user search queries
- 输入验证:对用户的搜索查询进行清理和验证
- 速率限制:实现速率限制以防止滥用
- API密钥保护:切勿在客户端代码中暴露SDK凭证
- 结果过滤:过滤潜在有害或不当内容
- URL验证:在重定向用户前验证URL的有效性
- 隐私保护:不要记录用户的敏感搜索查询
Remember
注意事项
- Always use z-ai-web-dev-sdk in backend code only
- The SDK is already installed - import as shown in examples
- Search results are returned as an array of SearchFunctionResultItem objects
- Implement proper error handling and retries for production
- Cache results when appropriate to reduce API calls
- Use specific query terms for better search results
- Validate and filter results before displaying to users
- Check for a quick start example
scripts/web_search.ts
- 始终仅在后端代码中使用z-ai-web-dev-sdk
- SDK已预先安装 - 请按照示例中的方式导入
- 搜索结果以SearchFunctionResultItem对象数组的形式返回
- 在生产环境中实现完善的错误处理和重试机制
- 适当时缓存结果以减少API调用
- 使用具体的查询词以获得更好的搜索结果
- 在向用户展示前验证并过滤结果
- 查看以获取快速入门示例
scripts/web_search.ts