kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
pull/643/head^2
rodzic
760b4d5716
commit
ca9254d567
|
@ -7,7 +7,8 @@ import restoreCursor from 'restore-cursor'
|
||||||
// import { ClearbitClient } from '../src/index.js'
|
// import { ClearbitClient } from '../src/index.js'
|
||||||
// import { ProxycurlClient } from '../src/services/proxycurl-client.js'
|
// import { ProxycurlClient } from '../src/services/proxycurl-client.js'
|
||||||
// import { WikipediaClient } from '../src/index.js'
|
// import { WikipediaClient } from '../src/index.js'
|
||||||
import { PerigonClient } from '../src/index.js'
|
// import { PerigonClient } from '../src/index.js'
|
||||||
|
import { FirecrawlClient } from '../src/index.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scratch pad for testing.
|
* Scratch pad for testing.
|
||||||
|
@ -41,18 +42,24 @@ async function main() {
|
||||||
// })
|
// })
|
||||||
// console.log(JSON.stringify(res, null, 2))
|
// console.log(JSON.stringify(res, null, 2))
|
||||||
|
|
||||||
const perigon = new PerigonClient()
|
// const perigon = new PerigonClient()
|
||||||
const res = await perigon.searchArticles({
|
// const res = await perigon.searchArticles({
|
||||||
q: 'AI agents AND startup',
|
// q: 'AI agents AND startup',
|
||||||
sourceGroup: 'top50tech'
|
// sourceGroup: 'top50tech'
|
||||||
})
|
// })
|
||||||
|
// console.log(JSON.stringify(res, null, 2))
|
||||||
|
|
||||||
|
const firecrawl = new FirecrawlClient()
|
||||||
|
const res = await firecrawl.scrapeUrl({
|
||||||
|
// url: 'https://www.bbc.com/news/articles/cp4475gwny1o'
|
||||||
|
url: 'https://www.firecrawl.dev'
|
||||||
|
})
|
||||||
console.log(JSON.stringify(res, null, 2))
|
console.log(JSON.stringify(res, null, 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await main()
|
await main()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('unexpected error', err)
|
console.error('error', err)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
import 'dotenv/config'
|
import 'dotenv/config'
|
||||||
|
|
||||||
import OpenAI from 'openai'
|
import OpenAI from 'openai'
|
||||||
import { default as assert } from 'tiny-invariant'
|
|
||||||
|
|
||||||
import { WeatherClient } from '../../src/index.js'
|
import { assert, WeatherClient } from '../../src/index.js'
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const weather = new WeatherClient()
|
const weather = new WeatherClient()
|
||||||
|
|
|
@ -63,7 +63,6 @@
|
||||||
"jsonrepair": "^3.6.1",
|
"jsonrepair": "^3.6.1",
|
||||||
"ky": "^1.2.4",
|
"ky": "^1.2.4",
|
||||||
"p-throttle": "^6.1.0",
|
"p-throttle": "^6.1.0",
|
||||||
"tiny-invariant": "^1.3.3",
|
|
||||||
"twitter-api-sdk": "^1.2.1",
|
"twitter-api-sdk": "^1.2.1",
|
||||||
"type-fest": "^4.18.3",
|
"type-fest": "^4.18.3",
|
||||||
"zod": "^3.23.3",
|
"zod": "^3.23.3",
|
||||||
|
|
|
@ -26,9 +26,6 @@ importers:
|
||||||
p-throttle:
|
p-throttle:
|
||||||
specifier: ^6.1.0
|
specifier: ^6.1.0
|
||||||
version: 6.1.0
|
version: 6.1.0
|
||||||
tiny-invariant:
|
|
||||||
specifier: ^1.3.3
|
|
||||||
version: 1.3.3
|
|
||||||
twitter-api-sdk:
|
twitter-api-sdk:
|
||||||
specifier: ^1.2.1
|
specifier: ^1.2.1
|
||||||
version: 1.2.1
|
version: 1.2.1
|
||||||
|
@ -75,9 +72,6 @@ importers:
|
||||||
eslint:
|
eslint:
|
||||||
specifier: ^8.57.0
|
specifier: ^8.57.0
|
||||||
version: 8.57.0
|
version: 8.57.0
|
||||||
exit-hook:
|
|
||||||
specifier: ^4.0.0
|
|
||||||
version: 4.0.0
|
|
||||||
husky:
|
husky:
|
||||||
specifier: ^9.0.11
|
specifier: ^9.0.11
|
||||||
version: 9.0.11
|
version: 9.0.11
|
||||||
|
@ -4060,9 +4054,6 @@ packages:
|
||||||
tiktoken@1.0.15:
|
tiktoken@1.0.15:
|
||||||
resolution: {integrity: sha512-sCsrq/vMWUSEW29CJLNmPvWxlVp7yh2tlkAjpJltIKqp5CKf98ZNpdeHRmAlPVFlGEbswDc6SmI8vz64W/qErw==}
|
resolution: {integrity: sha512-sCsrq/vMWUSEW29CJLNmPvWxlVp7yh2tlkAjpJltIKqp5CKf98ZNpdeHRmAlPVFlGEbswDc6SmI8vz64W/qErw==}
|
||||||
|
|
||||||
tiny-invariant@1.3.3:
|
|
||||||
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
|
|
||||||
|
|
||||||
tinybench@2.8.0:
|
tinybench@2.8.0:
|
||||||
resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==}
|
resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==}
|
||||||
|
|
||||||
|
@ -8681,8 +8672,6 @@ snapshots:
|
||||||
|
|
||||||
tiktoken@1.0.15: {}
|
tiktoken@1.0.15: {}
|
||||||
|
|
||||||
tiny-invariant@1.3.3: {}
|
|
||||||
|
|
||||||
tinybench@2.8.0: {}
|
tinybench@2.8.0: {}
|
||||||
|
|
||||||
tinypool@0.9.0: {}
|
tinypool@0.9.0: {}
|
||||||
|
|
|
@ -50,6 +50,11 @@
|
||||||
- instructor-js
|
- instructor-js
|
||||||
- TODO
|
- TODO
|
||||||
- services
|
- services
|
||||||
|
- calculator
|
||||||
|
- e2b
|
||||||
|
- search-and-scrape
|
||||||
|
- replicate
|
||||||
|
- huggingface
|
||||||
- wolfram alpha
|
- wolfram alpha
|
||||||
- midjourney
|
- midjourney
|
||||||
- unstructured
|
- unstructured
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
* Slightly modified version of [tiny-invariant](https://github.com/alexreardon/tiny-invariant).
|
||||||
|
*
|
||||||
|
* `assert` is used to [assert](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions) that the `condition` is [truthy](https://github.com/getify/You-Dont-Know-JS/blob/bdbe570600d4e1107d0b131787903ca1c9ec8140/up%20%26%20going/ch2.md#truthy--falsy).
|
||||||
|
*
|
||||||
|
* 💥 `assert` will `throw` an `Error` if the `condition` is [falsey](https://github.com/getify/You-Dont-Know-JS/blob/bdbe570600d4e1107d0b131787903ca1c9ec8140/up%20%26%20going/ch2.md#truthy--falsy)
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const value: Person | null = { name: 'Alex' };
|
||||||
|
* assert(value, 'Expected value to be a person');
|
||||||
|
* // type of `value`` has been narrowed to `Person`
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function assert(
|
||||||
|
condition: any,
|
||||||
|
/**
|
||||||
|
* Can provide a string, or a function that returns a string for cases where
|
||||||
|
* the message takes a fair amount of effort to compute.
|
||||||
|
*/
|
||||||
|
message?: string | (() => string)
|
||||||
|
): asserts condition {
|
||||||
|
if (condition) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const providedMessage: string | undefined =
|
||||||
|
typeof message === 'function' ? message() : message
|
||||||
|
|
||||||
|
throw new Error(providedMessage ?? 'Assertion failed')
|
||||||
|
}
|
|
@ -1,15 +1,17 @@
|
||||||
import defaultKy, { type KyInstance } from 'ky'
|
import defaultKy, { type KyInstance } from 'ky'
|
||||||
import z from 'zod'
|
import z from 'zod'
|
||||||
|
|
||||||
|
import { aiFunction, AIFunctionsProvider } from '../fns.js'
|
||||||
import { assert, delay, getEnv } from '../utils.js'
|
import { assert, delay, getEnv } from '../utils.js'
|
||||||
import { zodToJsonSchema } from '../zod-to-json-schema.js'
|
import { zodToJsonSchema } from '../zod-to-json-schema.js'
|
||||||
|
|
||||||
|
// TODO: Deprioritizing this client for now because the API doesn't seem to be stable.
|
||||||
|
|
||||||
export namespace firecrawl {
|
export namespace firecrawl {
|
||||||
/**
|
/**
|
||||||
* Generic parameter interface.
|
* Generic parameter interface.
|
||||||
*/
|
*/
|
||||||
export interface Params {
|
export interface Params {
|
||||||
[key: string]: any
|
|
||||||
extractorOptions?: {
|
extractorOptions?: {
|
||||||
extractionSchema: z.ZodSchema | any
|
extractionSchema: z.ZodSchema | any
|
||||||
mode?: 'llm-extraction'
|
mode?: 'llm-extraction'
|
||||||
|
@ -59,8 +61,9 @@ export namespace firecrawl {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://www.firecrawl.dev
|
* @see https://www.firecrawl.dev
|
||||||
|
* @see https://github.com/mendableai/firecrawl
|
||||||
*/
|
*/
|
||||||
export class FirecrawlClient {
|
export class FirecrawlClient extends AIFunctionsProvider {
|
||||||
readonly ky: KyInstance
|
readonly ky: KyInstance
|
||||||
readonly apiKey: string
|
readonly apiKey: string
|
||||||
readonly apiBaseUrl: string
|
readonly apiBaseUrl: string
|
||||||
|
@ -69,10 +72,12 @@ export class FirecrawlClient {
|
||||||
apiKey = getEnv('FIRECRAWL_API_KEY'),
|
apiKey = getEnv('FIRECRAWL_API_KEY'),
|
||||||
apiBaseUrl = getEnv('FIRECRAWL_API_BASE_URL') ??
|
apiBaseUrl = getEnv('FIRECRAWL_API_BASE_URL') ??
|
||||||
'https://api.firecrawl.dev',
|
'https://api.firecrawl.dev',
|
||||||
|
timeoutMs = 60_000,
|
||||||
ky = defaultKy
|
ky = defaultKy
|
||||||
}: {
|
}: {
|
||||||
apiKey?: string
|
apiKey?: string
|
||||||
apiBaseUrl?: string
|
apiBaseUrl?: string
|
||||||
|
timeoutMs?: number
|
||||||
ky?: KyInstance
|
ky?: KyInstance
|
||||||
} = {}) {
|
} = {}) {
|
||||||
assert(
|
assert(
|
||||||
|
@ -83,18 +88,27 @@ export class FirecrawlClient {
|
||||||
apiBaseUrl,
|
apiBaseUrl,
|
||||||
'FirecrawlClient missing required "apiBaseUrl" (defaults to "FIRECRAWL_API_BASE_URL")'
|
'FirecrawlClient missing required "apiBaseUrl" (defaults to "FIRECRAWL_API_BASE_URL")'
|
||||||
)
|
)
|
||||||
|
super()
|
||||||
|
|
||||||
this.apiKey = apiKey
|
this.apiKey = apiKey
|
||||||
this.apiBaseUrl = apiBaseUrl
|
this.apiBaseUrl = apiBaseUrl
|
||||||
|
|
||||||
this.ky = ky.extend({
|
this.ky = ky.extend({
|
||||||
prefixUrl: apiBaseUrl,
|
prefixUrl: apiBaseUrl,
|
||||||
|
timeout: timeoutMs,
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${this.apiKey}`
|
Authorization: `Bearer ${this.apiKey}`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@aiFunction({
|
||||||
|
name: 'firecrawl_scrape_url',
|
||||||
|
description: 'Scrape the contents of a URL.',
|
||||||
|
inputSchema: z.object({
|
||||||
|
url: z.string().url().describe('The URL to scrape.')
|
||||||
|
})
|
||||||
|
})
|
||||||
async scrapeUrl(
|
async scrapeUrl(
|
||||||
opts: {
|
opts: {
|
||||||
url: string
|
url: string
|
||||||
|
@ -173,7 +187,7 @@ export class FirecrawlClient {
|
||||||
|
|
||||||
async waitForCrawlJob({
|
async waitForCrawlJob({
|
||||||
jobId,
|
jobId,
|
||||||
timeoutMs = 30_000
|
timeoutMs = 60_000
|
||||||
}: {
|
}: {
|
||||||
jobId: string
|
jobId: string
|
||||||
timeoutMs?: number
|
timeoutMs?: number
|
||||||
|
|
|
@ -3,12 +3,25 @@ import pThrottle from 'p-throttle'
|
||||||
|
|
||||||
import { assert, getEnv, throttleKy } from '../utils.js'
|
import { assert, getEnv, throttleKy } from '../utils.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: I'm holding off on converting this client to an `AIFunctionsProvider`
|
||||||
|
* because it seems to be significantly more expensive than other data sources,
|
||||||
|
* and I'm not sure if it's worth the cost.
|
||||||
|
*/
|
||||||
|
|
||||||
export namespace peopledatalabs {
|
export namespace peopledatalabs {
|
||||||
export const BASE_URL = 'https://api.peopledatalabs.com/v5/'
|
export const BASE_URL = 'https://api.peopledatalabs.com/v5/'
|
||||||
|
|
||||||
// Allow up to 20 requests per minute by default.
|
// Allow up to 10 requests per minute.
|
||||||
export const throttle = pThrottle({
|
export const throttle10PerMin = pThrottle({
|
||||||
limit: 20,
|
limit: 10,
|
||||||
|
interval: 60 * 1000,
|
||||||
|
strict: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// Allow up to 100 requests per minute.
|
||||||
|
export const throttle100PerMin = pThrottle({
|
||||||
|
limit: 100,
|
||||||
interval: 60 * 1000,
|
interval: 60 * 1000,
|
||||||
strict: true
|
strict: true
|
||||||
})
|
})
|
||||||
|
@ -431,6 +444,11 @@ export namespace peopledatalabs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* People & Company Data
|
||||||
|
*
|
||||||
|
* @see https://www.peopledatalabs.com
|
||||||
|
*/
|
||||||
export class PeopleDataLabsClient {
|
export class PeopleDataLabsClient {
|
||||||
readonly ky: KyInstance
|
readonly ky: KyInstance
|
||||||
readonly apiKey: string
|
readonly apiKey: string
|
||||||
|
@ -457,13 +475,15 @@ export class PeopleDataLabsClient {
|
||||||
this.apiKey = apiKey
|
this.apiKey = apiKey
|
||||||
this.apiBaseUrl = apiBaseUrl
|
this.apiBaseUrl = apiBaseUrl
|
||||||
|
|
||||||
const throttledKy = throttle ? throttleKy(ky, peopledatalabs.throttle) : ky
|
const throttledKy = throttle
|
||||||
|
? throttleKy(ky, peopledatalabs.throttle10PerMin)
|
||||||
|
: ky
|
||||||
|
|
||||||
this.ky = throttledKy.extend({
|
this.ky = throttledKy.extend({
|
||||||
prefixUrl: apiBaseUrl,
|
prefixUrl: apiBaseUrl,
|
||||||
timeout: timeoutMs,
|
timeout: timeoutMs,
|
||||||
headers: {
|
headers: {
|
||||||
'X-Api-Key': `${this.apiKey}`
|
'x-api-key': `${this.apiKey}`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type * as types from './types.js'
|
import type * as types from './types.js'
|
||||||
|
|
||||||
|
export { assert } from './assert.js'
|
||||||
export { default as delay } from 'delay'
|
export { default as delay } from 'delay'
|
||||||
export { default as assert } from 'tiny-invariant'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* From `inputObj`, create a new object that does not include `keys`.
|
* From `inputObj`, create a new object that does not include `keys`.
|
||||||
|
|
Ładowanie…
Reference in New Issue