网淘吧来吧,欢迎您!

Integrate You.com web tools with Vercel AI SDK技能使用说明

2026-04-01 新闻来源:网淘吧 围观:14
电脑广告
手机广告

将AI SDK与You.com工具集成

使用以下工具将You.com工具添加到您的Vercel AI SDK应用程序的交互式工作流程@youdotcom-oss/ai-sdk-plugin

工作流程

  1. 询问:包管理器

    Integrate You.com web tools with Vercel AI SDK

    • 选择哪种包管理器?(npm、bun、yarn、pnpm)
    • 使用他们选择的包管理器安装包:
      npm install @youdotcom-oss/ai-sdk-plugin
      # or bun add @youdotcom-oss/ai-sdk-plugin
      # or yarn add @youdotcom-oss/ai-sdk-plugin
      # or pnpm add @youdotcom-oss/ai-sdk-plugin
      
  2. 询问:环境变量名称

    • 使用标准YDC_API_KEY
    • 还是自定义名称?(如果自定义,请获取名称)
    • 他们是否已在环境中设置?
    • 如果没有:引导他们从以下网址获取密钥https://you.com/platform/api-keys
  3. 询问:使用哪些AI SDK函数?

    • 他们是否使用generateText()
    • 他们是否使用streamText()
    • 两者都要?
  4. 询问:现有文件还是新文件?

    • 现有:询问要编辑哪个(哪些)文件
    • 新建:询问在何处创建文件以及如何命名
  5. 针对每个文件,询问:

    • 要添加哪些工具?
      • youSearch(网络搜索)
      • youExpress(AI代理)
      • youContents(内容提取)
      • 多个?(哪种组合?)
    • 使用generateText()还是streamText()在此文件中?
    • 使用哪个AI提供商模型?(以确定是否需要stopWhen)
  6. 参考集成示例

    完整的代码模式请参见下方的"集成示例"部分:

    • generateText() - 使用工具进行基本文本生成
    • streamText() - 与Web框架流式响应(Next.js, Express, React)
  7. 更新/创建文件

    针对每个文件:

    • 参考集成示例(根据其回答使用 generateText 或 streamText)
    • 添加所选工具的导入
    • 如果是现有文件:找到其 generateText/streamText 调用并添加工具对象
    • 如果是新文件:使用示例结构创建文件
    • 基于环境变量名的工具调用模式:
      • 标准YDC_API_KEY:youSearch()
      • 自定义名称:youSearch({ apiKey: process.env.CUSTOM_NAME })
    • 将所选工具添加到工具对象
    • 如果是 streamText + Anthropic:添加 stopWhen 参数

集成示例

generateText() - 基础文本生成

环境变量设置:

import { anthropic } from '@ai-sdk/anthropic';
import { generateText } from 'ai';
import { youContents, youExpress, youSearch } from '@youdotcom-oss/ai-sdk-plugin';

// Reads YDC_API_KEY from environment automatically
const result = await generateText({
  model: anthropic('claude-sonnet-4-5-20250929'),
  tools: {
    search: youSearch(),
  },
  prompt: 'What are the latest developments in quantum computing?',
});

console.log(result.text);

多工具:

const result = await generateText({
  model: anthropic('claude-sonnet-4-5-20250929'),
  tools: {
    search: youSearch(),      // Web search with citations
    agent: youExpress(),      // AI answers with web context
    extract: youContents(),   // Content extraction from URLs
  },
  prompt: 'Research quantum computing and summarize the key papers',
});

自定义API密钥:

const result = await generateText({
  model: anthropic('claude-sonnet-4-5-20250929'),
  tools: {
    search: youSearch({ apiKey: 'your-custom-key' }),
  },
  prompt: 'Your prompt here',
});

完整示例:

import { anthropic } from '@ai-sdk/anthropic';
import { generateText } from 'ai';
import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';

const main = async () => {
  try {
    const result = await generateText({
      model: anthropic('claude-sonnet-4-5-20250929'),
      tools: {
        search: youSearch(),
      },
      maxSteps: 5,
      prompt: 'What are the latest developments in quantum computing?',
    });

    console.log('Generated text:', result.text);
    console.log('\nTool calls:', result.steps.flatMap(s => s.toolCalls));
  } catch (error) {
    console.error('Error:', error);
    process.exit(1);
  }
};

main();

streamText() - 流式响应

基础流式处理与 stopWhen 模式:

import { anthropic } from '@ai-sdk/anthropic';
import { streamText, type StepResult } from 'ai';
import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';

// CRITICAL: Always use stopWhen for Anthropic streaming
// Anthropic's SDK requires explicit stop conditions
const stepCountIs = (n: number) => (stepResult: StepResult<any>) =>
  stepResult.stepNumber >= n;

