diff --git a/docs/core_docs/docs/integrations/tools/google_trends.mdx b/docs/core_docs/docs/integrations/tools/google_trends.mdx index f5fc69985e8e..bbbdec5d70c0 100644 --- a/docs/core_docs/docs/integrations/tools/google_trends.mdx +++ b/docs/core_docs/docs/integrations/tools/google_trends.mdx @@ -11,6 +11,9 @@ This can be useful for understanding trending topics, regional search interest, For API details see [here](https://serpapi.com/google-trends-api) +SerpApi caches queries, so the first query will be slower while subsequent identical queries will be fast. +Occasionally, related queries will not work while interest over time will be fine. You can check your query [here](https://serpapi.com/playground?engine=google_trends&q=monster&data_type=RELATED_QUERIES). + ## Setup To use this tool, you will need to configure access to the Google Trends API from SerpApi. diff --git a/examples/src/tools/google_trends.ts b/examples/src/tools/google_trends.ts index 2934b9a1a7f7..25cf5f174ba3 100644 --- a/examples/src/tools/google_trends.ts +++ b/examples/src/tools/google_trends.ts @@ -1,9 +1,9 @@ -import { GoogleTrendsAPI } from "@langchain/community/tools/google_trends"; +import { SERPGoogleTrendsTool } from "@langchain/community/tools/google_trends"; export async function run() { - const tool = new GoogleTrendsAPI(); + const tool = new SERPGoogleTrendsTool(); - const res = await tool._call("Monster"); + const res = await tool.invoke("Monster"); console.log(res); } diff --git a/libs/langchain-community/src/tools/google_trends.ts b/libs/langchain-community/src/tools/google_trends.ts index 461dd9594661..18f063e791e8 100644 --- a/libs/langchain-community/src/tools/google_trends.ts +++ b/libs/langchain-community/src/tools/google_trends.ts @@ -2,18 +2,33 @@ import { getEnvironmentVariable } from "@langchain/core/utils/env"; import { Tool } from "@langchain/core/tools"; /** - * Interface for parameters required by GoogleTrendsAPI class. + * Interfaces for the response from the SerpApi Google Trends API. */ -export interface GoogleTrendsAPIParams { +interface TimelineValue { + query: string; + value: string; + extracted_value: number; +} + +interface TimelineData { + date: string; + timestamp: string; + values: TimelineValue[]; +} + +/** + * Interface for parameters required by SERPGoogleTrendsTool class. + */ +export interface SERPGoogleTrendsToolParams { apiKey?: string; } /** * Tool that queries the Google Trends API. Uses default interest over time. */ -export class GoogleTrendsAPI extends Tool { +export class SERPGoogleTrendsTool extends Tool { static lc_name() { - return "GoogleTrendsAPI"; + return "SERPGoogleTrendsTool"; } get lc_secrets(): { [key: string]: string } | undefined { @@ -29,7 +44,7 @@ export class GoogleTrendsAPI extends Tool { description = `A wrapper around Google Trends API. Useful for analyzing and retrieving trending search data based on keywords, categories, or regions. Input should be a search query or specific parameters for trends analysis.`; - constructor(fields?: GoogleTrendsAPIParams) { + constructor(fields?: SERPGoogleTrendsToolParams) { super(...arguments); const apiKey = fields?.apiKey ?? getEnvironmentVariable("SERPAPI_API_KEY"); if (apiKey === undefined) { @@ -45,6 +60,9 @@ export class GoogleTrendsAPI extends Tool { * Related queries only accepts one at a time, and multiple * queries at once on interest over time (default) is effectively the same as * each query one by one. + * + * SerpApi caches queries, so the first time will be slower + * and subsequent identical queries will be very fast. */ if (query.split(",").length > 1) { throw new Error("Please do one query at a time"); @@ -80,7 +98,7 @@ export class GoogleTrendsAPI extends Tool { const startDate = totalResults[0].date.split(" "); const endDate = totalResults[totalResults.length - 1].date.split(" "); const values = totalResults.map( - (result: any) => result.values[0].extracted_value + (result: TimelineData) => result.values[0].extracted_value ); const minValue = Math.min(...values); const maxValue = Math.max(...values); @@ -109,6 +127,7 @@ export class GoogleTrendsAPI extends Tool { let rising = []; let top = []; if (!relatedRes.ok) { + // Sometimes related queries from SerpAPI will fail, but interest over time will be fine console.error( `Error fetching related queries from SerpAPI: ${relatedRes.statusText}` ); @@ -116,11 +135,12 @@ export class GoogleTrendsAPI extends Tool { const relatedDict = await relatedRes.json(); rising = relatedDict.related_queries?.rising?.map( - (result: any) => result.query + (result: { query: string }) => result.query ) ?? []; top = - relatedDict.related_queries?.top?.map((result: any) => result.query) ?? - []; + relatedDict.related_queries?.top?.map( + (result: { query: string }) => result.query + ) ?? []; } const doc = [ diff --git a/libs/langchain-community/src/tools/tests/google_trends.int.test.ts b/libs/langchain-community/src/tools/tests/google_trends.int.test.ts index e51175be998b..49be189bd7ad 100644 --- a/libs/langchain-community/src/tools/tests/google_trends.int.test.ts +++ b/libs/langchain-community/src/tools/tests/google_trends.int.test.ts @@ -1,14 +1,14 @@ import { expect, describe } from "@jest/globals"; -import { GoogleTrendsAPI } from "../google_trends.js"; +import { SERPGoogleTrendsTool } from "../google_trends.js"; -describe("GoogleTrendsAPI", () => { +describe("SERPGoogleTrendsTool", () => { test("should be setup with correct parameters", async () => { - const instance = new GoogleTrendsAPI(); + const instance = new SERPGoogleTrendsTool(); expect(instance.name).toBe("google_trends"); }); - test("GoogleTrendsAPI returns expected result for valid query", async () => { - const tool = new GoogleTrendsAPI(); + test("SERPGoogleTrendsTool returns expected result for valid query", async () => { + const tool = new SERPGoogleTrendsTool(); const result = await tool._call("Coffee"); @@ -24,8 +24,8 @@ describe("GoogleTrendsAPI", () => { expect(result).toContain("Top Related Queries:"); }); - test("GoogleTrendsAPI returns 'No good Trend Result was found' for a non-existent query", async () => { - const tool = new GoogleTrendsAPI(); + test("SERPGoogleTrendsTool returns 'No good Trend Result was found' for a non-existent query", async () => { + const tool = new SERPGoogleTrendsTool(); const result = await tool._call("earghajgpajrpgjaprgag");