feat: add tavily client

pull/643/head^2
Travis Fischer 2024-06-06 02:22:26 -05:00
rodzic 1961a26b4b
commit f7d6fae425
7 zmienionych plików z 210 dodań i 63 usunięć

Wyświetl plik

@ -2,6 +2,7 @@
import 'dotenv/config'
import restoreCursor from 'restore-cursor'
import { TavilyClient } from 'tavily'
// import { SearxngClient } from '../src/services/searxng-client.js'
// import { ClearbitClient } from '../src/index.js'
@ -17,7 +18,7 @@ import restoreCursor from 'restore-cursor'
// TwitterClient
// } from '../src/services/twitter/index.js'
// import { MidjourneyClient } from '../src/index.js'
import { BingClient } from '../src/index.js'
// import { BingClient } from '../src/index.js'
/**
* Scratch pad for testing.
@ -105,10 +106,16 @@ async function main() {
// )
// console.log(JSON.stringify(res, null, 2))
const bing = new BingClient()
const res = await bing.search({
q: 'world cup 2024 freestyle wrestling news'
})
// const bing = new BingClient()
// const res = await bing.search({
// q: 'world cup 2024 freestyle wrestling news'
// })
// console.log(JSON.stringify(res, null, 2))
const tavily = new TavilyClient()
const res = await tavily.search(
'when do experts predict that OpenAI will release GPT-5?'
)
console.log(JSON.stringify(res, null, 2))
}

Wyświetl plik

@ -5858,7 +5858,7 @@ snapshots:
'@aws-crypto/sha256-browser': 3.0.0
'@aws-crypto/sha256-js': 3.0.0
'@aws-sdk/client-sso-oidc': 3.590.0
'@aws-sdk/client-sts': 3.590.0
'@aws-sdk/client-sts': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)
'@aws-sdk/core': 3.588.0
'@aws-sdk/credential-provider-node': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0)
'@aws-sdk/middleware-host-header': 3.577.0
@ -5904,7 +5904,7 @@ snapshots:
'@aws-crypto/sha256-browser': 3.0.0
'@aws-crypto/sha256-js': 3.0.0
'@aws-sdk/client-sso-oidc': 3.590.0
'@aws-sdk/client-sts': 3.590.0
'@aws-sdk/client-sts': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)
'@aws-sdk/core': 3.588.0
'@aws-sdk/credential-provider-node': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0)
'@aws-sdk/middleware-host-header': 3.577.0
@ -5951,9 +5951,9 @@ snapshots:
dependencies:
'@aws-crypto/sha256-browser': 3.0.0
'@aws-crypto/sha256-js': 3.0.0
'@aws-sdk/client-sts': 3.590.0
'@aws-sdk/client-sts': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)
'@aws-sdk/core': 3.588.0
'@aws-sdk/credential-provider-node': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0(@aws-sdk/client-sso-oidc@3.590.0))
'@aws-sdk/credential-provider-node': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0)
'@aws-sdk/middleware-host-header': 3.577.0
'@aws-sdk/middleware-logger': 3.577.0
'@aws-sdk/middleware-recursion-detection': 3.577.0
@ -6035,58 +6035,13 @@ snapshots:
transitivePeerDependencies:
- aws-crt
'@aws-sdk/client-sts@3.590.0':
dependencies:
'@aws-crypto/sha256-browser': 3.0.0
'@aws-crypto/sha256-js': 3.0.0
'@aws-sdk/client-sso-oidc': 3.590.0
'@aws-sdk/core': 3.588.0
'@aws-sdk/credential-provider-node': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0)
'@aws-sdk/middleware-host-header': 3.577.0
'@aws-sdk/middleware-logger': 3.577.0
'@aws-sdk/middleware-recursion-detection': 3.577.0
'@aws-sdk/middleware-user-agent': 3.587.0
'@aws-sdk/region-config-resolver': 3.587.0
'@aws-sdk/types': 3.577.0
'@aws-sdk/util-endpoints': 3.587.0
'@aws-sdk/util-user-agent-browser': 3.577.0
'@aws-sdk/util-user-agent-node': 3.587.0
'@smithy/config-resolver': 3.0.1
'@smithy/core': 2.2.0
'@smithy/fetch-http-handler': 3.0.1
'@smithy/hash-node': 3.0.0
'@smithy/invalid-dependency': 3.0.0
'@smithy/middleware-content-length': 3.0.0
'@smithy/middleware-endpoint': 3.0.1
'@smithy/middleware-retry': 3.0.3
'@smithy/middleware-serde': 3.0.0
'@smithy/middleware-stack': 3.0.0
'@smithy/node-config-provider': 3.1.0
'@smithy/node-http-handler': 3.0.0
'@smithy/protocol-http': 4.0.0
'@smithy/smithy-client': 3.1.1
'@smithy/types': 3.0.0
'@smithy/url-parser': 3.0.0
'@smithy/util-base64': 3.0.0
'@smithy/util-body-length-browser': 3.0.0
'@smithy/util-body-length-node': 3.0.0
'@smithy/util-defaults-mode-browser': 3.0.3
'@smithy/util-defaults-mode-node': 3.0.3
'@smithy/util-endpoints': 2.0.1
'@smithy/util-middleware': 3.0.0
'@smithy/util-retry': 3.0.0
'@smithy/util-utf8': 3.0.0
tslib: 2.6.2
transitivePeerDependencies:
- aws-crt
'@aws-sdk/client-sts@3.590.0(@aws-sdk/client-sso-oidc@3.590.0)':
dependencies:
'@aws-crypto/sha256-browser': 3.0.0
'@aws-crypto/sha256-js': 3.0.0
'@aws-sdk/client-sso-oidc': 3.590.0
'@aws-sdk/core': 3.588.0
'@aws-sdk/credential-provider-node': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0(@aws-sdk/client-sso-oidc@3.590.0))
'@aws-sdk/credential-provider-node': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0)
'@aws-sdk/middleware-host-header': 3.577.0
'@aws-sdk/middleware-logger': 3.577.0
'@aws-sdk/middleware-recursion-detection': 3.577.0
@ -6172,7 +6127,7 @@ snapshots:
'@aws-sdk/credential-provider-http': 3.587.0
'@aws-sdk/credential-provider-process': 3.587.0
'@aws-sdk/credential-provider-sso': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)
'@aws-sdk/credential-provider-web-identity': 3.587.0(@aws-sdk/client-sts@3.590.0)
'@aws-sdk/credential-provider-web-identity': 3.587.0(@aws-sdk/client-sts@3.590.0(@aws-sdk/client-sso-oidc@3.590.0))
'@aws-sdk/types': 3.577.0
'@smithy/credential-provider-imds': 3.1.0
'@smithy/property-provider': 3.1.0
@ -6182,10 +6137,11 @@ snapshots:
transitivePeerDependencies:
- '@aws-sdk/client-sso-oidc'
- aws-crt
optional: true
'@aws-sdk/credential-provider-ini@3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0)':
dependencies:
'@aws-sdk/client-sts': 3.590.0
'@aws-sdk/client-sts': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)
'@aws-sdk/credential-provider-env': 3.587.0
'@aws-sdk/credential-provider-http': 3.587.0
'@aws-sdk/credential-provider-process': 3.587.0
@ -6208,7 +6164,7 @@ snapshots:
'@aws-sdk/credential-provider-ini': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0(@aws-sdk/client-sso-oidc@3.590.0))
'@aws-sdk/credential-provider-process': 3.587.0
'@aws-sdk/credential-provider-sso': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)
'@aws-sdk/credential-provider-web-identity': 3.587.0(@aws-sdk/client-sts@3.590.0)
'@aws-sdk/credential-provider-web-identity': 3.587.0(@aws-sdk/client-sts@3.590.0(@aws-sdk/client-sso-oidc@3.590.0))
'@aws-sdk/types': 3.577.0
'@smithy/credential-provider-imds': 3.1.0
'@smithy/property-provider': 3.1.0
@ -6219,6 +6175,7 @@ snapshots:
- '@aws-sdk/client-sso-oidc'
- '@aws-sdk/client-sts'
- aws-crt
optional: true
'@aws-sdk/credential-provider-node@3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0)':
dependencies:
@ -6260,6 +6217,15 @@ snapshots:
- '@aws-sdk/client-sso-oidc'
- aws-crt
'@aws-sdk/credential-provider-web-identity@3.587.0(@aws-sdk/client-sts@3.590.0(@aws-sdk/client-sso-oidc@3.590.0))':
dependencies:
'@aws-sdk/client-sts': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)
'@aws-sdk/types': 3.577.0
'@smithy/property-provider': 3.1.0
'@smithy/types': 3.0.0
tslib: 2.6.2
optional: true
'@aws-sdk/credential-provider-web-identity@3.587.0(@aws-sdk/client-sts@3.590.0)':
dependencies:
'@aws-sdk/client-sts': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)
@ -6276,8 +6242,8 @@ snapshots:
'@aws-sdk/credential-provider-cognito-identity': 3.590.0
'@aws-sdk/credential-provider-env': 3.587.0
'@aws-sdk/credential-provider-http': 3.587.0
'@aws-sdk/credential-provider-ini': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0(@aws-sdk/client-sso-oidc@3.590.0))
'@aws-sdk/credential-provider-node': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0(@aws-sdk/client-sso-oidc@3.590.0))
'@aws-sdk/credential-provider-ini': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0)
'@aws-sdk/credential-provider-node': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0)
'@aws-sdk/credential-provider-process': 3.587.0
'@aws-sdk/credential-provider-sso': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)
'@aws-sdk/credential-provider-web-identity': 3.587.0(@aws-sdk/client-sts@3.590.0)
@ -9931,7 +9897,7 @@ snapshots:
zod: 3.23.8
zod-to-json-schema: 3.23.0(zod@3.23.8)
optionalDependencies:
'@aws-sdk/credential-provider-node': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0)
'@aws-sdk/credential-provider-node': 3.590.0(@aws-sdk/client-sso-oidc@3.590.0)(@aws-sdk/client-sts@3.590.0(@aws-sdk/client-sso-oidc@3.590.0))
'@notionhq/client': 2.2.15(encoding@0.1.13)
'@pinecone-database/pinecone': 2.2.2
assemblyai: 4.4.5(bufferutil@4.0.8)(utf-8-validate@6.0.4)

Wyświetl plik

@ -129,6 +129,7 @@ All heavy third-party imports are isolated as _optional peer dependencies_ to ke
| [SerpAPI](https://serpapi.com/search-api) | `SerpAPIClient` | Lightweight wrapper around SerpAPI for Google search. |
| [Serper](https://serper.dev) | `SerperClient` | Lightweight wrapper around Serper for Google search. |
| [Slack](https://api.slack.com/docs) | `SlackClient` | Send and receive Slack messages. |
| [Tavily](https://tavily.com) | `TavilyClient` | Web search API tailored for LLMs. 🔥 |
| [Twilio](https://www.twilio.com/docs/conversations/api) | `TwilioClient` | Twilio conversation API to send and receive SMS messages. |
| [Twitter](https://developer.x.com/en/docs/twitter-api) | `TwitterClient` | Basic Twitter API methods for fetching users, tweets, and searching recent tweets. Includes support for plan-aware rate-limiting. |
| [WeatherAPI](https://www.weatherapi.com) | `WeatherClient` | Basic access to current weather data based on location. |

Wyświetl plik

@ -16,6 +16,7 @@ export * from './searxng-client.js'
export * from './serpapi-client.js'
export * from './serper-client.js'
export * from './slack-client.js'
export * from './tavily-client.js'
export * from './twilio-client.js'
export * from './weather-client.js'
export * from './wikipedia-client.js'

Wyświetl plik

@ -667,7 +667,7 @@ export class SerpAPIClient extends AIFunctionsProvider {
@aiFunction({
name: 'serpapi_google_search',
description:
'Uses Google Search to return the most relevant web pages for a given query. Can also be used to find up-to-date news and information about many topics.',
'Uses Google Search to return the most relevant web pages for a given query. Useful for finding up-to-date news and information about any topic.',
inputSchema: z.object({
q: z.string().describe('search query'),
num: z

Wyświetl plik

@ -247,7 +247,7 @@ export class SerperClient extends AIFunctionsProvider {
@aiFunction({
name: 'serper_google_search',
description:
'Uses Google Search to return the most relevant web pages for a given query. Can also be used to find up-to-date news and information about many topics.',
'Uses Google Search to return the most relevant web pages for a given query. Useful for finding up-to-date news and information about any topic.',
inputSchema: serper.GeneralSearchSchema.pick({
q: true,
num: true,

Wyświetl plik

@ -0,0 +1,172 @@
import defaultKy, { type KyInstance } from 'ky'
import { z } from 'zod'
import { aiFunction, AIFunctionsProvider } from '../fns.js'
import { assert, getEnv, pruneNullOrUndefined } from '../utils.js'
export namespace tavily {
export const API_BASE_URL = 'https://api.tavily.com'
export interface SearchOptions {
/** Search query. (required) */
query: string
/** The depth of the search. It can be basic or advanced. Default is basic for quick results and advanced for indepth high quality results but longer response time. Advanced calls equals 2 requests. */
search_depth?: 'basic' | 'advanced'
/** Include a synthesized answer in the search results. Default is `false`. */
include_answer?: boolean
/** Include a list of query related images in the response. Default is `false`. */
include_images?: boolean
/** Include raw content in the search results. Default is `false`. */
include_raw_content?: boolean
/** The number of maximum search results to return. Default is `5`. */
max_results?: number
/** A list of domains to specifically include in the search results. Default is `undefined`, which includes all domains. */
include_domains?: string[]
/** A list of domains to specifically exclude from the search results. Default is `undefined`, which doesn't exclude any domains. */
exclude_domains?: string[]
}
export interface SearchResponse {
/** The search query. */
query: string
/** A list of sorted search results ranked by relevancy. */
results: SearchResult[]
/** The answer to your search query. */
answer?: string
/** A list of query related image urls. */
images?: string[]
/** A list of suggested research follow up questions related to original query. */
follow_up_questions?: string[]
/** How long it took to generate a response. */
response_time: string
}
export interface SearchResult {
/** The url of the search result. */
url: string
/** The title of the search result page. */
title: string
/**
* The most query related content from the scraped url. We use proprietary AI and algorithms to extract only the most relevant content from each url, to optimize for context quality and size.
*/
content: string
/** The parsed and cleaned HTML of the site. For now includes parsed text only. */
raw_content?: string
/** The relevance score of the search result. */
score: string
}
}
/**
* Tavily provides a web search API tailored for LLMs.
*
* @see https://tavily.com
*/
export class TavilyClient extends AIFunctionsProvider {
protected readonly ky: KyInstance
protected readonly apiKey: string
protected readonly apiBaseUrl: string
constructor({
apiKey = getEnv('TAVILY_API_KEY'),
apiBaseUrl = tavily.API_BASE_URL,
ky = defaultKy
}: {
apiKey?: string
apiBaseUrl?: string
ky?: KyInstance
} = {}) {
assert(
apiKey,
'TavilyClient missing required "apiKey" (defaults to "TAVILY_API_KEY")'
)
super()
this.apiKey = apiKey
this.apiBaseUrl = apiBaseUrl
this.ky = ky.extend({
prefixUrl: this.apiBaseUrl
})
}
/**
* Searches the web for pages relevant to the given query and summarizes the results.
*/
@aiFunction({
name: 'tavily_web_search',
description:
'Searches the web to find the most relevant pages for a given query and summarizes the results. Very useful for finding up-to-date news and information about any topic.',
inputSchema: z.object({
query: z
.string()
.describe('The query to search for. Accepts any Google search query.'),
search_depth: z
.enum(['basic', 'advanced'])
.optional()
.describe(
'How deep of a search to perform. Use "basic" for quick results and "advanced" for slower, in-depth results.'
),
include_answer: z
.boolean()
.optional()
.describe(
'Whether or not to include an answer summary in the results.'
),
include_images: z
.boolean()
.optional()
.describe('Whether or not to include images in the results.'),
max_results: z
.number()
.int()
.positive()
.default(5)
.optional()
.describe('Max number of search results to return.')
// include_domains: z
// .array(z.string())
// .optional()
// .describe(
// 'List of domains to specifically include in the search results.'
// ),
// exclude_domains: z
// .array(z.string())
// .optional()
// .describe(
// 'List of domains to specifically exclude from the search results.'
// )
})
})
async search(queryOrOpts: string | tavily.SearchOptions) {
const options =
typeof queryOrOpts === 'string' ? { query: queryOrOpts } : queryOrOpts
const res = await this.ky
.post('search', {
json: {
...options,
api_key: this.apiKey
}
})
.json<tavily.SearchResponse>()
return pruneNullOrUndefined(res).results?.map(pruneNullOrUndefined)
}
}