kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: add SerpAPI as tool
rodzic
487db113ab
commit
30e0d21e31
|
@ -2,43 +2,32 @@ import { OpenAIClient } from '@agentic/openai-fetch'
|
|||
import 'dotenv/config'
|
||||
import { z } from 'zod'
|
||||
|
||||
import { Agentic, MetaphorSearchTool } from '@/index'
|
||||
import { Agentic, SerpAPITool } from '@/index'
|
||||
|
||||
async function main() {
|
||||
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
||||
const $ = new Agentic({ openai })
|
||||
const metaphorSearch = new MetaphorSearchTool({ agentic: $ })
|
||||
const agentic = new Agentic({ openai })
|
||||
|
||||
const { results: searchResults } = await metaphorSearch.call({
|
||||
query: 'news from today, 2023',
|
||||
numResults: 5
|
||||
})
|
||||
|
||||
console.log('searchResults', searchResults)
|
||||
|
||||
const res = await $.gpt4(
|
||||
`Give me a summary of today's news. Here is what I got back from a search engine: \n{{#searchResults}}{{title}}\n{{/searchResults}}`
|
||||
const res = await agentic
|
||||
.gpt4(
|
||||
`Can you summarize the top {{numResults}} results for today's news about {{topic}}?`
|
||||
)
|
||||
.tools([new SerpAPITool()])
|
||||
.input(
|
||||
z.object({
|
||||
searchResults: z.any() // TODO
|
||||
topic: z.string(),
|
||||
numResults: z.number().default(3)
|
||||
})
|
||||
)
|
||||
.output(
|
||||
z.object({
|
||||
summary: z.string(),
|
||||
linkToLearnMore: z.string(),
|
||||
metadata: z.object({
|
||||
title: z.string(),
|
||||
keyTopics: z.string().array(),
|
||||
datePublished: z.string()
|
||||
}),
|
||||
isWorthFollowingUp: z.boolean()
|
||||
summary: z.string()
|
||||
})
|
||||
)
|
||||
.call({
|
||||
searchResults
|
||||
topic: 'OpenAI'
|
||||
})
|
||||
|
||||
console.log(res)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export * from './calculator'
|
||||
export * from './metaphor'
|
||||
export * from './novu'
|
||||
export * from './serpapi'
|
||||
export * from './weather'
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
import { z } from 'zod'
|
||||
|
||||
import * as types from '@/types'
|
||||
import { SerpAPIClient } from '@/services/serpapi'
|
||||
import { BaseTask } from '@/task'
|
||||
|
||||
export const SerpAPIInputSchema = z.object({
|
||||
query: z.string().describe('search query'),
|
||||
numResults: z.number().int().positive().default(10).optional()
|
||||
})
|
||||
export type SerpAPIInput = z.infer<typeof SerpAPIInputSchema>
|
||||
|
||||
export const SerpAPIOrganicSearchResult = z.object({
|
||||
position: z.number(),
|
||||
title: z.string(),
|
||||
link: z.string(),
|
||||
displayed_link: z.string(),
|
||||
snippet: z.string(),
|
||||
source: z.string().optional(),
|
||||
date: z.string().optional()
|
||||
})
|
||||
|
||||
export const SerpAPIAnswerBox = z.object({
|
||||
type: z.string(),
|
||||
title: z.string(),
|
||||
link: z.string(),
|
||||
displayed_link: z.string(),
|
||||
snippet: z.string()
|
||||
})
|
||||
|
||||
export const SerpAPIKnowledgeGraph = z.object({
|
||||
type: z.string(),
|
||||
description: z.string()
|
||||
})
|
||||
|
||||
export const SerpAPIOutputSchema = z.object({
|
||||
knowledgeGraph: SerpAPIKnowledgeGraph.optional(),
|
||||
answerBox: SerpAPIAnswerBox.optional(),
|
||||
organicResults: z.array(SerpAPIOrganicSearchResult)
|
||||
})
|
||||
export type SerpAPIOutput = z.infer<typeof SerpAPIOutputSchema>
|
||||
|
||||
export class SerpAPITool extends BaseTask<SerpAPIInput, SerpAPIOutput> {
|
||||
protected _serpapiClient: SerpAPIClient
|
||||
|
||||
constructor(
|
||||
opts: {
|
||||
serpapi?: SerpAPIClient
|
||||
} & types.BaseTaskOptions = {}
|
||||
) {
|
||||
super(opts)
|
||||
|
||||
this._serpapiClient =
|
||||
opts.serpapi ?? new SerpAPIClient({ ky: opts.agentic?.ky })
|
||||
}
|
||||
|
||||
public override get inputSchema() {
|
||||
return SerpAPIInputSchema
|
||||
}
|
||||
|
||||
public override get outputSchema() {
|
||||
return SerpAPIOutputSchema
|
||||
}
|
||||
|
||||
public override get nameForModel(): string {
|
||||
return 'googleWebSearch'
|
||||
}
|
||||
|
||||
public override get nameForHuman(): string {
|
||||
return 'SerpAPI'
|
||||
}
|
||||
|
||||
public override get descForModel(): string {
|
||||
return 'Uses Google to search the web and return the most relevant results.'
|
||||
}
|
||||
|
||||
protected override async _call(
|
||||
ctx: types.TaskCallContext<SerpAPIInput>
|
||||
): Promise<SerpAPIOutput> {
|
||||
const res = await this._serpapiClient.search({
|
||||
q: ctx.input!.query,
|
||||
num: ctx.input!.numResults
|
||||
})
|
||||
|
||||
return this.outputSchema.parse({
|
||||
knowledgeGraph: res.knowledge_graph,
|
||||
answerBox: res.answer_box,
|
||||
organicResults: res.organic_results
|
||||
})
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue