|
|
|
|
@ -6,6 +6,7 @@ from serpapi import GoogleSearch
|
|
|
|
|
|
|
|
|
|
from core.tools.entities.tool_entities import ToolInvokeMessage
|
|
|
|
|
from core.tools.tool.builtin_tool import BuiltinTool
|
|
|
|
|
from core.workflow.nodes.llm.knowledge_resource import KnowledgeResource
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class HiddenPrints:
|
|
|
|
|
@ -35,7 +36,7 @@ class SerpAPI:
|
|
|
|
|
self.serpapi_api_key = api_key
|
|
|
|
|
self.search_engine = GoogleSearch
|
|
|
|
|
|
|
|
|
|
def run(self, query: str, **kwargs: Any) -> str:
|
|
|
|
|
def run(self, query: str, **kwargs: Any) -> str | list[KnowledgeResource]:
|
|
|
|
|
"""Run query through SerpAPI and parse result."""
|
|
|
|
|
typ = kwargs.get("result_type", "text")
|
|
|
|
|
return self._process_response(self.results(query), typ=typ)
|
|
|
|
|
@ -64,63 +65,79 @@ class SerpAPI:
|
|
|
|
|
return params
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def _process_response(res: dict, typ: str) -> str:
|
|
|
|
|
def _process_response(res: dict, typ: str) -> str | list[KnowledgeResource]:
|
|
|
|
|
"""Process response from SerpAPI."""
|
|
|
|
|
if "error" in res.keys():
|
|
|
|
|
raise ValueError(f"Got error from SerpAPI: {res['error']}")
|
|
|
|
|
|
|
|
|
|
if typ == "text":
|
|
|
|
|
toret = ""
|
|
|
|
|
chunks = []
|
|
|
|
|
toret = ""
|
|
|
|
|
if typ == "text" or typ == "chunk":
|
|
|
|
|
if "answer_box" in res.keys() and type(res["answer_box"]) == list:
|
|
|
|
|
res["answer_box"] = res["answer_box"][0] + "\n"
|
|
|
|
|
if "answer_box" in res.keys() and "answer" in res["answer_box"].keys():
|
|
|
|
|
toret += res["answer_box"]["answer"] + "\n"
|
|
|
|
|
chunks.append(KnowledgeResource(content=res["answer_box"]["answer"], title=res["answer_box"]["answer"]))
|
|
|
|
|
if "answer_box" in res.keys() and "snippet" in res["answer_box"].keys():
|
|
|
|
|
toret += res["answer_box"]["snippet"] + "\n"
|
|
|
|
|
chunks.append(
|
|
|
|
|
KnowledgeResource(content=res["answer_box"]["snippet"], title=res["answer_box"]["snippet"]))
|
|
|
|
|
if (
|
|
|
|
|
"answer_box" in res.keys()
|
|
|
|
|
and "snippet_highlighted_words" in res["answer_box"].keys()
|
|
|
|
|
"answer_box" in res.keys()
|
|
|
|
|
and "snippet_highlighted_words" in res["answer_box"].keys()
|
|
|
|
|
):
|
|
|
|
|
for item in res["answer_box"]["snippet_highlighted_words"]:
|
|
|
|
|
toret += item + "\n"
|
|
|
|
|
chunks.append(KnowledgeResource(content=item, title=item))
|
|
|
|
|
if (
|
|
|
|
|
"sports_results" in res.keys()
|
|
|
|
|
and "game_spotlight" in res["sports_results"].keys()
|
|
|
|
|
"sports_results" in res.keys()
|
|
|
|
|
and "game_spotlight" in res["sports_results"].keys()
|
|
|
|
|
):
|
|
|
|
|
toret += res["sports_results"]["game_spotlight"] + "\n"
|
|
|
|
|
chunks.append(KnowledgeResource(content=res["sports_results"]["game_spotlight"],
|
|
|
|
|
title=res["sports_results"]["game_spotlight"]))
|
|
|
|
|
if (
|
|
|
|
|
"shopping_results" in res.keys()
|
|
|
|
|
and "title" in res["shopping_results"][0].keys()
|
|
|
|
|
"shopping_results" in res.keys()
|
|
|
|
|
and "title" in res["shopping_results"][0].keys()
|
|
|
|
|
):
|
|
|
|
|
toret += res["shopping_results"][:3] + "\n"
|
|
|
|
|
chunks.append(KnowledgeResource(content=res["shopping_results"][:3], title=res["shopping_results"][:3]))
|
|
|
|
|
if (
|
|
|
|
|
"knowledge_graph" in res.keys()
|
|
|
|
|
and "description" in res["knowledge_graph"].keys()
|
|
|
|
|
"knowledge_graph" in res.keys()
|
|
|
|
|
and "description" in res["knowledge_graph"].keys()
|
|
|
|
|
):
|
|
|
|
|
toret = res["knowledge_graph"]["description"] + "\n"
|
|
|
|
|
chunks.append(KnowledgeResource(content=res["knowledge_graph"]["description"],
|
|
|
|
|
title=res["knowledge_graph"]["description"]))
|
|
|
|
|
if "snippet" in res["organic_results"][0].keys():
|
|
|
|
|
for item in res["organic_results"]:
|
|
|
|
|
toret += "content: " + item["snippet"] + "\n" + "link: " + item["link"] + "\n"
|
|
|
|
|
chunks.append(KnowledgeResource(content=item["snippet"], title=item["title"], url=item["link"]))
|
|
|
|
|
if (
|
|
|
|
|
"images_results" in res.keys()
|
|
|
|
|
and "thumbnail" in res["images_results"][0].keys()
|
|
|
|
|
"images_results" in res.keys()
|
|
|
|
|
and "thumbnail" in res["images_results"][0].keys()
|
|
|
|
|
):
|
|
|
|
|
thumbnails = [item["thumbnail"] for item in res["images_results"][:10]]
|
|
|
|
|
toret = thumbnails
|
|
|
|
|
chunks.append(KnowledgeResource(content=thumbnails, title=thumbnails))
|
|
|
|
|
if toret == "":
|
|
|
|
|
toret = "No good search result found"
|
|
|
|
|
elif typ == "link":
|
|
|
|
|
if typ == "link" or typ == "chunk":
|
|
|
|
|
if "knowledge_graph" in res.keys() and "title" in res["knowledge_graph"].keys() \
|
|
|
|
|
and "description_link" in res["knowledge_graph"].keys():
|
|
|
|
|
toret = res["knowledge_graph"]["description_link"]
|
|
|
|
|
chunks.append(KnowledgeResource(content=res["knowledge_graph"]["description"],
|
|
|
|
|
title=res["knowledge_graph"]["title"],
|
|
|
|
|
url=res["knowledge_graph"]["knowledge_graph_search_link"])
|
|
|
|
|
)
|
|
|
|
|
elif "knowledge_graph" in res.keys() and "see_results_about" in res["knowledge_graph"].keys() \
|
|
|
|
|
and len(res["knowledge_graph"]["see_results_about"]) > 0:
|
|
|
|
|
and len(res["knowledge_graph"]["see_results_about"]) > 0:
|
|
|
|
|
see_result_about = res["knowledge_graph"]["see_results_about"]
|
|
|
|
|
toret = ""
|
|
|
|
|
for item in see_result_about:
|
|
|
|
|
if "name" not in item.keys() or "link" not in item.keys():
|
|
|
|
|
continue
|
|
|
|
|
toret += f"[{item['name']}]({item['link']})\n"
|
|
|
|
|
chunks.append(KnowledgeResource(content=f"[{item['name']}]({item['link']})\n", title=item['name'], url=item['link']))
|
|
|
|
|
elif "organic_results" in res.keys() and len(res["organic_results"]) > 0:
|
|
|
|
|
organic_results = res["organic_results"]
|
|
|
|
|
toret = ""
|
|
|
|
|
@ -128,6 +145,7 @@ class SerpAPI:
|
|
|
|
|
if "title" not in item.keys() or "link" not in item.keys():
|
|
|
|
|
continue
|
|
|
|
|
toret += f"[{item['title']}]({item['link']})\n"
|
|
|
|
|
chunks.append(KnowledgeResource(content=f"[{item['title']}]({item['link']})\n", title=item['title'], url=item['link']))
|
|
|
|
|
elif "related_questions" in res.keys() and len(res["related_questions"]) > 0:
|
|
|
|
|
related_questions = res["related_questions"]
|
|
|
|
|
toret = ""
|
|
|
|
|
@ -135,6 +153,7 @@ class SerpAPI:
|
|
|
|
|
if "question" not in item.keys() or "link" not in item.keys():
|
|
|
|
|
continue
|
|
|
|
|
toret += f"[{item['question']}]({item['link']})\n"
|
|
|
|
|
chunks.append(KnowledgeResource(content=f"[{item['question']}]({item['link']})\n", title=item['title'], url=item['link']))
|
|
|
|
|
elif "related_searches" in res.keys() and len(res["related_searches"]) > 0:
|
|
|
|
|
related_searches = res["related_searches"]
|
|
|
|
|
toret = ""
|
|
|
|
|
@ -142,15 +161,19 @@ class SerpAPI:
|
|
|
|
|
if "query" not in item.keys() or "link" not in item.keys():
|
|
|
|
|
continue
|
|
|
|
|
toret += f"[{item['query']}]({item['link']})\n"
|
|
|
|
|
chunks.append(KnowledgeResource(content=f"[{item['query']}]({item['link']})\n", title=item['query'], url=item['link']))
|
|
|
|
|
else:
|
|
|
|
|
toret = "No good search result found"
|
|
|
|
|
if typ == "chunk":
|
|
|
|
|
return chunks
|
|
|
|
|
return toret
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GoogleSearchTool(BuiltinTool):
|
|
|
|
|
def _invoke(self,
|
|
|
|
|
def _invoke(self,
|
|
|
|
|
user_id: str,
|
|
|
|
|
tool_parameters: dict[str, Any],
|
|
|
|
|
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
|
|
|
|
|
tool_parameters: dict[str, Any],
|
|
|
|
|
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
|
|
|
|
|
"""
|
|
|
|
|
invoke tools
|
|
|
|
|
"""
|
|
|
|
|
@ -160,5 +183,9 @@ class GoogleSearchTool(BuiltinTool):
|
|
|
|
|
result = SerpAPI(api_key).run(query, result_type=result_type)
|
|
|
|
|
if result_type == 'text':
|
|
|
|
|
return self.create_text_message(text=result)
|
|
|
|
|
return self.create_link_message(link=result)
|
|
|
|
|
|
|
|
|
|
elif result_type == 'link':
|
|
|
|
|
return self.create_link_message(link=result)
|
|
|
|
|
elif result_type == 'chunk':
|
|
|
|
|
return self.create_chunk_message(chunks=result)
|
|
|
|
|
else:
|
|
|
|
|
raise ValueError(f"Invalid result type: {result_type}")
|
|
|
|
|
|