const result = streamText({
  model: anthropic('claude-sonnet-4-5-20250929'),
  tools: { search: youSearch() },
  stopWhen: stepCountIs(3),  // Required for Anthropic
  prompt: 'What are the latest AI developments?',
});

// Consume stream
for await (const chunk of result.textStream) {
  process.stdout.write(chunk);
}

Next.js 集成(应用路由器):

// app/api/chat/route.ts
import { anthropic } from '@ai-sdk/anthropic';
import { streamText, type StepResult } from 'ai';
import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';

const stepCountIs = (n: number) => (stepResult: StepResult<any>) =>
  stepResult.stepNumber >= n;

export async function POST(req: Request) {
  const { prompt } = await req.json();

  const result = streamText({
    model: anthropic('claude-sonnet-4-5-20250929'),
    tools: { search: youSearch() },
    stopWhen: stepCountIs(5),
    prompt,
  });

  return result.toDataStreamResponse();
}

Express.js 集成:

// server.ts
import express from 'express';
import { anthropic } from '@ai-sdk/anthropic';
import { streamText, type StepResult } from 'ai';
import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';

const app = express();
app.use(express.json());

const stepCountIs = (n: number) => (stepResult: StepResult<any>) =>
  stepResult.stepNumber >= n;

app.post('/api/chat', async (req, res) => {
  const { prompt } = req.body;

  const result = streamText({
    model: anthropic('claude-sonnet-4-5-20250929'),
    tools: { search: youSearch() },
    stopWhen: stepCountIs(5),
    prompt,
  });

  res.setHeader('Content-Type', 'text/plain; charset=utf-8');
  res.setHeader('Transfer-Encoding', 'chunked');

  for await (const chunk of result.textStream) {
    res.write(chunk);
  }

  res.end();
});

app.listen(3000);

React 客户端(配合 Next.js):

// components/Chat.tsx
'use client';

import { useChat } from 'ai/react';

export default function Chat() {
  const { messages, input, handleInputChange, handleSubmit } = useChat({
    api: '/api/chat',
  });

  return (
    <div>
      {messages.map(m => (
        <div key={m.id}>
          <strong>{m.role}:</strong> {m.content}
        </div>
      ))}

      <form onSubmit={handleSubmit}>
        <input value={input} onChange={handleInputChange} />
        <button type="submit">Send</button>
      </form>
    </div>
  );
}

完整流式处理示例:

import { anthropic } from '@ai-sdk/anthropic';
import { streamText, type StepResult } from 'ai';
import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';

const stepCountIs = (n: number) => (stepResult: StepResult<any>) =>
  stepResult.stepNumber >= n;

const main = async () => {
  try {
    const result = streamText({
      model: anthropic('claude-sonnet-4-5-20250929'),
      tools: {
        search: youSearch(),
      },
      stopWhen: stepCountIs(3),
      prompt: 'What are the latest AI developments?',
    });

    // Stream to stdout
    console.log('Streaming response:\n');
    for await (const chunk of result.textStream) {
      process.stdout.write(chunk);
    }
    console.log('\n\nDone!');
  } catch (error) {
    console.error('Error:', error);
    process.exit(1);
  }
};

main();

工具调用模式

基于步骤2中的环境变量名称:

标准 YDC_API_KEY:

import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';

tools: {
  search: youSearch(),
}

自定义环境变量:

import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';

const apiKey = process.env.THEIR_CUSTOM_NAME;

tools: {
  search: youSearch({ apiKey }),
}

使用标准环境变量的多工具:

import { youSearch, youExpress, youContents } from '@youdotcom-oss/ai-sdk-plugin';

tools: {
  search: youSearch(),
  agent: youExpress(),
  extract: youContents(),
}

使用自定义环境变量的多工具:

import { youSearch, youExpress, youContents } from '@youdotcom-oss/ai-sdk-plugin';

const apiKey = process.env.THEIR_CUSTOM_NAME;

tools: {
  search: youSearch({ apiKey }),
  agent: youExpress({ apiKey }),
  extract: youContents({ apiKey }),
}

可用工具

youSearch

网络与新闻搜索 - 模型决定参数(查询、数量、国家等)

youExpress

具备网络上下文的AI代理 - 模型决定参数(输入、工具)

youContents

网页内容提取 - 模型决定参数(网址、格式)

关键集成模式

以上示例展示了:

  • 导入语句(AI SDK + 提供商 + You.com工具)
  • 环境变量验证(对新文件可选)
  • 基于环境变量的工具配置
  • 结合工具使用generateText/streamText
  • 结果处理(特别是streamText的textStream解构)
  • Anthropic流式处理模式(stopWhen: stepCountIs(3))
  • Web框架集成(Next.js, Express, React)

