kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
pull/643/head^2
rodzic
0953469e8d
commit
0d96cef757
|
@ -4,7 +4,8 @@ import 'dotenv/config'
|
|||
import { gracefulExit } from 'exit-hook'
|
||||
import restoreCursor from 'restore-cursor'
|
||||
|
||||
import type * as types from '@/types.js'
|
||||
// import { ClearbitClient } from '../src/index.js'
|
||||
import { ProxycurlClient } from '../src/services/proxycurl-client.js'
|
||||
|
||||
/**
|
||||
* Scratch for quick testing.
|
||||
|
@ -12,6 +13,19 @@ import type * as types from '@/types.js'
|
|||
async function main() {
|
||||
restoreCursor()
|
||||
|
||||
// const clearbit = new ClearbitClient()
|
||||
// const res = await clearbit.companyEnrichment({
|
||||
// domain: 'https://clay.com'
|
||||
// })
|
||||
// console.log(JSON.stringify(res, null, 2))
|
||||
|
||||
const proxycurl = new ProxycurlClient()
|
||||
const res = await proxycurl.getLinkedInPerson({
|
||||
linkedin_profile_url: 'https://linkedin.com/in/fisch2'
|
||||
// personal_email: 'fisch0920@gmail.com'
|
||||
})
|
||||
console.log(JSON.stringify(res, null, 2))
|
||||
|
||||
return gracefulExit(0)
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
14
package.json
14
package.json
|
@ -45,10 +45,10 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@dexaai/dexter": "^2.0.0",
|
||||
"@nangohq/node": "^0.39.30",
|
||||
"chalk": "^5.3.0",
|
||||
"delay": "^6.0.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"execa": "^8.0.1",
|
||||
"exit-hook": "^4.0.0",
|
||||
"jsonrepair": "^3.6.1",
|
||||
"ky": "^1.2.4",
|
||||
|
@ -56,10 +56,14 @@
|
|||
"p-map": "^7.0.2",
|
||||
"p-retry": "^6.2.0",
|
||||
"p-throttle": "^6.1.0",
|
||||
"proxycurl-js-linkedin-profile-scraper": "^1.0.2",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"restore-cursor": "^5.0.0",
|
||||
"tiny-invariant": "^1.3.3",
|
||||
"twitter-api-sdk": "^1.2.1",
|
||||
"type-fest": "^4.16.0",
|
||||
"zod": "^3.23.3"
|
||||
"zod": "^3.23.3",
|
||||
"zod-to-json-schema": "^3.23.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fisch0920/eslint-config": "^1.3.1",
|
||||
|
@ -68,12 +72,12 @@
|
|||
"del-cli": "^5.1.0",
|
||||
"eslint": "^8.57.0",
|
||||
"husky": "^9.0.11",
|
||||
"lint-staged": "^15.2.2",
|
||||
"lint-staged": "^15.2.4",
|
||||
"np": "^10.0.5",
|
||||
"npm-run-all2": "^6.1.2",
|
||||
"npm-run-all2": "^6.2.0",
|
||||
"prettier": "^3.2.5",
|
||||
"tsup": "^8.0.2",
|
||||
"tsx": "^4.7.2",
|
||||
"tsx": "^4.10.5",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.2.10",
|
||||
"vitest": "^1.5.0"
|
||||
|
|
556
pnpm-lock.yaml
556
pnpm-lock.yaml
Plik diff jest za duży
Load Diff
File diff suppressed because one or more lines are too long
Plik diff jest za duży
Load Diff
106
src/fns.ts
106
src/fns.ts
|
@ -9,13 +9,6 @@ import { zodToJsonSchema } from './zod-to-json-schema.js'
|
|||
|
||||
export const invocableMetadataKey = Symbol('invocable')
|
||||
|
||||
export interface Invocable {
|
||||
name: string
|
||||
description?: string
|
||||
inputSchema?: z.AnyZodObject
|
||||
callback: (args: Record<string, any>) => Promise<any>
|
||||
}
|
||||
|
||||
export abstract class AIToolsProvider {
|
||||
private _tools?: ToolSet
|
||||
private _functions?: FunctionSet
|
||||
|
@ -34,7 +27,16 @@ export abstract class AIToolsProvider {
|
|||
|
||||
get functions(): FunctionSet {
|
||||
if (!this._functions) {
|
||||
const invocables = getInvocables(this)
|
||||
const metadata = this.constructor[Symbol.metadata]
|
||||
const invocables = (metadata?.invocables as Invocable[]) ?? []
|
||||
const namespace = this.namespace
|
||||
|
||||
const functions = invocables.map((invocable) => ({
|
||||
...invocable,
|
||||
name: invocable.name ?? `${namespace}_${invocable.propertyKey}`,
|
||||
callback: (target as any)[invocable.propertyKey].bind(target)
|
||||
}))
|
||||
|
||||
const functions = invocables.map(getFunctionSpec)
|
||||
this._functions = new FunctionSet(functions)
|
||||
}
|
||||
|
@ -43,7 +45,14 @@ export abstract class AIToolsProvider {
|
|||
}
|
||||
}
|
||||
|
||||
export function getFunctionSpec(invocable: Invocable): types.AIFunctionSpec {
|
||||
export interface Invocable {
|
||||
name: string
|
||||
description?: string
|
||||
inputSchema?: z.AnyZodObject
|
||||
callback: (args: Record<string, any>) => Promise<any>
|
||||
}
|
||||
|
||||
function getFunctionSpec(invocable: Invocable): types.AIFunctionSpec {
|
||||
const { name, description, inputSchema } = invocable
|
||||
|
||||
return {
|
||||
|
@ -58,14 +67,11 @@ export function getFunctionSpec(invocable: Invocable): types.AIFunctionSpec {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constraints:
|
||||
* - params must be an object, so the underlying function should only expect a
|
||||
* single parameter
|
||||
* - for the return value type `T | MaybePromise<T>`, `T` must be serializable
|
||||
* to JSON
|
||||
*/
|
||||
export function aiFunction({
|
||||
export function aiFunction<
|
||||
This,
|
||||
Args extends any[],
|
||||
Return extends Promise<any>
|
||||
>({
|
||||
name,
|
||||
description,
|
||||
inputSchema
|
||||
|
@ -77,48 +83,38 @@ export function aiFunction({
|
|||
// single parameter
|
||||
inputSchema?: z.AnyZodObject
|
||||
}) {
|
||||
return function (
|
||||
target: object,
|
||||
propertyKey: string,
|
||||
descriptor: PropertyDescriptor
|
||||
) {
|
||||
const existingInvocables = getPrivateInvocables(target)
|
||||
return (
|
||||
targetMethod: (this: This, ...args: Args) => Return,
|
||||
context: ClassMethodDecoratorContext<
|
||||
This,
|
||||
(this: This, ...args: Args) => Return
|
||||
> & {
|
||||
readonly metadata: {
|
||||
invocables: Invocable[]
|
||||
}
|
||||
}
|
||||
) => {
|
||||
const methodName = String(context.name)
|
||||
if (!context.metadata.invocables) {
|
||||
context.metadata.invocables = []
|
||||
}
|
||||
|
||||
existingInvocables.push({
|
||||
propertyKey,
|
||||
context.metadata.invocables.push({
|
||||
name: name ?? methodName,
|
||||
description,
|
||||
name,
|
||||
inputSchema
|
||||
inputSchema,
|
||||
callback: targetMethod
|
||||
})
|
||||
|
||||
setPrivateInvocables(target, existingInvocables)
|
||||
return targetMethod
|
||||
|
||||
return descriptor.get ?? descriptor.value
|
||||
// function replacementMethod(this: This, ...args: Args): Return {
|
||||
// console.log(`LOG: Entering method '${methodName}'.`)
|
||||
// const result = targetMethod.call(this, ...args)
|
||||
// console.log(`LOG: Exiting method '${methodName}'.`)
|
||||
// return result
|
||||
// }
|
||||
|
||||
// return replacementMethod
|
||||
}
|
||||
}
|
||||
|
||||
export function getInvocables(target: object): Invocable[] {
|
||||
const invocables = getPrivateInvocables(target)
|
||||
const namespace = target.constructor.name
|
||||
|
||||
return invocables.map((invocable) => ({
|
||||
...invocable,
|
||||
name: invocable.name ?? `${namespace}_${invocable.propertyKey}`,
|
||||
callback: (target as any)[invocable.propertyKey].bind(target)
|
||||
}))
|
||||
}
|
||||
|
||||
interface PrivateInvocable {
|
||||
propertyKey: string
|
||||
name?: string
|
||||
description?: string
|
||||
inputSchema?: z.AnyZodObject
|
||||
}
|
||||
|
||||
function getPrivateInvocables(target: object): PrivateInvocable[] {
|
||||
return Reflect.getMetadata(invocableMetadataKey, target) ?? []
|
||||
}
|
||||
|
||||
function setPrivateInvocables(target: object, invocables: PrivateInvocable[]) {
|
||||
Reflect.defineMetadata(invocableMetadataKey, invocables, target)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
export * from './fns.js'
|
||||
export * from './function-set.js'
|
||||
export * from './parse-structured-output.js'
|
||||
export * from './services/index.js'
|
||||
|
|
|
@ -24,7 +24,7 @@ export class DexaClient {
|
|||
this.ky = ky.extend({ prefixUrl: this.apiBaseUrl, timeout: 60_000 })
|
||||
}
|
||||
|
||||
async generateResponse({ messages }: { messages: Prompt.Msg[] }) {
|
||||
async askDexa({ messages }: { messages: Prompt.Msg[] }) {
|
||||
return this.ky
|
||||
.post('api/ask-dexa', {
|
||||
json: {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
export * from './clearbit.js'
|
||||
export * from './clearbit-client.js'
|
||||
export * from './dexa-client.js'
|
||||
export * from './diffbot.js'
|
||||
export * from './diffbot-client.js'
|
||||
export * from './openai-client.js'
|
||||
export * from './proxycurl-client.js'
|
||||
export * from './scraper-client.js'
|
||||
export * from './serpapi.js'
|
||||
export * from './serper.js'
|
||||
export * from './serpapi-client.js'
|
||||
export * from './serper-client.js'
|
||||
export * from './twitter-client.js'
|
||||
export * from './weather.js'
|
||||
export * from './weather-client.js'
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -2,25 +2,27 @@ import defaultKy, { type KyInstance } from 'ky'
|
|||
|
||||
import { assert, getEnv } from '../utils.js'
|
||||
|
||||
export type ScrapeResult = {
|
||||
author: string
|
||||
byline: string
|
||||
/** The HTML for the main content of the page. */
|
||||
content: string
|
||||
description: string
|
||||
imageUrl: string
|
||||
lang: string
|
||||
length: number
|
||||
logoUrl: string
|
||||
/** The text for the main content of the page in markdown format. */
|
||||
markdownContent: string
|
||||
publishedTime: string
|
||||
/** The raw HTML response from the server. */
|
||||
rawHtml: string
|
||||
siteName: string
|
||||
/** The text for the main content of the page. */
|
||||
textContent: string
|
||||
title: string
|
||||
export namespace scraper {
|
||||
export type ScrapeResult = {
|
||||
author: string
|
||||
byline: string
|
||||
/** The HTML for the main content of the page. */
|
||||
content: string
|
||||
description: string
|
||||
imageUrl: string
|
||||
lang: string
|
||||
length: number
|
||||
logoUrl: string
|
||||
/** The text for the main content of the page in markdown format. */
|
||||
markdownContent: string
|
||||
publishedTime: string
|
||||
/** The raw HTML response from the server. */
|
||||
rawHtml: string
|
||||
siteName: string
|
||||
/** The text for the main content of the page. */
|
||||
textContent: string
|
||||
title: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,7 +58,7 @@ export class ScraperClient {
|
|||
}: {
|
||||
timeout?: number
|
||||
} = {}
|
||||
): Promise<ScrapeResult> {
|
||||
): Promise<scraper.ScrapeResult> {
|
||||
return this.ky
|
||||
.post('scrape', {
|
||||
json: { url },
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
// https://github.com/microsoft/TypeScript/issues/53461
|
||||
// symbol-polyfill.ts
|
||||
|
||||
declare global {
|
||||
interface SymbolConstructor {
|
||||
readonly metadata: unique symbol
|
||||
}
|
||||
}
|
||||
|
||||
;(Symbol as any).metadata ??= Symbol.for('Symbol.metadata')
|
||||
|
||||
const _metadata = Object.create(null)
|
||||
|
||||
if (typeof Symbol === 'function' && Symbol.metadata) {
|
||||
Object.defineProperty(globalThis, Symbol.metadata, {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: _metadata
|
||||
})
|
||||
}
|
102
src/types.ts
102
src/types.ts
|
@ -14,3 +14,105 @@ export interface AIToolSpec {
|
|||
type: 'function'
|
||||
function: AIFunctionSpec
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic/default OpenAI message without any narrowing applied
|
||||
*/
|
||||
export interface Msg {
|
||||
/** The contents of the message. `content` is required for all messages, and may be null for assistant messages with function calls. */
|
||||
content: string | null
|
||||
/** The role of the messages author. One of `system`, `user`, `assistant`, 'tool', or `function`. */
|
||||
role: Msg.Role
|
||||
/** The name and arguments of a function that should be called, as generated by the model. */
|
||||
function_call?: Msg.Call.Function
|
||||
/** The tool calls generated by the model, such as function calls. */
|
||||
tool_calls?: Msg.Call.Tool[]
|
||||
/**
|
||||
* Tool call that this message is responding to.
|
||||
*/
|
||||
tool_call_id?: string
|
||||
/**
|
||||
* The name of the author of this message. `name` is required if role is
|
||||
* `function`, and it should be the name of the function whose response is in the
|
||||
* `content`. May contain a-z, A-Z, 0-9, and underscores, with a maximum length of
|
||||
* 64 characters.
|
||||
*/
|
||||
name?: string
|
||||
}
|
||||
|
||||
/** Narrowed ChatModel.Message types. */
|
||||
export namespace Msg {
|
||||
/** The possible roles for a message. */
|
||||
export type Role = 'system' | 'user' | 'assistant' | 'function' | 'tool'
|
||||
|
||||
export namespace Call {
|
||||
/** The name and arguments of a function that should be called, as generated by the model. */
|
||||
export type Function = {
|
||||
/** The arguments to call the function with, as generated by the model in JSON format. */
|
||||
arguments: string
|
||||
/** The name of the function to call. */
|
||||
name: string
|
||||
}
|
||||
|
||||
/** The tool calls generated by the model, such as function calls. */
|
||||
export type Tool = {
|
||||
/** The ID of the tool call. */
|
||||
id: string
|
||||
/** The type of the tool. Currently, only `function` is supported. */
|
||||
type: 'function'
|
||||
/** The function that the model called. */
|
||||
function: Call.Function
|
||||
}
|
||||
}
|
||||
|
||||
/** Message with text content for the system. */
|
||||
export type System = {
|
||||
role: 'system'
|
||||
content: string
|
||||
name?: string
|
||||
}
|
||||
|
||||
/** Message with text content from the user. */
|
||||
export type User = {
|
||||
role: 'user'
|
||||
name?: string
|
||||
content: string
|
||||
}
|
||||
|
||||
/** Message with text content from the assistant. */
|
||||
export type Assistant = {
|
||||
role: 'assistant'
|
||||
name?: string
|
||||
content: string
|
||||
}
|
||||
|
||||
/** Message with arguments to call a function. */
|
||||
export type FuncCall = {
|
||||
role: 'assistant'
|
||||
name?: string
|
||||
content: null
|
||||
function_call: Call.Function
|
||||
}
|
||||
|
||||
/** Message with the result of a function call. */
|
||||
export type FuncResult = {
|
||||
role: 'function'
|
||||
name: string
|
||||
content: string
|
||||
}
|
||||
|
||||
/** Message with arguments to call one or more tools. */
|
||||
export type ToolCall = {
|
||||
role: 'assistant'
|
||||
name?: string
|
||||
content: null
|
||||
tool_calls: Call.Tool[]
|
||||
}
|
||||
|
||||
/** Message with the result of a tool call. */
|
||||
export type ToolResult = {
|
||||
role: 'tool'
|
||||
tool_call_id: string
|
||||
content: string
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ export function zodToJsonSchema(schema: z.ZodType): Record<string, unknown> {
|
|||
'default',
|
||||
'definitions',
|
||||
'description',
|
||||
'markdownDescription',
|
||||
'additionalProperties'
|
||||
'markdownDescription'
|
||||
)
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue