Source code for langchain_community.utilities.google_books

"""Util that calls Google Books."""

from typing import Dict, List, Optional

import requests
from langchain_core.utils import get_from_dict_or_env
from pydantic import BaseModel, ConfigDict, model_validator

GOOGLE_BOOKS_MAX_ITEM_SIZE = 5
GOOGLE_BOOKS_API_URL = "https://www.googleapis.com/books/v1/volumes"


[docs] class GoogleBooksAPIWrapper(BaseModel): """Wrapper around Google Books API. To use, you should have a Google Books API key available. This wrapper will use the Google Books API to conduct searches and fetch books based on a query passed in by the agents. By default, it will return the top-k results. The response for each book will contain the book title, author name, summary, and a source link. """ google_books_api_key: Optional[str] = None top_k_results: int = GOOGLE_BOOKS_MAX_ITEM_SIZE model_config = ConfigDict( extra="forbid", ) @model_validator(mode="before") @classmethod def validate_environment(cls, values: Dict) -> Dict: """Validate that api key exists in environment.""" google_books_api_key = get_from_dict_or_env( values, "google_books_api_key", "GOOGLE_BOOKS_API_KEY" ) values["google_books_api_key"] = google_books_api_key return values
[docs] def run(self, query: str) -> str: # build Url based on API key, query, and max results params = ( ("q", query), ("maxResults", self.top_k_results), ("key", self.google_books_api_key), ) # send request response = requests.get(GOOGLE_BOOKS_API_URL, params=params) json = response.json() # some error handeling if response.status_code != 200: code = response.status_code error = json.get("error", {}).get("message", "Internal failure") return f"Unable to retrieve books got status code {code}: {error}" # send back data return self._format(query, json.get("items", []))
def _format(self, query: str, books: List) -> str: if not books: return f"Sorry no books could be found for your query: {query}" start = f"Here are {len(books)} suggestions for books related to {query}:" results = [] results.append(start) i = 1 for book in books: info = book["volumeInfo"] title = info["title"] authors = self._format_authors(info["authors"]) summary = info["description"] source = info["infoLink"] desc = f'{i}. "{title}" by {authors}: {summary}\n' desc += f"You can read more at {source}" results.append(desc) i += 1 return "\n\n".join(results) def _format_authors(self, authors: List) -> str: if len(authors) == 1: return authors[0] return "{} and {}".format(", ".join(authors[:-1]), authors[-1])