web-search

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Web 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-search
Extract this skill package to the above path in your project.
Reference Scripts: Example test scripts are available in the
{project_path}/skills/web-search/scripts/
directory for quick testing and reference. See
{project_path}/skills/web-search/scripts/web_search.ts
for a working example.
推荐路径
{project_path}/skills/web-search
将此技能包解压到项目中的上述路径。
参考脚本:在
{project_path}/skills/web-search/scripts/
目录下提供了示例测试脚本,可用于快速测试和参考。工作示例请查看
{project_path}/skills/web-search/scripts/web_search.ts

Overview

概述

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
undefined
bash
undefined

Simple 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"}'
undefined
z-ai function -n web_search -a '{"query": "latest tech news"}'
undefined

Search with Custom Parameters

带自定义参数的搜索

bash
undefined
bash
undefined

Limit number of results

Limit number of results

z-ai function
-n web_search
-a '{"query": "machine learning", "num": 5}'
z-ai function
-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}'
undefined
z-ai function
-n web_search
-a '{"query": "cryptocurrency news", "num": 10, "recency_days": 7}'
undefined

Save Search Results

保存搜索结果

bash
undefined
bash
undefined

Save 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
z-ai function
-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
undefined
z-ai function
-n web_search
-a '{"query": "AI breakthroughs", "num": 3, "recency_days": 1}'
-o ai_news.json
undefined

Advanced Search Examples

高级搜索示例

bash
undefined
bash
undefined

Search for specific topics

Search for specific topics

z-ai function
-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

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
z-ai function
-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
undefined
z-ai function
-n web_search
-a '{"query": "tech industry updates", "recency_days": 1}'
-o today_tech.json
undefined

CLI Parameters

CLI参数

  • --name, -n
    : Required - Function name (use "web_search")
  • --args, -a
    : Required - JSON arguments object with:
    • query
      (string, required): Search keywords
    • num
      (number, optional): Number of results (default: 10)
    • recency_days
      (number, optional): Filter results from last N days
  • --output, -o <path>
    : Optional - Output file path (JSON format)
  • --name, -n
    必填 - 函数名称(使用"web_search")
  • --args, -a
    必填 - JSON参数对象,包含:
    • query
      (字符串,必填):搜索关键词
    • num
      (数字,可选):结果数量(默认值:10)
    • recency_days
      (数字,可选):过滤最近N天的结果
  • --output, -o <path>
    :可选 - 输出文件路径(JSON格式)

Search Result Structure

搜索结果结构

Each result contains:
  • url
    : Full URL of the result
  • name
    : Title of the page
  • snippet
    : Preview text/description
  • host_name
    : Domain name
  • rank
    : Result ranking
  • date
    : Publication/update date
  • favicon
    : Favicon URL
每个结果包含:
  • url
    :结果的完整URL
  • name
    :页面标题
  • snippet
    :预览文本/描述
  • host_name
    :域名
  • rank
    :结果排名
  • date
    :发布/更新日期
  • favicon
    :网站图标URL

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
SearchFunctionResultItem
with the following structure:
typescript
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
}
每个搜索结果都是
SearchFunctionResultItem
类型,结构如下:
typescript
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); // true
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); // true

4. 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

常见使用场景

  1. Real-time Information Retrieval: Get current news, stock prices, weather
  2. Research & Analysis: Gather information on specific topics
  3. Content Discovery: Find articles, tutorials, documentation
  4. Competitive Analysis: Research competitors and market trends
  5. Fact Checking: Verify information against web sources
  6. SEO & Content Research: Analyze search results for content strategy
  7. News Aggregation: Collect news from various sources
  8. Academic Research: Find papers, studies, and academic content
  1. 实时信息检索:获取最新新闻、股票价格、天气情况
  2. 研究与分析:收集特定主题的相关信息
  3. 内容发现:查找文章、教程、文档
  4. 竞品分析:研究竞争对手和市场趋势
  5. 事实核查:通过网络来源验证信息
  6. SEO与内容研究:分析搜索结果以制定内容策略
  7. 新闻聚合:从多个来源收集新闻
  8. 学术研究:查找论文、研究报告和学术内容

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

性能优化技巧

  1. Reuse SDK Instance: Create ZAI instance once and reuse across searches
  2. Implement Caching: Cache search results to reduce API calls
  3. Optimize Query Terms: Use specific, targeted queries for better results
  4. Limit Result Count: Request only the number of results you need
  5. Parallel Searches: Use Promise.all for multiple independent searches
  6. Result Filtering: Filter results on client side when possible
  1. 复用SDK实例:创建一次ZAI实例并在多次搜索中复用
  2. 实现缓存:缓存搜索结果以减少API调用
  3. 优化查询词:使用具体、针对性的查询词以获得更好的结果
  4. 限制结果数量:仅请求所需数量的结果
  5. 并行搜索:使用Promise.all处理多个独立搜索
  6. 结果过滤:尽可能在客户端过滤结果

Security Considerations

安全注意事项

  1. Input Validation: Sanitize and validate user search queries
  2. Rate Limiting: Implement rate limits to prevent abuse
  3. API Key Protection: Never expose SDK credentials in client-side code
  4. Result Filtering: Filter potentially harmful or inappropriate content
  5. URL Validation: Validate URLs before redirecting users
  6. Privacy: Don't log sensitive user search queries
  1. 输入验证:对用户的搜索查询进行清理和验证
  2. 速率限制:实现速率限制以防止滥用
  3. API密钥保护:切勿在客户端代码中暴露SDK凭证
  4. 结果过滤:过滤潜在有害或不当内容
  5. URL验证:在重定向用户前验证URL的有效性
  6. 隐私保护:不要记录用户的敏感搜索查询

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
    scripts/web_search.ts
    for a quick start example
  • 始终仅在后端代码中使用z-ai-web-dev-sdk
  • SDK已预先安装 - 请按照示例中的方式导入
  • 搜索结果以SearchFunctionResultItem对象数组的形式返回
  • 在生产环境中实现完善的错误处理和重试机制
  • 适当时缓存结果以减少API调用
  • 使用具体的查询词以获得更好的搜索结果
  • 在向用户展示前验证并过滤结果
  • 查看
    scripts/web_search.ts
    以获取快速入门示例