UNPKG

@langchain/community

Version:
1 lines 7.29 kB
{"version":3,"file":"stackexchange.cjs","names":["Tool"],"sources":["../../src/tools/stackexchange.ts"],"sourcesContent":["import { Tool } from \"@langchain/core/tools\";\n\nexport interface StackExchangeAnswer {\n items: StackExchangeItem[];\n has_more: boolean;\n quota_max: number;\n quota_remaining: number;\n}\n\nexport interface StackExchangeItem {\n tags: string[];\n question_score: number;\n is_accepted: boolean;\n has_accepted_answer?: boolean;\n answer_count?: number;\n is_answered: boolean;\n question_id: number;\n item_type: string;\n score: number;\n last_activity_date: number;\n creation_date: number;\n body: string;\n excerpt: string;\n title: string;\n answer_id?: number;\n}\n\ntype StackExchangeOptions = Record<string, string | number | boolean>;\n\nexport interface StackExchangeAPIParams {\n /**\n * The maximum number of results to return from the search.\n * Limiting to 10 to avoid context overload.\n * @default 3\n */\n maxResult?: number;\n /**\n * Which part of StackOverflows items to match against. One of 'all', 'title',\n * 'body'.\n * @default \"all\"\n */\n queryType?: \"all\" | \"title\" | \"body\";\n /**\n * Additional params to pass to the StackExchange API\n */\n options?: StackExchangeOptions;\n /**\n * Separator between question,answer pairs.\n * @default \"\\n\\n\"\n */\n resultSeparator?: string;\n}\n\n/**\n * Class for interacting with the StackExchange API\n * It extends the base Tool class to perform retrieval.\n */\nexport class StackExchangeAPI extends Tool {\n name = \"stackexchange\";\n\n description = \"Stack Exchange API Implementation\";\n\n private pageSize: number;\n\n private maxResult = 3;\n\n private key: string | null;\n\n private accessToken: string | null;\n\n private site = \"stackoverflow\";\n\n private version = \"2.3\";\n\n private baseUrl = \"https://api.stackexchange.com\";\n\n private queryType = \"all\";\n\n private options?: StackExchangeOptions = {};\n\n private resultSeparator?: string = \"\\n\\n\";\n\n constructor(params: StackExchangeAPIParams = {}) {\n const { maxResult, queryType = \"all\", options, resultSeparator } = params;\n super();\n this.maxResult = maxResult || this.maxResult;\n this.pageSize = 100;\n this.baseUrl = `${this.baseUrl}/${this.version}/`;\n this.queryType = queryType === \"all\" ? \"q\" : queryType;\n this.options = options || this.options;\n this.resultSeparator = resultSeparator || this.resultSeparator;\n }\n\n async _call(query: string): Promise<string> {\n const params = {\n [this.queryType]: query,\n site: this.site,\n ...this.options,\n };\n const output = await this._fetch<StackExchangeAnswer>(\n \"search/excerpts\",\n params\n );\n if (output.items.length < 1) {\n return `No relevant results found for '${query}' on Stack Overflow.`;\n }\n const questions = output.items\n .filter((item) => item.item_type === \"question\")\n .slice(0, this.maxResult);\n const answers = output.items.filter((item) => item.item_type === \"answer\");\n\n const results: string[] = [];\n\n for (const question of questions) {\n let res_text = `Question: ${question.title}\\n${question.excerpt}`;\n\n const relevant_answers = answers.filter(\n (answer) => answer.question_id === question.question_id\n );\n const accepted_answers = relevant_answers.filter(\n (answer) => answer.is_accepted\n );\n\n if (relevant_answers.length > 0) {\n const top_answer =\n accepted_answers.length > 0\n ? accepted_answers[0]\n : relevant_answers[0];\n const { excerpt } = top_answer;\n res_text += `\\nAnswer: ${excerpt}`;\n }\n\n results.push(res_text);\n }\n\n return results.join(this.resultSeparator);\n }\n\n /**\n * Call the StackExchange API\n * @param endpoint Name of the endpoint from StackExchange API\n * @param params Additional parameters passed to the endpoint\n * @param page Number of the page to retrieve\n * @param filter Filtering properties\n */\n private async _fetch<T>(\n endpoint: string,\n params: StackExchangeOptions = {},\n page = 1,\n filter = \"default\"\n ): Promise<T> {\n try {\n if (!endpoint) {\n throw new Error(\"No end point provided.\");\n }\n const queryParams = new URLSearchParams({\n pagesize: this.pageSize.toString(),\n page: page.toString(),\n filter,\n ...params,\n });\n\n if (this.key) {\n queryParams.append(\"key\", this.key);\n }\n if (this.accessToken) {\n queryParams.append(\"access_token\", this.accessToken);\n }\n\n const queryParamsString = queryParams.toString();\n\n const endpointUrl = `${this.baseUrl}${endpoint}?${queryParamsString}`;\n return await this._makeRequest(endpointUrl);\n } catch {\n throw new Error(\"Error while calling Stack Exchange API\");\n }\n }\n\n /**\n * Fetch the result of a specific endpoint\n * @param endpointUrl Endpoint to call\n */\n private async _makeRequest<T>(endpointUrl: string): Promise<T> {\n try {\n const response = await fetch(endpointUrl);\n if (response.status !== 200) {\n throw new Error(`HTTP Error: ${response.statusText}`);\n }\n return await response.json();\n } catch {\n throw new Error(`Error while calling Stack Exchange API: ${endpointUrl}`);\n }\n }\n}\n"],"mappings":";;;;;;;;;AAyDA,IAAa,mBAAb,cAAsCA,sBAAAA,KAAK;CACzC,OAAO;CAEP,cAAc;CAEd;CAEA,YAAoB;CAEpB;CAEA;CAEA,OAAe;CAEf,UAAkB;CAElB,UAAkB;CAElB,YAAoB;CAEpB,UAAyC,EAAE;CAE3C,kBAAmC;CAEnC,YAAY,SAAiC,EAAE,EAAE;EAC/C,MAAM,EAAE,WAAW,YAAY,OAAO,SAAS,oBAAoB;AACnE,SAAO;AACP,OAAK,YAAY,aAAa,KAAK;AACnC,OAAK,WAAW;AAChB,OAAK,UAAU,GAAG,KAAK,QAAQ,GAAG,KAAK,QAAQ;AAC/C,OAAK,YAAY,cAAc,QAAQ,MAAM;AAC7C,OAAK,UAAU,WAAW,KAAK;AAC/B,OAAK,kBAAkB,mBAAmB,KAAK;;CAGjD,MAAM,MAAM,OAAgC;EAC1C,MAAM,SAAS;IACZ,KAAK,YAAY;GAClB,MAAM,KAAK;GACX,GAAG,KAAK;GACT;EACD,MAAM,SAAS,MAAM,KAAK,OACxB,mBACA,OACD;AACD,MAAI,OAAO,MAAM,SAAS,EACxB,QAAO,kCAAkC,MAAM;EAEjD,MAAM,YAAY,OAAO,MACtB,QAAQ,SAAS,KAAK,cAAc,WAAW,CAC/C,MAAM,GAAG,KAAK,UAAU;EAC3B,MAAM,UAAU,OAAO,MAAM,QAAQ,SAAS,KAAK,cAAc,SAAS;EAE1E,MAAM,UAAoB,EAAE;AAE5B,OAAK,MAAM,YAAY,WAAW;GAChC,IAAI,WAAW,aAAa,SAAS,MAAM,IAAI,SAAS;GAExD,MAAM,mBAAmB,QAAQ,QAC9B,WAAW,OAAO,gBAAgB,SAAS,YAC7C;GACD,MAAM,mBAAmB,iBAAiB,QACvC,WAAW,OAAO,YACpB;AAED,OAAI,iBAAiB,SAAS,GAAG;IAK/B,MAAM,EAAE,YAHN,iBAAiB,SAAS,IACtB,iBAAiB,KACjB,iBAAiB;AAEvB,gBAAY,aAAa;;AAG3B,WAAQ,KAAK,SAAS;;AAGxB,SAAO,QAAQ,KAAK,KAAK,gBAAgB;;;;;;;;;CAU3C,MAAc,OACZ,UACA,SAA+B,EAAE,EACjC,OAAO,GACP,SAAS,WACG;AACZ,MAAI;AACF,OAAI,CAAC,SACH,OAAM,IAAI,MAAM,yBAAyB;GAE3C,MAAM,cAAc,IAAI,gBAAgB;IACtC,UAAU,KAAK,SAAS,UAAU;IAClC,MAAM,KAAK,UAAU;IACrB;IACA,GAAG;IACJ,CAAC;AAEF,OAAI,KAAK,IACP,aAAY,OAAO,OAAO,KAAK,IAAI;AAErC,OAAI,KAAK,YACP,aAAY,OAAO,gBAAgB,KAAK,YAAY;GAGtD,MAAM,oBAAoB,YAAY,UAAU;GAEhD,MAAM,cAAc,GAAG,KAAK,UAAU,SAAS,GAAG;AAClD,UAAO,MAAM,KAAK,aAAa,YAAY;UACrC;AACN,SAAM,IAAI,MAAM,yCAAyC;;;;;;;CAQ7D,MAAc,aAAgB,aAAiC;AAC7D,MAAI;GACF,MAAM,WAAW,MAAM,MAAM,YAAY;AACzC,OAAI,SAAS,WAAW,IACtB,OAAM,IAAI,MAAM,eAAe,SAAS,aAAa;AAEvD,UAAO,MAAM,SAAS,MAAM;UACtB;AACN,SAAM,IAAI,MAAM,2CAA2C,cAAc"}