Skip to content

Commit

Permalink
refactor: Update Serp API component to standard output pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
raphaelchristi committed Dec 25, 2024
1 parent b4673d3 commit 30f0279
Showing 1 changed file with 41 additions and 44 deletions.
85 changes: 41 additions & 44 deletions src/backend/base/langflow/components/tools/serp_api.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from typing import Any

from langchain.tools import StructuredTool
from langchain_community.utilities.serpapi import SerpAPIWrapper
from langchain_core.tools import ToolException
from loguru import logger
from pydantic import BaseModel, Field

from langflow.base.langchain_utilities.model import LCToolComponent
from langflow.field_typing import Tool
from langflow.custom import Component
from langflow.inputs import DictInput, IntInput, MultilineInput, SecretStrInput
from langflow.io import Output
from langflow.schema import Data
from langflow.schema.message import Message


class SerpAPISchema(BaseModel):
Expand All @@ -29,7 +29,7 @@ class SerpAPISchema(BaseModel):
max_snippet_length: int = Field(100, description="Maximum length of each result snippet")


class SerpAPIComponent(LCToolComponent):
class SerpAPIComponent(Component):
display_name = "Serp Search API"
description = "Call Serp Search API with result limiting"
name = "SerpAPI"
Expand All @@ -40,12 +40,18 @@ class SerpAPIComponent(LCToolComponent):
MultilineInput(
name="input_value",
display_name="Input",
tool_mode=True,
),
DictInput(name="search_params", display_name="Parameters", advanced=True, is_list=True),
IntInput(name="max_results", display_name="Max Results", value=5, advanced=True),
IntInput(name="max_snippet_length", display_name="Max Snippet Length", value=100, advanced=True),
]

outputs = [
Output(display_name="Data", name="data", method="fetch_content"),
Output(display_name="Text", name="text", method="fetch_content_text"),
]

def _build_wrapper(self, params: dict[str, Any] | None = None) -> SerpAPIWrapper:
"""Build a SerpAPIWrapper with the provided parameters."""
params = params or {}
Expand All @@ -56,12 +62,15 @@ def _build_wrapper(self, params: dict[str, Any] | None = None) -> SerpAPIWrapper
)
return SerpAPIWrapper(serpapi_api_key=self.serpapi_api_key)

def build_tool(self) -> Tool:
def run_model(self) -> list[Data]:
return self.fetch_content()

def fetch_content(self) -> list[Data]:
wrapper = self._build_wrapper(self.search_params)

def search_func(
query: str, params: dict[str, Any] | None = None, max_results: int = 5, max_snippet_length: int = 100
) -> list[dict[str, Any]]:
) -> list[Data]:
try:
local_wrapper = wrapper
if params:
Expand All @@ -70,49 +79,37 @@ def search_func(
full_results = local_wrapper.results(query)
organic_results = full_results.get("organic_results", [])[:max_results]

limited_results = []
for result in organic_results:
limited_result = {
"title": result.get("title", "")[:max_snippet_length],
"link": result.get("link", ""),
"snippet": result.get("snippet", "")[:max_snippet_length],
}
limited_results.append(limited_result)
limited_results = [
Data(
text=result.get("snippet", ""),
data={
"title": result.get("title", "")[:max_snippet_length],
"link": result.get("link", ""),
"snippet": result.get("snippet", "")[:max_snippet_length],
},
)
for result in organic_results
]

except Exception as e:
error_message = f"Error in SerpAPI search: {e!s}"
logger.debug(error_message)
raise ToolException(error_message) from e
return limited_results

tool = StructuredTool.from_function(
name="serp_search_api",
description="Search for recent results using SerpAPI with result limiting",
func=search_func,
args_schema=SerpAPISchema,
results = search_func(
self.input_value,
params=self.search_params,
max_results=self.max_results,
max_snippet_length=self.max_snippet_length,
)

self.status = "SerpAPI Tool created"
return tool

def run_model(self) -> list[Data]:
tool = self.build_tool()
try:
results = tool.run(
{
"query": self.input_value,
"params": self.search_params or {},
"max_results": self.max_results,
"max_snippet_length": self.max_snippet_length,
}
)

data_list = [Data(data=result, text=result.get("snippet", "")) for result in results]

except Exception as e: # noqa: BLE001
logger.opt(exception=True).debug("Error running SerpAPI")
self.status = f"Error: {e}"
return [Data(data={"error": str(e)}, text=str(e))]

self.status = data_list # type: ignore[assignment]
return data_list
self.status = results
return results

def fetch_content_text(self) -> Message:
data = self.fetch_content()
result_string = ""
for item in data:
result_string += item.text + "\n"
self.status = result_string
return Message(text=result_string)

0 comments on commit 30f0279

Please sign in to comment.