实施检查清单

针对每个正在更新/创建的文件:

  • 已添加选定工具的导入
  • 若使用自定义环境变量:已用正确名称声明变量
  • 已将tools对象添加到generateText/streamText
  • 每个选定工具已正确调用:
    • 标准环境:toolName()
    • 自定义环境:toolName({ apiKey })
  • 若使用streamText:已解构const { textStream } = ...
  • 如果 Anthropic + streamText: 已添加stopWhen: stepCountIs(3)

全局检查清单:

  • 使用他们的包管理器安装的包
  • 在他们的环境中设置的环境变量
  • 所有文件已更新/创建
  • 准备测试

常见问题

问题: "无法找到模块 @youdotcom-oss/ai-sdk-plugin"修复: 使用他们的包管理器安装

问题: "需要 YDC_API_KEY(或自定义名称)环境变量"修复: 在他们的环境中设置(获取密钥:https://you.com/platform/api-keys)

问题: "工具执行失败,错误代码 401"修复: 验证 API 密钥是否有效

问题:"响应不完整或缺失"修复方法:如果使用 streamText,请增加步骤数。从 3 开始,并根据需要逐步增加(请参阅 README 故障排除部分)

问题:"textStream 不可迭代"修复方法:使用解构赋值:const { textStream } = streamText(...)

问题:"自定义环境变量无效"修复方法:传递给每个工具:youSearch({ apiKey })

进阶:工具开发模式

适用于创建自定义 AI SDK 工具或为 @youdotcom-oss/ai-sdk-plugin 做贡献的开发者:

工具函数结构

每个工具函数遵循以下模式:

export const youToolName = (config: YouToolsConfig = {}) => {
  const apiKey = config.apiKey ?? process.env.YDC_API_KEY;

  return tool({
    description: 'Tool description for AI model',
    inputSchema: ZodSchema,
    execute: async (params) => {
      if (!apiKey) {
        throw new Error('YDC_API_KEY is required');
      }

      const response = await callApiUtility({
        params,
        YDC_API_KEY: apiKey,
        getUserAgent,
      });

      // Return raw API response for maximum flexibility
      return response;
    },
  });
};

输入模式支持智能查询

始终使用来自@youdotcom-oss/mcp的模式:

// ✅ Import from @youdotcom-oss/mcp
import { SearchQuerySchema } from '@youdotcom-oss/mcp';

export const youSearch = (config: YouToolsConfig = {}) => {
  return tool({
    description: '...',
    inputSchema: SearchQuerySchema,  // Enables AI to use all search parameters
    execute: async (params) => { ... },
  });
};

// ❌ Don't duplicate or simplify schemas
const MySearchSchema = z.object({ query: z.string() });  // Missing filters!

这为何重要:

  • 丰富的模式使AI能够使用高级查询参数(过滤器、时效性、国家等)
  • AI能够基于用户意图构建更智能的查询
  • 防止在多个包中重复定义模式
  • 确保与MCP服务器模式的一致性

API密钥处理

始终提供环境变量备选方案并在API调用前进行验证:

// ✅ Automatic environment variable fallback
const apiKey = config.apiKey ?? process.env.YDC_API_KEY;

// ✅ Check API key in execute function
execute: async (params) => {
  if (!apiKey) {
    throw new Error('YDC_API_KEY is required');
  }
  const response = await callApi(...);
}

响应格式

始终返回原始API响应以获得最大灵活性:

// ✅ Return raw API response
execute: async (params) => {
  const response = await fetchSearchResults({
    searchQuery: params,
    YDC_API_KEY: apiKey,
    getUserAgent,
  });

  return response;  // Raw response for maximum flexibility
}

// ❌ Don't format or transform responses
return {
  text: formatResponse(response),
  data: response,
};

为何采用原始响应?

  • 为AI SDK处理结果提供最大灵活性
  • 避免因格式化造成信息丢失
  • AI SDK处理展示层
  • 更易于调试(查看实际的API响应)

工具描述

编写能指导AI行为的描述:

// ✅ Clear guidance for AI model
description: 'Search the web for current information, news, articles, and content using You.com. Returns web results with snippets and news articles. Use this when you need up-to-date information or facts from the internet.'

// ❌ Too brief
description: 'Search the web'

附加资源

免责申明
部分文章来自各大搜索引擎,如有侵权,请与我联系删除。
打赏

文章底部电脑广告
手机广告位-内容正文底部

相关文章

您是本站第393649名访客 今日有1篇新文章/评论