UNPKG

@langchain/community

Version:
1 lines • 7.65 kB
{"version":3,"file":"stackexchange.cjs","names":["Tool","params: StackExchangeAPIParams","query: string","results: string[]","endpoint: string","params: StackExchangeOptions","endpointUrl: string"],"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,4BAAK;CACzC,OAAO;CAEP,cAAc;CAEd,AAAQ;CAER,AAAQ,YAAY;CAEpB,AAAQ;CAER,AAAQ;CAER,AAAQ,OAAO;CAEf,AAAQ,UAAU;CAElB,AAAQ,UAAU;CAElB,AAAQ,YAAY;CAEpB,AAAQ,UAAiC,CAAE;CAE3C,AAAQ,kBAA2B;CAEnC,YAAYC,SAAiC,CAAE,GAAE;EAC/C,MAAM,EAAE,WAAW,YAAY,OAAO,SAAS,iBAAiB,GAAG;EACnE,OAAO;EACP,KAAK,YAAY,aAAa,KAAK;EACnC,KAAK,WAAW;EAChB,KAAK,UAAU,GAAG,KAAK,QAAQ,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;EACjD,KAAK,YAAY,cAAc,QAAQ,MAAM;EAC7C,KAAK,UAAU,WAAW,KAAK;EAC/B,KAAK,kBAAkB,mBAAmB,KAAK;CAChD;CAED,MAAM,MAAMC,OAAgC;EAC1C,MAAM,SAAS;IACZ,KAAK,YAAY;GAClB,MAAM,KAAK;GACX,GAAG,KAAK;EACT;EACD,MAAM,SAAS,MAAM,KAAK,OACxB,mBACA,OACD;AACD,MAAI,OAAO,MAAM,SAAS,EACxB,QAAO,CAAC,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;EAEtE,MAAM,YAAY,OAAO,MACtB,OAAO,CAAC,SAAS,KAAK,cAAc,WAAW,CAC/C,MAAM,GAAG,KAAK,UAAU;EAC3B,MAAM,UAAU,OAAO,MAAM,OAAO,CAAC,SAAS,KAAK,cAAc,SAAS;EAE1E,MAAMC,UAAoB,CAAE;AAE5B,OAAK,MAAM,YAAY,WAAW;GAChC,IAAI,WAAW,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,SAAS,SAAS;GAEjE,MAAM,mBAAmB,QAAQ,OAC/B,CAAC,WAAW,OAAO,gBAAgB,SAAS,YAC7C;GACD,MAAM,mBAAmB,iBAAiB,OACxC,CAAC,WAAW,OAAO,YACpB;AAED,OAAI,iBAAiB,SAAS,GAAG;IAC/B,MAAM,aACJ,iBAAiB,SAAS,IACtB,iBAAiB,KACjB,iBAAiB;IACvB,MAAM,EAAE,SAAS,GAAG;IACpB,YAAY,CAAC,UAAU,EAAE,SAAS;GACnC;GAED,QAAQ,KAAK,SAAS;EACvB;AAED,SAAO,QAAQ,KAAK,KAAK,gBAAgB;CAC1C;;;;;;;;CASD,MAAc,OACZC,UACAC,SAA+B,CAAE,GACjC,OAAO,GACP,SAAS,WACG;AACZ,MAAI;AACF,OAAI,CAAC,SACH,OAAM,IAAI,MAAM;GAElB,MAAM,cAAc,IAAI,gBAAgB;IACtC,UAAU,KAAK,SAAS,UAAU;IAClC,MAAM,KAAK,UAAU;IACrB;IACA,GAAG;GACJ;AAED,OAAI,KAAK,KACP,YAAY,OAAO,OAAO,KAAK,IAAI;AAErC,OAAI,KAAK,aACP,YAAY,OAAO,gBAAgB,KAAK,YAAY;GAGtD,MAAM,oBAAoB,YAAY,UAAU;GAEhD,MAAM,cAAc,GAAG,KAAK,UAAU,SAAS,CAAC,EAAE,mBAAmB;AACrE,UAAO,MAAM,KAAK,aAAa,YAAY;EAC5C,QAAO;AACN,SAAM,IAAI,MAAM;EACjB;CACF;;;;;CAMD,MAAc,aAAgBC,aAAiC;AAC7D,MAAI;GACF,MAAM,WAAW,MAAM,MAAM,YAAY;AACzC,OAAI,SAAS,WAAW,IACtB,OAAM,IAAI,MAAM,CAAC,YAAY,EAAE,SAAS,YAAY;AAEtD,UAAO,MAAM,SAAS,MAAM;EAC7B,QAAO;AACN,SAAM,IAAI,MAAM,CAAC,wCAAwC,EAAE,aAAa;EACzE;CACF;AACF"}