From 5d2fa3afe1caecb837623a8145106f1c3a6bde96 Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Mon, 23 Sep 2024 09:53:50 -0700 Subject: [PATCH 01/20] added some rate limit checks into llm wrapper class --- paperqa/llms.py | 23 ++- paperqa/rate_limiter.py | 334 ++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 2 + uv.lock | 103 ++++++++++++- 4 files changed, 460 insertions(+), 2 deletions(-) create mode 100644 paperqa/rate_limiter.py diff --git a/paperqa/llms.py b/paperqa/llms.py index 6c9b7401..248f3988 100644 --- a/paperqa/llms.py +++ b/paperqa/llms.py @@ -7,7 +7,8 @@ from enum import StrEnum from inspect import signature from sys import version_info -from typing import Any +from typing import Any, ClassVar +from xml.dom.pulldom import CHARACTERS import numpy as np import tiktoken @@ -17,6 +18,7 @@ from paperqa.prompts import default_system_prompt from paperqa.types import Embeddable, LLMResult from paperqa.utils import is_coroutine_callable +from paperqa.rate_limiter import GLOBAL_LIMITER PromptRunner = Callable[ [dict, list[Callable[[str], None]] | None, str | None], @@ -366,6 +368,8 @@ class LiteLLMModel(LLMModel): `model_list`: stores a list of all model configurations (see https://docs.litellm.ai/docs/routing) `router_kwargs`: kwargs for the Router class + `rate_limits`: (Optional) dictionary keyed by model group name + with values of type limits.RateLimitItem (in tokens / minute) This way users can specify routing strategies, retries, etc. """ @@ -373,6 +377,7 @@ class LiteLLMModel(LLMModel): config: dict = Field(default_factory=dict) name: str = "gpt-4o-mini" _router: Router | None = None + CHARACTERS_PER_TOKEN: ClassVar[float] = 4.0 @model_validator(mode="before") @classmethod @@ -424,8 +429,15 @@ def router(self): ) return self._router + async def check_rate_limit(self, token_count: float): + await GLOBAL_LIMITER.try_acquire(('client', self.name), + self.config.get("rate_limits", {}).get(self.name, None), + weight=token_count) + async def acomplete(self, prompt: str) -> Chunk: + await self.check_rate_limit(len(prompt) / self.CHARACTERS_PER_TOKEN) response = await self.router.atext_completion(model=self.name, prompt=prompt) + await self.check_rate_limit(response.usage.completion_tokens) return Chunk( text=response.choices[0].text, prompt_tokens=response.usage.prompt_tokens, @@ -433,6 +445,7 @@ async def acomplete(self, prompt: str) -> Chunk: ) async def acomplete_iter(self, prompt: str) -> AsyncIterable[Chunk]: + await self.check_rate_limit(len(prompt) / self.CHARACTERS_PER_TOKEN) completion = await self.router.atext_completion( model=self.name, prompt=prompt, @@ -440,16 +453,21 @@ async def acomplete_iter(self, prompt: str) -> AsyncIterable[Chunk]: stream_options={"include_usage": True}, ) async for chunk in completion: + await self.check_rate_limit(len(chunk.choices[0].text) / self.CHARACTERS_PER_TOKEN) yield Chunk( text=chunk.choices[0].text, prompt_tokens=0, completion_tokens=0 ) if hasattr(chunk, "usage") and hasattr(chunk.usage, "prompt_tokens"): + #TODO: should this access chunk.usage and chunk.usage.prompt_tokens? + await self.check_rate_limit(len(chunk.choices[0].text) / self.CHARACTERS_PER_TOKEN) yield Chunk( text=chunk.choices[0].text, prompt_tokens=0, completion_tokens=0 ) async def achat(self, messages: Iterable[dict[str, str]]) -> Chunk: + await self.check_rate_limit(len(str(messages)) / self.CHARACTERS_PER_TOKEN) response = await self.router.acompletion(self.name, messages) + await self.check_rate_limit(response.usage.completion_tokens) return Chunk( text=response.choices[0].message.content, prompt_tokens=response.usage.prompt_tokens, @@ -459,16 +477,19 @@ async def achat(self, messages: Iterable[dict[str, str]]) -> Chunk: async def achat_iter( self, messages: Iterable[dict[str, str]] ) -> AsyncIterable[Chunk]: + await self.check_rate_limit(len(str(messages)) / self.CHARACTERS_PER_TOKEN) completion = await self.router.acompletion( self.name, messages, stream=True, stream_options={"include_usage": True} ) async for chunk in completion: + await self.check_rate_limit(len(chunk.choices[0].delta.content) / self.CHARACTERS_PER_TOKEN) yield Chunk( text=chunk.choices[0].delta.content, prompt_tokens=0, completion_tokens=0, ) if hasattr(chunk, "usage") and hasattr(chunk.usage, "prompt_tokens"): + await self.check_rate_limit(chunk.usage.completion_tokens) yield Chunk( text=None, prompt_tokens=chunk.usage.prompt_tokens, diff --git a/paperqa/rate_limiter.py b/paperqa/rate_limiter.py new file mode 100644 index 00000000..8de1dab9 --- /dev/null +++ b/paperqa/rate_limiter.py @@ -0,0 +1,334 @@ +import asyncio +import logging +import os +from collections.abc import Collection +from typing import ClassVar, Literal +from urllib.parse import urlparse + +import aiohttp +from coredis import Redis +from limits import ( + RateLimitItem, + RateLimitItemPerHour, + RateLimitItemPerMinute, + RateLimitItemPerSecond, +) +from limits.aio.storage import MemoryStorage, RedisStorage +from limits.aio.strategies import MovingWindowRateLimiter + +logger = logging.getLogger(__name__) + +GLOBAL_RATE_LIMITER_TIMEOUT = float(os.environ.get("RATE_LIMITER_TIMOUT", "30")) +# RATE_CONFIG keys are tuples, corresponding to a namespace and primary key. +# Anything defined with MATCH_ALL variable, will match all non-matched requests for that namespace. +# For the "get" namespace, all primary key urls will be parsed down to the domain level. +# For example, you're trying to do a get request to "https://google.com", "google.com" will get +# its own limit, and it will use the ("get", MATCH_ALL) for its limits. +# machine_id is a unique identifier for the machine making the request, it's used to limit the +# rate of requests per machine. If the machine_id is not in the NO_PROXY_EXTENSIONS list, then +# the dynamic IP of the machine will be used to limit the rate of requests, otherwise the +# user input proxy_id will be used. +# NOTICE: When liteLLM is implemented, LLM-client limits can be set via the RouterAPI, for now we only +# have a custom client limit for openAI based embedding models +MATCH_ALL = None +MATCH_ALL_INPUTS = Literal[None] +MATCH_MACHINE_ID = "" + +FALLBACK_RATE_LIMIT = RateLimitItemPerSecond(3, 1) +TOKEN_FALLBACK_RATE_LIMIT = RateLimitItemPerMinute(30_000, 1) + +RATE_CONFIG: dict[tuple[str, str | MATCH_ALL_INPUTS], RateLimitItem] = { + ("get", "api.crossref.org"): RateLimitItemPerSecond(30, 1), + ("get", "api.semanticscholar.org"): RateLimitItemPerSecond(15, 1), + ("client", MATCH_ALL): TOKEN_FALLBACK_RATE_LIMIT, + # MATCH_MACHINE_ID is a placeholder for the machine_id passed in by the caller + (f"get|{MATCH_MACHINE_ID}", MATCH_ALL): FALLBACK_RATE_LIMIT, +} + +UNKNOWN_IP: str = "0.0.0.0" # noqa: S104 + + +class GlobalRateLimiter: + + WAIT_INCREMENT: ClassVar[float] = 0.01 # seconds + IP_CHECK_SERVICES: ClassVar[Collection[str]] = { + "https://api.ipify.org", + "https://ifconfig.me", + "http://icanhazip.com", + "https://ipecho.net/plain", + } + # top sources pulled from prod log proxy failures + NO_PROXY_EXTENSIONS: ClassVar[Collection[str]] = { + ".gov", + ".uk", + "doi.org", + "cyberleninka.org", + ".de", + ".jp", + ".ro", + "microsoft.com", + "cambridge.org", + } + + def __init__( + self, + rate_config: dict[ + tuple[str, str | MATCH_ALL_INPUTS], RateLimitItem + ] = RATE_CONFIG, + use_in_memory: bool = False, + ): + self.rate_config = rate_config + self.use_in_memory = use_in_memory + self._storage = None + self._rate_limiter = None + self._current_ip: str | None = None + + @staticmethod + async def get_outbound_ip(session: aiohttp.ClientSession, url: str) -> str | None: + try: + async with session.get(url, timeout=aiohttp.ClientTimeout(5)) as response: + if response.status == 200: + return await response.text() + except TimeoutError: + logger.warning(f"Timeout occurred while connecting to {url}") + except aiohttp.ClientError: + logger.warning(f"Error occurred while connecting to {url}.", exc_info=True) + return None + + async def outbount_ip(self) -> str: + if self._current_ip is None: + async with aiohttp.ClientSession() as session: + for service in self.IP_CHECK_SERVICES: + ip = await self.get_outbound_ip(session, service) + if ip: + logger.info(f"Successfully retrieved IP from {service}") + self._current_ip = ip.strip() + else: + logger.error("Failed to retrieve IP from all services") + self._current_ip = UNKNOWN_IP + return self._current_ip # type: ignore[return-value] + + @property + def storage(self): + if self._storage is None: + if os.environ.get("REDIS_URL") and not self.use_in_memory: + self._storage = RedisStorage(f"async+redis://{os.environ['REDIS_URL']}") + logger.info("Connected to redis instance for rate limiting.") + else: + self._storage = MemoryStorage() + logger.info("Using in-memory rate limiter.") + + return self._storage + + @property + def rate_limiter(self): + if self._rate_limiter is None: + self._rate_limiter = MovingWindowRateLimiter(self.storage) + return self._rate_limiter + + async def parse_namespace_and_primary_key( + self, namespace_and_key: tuple[str, str | MATCH_ALL_INPUTS], proxy_id: int = 0 + ) -> tuple[str, str | MATCH_ALL_INPUTS]: + """Turn get key into a namespace and primary-key.""" + namespace, primary_key = namespace_and_key + + if namespace.startswith("get") and primary_key is not None: + # for URLs to be parsed correctly, they need a protocol + if not primary_key.startswith(("http://", "https://")): + primary_key = "https://" + primary_key + + primary_key = urlparse(primary_key).netloc or urlparse(primary_key).path + + if any(ext in primary_key for ext in self.NO_PROXY_EXTENSIONS): + namespace = f"{namespace}|{await self.outbount_ip()}" + else: + namespace = f"{namespace}|{proxy_id}" + + return namespace, primary_key + + def parse_rate_limits_and_namespace( + self, + namespace: str, + primary_key: str | MATCH_ALL_INPUTS, + ) -> tuple[RateLimitItem, str]: + """Get rate limit and new namespace for a given namespace and primary_key.""" + # the namespace may have a machine_id in it -- we replace if that's the case + namespace_w_stub_machine_id = namespace + namespace_w_machine_id_stripped = namespace + + # strip off the machine_id, and replace it with the MATCH_MACHINE_ID placeholder + if namespace.startswith("get"): + machine_id = namespace.split("|")[-1] + if machine_id != "get": + namespace_w_stub_machine_id = namespace.replace( + machine_id, MATCH_MACHINE_ID, 1 + ) + # try stripping the machine id for the namespace for shared limits + # i.e. matching to one rate limit across ALL machines + # these limits are in RATE_CONFIG WITHOUT a MATCH_MACHINE_ID placeholder + namespace_w_machine_id_stripped = "|".join(namespace.split("|")[:-1]) + + # here we want to use namespace_w_machine_id_stripped -- the rate should be shared + # this needs to be checked first, since it's more specific than the stub machine id + if (namespace_w_machine_id_stripped, primary_key) in self.rate_config: + return ( + self.rate_config[(namespace_w_machine_id_stripped, primary_key)], + namespace_w_machine_id_stripped, + ) + # we keep the old namespace if we match on the namespace_w_stub_machine_id + if (namespace_w_stub_machine_id, primary_key) in self.rate_config: + return ( + self.rate_config[(namespace_w_stub_machine_id, primary_key)], + namespace, + ) + # again we only want the original namespace, keep the old namespace + if (namespace_w_stub_machine_id, MATCH_ALL) in self.rate_config: + return ( + self.rate_config[(namespace_w_stub_machine_id, MATCH_ALL)], + namespace, + ) + # again we want to use the stripped namespace if it matches + if (namespace_w_machine_id_stripped, MATCH_ALL) in self.rate_config: + return ( + self.rate_config[(namespace_w_machine_id_stripped, MATCH_ALL)], + namespace_w_machine_id_stripped, + ) + return FALLBACK_RATE_LIMIT, namespace + + def parse_key( + self, key: str + ) -> tuple[RateLimitItem, tuple[str, str | MATCH_ALL_INPUTS]]: + """Parse the rate limit item from a redis/in-memory key. + + Note the key is created with RateLimitItem.key_for(*identifiers), + the first key is the namespace, then the next two will be our identifiers. + + """ + namespace, primary_key = key.split("/")[1:3] + rate_limit, new_namespace = self.parse_rate_limits_and_namespace( + namespace, primary_key + ) + return ( + rate_limit, + (new_namespace, primary_key), + ) + + async def get_rate_limit_keys( + self, + ) -> list[tuple[RateLimitItem, tuple[str, str | MATCH_ALL_INPUTS]]]: + """Returns a list of current RateLimitItems with tuples of namespace and primary key""" + host, port = os.environ.get("REDIS_URL", ":").split(":", maxsplit=2) + + if not (host and port): + raise ValueError(f'Invalid REDIS_URL: {os.environ.get("REDIS_URL")}.') + + client = Redis(host=host, port=port) + + cursor = b"0" + matching_keys = [] + + while cursor: + cursor, keys = await client.scan( + cursor, match=f"{self.storage.PREFIX}*", count=100 + ) + matching_keys.extend(keys) + + await client.quit() + + return [self.parse_key(key.decode("utf-8")) for key in matching_keys] + + def get_in_memory_limit_keys( + self, + ) -> list[tuple[RateLimitItem, tuple[str, str | MATCH_ALL_INPUTS]]]: + """Returns a list of current RateLimitItems with tuples of namespace and primary key""" + return [self.parse_key(key) for key in self.storage.events] + + async def get_limit_keys( + self, + ) -> list[tuple[RateLimitItem, tuple[str, str | MATCH_ALL_INPUTS]]]: + if os.environ.get("REDIS_URL") and not self.use_in_memory: + return await self.get_rate_limit_keys() + return self.get_in_memory_limit_keys() + + async def rate_limit_status(self): + + limit_status = {} + + for rate_limit, (namespace, primary_key) in await self.get_limit_keys(): + period_start, n_items_in_period = await self.storage.get_moving_window( + rate_limit.key_for(*(namespace, primary_key)), + rate_limit.amount, + rate_limit.get_expiry(), + ) + limit_status[(namespace, primary_key)] = { + "period_start": period_start, + "n_items_in_period": n_items_in_period, + "period_seconds": rate_limit.GRANULARITY.seconds, + "period_name": rate_limit.GRANULARITY.name, + "period_cap": rate_limit.amount, + } + return limit_status + + async def try_acquire( + self, + namespace_and_key: tuple[str, str | MATCH_ALL_INPUTS], + rate_limit: RateLimitItem | None = None, + proxy_id: int = 0, + timeout: float = GLOBAL_RATE_LIMITER_TIMEOUT, + weight: int = 1, + ) -> None: + """Returns when the limit is satisfied for the namespace_and_key. + + Args: + `namespace_and_key` is composed of a tuple with namespace (e.g. "get") and a primary-key (e.g. "arxiv.org"). + namespaces can be nested with multiple '|', primary-keys in the "get" namespace will be stripped to the domain. + + `proxy_id` will be used to modify the namespace of get requests if + the primary key is not in the NO_PROXY_EXTENSIONS list. + Otherwise, the outbound IP will be used to modify the namespace. + + The proxy_id / outbound IP are referred to as the machine_id. + + `rate_limit` is the rate limit to be used for the namespace and primary-key. + + `timeout` is the maximum time to wait for the rate limit to be satisfied. + + `weight` is the cost of the request, default is 1. (could be tokens for example) + + returns if the limit is satisfied or times out via a TimeoutError. + + """ + namespace, primary_key = await self.parse_namespace_and_primary_key( + namespace_and_key, proxy_id=proxy_id + ) + + _rate_limit, new_namespace = self.parse_rate_limits_and_namespace( + namespace, primary_key + ) + + rate_limit = rate_limit or _rate_limit + + while True: + elapsed = 0.0 + while ( + not ( + await self.rate_limiter.test(rate_limit, new_namespace, primary_key, cost=weight) + ) + and elapsed < timeout + ): + await asyncio.sleep(self.WAIT_INCREMENT) + elapsed += self.WAIT_INCREMENT + + if elapsed >= timeout: + raise TimeoutError( + f"Timeout ({elapsed} secs): rate limit for key: {namespace_and_key}" + ) + + # If the rate limit hit is False, then we're violating the limit, so we + # need to wait again. This can happen in race conditions. + if await self.rate_limiter.hit(rate_limit, new_namespace, primary_key, cost=weight): + break + timeout = max(timeout - elapsed, 1.0) + + +GLOBAL_LIMITER = GlobalRateLimiter() diff --git a/pyproject.toml b/pyproject.toml index 7cc00201..fb32ca1e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,9 +20,11 @@ dependencies = [ "PyMuPDF>=1.24.3", # python -c "import pymupdf" won't run before version 1.24.3 "aiohttp", # TODO: remove in favor of httpx "anyio", + "coredis", "fhaviary[llm]>=0.6", # For info on Message "html2text", # TODO: evaluate moving to an opt-in dependency "httpx", + "limits", "litellm>=1.44", # to prevent sys.stdout on router creation "numpy", "pybtex", diff --git a/uv.lock b/uv.lock index 32ba156e..10a2ad86 100644 --- a/uv.lock +++ b/uv.lock @@ -140,6 +140,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/45/86/4736ac618d82a20d87d2f92ae19441ebc7ac9e7a581d7e58bbe79233b24a/asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24", size = 27764 }, ] +[[package]] +name = "async-timeout" +version = "4.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/87/d6/21b30a550dafea84b1b8eee21b5e23fa16d010ae006011221f33dcd8d7f8/async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f", size = 8345 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/fa/e01228c2938de91d47b307831c62ab9e4001e747789d0b05baf779a6488c/async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028", size = 5721 }, +] + [[package]] name = "attrs" version = "24.2.0" @@ -285,6 +294,33 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2b/1e/1e726ba66eddf21c940821df8cf1a7d15cb165f0682d62161eaa5e93dae1/contourpy-1.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:33c92cdae89ec5135d036e7218e69b0bb2851206077251f04a6c4e0e21f03927", size = 1314829 }, ] +[[package]] +name = "coredis" +version = "4.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "async-timeout" }, + { name = "deprecated" }, + { name = "packaging" }, + { name = "pympler" }, + { name = "typing-extensions" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/0c/0f2fb1cedd224666ef08e898447bb9cf4d1e98a86b03119f1c6513093ddc/coredis-4.17.0.tar.gz", hash = "sha256:04e9976e71a42004dfe19a862c648b4047bf813e15184cddfd3cb37eb704b83f", size = 243157 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/2c/2335e476f0c0b33eea53c307169bcafe9c19a4b277738258eb80354ee90c/coredis-4.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f3050806b4854a6624e3c2efa013b540265d88e766f815963d447c116240d75d", size = 330690 }, + { url = "https://files.pythonhosted.org/packages/6a/b1/3c24a708b24f8e2566b1b91b64b4dc75f74633b875def19f2ac0fa03a0a0/coredis-4.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5f0f1044bdafc93f421e59e711da762c6c741ab76df0c12a42c447c1db1fcd75", size = 328051 }, + { url = "https://files.pythonhosted.org/packages/0f/a6/e5a8add1ae7b31240248528f669127e5fd347c69625a9b423965a5902302/coredis-4.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1befa7db121978fd0995151af5d15ce5e37a14847797c3fbd9403882f21b48c", size = 352651 }, + { url = "https://files.pythonhosted.org/packages/b8/d1/0ece1b888547ec26f4d33be30513cd44c77df25c9f943e7d3c20b49cc634/coredis-4.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52583dcef671c8d3a1cbecbf81cd630b1a72f946cf46601016c4f85d3f12a4a1", size = 355472 }, + { url = "https://files.pythonhosted.org/packages/00/c2/771bafa43c37d8c968804b6bb34063eb631b5d2377db31bca6d784131f48/coredis-4.17.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:845f5c0bb7012609a1f41f8308e5166c01f162599af33cb001bd2b0d6a4386f5", size = 358740 }, + { url = "https://files.pythonhosted.org/packages/fb/d3/90846efc003d692c46f2988ddaffaac47f2c95f378102dad490e911de157/coredis-4.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e3638c9a894ac7d0a04fa14515f24d0f717c431266ee0ac612ddb3a142862258", size = 330509 }, + { url = "https://files.pythonhosted.org/packages/4c/2d/1f97441d377b457831bd9327dbdaa29888effa2edf6318cb4138a425538f/coredis-4.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73cb260bf96eacb4e455c300b5e41382bc52d9a2125f3f7e55657662a627e0cb", size = 327735 }, + { url = "https://files.pythonhosted.org/packages/3a/3f/1dcd57f6df67b7a20b1c27abcf768cf6789be5f33d173739f482d672e9d1/coredis-4.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9421423bb109eb62b7595e1d0c84d8c9399bf160826ee478b6b7771bf6ad831e", size = 353755 }, + { url = "https://files.pythonhosted.org/packages/38/24/de68bdd4b3549a8a05674f0952e646d45afd15453543e0e679dc6899174c/coredis-4.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74abdeda89ff5ea40d0da771d2871148b64b2f1c758f11485397adc1928b08e", size = 357309 }, + { url = "https://files.pythonhosted.org/packages/ab/66/2bd9f9e1c10b307caf8f4e77527c620a0320291aa83a9e0e98e8df5a326c/coredis-4.17.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ddad826c5bc91f05e5fe36435086cdbe51019b2f4f0faf96d40250823548fee", size = 360856 }, + { url = "https://files.pythonhosted.org/packages/08/1c/7249845c0f6105290d70d90c9ad48b550f5bcb989766819d38aa0f784aec/coredis-4.17.0-py3-none-any.whl", hash = "sha256:a8254fcc746efd72990d565d87e5399646ad737b7a61d86ef129df846e86b0d3", size = 239667 }, +] + [[package]] name = "cycler" version = "0.12.1" @@ -328,6 +364,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d5/50/83c593b07763e1161326b3b8c6686f0f4b0f24d5526546bee538c89837d6/decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186", size = 9073 }, ] +[[package]] +name = "deprecated" +version = "1.2.14" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/92/14/1e41f504a246fc224d2ac264c227975427a85caf37c3979979edb9b1b232/Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3", size = 2974416 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c", size = 9561 }, +] + [[package]] name = "dill" version = "0.3.8" @@ -615,6 +663,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b", size = 26514 }, ] +[[package]] +name = "importlib-resources" +version = "6.4.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/be/f3e8c6081b684f176b761e6a2fef02a0be939740ed6f54109a2951d806f3/importlib_resources-6.4.5.tar.gz", hash = "sha256:980862a1d16c9e147a59603677fa2aa5fd82b87f223b6cb870695bcfce830065", size = 43372 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/6a/4604f9ae2fa62ef47b9de2fa5ad599589d28c9fd1d335f32759813dfa91e/importlib_resources-6.4.5-py3-none-any.whl", hash = "sha256:ac29d5f956f01d5e4bb63102a5a19957f1b9175e45649977264a1416783bb717", size = 36115 }, +] + [[package]] name = "iniconfig" version = "2.0.0" @@ -827,6 +884,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a1/54/35901a2c4ad046da2f297c69b65c6135b6af02edaada11534e3aaf0a4ff5/ldp-0.6.0-py3-none-any.whl", hash = "sha256:217ede95ecc6e1ddc958d631eac86f4ebfe50374fe39cc2b0e44ca7ba9d807bc", size = 85312 }, ] +[[package]] +name = "limits" +version = "3.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "deprecated" }, + { name = "importlib-resources" }, + { name = "packaging" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c4/5f/89fb5405ee37d8b172e48e357438dd79482731b0cd5db2f734ac58f019e4/limits-3.13.0.tar.gz", hash = "sha256:6571b0c567bfa175a35fed9f8a954c0c92f1c3200804282f1b8f1de4ad98a953", size = 70218 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/80/b340bc7c3eb8f5c40e4d38c8e3cd04c127756d8de06b9e54caefb4ae16d5/limits-3.13.0-py3-none-any.whl", hash = "sha256:9767f7233da4255e9904b79908a728e8ec0984c0b086058b4cbbd309aea553f6", size = 45547 }, +] + [[package]] name = "litellm" version = "1.46.1" @@ -1203,14 +1275,16 @@ wheels = [ [[package]] name = "paper-qa" -version = "5.0.4.dev13+g9919c4a.d20240917" +version = "5.0.8.dev1+ga3a069b.d20240923" source = { editable = "." } dependencies = [ { name = "aiohttp" }, { name = "anyio" }, + { name = "coredis" }, { name = "fhaviary", extra = ["llm"] }, { name = "html2text" }, { name = "httpx" }, + { name = "limits" }, { name = "litellm" }, { name = "numpy" }, { name = "pybtex" }, @@ -1269,11 +1343,13 @@ dev = [ requires-dist = [ { name = "aiohttp" }, { name = "anyio" }, + { name = "coredis" }, { name = "datasets", marker = "extra == 'datasets'" }, { name = "fhaviary", extras = ["llm"], specifier = ">=0.6" }, { name = "html2text" }, { name = "httpx" }, { name = "ldp", marker = "extra == 'ldp'", specifier = ">=0.6" }, + { name = "limits" }, { name = "litellm", specifier = ">=1.44" }, { name = "numpy" }, { name = "pandas-stubs", marker = "extra == 'typing'" }, @@ -1602,6 +1678,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/11/80/34b429c6534be99ef3d6d20bd794b26fda0682d38e2d57f85df258beaac2/pylint_pydantic-0.3.2-py3-none-any.whl", hash = "sha256:e5cec02370aa68ac8eff138e5d573b0ac049bab864e9a6c3a9057cf043440aa1", size = 15951 }, ] +[[package]] +name = "pympler" +version = "1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pywin32", marker = "platform_system == 'Windows'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dd/37/c384631908029676d8e7213dd956bb686af303a80db7afbc9be36bc49495/pympler-1.1.tar.gz", hash = "sha256:1eaa867cb8992c218430f1708fdaccda53df064144d1c5656b1e6f1ee6000424", size = 179954 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/4f/a6a2e2b202d7fd97eadfe90979845b8706676b41cbd3b42ba75adf329d1f/Pympler-1.1-py3-none-any.whl", hash = "sha256:5b223d6027d0619584116a0cbc28e8d2e378f7a79c1e5e024f9ff3b673c58506", size = 165766 }, +] + [[package]] name = "pymupdf" version = "1.24.10" @@ -1791,6 +1879,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/11/c3/005fcca25ce078d2cc29fd559379817424e94885510568bc1bc53d7d5846/pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725", size = 508002 }, ] +[[package]] +name = "pywin32" +version = "306" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/1e/fc18ad83ca553e01b97aa8393ff10e33c1fb57801db05488b83282ee9913/pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407", size = 8507689 }, + { url = "https://files.pythonhosted.org/packages/7e/9e/ad6b1ae2a5ad1066dc509350e0fbf74d8d50251a51e420a2a8feaa0cecbd/pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e", size = 9227547 }, + { url = "https://files.pythonhosted.org/packages/91/20/f744bff1da8f43388498503634378dbbefbe493e65675f2cc52f7185c2c2/pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a", size = 10388324 }, + { url = "https://files.pythonhosted.org/packages/14/91/17e016d5923e178346aabda3dfec6629d1a26efe587d19667542105cf0a6/pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b", size = 8507705 }, + { url = "https://files.pythonhosted.org/packages/83/1c/25b79fc3ec99b19b0a0730cc47356f7e2959863bf9f3cd314332bddb4f68/pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e", size = 9227429 }, + { url = "https://files.pythonhosted.org/packages/1c/43/e3444dc9a12f8365d9603c2145d16bf0a2f8180f343cf87be47f5579e547/pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040", size = 10388145 }, +] + [[package]] name = "pyyaml" version = "6.0.2" From f98394b888098d96275613f3926a632399379136 Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Wed, 2 Oct 2024 15:39:26 -0700 Subject: [PATCH 02/20] added rate limit tests --- paperqa/llms.py | 152 +++++++++++++++---- paperqa/rate_limiter.py | 119 +++++++++------ tests/conftest.py | 14 ++ tests/test_rate_limiter.py | 299 +++++++++++++++++++++++++++++++++++++ 4 files changed, 509 insertions(+), 75 deletions(-) create mode 100644 tests/test_rate_limiter.py diff --git a/paperqa/llms.py b/paperqa/llms.py index 248f3988..0df50283 100644 --- a/paperqa/llms.py +++ b/paperqa/llms.py @@ -2,13 +2,21 @@ import asyncio import contextlib +import functools from abc import ABC, abstractmethod -from collections.abc import AsyncIterable, Awaitable, Callable, Iterable, Sequence +from collections.abc import ( + AsyncGenerator, + AsyncIterable, + Awaitable, + Callable, + Coroutine, + Iterable, + Sequence, +) from enum import StrEnum -from inspect import signature +from inspect import isasyncgenfunction, signature from sys import version_info -from typing import Any, ClassVar -from xml.dom.pulldom import CHARACTERS +from typing import Any, ClassVar, TypeVar, cast import numpy as np import tiktoken @@ -16,9 +24,9 @@ from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, model_validator from paperqa.prompts import default_system_prompt +from paperqa.rate_limiter import GLOBAL_LIMITER from paperqa.types import Embeddable, LLMResult from paperqa.utils import is_coroutine_callable -from paperqa.rate_limiter import GLOBAL_LIMITER PromptRunner = Callable[ [dict, list[Callable[[str], None]] | None, str | None], @@ -54,6 +62,20 @@ class EmbeddingModes(StrEnum): class EmbeddingModel(ABC, BaseModel): name: str + config: dict = Field( + default_factory=dict, + description="Optional `rate_limit` key, value must be a RateLimitItem", + ) + CHARACTERS_PER_TOKEN: ClassVar[float] = 4.0 + + async def check_rate_limit(self, token_count: float, **kwargs): + if "rate_limit" in self.config: + await GLOBAL_LIMITER.try_acquire( + ("client", self.name), + self.config["rate_limit"], + weight=max(int(token_count), 1), + **kwargs, + ) def set_mode(self, mode: EmbeddingModes) -> None: """Several embedding models have a 'mode' or prompt which affects output.""" @@ -73,10 +95,19 @@ async def embed_documents( N = len(texts) embeddings = [] for i in range(0, N, batch_size): + + await self.check_rate_limit( + sum( + len(t) / self.CHARACTERS_PER_TOKEN + for t in texts[i : i + batch_size] + ) + ) + response = await aembedding( self.name, input=texts[i : i + batch_size], **self.embedding_kwargs ) embeddings.extend([e["embedding"] for e in response.data]) + return embeddings @@ -134,6 +165,7 @@ class LLMModel(ABC, BaseModel): exclude=True, ) config: dict = Field(default_factory=dict) + CHARACTERS_PER_TOKEN: ClassVar[float] = 4.0 async def acomplete(self, prompt: str) -> Chunk: """Return the completion as string and the number of tokens in the prompt and completion.""" @@ -234,12 +266,12 @@ async def _run_chat( start_clock = asyncio.get_running_loop().time() if callbacks is None: - chunk = await self.achat(messages) + chunk = cast(Chunk, self.achat(messages)) output = chunk.text else: sync_callbacks = [f for f in callbacks if not is_coroutine_callable(f)] async_callbacks = [f for f in callbacks if is_coroutine_callable(f)] - completion = self.achat_iter(messages) + completion = await self.achat_iter(messages) # type: ignore[misc] text_result = [] async for chunk in completion: if chunk.text: @@ -334,6 +366,69 @@ async def _run_completion( return result +LLMModelOrChild = TypeVar("LLMModelOrChild", bound=LLMModel) + + +def rate_limited( + func: Callable[[LLMModelOrChild, Any], Awaitable[Chunk] | AsyncIterable[Chunk]], +) -> Callable[ + [LLMModelOrChild, Any, Any], + Coroutine[ + Any, Any, Chunk | AsyncIterable[Chunk] | AsyncGenerator[LLMModelOrChild, None] + ], +]: + """Decorator to rate limit relevant methods of an LLMModel.""" + + @functools.wraps(func) + async def wrapper( + self: LLMModelOrChild, *args: Any, **kwargs: Any + ) -> Chunk | AsyncIterable[Chunk] | AsyncGenerator[LLMModelOrChild, None]: + + if not hasattr(self, "check_rate_limit") or not hasattr( + self, "CHARACTERS_PER_TOKEN" + ): + raise NotImplementedError( + f"Model {self.name} must have a `check_rate_limit` method " + "and a `CHARACTERS_PER_TOKEN` class variable." + ) + + # Estimate token count based on input + if func.__name__ in {"acomplete", "acomplete_iter"}: + prompt = args[0] if args else kwargs.get("prompt", "") + token_count = len(prompt) / self.CHARACTERS_PER_TOKEN + elif func.__name__ in {"achat", "achat_iter"}: + messages = args[0] if args else kwargs.get("messages", []) + token_count = len(str(messages)) / self.CHARACTERS_PER_TOKEN + else: + token_count = 0 # Default if method is unknown + + await self.check_rate_limit(token_count) + + # If wrapping a generator, count the tokens for each + # portion before yielding + if isasyncgenfunction(func): + + async def rate_limited_generator() -> AsyncGenerator[LLMModelOrChild, None]: + async for item in func(self, *args, **kwargs): + token_count = 0 + if isinstance(item, Chunk): + token_count = int( + len(item.text or "") / self.CHARACTERS_PER_TOKEN + ) + await self.check_rate_limit(token_count) + yield item + + return rate_limited_generator() + + result = await func(self, *args, **kwargs) # type: ignore[misc] + + if func.__name__ in {"acomplete", "achat"} and isinstance(result, Chunk): + await self.check_rate_limit(result.completion_tokens) + return result + + return wrapper + + DEFAULT_VERTEX_SAFETY_SETTINGS: list[dict[str, str]] = [ { "category": "HARM_CATEGORY_HARASSMENT", @@ -368,7 +463,7 @@ class LiteLLMModel(LLMModel): `model_list`: stores a list of all model configurations (see https://docs.litellm.ai/docs/routing) `router_kwargs`: kwargs for the Router class - `rate_limits`: (Optional) dictionary keyed by model group name + `rate_limit`: (Optional) dictionary keyed by model group name with values of type limits.RateLimitItem (in tokens / minute) This way users can specify routing strategies, retries, etc. @@ -377,7 +472,6 @@ class LiteLLMModel(LLMModel): config: dict = Field(default_factory=dict) name: str = "gpt-4o-mini" _router: Router | None = None - CHARACTERS_PER_TOKEN: ClassVar[float] = 4.0 @model_validator(mode="before") @classmethod @@ -429,23 +523,29 @@ def router(self): ) return self._router - async def check_rate_limit(self, token_count: float): - await GLOBAL_LIMITER.try_acquire(('client', self.name), - self.config.get("rate_limits", {}).get(self.name, None), - weight=token_count) + async def check_rate_limit(self, token_count: float, **kwargs): + # TODO: validate rate_limit config structure? + if "rate_limit" in self.config: + await GLOBAL_LIMITER.try_acquire( + ("client", self.name), + self.config["rate_limit"].get(self.name, None), + weight=max(int(token_count), 1), + **kwargs, + ) - async def acomplete(self, prompt: str) -> Chunk: - await self.check_rate_limit(len(prompt) / self.CHARACTERS_PER_TOKEN) + @rate_limited + async def acomplete(self, prompt: str) -> Chunk: # type: ignore[override] response = await self.router.atext_completion(model=self.name, prompt=prompt) - await self.check_rate_limit(response.usage.completion_tokens) return Chunk( text=response.choices[0].text, prompt_tokens=response.usage.prompt_tokens, completion_tokens=response.usage.completion_tokens, ) - async def acomplete_iter(self, prompt: str) -> AsyncIterable[Chunk]: - await self.check_rate_limit(len(prompt) / self.CHARACTERS_PER_TOKEN) + @rate_limited + async def acomplete_iter( # type: ignore[override] + self, prompt: str + ) -> AsyncIterable[Chunk]: completion = await self.router.atext_completion( model=self.name, prompt=prompt, @@ -453,43 +553,39 @@ async def acomplete_iter(self, prompt: str) -> AsyncIterable[Chunk]: stream_options={"include_usage": True}, ) async for chunk in completion: - await self.check_rate_limit(len(chunk.choices[0].text) / self.CHARACTERS_PER_TOKEN) yield Chunk( text=chunk.choices[0].text, prompt_tokens=0, completion_tokens=0 ) if hasattr(chunk, "usage") and hasattr(chunk.usage, "prompt_tokens"): - #TODO: should this access chunk.usage and chunk.usage.prompt_tokens? - await self.check_rate_limit(len(chunk.choices[0].text) / self.CHARACTERS_PER_TOKEN) yield Chunk( text=chunk.choices[0].text, prompt_tokens=0, completion_tokens=0 ) - async def achat(self, messages: Iterable[dict[str, str]]) -> Chunk: - await self.check_rate_limit(len(str(messages)) / self.CHARACTERS_PER_TOKEN) + @rate_limited + async def achat( # type: ignore[override] + self, messages: Iterable[dict[str, str]] + ) -> Chunk: response = await self.router.acompletion(self.name, messages) - await self.check_rate_limit(response.usage.completion_tokens) return Chunk( text=response.choices[0].message.content, prompt_tokens=response.usage.prompt_tokens, completion_tokens=response.usage.completion_tokens, ) - async def achat_iter( + @rate_limited + async def achat_iter( # type: ignore[override] self, messages: Iterable[dict[str, str]] ) -> AsyncIterable[Chunk]: - await self.check_rate_limit(len(str(messages)) / self.CHARACTERS_PER_TOKEN) completion = await self.router.acompletion( self.name, messages, stream=True, stream_options={"include_usage": True} ) async for chunk in completion: - await self.check_rate_limit(len(chunk.choices[0].delta.content) / self.CHARACTERS_PER_TOKEN) yield Chunk( text=chunk.choices[0].delta.content, prompt_tokens=0, completion_tokens=0, ) if hasattr(chunk, "usage") and hasattr(chunk.usage, "prompt_tokens"): - await self.check_rate_limit(chunk.usage.completion_tokens) yield Chunk( text=None, prompt_tokens=chunk.usage.prompt_tokens, diff --git a/paperqa/rate_limiter.py b/paperqa/rate_limiter.py index 8de1dab9..a0d019ea 100644 --- a/paperqa/rate_limiter.py +++ b/paperqa/rate_limiter.py @@ -9,7 +9,6 @@ from coredis import Redis from limits import ( RateLimitItem, - RateLimitItemPerHour, RateLimitItemPerMinute, RateLimitItemPerSecond, ) @@ -19,17 +18,17 @@ logger = logging.getLogger(__name__) GLOBAL_RATE_LIMITER_TIMEOUT = float(os.environ.get("RATE_LIMITER_TIMOUT", "30")) + # RATE_CONFIG keys are tuples, corresponding to a namespace and primary key. # Anything defined with MATCH_ALL variable, will match all non-matched requests for that namespace. # For the "get" namespace, all primary key urls will be parsed down to the domain level. # For example, you're trying to do a get request to "https://google.com", "google.com" will get # its own limit, and it will use the ("get", MATCH_ALL) for its limits. # machine_id is a unique identifier for the machine making the request, it's used to limit the -# rate of requests per machine. If the machine_id is not in the NO_PROXY_EXTENSIONS list, then +# rate of requests per machine. If the primary_key is in the NO_MACHINE_ID_EXTENSIONS list, then # the dynamic IP of the machine will be used to limit the rate of requests, otherwise the -# user input proxy_id will be used. -# NOTICE: When liteLLM is implemented, LLM-client limits can be set via the RouterAPI, for now we only -# have a custom client limit for openAI based embedding models +# user input machine_id will be used. + MATCH_ALL = None MATCH_ALL_INPUTS = Literal[None] MATCH_MACHINE_ID = "" @@ -57,18 +56,9 @@ class GlobalRateLimiter: "http://icanhazip.com", "https://ipecho.net/plain", } - # top sources pulled from prod log proxy failures - NO_PROXY_EXTENSIONS: ClassVar[Collection[str]] = { - ".gov", - ".uk", - "doi.org", - "cyberleninka.org", - ".de", - ".jp", - ".ro", - "microsoft.com", - "cambridge.org", - } + # the following will use IP scope for limiting, rather + # than user input machine ID + NO_MACHINE_ID_EXTENSIONS: ClassVar[Collection[str]] = {"crossref.org"} def __init__( self, @@ -87,7 +77,7 @@ def __init__( async def get_outbound_ip(session: aiohttp.ClientSession, url: str) -> str | None: try: async with session.get(url, timeout=aiohttp.ClientTimeout(5)) as response: - if response.status == 200: + if response.ok: return await response.text() except TimeoutError: logger.warning(f"Timeout occurred while connecting to {url}") @@ -103,10 +93,11 @@ async def outbount_ip(self) -> str: if ip: logger.info(f"Successfully retrieved IP from {service}") self._current_ip = ip.strip() - else: - logger.error("Failed to retrieve IP from all services") - self._current_ip = UNKNOWN_IP - return self._current_ip # type: ignore[return-value] + break + if self._current_ip is None: + logger.error("Failed to retrieve IP from all services") + self._current_ip = UNKNOWN_IP + return self._current_ip @property def storage(self): @@ -127,9 +118,15 @@ def rate_limiter(self): return self._rate_limiter async def parse_namespace_and_primary_key( - self, namespace_and_key: tuple[str, str | MATCH_ALL_INPUTS], proxy_id: int = 0 + self, namespace_and_key: tuple[str, str | MATCH_ALL_INPUTS], machine_id: int = 0 ) -> tuple[str, str | MATCH_ALL_INPUTS]: - """Turn get key into a namespace and primary-key.""" + """Turn namespace_and_key tuple into a namespace and primary-key. + + If using a namespace starting with "get", then the primary key will be url parsed. + "get" namespaces will also have their machine_ids appended to the namespace here, + unless the primary key is in the NO_MACHINE_ID_EXTENSIONS list, in which case + the outbound IP will be used. + """ namespace, primary_key = namespace_and_key if namespace.startswith("get") and primary_key is not None: @@ -139,10 +136,10 @@ async def parse_namespace_and_primary_key( primary_key = urlparse(primary_key).netloc or urlparse(primary_key).path - if any(ext in primary_key for ext in self.NO_PROXY_EXTENSIONS): + if any(ext in primary_key for ext in self.NO_MACHINE_ID_EXTENSIONS): namespace = f"{namespace}|{await self.outbount_ip()}" else: - namespace = f"{namespace}|{proxy_id}" + namespace = f"{namespace}|{machine_id}" return namespace, primary_key @@ -151,7 +148,13 @@ def parse_rate_limits_and_namespace( namespace: str, primary_key: str | MATCH_ALL_INPUTS, ) -> tuple[RateLimitItem, str]: - """Get rate limit and new namespace for a given namespace and primary_key.""" + """Get rate limit and new namespace for a given namespace and primary_key. + + This parsing logic finds the correct rate limits for a namespace/primary_key. + It's a bit complex due to the and placeholders. + These allow users to match + + """ # the namespace may have a machine_id in it -- we replace if that's the case namespace_w_stub_machine_id = namespace namespace_w_machine_id_stripped = namespace @@ -216,7 +219,7 @@ def parse_key( async def get_rate_limit_keys( self, ) -> list[tuple[RateLimitItem, tuple[str, str | MATCH_ALL_INPUTS]]]: - """Returns a list of current RateLimitItems with tuples of namespace and primary key""" + """Returns a list of current RateLimitItems with tuples of namespace and primary key.""" host, port = os.environ.get("REDIS_URL", ":").split(":", maxsplit=2) if not (host and port): @@ -240,7 +243,7 @@ async def get_rate_limit_keys( def get_in_memory_limit_keys( self, ) -> list[tuple[RateLimitItem, tuple[str, str | MATCH_ALL_INPUTS]]]: - """Returns a list of current RateLimitItems with tuples of namespace and primary key""" + """Returns a list of current RateLimitItems with tuples of namespace and primary key.""" return [self.parse_key(key) for key in self.storage.events] async def get_limit_keys( @@ -273,52 +276,64 @@ async def try_acquire( self, namespace_and_key: tuple[str, str | MATCH_ALL_INPUTS], rate_limit: RateLimitItem | None = None, - proxy_id: int = 0, - timeout: float = GLOBAL_RATE_LIMITER_TIMEOUT, + machine_id: int = 0, + timeout: float = GLOBAL_RATE_LIMITER_TIMEOUT, # noqa: ASYNC109 weight: int = 1, + raise_impossible_limits: bool = False, ) -> None: """Returns when the limit is satisfied for the namespace_and_key. - + Args: - `namespace_and_key` is composed of a tuple with namespace (e.g. "get") and a primary-key (e.g. "arxiv.org"). - namespaces can be nested with multiple '|', primary-keys in the "get" namespace will be stripped to the domain. + namespace_and_key: is composed of a tuple with namespace (e.g. "get") and + a primary-key (e.g. "arxiv.org"). namespaces can be nested with multiple '|', + primary-keys in the "get" namespace will be stripped to the domain. + + rate_limit: Optional RateLimitItem to be used for the namespace and primary-key. + If not provided, RATE_CONFIG will be used to find the rate limit. - `proxy_id` will be used to modify the namespace of get requests if - the primary key is not in the NO_PROXY_EXTENSIONS list. - Otherwise, the outbound IP will be used to modify the namespace. + machine_id: will be used to modify the namespace of GET requests if + the primary key is not in the NO_MACHINE_ID_EXTENSIONS list. + In that case, the outbound IP will be used to modify the namespace. - The proxy_id / outbound IP are referred to as the machine_id. + timeout: is the maximum time to wait for the rate limit to be satisfied. - `rate_limit` is the rate limit to be used for the namespace and primary-key. - - `timeout` is the maximum time to wait for the rate limit to be satisfied. + weight: is the cost of the request, default is 1. (could be tokens for example) - `weight` is the cost of the request, default is 1. (could be tokens for example) + raise_impossible_limits: flag will raise a ValueError for weights that exceed the rate. returns if the limit is satisfied or times out via a TimeoutError. """ namespace, primary_key = await self.parse_namespace_and_primary_key( - namespace_and_key, proxy_id=proxy_id + namespace_and_key, machine_id=machine_id ) - + _rate_limit, new_namespace = self.parse_rate_limits_and_namespace( namespace, primary_key ) rate_limit = rate_limit or _rate_limit + if rate_limit.amount < weight and raise_impossible_limits: + raise ValueError( + f"Weight ({weight}) > RateLimit ({rate_limit}), cannot satisfy rate limit." + ) + while True: elapsed = 0.0 while ( not ( - await self.rate_limiter.test(rate_limit, new_namespace, primary_key, cost=weight) + await self.rate_limiter.test( + rate_limit, + new_namespace, + primary_key, + cost=min(weight, rate_limit.amount), + ) ) and elapsed < timeout ): await asyncio.sleep(self.WAIT_INCREMENT) elapsed += self.WAIT_INCREMENT - if elapsed >= timeout: raise TimeoutError( f"Timeout ({elapsed} secs): rate limit for key: {namespace_and_key}" @@ -326,7 +341,17 @@ async def try_acquire( # If the rate limit hit is False, then we're violating the limit, so we # need to wait again. This can happen in race conditions. - if await self.rate_limiter.hit(rate_limit, new_namespace, primary_key, cost=weight): + if await self.rate_limiter.hit( + rate_limit, + new_namespace, + primary_key, + cost=min(weight, rate_limit.amount), + ): + # we need to keep trying when we have an "impossible" limit + if rate_limit.amount < weight: + weight -= rate_limit.amount + timeout = max(timeout - elapsed, 1.0) + continue break timeout = max(timeout - elapsed, 1.0) diff --git a/tests/conftest.py b/tests/conftest.py index 18f96c1b..781dc034 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,6 +13,7 @@ from paperqa.clients.crossref import CROSSREF_HEADER_KEY from paperqa.clients.semantic_scholar import SEMANTIC_SCHOLAR_HEADER_KEY +from paperqa.llms import LiteLLMEmbeddingModel, LiteLLMModel from paperqa.settings import Settings from paperqa.types import Answer from paperqa.utils import setup_default_logs @@ -120,3 +121,16 @@ def reset_log_levels(caplog): logger = logging.getLogger(name) logger.setLevel(logging.NOTSET) logger.propagate = True + + +# get a new module objects +# to avoid sharing a rate limiter +# between calls +@pytest.fixture +def litellm_model() -> type[LiteLLMModel]: + return LiteLLMModel + + +@pytest.fixture +def litellm_embedding_model() -> type[LiteLLMEmbeddingModel]: + return LiteLLMEmbeddingModel diff --git a/tests/test_rate_limiter.py b/tests/test_rate_limiter.py new file mode 100644 index 00000000..f183090e --- /dev/null +++ b/tests/test_rate_limiter.py @@ -0,0 +1,299 @@ +import asyncio +import time +from itertools import product +from typing import Any + +import pytest +from limits import RateLimitItemPerSecond +from litellm import Type + +from paperqa.llms import Chunk, LiteLLMEmbeddingModel, LiteLLMModel +from paperqa.types import LLMResult + +LLM_CONFIG_W_RATE_LIMITS = [ + { + "name": "gpt-4o-mini", + "config": { + "model_list": [ + { + "model_name": "gpt-4o-mini", + "litellm_params": { + "model": "gpt-4o-mini", + "temperature": 0, + }, + } + ], + "rate_limit": {"gpt-4o-mini": RateLimitItemPerSecond(20, 3)}, + }, + }, + { + "name": "gpt-4o-mini", + "config": { + "model_list": [ + { + "model_name": "gpt-4o-mini", + "litellm_params": { + "model": "gpt-4o-mini", + "temperature": 0, + }, + } + ], + "rate_limit": {"gpt-4o-mini": RateLimitItemPerSecond(20, 1)}, + }, + }, + { + "name": "gpt-4o-mini", + "config": { + "model_list": [ + { + "model_name": "gpt-4o-mini", + "litellm_params": { + "model": "gpt-4o-mini", + "temperature": 0, + }, + } + ], + "rate_limit": {"gpt-4o-mini": RateLimitItemPerSecond(1_000_000, 1)}, + }, + }, + { + "name": "gpt-4o-mini", + "config": { + "model_list": [ + { + "model_name": "gpt-4o-mini", + "litellm_params": { + "model": "gpt-4o-mini", + "temperature": 0, + }, + } + ] + }, + }, +] + +LLM_METHOD_AND_INPUTS = [ + { + "method": "acomplete", + "kwargs": {"prompt": "The duck says"}, + }, + { + "method": "acomplete_iter", + "kwargs": {"prompt": "The duck says"}, + }, + { + "method": "achat", + "kwargs": {"messages": [{"role": "user", "content": "The duck says"}]}, + }, + { + "method": "achat_iter", + "kwargs": {"messages": [{"role": "user", "content": "The duck says"}]}, + }, +] + +rate_limit_configurations = list( + product(LLM_CONFIG_W_RATE_LIMITS, LLM_METHOD_AND_INPUTS) +) + +EMBEDDING_CONFIG_W_RATE_LIMITS = [ + {"config": {"rate_limit": RateLimitItemPerSecond(20, 5)}}, + {"config": {"rate_limit": RateLimitItemPerSecond(20, 3)}}, + {"config": {"rate_limit": RateLimitItemPerSecond(1_000_000, 1)}}, + {}, +] + +ACCEPTABLE_RATE_LIMIT_ERROR: float = 0.10 # 10% error margin for token estimate error + + +async def time_n_llm_methods( + llm: LiteLLMModel, method: str, n: int, use_gather: bool = False, *args, **kwargs +) -> float: + """Give the token per second rate of a method call.""" + start_time = time.time() + outputs = [] + + if not use_gather: + for _ in range(n): + if "iter" in method: + outputs.extend( + [ + output + async for output in await getattr(llm, method)(*args, **kwargs) + ] + ) + else: + outputs.append(await getattr(llm, method)(*args, **kwargs)) + + else: + outputs = await asyncio.gather( + *[getattr(llm, method)(*args, **kwargs) for _ in range(n)] + ) + + character_count = 0 + token_count = 0 + + if isinstance(outputs[0], Chunk | LLMResult): + character_count = sum(len(o.text or "") for o in outputs) + else: + character_count = sum(len(o) for o in outputs) + + if hasattr(outputs[0], "prompt_tokens"): + token_count = sum(o.prompt_tokens + o.completion_tokens for o in outputs) + + return max(character_count / llm.CHARACTERS_PER_TOKEN, token_count) / ( + time.time() - start_time + ) + + +@pytest.mark.parametrize("llm_config_w_rate_limits", LLM_CONFIG_W_RATE_LIMITS) +@pytest.mark.asyncio +async def test_rate_limit_on_run_prompt( + llm_config_w_rate_limits: dict[str, Any], litellm_model: Type[LiteLLMModel] +) -> None: + + llm = litellm_model(**llm_config_w_rate_limits) + + outputs = [] + + def accum(x) -> None: + outputs.append(x) + + estimated_tokens_per_second = await time_n_llm_methods( + llm, + "run_prompt", + 3, + prompt="The {animal} says", + data={"animal": "duck"}, + skip_system=True, + callbacks=[accum], + ) + + if "rate_limit" in llm.config: + max_tokens_per_second = ( + llm.config["rate_limit"]["gpt-4o-mini"].amount + / llm.config["rate_limit"]["gpt-4o-mini"].multiples + ) + assert estimated_tokens_per_second / max_tokens_per_second < ( + 1.0 + ACCEPTABLE_RATE_LIMIT_ERROR + ) + else: + assert estimated_tokens_per_second > 0 + + outputs = [] + + def accum2(x) -> None: + outputs.append(x) + + estimated_tokens_per_second = await time_n_llm_methods( + llm, + "run_prompt", + 3, + use_gather=True, + prompt="The {animal} says", + data={"animal": "duck"}, + skip_system=True, + callbacks=[accum2], + ) + + if "rate_limit" in llm.config: + max_tokens_per_second = ( + llm.config["rate_limit"]["gpt-4o-mini"].amount + / llm.config["rate_limit"]["gpt-4o-mini"].multiples + ) + assert estimated_tokens_per_second / max_tokens_per_second < ( + 1.0 + ACCEPTABLE_RATE_LIMIT_ERROR + ) + else: + assert estimated_tokens_per_second > 0 + + +@pytest.mark.parametrize( + ("llm_config_w_rate_limits", "llm_method_kwargs"), rate_limit_configurations +) +@pytest.mark.asyncio +async def test_rate_limit_on_sequential_completion_litellm_methods( + llm_config_w_rate_limits: dict[str, Any], + llm_method_kwargs: dict[str, Any], + litellm_model: Type[LiteLLMModel], +) -> None: + + llm = litellm_model(**llm_config_w_rate_limits) + + estimated_tokens_per_second = await time_n_llm_methods( + llm, + llm_method_kwargs["method"], + 3, + use_gather=False, + **llm_method_kwargs["kwargs"], + ) + if "rate_limit" in llm.config: + max_tokens_per_second = ( + llm.config["rate_limit"]["gpt-4o-mini"].amount + / llm.config["rate_limit"]["gpt-4o-mini"].multiples + ) + assert estimated_tokens_per_second / max_tokens_per_second < ( + 1.0 + ACCEPTABLE_RATE_LIMIT_ERROR + ) + else: + assert estimated_tokens_per_second > 0 + + +@pytest.mark.parametrize( + ("llm_config_w_rate_limits", "llm_method_kwargs"), rate_limit_configurations +) +@pytest.mark.asyncio +async def test_rate_limit_on_parallel_completion_litellm_methods( + llm_config_w_rate_limits: dict[str, Any], + llm_method_kwargs: dict[str, Any], + litellm_model: Type[LiteLLMModel], +) -> None: + + llm = litellm_model(**llm_config_w_rate_limits) + + if "iter" not in llm_method_kwargs["method"]: + estimated_tokens_per_second = await time_n_llm_methods( + llm, + llm_method_kwargs["method"], + 3, + use_gather=True, + **llm_method_kwargs["kwargs"], + ) + if "rate_limit" in llm.config: + max_tokens_per_second = ( + llm.config["rate_limit"]["gpt-4o-mini"].amount + / llm.config["rate_limit"]["gpt-4o-mini"].multiples + ) + assert estimated_tokens_per_second / max_tokens_per_second < ( + 1.0 + ACCEPTABLE_RATE_LIMIT_ERROR + ) + else: + assert estimated_tokens_per_second > 0 + + +@pytest.mark.parametrize( + "embedding_config_w_rate_limits", EMBEDDING_CONFIG_W_RATE_LIMITS +) +@pytest.mark.asyncio +async def test_embedding_rate_limits( + embedding_config_w_rate_limits: dict[str, Any], + litellm_embedding_model: Type[LiteLLMEmbeddingModel], +) -> None: + + embedding_model = litellm_embedding_model(**embedding_config_w_rate_limits) + texts_to_embed = ["the duck says"] * 10 + start = time.time() + await embedding_model.embed_documents(texts=texts_to_embed, batch_size=5) + estimated_tokens_per_second = sum( + len(t) / embedding_model.CHARACTERS_PER_TOKEN for t in texts_to_embed + ) / (time.time() - start) + + if "rate_limit" in embedding_config_w_rate_limits: + max_tokens_per_second = ( + embedding_config_w_rate_limits["rate_limit"].amount + / embedding_config_w_rate_limits["rate_limit"].multiples + ) + assert estimated_tokens_per_second / max_tokens_per_second < ( + 1.0 + ACCEPTABLE_RATE_LIMIT_ERROR + ) + else: + assert estimated_tokens_per_second > 0 From 6eb4a2c8ff857d7c4ab183ca90ab54ae9e6765cf Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Wed, 2 Oct 2024 15:51:14 -0700 Subject: [PATCH 03/20] update type annotations --- paperqa/rate_limiter.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/paperqa/rate_limiter.py b/paperqa/rate_limiter.py index a0d019ea..35fcbc24 100644 --- a/paperqa/rate_limiter.py +++ b/paperqa/rate_limiter.py @@ -69,8 +69,8 @@ def __init__( ): self.rate_config = rate_config self.use_in_memory = use_in_memory - self._storage = None - self._rate_limiter = None + self._storage: RedisStorage | MemoryStorage | None = None + self._rate_limiter: MovingWindowRateLimiter | None = None self._current_ip: str | None = None @staticmethod @@ -225,16 +225,16 @@ async def get_rate_limit_keys( if not (host and port): raise ValueError(f'Invalid REDIS_URL: {os.environ.get("REDIS_URL")}.') - client = Redis(host=host, port=port) + client = Redis(host=host, port=int(port)) cursor = b"0" - matching_keys = [] + matching_keys: list[bytes] = [] while cursor: cursor, keys = await client.scan( - cursor, match=f"{self.storage.PREFIX}*", count=100 + int(cursor), match=f"{self.storage.PREFIX}*", count=100 ) - matching_keys.extend(keys) + matching_keys.extend(list(keys)) await client.quit() @@ -259,7 +259,7 @@ async def rate_limit_status(self): for rate_limit, (namespace, primary_key) in await self.get_limit_keys(): period_start, n_items_in_period = await self.storage.get_moving_window( - rate_limit.key_for(*(namespace, primary_key)), + rate_limit.key_for(*(namespace, primary_key or "")), rate_limit.amount, rate_limit.get_expiry(), ) From 1bd177669ef53b8b8001137b00aa35a98789e4ab Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Wed, 2 Oct 2024 16:04:33 -0700 Subject: [PATCH 04/20] remove CHARACTERS_PER_TOKEN as a classvar --- paperqa/llms.py | 17 +++++++---------- tests/test_rate_limiter.py | 20 ++++++++++++-------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/paperqa/llms.py b/paperqa/llms.py index ea1e4f1b..40f03a85 100644 --- a/paperqa/llms.py +++ b/paperqa/llms.py @@ -60,13 +60,15 @@ class EmbeddingModes(StrEnum): QUERY = "query" +CHARACTERS_PER_TOKEN: float = 4.0 + + class EmbeddingModel(ABC, BaseModel): name: str config: dict = Field( default_factory=dict, description="Optional `rate_limit` key, value must be a RateLimitItem", ) - CHARACTERS_PER_TOKEN: ClassVar[float] = 4.0 async def check_rate_limit(self, token_count: float, **kwargs): if "rate_limit" in self.config: @@ -97,10 +99,7 @@ async def embed_documents( for i in range(0, N, batch_size): await self.check_rate_limit( - sum( - len(t) / self.CHARACTERS_PER_TOKEN - for t in texts[i : i + batch_size] - ) + sum(len(t) / CHARACTERS_PER_TOKEN for t in texts[i : i + batch_size]) ) response = await aembedding( @@ -395,10 +394,10 @@ async def wrapper( # Estimate token count based on input if func.__name__ in {"acomplete", "acomplete_iter"}: prompt = args[0] if args else kwargs.get("prompt", "") - token_count = len(prompt) / self.CHARACTERS_PER_TOKEN + token_count = len(prompt) / CHARACTERS_PER_TOKEN elif func.__name__ in {"achat", "achat_iter"}: messages = args[0] if args else kwargs.get("messages", []) - token_count = len(str(messages)) / self.CHARACTERS_PER_TOKEN + token_count = len(str(messages)) / CHARACTERS_PER_TOKEN else: token_count = 0 # Default if method is unknown @@ -412,9 +411,7 @@ async def rate_limited_generator() -> AsyncGenerator[LLMModelOrChild, None]: async for item in func(self, *args, **kwargs): token_count = 0 if isinstance(item, Chunk): - token_count = int( - len(item.text or "") / self.CHARACTERS_PER_TOKEN - ) + token_count = int(len(item.text or "") / CHARACTERS_PER_TOKEN) await self.check_rate_limit(token_count) yield item diff --git a/tests/test_rate_limiter.py b/tests/test_rate_limiter.py index f183090e..ecc06828 100644 --- a/tests/test_rate_limiter.py +++ b/tests/test_rate_limiter.py @@ -5,9 +5,13 @@ import pytest from limits import RateLimitItemPerSecond -from litellm import Type -from paperqa.llms import Chunk, LiteLLMEmbeddingModel, LiteLLMModel +from paperqa.llms import ( + CHARACTERS_PER_TOKEN, + Chunk, + LiteLLMEmbeddingModel, + LiteLLMModel, +) from paperqa.types import LLMResult LLM_CONFIG_W_RATE_LIMITS = [ @@ -140,7 +144,7 @@ async def time_n_llm_methods( if hasattr(outputs[0], "prompt_tokens"): token_count = sum(o.prompt_tokens + o.completion_tokens for o in outputs) - return max(character_count / llm.CHARACTERS_PER_TOKEN, token_count) / ( + return max(character_count / CHARACTERS_PER_TOKEN, token_count) / ( time.time() - start_time ) @@ -148,7 +152,7 @@ async def time_n_llm_methods( @pytest.mark.parametrize("llm_config_w_rate_limits", LLM_CONFIG_W_RATE_LIMITS) @pytest.mark.asyncio async def test_rate_limit_on_run_prompt( - llm_config_w_rate_limits: dict[str, Any], litellm_model: Type[LiteLLMModel] + llm_config_w_rate_limits: dict[str, Any], litellm_model: type[LiteLLMModel] ) -> None: llm = litellm_model(**llm_config_w_rate_limits) @@ -214,7 +218,7 @@ def accum2(x) -> None: async def test_rate_limit_on_sequential_completion_litellm_methods( llm_config_w_rate_limits: dict[str, Any], llm_method_kwargs: dict[str, Any], - litellm_model: Type[LiteLLMModel], + litellm_model: type[LiteLLMModel], ) -> None: llm = litellm_model(**llm_config_w_rate_limits) @@ -245,7 +249,7 @@ async def test_rate_limit_on_sequential_completion_litellm_methods( async def test_rate_limit_on_parallel_completion_litellm_methods( llm_config_w_rate_limits: dict[str, Any], llm_method_kwargs: dict[str, Any], - litellm_model: Type[LiteLLMModel], + litellm_model: type[LiteLLMModel], ) -> None: llm = litellm_model(**llm_config_w_rate_limits) @@ -276,7 +280,7 @@ async def test_rate_limit_on_parallel_completion_litellm_methods( @pytest.mark.asyncio async def test_embedding_rate_limits( embedding_config_w_rate_limits: dict[str, Any], - litellm_embedding_model: Type[LiteLLMEmbeddingModel], + litellm_embedding_model: type[LiteLLMEmbeddingModel], ) -> None: embedding_model = litellm_embedding_model(**embedding_config_w_rate_limits) @@ -284,7 +288,7 @@ async def test_embedding_rate_limits( start = time.time() await embedding_model.embed_documents(texts=texts_to_embed, batch_size=5) estimated_tokens_per_second = sum( - len(t) / embedding_model.CHARACTERS_PER_TOKEN for t in texts_to_embed + len(t) / CHARACTERS_PER_TOKEN for t in texts_to_embed ) / (time.time() - start) if "rate_limit" in embedding_config_w_rate_limits: From 83b9f68e78e117c4ab3f13bd3d117691ef22f8c2 Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Wed, 2 Oct 2024 16:16:12 -0700 Subject: [PATCH 05/20] need to await achat in _achat --- paperqa/llms.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paperqa/llms.py b/paperqa/llms.py index 40f03a85..4c3b041f 100644 --- a/paperqa/llms.py +++ b/paperqa/llms.py @@ -16,7 +16,7 @@ from enum import StrEnum from inspect import isasyncgenfunction, signature from sys import version_info -from typing import Any, ClassVar, TypeVar, cast +from typing import Any, ClassVar, TypeVar import numpy as np import tiktoken @@ -265,7 +265,7 @@ async def _run_chat( start_clock = asyncio.get_running_loop().time() if callbacks is None: - chunk = cast(Chunk, self.achat(messages)) + chunk = await self.achat(messages) output = chunk.text else: sync_callbacks = [f for f in callbacks if not is_coroutine_callable(f)] From cbc4454dc2dfb6862ac82c68dcb9c35d707811f1 Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Wed, 2 Oct 2024 16:52:05 -0700 Subject: [PATCH 06/20] remove un-needed fixtures --- paperqa/llms.py | 9 ++++----- tests/conftest.py | 14 -------------- tests/test_rate_limiter.py | 30 ++++++++++-------------------- 3 files changed, 14 insertions(+), 39 deletions(-) diff --git a/paperqa/llms.py b/paperqa/llms.py index 4c3b041f..fe508cb9 100644 --- a/paperqa/llms.py +++ b/paperqa/llms.py @@ -70,7 +70,7 @@ class EmbeddingModel(ABC, BaseModel): description="Optional `rate_limit` key, value must be a RateLimitItem", ) - async def check_rate_limit(self, token_count: float, **kwargs): + async def check_rate_limit(self, token_count: float, **kwargs) -> None: if "rate_limit" in self.config: await GLOBAL_LIMITER.try_acquire( ("client", self.name), @@ -474,7 +474,7 @@ class LiteLLMModel(LLMModel): @classmethod def maybe_set_config_attribute(cls, data: dict[str, Any]) -> dict[str, Any]: """If a user only gives a name, make a sensible config dict for them.""" - if "name" in data and "config" not in data: + if "name" in data and ("model_list" not in data.get("config", {})): data["config"] = { "model_list": [ { @@ -488,7 +488,7 @@ def maybe_set_config_attribute(cls, data: dict[str, Any]) -> dict[str, Any]: } ], "router_kwargs": {"num_retries": 3, "retry_after": 5, "timeout": 60}, - } + } | data.get("config", {}) # we only support one "model name" for now, here we validate model_list = data["config"]["model_list"] if IS_PYTHON_BELOW_312: @@ -520,8 +520,7 @@ def router(self): ) return self._router - async def check_rate_limit(self, token_count: float, **kwargs): - # TODO: validate rate_limit config structure? + async def check_rate_limit(self, token_count: float, **kwargs) -> None: if "rate_limit" in self.config: await GLOBAL_LIMITER.try_acquire( ("client", self.name), diff --git a/tests/conftest.py b/tests/conftest.py index 1f6f7e7d..1f0ac16e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,7 +13,6 @@ from paperqa.clients.crossref import CROSSREF_HEADER_KEY from paperqa.clients.semantic_scholar import SEMANTIC_SCHOLAR_HEADER_KEY -from paperqa.llms import LiteLLMEmbeddingModel, LiteLLMModel from paperqa.settings import Settings from paperqa.types import Answer from paperqa.utils import setup_default_logs @@ -130,16 +129,3 @@ def fixture_reset_log_levels(caplog) -> Iterator[None]: logger = logging.getLogger(name) logger.setLevel(logging.NOTSET) logger.propagate = True - - -# get a new module objects -# to avoid sharing a rate limiter -# between calls -@pytest.fixture -def litellm_model() -> type[LiteLLMModel]: - return LiteLLMModel - - -@pytest.fixture -def litellm_embedding_model() -> type[LiteLLMEmbeddingModel]: - return LiteLLMEmbeddingModel diff --git a/tests/test_rate_limiter.py b/tests/test_rate_limiter.py index ecc06828..88373eac 100644 --- a/tests/test_rate_limiter.py +++ b/tests/test_rate_limiter.py @@ -15,18 +15,11 @@ from paperqa.types import LLMResult LLM_CONFIG_W_RATE_LIMITS = [ + # following ensures that "short-form" rate limits are also supported + # where the user doesn't specify the model_list { "name": "gpt-4o-mini", "config": { - "model_list": [ - { - "model_name": "gpt-4o-mini", - "litellm_params": { - "model": "gpt-4o-mini", - "temperature": 0, - }, - } - ], "rate_limit": {"gpt-4o-mini": RateLimitItemPerSecond(20, 3)}, }, }, @@ -144,18 +137,18 @@ async def time_n_llm_methods( if hasattr(outputs[0], "prompt_tokens"): token_count = sum(o.prompt_tokens + o.completion_tokens for o in outputs) - return max(character_count / CHARACTERS_PER_TOKEN, token_count) / ( - time.time() - start_time - ) + return ( + (character_count / CHARACTERS_PER_TOKEN) if token_count == 0 else token_count + ) / (time.time() - start_time) @pytest.mark.parametrize("llm_config_w_rate_limits", LLM_CONFIG_W_RATE_LIMITS) @pytest.mark.asyncio async def test_rate_limit_on_run_prompt( - llm_config_w_rate_limits: dict[str, Any], litellm_model: type[LiteLLMModel] + llm_config_w_rate_limits: dict[str, Any], ) -> None: - llm = litellm_model(**llm_config_w_rate_limits) + llm = LiteLLMModel(**llm_config_w_rate_limits) outputs = [] @@ -218,10 +211,9 @@ def accum2(x) -> None: async def test_rate_limit_on_sequential_completion_litellm_methods( llm_config_w_rate_limits: dict[str, Any], llm_method_kwargs: dict[str, Any], - litellm_model: type[LiteLLMModel], ) -> None: - llm = litellm_model(**llm_config_w_rate_limits) + llm = LiteLLMModel(**llm_config_w_rate_limits) estimated_tokens_per_second = await time_n_llm_methods( llm, @@ -249,10 +241,9 @@ async def test_rate_limit_on_sequential_completion_litellm_methods( async def test_rate_limit_on_parallel_completion_litellm_methods( llm_config_w_rate_limits: dict[str, Any], llm_method_kwargs: dict[str, Any], - litellm_model: type[LiteLLMModel], ) -> None: - llm = litellm_model(**llm_config_w_rate_limits) + llm = LiteLLMModel(**llm_config_w_rate_limits) if "iter" not in llm_method_kwargs["method"]: estimated_tokens_per_second = await time_n_llm_methods( @@ -280,10 +271,9 @@ async def test_rate_limit_on_parallel_completion_litellm_methods( @pytest.mark.asyncio async def test_embedding_rate_limits( embedding_config_w_rate_limits: dict[str, Any], - litellm_embedding_model: type[LiteLLMEmbeddingModel], ) -> None: - embedding_model = litellm_embedding_model(**embedding_config_w_rate_limits) + embedding_model = LiteLLMEmbeddingModel(**embedding_config_w_rate_limits) texts_to_embed = ["the duck says"] * 10 start = time.time() await embedding_model.embed_documents(texts=texts_to_embed, batch_size=5) From 0c0936c962a021377e0696ac0b78933ad8c4f07b Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Thu, 3 Oct 2024 08:51:51 -0700 Subject: [PATCH 07/20] rename CHARACTERS_PER_TOKEN->CHARACTERS_PER_TOKEN_ASSUMPTION, add typehints to return properties, add basal tokens to completion --- paperqa/llms.py | 42 +++++++++++++++++++++++--------------- paperqa/rate_limiter.py | 7 ++++--- tests/test_rate_limiter.py | 18 +++++++++------- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/paperqa/llms.py b/paperqa/llms.py index fe508cb9..74f09b07 100644 --- a/paperqa/llms.py +++ b/paperqa/llms.py @@ -7,16 +7,16 @@ from collections.abc import ( AsyncGenerator, AsyncIterable, + AsyncIterator, Awaitable, Callable, - Coroutine, Iterable, Sequence, ) from enum import StrEnum from inspect import isasyncgenfunction, signature from sys import version_info -from typing import Any, ClassVar, TypeVar +from typing import Any, TypeVar import numpy as np import tiktoken @@ -60,7 +60,13 @@ class EmbeddingModes(StrEnum): QUERY = "query" -CHARACTERS_PER_TOKEN: float = 4.0 +# Estimate from OpenAI's FAQ +# https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them +CHARACTERS_PER_TOKEN_ASSUMPTION: float = 4.0 +# Added tokens from user/role message +# Need to add while doing rate limits +# Taken from empirical counts in tests +EXTRA_TOKENS_FROM_USER_ROLE: int = 7 class EmbeddingModel(ABC, BaseModel): @@ -99,7 +105,10 @@ async def embed_documents( for i in range(0, N, batch_size): await self.check_rate_limit( - sum(len(t) / CHARACTERS_PER_TOKEN for t in texts[i : i + batch_size]) + sum( + len(t) / CHARACTERS_PER_TOKEN_ASSUMPTION + for t in texts[i : i + batch_size] + ) ) response = await aembedding( @@ -164,7 +173,6 @@ class LLMModel(ABC, BaseModel): exclude=True, ) config: dict = Field(default_factory=dict) - CHARACTERS_PER_TOKEN: ClassVar[float] = 4.0 async def acomplete(self, prompt: str) -> Chunk: """Return the completion as string and the number of tokens in the prompt and completion.""" @@ -372,32 +380,30 @@ def rate_limited( func: Callable[[LLMModelOrChild, Any], Awaitable[Chunk] | AsyncIterable[Chunk]], ) -> Callable[ [LLMModelOrChild, Any, Any], - Coroutine[ - Any, Any, Chunk | AsyncIterable[Chunk] | AsyncGenerator[LLMModelOrChild, None] - ], + Awaitable[Chunk | AsyncIterator[Chunk] | AsyncIterator[LLMModelOrChild]], ]: """Decorator to rate limit relevant methods of an LLMModel.""" @functools.wraps(func) async def wrapper( self: LLMModelOrChild, *args: Any, **kwargs: Any - ) -> Chunk | AsyncIterable[Chunk] | AsyncGenerator[LLMModelOrChild, None]: + ) -> Chunk | AsyncIterator[Chunk] | AsyncIterator[LLMModelOrChild]: - if not hasattr(self, "check_rate_limit") or not hasattr( - self, "CHARACTERS_PER_TOKEN" - ): + if not hasattr(self, "check_rate_limit"): raise NotImplementedError( - f"Model {self.name} must have a `check_rate_limit` method " - "and a `CHARACTERS_PER_TOKEN` class variable." + f"Model {self.name} must have a `check_rate_limit` method." ) # Estimate token count based on input if func.__name__ in {"acomplete", "acomplete_iter"}: prompt = args[0] if args else kwargs.get("prompt", "") - token_count = len(prompt) / CHARACTERS_PER_TOKEN + token_count = ( + len(prompt) / CHARACTERS_PER_TOKEN_ASSUMPTION + + EXTRA_TOKENS_FROM_USER_ROLE + ) elif func.__name__ in {"achat", "achat_iter"}: messages = args[0] if args else kwargs.get("messages", []) - token_count = len(str(messages)) / CHARACTERS_PER_TOKEN + token_count = len(str(messages)) / CHARACTERS_PER_TOKEN_ASSUMPTION else: token_count = 0 # Default if method is unknown @@ -411,7 +417,9 @@ async def rate_limited_generator() -> AsyncGenerator[LLMModelOrChild, None]: async for item in func(self, *args, **kwargs): token_count = 0 if isinstance(item, Chunk): - token_count = int(len(item.text or "") / CHARACTERS_PER_TOKEN) + token_count = int( + len(item.text or "") / CHARACTERS_PER_TOKEN_ASSUMPTION + ) await self.check_rate_limit(token_count) yield item diff --git a/paperqa/rate_limiter.py b/paperqa/rate_limiter.py index 35fcbc24..0ff81473 100644 --- a/paperqa/rate_limiter.py +++ b/paperqa/rate_limiter.py @@ -50,6 +50,8 @@ class GlobalRateLimiter: WAIT_INCREMENT: ClassVar[float] = 0.01 # seconds + # list of public free outbount IP services + # generated initially w. claude, then filtered IP_CHECK_SERVICES: ClassVar[Collection[str]] = { "https://api.ipify.org", "https://ifconfig.me", @@ -100,7 +102,7 @@ async def outbount_ip(self) -> str: return self._current_ip @property - def storage(self): + def storage(self) -> RedisStorage | MemoryStorage: if self._storage is None: if os.environ.get("REDIS_URL") and not self.use_in_memory: self._storage = RedisStorage(f"async+redis://{os.environ['REDIS_URL']}") @@ -112,7 +114,7 @@ def storage(self): return self._storage @property - def rate_limiter(self): + def rate_limiter(self) -> MovingWindowRateLimiter: if self._rate_limiter is None: self._rate_limiter = MovingWindowRateLimiter(self.storage) return self._rate_limiter @@ -318,7 +320,6 @@ async def try_acquire( raise ValueError( f"Weight ({weight}) > RateLimit ({rate_limit}), cannot satisfy rate limit." ) - while True: elapsed = 0.0 while ( diff --git a/tests/test_rate_limiter.py b/tests/test_rate_limiter.py index 88373eac..1c299e49 100644 --- a/tests/test_rate_limiter.py +++ b/tests/test_rate_limiter.py @@ -7,7 +7,7 @@ from limits import RateLimitItemPerSecond from paperqa.llms import ( - CHARACTERS_PER_TOKEN, + CHARACTERS_PER_TOKEN_ASSUMPTION, Chunk, LiteLLMEmbeddingModel, LiteLLMModel, @@ -69,22 +69,24 @@ }, ] +RATE_LIMITER_PROMPT = "Animals make many noises. The duck says" + LLM_METHOD_AND_INPUTS = [ { "method": "acomplete", - "kwargs": {"prompt": "The duck says"}, + "kwargs": {"prompt": RATE_LIMITER_PROMPT}, }, { "method": "acomplete_iter", - "kwargs": {"prompt": "The duck says"}, + "kwargs": {"prompt": RATE_LIMITER_PROMPT}, }, { "method": "achat", - "kwargs": {"messages": [{"role": "user", "content": "The duck says"}]}, + "kwargs": {"messages": [{"role": "user", "content": RATE_LIMITER_PROMPT}]}, }, { "method": "achat_iter", - "kwargs": {"messages": [{"role": "user", "content": "The duck says"}]}, + "kwargs": {"messages": [{"role": "user", "content": RATE_LIMITER_PROMPT}]}, }, ] @@ -138,7 +140,9 @@ async def time_n_llm_methods( token_count = sum(o.prompt_tokens + o.completion_tokens for o in outputs) return ( - (character_count / CHARACTERS_PER_TOKEN) if token_count == 0 else token_count + (character_count / CHARACTERS_PER_TOKEN_ASSUMPTION) + if token_count == 0 + else token_count ) / (time.time() - start_time) @@ -278,7 +282,7 @@ async def test_embedding_rate_limits( start = time.time() await embedding_model.embed_documents(texts=texts_to_embed, batch_size=5) estimated_tokens_per_second = sum( - len(t) / CHARACTERS_PER_TOKEN for t in texts_to_embed + len(t) / CHARACTERS_PER_TOKEN_ASSUMPTION for t in texts_to_embed ) / (time.time() - start) if "rate_limit" in embedding_config_w_rate_limits: From 8331f9b5fb5f0a865a5bc19a759d87b1126cc501 Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Thu, 3 Oct 2024 08:55:12 -0700 Subject: [PATCH 08/20] refurb update to remove defaults --- paperqa/rate_limiter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paperqa/rate_limiter.py b/paperqa/rate_limiter.py index 0ff81473..84d4ec64 100644 --- a/paperqa/rate_limiter.py +++ b/paperqa/rate_limiter.py @@ -240,7 +240,7 @@ async def get_rate_limit_keys( await client.quit() - return [self.parse_key(key.decode("utf-8")) for key in matching_keys] + return [self.parse_key(key.decode()) for key in matching_keys] def get_in_memory_limit_keys( self, From 6b60dc81af6793f7bccbaa251b1a6543ce5bf202 Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Thu, 3 Oct 2024 15:15:23 -0700 Subject: [PATCH 09/20] add passthrough from settings into llm rate limits, add test for passthrough, update default rate limits --- paperqa/configs/fast.json | 3 ++ paperqa/configs/high_quality.json | 6 ---- paperqa/configs/tier1_limits.json | 53 +++++++++++++++++++++++++++++ paperqa/configs/tier2_limits.json | 55 +++++++++++++++++++++++++++++++ paperqa/configs/tier3_limits.json | 55 +++++++++++++++++++++++++++++++ paperqa/configs/tier4_limits.json | 55 +++++++++++++++++++++++++++++++ paperqa/configs/tier5_limits.json | 55 +++++++++++++++++++++++++++++++ paperqa/llms.py | 10 +++--- paperqa/rate_limiter.py | 22 +++++++++---- paperqa/settings.py | 12 +++---- tests/test_agents.py | 28 ++++++++++++++++ 11 files changed, 331 insertions(+), 23 deletions(-) create mode 100644 paperqa/configs/tier1_limits.json create mode 100644 paperqa/configs/tier2_limits.json create mode 100644 paperqa/configs/tier3_limits.json create mode 100644 paperqa/configs/tier4_limits.json create mode 100644 paperqa/configs/tier5_limits.json diff --git a/paperqa/configs/fast.json b/paperqa/configs/fast.json index c7b2252b..434a3e39 100644 --- a/paperqa/configs/fast.json +++ b/paperqa/configs/fast.json @@ -9,5 +9,8 @@ }, "parsing": { "use_doc_details": false + }, + "agent": { + "agent_type": "fake" } } diff --git a/paperqa/configs/high_quality.json b/paperqa/configs/high_quality.json index a4160a8d..1fac7788 100644 --- a/paperqa/configs/high_quality.json +++ b/paperqa/configs/high_quality.json @@ -8,11 +8,5 @@ "use_doc_details": true, "chunk_size": 7000, "overlap": 250 - }, - "prompts": { - "use_json": true - }, - "agent": { - "agent_type": "ToolSelector" } } diff --git a/paperqa/configs/tier1_limits.json b/paperqa/configs/tier1_limits.json new file mode 100644 index 00000000..c4ac5f71 --- /dev/null +++ b/paperqa/configs/tier1_limits.json @@ -0,0 +1,53 @@ +{ + "answer": { + "evidence_k": 5, + "evidence_detailed_citations": false, + "evidence_summary_length": "25 to 50 words", + "answer_max_sources": 3, + "answer_length": "50 to 100 words", + "max_concurrent_requests": 5 + }, + "parsing": { + "use_doc_details": false + }, + "prompts": { + "use_json": true + }, + "llm_config": { + "rate_limit": { + "gpt-4o": "30000 per 1 minute", + "gpt-4o-2024-08-06": "30000 per 1 minute", + "gpt-4o-2024-05-13": "30000 per 1 minute", + "gpt-4o-mini": "200000 per 1 minute", + "gpt-4o-mini-2024-07-18": "200000 per 1 minute", + "gpt-4-turbo": "30000 per 1 minute", + "gpt-4-turbo-2024-04-09": "30000 per 1 minute", + "gpt-4-0613": "10000 per 1 minute", + "gpt-4-0314": "10000 per 1 minute", + "gpt-4": "10000 per 1 minute", + "gpt-3.5-turbo-0125": "200000 per 1 minute", + "gpt-3.5-turbo": "200000 per 1 minute", + "gpt-3.5-turbo-1106": "200000 per 1 minute" + } + }, + "summary_llm_config": { + "rate_limit": { + "gpt-4o": "30000 per 1 minute", + "gpt-4o-2024-08-06": "30000 per 1 minute", + "gpt-4o-2024-05-13": "30000 per 1 minute", + "gpt-4o-mini": "200000 per 1 minute", + "gpt-4o-mini-2024-07-18": "200000 per 1 minute", + "gpt-4-turbo": "30000 per 1 minute", + "gpt-4-turbo-2024-04-09": "30000 per 1 minute", + "gpt-4-0613": "10000 per 1 minute", + "gpt-4-0314": "10000 per 1 minute", + "gpt-4": "10000 per 1 minute", + "gpt-3.5-turbo-0125": "200000 per 1 minute", + "gpt-3.5-turbo": "200000 per 1 minute", + "gpt-3.5-turbo-1106": "200000 per 1 minute" + } + }, + "embedding_config": { + "rate_limit": "1000000 per 1 minute" + } +} diff --git a/paperqa/configs/tier2_limits.json b/paperqa/configs/tier2_limits.json new file mode 100644 index 00000000..fb1ad124 --- /dev/null +++ b/paperqa/configs/tier2_limits.json @@ -0,0 +1,55 @@ +{ + "answer": { + "evidence_k": 8, + "answer_max_sources": 3, + "max_concurrent_requests": 8 + }, + "parsing": { + "use_doc_details": true, + "chunk_size": 7000, + "overlap": 250 + }, + "prompts": { + "use_json": true + }, + "agent": { + "agent_type": "ToolSelector" + }, + "llm_config": { + "rate_limit": { + "gpt-4o": "450000 per 1 minute", + "gpt-4o-2024-08-06": "450000 per 1 minute", + "gpt-4o-2024-05-13": "450000 per 1 minute", + "gpt-4o-mini": "2000000 per 1 minute", + "gpt-4o-mini-2024-07-18": "2000000 per 1 minute", + "gpt-4-turbo": "450000 per 1 minute", + "gpt-4-turbo-2024-04-09": "450000 per 1 minute", + "gpt-4-0613": "40000 per 1 minute", + "gpt-4-0314": "40000 per 1 minute", + "gpt-4": "40000 per 1 minute", + "gpt-3.5-turbo-0125": "2000000 per 1 minute", + "gpt-3.5-turbo": "2000000 per 1 minute", + "gpt-3.5-turbo-1106": "2000000 per 1 minute" + } + }, + "summary_llm_config": { + "rate_limit": { + "gpt-4o": "450000 per 1 minute", + "gpt-4o-2024-08-06": "450000 per 1 minute", + "gpt-4o-2024-05-13": "450000 per 1 minute", + "gpt-4o-mini": "2000000 per 1 minute", + "gpt-4o-mini-2024-07-18": "2000000 per 1 minute", + "gpt-4-turbo": "450000 per 1 minute", + "gpt-4-turbo-2024-04-09": "450000 per 1 minute", + "gpt-4-0613": "40000 per 1 minute", + "gpt-4-0314": "40000 per 1 minute", + "gpt-4": "40000 per 1 minute", + "gpt-3.5-turbo-0125": "2000000 per 1 minute", + "gpt-3.5-turbo": "2000000 per 1 minute", + "gpt-3.5-turbo-1106": "2000000 per 1 minute" + } + }, + "embedding_config": { + "rate_limit": "1000000 per 1 minute" + } +} diff --git a/paperqa/configs/tier3_limits.json b/paperqa/configs/tier3_limits.json new file mode 100644 index 00000000..7366e989 --- /dev/null +++ b/paperqa/configs/tier3_limits.json @@ -0,0 +1,55 @@ +{ + "answer": { + "evidence_k": 8, + "answer_max_sources": 3, + "max_concurrent_requests": 8 + }, + "parsing": { + "use_doc_details": true, + "chunk_size": 7000, + "overlap": 250 + }, + "prompts": { + "use_json": true + }, + "agent": { + "agent_type": "ToolSelector" + }, + "llm_config": { + "rate_limit": { + "gpt-4o": "800000 per 1 minute", + "gpt-4o-2024-08-06": "800000 per 1 minute", + "gpt-4o-2024-05-13": "800000 per 1 minute", + "gpt-4o-mini": "4000000 per 1 minute", + "gpt-4o-mini-2024-07-18": "4000000 per 1 minute", + "gpt-4-turbo": "600000 per 1 minute", + "gpt-4-turbo-2024-04-09": "600000 per 1 minute", + "gpt-4-0613": "80000 per 1 minute", + "gpt-4-0314": "80000 per 1 minute", + "gpt-4": "80000 per 1 minute", + "gpt-3.5-turbo-0125": "4000000 per 1 minute", + "gpt-3.5-turbo": "4000000 per 1 minute", + "gpt-3.5-turbo-1106": "4000000 per 1 minute" + } + }, + "summary_llm_config": { + "rate_limit": { + "gpt-4o": "800000 per 1 minute", + "gpt-4o-2024-08-06": "800000 per 1 minute", + "gpt-4o-2024-05-13": "800000 per 1 minute", + "gpt-4o-mini": "4000000 per 1 minute", + "gpt-4o-mini-2024-07-18": "4000000 per 1 minute", + "gpt-4-turbo": "600000 per 1 minute", + "gpt-4-turbo-2024-04-09": "600000 per 1 minute", + "gpt-4-0613": "80000 per 1 minute", + "gpt-4-0314": "80000 per 1 minute", + "gpt-4": "80000 per 1 minute", + "gpt-3.5-turbo-0125": "4000000 per 1 minute", + "gpt-3.5-turbo": "4000000 per 1 minute", + "gpt-3.5-turbo-1106": "4000000 per 1 minute" + } + }, + "embedding_config": { + "rate_limit": "5000000 per 1 minute" + } +} diff --git a/paperqa/configs/tier4_limits.json b/paperqa/configs/tier4_limits.json new file mode 100644 index 00000000..07b2bb73 --- /dev/null +++ b/paperqa/configs/tier4_limits.json @@ -0,0 +1,55 @@ +{ + "answer": { + "evidence_k": 10, + "answer_max_sources": 5, + "max_concurrent_requests": 8 + }, + "parsing": { + "use_doc_details": true, + "chunk_size": 7000, + "overlap": 250 + }, + "prompts": { + "use_json": true + }, + "agent": { + "agent_type": "ToolSelector" + }, + "llm_config": { + "rate_limit": { + "gpt-4o": "2000000 per 1 minute", + "gpt-4o-2024-08-06": "2000000 per 1 minute", + "gpt-4o-2024-05-13": "2000000 per 1 minute", + "gpt-4o-mini": "10000000 per 1 minute", + "gpt-4o-mini-2024-07-18": "10000000 per 1 minute", + "gpt-4-turbo": "800000 per 1 minute", + "gpt-4-turbo-2024-04-09": "800000 per 1 minute", + "gpt-4-0613": "300000 per 1 minute", + "gpt-4-0314": "300000 per 1 minute", + "gpt-4": "300000 per 1 minute", + "gpt-3.5-turbo-0125": "10000000 per 1 minute", + "gpt-3.5-turbo": "10000000 per 1 minute", + "gpt-3.5-turbo-1106": "10000000 per 1 minute" + } + }, + "summary_llm_config": { + "rate_limit": { + "gpt-4o": "2000000 per 1 minute", + "gpt-4o-2024-08-06": "2000000 per 1 minute", + "gpt-4o-2024-05-13": "2000000 per 1 minute", + "gpt-4o-mini": "10000000 per 1 minute", + "gpt-4o-mini-2024-07-18": "10000000 per 1 minute", + "gpt-4-turbo": "800000 per 1 minute", + "gpt-4-turbo-2024-04-09": "800000 per 1 minute", + "gpt-4-0613": "300000 per 1 minute", + "gpt-4-0314": "300000 per 1 minute", + "gpt-4": "300000 per 1 minute", + "gpt-3.5-turbo-0125": "10000000 per 1 minute", + "gpt-3.5-turbo": "10000000 per 1 minute", + "gpt-3.5-turbo-1106": "10000000 per 1 minute" + } + }, + "embedding_config": { + "rate_limit": "5000000 per 1 minute" + } +} diff --git a/paperqa/configs/tier5_limits.json b/paperqa/configs/tier5_limits.json new file mode 100644 index 00000000..91d82383 --- /dev/null +++ b/paperqa/configs/tier5_limits.json @@ -0,0 +1,55 @@ +{ + "answer": { + "evidence_k": 15, + "answer_max_sources": 5, + "max_concurrent_requests": 8 + }, + "parsing": { + "use_doc_details": true, + "chunk_size": 7000, + "overlap": 250 + }, + "prompts": { + "use_json": true + }, + "agent": { + "agent_type": "ToolSelector" + }, + "llm_config": { + "rate_limit": { + "gpt-4o": "30000000 per 1 minute", + "gpt-4o-2024-08-06": "30000000 per 1 minute", + "gpt-4o-2024-05-13": "30000000 per 1 minute", + "gpt-4o-mini": "150000000 per 1 minute", + "gpt-4o-mini-2024-07-18": "150000000 per 1 minute", + "gpt-4-turbo": "2000000 per 1 minute", + "gpt-4-turbo-2024-04-09": "2000000 per 1 minute", + "gpt-4-0613": "1000000 per 1 minute", + "gpt-4-0314": "1000000 per 1 minute", + "gpt-4": "1000000 per 1 minute", + "gpt-3.5-turbo-0125": "50000000 per 1 minute", + "gpt-3.5-turbo": "50000000 per 1 minute", + "gpt-3.5-turbo-1106": "50000000 per 1 minute" + } + }, + "summary_llm_config": { + "rate_limit": { + "gpt-4o": "30000000 per 1 minute", + "gpt-4o-2024-08-06": "30000000 per 1 minute", + "gpt-4o-2024-05-13": "30000000 per 1 minute", + "gpt-4o-mini": "150000000 per 1 minute", + "gpt-4o-mini-2024-07-18": "150000000 per 1 minute", + "gpt-4-turbo": "2000000 per 1 minute", + "gpt-4-turbo-2024-04-09": "2000000 per 1 minute", + "gpt-4-0613": "1000000 per 1 minute", + "gpt-4-0314": "1000000 per 1 minute", + "gpt-4": "1000000 per 1 minute", + "gpt-3.5-turbo-0125": "50000000 per 1 minute", + "gpt-3.5-turbo": "50000000 per 1 minute", + "gpt-3.5-turbo-1106": "50000000 per 1 minute" + } + }, + "embedding_config": { + "rate_limit": "10000000 per 1 minute" + } +} diff --git a/paperqa/llms.py b/paperqa/llms.py index 74f09b07..c720ab7e 100644 --- a/paperqa/llms.py +++ b/paperqa/llms.py @@ -73,7 +73,7 @@ class EmbeddingModel(ABC, BaseModel): name: str config: dict = Field( default_factory=dict, - description="Optional `rate_limit` key, value must be a RateLimitItem", + description="Optional `rate_limit` key, value must be a RateLimitItem or RateLimitItem string for parsing", ) async def check_rate_limit(self, token_count: float, **kwargs) -> None: @@ -95,7 +95,6 @@ async def embed_documents(self, texts: list[str]) -> list[list[float]]: class LiteLLMEmbeddingModel(EmbeddingModel): name: str = Field(default="text-embedding-3-small") - embedding_kwargs: dict = Field(default_factory=dict) async def embed_documents( self, texts: list[str], batch_size: int = 16 @@ -112,7 +111,9 @@ async def embed_documents( ) response = await aembedding( - self.name, input=texts[i : i + batch_size], **self.embedding_kwargs + self.name, + input=texts[i : i + batch_size], + **self.config.get("kwargs", {}), ) embeddings.extend([e["embedding"] for e in response.data]) @@ -470,6 +471,7 @@ class LiteLLMModel(LLMModel): `router_kwargs`: kwargs for the Router class `rate_limit`: (Optional) dictionary keyed by model group name with values of type limits.RateLimitItem (in tokens / minute) + or valid limits.RateLimitItem string for parsing This way users can specify routing strategies, retries, etc. """ @@ -745,4 +747,4 @@ def embedding_model_factory(embedding: str, **kwargs) -> EmbeddingModel: if embedding == "sparse": return SparseEmbeddingModel(**kwargs) - return LiteLLMEmbeddingModel(name=embedding, embedding_kwargs=kwargs) + return LiteLLMEmbeddingModel(name=embedding, config=kwargs) diff --git a/paperqa/rate_limiter.py b/paperqa/rate_limiter.py index 84d4ec64..4e793188 100644 --- a/paperqa/rate_limiter.py +++ b/paperqa/rate_limiter.py @@ -12,12 +12,15 @@ RateLimitItemPerMinute, RateLimitItemPerSecond, ) +from limits import ( + parse as limit_parse, +) from limits.aio.storage import MemoryStorage, RedisStorage from limits.aio.strategies import MovingWindowRateLimiter logger = logging.getLogger(__name__) -GLOBAL_RATE_LIMITER_TIMEOUT = float(os.environ.get("RATE_LIMITER_TIMOUT", "30")) +GLOBAL_RATE_LIMITER_TIMEOUT = float(os.environ.get("RATE_LIMITER_TIMOUT", "60")) # RATE_CONFIG keys are tuples, corresponding to a namespace and primary key. # Anything defined with MATCH_ALL variable, will match all non-matched requests for that namespace. @@ -64,12 +67,12 @@ class GlobalRateLimiter: def __init__( self, - rate_config: dict[ - tuple[str, str | MATCH_ALL_INPUTS], RateLimitItem - ] = RATE_CONFIG, + rate_config: ( + None | dict[tuple[str, str | MATCH_ALL_INPUTS], RateLimitItem] + ) = None, use_in_memory: bool = False, ): - self.rate_config = rate_config + self.rate_config = RATE_CONFIG if rate_config is None else rate_config self.use_in_memory = use_in_memory self._storage: RedisStorage | MemoryStorage | None = None self._rate_limiter: MovingWindowRateLimiter | None = None @@ -277,7 +280,7 @@ async def rate_limit_status(self): async def try_acquire( self, namespace_and_key: tuple[str, str | MATCH_ALL_INPUTS], - rate_limit: RateLimitItem | None = None, + rate_limit: RateLimitItem | str | None = None, machine_id: int = 0, timeout: float = GLOBAL_RATE_LIMITER_TIMEOUT, # noqa: ASYNC109 weight: int = 1, @@ -291,7 +294,9 @@ async def try_acquire( primary-keys in the "get" namespace will be stripped to the domain. rate_limit: Optional RateLimitItem to be used for the namespace and primary-key. - If not provided, RATE_CONFIG will be used to find the rate limit. + If not provided, RATE_CONFIG will be used to find the rate limit. Can also + use a string of the form: + [count] [per|/] [n (optional)] [second|minute|hour|day|month|year] machine_id: will be used to modify the namespace of GET requests if the primary key is not in the NO_MACHINE_ID_EXTENSIONS list. @@ -314,6 +319,9 @@ async def try_acquire( namespace, primary_key ) + if isinstance(rate_limit, str): + rate_limit = limit_parse(rate_limit) + rate_limit = rate_limit or _rate_limit if rate_limit.amount < weight and raise_impossible_limits: diff --git a/paperqa/settings.py b/paperqa/settings.py index 32176fd5..658457d8 100644 --- a/paperqa/settings.py +++ b/paperqa/settings.py @@ -115,12 +115,12 @@ def valid_parsings(self) -> list[ParsingOptions]: class ParsingSettings(BaseModel): """Settings relevant for parsing and chunking documents.""" - chunk_size: int = Field(default=3000, description="Number of characters per chunk") + chunk_size: int = Field(default=5000, description="Number of characters per chunk") use_doc_details: bool = Field( default=True, description="Whether to try to get metadata details for a Doc" ) overlap: int = Field( - default=100, description="Number of characters to overlap chunks" + default=250, description="Number of characters to overlap chunks" ) citation_prompt: str = Field( default=citation_prompt, @@ -204,7 +204,7 @@ class PromptSettings(BaseModel): ) post: str | None = None system: str = default_system_prompt - use_json: bool = False + use_json: bool = True # Not thrilled about this model, # but need to split out the system/summary # to get JSON @@ -309,7 +309,7 @@ class IndexSettings(BaseModel): description="Whether to recurse into subdirectories when indexing sources.", ) concurrency: int = Field( - default=30, + default=5, # low default for folks without S2/Crossref keys description="Number of concurrent filesystem reads for indexing", ) sync_with_paper_directory: bool = Field( @@ -343,7 +343,7 @@ class AgentSettings(BaseModel): ) agent_type: str = Field( - default="fake", + default="ToolSelector", description="Type of agent to use", ) agent_config: dict[str, Any] | None = Field( @@ -402,7 +402,7 @@ class AgentSettings(BaseModel): ) index_concurrency: int = Field( - default=30, + default=5, # low default for folks without S2/Crossref keys description="Number of concurrent filesystem reads for indexing", exclude=True, frozen=True, diff --git a/tests/test_agents.py b/tests/test_agents.py index 2c5e36a0..f34b931d 100644 --- a/tests/test_agents.py +++ b/tests/test_agents.py @@ -1,5 +1,6 @@ from __future__ import annotations +import importlib import itertools import json import re @@ -409,6 +410,33 @@ async def test_agent_sharing_state( ), "Answer has more sources than expected" +def test_settings_model_config() -> None: + + settings_name = "tier1_limits" + tier1 = Settings.from_name(settings_name) + + with Path( + str(importlib.resources.files("paperqa.configs") / f"{settings_name}.json") + ).open("r") as f: + raw_settings = json.loads(f.read()) + + llm_model = tier1.get_llm() + summary_llm_model = tier1.get_summary_llm() + embedding_model = tier1.get_embedding_model() + assert ( + llm_model.config["rate_limit"]["gpt-4o"] + == raw_settings["llm_config"]["rate_limit"]["gpt-4o"] + ) + assert ( + summary_llm_model.config["rate_limit"]["gpt-4o"] + == raw_settings["summary_llm_config"]["rate_limit"]["gpt-4o"] + ) + assert ( + embedding_model.config["rate_limit"] + == raw_settings["embedding_config"]["rate_limit"] + ) + + def test_tool_schema(agent_test_settings: Settings) -> None: """Check the tool schema passed to LLM providers.""" tools = settings_to_tools(agent_test_settings) From d7c77ed5073ada8127a3fc6cf65694a3935cb3f3 Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Thu, 3 Oct 2024 15:42:22 -0700 Subject: [PATCH 10/20] add rate limits to readme and refurb non-default fix --- README.md | 33 +++++++++++++++++++++++++++++++++ tests/test_agents.py | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3de3eeb9..19bccc92 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ question answering, summarization, and contradiction detection. - [Installation](#installation) - [CLI Usage](#cli-usage) - [Bundled Settings](#bundled-settings) + - [Rate Limits](#rate-limits) - [Library Usage](#library-usage) - [`ask` manually](#ask-manually) - [Adding Documents Manually](#adding-documents-manually) @@ -250,6 +251,38 @@ Inside [`paperqa/configs`](paperqa/configs) we bundle known useful settings: | wikicrow | Setting to emulate the Wikipedia article writing used in our WikiCrow publication. | | contracrow | Setting to find contradictions in papers, your query should be a claim that needs to be flagged as a contradiction (or not). | | debug | Setting useful solely for debugging, but not in any actual application beyond debugging. | +| tier1_limits | Settings that match OpenAI rate limits for each tier, you can use `tier<1-5>_limits` to specify the tier. | + +### Rate Limits + +If you are hitting rate limits, say with the OpenAI Tier 1 plan, you can add them into PaperQA2. +For each OpenAI tier, a pre-built setting exists to limit usage. + +```bash +pqa --settings 'tier1_limits' ask 'Are there nm scale features in thermoelectric materials?' +``` + +This will limit your system to use the tier1_limits, and slow down your queries to accommodate. + +You can also specify them manually: + +```bash +pqa --summary_llm_config '{"rate_limit": {"gpt-4o-2024-08-06": "30000 per 1 minute"}}' ask 'Are there nm scale features in thermoelectric materials?' +``` + +Or by adding into a settings object, if calling imperatively: + +```python +from paperqa import Settings, ask + +answer = ask( + "What manufacturing challenges are unique to bispecific antibodies?", + settings=Settings( + llm_config={"rate_limit": {"gpt-4o-2024-08-06": "30000 per 1 minute"}}, + summary_llm_config={"rate_limit": {"gpt-4o-2024-08-06": "30000 per 1 minute"}}, + ), +) +``` ## Library Usage diff --git a/tests/test_agents.py b/tests/test_agents.py index f34b931d..c4e93945 100644 --- a/tests/test_agents.py +++ b/tests/test_agents.py @@ -417,7 +417,7 @@ def test_settings_model_config() -> None: with Path( str(importlib.resources.files("paperqa.configs") / f"{settings_name}.json") - ).open("r") as f: + ).open() as f: raw_settings = json.loads(f.read()) llm_model = tier1.get_llm() From e1c24f5168d2170d028b83cc15d571ce1d80dee5 Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Thu, 3 Oct 2024 16:03:22 -0700 Subject: [PATCH 11/20] add google style docstring to rate limiter --- paperqa/rate_limiter.py | 85 ++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/paperqa/rate_limiter.py b/paperqa/rate_limiter.py index 4e793188..0648ae5b 100644 --- a/paperqa/rate_limiter.py +++ b/paperqa/rate_limiter.py @@ -6,6 +6,8 @@ from urllib.parse import urlparse import aiohttp +from clients.crossref import CROSSREF_BASE_URL +from clients.semantic_scholar import SEMANTIC_SCHOLAR_BASE_URL from coredis import Redis from limits import ( RateLimitItem, @@ -33,15 +35,15 @@ # user input machine_id will be used. MATCH_ALL = None -MATCH_ALL_INPUTS = Literal[None] +MatchAllInputs = Literal[None] MATCH_MACHINE_ID = "" FALLBACK_RATE_LIMIT = RateLimitItemPerSecond(3, 1) TOKEN_FALLBACK_RATE_LIMIT = RateLimitItemPerMinute(30_000, 1) -RATE_CONFIG: dict[tuple[str, str | MATCH_ALL_INPUTS], RateLimitItem] = { - ("get", "api.crossref.org"): RateLimitItemPerSecond(30, 1), - ("get", "api.semanticscholar.org"): RateLimitItemPerSecond(15, 1), +RATE_CONFIG: dict[tuple[str, str | MatchAllInputs], RateLimitItem] = { + ("get", CROSSREF_BASE_URL): RateLimitItemPerSecond(30, 1), + ("get", SEMANTIC_SCHOLAR_BASE_URL): RateLimitItemPerSecond(15, 1), ("client", MATCH_ALL): TOKEN_FALLBACK_RATE_LIMIT, # MATCH_MACHINE_ID is a placeholder for the machine_id passed in by the caller (f"get|{MATCH_MACHINE_ID}", MATCH_ALL): FALLBACK_RATE_LIMIT, @@ -51,6 +53,12 @@ class GlobalRateLimiter: + """Rate limiter for all requests within or between processes. + + Supports both Redis and in-memory storage. + 'Global' refers to being able to limit the rate + of requests across processes with Redis. + """ WAIT_INCREMENT: ClassVar[float] = 0.01 # seconds # list of public free outbount IP services @@ -68,7 +76,7 @@ class GlobalRateLimiter: def __init__( self, rate_config: ( - None | dict[tuple[str, str | MATCH_ALL_INPUTS], RateLimitItem] + None | dict[tuple[str, str | MatchAllInputs], RateLimitItem] ) = None, use_in_memory: bool = False, ): @@ -123,8 +131,8 @@ def rate_limiter(self) -> MovingWindowRateLimiter: return self._rate_limiter async def parse_namespace_and_primary_key( - self, namespace_and_key: tuple[str, str | MATCH_ALL_INPUTS], machine_id: int = 0 - ) -> tuple[str, str | MATCH_ALL_INPUTS]: + self, namespace_and_key: tuple[str, str | MatchAllInputs], machine_id: int = 0 + ) -> tuple[str, str | MatchAllInputs]: """Turn namespace_and_key tuple into a namespace and primary-key. If using a namespace starting with "get", then the primary key will be url parsed. @@ -151,7 +159,7 @@ async def parse_namespace_and_primary_key( def parse_rate_limits_and_namespace( self, namespace: str, - primary_key: str | MATCH_ALL_INPUTS, + primary_key: str | MatchAllInputs, ) -> tuple[RateLimitItem, str]: """Get rate limit and new namespace for a given namespace and primary_key. @@ -205,7 +213,7 @@ def parse_rate_limits_and_namespace( def parse_key( self, key: str - ) -> tuple[RateLimitItem, tuple[str, str | MATCH_ALL_INPUTS]]: + ) -> tuple[RateLimitItem, tuple[str, str | MatchAllInputs]]: """Parse the rate limit item from a redis/in-memory key. Note the key is created with RateLimitItem.key_for(*identifiers), @@ -222,8 +230,8 @@ def parse_key( ) async def get_rate_limit_keys( - self, - ) -> list[tuple[RateLimitItem, tuple[str, str | MATCH_ALL_INPUTS]]]: + self, cursor_scan_count: int = 100 + ) -> list[tuple[RateLimitItem, tuple[str, str | MatchAllInputs]]]: """Returns a list of current RateLimitItems with tuples of namespace and primary key.""" host, port = os.environ.get("REDIS_URL", ":").split(":", maxsplit=2) @@ -237,7 +245,7 @@ async def get_rate_limit_keys( while cursor: cursor, keys = await client.scan( - int(cursor), match=f"{self.storage.PREFIX}*", count=100 + int(cursor), match=f"{self.storage.PREFIX}*", count=cursor_scan_count ) matching_keys.extend(list(keys)) @@ -247,13 +255,13 @@ async def get_rate_limit_keys( def get_in_memory_limit_keys( self, - ) -> list[tuple[RateLimitItem, tuple[str, str | MATCH_ALL_INPUTS]]]: + ) -> list[tuple[RateLimitItem, tuple[str, str | MatchAllInputs]]]: """Returns a list of current RateLimitItems with tuples of namespace and primary key.""" return [self.parse_key(key) for key in self.storage.events] async def get_limit_keys( self, - ) -> list[tuple[RateLimitItem, tuple[str, str | MATCH_ALL_INPUTS]]]: + ) -> list[tuple[RateLimitItem, tuple[str, str | MatchAllInputs]]]: if os.environ.get("REDIS_URL") and not self.use_in_memory: return await self.get_rate_limit_keys() return self.get_in_memory_limit_keys() @@ -279,7 +287,7 @@ async def rate_limit_status(self): async def try_acquire( self, - namespace_and_key: tuple[str, str | MATCH_ALL_INPUTS], + namespace_and_key: tuple[str, str | MatchAllInputs], rate_limit: RateLimitItem | str | None = None, machine_id: int = 0, timeout: float = GLOBAL_RATE_LIMITER_TIMEOUT, # noqa: ASYNC109 @@ -289,27 +297,32 @@ async def try_acquire( """Returns when the limit is satisfied for the namespace_and_key. Args: - namespace_and_key: is composed of a tuple with namespace (e.g. "get") and - a primary-key (e.g. "arxiv.org"). namespaces can be nested with multiple '|', - primary-keys in the "get" namespace will be stripped to the domain. - - rate_limit: Optional RateLimitItem to be used for the namespace and primary-key. - If not provided, RATE_CONFIG will be used to find the rate limit. Can also - use a string of the form: - [count] [per|/] [n (optional)] [second|minute|hour|day|month|year] - - machine_id: will be used to modify the namespace of GET requests if - the primary key is not in the NO_MACHINE_ID_EXTENSIONS list. - In that case, the outbound IP will be used to modify the namespace. - - timeout: is the maximum time to wait for the rate limit to be satisfied. - - weight: is the cost of the request, default is 1. (could be tokens for example) - - raise_impossible_limits: flag will raise a ValueError for weights that exceed the rate. - - returns if the limit is satisfied or times out via a TimeoutError. - + namespace_and_key (:obj:`tuple[str, str | MatchAllInputs]`): is + composed of a tuple with namespace (e.g. "get") and a primary-key + (e.g. "arxiv.org"). namespaces can be nested with multiple '|', + primary-keys in the "get" namespace will be stripped to the domain. + rate_limit (:obj:`RateLimitItem | str | None`, optional): Optional + RateLimitItem to be used for the namespace and primary-key. + If not provided, RATE_CONFIG will be used to find the rate limit. + Can also use a string of the form: + [count] [per|/] [n (optional)] [second|minute|hour|day|month|year] + machine_id (:obj:`int`, optional): will be used to modify the namespace + of GET requests if the primary key is not in the + NO_MACHINE_ID_EXTENSIONS list. In that case, the outbound IP will be + used to modify the namespace. + timeout (:obj:`float`, optional): is the maximum time (in seconds) to + wait for the rate limit to be satisfied. + weight (:obj:`int`, optional): is the cost of the request, + default is 1. (could be tokens for example) + raise_impossible_limits (:obj:`bool`, optional): flag will raise a + ValueError for weights that exceed the rate. + + Returns: + None if the rate limit is satisfied. + + Raises: + TimeoutError: if the timeout is exceeded. + ValueError: if the weight exceeds the rate limit and raise_impossible_limits is True. """ namespace, primary_key = await self.parse_namespace_and_primary_key( namespace_and_key, machine_id=machine_id From ff1b7ea5896ae7b6d089918a488a72da08b09411 Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Thu, 3 Oct 2024 16:06:55 -0700 Subject: [PATCH 12/20] make imports reference the package --- paperqa/rate_limiter.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/paperqa/rate_limiter.py b/paperqa/rate_limiter.py index 0648ae5b..88d96999 100644 --- a/paperqa/rate_limiter.py +++ b/paperqa/rate_limiter.py @@ -6,8 +6,6 @@ from urllib.parse import urlparse import aiohttp -from clients.crossref import CROSSREF_BASE_URL -from clients.semantic_scholar import SEMANTIC_SCHOLAR_BASE_URL from coredis import Redis from limits import ( RateLimitItem, @@ -20,6 +18,9 @@ from limits.aio.storage import MemoryStorage, RedisStorage from limits.aio.strategies import MovingWindowRateLimiter +from .clients.crossref import CROSSREF_BASE_URL +from .clients.semantic_scholar import SEMANTIC_SCHOLAR_BASE_URL + logger = logging.getLogger(__name__) GLOBAL_RATE_LIMITER_TIMEOUT = float(os.environ.get("RATE_LIMITER_TIMOUT", "60")) From 1efd7aae3c925fffd63e6455150872f801657122 Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Thu, 3 Oct 2024 16:55:42 -0700 Subject: [PATCH 13/20] modify readme, rename timeout->acquire_timeout, remove defaults from rate_limit classes --- README.md | 2 +- paperqa/configs/tier2_limits.json | 3 --- paperqa/configs/tier3_limits.json | 3 --- paperqa/configs/tier4_limits.json | 3 --- paperqa/configs/tier5_limits.json | 3 --- paperqa/rate_limiter.py | 43 +++++++++++++++++-------------- 6 files changed, 24 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 19bccc92..b0e0002f 100644 --- a/README.md +++ b/README.md @@ -264,7 +264,7 @@ pqa --settings 'tier1_limits' ask 'Are there nm scale features in thermoelectric This will limit your system to use the tier1_limits, and slow down your queries to accommodate. -You can also specify them manually: +You can also specify them manually with any rate limit string that matches the specification in the [limits](https://limits.readthedocs.io/en/stable/quickstart.html#rate-limit-string-notation) module: ```bash pqa --summary_llm_config '{"rate_limit": {"gpt-4o-2024-08-06": "30000 per 1 minute"}}' ask 'Are there nm scale features in thermoelectric materials?' diff --git a/paperqa/configs/tier2_limits.json b/paperqa/configs/tier2_limits.json index fb1ad124..238974c9 100644 --- a/paperqa/configs/tier2_limits.json +++ b/paperqa/configs/tier2_limits.json @@ -12,9 +12,6 @@ "prompts": { "use_json": true }, - "agent": { - "agent_type": "ToolSelector" - }, "llm_config": { "rate_limit": { "gpt-4o": "450000 per 1 minute", diff --git a/paperqa/configs/tier3_limits.json b/paperqa/configs/tier3_limits.json index 7366e989..4c21bda9 100644 --- a/paperqa/configs/tier3_limits.json +++ b/paperqa/configs/tier3_limits.json @@ -12,9 +12,6 @@ "prompts": { "use_json": true }, - "agent": { - "agent_type": "ToolSelector" - }, "llm_config": { "rate_limit": { "gpt-4o": "800000 per 1 minute", diff --git a/paperqa/configs/tier4_limits.json b/paperqa/configs/tier4_limits.json index 07b2bb73..ddc6879d 100644 --- a/paperqa/configs/tier4_limits.json +++ b/paperqa/configs/tier4_limits.json @@ -12,9 +12,6 @@ "prompts": { "use_json": true }, - "agent": { - "agent_type": "ToolSelector" - }, "llm_config": { "rate_limit": { "gpt-4o": "2000000 per 1 minute", diff --git a/paperqa/configs/tier5_limits.json b/paperqa/configs/tier5_limits.json index 91d82383..2b15880f 100644 --- a/paperqa/configs/tier5_limits.json +++ b/paperqa/configs/tier5_limits.json @@ -12,9 +12,6 @@ "prompts": { "use_json": true }, - "agent": { - "agent_type": "ToolSelector" - }, "llm_config": { "rate_limit": { "gpt-4o": "30000000 per 1 minute", diff --git a/paperqa/rate_limiter.py b/paperqa/rate_limiter.py index 88d96999..a3c16971 100644 --- a/paperqa/rate_limiter.py +++ b/paperqa/rate_limiter.py @@ -46,7 +46,7 @@ ("get", CROSSREF_BASE_URL): RateLimitItemPerSecond(30, 1), ("get", SEMANTIC_SCHOLAR_BASE_URL): RateLimitItemPerSecond(15, 1), ("client", MATCH_ALL): TOKEN_FALLBACK_RATE_LIMIT, - # MATCH_MACHINE_ID is a placeholder for the machine_id passed in by the caller + # MATCH_MACHINE_ID is a sentinel for the machine_id passed in by the caller (f"get|{MATCH_MACHINE_ID}", MATCH_ALL): FALLBACK_RATE_LIMIT, } @@ -217,8 +217,9 @@ def parse_key( ) -> tuple[RateLimitItem, tuple[str, str | MatchAllInputs]]: """Parse the rate limit item from a redis/in-memory key. - Note the key is created with RateLimitItem.key_for(*identifiers), - the first key is the namespace, then the next two will be our identifiers. + Args: + key (str): is created with RateLimitItem.key_for(*identifiers), + the first key is the namespace, then the next two will be our identifiers. """ namespace, primary_key = key.split("/")[1:3] @@ -241,16 +242,18 @@ async def get_rate_limit_keys( client = Redis(host=host, port=int(port)) - cursor = b"0" - matching_keys: list[bytes] = [] - - while cursor: - cursor, keys = await client.scan( - int(cursor), match=f"{self.storage.PREFIX}*", count=cursor_scan_count - ) - matching_keys.extend(list(keys)) - - await client.quit() + try: + cursor = b"0" + matching_keys: list[bytes] = [] + while cursor: + cursor, keys = await client.scan( + int(cursor), + match=f"{self.storage.PREFIX}*", + count=cursor_scan_count, + ) + matching_keys.extend(list(keys)) + finally: + await client.quit() return [self.parse_key(key.decode()) for key in matching_keys] @@ -291,7 +294,7 @@ async def try_acquire( namespace_and_key: tuple[str, str | MatchAllInputs], rate_limit: RateLimitItem | str | None = None, machine_id: int = 0, - timeout: float = GLOBAL_RATE_LIMITER_TIMEOUT, # noqa: ASYNC109 + acquire_timeout: float = GLOBAL_RATE_LIMITER_TIMEOUT, weight: int = 1, raise_impossible_limits: bool = False, ) -> None: @@ -311,7 +314,7 @@ async def try_acquire( of GET requests if the primary key is not in the NO_MACHINE_ID_EXTENSIONS list. In that case, the outbound IP will be used to modify the namespace. - timeout (:obj:`float`, optional): is the maximum time (in seconds) to + acquire_timeout (:obj:`float`, optional): is the maximum time (in seconds) to wait for the rate limit to be satisfied. weight (:obj:`int`, optional): is the cost of the request, default is 1. (could be tokens for example) @@ -322,7 +325,7 @@ async def try_acquire( None if the rate limit is satisfied. Raises: - TimeoutError: if the timeout is exceeded. + TimeoutError: if the acquire_timeout is exceeded. ValueError: if the weight exceeds the rate limit and raise_impossible_limits is True. """ namespace, primary_key = await self.parse_namespace_and_primary_key( @@ -353,11 +356,11 @@ async def try_acquire( cost=min(weight, rate_limit.amount), ) ) - and elapsed < timeout + and elapsed < acquire_timeout ): await asyncio.sleep(self.WAIT_INCREMENT) elapsed += self.WAIT_INCREMENT - if elapsed >= timeout: + if elapsed >= acquire_timeout: raise TimeoutError( f"Timeout ({elapsed} secs): rate limit for key: {namespace_and_key}" ) @@ -373,10 +376,10 @@ async def try_acquire( # we need to keep trying when we have an "impossible" limit if rate_limit.amount < weight: weight -= rate_limit.amount - timeout = max(timeout - elapsed, 1.0) + acquire_timeout = max(acquire_timeout - elapsed, 1.0) continue break - timeout = max(timeout - elapsed, 1.0) + acquire_timeout = max(acquire_timeout - elapsed, 1.0) GLOBAL_LIMITER = GlobalRateLimiter() From d3785b45868b9fc462115b441bedb0d770e6fd8a Mon Sep 17 00:00:00 2001 From: mskarlin <12701035+mskarlin@users.noreply.github.com> Date: Thu, 3 Oct 2024 16:59:28 -0700 Subject: [PATCH 14/20] Update README.md Co-authored-by: James Braza --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b0e0002f..14f414d4 100644 --- a/README.md +++ b/README.md @@ -270,7 +270,7 @@ You can also specify them manually with any rate limit string that matches the s pqa --summary_llm_config '{"rate_limit": {"gpt-4o-2024-08-06": "30000 per 1 minute"}}' ask 'Are there nm scale features in thermoelectric materials?' ``` -Or by adding into a settings object, if calling imperatively: +Or by adding into a `Settings` object, if calling imperatively: ```python from paperqa import Settings, ask From 52303021213196885384202f6175f858a5fd228a Mon Sep 17 00:00:00 2001 From: mskarlin <12701035+mskarlin@users.noreply.github.com> Date: Thu, 3 Oct 2024 16:59:34 -0700 Subject: [PATCH 15/20] Update README.md Co-authored-by: James Braza --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 14f414d4..6aca484a 100644 --- a/README.md +++ b/README.md @@ -262,7 +262,8 @@ For each OpenAI tier, a pre-built setting exists to limit usage. pqa --settings 'tier1_limits' ask 'Are there nm scale features in thermoelectric materials?' ``` -This will limit your system to use the tier1_limits, and slow down your queries to accommodate. +This will limit your system to use the [tier1_limits](paperqa/config/tier1_limits.json), +and slow down your queries to accommodate. You can also specify them manually with any rate limit string that matches the specification in the [limits](https://limits.readthedocs.io/en/stable/quickstart.html#rate-limit-string-notation) module: From 033c033a164b6bf03b23e2ad607aa27d0bcf74ca Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Fri, 4 Oct 2024 08:43:14 -0700 Subject: [PATCH 16/20] update tests to support default use of json, change debug and fast mode to not use json, and add warning for users --- paperqa/configs/debug.json | 3 +++ paperqa/configs/fast.json | 3 +++ paperqa/core.py | 11 +++++++++-- tests/test_paperqa.py | 17 ++++++++++++----- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/paperqa/configs/debug.json b/paperqa/configs/debug.json index f560bb99..2021d46e 100644 --- a/paperqa/configs/debug.json +++ b/paperqa/configs/debug.json @@ -11,5 +11,8 @@ }, "parsing": { "use_doc_details": false + }, + "prompts": { + "use_json": false } } diff --git a/paperqa/configs/fast.json b/paperqa/configs/fast.json index 434a3e39..0921511a 100644 --- a/paperqa/configs/fast.json +++ b/paperqa/configs/fast.json @@ -10,6 +10,9 @@ "parsing": { "use_doc_details": false }, + "prompts": { + "use_json": false + }, "agent": { "agent_type": "fake" } diff --git a/paperqa/core.py b/paperqa/core.py index 231f92b2..baa55643 100644 --- a/paperqa/core.py +++ b/paperqa/core.py @@ -28,8 +28,15 @@ def replace_newlines(match: re.Match) -> str: # https://regex101.com/r/VFcDmB/1 pattern = r'"(?:[^"\\]|\\.)*"' text = re.sub(pattern, replace_newlines, text) - - return json.loads(text) + try: + return json.loads(text) + except json.JSONDecodeError as e: + raise ValueError( + "Failed to parse JSON. Your model may not " + "be capable of supporting JSON output. Try " + "a different model or with " + "`Settings(prompts={'use_json': False})`" + ) from e async def map_fxn_summary( diff --git a/tests/test_paperqa.py b/tests/test_paperqa.py index 0b59d107..106a583e 100644 --- a/tests/test_paperqa.py +++ b/tests/test_paperqa.py @@ -542,12 +542,12 @@ def test_make_docs(stub_data_dir: Path) -> None: def test_evidence(docs_fixture) -> None: - fast_settings = Settings.from_name("debug") + debug_settings = Settings.from_name("debug") evidence = docs_fixture.get_evidence( Answer(question="What does XAI stand for?"), - settings=fast_settings, + settings=debug_settings, ).contexts - assert len(evidence) >= fast_settings.answer.evidence_k + assert len(evidence) >= debug_settings.answer.evidence_k def test_json_evidence(docs_fixture) -> None: @@ -741,11 +741,18 @@ async def acomplete_iter( dockey="test", llm_model=MyLLM(), ) - evidence = docs.get_evidence("Echo", summary_llm_model=MyLLM()).contexts + # ensure JSON summaries are not used + no_json_settings = Settings(prompts={"use_json": False}) + evidence = docs.get_evidence( + "Echo", summary_llm_model=MyLLM(), settings=no_json_settings + ).contexts assert "Echo" in evidence[0].context evidence = docs.get_evidence( - "Echo", callbacks=[print_callback], summary_llm_model=MyLLM() + "Echo", + callbacks=[print_callback], + summary_llm_model=MyLLM(), + settings=no_json_settings, ).contexts assert "Echo" in evidence[0].context From 3452018f0326c8507e89c3ca07622c9d6b7b3f16 Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Fri, 4 Oct 2024 10:34:33 -0700 Subject: [PATCH 17/20] re-recorded vcr cassette with new settings + added docs for dockey non-determinism in crossref --- .../test_pdf_reader_match_doc_details.yaml | 7479 ++++++++--------- tests/test_paperqa.py | 9 +- 2 files changed, 3295 insertions(+), 4193 deletions(-) diff --git a/tests/cassettes/test_pdf_reader_match_doc_details.yaml b/tests/cassettes/test_pdf_reader_match_doc_details.yaml index 0d2bf73f..c9703748 100644 --- a/tests/cassettes/test_pdf_reader_match_doc_details.yaml +++ b/tests/cassettes/test_pdf_reader_match_doc_details.yaml @@ -37,25 +37,25 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: !!binary | - H4sIAAAAAAAAAwAAAP//dFHBbtpAEL3zFaM5Q2UMhIRbmkZtD1HTSlUOcYSX9WA2Xe9sd4dAi/j3 - aG0H0kMvc3hv3tN7M4cBAJoKF4B6o0Q33o6ub+bfvjzQTn2f3Gx2Uv/+8ffrx9tPq2r/+ecLDpOC - V8+k5U31QXPjLYlh19E6kBJKruN5Pp/OxvPsqiUarsgmWe1lNOVRnuXTUXY5yi564YaNpogLeBwA - ABzamSK6iva4gGz4hjQUo6oJF6clAAxsE4IqRhNFOcHhmdTshFybuizL58iucIfCARQoRiwVuIAC - r+GeQvSkxbwQsIPbvbfKqdQuAq/hji3prVUB7gNVRicC7lKxWOCw81Nb2XCIyfGxwAeyVu2UCAEJ - KFvgU79XsUk7bmtt4Y6FK8vyfeJA621Utt/o8ePpBJZrH3gVe/6Er40zcbMMpCK7VDcKe2zZ4wDg - qT319p/roQ/ceFkK/yKXDC8nnR2ef3smJ1c9KSzKnvFxnv9PtaxIlLHx3b+wC2hcfXbITinbmhj/ - RKFmuTaupuCD6d639stZNsvyyYVeVTg4Dl4BAAD//wMAjAmQ4scCAAA= + H4sIAAAAAAAAAwAAAP//bFFNb9swDL37VxA8x4PrBImTW4H1mKHrBgxbXcSqTDvqZEmQ6K1dkP8+ + KHbjFO1Fh/clPvKQAKCqcQMo94Jl53R6fdPeff7+ZVXk4uWn1IKbb9v1uu9+/bsLX3EWHfbxiSS/ + uj5J2zlNrKwZaOlJMMXUq1VeZMt5VqxORGdr0tHWOk4XNs2zfJFmRZotR+PeKkkBN3CfAAAcTm8c + 0dT0jBvIZq9IRyGIlnBzFgGgtzoiKEJQgYVhnE2ktIbJnKauquopWFOaQ2kASmTFmkrcQInXcEs+ + OJKs/hBYAzfPTgsjYrsAtoGt1SR7LTzceqqVjARsY7FQ4mzIEz3vrQ8x8b7EH6S1+CuYCYhB6BIf + Rl1tVdSYXuvSHEtTVdXlxJ6aPgg9Kkb8eF6Btq3z9jGM/BlvlFFhv/MkgjWxbmDr8MQeE4CH06r7 + N9tD523neMf2N5kYWMyHOJxuO5Hz9UiyZaEn/CrPZx/E7WpioXS4uBVKIfdUT9Ysuej2/tOPIoZ+ + yrTvUpIxCcNLYOp2jTIteefVcP3G7RYk5sv1alkITI7JfwAAAP//AwBgmKLEBgMAAA== headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c999d5d1867b2-SJC + - 8cd6e7daca292513-SJC Connection: - keep-alive Content-Encoding: @@ -63,14 +63,14 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:49 GMT + - Fri, 04 Oct 2024 17:31:28 GMT Server: - cloudflare Set-Cookie: - - __cf_bm=gK44ohFwDd5WKiBoRjoA0YGKDmimgFNiQ8ukJRMnG.A-1727451709-1.0.1.1-V.Zf3Hhy8YwzkEJok22089NmBFWmCEmiPmP.GiqkV157_lXG1woQd1UeERTqCaqseJgfOhGmnEFH1L3FUqTMNA; - path=/; expires=Fri, 27-Sep-24 16:11:49 GMT; domain=.api.openai.com; HttpOnly; + - __cf_bm=XQFBa4G1ogzFjs1dFWWM5RzPprmxv6SViF_5BY0JIRg-1728063088-1.0.1.1-4EueKaXWPbzCbAjHOAhUbV1QcdyIsXeEF_6uMGE8LaW_r5.qy_udqgA2Q5AVz9oLaeJNnQzu64vN4GSBoZ51_g; + path=/; expires=Fri, 04-Oct-24 18:01:28 GMT; domain=.api.openai.com; HttpOnly; Secure; SameSite=None - - _cfuvid=DoEGhZd5DcgECkMyAWnjKWwxp_c7OpMX6A9fxXzv9sM-1727451709777-0.0.1.1-604800000; + - _cfuvid=3jth.Yky6RI6Dq.vlHpkpCI.MWfoRyH2nDN_mvKIP3Q-1728063088686-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None Transfer-Encoding: - chunked @@ -83,7 +83,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "506" + - "686" openai-version: - "2020-10-01" strict-transport-security: @@ -95,13 +95,13 @@ interactions: x-ratelimit-remaining-requests: - "9999" x-ratelimit-remaining-tokens: - - "29999904" + - "29999650" x-ratelimit-reset-requests: - 6ms x-ratelimit-reset-tokens: - 0s x-request-id: - - req_74f9b5e3a661e39a92ed20c8b465b356 + - req_c546f4f1b235c33ededbfdabbeca022c status: code: 200 message: OK @@ -113,14 +113,18 @@ interactions: response: body: string: - '{"status":"ok","message-type":"work-list","message-version":"1.0.0","message":{"facets":{},"total-results":17288,"items":[{"DOI":"10.26434\/chemrxiv-2022-qfv02","author":[{"given":"Geemi - P.","family":"Wellawatte","sequence":"first","affiliation":[{"name":"University - of Rochester"}]},{"given":"Heta A.","family":"Gandhi","sequence":"additional","affiliation":[{"name":"University - of Rochester"}]},{"given":"Aditi","family":"Seshadri","sequence":"additional","affiliation":[{"name":"University - of Rochester"}]},{"ORCID":"http:\/\/orcid.org\/0000-0002-6647-3965","authenticated-orcid":false,"given":"Andrew - D.","family":"White","sequence":"additional","affiliation":[{"name":"University - of Rochester"}]}],"title":["A Perspective on Explanations of Molecular Prediction - Models"]}],"items-per-page":1,"query":{"start-index":0,"search-terms":null}}}' + '{"status":"ok","message-type":"work-list","message-version":"1.0.0","message":{"facets":{},"total-results":17354,"items":[{"DOI":"10.1021\/acs.jctc.2c01235","author":[{"ORCID":"http:\/\/orcid.org\/0000-0002-3772-6927","authenticated-orcid":true,"given":"Geemi + P.","family":"Wellawatte","sequence":"first","affiliation":[{"name":"Department + of Chemistry, University of Rochester, Rochester, New York 14627, United States"}]},{"ORCID":"http:\/\/orcid.org\/0000-0002-9465-3840","authenticated-orcid":true,"given":"Heta + A.","family":"Gandhi","sequence":"additional","affiliation":[{"name":"Department + of Chemical Engineering, University of Rochester, Rochester, New York 14627, + United States"}]},{"given":"Aditi","family":"Seshadri","sequence":"additional","affiliation":[{"name":"Department + of Chemical Engineering, University of Rochester, Rochester, New York 14627, + United States"}]},{"ORCID":"http:\/\/orcid.org\/0000-0002-6647-3965","authenticated-orcid":true,"given":"Andrew + D.","family":"White","sequence":"additional","affiliation":[{"name":"Department + of Chemical Engineering, University of Rochester, Rochester, New York 14627, + United States"}]}],"container-title":["Journal of Chemical Theory and Computation"],"title":["A + Perspective on Explanations of Molecular Prediction Models"]}],"items-per-page":1,"query":{"start-index":0,"search-terms":null}}}' headers: Access-Control-Allow-Headers: - X-Requested-With, Accept, Accept-Encoding, Accept-Charset, Accept-Language, @@ -131,14 +135,18 @@ interactions: - Link Connection: - close + Content-Encoding: + - gzip + Content-Length: + - "535" Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:51 GMT + - Fri, 04 Oct 2024 17:31:29 GMT Server: - Jetty(9.4.40.v20210413) - Transfer-Encoding: - - chunked + Vary: + - Accept-Encoding permissions-policy: - interest-cohort=() x-api-pool: @@ -195,46 +203,46 @@ interactions: why\nthe prediction was made.17 Explaining predictions can help developers of DL models ensure\nthe model is not learning spurious correlations.18,19 Two infamous examples are, 1)neural\nnetworks that learned to recognize horses by - looking for a photogr", "o infamous examples are, 1)neural\nnetworks that learned - to recognize horses by looking for a photographer\u2019s watermark20 and,\n2) - neural networks that predicted a COVID-19 diagnoses by looking at the font choice\non - medical images.21 As a result, there is an emerging regulatory framework for - when any\ncomputer algorithms impact humans.22\u201324 Although we know of no - examples yet in chemistry,\none can assume the use of AI in predicting toxicity, - carcinogenicity, and environmental\npersistence will require rationale for the - predictions due to regulatory consequences.\n1there does happen to be one human - solubility savant, participant 11, who matched machine performance\n2\nEXplainable - Artificial Intelligence (XAI) is a field of growing importance that aims to\nprovide - model interpretations of DL predictions Three terms highly associated with XAI - are,\ninterpretability, justifications and explainability. Miller 25 defines - that interpretability of a\nmodel refers to the degree of human understandability - intrinsic within the model. Murdoch\net al. 26 clarify that interpretability - can be perceived as \u201cknowledge\u201d which provide insight\nto a particular - problem.\nJustifications are quantitative metrics tell the users \u201cwhy the\nmodel - should be trusted,\u201d like test error.27 Justifications are evidence which - defend why a\nprediction is trustworthy.25 An \u201cexplanation\u201d is a description - on why a certain prediction was\nmade.9,28 Interpretability and explanation - are often used interchangeably. Arrieta et al. 14\ndistinguish that interpretability - is a passive characteristic of a model, whereas explainability\nis an active - characteristic which is used to clarify the internal decision-making process.\nNamely, - an explanation is extra information that gives the context and a cause for one - or\nmore predictions.29 We adopt the same nomenclature in this perspective.\nAccuracy - and interpretability are two attractive characteristics of DL models. However,\nDL - models are often highly accurate and less interpretable.28,30 XAI provides a - way to avoid\nthat trade-off in chemical property prediction. XAI can be viewed - as a two-step process.\nFirst, we develop an accurate but uninterpretable DL - model. Next, we add explanations to\npredictions. Ideally, if the DL model has - correctly learned the input-output relations, then\nthe explanations should - give insight into the underlying mechanism.\nIn the remainder of this article, - we review recent approaches for XAI of chemical property\nprediction while drawing - specific examples from our recent XAI work.9,10,31 We show how\nin various systems - these methods yield explanations that are consistent with known and\nmechanisms - in structure-property relationships.\n3\nTheory\nIn this work, we aim to assemble - a common taxonomy for the landscape of XAI while\nproviding our perspectives. - We utilized the vocabulary proposed by Das and Rad 32 to classify\nXAI. According - to their classification, interpretations can be categorized as global or local\ninterpretations - on the basis of \u201cwhat ", "cation, interpretations can be categorized as - global or local\ninterpretations on the basis of \u201cwhat is being explained?\u201d. + looking for a photographer\u2019s watermark20 and,\n2) neural networks that + predicted a COVID-19 diagnoses by looking at the font choice\non medical images.21 + As a result, there is an emerging regulatory framework for when any\ncomputer + algorithms impact humans.22\u201324 Although we know of no examples yet in chemistry,\none + can assume the use of AI in predicting toxicity, carcinogenicity, and environmental\npersistence + will require rationale for the predictions due to regulatory consequences.\n1there + does happen to be one human solubility savant, participant 11, who matched machine + performance\n2\nEXplainable Artificial Intelligence (XAI) is a field of growing + importance that aims to\nprovide model interpretations of DL predictions Three + terms highly associated with XAI are,\ninterpretability, justifications and + explainability. Miller 25 defines that interpretability of a\nmodel refers to + the degree of human understandability intrinsic within the model. Murdoch\net + al. 26 clarify that interpretability can be perceived as \u201cknowledge\u201d + which provide insight\nto a particular problem.\nJustifications are quantitative + metrics tell the users \u201cwhy the\nmodel should be trusted,\u201d like test + error.27 Justifications are evidence which defend why a\nprediction is trustworthy.25 + An \u201cexplanation\u201d is a description on why a certain prediction was\nmade.9,28 + Interpretability and explanation are often used interchangeably. Arrieta et + al. 14\ndistinguish that interpretability is a passive characteristic of a model, + whereas explainability\nis an active characteristic which is used to clarify + the internal decision-making process.\nNamely, an explanation is extra information + that gives the context and a cause for one or\nmore predictions.29 We adopt + the same nomenclature in this perspective.\nAccuracy and interpretability are + two attractive characteristics of DL models. However,\nDL models are often highly + accurate and less interpretable.28,30 XAI provides a way to avoid\nthat trade-off + in chemical property prediction. XAI can be viewed as a", "ccuracy and interpretability + are two attractive characteristics of DL models. However,\nDL models are often + highly accurate and less interpretable.28,30 XAI provides a way to avoid\nthat + trade-off in chemical property prediction. XAI can be viewed as a two-step process.\nFirst, + we develop an accurate but uninterpretable DL model. Next, we add explanations + to\npredictions. Ideally, if the DL model has correctly learned the input-output + relations, then\nthe explanations should give insight into the underlying mechanism.\nIn + the remainder of this article, we review recent approaches for XAI of chemical + property\nprediction while drawing specific examples from our recent XAI work.9,10,31 + We show how\nin various systems these methods yield explanations that are consistent + with known and\nmechanisms in structure-property relationships.\n3\nTheory\nIn + this work, we aim to assemble a common taxonomy for the landscape of XAI while\nproviding + our perspectives. We utilized the vocabulary proposed by Das and Rad 32 to classify\nXAI. + According to their classification, interpretations can be categorized as global + or local\ninterpretations on the basis of \u201cwhat is being explained?\u201d. For example, counterfactuals are\nlocal interpretations, as these can explain only a given instance. The second classification is\nbased on the relation between the model and the interpretation \u2013 is interpretability post-hoc\n(extrinsic) @@ -272,58 +280,58 @@ interactions: to the prediction?44\n\u2022 Correct. Does the explanation agree with hypothesized or known underlying physical\nmechanism?39\n\u2022 Domain Applicable. Does the explanation use language and concepts of domain ex-\nperts?\n\u2022 Fidelity/Faithful. - Does the explanation ag", "lanation use language and concepts of domain ex-\nperts?\n\u2022 - Fidelity/Faithful. Does the explanation agree with the black box model?\n\u2022 - Robust. Does the explanation change significantly with small changes to the - model or\ninstance being explained?\n\u2022 Sparse/Succinct. Is the explanation - succinct?\nWe present an example evaluation of the SHAP explanation method based - on the above\nattributes.44 Shapley values were proposed as a local explanation - method based on feature\nattribution, as they offer a complete explanation - - each feature is assigned a fraction of\nthe prediction value.44,45 Completeness - is a clearly measurable and well-defined metric, but\nyields explanations with - many components. Yet Shapley values are not actionable nor sparse.\nThey are - non-sparse as every feature has a non-zero attribution and not-actionable because\nthey - do not provide a set of features which changes the outcome.46 Ribeiro et al. - 35 proposed\na surrogate model method that aims to provide sparse/succinct explanations - that have high\n5\nfidelity to the original model. In Wellawatte et al. 9 we - argue that counterfactuals are \u201cbet-\nter\u201d explanations because they - are actionable and sparse. We highlight that, evaluation of\nexplanations is - a difficult task because explanations are fundamentally for and by humans.\nTherefore, - these evaluations are subjective, as they depend on \u201ccomplex human factors - and\napplication scenarios.\u201d37\nSelf-explaining models\nA self-explanatory - model is one that is intrinsically interpretable to an expert.47 Two com-\nmon - examples found in the literature are linear regression models and decision trees - (DT).\nIntrinsic models can be found in other XAI applications acting as surrogate - models (proxy\nmodels) due to their transparent nature.48,49 A linear model - is described by the equation\n1 where, W\u2019s are the weight parameters and - x\u2019s are the input features associated with the\nprediction \u02c6y. Therefore, - we observe that the weights can be used to derive a complete expla-\nnation - of the model - trained weights quantify the importance of each feature.47 DT - models\nare another type of self-explaining models which have been used in classification - and high-\nthroughput screening tasks. Gajewicz et al. 50 used DT models to - classify nanomaterials\nthat identify structural features responsible for surface - activity. In another study by Han\net al. 51, a DT model was developed to filter - compounds by their bioactivity based on the\nchemical fingerprints.\n\u02c6y - = \u03a3iWixi\n(1)\nRegularization techniques such as EXPO52 and RRR53 are designed - to enhance the black-\nbox model interpretability.54 Although one can argue - that \u201csimplicity\u201d of models are posi-\ntively correlated with interpretability, - this is based on how the interpretability is evaluated.\nFor example, Lipton - 55 argue that, from the notion of \u201csimulatability\u201d (the degree to - which a\nhuman can predict the outcome based on inputs), self-explanatory linear - models, rule-based\n6\nsystems, and DT\u2019s can be claimed uninterpretable. - A human can pred", "atory linear models, rule-based\n6\nsystems, and DT\u2019s - can be claimed uninterpretable. A human can predict the outcome given\nthe inputs - only if the input features are interpretable. Therefore, a linear model which - takes\nin non-descriptive inputs may not be as transparent. On the other hand, - a linear model\nis not innately accurate as they fail to capture non-linear - relationships in data, limiting is\napplicability. Similarly, a DT is a rule-based - model and lacks physics informed knowledge.\nTherefore, an existing drawback - is the trade-off between the degree of understandability and\nthe accuracy of - a model. For example, an intrinsic model (linear regression or decision trees)\ncan - be described through the trainable parameters, but it may fail to \u201ccorrectly\u201d - capture\nnon-linear relations in the data.\nAttribution methods\nFeature attribution - methods explain black box predictions by assigning each input feature\na numerical - value, which indicates its importance or contribution to the prediction. Feature\nattributions + Does the explanation agree with the black box model?\n\u2022 Robust. Does the + explanation change significantly with small changes to the model or\ninstance + being explained?\n\u2022 Sparse/Succinct. Is the explanation succinct?\nWe present + an example evaluation of the SHAP explanation method based on the above\nattributes.44 + Shapley values were proposed as a local explanation method based on feature\nattribution, + as they offer a complete explanation - each feature is assigned a fraction of\nthe + prediction value.44,45 Completeness is a clearly measurable and well-defined + metric, but\nyields explanations with many components. Yet Shapley values are + not actionable nor sparse.\nThey are non-sparse as every feature has a non-zero + attribution and not-actionable because\nthey do not provide a set of features + which changes the outcome.46 Ribeiro et al. 35 proposed\na surrogate model method + that aims to provide sparse/succinct explanations that have high\n5\nfidelity + to the original model. I", "ion and not-actionable because\nthey do not provide + a set of features which changes the outcome.46 Ribeiro et al. 35 proposed\na + surrogate model method that aims to provide sparse/succinct explanations that + have high\n5\nfidelity to the original model. In Wellawatte et al. 9 we argue + that counterfactuals are \u201cbet-\nter\u201d explanations because they are + actionable and sparse. We highlight that, evaluation of\nexplanations is a difficult + task because explanations are fundamentally for and by humans.\nTherefore, these + evaluations are subjective, as they depend on \u201ccomplex human factors and\napplication + scenarios.\u201d37\nSelf-explaining models\nA self-explanatory model is one + that is intrinsically interpretable to an expert.47 Two com-\nmon examples found + in the literature are linear regression models and decision trees (DT).\nIntrinsic + models can be found in other XAI applications acting as surrogate models (proxy\nmodels) + due to their transparent nature.48,49 A linear model is described by the equation\n1 + where, W\u2019s are the weight parameters and x\u2019s are the input features + associated with the\nprediction \u02c6y. Therefore, we observe that the weights + can be used to derive a complete expla-\nnation of the model - trained weights + quantify the importance of each feature.47 DT models\nare another type of self-explaining + models which have been used in classification and high-\nthroughput screening + tasks. Gajewicz et al. 50 used DT models to classify nanomaterials\nthat identify + structural features responsible for surface activity. In another study by Han\net + al. 51, a DT model was developed to filter compounds by their bioactivity based + on the\nchemical fingerprints.\n\u02c6y = \u03a3iWixi\n(1)\nRegularization techniques + such as EXPO52 and RRR53 are designed to enhance the black-\nbox model interpretability.54 + Although one can argue that \u201csimplicity\u201d of models are posi-\ntively + correlated with interpretability, this is based on how the interpretability + is evaluated.\nFor example, Lipton 55 argue that, from the notion of \u201csimulatability\u201d + (the degree to which a\nhuman can predict the outcome based on inputs), self-explanatory + linear models, rule-based\n6\nsystems, and DT\u2019s can be claimed uninterpretable. + A human can predict the outcome given\nthe inputs only if the input features + are interpretable. Therefore, a linear model which takes\nin non-descriptive + inputs may not be as transparent. On the other hand, a linear model\nis not + innately accurate as they fail to capture non-linear relationships in data, + limiting is\napplicability. Similarly, a DT is a rule-based model and lacks + physics informed knowledge.\nTherefore, an existing drawback is the trade-off + between the degree of understandability and\nthe accuracy of a model. For example, + an intrinsic model (linear regression or decision trees)\ncan be described through + the trainable parameters, but it may fail to \u201ccorrectly\u201d capture\nnon-linear + relations in the data.\nAttribution methods\nFeature attribution methods explain + black box predictions by assigning each input feature\na numerical value, which + indicates its importance or contribution to the prediction. Feature\nattributions provide local explanations, but can be averaged or combined to explain multi-\nple instances. Atom-based numerical assignments are commonly referred to as heatmaps.56\nSheridan 57 describes an atom-wise attribution method for interpreting QSAR models. Re-\ncently, @@ -347,87 +355,89 @@ interactions: et al. 60 used graph convolutional networks (GCNs) to predict protein-ligand\nbinding and explained the binding logic for these predictions using integrated gradients.\nPope et al. 66 and Jim\u00b4enez-Luna et al. 67 show application of gradCAM and integrated + gradi-\nents to explain molecular prope", "ks (GCNs) to predict protein-ligand\nbinding + and explained the binding logic for these predictions using integrated gradients.\nPope + et al. 66 and Jim\u00b4enez-Luna et al. 67 show application of gradCAM and integrated gradi-\nents to explain molecular property predictions from trained graph neural - networks (GNNs).\nSanchez-Lengeling et al. 68 present compr", "rty predictions - from trained graph neural networks (GNNs).\nSanchez-Lengeling et al. 68 present - comprehensive, open-source XAI benchmarks to explain\nGNNs and other graph based - models. They compare the performance of class activation\nmaps (CAM),63 gradCAM,64 - smoothGrad,,65 integrated gradients62 and attention mecha-\nnisms for explaining - outcomes of classification as well as regression tasks. They concluded\nthat - CAM and integrated gradients perform well for graph based models. Another attempt\nat - creating XAI benchmarks for graph models was made by Rao et al. 70. They compared\nthese - gradient based methods to find subgraph importance when predicting activity - cliffs\nand concluded that gradCAM and integrated gradients provided the most - interpretability\nfor GNNs.\nThe GNNExplainer69 is an approach for generating - explanations (local and\nglobal) for graph based models. This method focuses - on identifying which sub-graphs con-\ntribute most to the prediction by maximizing - mutual information between the prediction\nand distribution of all possible - sub-graphs. Ying et al. 69 show that GNNExplainer can be\nused to obtain model-agnostic - explanations. SubgraphX is a similar method that explains\nGNN predictions by - identifying important subgraphs.71\nAnother set of approaches like DeepLIFT72 - and Layerwise Relevance backPropagation73\n8\n(LRP) are based on backpropagation - of the prediction scores through each layer of the neu-\nral network. The specific - backpropagation logic across various activation functions differs\nin these - approaches, which means each layer must have its own implementation. Baldas-\nsarre - and Azizpour 74 showed application of LRP to explain aqueous solubility prediction - for\nmolecules.\nSHAP is a model-agnostic feature attribution method that is - inspired from the game\ntheory concept of Shapley values.44,46 SHAP has been - popularly used in explaining molecular\nprediction models.75\u201378 It\u2019s - an additive feature contribution approach, which assumes that\nan explanation - model is a linear combination of binary variables z. If the Shapley value\ni - \u03d5i(\u20d7x)zi(\u20d7x). Shapley values for\nfeatures are computed using - Equation 3.79,80\nfor the ith feature is \u03d5i, then the explanation is \u02c6f(\u20d7x) - = P\n\u03d5i(\u20d7x) = 1\nM\nM\nX \u02c6f (\u20d7z+i) \u2212\u02c6f (\u20d7z\u2212i)\n(3)\nHere - \u20d7z is a fabricated example created from the original \u20d7x and a random - perturbation \u20d7x\u2032.\n\u20d7z+i has the feature i from \u20d7x and \u20d7z\u2212i - has the ith feature from \u20d7x\u2032. Some care should be taken\nin constructing - \u20d7z when working with molecular descriptors to ensure that an impossible - \u20d7z is\nnot sampled (e.g., high count of acid groups but no hydrogen bond - donors). M is the sample\nsize of perturbations around \u20d7x. Shapley value - computation is expensive, hence M is chosen\naccordingly. Equation 3 is an approximation - and gives contributions with an expectation\ni=1 \u03d5i(\u20d7x) = \u02c6f(\u20d7x).\nVisualization + networks (GNNs).\nSanchez-Lengeling et al. 68 present comprehensive, open-source + XAI benchmarks to explain\nGNNs and other graph based models. They compare the + performance of class activation\nmaps (CAM),63 gradCAM,64 smoothGrad,,65 integrated + gradients62 and attention mecha-\nnisms for explaining outcomes of classification + as well as regression tasks. They concluded\nthat CAM and integrated gradients + perform well for graph based models. Another attempt\nat creating XAI benchmarks + for graph models was made by Rao et al. 70. They compared\nthese gradient based + methods to find subgraph importance when predicting activity cliffs\nand concluded + that gradCAM and integrated gradients provided the most interpretability\nfor + GNNs.\nThe GNNExplainer69 is an approach for generating explanations (local + and\nglobal) for graph based models. This method focuses on identifying which + sub-graphs con-\ntribute most to the prediction by maximizing mutual information + between the prediction\nand distribution of all possible sub-graphs. Ying et + al. 69 show that GNNExplainer can be\nused to obtain model-agnostic explanations. + SubgraphX is a similar method that explains\nGNN predictions by identifying + important subgraphs.71\nAnother set of approaches like DeepLIFT72 and Layerwise + Relevance backPropagation73\n8\n(LRP) are based on backpropagation of the prediction + scores through each layer of the neu-\nral network. The specific backpropagation + logic across various activation functions differs\nin these approaches, which + means each layer must have its own implementation. Baldas-\nsarre and Azizpour + 74 showed application of LRP to explain aqueous solubility prediction for\nmolecules.\nSHAP + is a model-agnostic feature attribution method that is inspired from the game\ntheory + concept of Shapley values.44,46 SHAP has been popularly used in explaining molecular\nprediction + models.75\u201378 It\u2019s an additive feature contribution approach, which + assumes that\nan explanation model is a linear combination of binary variables + z. If the Shapley value\ni \u03d5i(\u20d7x)zi(\u20d7x). Shapley values for\nfeatures + are computed using Equation 3.79,80\nfor the ith feature is \u03d5i, then the + explanation is \u02c6f(\u20d7x) = P\n\u03d5i(\u20d7x) = 1\nM\nM\nX \u02c6f (\u20d7z+i) + \u2212\u02c6f (\u20d7z\u2212i)\n(3)\nHere \u20d7z is a fabricated example created + from the original \u20d7x and a random perturbation \u20d7x\u2032.\n\u20d7z+i + has the feature i from \u20d7x and \u20d7z\u2212i has the ith feature from \u20d7x\u2032. + Some care should be taken\nin constructing \u20d7z when working with molecular + descriptors to ensure that an impossible \u20d7z is\nnot sampled (e.g., high + count of acid groups but no hydrogen bond donors). M is the sample\nsize of + perturbations around \u20d7x. Shapley value computation is expensive, hence + M is chosen\naccordingly. Equation 3 is an approximation and gives contributions + with an expectation\ni=1 \u03d5i(\u20d7x) = \u02c6f(\u20d7x).\nVisualization based feature attribution has also been used for molecular data. In com-\nterm as \u03d50 + P\nputer science, saliency maps are a way to measure spatial feature - contribution.8", "com-\nterm as \u03d50 + P\nputer science, saliency maps are - a way to measure spatial feature contribution.81 Simply put,\nsaliency maps - draw a connection between the model\u2019s neural fingerprint components (trained\nweights) - and input features. Weber et al. 82 used saliency maps to build an explainable - GCN\narchitecture that gives subgraph importance for small molecule activity - prediction. On the\nother hand, similarity maps compare model predictions for - two or more molecules based on\ntheir chemical fingerprints.83 Similarity maps - provide atomic weights or predicted probabil-\n9\nity difference between the - molecules by removing one atom at a time. These weights can\nthen be used to - color the molecular graph and give a visual presentation. ChemInformatics\nModel - Explorer (CIME) is an interactive web based toolkit which allows visualization - and\ncomparison of different explanation methods for molecular property prediction - models.84\nSurrogate models\nOne approach to explain black box predictions is - to fit a self-explaining or interpretable\nmodel to the black box model, in - the vicinity of one or a few specific examples. These are\nknown as surrogate - models. Generally, one model per explanation is trained. However, if we\ncould - find one surrogate model that explained the whole DL model, then we would simply\nhave - a globally accurate interpretable model. This means that the black-box model - is no\nlonger needed.79 In the work by White 79, a weighted least squares linear - model is used as\nthe surrogate model. This model provides natural language - based descriptor explanations by\nreplacing input features with chemically interpretable - descriptors. This approach is similar\nto the concept-based explanations approach - used by McGrath et al. 85, where human under-\nstandable concepts were used - in place of input features in acquisition of chess knowledge in\nAlphaZero. - Any of the self-explaining models detailed in the Self-explaining models section\ncan - be used as a surrogate model.\nThe most commonly used surrogate model based - method is Locally Interpretable Model\nExplanations (LIME).35 LIME creates perturbations - around the example of interest and fits\nan interpretable model to these local - perturbations. Ribeiro et al. 35 mathematically define\nan explanation \u03be - for an example \u20d7x using Equation 4.\n\u03be(\u20d7x) = arg min\ng\u2208G - L(f, g, \u03c0x) + \u2126(g)\n(4)\nHere f is the black box model and g \u2208G - is the interpretable explanation model. G is\na class of potential interpretable - models (e.g.: linear models). \u03c0x is a similarity measure\n10\nbetween original - input \u20d7x and it\u2019s perturbed input \u20d7x\u2032. In context of molecular - data, this can\nbe a chemical similarity metric like Tanimoto86 similarity between - fingerprints. The goal for\nLIME is to minimize the loss, L, such that f is - closely approximated by g. \u2126is a parameter\nthat controls the complexity - (sparsity) of g. Ribeiro et al. 35 termed the agreement (how low\nthe loss is) - between f and g as the \u201cfidelity\u201d.\nGraphLIME87 and LIMEtree88 are - modifications to LIME as applica", ") between f and g as the \u201cfidelity\u201d.\nGraphLIME87 + contribution.81 Simply put,\nsaliency maps draw a connection between the model\u2019s + neural fingerprint components (trained\nweights) and input features. Weber et + al. 82 used saliency maps to build an explainable GCN\narchitecture that gives + subgraph importance for small molecule activity prediction. On the\nother hand, + similarity maps compare model predictions for two or more molecules based on\ntheir + chemical fingerprints.83 Similarity maps provide atomic weights or predicted + probabil-\n9\nity difference between the molecules by removing one atom at a + time. These weights can\nthen be used to color the molecular graph and give + a visual presentation. ChemInformatics\nModel Explorer (CIME) is an interactive + web based toolkit which allows visualization and\ncomparison of different explanation + methods for molecular property prediction models.84\nSurrogate models\nOne approach + to explain black box predictions is to fit a self-explaining or interpretable\nmodel + to the black box model, in the vicinity of one or a few specific examples. These + are\nknown as surrogate models. Generally, one model per explanation is trained. + However, if we\ncould find one surrogate model that explained the whole DL model, + then we would simply\nhave a globally accurate interpretable model. This means + that the black-box model is no\nlonger needed.79 In the work by White 79, a + weighted least squares linear model is used as\nthe surrogate model. This model + provides natural language based descriptor explanations by\nreplacing input + features with chemically interpretable descriptors. This approach is similar\nto + the concept-based explanations approach used by McGrath et al. 85, where human + under-\nstandable concepts were used in place of input features in acquisition + of chess knowledge in\nAl", "th chemically interpretable descriptors. This approach + is similar\nto the concept-based explanations approach used by McGrath et al. + 85, where human under-\nstandable concepts were used in place of input features + in acquisition of chess knowledge in\nAlphaZero. Any of the self-explaining + models detailed in the Self-explaining models section\ncan be used as a surrogate + model.\nThe most commonly used surrogate model based method is Locally Interpretable + Model\nExplanations (LIME).35 LIME creates perturbations around the example + of interest and fits\nan interpretable model to these local perturbations. Ribeiro + et al. 35 mathematically define\nan explanation \u03be for an example \u20d7x + using Equation 4.\n\u03be(\u20d7x) = arg min\ng\u2208G L(f, g, \u03c0x) + \u2126(g)\n(4)\nHere + f is the black box model and g \u2208G is the interpretable explanation model. + G is\na class of potential interpretable models (e.g.: linear models). \u03c0x + is a similarity measure\n10\nbetween original input \u20d7x and it\u2019s perturbed + input \u20d7x\u2032. In context of molecular data, this can\nbe a chemical similarity + metric like Tanimoto86 similarity between fingerprints. The goal for\nLIME is + to minimize the loss, L, such that f is closely approximated by g. \u2126is + a parameter\nthat controls the complexity (sparsity) of g. Ribeiro et al. 35 + termed the agreement (how low\nthe loss is) between f and g as the \u201cfidelity\u201d.\nGraphLIME87 and LIMEtree88 are modifications to LIME as applicable to graph neural\nnetworks and regression trees, respectively. LIME has been used in chemistry previously,\nsuch as Whitmore et al. 89 who used LIME to explain octane number predictions of @@ -466,51 +476,51 @@ interactions: become a useful tool for XAI in chemistry, as they\nsuch that\n\f\f\f \u02c6f(x) \u2212\u02c6f(x\u2032)\n\f\f\f \u2265\u2206\n(6)\nprovide intuitive understanding of predictions and are able to uncover spurious relationships\nin training data.101 - Counterfactuals create local (instance-level), actionable explan", " relationships\nin - training data.101 Counterfactuals create local (instance-level), actionable - explanations.\nActionability of an explanation suggest which features can be - altered to change the outcome.\nFor example, changing a hydrophobic functional - group in a molecule to a hydrophilic group\nto increase solubility.\nCounterfactual - generation is a demanding task as it requires gradient optimization over\ndiscrete - features that represents a molecule. Recent work by Fu et al. 102 and Shen et - al. 103\npresent two techniques which allow continuous gradient-based optimization. - Although, these\nmethodologies are shown to circumvent the issue of discrete - molecular optimization, counter-\nfactual explanation based model interpretation - still remains unexplored compared to other\n12\npost-hoc methods.\nCF-GNNExplainer104 - is a counterfactual explanation generating method based on GN-\nNExplainer69 - for graph data. This method generate counterfactuals by perturbing the input\ndata - (removing edges in the graph), and keeping account of perturbations which lead - to\nchanges in the output.\nHowever, this method is only applicable to graph-based - models\nand can generate infeasible molecular structures. Another related work - by Numeroso and\nBacciu 105 focus on generating counterfactual explanations - for deep graph networks. Their\nmethod MEG (Molecular counterfactual Explanation - Generator) uses a reinforcement learn-\ning based generator to create molecular - counterfactuals (molecular graphs).\nWhile this\nmethod is able to generate - counterfactuals through a multi-objective reinforcement learner,\nthis is not - a universal approach and requires training the generator for each task.\nWork - by Wellawatte et al. 9 present a model agnostic counterfactual generator MMACE\n(Molecular - Model Agnostic Counterfactual Explanations) which does not require training\nor - computing gradients. This method firstly populates a local chemical space through - ran-\ndom string mutations of SELFIES106 molecular representations using the - STONED algo-\nrithm.107 Next, the labels (predictions) of the molecules in the - local space are generated\nusing the model that needs to be explained. Finally, - the counterfactuals are identified and\nsorted by their similarities \u2013 - Tanimoto distance96 between ECFP4 fingerprints.97 Unlike the\nCF-GNNExplainer104 - and MEG105 methods, the MMACE algorithm ensures that generated\nmolecules are - valid, owing to the surjective property of SELFIES. Additionally, the MMACE\nmethod - can be applied to both regression and classification models. However, like most - XAI\nmethods for molecular prediction, MMACE does not account for the chemical - stability of\npredicted counterfactuals.\nTo circumvent this drawback, Wellawatte - et al. 9 propose an-\nother approach, which identift counterfactuals through - a similarity search on the PubChem\ndatabase.108\n13\nSimilarity to adjacent - fields\nTangential examples to counterfactual explanations are adversarial training - and matched\nmolecular pairs. Adversarial perturbations are used d", "lanations - are adversarial training and matched\nmolecular pairs. Adversarial perturbations - are used during training to deceive the model\nto expose the vulnerabilities - of a model109,110 whereas counterfactuals are applied post-hoc.\nTherefore, - the main difference between adversarial and counterfactual examples are in the\napplication, - although both are derived from the same optimization problem.100 Grabocka\net - al. 111 have developed a method named Adversarial Training on EXplanations (ATEX)\nwhich + Counterfactuals create local (instance-level), actionable explanations.\nActionability + of an explanation suggest which features can be altered to change the outcome.\nFor + example, changing a hydrophobic functional group in a molecule to a hydrophilic + group\nto increase solubility.\nCounterfactual generation is a demanding task + as it requires gradient optimization over\ndiscrete features that represents + a molecule. Recent work by Fu et al. 102 and Shen et al. 103\npresent two techniques + which allow continuous gradient-based optimization. Although, these\nmethodologies + are shown to circumvent the issue of discrete molecular optimization, counter-\nfactual + explanation based model interpretation still remains unexplored compared to + other\n12\npost-hoc methods.\nCF-GNNE", "nt-based optimization. Although, these\nmethodologies + are shown to circumvent the issue of discrete molecular optimization, counter-\nfactual + explanation based model interpretation still remains unexplored compared to + other\n12\npost-hoc methods.\nCF-GNNExplainer104 is a counterfactual explanation + generating method based on GN-\nNExplainer69 for graph data. This method generate + counterfactuals by perturbing the input\ndata (removing edges in the graph), + and keeping account of perturbations which lead to\nchanges in the output.\nHowever, + this method is only applicable to graph-based models\nand can generate infeasible + molecular structures. Another related work by Numeroso and\nBacciu 105 focus + on generating counterfactual explanations for deep graph networks. Their\nmethod + MEG (Molecular counterfactual Explanation Generator) uses a reinforcement learn-\ning + based generator to create molecular counterfactuals (molecular graphs).\nWhile + this\nmethod is able to generate counterfactuals through a multi-objective reinforcement + learner,\nthis is not a universal approach and requires training the generator + for each task.\nWork by Wellawatte et al. 9 present a model agnostic counterfactual + generator MMACE\n(Molecular Model Agnostic Counterfactual Explanations) which + does not require training\nor computing gradients. This method firstly populates + a local chemical space through ran-\ndom string mutations of SELFIES106 molecular + representations using the STONED algo-\nrithm.107 Next, the labels (predictions) + of the molecules in the local space are generated\nusing the model that needs + to be explained. Finally, the counterfactuals are identified and\nsorted by + their similarities \u2013 Tanimoto distance96 between ECFP4 fingerprints.97 + Unlike the\nCF-GNNExplainer104 and MEG105 methods, the MMACE algorithm ensures + that generated\nmolecules are valid, owing to the surjective property of SELFIES. + Additionally, the MMACE\nmethod can be applied to both regression and classification + models. However, like most XAI\nmethods for molecular prediction, MMACE does + not account for the chemical stability of\npredicted counterfactuals.\nTo circumvent + this drawback, Wellawatte et al. 9 propose an-\nother approach, which identift + counterfactuals through a similarity search on the PubChem\ndatabase.108\n13\nSimilarity + to adjacent fields\nTangential examples to counterfactual explanations are adversarial + training and matched\nmolecular pairs. Adversarial perturbations are used during + training to deceive the model\nto expose the vulnerabilities of a model109,110 + whereas counterfactuals are applied post-hoc.\nTherefore, the main difference + between adversarial and counterfactual examples are in the\napplication, although + both are derived from the same optimization problem.100 Grabocka\net al. 111 + have developed a method named Adversarial Training on EXplanations (ATEX)\nwhich improves model robustness via exposure to adversarial examples. While there are\nconceptual disparities, we note that the counterfactual and adversarial explanations are\nequivalent mathematical objects.\nMatched molecular pairs @@ -537,12 +547,14 @@ interactions: passive diffusion of drugs from the blood stream to the brain is a critical aspect in drug\ndevelopment and discovery.120 Small molecule blood-brain barrier (BBB) permeation is a\nclassification problem routinely assessed with DL models.121,122 - To explain why DL models\nwork, we trained two models a random forest (RF) model123 - and a Gated Recurrent Unit\nRecurrent Neural Network (GRU-RNN). Then we explained - the RF model with generated\ncounterfactuals explanations using the MMACE9 and - the GRU-RNN with descriptor expla-\nnations.10 Both the models were trained - on the dataset developed by Martins et al. 124. The\nRF model was implemented - in Scikit-learn125 usi", " on the dataset developed by Martins et al. 124. The\nRF + To explain why DL models\nwork, we trained two models a random fore", "in is + a critical aspect in drug\ndevelopment and discovery.120 Small molecule blood-brain + barrier (BBB) permeation is a\nclassification problem routinely assessed with + DL models.121,122 To explain why DL models\nwork, we trained two models a random + forest (RF) model123 and a Gated Recurrent Unit\nRecurrent Neural Network (GRU-RNN). + Then we explained the RF model with generated\ncounterfactuals explanations + using the MMACE9 and the GRU-RNN with descriptor expla-\nnations.10 Both the + models were trained on the dataset developed by Martins et al. 124. The\nRF model was implemented in Scikit-learn125 using Mordred molecular descriptors126 as the\ninput features. The GRU-RNN model was implemented in Keras.127 See Wellawatte et al. 9\nand Gandhi and White 10 for more details.\nAccording to the counterfactuals @@ -580,14 +592,13 @@ interactions: a quantitative measurement of how substructures are contributing to the pre-\n16\nFigure 2: Descriptor explanations along with natural language explanation obtained for BBB\npermeability of Alprozolam molecule. The green and red bars show descriptors - t", "tion obtained for BBB\npermeability of Alprozolam molecule. The green and - red bars show descriptors that influ-\nence predictions positively and negatively, - respectively. Dotted yellow lines show significance\nthreshold (\u03b1 = 0.05) - for the t-statistic. Molecular descriptors show molecule-level proper-\nties - that are important for the prediction. ECFP and MACCS descriptors indicate which\nsubstructures - influence model predictions. MACCS explanations lead to text explanations\nas - shown. Republished from Ref.10 with permission from authors. SMARTS annotations - for\nMACCS descriptors were created using SMARTSviewer (smartsview.zbh.uni-hamburg.de,\nCopyright: + that influ-\nence predictions positively and negatively, respectively. Dotted + yellow lines show significance\nthreshold (\u03b1 = 0.05) for the t-statistic. + Molecular descriptors show molecule-level proper-\nties that are important for + the prediction. ECFP and MACCS descriptors indicate which\nsubstructures influence + model predictions. MACCS explanations lead to text explanations\nas shown. Republished + from Ref.10 with permission from authors. SMARTS annotations for\nMACCS descriptors + were created using SMARTSviewer (smartsview.zbh.uni-hamburg.de,\nCopyright: ZBH, Center for Bioinformatics Hamburg) developed by Schomburg et al. 132.\n17\ndiction. For example, we see that adding acidic and basic groups as well as hydrogen bond\nacceptors, increases solubility. Substructure importance from ECFP97 and @@ -600,53 +611,56 @@ interactions: is colored by solubility. Top 4 counterfactuals are shown here.\nRepublished from Ref.9 with permission from the Royal Society of Chemistry.\nGeneralizing XAI \u2013 interpreting scent-structure relationships\nIn this example, we show - how non-local structure-property relationships can be learned with\nXAI across - multiple molecules. Molecular scent prediction is a multi-label classification - task\nbecause a molecule can be described by more than one scent. For example, - the molecule\njasmone can be described as having \u2018jasmine,\u2019 \u2018woody,\u2019 - \u2018floral,\u2019 and \u2019herbal\u2019 scents.139 The\nscent-structure relationship - is not very well understood,140 although some relationships are\nknown. For - example, molecules with an ester functional group are often associated with\n18\nFigure - 4: Descriptor explanations for solubility prediction model. The green and red - bars\nshow descriptors that influence predictions positively and negatively, - respectively. Dotted\nyellow lines show significance threshold (\u03b1 = 0.05) - for the t-statistic. The MACCS and\nECFP descriptors indicate which substructures - influence model predictions. MACCS sub-\nstructures may either be present in - the molecule as is or may represent a modification. ECFP\nfingerprints are substructures - in the molecule that affect the prediction. MACCS descriptor\nare used to obtain - text explanations as shown. Republished from Ref.10 with permission from\nauthors. - SMARTS annotations for MACCS descriptors were created using SMARTSviewer\n(smartsview.zbh.uni-hamburg.de, + how non", "Each data point is colored by solubility. Top 4 counterfactuals are + shown here.\nRepublished from Ref.9 with permission from the Royal Society of + Chemistry.\nGeneralizing XAI \u2013 interpreting scent-structure relationships\nIn + this example, we show how non-local structure-property relationships can be + learned with\nXAI across multiple molecules. Molecular scent prediction is a + multi-label classification task\nbecause a molecule can be described by more + than one scent. For example, the molecule\njasmone can be described as having + \u2018jasmine,\u2019 \u2018woody,\u2019 \u2018floral,\u2019 and \u2019herbal\u2019 + scents.139 The\nscent-structure relationship is not very well understood,140 + although some relationships are\nknown. For example, molecules with an ester + functional group are often associated with\n18\nFigure 4: Descriptor explanations + for solubility prediction model. The green and red bars\nshow descriptors that + influence predictions positively and negatively, respectively. Dotted\nyellow + lines show significance threshold (\u03b1 = 0.05) for the t-statistic. The MACCS + and\nECFP descriptors indicate which substructures influence model predictions. + MACCS sub-\nstructures may either be present in the molecule as is or may represent + a modification. ECFP\nfingerprints are substructures in the molecule that affect + the prediction. MACCS descriptor\nare used to obtain text explanations as shown. + Republished from Ref.10 with permission from\nauthors. SMARTS annotations for + MACCS descriptors were created using SMARTSviewer\n(smartsview.zbh.uni-hamburg.de, Copyright: ZBH, Center for Bioinformatics Hamburg) de-\nveloped by Schomburg - et al. 132.\n19\nthe \u2018fruity\u2019 scent. There are some exceptions ", - "tics Hamburg) de-\nveloped by Schomburg et al. 132.\n19\nthe \u2018fruity\u2019 - scent. There are some exceptions though, like tert-amyl acetate which has a\n\u2018camphoraceous\u2019 - rather than \u2018fruity\u2019 scent.140,141\nIn Seshadri et al. 31, we trained - a GNN model to predict the scent of molecules and utilized\ncounterfactuals9 - and descriptor explanations10 to quantify scent-structure relationships. The\nMMACE - method was modified to account for the multi-label aspect of scent prediction. - This\nmodification defines molecules that differed from the instance molecule - by only the selected\nscent as counterfactuals. For instance, counterfactuals - of the jasmone molecule would be false\nfor the \u2018jasmine\u2019 scent but - would still be positive for \u2018woody,\u2019 \u2018floral\u2019 and \u2018herbal\u2019 - scents.\nFigure 5: Counterfactual for the 2,4 decadienal molecule.\nThe counterfactual - indicates\nstructural changes to ethyl benzoate that would result in the model - predicting the molecule\nto not contain the \u2018fruity\u2019 scent. The Tanimoto96 - similarity between the counterfactual and\n2,4 decadienal is also provided. - Republished with permission from authors.31\nThe molecule 2,4-decadienal, which - is known to have a \u2018fatty\u2019 scent, is analyzed in Fig-\nure 5.142,143 - The resulting counterfactual, which has a shorter carbon chain and no carbonyl\ngroups, - highlights the influence of these structural features on the \u2018fatty\u2019 - scent of 2,4 deca-\ndienal. To generalize to other molecules, Seshadri et al. - 31 applied the descriptor attribution\nmethod to obtain global explanations - for the scents. The global explanation for the \u2018fatty\u2019\nscent was - generated by gathering chemical spaces around many \u2018fatty\u2019 scented - molecules.\nThe resulting natural language explanation is: \u201cThe molecular - property \u201cfatty scent\u201d can\nbe explained by the presence of a heptanyl - fragment, two CH2 groups separated by four\n20\nbonds, and a C=O double bond, - as well as the lack of more than one or two O atoms.\u201d31\nThe importance - of a heptanyl fragment aligns with that reported in the literature, as \u2018fatty\u2019\nmolecules - often have a long carbon chain.144 Furthermore, the importance of a C=O dou-\nble - bond is supported by the findings reported by Licon et al. 145, where in addition + et al. 132.\n19\nthe \u2018fruity\u2019 scent. There are some exceptions though, + like tert-amyl acetate which has a\n\u2018camphoraceous\u2019 rather than \u2018fruity\u2019 + scent.140,141\nIn Seshadri et al. 31, we trained a GNN model to predict the + scent of molecules and utilized\ncounterfactuals9 and descriptor explanations10 + to quantify scent-structure relationships. The\nMMACE method was modified to + account for the multi-label aspect of scent prediction. This\nmodification defines + molecules that differed from the instance molecule by only the selected\nscent + as counterfactuals. For instance, counterfactuals of the jasmone molecule would + be false\nfor the \u2018jasmine\u2019 scent but would still be positive for + \u2018woody,\u2019 \u2018floral\u2019 and \u2018herbal\u2019 scents.\nFigure + 5: Counterfactual for the 2,4 decadienal molecule.\nThe counterfactual indicates\nstructural + changes to ethyl benzoate that would result in the model predicting the molecule\nto + not contain the \u2018fruity\u2019 scent. The Tanimoto96 similarity between + the counterfactual and\n2,4 decadienal is also provided. Republished with permission + from authors.31\nThe molecule 2,4-decadienal, which is known to have a \u2018fatty\u2019 + scent, is analyzed in Fig-\nure 5.142,143 The resulting counterfactual, which + has a shorter carbon chain and no carbonyl\ngroups, highlights the influence + of these structural features on the \u2018fatty\u2019 scent of 2,4 deca-\ndienal. + To generalize to other molecules, Seshadri et al. 31 applied the descriptor + attribution\nmethod to obtain global explanations for the scents. The global + explanation for the \u2018fatty\u2019\nscent was generated by gathering chemical + spaces around many \u2018fatty\u2019 scented molecules.\nThe resulting natural + language explanation is: \u201cThe molecular property \u201cfatty scent\u201d + can\nbe explained by the presence of a heptanyl fragment, two CH2 groups separated + by four\n20\nbonds, and a C=O double bond, as well as the lack of more than + one or two O atoms.\u201d31\nThe importance of a heptanyl fragment aligns with + that reported in the literature, as \u2018fatty\u2019\nmolecules often have + a long carbon chain.144 Furthermore, the importance of a C=O dou-\nble bond + is supported by the findings reported by Licon et al. 145, where in addition to a\n\u201clarger carbon-chain skeleton\u201d, they found that \u2018fatty\u2019 molecules also had \u201caldehyde or acid\nfunctions\u201d.145 For the \u2018pineapple\u2019 scent, the following natural language explanation was ob-\ntained: \u201cThe @@ -657,11 +671,13 @@ interactions: of a C=O double bond with an ether could\nalso correspond to an ester group. Additionally, aldehydes and ketones, which contain C=O\ndouble bonds, are also common in pineapple volatile compounds.146,148\nDiscussion\nWe have shown two - post-hoc XAI applications based on molecular counterfactual expla-\nnation", - "scussion\nWe have shown two post-hoc XAI applications based on molecular counterfactual - expla-\nnations9 and descriptor explanations.10 These methods can be used to - explain black-box\nmodels whose input is a molecule. These two methods can be - applied for both classification\nand regression tasks. Note that the \u201ccorrectness\u201d + post-hoc XAI applications based on molecular counterfactual expla-\nnations9 + and descriptor explanations.10 These methods can be used to explain black-box\nmodels + whose input is a molecule. These two methods can be applied for both classification\nand + regression tasks. Note that the \u201ccorrectness\u201d of the explanations + strongly depends on\nthe accuracy of the black-box model.\nA molecular counterfactual + is one with a minimal distance from a base molecular, but\nwith contrasting + chemical properties. In the above examples, we us", "hat the \u201ccorrectness\u201d of the explanations strongly depends on\nthe accuracy of the black-box model.\nA molecular counterfactual is one with a minimal distance from a base molecular, but\nwith contrasting chemical properties. In the above examples, we used Tanimoto @@ -695,37 +711,38 @@ interactions: can help assess if the model is learning\nthe correct underlying chemical principles. We also showed that black-box modeling first,\nfollowed by XAI, is a path to structure-property relationships without needing to trade\nbetween accuracy - and interpretability. However, XAI in chemistry has some maj", "thout needing - to trade\nbetween accuracy and interpretability. However, XAI in chemistry has - some major open\nquestions, that are also related to the black-box nature of - the deep learning.\nSome are\n22\nhighlighted below:\n\u2022 Explanation representation: - How is an explanation presented \u2013 text, a molecule, attri-\nbutions, a - concept, etc?\n\u2022 Molecular distance: in XAI approaches such as counterfactual - generation, the \u201cdis-\ntance\u201d between two molecules is minimized. - Molecular distance is subjective. Possibil-\nities are distance based on molecular - properties, synthesis routes, and direct structure\ncomparisons.\n\u2022 Regulations: - As black-box models move from research to industry, healthcare, and\nenvironmental - settings, we expect XAI to become more important to explain decisions\nto chemists - or non-experts and possibly be legally required. Explanations may need\nto be - tuned for be for doctors instead of chemists or to satisfy a legal requirement.\n\u2022 - Chemical space: Chemical space is the set of molecules that are realizable; - \u201crealiz-\nable\u201d can be defined from purchasable to synthesizable to - satisfied valences. What is\nmost useful? Can an explanation consider nearby - impossible molecules? How can we\ngenerate local chemical spaces centered around - a specific molecule for finding counter-\nfactuals or other instance explanations? - Similarly, can \u201cactivity cliffs\u201d be connected\nto explanations and - the local chemical space.149\n\u2022 Evaluating XAI : there is a lack of a systematic - framework (quantitative or qualitative)\nto evaluate correctness and applicability - of an explanation. Can there be a universal\nframework, or should explanations - be chosen and evaluated based on the audience and\ndomain? For example, work - by Rasmussen et al. 58 attempts to focus on comparing\nfeature attribution XAI - methods via Crippen\u2019s logP scores.\n23\nAcknowledgements\nResearch reported - in this work was supported by the National Institute of General Medical\nSciences + and interpretability. However, XAI in chemistry has some major open\nquestions, + that are also related to the black-box nature of the deep learning.\nSome are\n22\nhighlighted + below:\n\u2022 Explanation representation: How is an explanation presented \u2013 + text, a molecule, attri-\nbutions, a concept, etc?\n\u2022 Molecular distance: + in XAI approaches such as counterfactual generation, the \u201cdis-\ntance\u201d + between two molecules is minimized. Molecular distance is subjective. Possibil-\nities + are distance based on molecular properties, synthesis routes, and direct structure\ncomparisons.\n\u2022 + Regulations: As black-box models move from research to industry, healthcare, + and\nenvironmental settings, we expect XAI to become more important to explain + decisions\nto chemists or non-experts and possibly be legally required. Explanations + may need\nto be tuned for be for doctors instead of chemists or to satisfy a + legal requirement.\n\u2022 Chemical space: Chemical space is the set of molecules + that are realizable; \u201crealiz-\nable\u201d can be defined from purchasable + to synthesizable to satisfied valences. What is\nmost useful? Can an explanation + consider nearby impossible molecules? How can we\ngenerate local chemical spaces + centered around a specific molecule for finding counter-\nfactuals or other + instance explanations? Similarly, can \u201cactivity cliffs\u201d be connected\nto + explanations and the local chemical space.149\n\u2022 Evaluating XAI : there + is a lack of a systematic framework (quantitative or qualitative)\nto evaluate + correctness and applicability of an explanation. Can there be a universal\nframework, + or should explanations be chosen and evaluated based on the audience and\ndomain? + For example, work by Rasmussen et al. 58 attempts to focus on comparing\nfeature + attribution XAI methods via Crippen\u2019s logP scores.\n23\nAcknowledgements\nResearch + reported in this work was supported by the National Institute of General Medical\nSciences of the National Institutes of Health under award number R35GM137966. This work\nwas supported by the NSF under awards 1751471 and 1764415. We thank the Center for\nIntegrated Research Computing at the University of Rochester for providing computational\nresources.\nReferences\n(1) Choudhary, K.; DeCost, B.; Chen, C.; Jain, A.; Tavazza, F.; Cohn, R.; Park, C. W.;\nChoudhary, A.; Agrawal, A.; Billinge, S. J.; Holm, E.; Ong, S. P.; Wolverton, + C.\nRecent advances and ", "f Rochester for providing computational\nresources.\nReferences\n(1) + Choudhary, K.; DeCost, B.; Chen, C.; Jain, A.; Tavazza, F.; Cohn, R.; Park, + C. W.;\nChoudhary, A.; Agrawal, A.; Billinge, S. J.; Holm, E.; Ong, S. P.; Wolverton, C.\nRecent advances and applications of deep learning methods in materials science. npj\nComputational Materials 2022, 8.\n(2) Keith, J. A.; Vassilev-Galindo, V.; Cheng, B.; Chmiela, S.; Gastegger, M.; M\u00a8uller, K.-\nR.; Tkatchenko, A. @@ -733,1839 +750,53 @@ interactions: Into Chemical Systems. Chemical Reviews 2021, 121, 9816\u20139872,\nPMID: 34232033.\n(3) Goh, G. B.; Hodas, N. O.; Vishnu, A. Deep learning for computational chemistry.\nJournal of Computational Chemistry 2017, 38, 1291\u20131307.\n(4) Deringer, V. L.; Caro, - M. A.; Cs\u00b4anyi, G. Machine Learning Interatomic Potentials as\nEmergi", - "307.\n(4) Deringer, V. L.; Caro, M. A.; Cs\u00b4anyi, G. Machine Learning Interatomic - Potentials as\nEmerging Tools for Materials Science. Advanced Materials 2019, - 31, 1902765.\n(5) Faber, F. A.; Hutchison, L.; Huang, B.; Gilmer, J.; Schoenholz, - S. S.; Dahl, G. E.;\nVinyals, O.; Kearnes, S.; Riley, P. F.; von Lilienfeld, - O. A. Prediction Errors of Molec-\nular Machine Learning Models Lower than Hybrid - DFT Error. Journal of Chemical\nTheory and Computation 2017, 13, 5255\u20135264, - PMID: 28926232.\n24\n(6) Duch, W.; Swaminathan, K.; Meller, J. Artificial Intelligence - Approaches for Rational\nDrug Design and Discovery. Current Pharmaceutical Design - 2007, 13, 1497\u20131508.\n(7) Dara, S.; Dhamercherla, S.; Jadav, S. S.; Babu, - C. M.; Ahsan, M. J.; darasuresh, S. D.;\nDara, S. Machine Learning in Drug Discovery: - A Review. Artificial Intelligence Review\n123, 55, 1947\u20131999.\n(8) Gupta, - R.; Srivastava, D.; Sahu, M.; Tiwari, S.; Ambasta, R. K.; Kumar, P. Artifi-\ncial - intelligence to deep learning: machine intelligence approach for drug discovery.\nMolecular - diversity 2021, 25, 1315\u20131360.\n(9) Wellawatte, G. P.; Seshadri, A.; White, - A. D. Model agnostic generation of counter-\nfactual explanations for molecules. - Chemical Science 2022, 13, 3697\u20133705.\n(10) Gandhi, H. A.; White, A. D. - Explaining structure-activity relationships using locally\nfaithful surrogate - models. chemrxiv 2022,\n(11) Gormley, A. J.; Webb, M. A. Machine learning in - combinatorial polymer chemistry.\nNature Reviews Materials 2021,\n(12) Gomes, - C. P.; Fink, D.; Dover, R. B. V.; Gregoire, J. M. Computational sustainability\nmeets - materials science. Nature Reviews Materials 2021,\n(13) On scientific understanding - with artificial intelligence. Nature Reviews Physics 2022\n4:12 2022, 4, 761\u2013769.\n(14) - Arrieta, A. B.; D\u00b4\u0131az-Rodr\u00b4\u0131guez, N.; Ser, J. D.; Bennetot, - A.; Tabik, S.; Barbado, A.;\nGarcia, S.; Gil-Lopez, S.; Molina, D.; Benjamins, - R.; Chatila, R.; Herrera, F. Explain-\nable Artificial Intelligence (XAI): Concepts, - Taxonomies, Opportunities and Chal-\nlenges toward Responsible AI. Information - Fusion 2019, 58, 82\u2013115.\n(15) Murdoch, W. J.; Singh, C.; Kumbier, K.; - Abbasi-Asl, R.; Yu, B. Interpretable machine\nlearning: definitions, methods, - and applications. ArXiv 2019, abs/1901.04592.\n25\n(16) Boobier, S.; Osbourn, - A.; Mitchell, J. B. Can human experts predict solubility better\nthan computers? - Journal of cheminformatics 2017, 9, 1\u201314.\n(17) Lee, J. D.; See, K. A. - Trust in automation: Designing for appropriate reliance. Human\nFactors 2004, - 46, 50\u201380.\n(18) Bolukbasi, T.; Chang, K.-W.; Zou, J. Y.; Saligrama, V.; - Kalai, A. T. Man is to com-\nputer programmer as woman is to homemaker? debiasing - word embeddings. Advances\nin neural information processing systems 2016, 29.\n(19) - Buolamwini, J.; Gebru, T. Gender Shades: Intersectional Accuracy Disparities - in\nCommercial Gender Classification. Proceedings of the 1st Conference on Fairness,\nAccountability - and Transparency. 2018; pp 77\u201391.\n(20) Lapuschkin, S.; W\u00a8aldchen, - S.; Binder, A.; Montavon, "], "model": "text-embedding-3-small", "encoding_format": - "base64"}' - headers: - accept: - - application/json - accept-encoding: - - gzip, deflate - connection: - - keep-alive - content-length: - - "50126" - content-type: - - application/json - host: - - api.openai.com - user-agent: - - AsyncOpenAI/Python 1.46.1 - x-stainless-arch: - - arm64 - x-stainless-async: - - async:asyncio - x-stainless-lang: - - python - x-stainless-os: - - MacOS - x-stainless-package-version: - - 1.46.1 - x-stainless-raw-response: - - "true" - x-stainless-runtime: - - CPython - x-stainless-runtime-version: - - 3.12.6 - method: POST - uri: https://api.openai.com/v1/embeddings - response: - body: - string: !!binary | - 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 - headers: - CF-Cache-Status: - - DYNAMIC - CF-RAY: - - 8c9c99ac8df5fa8a-SJC - Connection: - - keep-alive - Content-Encoding: - - gzip - Content-Type: - - application/json - Date: - - Fri, 27 Sep 2024 15:41:51 GMT - Server: - - cloudflare - Set-Cookie: - - __cf_bm=TyZMV15EPWqQXIbTEKRZ1Fggt3ZrMRC8fwKSoQemN28-1727451711-1.0.1.1-1IuaZeYu1bHwXOBs1o2p6JiWcDrm8vtRUTauyAVfYSTF8WGo9o_nFHMe2VvmzxUrbomkaIIk65ZyCtLLaSGbrg; - path=/; expires=Fri, 27-Sep-24 16:11:51 GMT; domain=.api.openai.com; HttpOnly; - Secure; SameSite=None - - _cfuvid=8VnZjkM1FzzkfufFNQobFDcIb4Hs0eOF3OZxxZTYh.w-1727451711771-0.0.1.1-604800000; - path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None - Transfer-Encoding: - - chunked - X-Content-Type-Options: - - nosniff - access-control-allow-origin: - - "*" - access-control-expose-headers: - - X-Request-ID - alt-svc: - - h3=":443"; ma=86400 - openai-model: - - text-embedding-3-small - openai-organization: - - future-house-xr4tdh - openai-processing-ms: - - "128" - openai-version: - - "2020-10-01" - strict-transport-security: - - max-age=31536000; includeSubDomains; preload - x-ratelimit-limit-requests: - - "10000" - x-ratelimit-limit-tokens: - - "10000000" - x-ratelimit-remaining-requests: - - "9999" - x-ratelimit-remaining-tokens: - - "9987878" - x-ratelimit-reset-requests: - - 6ms - x-ratelimit-reset-tokens: - - 72ms - x-request-id: - - req_db08890591133dd81002e0e3135472fd - status: - code: 200 - message: OK - - request: - body: - '{"input": ["ability and Transparency. 2018; pp 77\u201391.\n(20) Lapuschkin, - S.; W\u00a8aldchen, S.; Binder, A.; Montavon, G.; Samek, W.; M\u00a8uller, K.-R.\nUnmasking - Clever Hans predictors and assessing what machines really learn. Nature\ncommunications - 2019, 10, 1\u20138.\n(21) DeGrave, A. J.; Janizek, J. D.; Lee, S.-I. AI for - radiographic COVID-19 detection\nselects shortcuts over signal. Nature Machine - Intelligence 2021, 3, 610\u2013619.\n(22) Goodman, B.; Flaxman, S. European - Union regulations on algorithmic decision-\nmaking and a \u201cright to explanation\u201d. - AI Magazine 2017, 38, 50\u201357.\n(23) ACT, A. I. European Commission. On Artificial - Intelligence: A European Approach\nto Excellence and Trust. 2021, COM/2021/206.\n(24) - Blueprint for an AI Bill of Rights, The White House. 2022; https://www.whitehouse.\ngov/ostp/ai-bill-of-rights/.\n(25) + M. A.; Cs\u00b4anyi, G. Machine Learning Interatomic Potentials as\nEmerging + Tools for Materials Science. Advanced Materials 2019, 31, 1902765.\n(5) Faber, + F. A.; Hutchison, L.; Huang, B.; Gilmer, J.; Schoenholz, S. S.; Dahl, G. E.;\nVinyals, + O.; Kearnes, S.; Riley, P. F.; von Lilienfeld, O. A. Prediction Errors of Molec-\nular + Machine Learning Models Lower than Hybrid DFT Error. Journal of Chemical\nTheory + and Computation 2017, 13, 5255\u20135264, PMID: 28926232.\n24\n(6) Duch, W.; + Swaminathan, K.; Meller, J. Artificial Intelligence Approaches for Rational\nDrug + Design and Discovery. Current Pharmaceutical Design 2007, 13, 1497\u20131508.\n(7) + Dara, S.; Dhamercherla, S.; Jadav, S. S.; Babu, C. M.; Ahsan, M. J.; darasuresh, + S. D.;\nDara, S. Machine Learning in Drug Discovery: A Review. Artificial Intelligence + Review\n123, 55, 1947\u20131999.\n(8) Gupta, R.; Srivastava, D.; Sahu, M.; Tiwari, + S.; Ambasta, R. K.; Kumar, P. Artifi-\ncial intelligence to deep learning: machine + intelligence approach for drug discovery.\nMolecular diversity 2021, 25, 1315\u20131360.\n(9) + Wellawatte, G. P.; Seshadri, A.; White, A. D. Model agnostic generation of counter-\nfactual + explanations for molecules. Chemical Science 2022, 13, 3697\u20133705.\n(10) + Gandhi, H. A.; White, A. D. Explaining structure-activity relationships using + locally\nfaithful surrogate models. chemrxiv 2022,\n(11) Gormley, A. J.; Webb, + M. A. Machine learning in combinatorial polymer chemistry.\nNature Reviews Materials + 2021,\n(12) Gomes, C. P.; Fink, D.; Dover, R. B. V.; Gregoire, J. M. Computational + sustainability\nmeets materials science. Nature Reviews Materials 2021,\n(13) + On scientific understanding with artificial intelligence. Nature Reviews Physics + 2022\n4:12 2022, 4, 761\u2013769.\n(14) Arrieta, A. B.; D\u00b4\u0131az-Rodr\u00b4\u0131guez, + N.; Ser, J. D.; Bennetot, A.; Tabik, S.; Barbado, A.;\nGarcia, S.; Gil-Lopez, + S.; Molina, D.; Benjamins, R.; Chatila, R.; Herrera, F. Explain-\nable Artificial + Intelligence (XAI): Concepts, Taxonomies, Opportunities and Chal-\nlenges toward + Responsible AI. Information Fusion 2019, 58, 82\u2013115.\n(15) Murdoch, W. + J.; Singh, C.; Kumbier, K.; Abbasi-Asl, R.; Yu, B. Interpretable machine\nlearning: + definitions, methods, and applications. ArXiv 2019, abs/1901.04592.\n25\n(16) + Boobier, S.; Osbourn, A.; Mitchell, J. B. Can human experts predict solubility + better\nthan computers? Journal of cheminformatics 2017, 9, 1\u201314.\n(17) + Lee, J. D.; See, K. A. Trust in automation: Designing for appropriate reliance. + Human\nFactors 2004, 46, 50\u201380.\n(18) Bolukbasi, T.; Chang, K.-W.; Zou, + J. Y.; Saligrama, V.; Kalai, A. T. Man is to com-\nputer programmer as woman + is to homemaker? debiasing word embeddings. Advances\nin neural information + processing systems 2016, 29.\n(19) Buolamwini, J.; Gebru, T. Gender Shades: + Intersectional Accuracy Disparities in\nCommercial Gender Classification. Proceedings + of the 1st Conference on Fairness,\nAccountability and Transparency. 2018; pp + 77\u201391.\n(20) Lapuschkin, S.; W\u00a8aldchen, S.; Binder, A.; Montavon, + G.; Samek, W.; M\u00a8uller, K.-R.\nUnmasking Clever Hans predictors and assessing + what machines really learn. Nature\ncommunications 2019, 10, 1\u20138.\n(21) + DeGrave, A. J.; Janizek, J. D.; Lee, S.-I. AI for radiographic COVID-19 detection\nselects + shortcuts over signal. Nature Machine Intelligence 2021, 3, 610\u2013619.\n(22) + Goodman, B.; Flaxman, S. European Union regulations on algorithmic decision-\nmaking + and a \u201cright to explanation\u201d. AI Magazine 2017, 38, 50\u201357.\n(23) + ACT, A. I. European Commission. On Artificial Intelligence: A European Approach\nto + Excellence and Trust. 2021, COM/2021/206.\n(24) Blueprint for an AI Bill of + Rights, The White House. 2022; https://www.whitehouse.\ngov/ostp/ai-bill-of-rights/.\n(25) Miller, T. Explanation in artificial intelligence: Insights from the social sciences. Ar-\ntificial intelligence 2019, 267, 1\u201338.\n26\n(26) Murdoch, W. J.; Singh, C.; Kumbier, K.; Abbasi-Asl, R.; Yu, B. Definitions, meth-\nods, @@ -2573,67 +804,71 @@ interactions: of Sciences of the United States of America 2019, 116, 22071\u201322080.\n(27) Gunning, D.; Aha, D. DARPA\u2019s Explainable Artificial Intelligence (XAI) Program.\nAI Magazine 2019, 40, 44\u201358.\n(28) Biran, O.; Cotton, C. Explanation - and justification in machine learning: A survey.\nIJCAI-17 workshop on explainable - AI (XAI). 2017; pp 8\u201313.\n(29) Palacio, S.; Lucieri, A.; Munir, M.; Ahmed, - S.; Hees, J.; Dengel, A. Xai handbook:\nTowards a unified framework for explainable - ai. Proceedings of the IEEE/CVF Inter-\nnational Conference on Computer Vision. - 2021; pp 3766\u20133775.\n(30) Kuhn, D. R.; Kacker, R. N.; Lei, Y.; Simos, D. - E. Combinatorial Methods for Ex-\nplainable AI. 2020 IEEE International Conference - on Software Testing, Verification\nand Validation Workshops (ICSTW) 2020, 167\u2013170.\n(31) - Seshadri, A.; Gandhi, H. A.; Wellawatte, G. P.; White, A. D. Why does that molecule\nsmell? - ChemRxiv 2022,\n(32) Das, A.; Rad, P. Opportunities and challenges in explainable - artificial intelligence\n(xai): A survey. arXiv preprint arXiv:2006.11371 2020,\n(33) - Machlev, R.; Heistrene, L.; Perl, M.; Levy, K. Y.; Belikov, J.; Mannor, S.; - Levron, Y.\nExplainable Artificial Intelligence (XAI) techniques for energy - and power systems:\nReview, challenges and opportunities. Energy and AI 2022, - 9, 100169.\n(34) Koh, P. W.; Liang, P. Understanding black-box predictions via - influence functions.\nInternational Conference on Machine Learning. 2017; pp - 1885\u20131894.\n(35) Ribeiro, M. T.; Singh, S.; Guestrin, C. \u201d Why should - i trust you?\u201d Explaining the\npredictions of any classifier. Proceedings - of the 22nd ACM SIGKDD international\n27\nconference on knowledge discovery - and data mining. San Diego, CA, USA, 2016; pp\n1135\u20131144.\n(36) Dhurandhar, - A.; Chen, P.-Y.; Luss, R.; Tu, C.-C.; Ting, P.; Shanmugam, K.; Das, P.\nExplanations - based on the missing: Towards contrastive explanations with pertinent\nnegatives. - Advances i", "anations based on the missing: Towards contrastive explanations - with pertinent\nnegatives. Advances in neural information processing systems - 2018, 31.\n(37) Jin, W.; Li, X.; Hamarneh, G. Evaluating Explainable AI on a - Multi-Modal Medical\nImaging Task: Can Existing Algorithms Fulfill Clinical - Requirements? Proceedings of\nthe AAAI Conference on Artificial Intelligence - 2022, 36, 11945\u201311953.\n(38) Zhang, Y.; Xu, F.; Zou, J.; Petrosian, O. - L.; Krinkin, K. V. XAI Evaluation: Evalu-\nating Black-Box Model Explanations - for Prediction. 2021 II International Conference\non Neural Networks and Neurotechnologies - (NeuroNT). 2021; pp 13\u201316.\n(39) Oviedo, F.; Ferres, J. L.; Buonassisi, - T.; Butler, K. T. Interpretable and Explain-\nable Machine Learning for Materials - Science and Chemistry. Accounts of Materials\nResearch 2022, 3, 597\u2013607.\n(40) - Yalcin, O.; Fan, X.; Liu, S. Evaluating the correctness of explainable AI algorithms\nfor - classification. arXiv preprint arXiv:2105.09740 2021,\n(41) Hoffman, R. R.; - Mueller, S. T.; Klein, G.; Litman, J. Metrics for Explainable AI:\nChallenges - and Prospects. 2018,\n(42) Mohseni, S.; Zarei, N.; Ragan, E. D. A Multidisciplinary - Survey and Framework for\nDesign and Evaluation of Explainable AI Systems. ACM - Transactions on Interactive\nIntelligent Systems 2018, 11, 46.\n(43) Humer, - C.; Heberle, H.; Montanari, F.; Wolf, T.; Huber, F.; Henderson, R.; Hein-\nrich, - J.; Streit, M. ChemInformatics Model Explorer (CIME): exploratory analysis of\nchemical - model explanations. Journal of Cheminformatics 2022, 14, 1\u201314.\n28\n(44) - Lundberg, S. M.; Lee, S.-I. In Advances in Neural Information Processing Systems\n30; - Guyon, I., Luxburg, U. V., Bengio, S., Wallach, H., Fergus, R., Vishwanathan, - S.,\nGarnett, R., Eds.; Curran Associates, Inc., 2017; pp 4765\u20134774.\n(45) - \u02c7Strumbelj, E.; Kononenko, I. Explaining prediction models and individual - predictions\nwith feature contributions. Knowledge and information systems 2014, - 41, 647\u2013665.\n(46) Shapley, L. S. A Value for N-Person Games; RAND Corporation: - Santa Monica, CA,\n1952.\n(47) Molnar, C.; Casalicchio, G.; Bischl, B. Interpretable - machine learning\u2013a brief history,\nstate-of-the-art and challenges. Joint - European Conference on Machine Learning and\nKnowledge Discovery in Databases. - 2020; pp 417\u2013431.\n(48) Lou, Y.; Caruana, R.; Gehrke, J. Intelligible models - for classification and regression.\nProceedings of the 18th ACM SIGKDD international - conference on Knowledge dis-\ncovery and data mining. 2012; pp 150\u2013158.\n(49) - Bastani, O.; Kim, C.; Bastani, H. Interpreting blackbox models via model extraction.\narXiv + and justifi", " National\nAcademy of Sciences of the United States of America + 2019, 116, 22071\u201322080.\n(27) Gunning, D.; Aha, D. DARPA\u2019s Explainable + Artificial Intelligence (XAI) Program.\nAI Magazine 2019, 40, 44\u201358.\n(28) + Biran, O.; Cotton, C. Explanation and justification in machine learning: A survey.\nIJCAI-17 + workshop on explainable AI (XAI). 2017; pp 8\u201313.\n(29) Palacio, S.; Lucieri, + A.; Munir, M.; Ahmed, S.; Hees, J.; Dengel, A. Xai handbook:\nTowards a unified + framework for explainable ai. Proceedings of the IEEE/CVF Inter-\nnational Conference + on Computer Vision. 2021; pp 3766\u20133775.\n(30) Kuhn, D. R.; Kacker, R. N.; + Lei, Y.; Simos, D. E. Combinatorial Methods for Ex-\nplainable AI. 2020 IEEE + International Conference on Software Testing, Verification\nand Validation Workshops + (ICSTW) 2020, 167\u2013170.\n(31) Seshadri, A.; Gandhi, H. A.; Wellawatte, G. + P.; White, A. D. Why does that molecule\nsmell? ChemRxiv 2022,\n(32) Das, A.; + Rad, P. Opportunities and challenges in explainable artificial intelligence\n(xai): + A survey. arXiv preprint arXiv:2006.11371 2020,\n(33) Machlev, R.; Heistrene, + L.; Perl, M.; Levy, K. Y.; Belikov, J.; Mannor, S.; Levron, Y.\nExplainable + Artificial Intelligence (XAI) techniques for energy and power systems:\nReview, + challenges and opportunities. Energy and AI 2022, 9, 100169.\n(34) Koh, P. W.; + Liang, P. Understanding black-box predictions via influence functions.\nInternational + Conference on Machine Learning. 2017; pp 1885\u20131894.\n(35) Ribeiro, M. T.; + Singh, S.; Guestrin, C. \u201d Why should i trust you?\u201d Explaining the\npredictions + of any classifier. Proceedings of the 22nd ACM SIGKDD international\n27\nconference + on knowledge discovery and data mining. San Diego, CA, USA, 2016; pp\n1135\u20131144.\n(36) + Dhurandhar, A.; Chen, P.-Y.; Luss, R.; Tu, C.-C.; Ting, P.; Shanmugam, K.; Das, + P.\nExplanations based on the missing: Towards contrastive explanations with + pertinent\nnegatives. Advances in neural information processing systems 2018, + 31.\n(37) Jin, W.; Li, X.; Hamarneh, G. Evaluating Explainable AI on a Multi-Modal + Medical\nImaging Task: Can Existing Algorithms Fulfill Clinical Requirements? + Proceedings of\nthe AAAI Conference on Artificial Intelligence 2022, 36, 11945\u201311953.\n(38) + Zhang, Y.; Xu, F.; Zou, J.; Petrosian, O. L.; Krinkin, K. V. XAI Evaluation: + Evalu-\nating Black-Box Model Explanations for Prediction. 2021 II International + Conference\non Neural Networks and Neurotechnologies (NeuroNT). 2021; pp 13\u201316.\n(39) + Oviedo, F.; Ferres, J. L.; Buonassisi, T.; Butler, K. T. Interpretable and Explain-\nable + Machine Learning for Materials Science and Chemistry. Accounts of Materials\nResearch + 2022, 3, 597\u2013607.\n(40) Yalcin, O.; Fan, X.; Liu, S. Evaluating the correctness + of explainable AI algorithms\nfor classification. arXiv preprint arXiv:2105.09740 + 2021,\n(41) Hoffman, R. R.; Mueller, S. T.; Klein, G.; Litman, J. Metrics for + Explainable AI:\nChallenges and Prospects. 2018,\n(42) Mohseni, S.; Zarei, N.; + Ragan, E. D. A Multidisciplinary Survey and Framework for\nDesign and Evaluation + of Explainable AI Systems. ACM Transactions on Interactive\nIntelligent Systems + 2018, 11, 46.\n(43) Humer, C.; Heberle, H.; Montanari, F.; Wolf, T.; Huber, + F.; Henderson, R.; Hein-\nrich, J.; Streit, M. ChemInformatics Model Explorer + (CIME): exploratory analysis of\nchemical model explanations. Journal of Cheminformatics + 2022, 14, 1\u201314.\n28\n(44) Lundberg, S. M.; Lee, S.-I. In Advances in Neural + Information Processing Systems\n30; Guyon, I., Luxburg, U. V., Bengio, S., Wallach, + H., Fergus, R., Vishwanathan, S.,\nGarnett, R., Eds.; Curran Associates, Inc., + 2017; pp 4765\u20134774.\n(45) \u02c7Strumbelj, E.; Kononenko, I. Explaining + prediction models and individual predictions\nwith feature contributions. Knowledge + and information systems 2014, 41, 647\u2013665.\n(46) Shapley, L. S. A Value + for N-Person Games; RAND Corporation: Santa Monica, CA,\n1952.\n(47) Molnar, + C.; Casalicchio, G.; Bischl, B. Interpretable machine learning\u2013a brief + history,\nstate-of-the-art and challenges. Joint European Conference on Machine + Learning and\nKnowledge Discovery in Databases. 2020; pp 417\u2013431.\n(48) + Lou, Y.; Caruana, R.; Gehrke, J. Intelligible models for classification and + regression.\nProceedings of the 18th ACM SIGKDD international conference on + Knowledge dis-\ncovery and data mining. 2012; pp 150\u2013158.\n(49) Bastani, + O.; Kim, C.; Bastani, H. Interpreting blackbox models via model extraction.\narXiv preprint arXiv:1705.08504 2017,\n(50) Gajewicz, A.; Puzyn, T.; Odziomek, K.; Urbaszek, P.; Haase, A.; Riebeling, C.;\nLuch, A.; Irfan, M. A.; Landsiedel, R.; van der Zande, M.; Bouwmeester, H. Deci-\nsion tree models to classify nanomaterials according to the DF4nanoGrouping scheme.\nNanotoxicology 2018, 12, 1\u201317.\n(51) Han, L.; Wang, Y.; Bryant, S. H. Developing and validating predictive decision - tree\nmodels from mining che", ".; Wang, Y.; Bryant, S. H. Developing and validating - predictive decision tree\nmodels from mining chemical structural fingerprints + tree\nmodels from mining chemical structural fingerprints and high\u2013throughput + screening\ndata in PubChem. BMC Bioinformatics 2008, 9, 401.\n(52) Plumb, G.; + Al-Shedivat, M.; Cabrera, \u00b4A. A.; Perer, A.; Xing, E.; Talwalkar, A. Regu-", + "ng predictive decision tree\nmodels from mining chemical structural fingerprints and high\u2013throughput screening\ndata in PubChem. BMC Bioinformatics 2008, 9, 401.\n(52) Plumb, G.; Al-Shedivat, M.; Cabrera, \u00b4A. A.; Perer, A.; Xing, E.; Talwalkar, A. Regu-\n29\nlarizing black-box models for improved interpretability. @@ -2671,35 +906,36 @@ interactions: Explanations from Deep Networks via Gradient-Based Localization. In-\nternational Journal of Computer Vision 2019, 128, 336\u2013359.\n(65) Smilkov, D.; Thorat, N.; Kim, B.; Vi\u00b4egas, F.; Wattenberg, M. Smoothgrad: removing\nnoise by - add", "(65) Smilkov, D.; Thorat, N.; Kim, B.; Vi\u00b4egas, F.; Wattenberg, - M. Smoothgrad: removing\nnoise by adding noise. arXiv preprint arXiv:1706.03825 - 2017,\n(66) Pope, P.; Kolouri, S.; Rostrami, M.; Martin, C.; Hoffmann, H. Discovering - Molec-\nular Functional Groups Using Graph Convolutional Neural Networks. 2018; - https:\n//arxiv.org/abs/1812.00265.\n(67) Jim\u00b4enez-Luna, J.; Skalic, M.; - Weskamp, N.; Schneider, G. Coloring molecules with ex-\nplainable artificial - intelligence for preclinical relevance assessment. Journal of Chem-\nical Information - and Modeling 2021, 61, 1083\u20131094.\n(68) Sanchez-Lengeling, B.; Wei, J.; - Lee, B.; Reif, E.; Wang, P. Y.; Qian, W. W.; Mc-\nCloskey, K.; Colwell, L.; - Wiltschko, A. Evaluating Attribution for Graph Neural\nNetworks. Proceedings - of the 34th International Conference on Neural Information\nProcessing Systems. - Red Hook, NY, USA, 2020.\n31\n(69) Ying, R.; Bourgeois, D.; You, J.; Zitnik, - M.; Leskovec, J. GNNExplainer: Generating\nExplanations for Graph Neural Networks. - Advances in neural information processing\nsystems 2019, 32, 9240\u20139251.\n(70) - Rao, J.; Zheng, S.; Yang, Y. Quantitative Evaluation of Explainable Graph Neural\nNetworks - for Molecular Property Prediction. arXiv preprint arXiv:2107.04119 2021,\n(71) - Yuan, H.; Yu, H.; Wang, J.; Li, K.; Ji, S. On Explainability of Graph Neural - Net-\nworks via Subgraph Explorations. Proceedings of the 38th International - Conference\non Machine Learning. 2021; pp 12241\u201312252.\n(72) Shrikumar, - A.; Greenside, P.; Kundaje, A. Learning Important Features Through\nPropagating - Activation Differences. 2017,\n(73) Montavon, G.; Binder, A.; Lapuschkin, S.; - Samek, W.; M\u00a8uller, K. R. Layer-Wise\nRelevance Propagation: An Overview. - Lecture Notes in Computer Science (including\nsubseries Lecture Notes in Artificial - Intelligence and Lecture Notes in Bioinformatics)\n2019, 11700 LNCS, 193\u2013209.\n(74) - Baldassarre, F.; Azizpour, H. Explainability Techniques for Graph Convolutional - Net-\nworks. 2019; https://arxiv.org/abs/1905.13686.\n(75) Hochuli, J.; Helbling, - A.; Skaist, T.; Ragoza, M.; Koes, D. R. Visualizing convolutional\nneural network - protein-ligand scoring. Journal of Molecular Graphics and Modelling\n2018, 84, - 96\u2013108.\n(76) Rodr\u00b4\u0131guez-P\u00b4erez, R.; Bajorath, J. Interpretation + adding noise. arXiv preprint arXiv:1706.03825 2017,\n(66) Pope, P.; Kolouri, + S.; Rostrami, M.; Martin, C.; Hoffmann, H. Discovering Molec-\nular Functional + Groups Using Graph Convolutional Neural Networks. 2018; https:\n//arxiv.org/abs/1812.00265.\n(67) + Jim\u00b4enez-Luna, J.; Skalic, M.; Weskamp, N.; Schneider, G. Coloring molecules + with ex-\nplainable artificial intelligence for preclinical relevance assessment. + Journal of Chem-\nical Information and Modeling 2021, 61, 1083\u20131094.\n(68) + Sanchez-Lengeling, B.; Wei, J.; Lee, B.; Reif, E.; Wang, P. Y.; Qian, W. W.; + Mc-\nCloskey, K.; Colwell, L.; Wiltschko, A. Evaluating Attribution for Graph + Neural\nNetworks. Proceedings of the 34th International Conference on Neural + Information\nProcessing Systems. Red Hook, NY, USA, 2020.\n31\n(69) Ying, R.; + Bourgeois, D.; You, J.; Zitnik, M.; Leskovec, J. GNNExplainer: Generating\nExplanations + for Graph Neural Networks. Advances in neural information processing\nsystems + 2019, 32, 9240\u20139251.\n(70) Rao, J.; Zheng, S.; Yang, Y. Quantitative Evaluation + of Explainable Graph Neural\nNetworks for Molecular Property Prediction. arXiv + preprint arXiv:2107.04119 2021,\n(71) Yuan, H.; Yu, H.; Wang, J.; Li, K.; Ji, + S. On Explainability of Graph Neural Net-\nworks via Subgraph Explorations. + Proceedings of the 38th International Conference\non Machine Learning. 2021; + pp 12241\u201312252.\n(72) Shrikumar, A.; Greenside, P.; Kundaje, A. Learning + Important Features Through\nPropagating Activation Differences. 2017,\n(73) + Montavon, G.; Binder, A.; Lapuschkin, S.; Samek, W.; M\u00a8uller, K. R. Layer-Wise\nRelevance + Propagation: An Overview. Lecture Notes in Computer Science (including\nsubseries + Lecture Notes in Artificial Intelligence and Lecture Notes in Bioinformatics)\n2019, + 11700 LNCS, 193\u2013209.\n(74) Baldassarre, F.; Azizpour, H. Explainability + Techniques for Graph Convolutional Net-\nworks. 2019; https://arxiv.org/abs/1905.13686.\n(75) + Hochuli, J.; Helbling, A.; Skaist, T.; Ragoza, M.; Koes, D. R. Visualizing convolutional\nneural + network protein-ligand scoring. Journal of Molecular Graphi", "ty Techniques + for Graph Convolutional Net-\nworks. 2019; https://arxiv.org/abs/1905.13686.\n(75) + Hochuli, J.; Helbling, A.; Skaist, T.; Ragoza, M.; Koes, D. R. Visualizing convolutional\nneural + network protein-ligand scoring. Journal of Molecular Graphics and Modelling\n2018, + 84, 96\u2013108.\n(76) Rodr\u00b4\u0131guez-P\u00b4erez, R.; Bajorath, J. Interpretation of Compound Activity Predictions\nfrom Complex Machine Learning Models Using Local Approximations and Shapley\nValues. Journal of Medicinal Chemistry 2020, 63, 8761\u20138777, PMID: 31512867.\n(77) Wojtuch, A.; Jankowski, R.; Podlewska, @@ -2709,16 +945,15 @@ interactions: Bond-Centric Shapley Value-Based Explanation Method for Graph Neural\nNetworks. iScience 2022, 25, 105043.\n(79) White, A. D. Deep learning for molecules and materials. Living Journal of Computa-\ntional Molecular Science 2022, 3.\n(80) - \u02d8Strumbelj, E.; Kononenko, I. Explaining prediction models and individ", - "lecular Science 2022, 3.\n(80) \u02d8Strumbelj, E.; Kononenko, I. Explaining - prediction models and individual predictions\nwith feature contributions. Knowledge - and Information Systems 2014, 41, 647\u2013665.\n(81) Erhan, D.; Bengio, Y.; - Courville, A.; Vincent, P. Visualizing Higher-Layer Features of\na Deep Network. - Technical Report, Univerist\u00b4e de Montr\u00b4eal 2009,\n(82) Weber, J. K.; - Morrone, J. A.; Bagchi, S.; Pabon, J. D.; gu Kang, S.; Zhang, L.;\nCornell, - W. D. Simplified, interpretable graph convolutional neural networks for small\nmolecule - activity prediction. Journal of Computer-Aided Molecular Design 2022, 36,\n391\u2013404.\n(83) - Riniker, S.; Landrum, G. A. Similarity maps - A visualization strategy for molecular\nfingerprints + \u02d8Strumbelj, E.; Kononenko, I. Explaining prediction models and individual + predictions\nwith feature contributions. Knowledge and Information Systems 2014, + 41, 647\u2013665.\n(81) Erhan, D.; Bengio, Y.; Courville, A.; Vincent, P. Visualizing + Higher-Layer Features of\na Deep Network. Technical Report, Univerist\u00b4e + de Montr\u00b4eal 2009,\n(82) Weber, J. K.; Morrone, J. A.; Bagchi, S.; Pabon, + J. D.; gu Kang, S.; Zhang, L.;\nCornell, W. D. Simplified, interpretable graph + convolutional neural networks for small\nmolecule activity prediction. Journal + of Computer-Aided Molecular Design 2022, 36,\n391\u2013404.\n(83) Riniker, S.; + Landrum, G. A. Similarity maps - A visualization strategy for molecular\nfingerprints and machine-learning methods. Journal of Cheminformatics 2013, 5, 1\u20137.\n(84) Humer, C.; Heberle, H.; Montanari, F.; Wolf, T.; Huber, F.; Henderson, R.; Hein-\nrich, J.; Streit, M. ChemInformatics Model Explorer (CIME): exploratory analysis of\nchemical @@ -2748,12 +983,11 @@ interactions: M. Extended-Connectivity Fingerprints. Journal of Chemical In-\nformation and Modeling 2010, 50, 742\u2013754, PMID: 20426451.\n(98) Mohapatra, S.; An, J.; G\u00b4omez-Bombarelli, R. Chemistry-informed macromolecule\ngraph representation - for simila", ", S.; An, J.; G\u00b4omez-Bombarelli, R. Chemistry-informed macromolecule\ngraph - representation for similarity computation, unsupervised and supervised learn-\ning. - Machine Learning: Science and Technology 2022, 3, 015028.\n(99) Doshi-Velez, - F.; Kortz, M.; Budish, R.; Bavitz, C.; Gershman, S.; O\u2019Brien, D.;\nScott, - K.; Schieber, S.; Waldo, J.; Weinberger, D.; Weller, A.; Wood, A. Account-\nability - of AI Under the Law: The Role of Explanation. SSRN Electronic Journal\n2017,\n(100) + for similarity computation, unsupervised and supervised learn-\ning. Machine + Learning: Science and Technology 2022, 3, 015028.\n(99) Doshi-Velez, F.; Kortz, + M.; Budish, R.; Bavitz, C.; Gershman, S.; O\u2019Brien, D.;\nScott, K.; Schieber, + S.; Waldo, J.; Weinberger, D.; Weller, A.; Wood, A. Account-\nability of AI + Under the Law: The Role of Explanation. SSRN Electronic Journal\n2017,\n(100) Wachter, S.; Mittelstadt, B.; Russell, C. Counterfactual explanations without opening\nthe black box: Automated decisions and the GDPR. Harv. JL & Tech. 2017, 31, 841.\n(101) Jim\u00b4enez-Luna, J.; Grisoni, F.; Schneider, G. Drug discovery @@ -2762,6 +996,9 @@ interactions: C. W.; Sun, J. Differentiable Scaffold-\ning Tree for Molecule Optimization. International Conference on Learning Represen-\ntations. 2022.\n(103) Shen, C.; Krenn, M.; Eppel, S.; Aspuru-Guzik, A. Deep molecular dreaming: inverse\nmachine + learning ", "Coley, C. W.; Sun, J. Differentiable Scaffold-\ning Tree for Molecule + Optimization. International Conference on Learning Represen-\ntations. 2022.\n(103) + Shen, C.; Krenn, M.; Eppel, S.; Aspuru-Guzik, A. Deep molecular dreaming: inverse\nmachine learning for de-novo molecular design and interpretability with surjective\nrepresentations. Machine Learning: Science and Technology 2021, 2, 03LT02.\n(104) Lucic,\nA.;\nter\nHoeve,\nM.;\nTolomei,\nG.;\nRijke,\nM.;\nSilvestri,\nF.\nCF-\nGNNExplainer:\nCounterfactual Explanations for Graph Neural Networks. arXiv\npreprint arXiv:2102.03322 2021,\n(105) @@ -2785,18 +1022,17 @@ interactions: N.; Wistuba, M.; Schmidt-Thieme, L. Learning time-series\nshapelets. Proceedings of the 20th ACM SIGKDD international conference on Knowl-\nedge discovery and data mining. 2014; pp 392\u2013401.\n(112) Kenny, P. W.; Sadowski, J. Structure - modification in ch", "ery and data mining. 2014; pp 392\u2013401.\n(112) Kenny, - P. W.; Sadowski, J. Structure modification in chemical databases. Chemoin-\nformatics - in drug discovery 2005, 271\u2013285.\n(113) Tyrchan, C.; Evertsson, E. Matched - Molecular Pair Analysis in Short: Algorithms,\nApplications and Limitations. - Computational and Structural Biotechnology Journal\n2017, 15, 86\u201390.\n36\n(114) - Griffen, E.; Leach, A. G.; Robb, G. R.; Warner, D. J. Matched Molecular Pairs - as\na Medicinal Chemistry Tool. Journal of Medicinal Chemistry 2011, 54, 7739\u20137750,\nPMID: - 21936582.\n(115) He, J.; Nittinger, E.; Tyrchan, C.; Czechtizky, W.; Patronov, - A.; Bjerrum, E. J.;\nEngkvist, O. Transformer-based molecular optimization beyond - matched molecular\npairs. Journal of cheminformatics 2022, 14, 1\u201314.\n(116) - Park, J.; Sung, G.; Lee, S.; Kang, S.; Park, C. ACGCN: Graph Convolutional Networks\nfor - Activity Cliff Prediction between Matched Molecular Pairs. Journal of Chemical\nInformation + modification in chemical databases. Chemoin-\nformatics in drug discovery 2005, + 271\u2013285.\n(113) Tyrchan, C.; Evertsson, E. Matched Molecular Pair Analysis + in Short: Algorithms,\nApplications and Limitations. Computational and Structural + Biotechnology Journal\n2017, 15, 86\u201390.\n36\n(114) Griffen, E.; Leach, + A. G.; Robb, G. R.; Warner, D. J. Matched Molecular Pairs as\na Medicinal Chemistry + Tool. Journal of Medicinal Chemistry 2011, 54, 7739\u20137750,\nPMID: 21936582.\n(115) + He, J.; Nittinger, E.; Tyrchan, C.; Czechtizky, W.; Patronov, A.; Bjerrum, E. + J.;\nEngkvist, O. Transformer-based molecular optimization beyond matched molecular\npairs. + Journal of cheminformatics 2022, 14, 1\u201314.\n(116) Park, J.; Sung, G.; Lee, + S.; Kang, S.; Park, C. ACGCN: Graph Convolutional Networks\nfor Activity Cliff + Prediction between Matched Molecular Pairs. Journal of Chemical\nInformation and Modeling 2022,\n(117) Langdon, S. R.; Ertl, P.; Brown, N. Bioisosteric Replacement and Scaffold Hopping\nin Lead Generation and Optimization. Molecular Informatics 2010, 29, 366\u2013385.\n(118) Turk, S.; Merget, B.; Rippmann, F.; Fulle, S. @@ -2822,8 +1058,10 @@ interactions: Journal of cheminformatics 2018, 10, 1\u201314.\n(127) Chollet, F., et al. Keras. https://keras.io, 2015.\n(128) Wager, T. T.; Chandrasekaran, R. Y.; Hou, X.; Troutman, M. D.; Verhoest, P. R.; Vil-\nlalobos, A.; Will, Y. Defining Desirable - Central Nervous System Drug Space through\nthe Alignment of Mo", "lobos, A.; - Will, Y. Defining Desirable Central Nervous System Drug Space through\nthe Alignment + Central Ner", "lator. Journal of cheminformatics 2018, 10, 1\u201314.\n(127) + Chollet, F., et al. Keras. https://keras.io, 2015.\n(128) Wager, T. T.; Chandrasekaran, + R. Y.; Hou, X.; Troutman, M. D.; Verhoest, P. R.; Vil-\nlalobos, A.; Will, Y. + Defining Desirable Central Nervous System Drug Space through\nthe Alignment of Molecular Properties, in Vitro ADME, and Safety Attributes. ACS\nChemical Neuroscience 2010, 1, 420\u2013434.\n(129) Ghose, A. K.; Herbertz, T.; Hudkins, R. L.; Dorsey, B. D.; Mallamo, J. P. Knowledge-\nBased, Central Nervous System @@ -2861,11 +1099,10 @@ interactions: molecular sciences 2019, 20, 3018.\n(142) Rowe, D. Aroma chemicals for savory flavors. Perfumer and Flavorist 1998, 23, 9\u201318.\n(143) Mallia, S.; Escher, F.; Schlichtherle-Cerny, H. Aroma-active compounds of butter: a\nreview. European - Food Research and Technology 2008, 226, 315", " H. Aroma-active compounds of - butter: a\nreview. European Food Research and Technology 2008, 226, 315\u2013325.\n(144) - Jelen, H.; Gracka, A. Characterization of aroma compounds: Structure, physico-\nchemical - and sensory properties. Flavour: From food to perception 2016, 126\u2013153.\n(145) - Licon, C. C.;\nBosc, G.;\nSabri, M.;\nMantel, M.;\nFournel, A.;\nBushdid, C.;\nGolebiowski, + Food Research and Technology 2008, 226, 315\u2013325.\n(144) Jelen, H.; Gracka, + A. Characterization of aroma compounds: Structure, physico-\nchemical and sensory + properties. Flavour: From food to perception 2016, 126\u2013153.\n(145) Licon, + C. C.;\nBosc, G.;\nSabri, M.;\nMantel, M.;\nFournel, A.;\nBushdid, C.;\nGolebiowski, J.; Robardet, C.; Plantevit, M.; Kaytoue, M., et al. Chemical features\nmining provides new descriptive structure-odor relationships. PLoS computational bi-\nology 2019, 15, e1006945.\n(146) Mostafa, S.; Wang, Y.; Zeng, W.; Jin, B. Floral Scents @@ -2887,7 +1124,7 @@ interactions: connection: - keep-alive content-length: - - "26417" + - "77520" content-type: - application/json host: @@ -2909,965 +1146,1598 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/embeddings response: body: string: !!binary | - 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 + +HYmpmflAQA= headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c99afd945fa8a-SJC + - 8cd6e7e50dd0ce40-SJC Connection: - keep-alive Content-Encoding: @@ -3875,9 +2745,15 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:52 GMT + - Fri, 04 Oct 2024 17:31:29 GMT Server: - cloudflare + Set-Cookie: + - __cf_bm=LQzmO.CJXVU9oPjCFRLHGSwtp1LPFZV5N3gWjP2v8yU-1728063089-1.0.1.1-eA8TQD6kR3MnG9n8tq5zLjqiB71BJiXC1mNGGL8oWmousMLq9EbwDj4MbQ_OSJNfXsAHU_6wdPOAK_Cl4sgMeQ; + path=/; expires=Fri, 04-Oct-24 18:01:29 GMT; domain=.api.openai.com; HttpOnly; + Secure; SameSite=None + - _cfuvid=3XZL.OPrXE1Jhj20CoY4K5qtiqYQVgDNan2kthSSujU-1728063089762-0.0.1.1-604800000; + path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None Transfer-Encoding: - chunked X-Content-Type-Options: @@ -3893,7 +2769,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "145" + - "103" openai-version: - "2020-10-01" strict-transport-security: @@ -3905,13 +2781,13 @@ interactions: x-ratelimit-remaining-requests: - "9999" x-ratelimit-remaining-tokens: - - "9993623" + - "9981227" x-ratelimit-reset-requests: - 6ms x-ratelimit-reset-tokens: - - 38ms + - 112ms x-request-id: - - req_4e89305535ce42cb47774650cea16db5 + - req_f241e3370b343718f5db378b857eb632 status: code: 200 message: OK @@ -3949,126 +2825,127 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/embeddings response: body: string: !!binary | - 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 + /wAAAP//AwDgwOyj4CAAAA== headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c99b82fe6fa72-SJC + - 8cd6e7ef5f429834-SJC Connection: - keep-alive Content-Encoding: @@ -4076,7 +2953,7 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:53 GMT + - Fri, 04 Oct 2024 17:31:31 GMT Server: - cloudflare Transfer-Encoding: @@ -4094,7 +2971,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "32" + - "42" openai-version: - "2020-10-01" strict-transport-security: @@ -4112,64 +2989,89 @@ interactions: x-ratelimit-reset-tokens: - 0s x-request-id: - - req_7de2b85bdc15a7d05b7fedcfb8159af4 + - req_3be291de484ecf6003fe0d50b78d04d1 status: code: 200 message: OK - request: body: - '{"messages": [{"role": "system", "content": "Answer in a direct and concise - tone. Your audience is an expert, so be highly specific. If there are ambiguous - terms or acronyms, first define them."}, {"role": "user", "content": "Summarize - the excerpt below to help answer a question.\n\nExcerpt from wellawatteUnknownyearaperspectiveon - pages 14-15: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew - D. White. A perspective on explanations of molecular prediction models. Unknown - journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, doi:10.26434/chemrxiv-2022-qfv02.\n\n----\n\nlanations - are adversarial training and matched\nmolecular pairs. Adversarial perturbations - are used during training to deceive the model\nto expose the vulnerabilities - of a model109,110 whereas counterfactuals are applied post-hoc.\nTherefore, - the main difference between adversarial and counterfactual examples are in the\napplication, - although both are derived from the same optimization problem.100 Grabocka\net - al. 111 have developed a method named Adversarial Training on EXplanations (ATEX)\nwhich - improves model robustness via exposure to adversarial examples. While there - are\nconceptual disparities, we note that the counterfactual and adversarial - explanations are\nequivalent mathematical objects.\nMatched molecular pairs - (MMPs) are pairs of molecules that differ structurally at only\none site by - a known transformation.112,113 MMPs are widely used in drug discovery and\nmedicinal - chemistry as these facilitate fast and easy understanding of structure-activity - re-\nlationships.114\u2013116 Counterfactuals and MMP examples intersect if - the structural change is\nassociated with a significant change in the properties. - In the case the associated changes in\nthe properties are non-significant, the - two molecules are known as bioisosteres.117,118 The con-\nnection between MMPs - and adversarial training examples has been explored by van Tilborg\net al. 119. - MMPs which belong to the counterfactual category are commonly used in outlier\nand - activity cliff detection.113 This approach is analogous to counterfactual explanations,\nas - the common objective is to uncover learned knowledge pertaining to structure-property\nrelationships.70\nApplications\nModel - interpretation is certainly not new and a common step in ML in chemistry, but - XAI for\nDL models is becoming more important60,66\u201369,73,88,104,105 Here - we illustrate some practical\nexamples drawn from our published work on how - model-agnostic XAI can be utilized to\n14\ninterpret black-box models and connect - the explanations to structure-property relationships.\nThe methods are \u201cMolecular - Model Agnostic Counterfactual Explanations\u201d (MMACE)9\nand \u201cExplaining - molecular properties with natural language\u201d.10 Then we demonstrate how\ncounterfactuals - and descriptor explanations can propose structure-property relationships in\nthe - domain of molecular scent.31\nBlood-brain barrier permeation prediction\nThe - passive diffusion of drugs from the blood stream to the brain is a critical - aspect in drug\ndevelopment and discovery.120 Small molecule blood-brain barrier - (BBB) permeation is a\nclassification problem routinely assessed with DL models.121,122 - To explain why DL models\nwork, we trained two models a random forest (RF) model123 - and a Gated Recurrent Unit\nRecurrent Neural Network (GRU-RNN). Then we explained - the RF model with generated\ncounterfactuals explanations using the MMACE9 and - the GRU-RNN with descriptor expla-\nnations.10 Both the models were trained - on the dataset developed by Martins et al. 124. The\nRF model was implemented - in Scikit-learn125 usi\n\n----\n\nQuestion: Are counterfactuals actionable? - [yes/no]\n\nDo not directly answer the question, instead summarize to give evidence - to help answer the question. Stay detailed; report specific numbers, equations, - or direct quotes (marked with quotation marks). Reply \"Not applicable\" if - the excerpt is irrelevant. At the end of your response, provide an integer score - from 1-10 on a newline indicating relevance to question. Do not explain your - score.\n\nRelevant Information Summary (about 100 words):"}], "model": "gpt-4o-2024-08-06", - "stream": false, "temperature": 0.0}' + '{"messages": [{"role": "system", "content": "Provide a summary of the relevant + information that could help answer the question based on the excerpt. Respond + with the following JSON format:\n\n{\n \"summary\": \"...\",\n \"relevance_score\": + \"...\"\n}\n\nwhere `summary` is relevant information from text - about 100 + words words and `relevance_score` is the relevance of `summary` to answer question + (out of 10).\n"}, {"role": "user", "content": "Excerpt from wellawatteUnknownyearaperspectiveon + pages 10-13: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew + D. White. A perspective on explanations of molecular prediction models. Journal + of Chemical Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\n----\n\nth chemically interpretable descriptors. + This approach is similar\nto the concept-based explanations approach used by + McGrath et al. 85, where human under-\nstandable concepts were used in place + of input features in acquisition of chess knowledge in\nAlphaZero. Any of the + self-explaining models detailed in the Self-explaining models section\ncan be + used as a surrogate model.\nThe most commonly used surrogate model based method + is Locally Interpretable Model\nExplanations (LIME).35 LIME creates perturbations + around the example of interest and fits\nan interpretable model to these local + perturbations. Ribeiro et al. 35 mathematically define\nan explanation \u03be + for an example \u20d7x using Equation 4.\n\u03be(\u20d7x) = arg min\ng\u2208G + L(f, g, \u03c0x) + \u2126(g)\n(4)\nHere f is the black box model and g \u2208G + is the interpretable explanation model. G is\na class of potential interpretable + models (e.g.: linear models). \u03c0x is a similarity measure\n10\nbetween original + input \u20d7x and it\u2019s perturbed input \u20d7x\u2032. In context of molecular + data, this can\nbe a chemical similarity metric like Tanimoto86 similarity between + fingerprints. The goal for\nLIME is to minimize the loss, L, such that f is + closely approximated by g. \u2126is a parameter\nthat controls the complexity + (sparsity) of g. Ribeiro et al. 35 termed the agreement (how low\nthe loss is) + between f and g as the \u201cfidelity\u201d.\nGraphLIME87 and LIMEtree88 are + modifications to LIME as applicable to graph neural\nnetworks and regression + trees, respectively. LIME has been used in chemistry previously,\nsuch as Whitmore + et al. 89 who used LIME to explain octane number predictions of molecules\nfrom + a random forest classifier. Mehdi and Tiwary 90 used LIME to explain thermodynamic\ncontributions + of features. Gandhi and White 10 use an approach similar to GraphLIME,\nbut + use chemistry specific fragmentation and descriptors to explain molecular property + pre-\ndiction.\nSome examples are highlighted in the Applications section.\nIn + recent work by\nMehdi and Tiwary 90, a thermodynamic-based surrogate model approach + was used to inter-\npret black-box models. The authors define an \u201cinterpretation + free energy\u201d which can be\nachieved by minimizing the surrogate model\u2019s + uncertainty and maximizing simplicity.\nCounterfactual explanations\nCounterfactual + explanations can be found in many fields such as statistics, mathematics and\nphilosophy.91\u201394 + According to Woodward and Hitchcock 92, a counterfactual is an example\nwith + minimum deviation from the initial instance but with a contrasting outcome. + They\ncan be used to answer the question, \u201cwhich smallest change could + alter the outcome of an\ninstance of interest?\u201d While the difference between + the two instances is based on the exis-\ntence of similar worlds in philosophy,95 + a distance metric based on molecular similarity is\nemployed in XAI for chemistry. + For example, in the work by Wellawatte et al. 9 distance\nbetween two molecules + is defined as the Tanimoto distance96 between ECFP4 fingerprints.97\nAdditionally, + Mohapatra et al. 98 introduced a chemistry-informed graph representation for\ncomputing + macromolecular similarity. Contrastive explanations are peripheral to counterfac-\n11\ntual + explanations. Unlike the counterfactual approach, contrastive approach employ + a dual\noptimization method, which works by generating a similar and a dissimilar + (counterfactuals)\nexample. Contrastive explanations can interpret the model + by identifying contribution of\npresence and absence of subsets of features + towards a certain prediction.36,99\nA counterfactual x\u2032 of an instance + x is one with a dissimilar prediction \u02c6f(x) in classi-\nfication tasks. + As shown in equation 5, counterfactual generation can be thought of as a\nconstrained + optimization problem which minimizes the vector distance d(x, x\u2032) between + the\nfeatures.9,100\nminimize\nd(x, x\u2032)\nsuch that\n\u02c6f(x) \u0338= + \u02c6f(x\u2032)\n(5)\nFor regression tasks, equation 6 adapted from equation + 5 can be used. Here, a counter-\nfactual is one with a defined increase or decrease + in the prediction.\nminimize\nd(x, x\u2032)\nCounterfactuals explanations have + become a useful tool for XAI in chemistry, as they\nsuch that\n\f\f\f \u02c6f(x) + \u2212\u02c6f(x\u2032)\n\f\f\f \u2265\u2206\n(6)\nprovide intuitive understanding + of predictions and are able to uncover spurious relationships\nin training data.101 + Counterfactuals create local (instance-level), actionable explanations.\nActionability + of an explanation suggest which features can be altered to change the outcome.\nFor + example, changing a hydrophobic functional group in a molecule to a hydrophilic + group\nto increase solubility.\nCounterfactual generation is a demanding task + as it requires gradient optimization over\ndiscrete features that represents + a molecule. Recent work by Fu et al. 102 and Shen et al. 103\npresent two techniques + which allow continuous gradient-based optimization. Although, these\nmethodologies + are shown to circumvent the issue of discrete molecular optimization, counter-\nfactual + explanation based model interpretation still remains unexplored compared to + other\n12\npost-hoc methods.\nCF-GNNE\n\n----\n\nQuestion: Are counterfactuals + actionable? [yes/no]\n\n"}], "model": "gpt-4o-2024-08-06", "stream": false, + "temperature": 0.0}' headers: accept: - application/json @@ -4178,7 +3080,7 @@ interactions: connection: - keep-alive content-length: - - "4257" + - "6199" content-type: - application/json host: @@ -4200,30 +3102,29 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: !!binary | - H4sIAAAAAAAAAwAAAP//hFTBbhtHDL3rK4g9aw1JtmPFtzTHBmhSuKcmELgz1C7j2eF0yJWlBv73 - YEaK5DZIctGBb9+bx0dSX2YADfvmHho3oLkxhfbN27s/3l2v4+9P9OG3f/9699B9+HP/9H7f37rP - t828MKT7TM6+sa6cjCmQscQj7DKhUVFd3q3ubm6Xd8vrCoziKRRan6y9kXa1WN20i3W7eHUiDsKO - tLmHv2cAAF/qb7EYPe2be1jMv1VGUsWemvvzRwBNllAqDaqyGkZr5hfQSTSK1fXDQEB7RzkZeFY3 - qZKCDQSTEsgWnEzRKG/R2YRBgSOMEshNATOkTJ5daRdqQzqHgfshcD8Yx77ocIbi5cjzFICLXMpk - WHkYPajlydmUqU1ZEmU7QKZQcR04AUYMB2W9grf/c4OZAFMKTB6SqLWDuCpZAPpn4h0GigYmgH5H - WTEzBqA9ljkdu0EbaERjhwGM8qhX8DDQoUpMSr6Qiy9R+pVTnUPCbFzTCYciX6L0MiLHkuYlOnUU - bX72yrFIjxQNS0RA+xSQYwnxGNslap2DTm4AVOiCiG+7XNQ7zJkpQ6I8UnVU+/jJHF+88TQcwBMl - CIT58qrCk+RH0KnvSa3uxQEcxpLHjj0BVkfY1QFrGXtRNjmZ7mjAHUuubXpyrCyxHfGxvJCyOCrr - 9n1oPk99XUfZUT6c2DsKkkpCUPd3b3r1MX6M65ebnWk7KZbDilMIp/rz+VSC9ClLpyf8XN9yZB02 - mVAllrNQk9RU9HkG8Kme5PSfK2tSljHZxuSRYhFcv14d9ZrLn8AFXS7XJ9TEMLwAFsvFj3gbT4Yc - 9MVpN0ePHPuLxOJstHba6EGNxs2WY18ujY+Xvk2b1fZm8ap7vVxeN7Pn2VcAAAD//wMAO9coUvIE - AAA= + H4sIAAAAAAAAA2xTTW/bMAy951cQOm1AEjgfzZrcim7FigIFuu1QYB4SRaZttrLoSVTWoMh/HxSn + aYr2Yhh85CPfI/XcA1BUqAUoU2sxTWsHF9+qH99n67vbq6/x5uf9LLucj725Pbu6u5n+Vf1UwesH + NPJSNTTctBaF2HWw8agFE+voy/g8m02y+WgPNFygTWVVK4MpD8bZeDrIzgfZ7FBYMxkMagG/ewAA + z/tvGtEV+KQWkPVfIg2GoCtUi2MSgPJsU0TpECiIdqL6r6BhJ+j2U69Wq4fALnfPuQPIVYhNo/02 + VwvI1SVHJ+hLbSRqC/jUWu10UhdAewRt0r9eWwQdQGrcQut5QwUCOYkktEGIrkCfRijIVcAltB4L + MgcWV0CIVYVB4F9NpoYStUSPAYx2sEbQVtBjAcJgau0qTH2AoxhucAhX7AGfdHK93yWkLhrqbeG5 + rXlNBsroukEtVJ5jC+RAQ8MWTbSYmI/5ZMkckoSBXNpfQAhs45osyXYIv2oKR+X7GJAryGjB5IEW + MG9s65RUMbnScEFlSt2LT41NTbhBKDBQUtlJDGnCE5v60OjHpEtqbEBDDFhGC8Jsodwb0FpN3SIu + ruHT/cX150RhamwoiN8Oc9Xv9uvR4kY7g8tg2GO351GWq9ztcrdarU7vxGMZg05n6qK1h/jueHiW + q9bzOhzwY7wkR6FeJuvYpSMLwq3ao7sewJ/9gcc3N6taz00rS+FHdIlwNJnOO0L1+qZO4Gx6QIVF + 2xNgejbpf0C5LFA02XDySpTRpsbitTbrneh73/Yjik4jueodS+/ApMI2CDbLklyFvvXUvbuyXY7L + aTZbz0ejiertev8BAAD//wMAvEAUjIAEAAA= headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c99b9dc83176d-SJC + - 8cd6e7f11a07cf0e-SJC Connection: - keep-alive Content-Encoding: @@ -4231,14 +3132,14 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:54 GMT + - Fri, 04 Oct 2024 17:31:32 GMT Server: - cloudflare Set-Cookie: - - __cf_bm=YSN79BcRAveJFGvOqV0R_nweoIuBpBSKTY3paJSWtWU-1727451714-1.0.1.1-6qdk2Jk4a0ZuH2ztuLubayTecZmIRiBA3RAWNl_o1zd7RytTwvzZ0sv4XI4iMgLk7fgDsBQSfmzLY1qs.CD0QQ; - path=/; expires=Fri, 27-Sep-24 16:11:54 GMT; domain=.api.openai.com; HttpOnly; + - __cf_bm=X_6CTI5QOy8D5vMPHCCreKMsZK0cQn6_Fy9l22nDYM8-1728063092-1.0.1.1-JllMGlg5aN9Xv1Mh9eIt9LQHi8oopiLHR60VVFgi7HonjLNQ6bxFH3UCDRCkw1KyjcTB7uk5d9r_myXhTltMuw; + path=/; expires=Fri, 04-Oct-24 18:01:32 GMT; domain=.api.openai.com; HttpOnly; Secure; SameSite=None - - _cfuvid=nxb3prQChp_2F.4JnUZS09dFvJKTYYCKn_T8JvX.EMM-1727451714959-0.0.1.1-604800000; + - _cfuvid=wT9kW1J6OW1eEmiXJLZ43hxxzjf10cuTifU0rDFyZ0Q-1728063092705-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None Transfer-Encoding: - chunked @@ -4251,7 +3152,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "1165" + - "1103" openai-version: - "2020-10-01" strict-transport-security: @@ -4263,70 +3164,94 @@ interactions: x-ratelimit-remaining-requests: - "9998" x-ratelimit-remaining-tokens: - - "29998973" + - "29998384" x-ratelimit-reset-requests: - - 9ms + - 11ms x-ratelimit-reset-tokens: - - 2ms + - 3ms x-request-id: - - req_8c4faba466f21bb9b8a0617e29284dab + - req_1b4811a1b5a9c65e082b0034ad107050 status: code: 200 message: OK - request: body: - '{"messages": [{"role": "system", "content": "Answer in a direct and concise - tone. Your audience is an expert, so be highly specific. If there are ambiguous - terms or acronyms, first define them."}, {"role": "user", "content": "Summarize - the excerpt below to help answer a question.\n\nExcerpt from wellawatteUnknownyearaperspectiveon - pages 35-36: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew - D. White. A perspective on explanations of molecular prediction models. Unknown - journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, doi:10.26434/chemrxiv-2022-qfv02.\n\n----\n\n, - S.; An, J.; G\u00b4omez-Bombarelli, R. Chemistry-informed macromolecule\ngraph - representation for similarity computation, unsupervised and supervised learn-\ning. - Machine Learning: Science and Technology 2022, 3, 015028.\n(99) Doshi-Velez, - F.; Kortz, M.; Budish, R.; Bavitz, C.; Gershman, S.; O\u2019Brien, D.;\nScott, - K.; Schieber, S.; Waldo, J.; Weinberger, D.; Weller, A.; Wood, A. Account-\nability - of AI Under the Law: The Role of Explanation. SSRN Electronic Journal\n2017,\n(100) - Wachter, S.; Mittelstadt, B.; Russell, C. Counterfactual explanations without - opening\nthe black box: Automated decisions and the GDPR. Harv. JL & Tech. 2017, - 31, 841.\n(101) Jim\u00b4enez-Luna, J.; Grisoni, F.; Schneider, G. Drug discovery - with explainable artificial\nintelligence. Nature Machine Intelligence 2020 - 2:10 2020, 2, 573\u2013584.\n(102) Fu, T.; Gao, W.; Xiao, C.; Yasonik, J.; Coley, - C. W.; Sun, J. Differentiable Scaffold-\ning Tree for Molecule Optimization. - International Conference on Learning Represen-\ntations. 2022.\n(103) Shen, - C.; Krenn, M.; Eppel, S.; Aspuru-Guzik, A. Deep molecular dreaming: inverse\nmachine - learning for de-novo molecular design and interpretability with surjective\nrepresentations. - Machine Learning: Science and Technology 2021, 2, 03LT02.\n(104) Lucic,\nA.;\nter\nHoeve,\nM.;\nTolomei,\nG.;\nRijke,\nM.;\nSilvestri,\nF.\nCF-\nGNNExplainer:\nCounterfactual - Explanations for Graph Neural Networks. arXiv\npreprint arXiv:2102.03322 2021,\n(105) - Numeroso, D.; Bacciu, D. Explaining Deep Graph Networks with Molecular Counter-\nfactuals. - arXiv preprint arXiv:2011.05134 2020,\n35\n(106) Krenn, M.; H\u00a8ase, F.; - Nigam, A.; Friederich, P.; Aspuru-Guzik, A. Self-Referencing\nEmbedded Strings - (SELFIES): A 100% robust molecular string representation. Ma-\nchine Learning: - Science and Technology 2020, 1, 045024.\n(107) Nigam, A.; Pollice, R.; Krenn, - M.; dos Passos Gomes, G.; Aspuru-Guzik, A. Beyond\ngenerative models: superfast - traversal, optimization, novelty, exploration and discov-\nery (STONED) algorithm - for molecules using SELFIES. Chemical science 2021, 12,\n7079\u20137090.\n(108) - Kim, S.; Chen, J.; Cheng, T.; Gindulyte, A.; He, J.; He, S.; Li, Q.; Shoemaker, - B. A.;\nThiessen, P. A.; Yu, B.; Zaslavsky, L.; Zhang, J.; Bolton, E. E. PubChem - in 2021:\nnew data content and improved web interfaces. Nucleic Acids Research - 2020, 49,\nD1388\u2013D1395.\n(109) Tolomei, G.; Silvestri, F.; Haines, A.; - Lalmas, M. Interpretable predictions of tree-\nbased ensembles via actionable - feature tweaking. Proceedings of the 23rd ACM\nSIGKDD international conference - on knowledge discovery and data mining. 2017;\npp 465\u2013474.\n(110) Freiesleben, - T. The intriguing relation between counterfactual explanations and ad-\nversarial - examples. Minds and Machines 2022, 32, 77\u2013109.\n(111) Grabocka, J.; Schilling, - N.; Wistuba, M.; Schmidt-Thieme, L. Learning time-series\nshapelets. Proceedings - of the 20th ACM SIGKDD international conference on Knowl-\nedge discovery and - data mining. 2014; pp 392\u2013401.\n(112) Kenny, P. W.; Sadowski, J. Structure - modification in ch\n\n----\n\nQuestion: Are counterfactuals actionable? [yes/no]\n\nDo - not directly answer the question, instead summarize to give evidence to help - answer the question. Stay detailed; report specific numbers, equations, or direct - quotes (marked with quotation marks). Reply \"Not applicable\" if the excerpt - is irrelevant. At the end of your response, provide an integer score from 1-10 - on a newline indicating relevance to question. Do not explain your score.\n\nRelevant - Information Summary (about 100 words):"}], "model": "gpt-4o-2024-08-06", "stream": - false, "temperature": 0.0}' + '{"messages": [{"role": "system", "content": "Provide a summary of the relevant + information that could help answer the question based on the excerpt. Respond + with the following JSON format:\n\n{\n \"summary\": \"...\",\n \"relevance_score\": + \"...\"\n}\n\nwhere `summary` is relevant information from text - about 100 + words words and `relevance_score` is the relevance of `summary` to answer question + (out of 10).\n"}, {"role": "user", "content": "Excerpt from wellawatteUnknownyearaperspectiveon + pages 3-6: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew D. + White. A perspective on explanations of molecular prediction models. Journal + of Chemical Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\n----\n\nccuracy and interpretability are two + attractive characteristics of DL models. However,\nDL models are often highly + accurate and less interpretable.28,30 XAI provides a way to avoid\nthat trade-off + in chemical property prediction. XAI can be viewed as a two-step process.\nFirst, + we develop an accurate but uninterpretable DL model. Next, we add explanations + to\npredictions. Ideally, if the DL model has correctly learned the input-output + relations, then\nthe explanations should give insight into the underlying mechanism.\nIn + the remainder of this article, we review recent approaches for XAI of chemical + property\nprediction while drawing specific examples from our recent XAI work.9,10,31 + We show how\nin various systems these methods yield explanations that are consistent + with known and\nmechanisms in structure-property relationships.\n3\nTheory\nIn + this work, we aim to assemble a common taxonomy for the landscape of XAI while\nproviding + our perspectives. We utilized the vocabulary proposed by Das and Rad 32 to classify\nXAI. + According to their classification, interpretations can be categorized as global + or local\ninterpretations on the basis of \u201cwhat is being explained?\u201d. + For example, counterfactuals are\nlocal interpretations, as these can explain + only a given instance. The second classification is\nbased on the relation between + the model and the interpretation \u2013 is interpretability post-hoc\n(extrinsic) + or intrinsic to the model?.32,33 An intrinsic XAI method is part of the model\nand + is self-explanatory32 These are also referred to as white-box models to contrast + them\nwith non-interpretable black box models.28 An extrinsic method is one + that can be applied\npost-training to any model.33 Post-hoc methods found in + the literature focus on interpreting\nmodels through 1) training data34 and + feature attribution,35 2) surrogate models10 and, 3)\ncounterfactual9 or contrastive + explanations.36\nOften, what is a \u201cgood\u201d explanation and what are + the required components of an ex-\nplanation are debated.32,37,38 Palacio et + al. 29 state that the lack of a standard framework\nhas caused the inability + to evaluate the interpretability of a model. In physical sciences,\nwe may instead + consider if the explanations somehow reflect and expand our understanding\nof + physical phenomena. For example, Oviedo et al. 39 propose that a model explanation\ncan + be evaluated by considering its agreement with physical observations, which + they term\n\u201ccorrectness.\u201d For example, if an explanation suggests + that polarity affects solubility of a\nmolecule, and the experimental evidence + strengthen the hypothesis, then the explanation\nis assumed \u201ccorrect\u201d. + In instances where such mechanistic knowledge is sparse, expert bi-\nases and + subjectivity can be used to measure the correctness.40 Other similar metrics + of\ncorrectness such as \u201cexplanation satisfaction scale\u201d can be found + in the literature.41,42 In a\nrecent study, Humer et al. 43 introduced CIME + an interactive web-based tool that allows the\nusers to inspect model explanations. + The aim of this study is to bridge the gap between\nanalysis of XAI methods. + Based on the above discussion, we identify that an agreed upon\n4\nevaluation + metric is necessary in XAI. We suggest the following attributes can be used + to\nevaluate explanations. However, the relative importance of each attribute + may depend on\nthe application - actionability may not be as important as faithfulness + when evaluating the\ninterpretability of a static physics based model. Therefore, + one can select relative importance\nof each attribute based on the application.\n\u2022 + Actionable. Is it clear how we could change the input features to modify the + output?\n\u2022 Complete. Does the explanation completely account for the prediction? + Did features\nnot included in the explanation really contribute zero effect + to the prediction?44\n\u2022 Correct. Does the explanation agree with hypothesized + or known underlying physical\nmechanism?39\n\u2022 Domain Applicable. Does the + explanation use language and concepts of domain ex-\nperts?\n\u2022 Fidelity/Faithful. + Does the explanation agree with the black box model?\n\u2022 Robust. Does the + explanation change significantly with small changes to the model or\ninstance + being explained?\n\u2022 Sparse/Succinct. Is the explanation succinct?\nWe present + an example evaluation of the SHAP explanation method based on the above\nattributes.44 + Shapley values were proposed as a local explanation method based on feature\nattribution, + as they offer a complete explanation - each feature is assigned a fraction of\nthe + prediction value.44,45 Completeness is a clearly measurable and well-defined + metric, but\nyields explanations with many components. Yet Shapley values are + not actionable nor sparse.\nThey are non-sparse as every feature has a non-zero + attribution and not-actionable because\nthey do not provide a set of features + which changes the outcome.46 Ribeiro et al. 35 proposed\na surrogate model method + that aims to provide sparse/succinct explanations that have high\n5\nfidelity + to the original model. I\n\n----\n\nQuestion: Are counterfactuals actionable? + [yes/no]\n\n"}], "model": "gpt-4o-2024-08-06", "stream": false, "temperature": + 0.0}' headers: accept: - application/json @@ -4335,7 +3260,7 @@ interactions: connection: - keep-alive content-length: - - "4294" + - "6082" content-type: - application/json host: @@ -4357,30 +3282,30 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: !!binary | - H4sIAAAAAAAAAwAAAP//fFRdaxsxEHz3r1juocRgG9txa8dv+aAh0KYmLbTQFLPW7d1topNUaS+x - CfnvRTrHuVKal3vY0Y5mZrX31APIOM+WkKkKRdVOD0/P518+Vxer4mz14/eNvTu/2u5OZpvxttjt - zrJB7LCbO1Ly0jVStnaahK1pYeUJhSLrZD6dz95P5pNZAmqbk45tpZPhzA6n4+lsOF4Mxx/2jZVl - RSFbws8eAMBT+kaJJqdttoTx4KVSUwhYUrY8HALIvNWxkmEIHASNZINXUFkjZJLqbxUBbRV5J+Cp - IE9GUYBAD+RRw6P19wE86egCxIKyjRHyBSppUANtnUaD0XAYwGPFqgL0BAg1SWVzKKwH5+0D52xK - 4NjrPAluWLPsgA2cXkEKI4zgqyPFBSvUejeA76gqIQ8kgHoER9PxZN6HnINqQnhLSGSViiDZ3ArY - ArARWycPOSkO6RSaPB27JJO8XqAgrLwVUpEGbqhsdGKEo8uL1U1/AKEpSwoSrUhF7MHZGCSjhhh4 - vFhTiRpQJX17myP41ChWHSfTST/df93U5G2w8A7OUCluEjjuJz/W05s2Y7aXHl0F19REB9ckaWAD - YJOzwo5QdE6z6sTevtRtm/0/gxnBR09MQdOGTNI0jZqwZkMhpZbeRJRRsYMNySOReVNttIv5A/mA - nhOIUcHh2dS4A66d3gGm/DtahXwd4hhbsd5umiCGQkv6MtFhjfdsytGtuTWL7nP3VDQB47aZRut9 - /fmwP9qWzttN2OOHesGGQ7X2hMGauCtBrMsS+twD+JX2tPlr9TLnbe1kLfaeTCScTBYnLWH2+mvo - wMeLPSpWUHeB6fx/feucBFmHzsJnrUg25SvF+KA0Wc3CLgjV64JNGUfN7f4Xbk3vaXYyOabFcdZ7 - 7v0BAAD//wMAqvgEMwgFAAA= + H4sIAAAAAAAAAwAAAP//bFTBbts4EL37KwY8dQE7cOJsmvoWFAu0aPcS7AJFq4VNUSNpUorkcoa2 + tUH+vSBlJ96mFx3m8T2+eZzR4wxAUaPWoEyvxQzBLu7+6O4/vP8sYu///HTvHv7+0vp/P3VfkcLh + PzXPDF8/oJET68L4IVgU8m6CTUQtmFUv317dLm9Wy3eXBRh8gzbTuiCLa7+4Wl5dL5a3i+XNkdh7 + MshqDd9mAACP5ZstugYPag3L+akyILPuUK2fDwGo6G2uKM1MLNqJmr+AxjtBV1xvt9sH9q5yj5UD + qBSnYdBxrNQaKvXeJycYW20kacugI0KDbCLV2IBmsN5oC5QPhYiic+MM5EB6hHLLQcC3gIdgNTld + W4S7j/Dmy93H36D1EUyPA2WNEH3AKCOEiA2ZLAQlI76Av3ocy92JsQHxJznggIZaMkAu92iQoR6B + e78n10Hv92B67ToslsiFJNCilhSRwfhkG7Coi2JDbYsRnYBPYvyA07WAB4MxCDTEJjEjw05H8olB + i0SqkyAXRzttkxacrLkpiDmQMzY12YwuLemaLMk4h31PpoeILcbCL3lZHUnGnFe2/rNf7aDGY0PF + 8+AbasdC9UlCkgv44Pe4wzgvxRJ+45HBeSnGyJDYEViy032P0mPMQbx65JNbi3Ook2Q5iuCKlezv + FLG2gjF3u0Nggy5nw8Cp65CFM208Bl2XeWBqMObReda/qNR8mryIFnf5ETdsfMRpAm8rVbmnym23 + 2/MBjtgm1nl/XLL2WH963gjruxB9zUf8ud6SI+43ETV7l6efxQdV0KcZwD9l89L/lkmF6IcgG/Hf + 0WXBy6vV20lQvSz7OXxzRMWLtmfA6mY1/4XkpkHRZPlsfZXRpsfmhbucnfX3+tpfSUw9kuteqcyO + SopHFhw2Lbkury9NP4Q2bPB3vH53ucLblZo9zX4AAAD//wMASr9HuBkFAAA= headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c99b9dc8b252d-SJC + - 8cd6e7f11c651590-SJC Connection: - keep-alive Content-Encoding: @@ -4388,14 +3313,14 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:55 GMT + - Fri, 04 Oct 2024 17:31:33 GMT Server: - cloudflare Set-Cookie: - - __cf_bm=oRXIDnhMIwrzVuWU43TNLxwOtps1lCgWkFEvurOX1ec-1727451715-1.0.1.1-mYe5OriqH2nTJCHOfNKVGgnv_Lr814JMGAyRoBJTE1d0ErDbM6dRXFJP1DQGt4Jyj5X.gCKiPYGQka4gk.fuEw; - path=/; expires=Fri, 27-Sep-24 16:11:55 GMT; domain=.api.openai.com; HttpOnly; + - __cf_bm=CaIq93NFBCa23TNZhASv4rM7a5FjMv.nUpD1R98OsbQ-1728063093-1.0.1.1-q206n2QYHSydhTpd7E8Q.R9QU0QfX2BeFcPUnvIxqAPqrKSfWG7Qr6ocy2zkMrfe1F6_hVb9WFCnnZEHkXRPsQ; + path=/; expires=Fri, 04-Oct-24 18:01:33 GMT; domain=.api.openai.com; HttpOnly; Secure; SameSite=None - - _cfuvid=UZKF9DkEQdqSzH0GSGBBSxSSOZ6dijLj3FNJS3PYWj4-1727451715847-0.0.1.1-604800000; + - _cfuvid=Gwmp2YkyIIOQGybXdVRaH8VxCbl.OGV22IXzUDPQecg-1728063093028-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None Transfer-Encoding: - chunked @@ -4408,7 +3333,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "1746" + - "1446" openai-version: - "2020-10-01" strict-transport-security: @@ -4420,72 +3345,96 @@ interactions: x-ratelimit-remaining-requests: - "9999" x-ratelimit-remaining-tokens: - - "29998970" + - "29998533" x-ratelimit-reset-requests: - 6ms x-ratelimit-reset-tokens: - 2ms x-request-id: - - req_cca139d54c9ab4e71b0d78555087d24a + - req_974f2955fde982cf8979031e68c267c9 status: code: 200 message: OK - request: body: - '{"messages": [{"role": "system", "content": "Answer in a direct and concise - tone. Your audience is an expert, so be highly specific. If there are ambiguous - terms or acronyms, first define them."}, {"role": "user", "content": "Summarize - the excerpt below to help answer a question.\n\nExcerpt from wellawatteUnknownyearaperspectiveon - pages 11-12: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew - D. White. A perspective on explanations of molecular prediction models. Unknown - journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, doi:10.26434/chemrxiv-2022-qfv02.\n\n----\n\n) - between f and g as the \u201cfidelity\u201d.\nGraphLIME87 and LIMEtree88 are - modifications to LIME as applicable to graph neural\nnetworks and regression - trees, respectively. LIME has been used in chemistry previously,\nsuch as Whitmore - et al. 89 who used LIME to explain octane number predictions of molecules\nfrom - a random forest classifier. Mehdi and Tiwary 90 used LIME to explain thermodynamic\ncontributions - of features. Gandhi and White 10 use an approach similar to GraphLIME,\nbut - use chemistry specific fragmentation and descriptors to explain molecular property - pre-\ndiction.\nSome examples are highlighted in the Applications section.\nIn - recent work by\nMehdi and Tiwary 90, a thermodynamic-based surrogate model approach - was used to inter-\npret black-box models. The authors define an \u201cinterpretation - free energy\u201d which can be\nachieved by minimizing the surrogate model\u2019s - uncertainty and maximizing simplicity.\nCounterfactual explanations\nCounterfactual - explanations can be found in many fields such as statistics, mathematics and\nphilosophy.91\u201394 - According to Woodward and Hitchcock 92, a counterfactual is an example\nwith - minimum deviation from the initial instance but with a contrasting outcome. - They\ncan be used to answer the question, \u201cwhich smallest change could - alter the outcome of an\ninstance of interest?\u201d While the difference between - the two instances is based on the exis-\ntence of similar worlds in philosophy,95 - a distance metric based on molecular similarity is\nemployed in XAI for chemistry. - For example, in the work by Wellawatte et al. 9 distance\nbetween two molecules - is defined as the Tanimoto distance96 between ECFP4 fingerprints.97\nAdditionally, - Mohapatra et al. 98 introduced a chemistry-informed graph representation for\ncomputing - macromolecular similarity. Contrastive explanations are peripheral to counterfac-\n11\ntual - explanations. Unlike the counterfactual approach, contrastive approach employ - a dual\noptimization method, which works by generating a similar and a dissimilar - (counterfactuals)\nexample. Contrastive explanations can interpret the model - by identifying contribution of\npresence and absence of subsets of features - towards a certain prediction.36,99\nA counterfactual x\u2032 of an instance - x is one with a dissimilar prediction \u02c6f(x) in classi-\nfication tasks. - As shown in equation 5, counterfactual generation can be thought of as a\nconstrained - optimization problem which minimizes the vector distance d(x, x\u2032) between - the\nfeatures.9,100\nminimize\nd(x, x\u2032)\nsuch that\n\u02c6f(x) \u0338= - \u02c6f(x\u2032)\n(5)\nFor regression tasks, equation 6 adapted from equation - 5 can be used. Here, a counter-\nfactual is one with a defined increase or decrease - in the prediction.\nminimize\nd(x, x\u2032)\nCounterfactuals explanations have - become a useful tool for XAI in chemistry, as they\nsuch that\n\f\f\f \u02c6f(x) - \u2212\u02c6f(x\u2032)\n\f\f\f \u2265\u2206\n(6)\nprovide intuitive understanding - of predictions and are able to uncover spurious relationships\nin training data.101 - Counterfactuals create local (instance-level), actionable explan\n\n----\n\nQuestion: - Are counterfactuals actionable? [yes/no]\n\nDo not directly answer the question, - instead summarize to give evidence to help answer the question. Stay detailed; - report specific numbers, equations, or direct quotes (marked with quotation - marks). Reply \"Not applicable\" if the excerpt is irrelevant. At the end of - your response, provide an integer score from 1-10 on a newline indicating relevance - to question. Do not explain your score.\n\nRelevant Information Summary (about - 100 words):"}], "model": "gpt-4o-2024-08-06", "stream": false, "temperature": - 0.0}' + '{"messages": [{"role": "system", "content": "Provide a summary of the relevant + information that could help answer the question based on the excerpt. Respond + with the following JSON format:\n\n{\n \"summary\": \"...\",\n \"relevance_score\": + \"...\"\n}\n\nwhere `summary` is relevant information from text - about 100 + words words and `relevance_score` is the relevance of `summary` to answer question + (out of 10).\n"}, {"role": "user", "content": "Excerpt from wellawatteUnknownyearaperspectiveon + pages 18-21: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew + D. White. A perspective on explanations of molecular prediction models. Journal + of Chemical Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\n----\n\nEach data point is colored by solubility. + Top 4 counterfactuals are shown here.\nRepublished from Ref.9 with permission + from the Royal Society of Chemistry.\nGeneralizing XAI \u2013 interpreting scent-structure + relationships\nIn this example, we show how non-local structure-property relationships + can be learned with\nXAI across multiple molecules. Molecular scent prediction + is a multi-label classification task\nbecause a molecule can be described by + more than one scent. For example, the molecule\njasmone can be described as + having \u2018jasmine,\u2019 \u2018woody,\u2019 \u2018floral,\u2019 and \u2019herbal\u2019 + scents.139 The\nscent-structure relationship is not very well understood,140 + although some relationships are\nknown. For example, molecules with an ester + functional group are often associated with\n18\nFigure 4: Descriptor explanations + for solubility prediction model. The green and red bars\nshow descriptors that + influence predictions positively and negatively, respectively. Dotted\nyellow + lines show significance threshold (\u03b1 = 0.05) for the t-statistic. The MACCS + and\nECFP descriptors indicate which substructures influence model predictions. + MACCS sub-\nstructures may either be present in the molecule as is or may represent + a modification. ECFP\nfingerprints are substructures in the molecule that affect + the prediction. MACCS descriptor\nare used to obtain text explanations as shown. + Republished from Ref.10 with permission from\nauthors. SMARTS annotations for + MACCS descriptors were created using SMARTSviewer\n(smartsview.zbh.uni-hamburg.de, + Copyright: ZBH, Center for Bioinformatics Hamburg) de-\nveloped by Schomburg + et al. 132.\n19\nthe \u2018fruity\u2019 scent. There are some exceptions though, + like tert-amyl acetate which has a\n\u2018camphoraceous\u2019 rather than \u2018fruity\u2019 + scent.140,141\nIn Seshadri et al. 31, we trained a GNN model to predict the + scent of molecules and utilized\ncounterfactuals9 and descriptor explanations10 + to quantify scent-structure relationships. The\nMMACE method was modified to + account for the multi-label aspect of scent prediction. This\nmodification defines + molecules that differed from the instance molecule by only the selected\nscent + as counterfactuals. For instance, counterfactuals of the jasmone molecule would + be false\nfor the \u2018jasmine\u2019 scent but would still be positive for + \u2018woody,\u2019 \u2018floral\u2019 and \u2018herbal\u2019 scents.\nFigure + 5: Counterfactual for the 2,4 decadienal molecule.\nThe counterfactual indicates\nstructural + changes to ethyl benzoate that would result in the model predicting the molecule\nto + not contain the \u2018fruity\u2019 scent. The Tanimoto96 similarity between + the counterfactual and\n2,4 decadienal is also provided. Republished with permission + from authors.31\nThe molecule 2,4-decadienal, which is known to have a \u2018fatty\u2019 + scent, is analyzed in Fig-\nure 5.142,143 The resulting counterfactual, which + has a shorter carbon chain and no carbonyl\ngroups, highlights the influence + of these structural features on the \u2018fatty\u2019 scent of 2,4 deca-\ndienal. + To generalize to other molecules, Seshadri et al. 31 applied the descriptor + attribution\nmethod to obtain global explanations for the scents. The global + explanation for the \u2018fatty\u2019\nscent was generated by gathering chemical + spaces around many \u2018fatty\u2019 scented molecules.\nThe resulting natural + language explanation is: \u201cThe molecular property \u201cfatty scent\u201d + can\nbe explained by the presence of a heptanyl fragment, two CH2 groups separated + by four\n20\nbonds, and a C=O double bond, as well as the lack of more than + one or two O atoms.\u201d31\nThe importance of a heptanyl fragment aligns with + that reported in the literature, as \u2018fatty\u2019\nmolecules often have + a long carbon chain.144 Furthermore, the importance of a C=O dou-\nble bond + is supported by the findings reported by Licon et al. 145, where in addition + to a\n\u201clarger carbon-chain skeleton\u201d, they found that \u2018fatty\u2019 + molecules also had \u201caldehyde or acid\nfunctions\u201d.145 For the \u2018pineapple\u2019 + scent, the following natural language explanation was ob-\ntained: \u201cThe + molecular property \u201cpineapple scent\u201d can be explained by the presence + of ester,\nethyl/ether O group, alkene/ether O group, and C=O double bond, as + well as the absence of\nan Aromatic atom.\u201d31 Esters, such as ethyl 2-methylbutyrate, + are present in many pineap-\nple volatile compounds.146,147 The combination + of a C=O double bond with an ether could\nalso correspond to an ester group. + Additionally, aldehydes and ketones, which contain C=O\ndouble bonds, are also + common in pineapple volatile compounds.146,148\nDiscussion\nWe have shown two + post-hoc XAI applications based on molecular counterfactual expla-\nnations9 + and descriptor explanations.10 These methods can be used to explain black-box\nmodels + whose input is a molecule. These two methods can be applied for both classification\nand + regression tasks. Note that the \u201ccorrectness\u201d of the explanations + strongly depends on\nthe accuracy of the black-box model.\nA molecular counterfactual + is one with a minimal distance from a base molecular, but\nwith contrasting + chemical properties. In the above examples, we us\n\n----\n\nQuestion: Are counterfactuals + actionable? [yes/no]\n\n"}], "model": "gpt-4o-2024-08-06", "stream": false, + "temperature": 0.0}' headers: accept: - application/json @@ -4494,7 +3443,7 @@ interactions: connection: - keep-alive content-length: - - "4358" + - "6262" content-type: - application/json host: @@ -4516,30 +3465,29 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: !!binary | - H4sIAAAAAAAAAwAAAP//dFRNbxs5DL37VxC6NAHswHbSfN2CNNgWWKAosIdd7BSGLHFm2Gioqchx - nE3z3xfSOLZ7yGWA4RMfHx9FvUwADHlzC8a1Vl3Xh9nd/dXXP+t/muj/uP72dfPz20Pnrp/uPz8t - P2+8meaMuP6BTt+yzlzs+oBKkUfYJbSKmXVxtby6+Li4WpwXoIseQ05rep1dxNlyvryYza9n88td - YhvJoZhb+HcCAPBSvlkie9yaW5hP3yIditgGze3+EIBJMeSIsSIkalnN9AC6yIpcVN/HgRVTbZ0O - NgBu+2DZ5gYEbELwKC7RGj1YAesyYNcBgRi0RShMW4VYw993X+DkIefTeOQuKdXkyAb4woohUIPs - 8BTqmMC12JFoej6Dv1p8LrUGQQ8awaNi6ogRKvPUkmtBOhsCioJrLTe57BA82KCYiow4qIsdZhmW - gTh37Mov5e5QdFoZIPbkrBI3OYnScT9sdUhYxABuHaZeRzOIBbS1mmseOTW60yBjygOG9TN0xNTR - fzt62KDTmMDTTkxVnfiT7RS2H06r6hTWqE+IDDWWyjIFGcpdyg7Yt0aJoU/oqQjNFFXVWn2pX0+2 - p1BVjD/hEBmJi7shz70u3UYGtfIoU7DsM8WvY47Zb/m/oKqawvkJg9o3uoRNQpE9VbaJBGRoGhR9 - x58+xQ35PENiHUhpgzCwx5T98NmlWB81J5UpAp1lGNjFDSaQfkgUB4GEYbyTLfUyhc4+7lzujmdo - tRi/H3/ADYaziiu+Ob79CetBbF4+HkLYxV/36xRi06e4lh2+j9fEJO0qoZXIeXVEY28K+joB+F7W - dvhtE02fYtfrSuMjcia8Of848pnDQ3FAF5fnO1Sj2nAEzG+u38tbeVRLQY7W34waiZsDxXwvtHRq - 5FkUu1VN3GDqE42vQd2vlvXF/HJ9s1icm8nr5H8AAAD//wMAxVwQjRYFAAA= + H4sIAAAAAAAAA2xTy24bMQy8+ysIXXJZB45jOIlvRdGi6CVAG/RSFwYtcXfZaCVB5Dpxg/x7ofUj + zuOiA0czHL6eRgCGnVmAsS2q7ZIff/rS/Pj2c3LT3XHm21/Sfd/0/zY+rW/l/t5UhRHXf8nqgXVu + Y5c8Kcewg20mVCqqF1fT68n8cnJzMQBddOQLrUk6nsXxdDKdjSfX48l8T2wjWxKzgN8jAICn4S0W + g6NHs4BJdYh0JIINmcXxE4DJ0ZeIQREWxaCmegFtDEphcP20DABLI33XYd4uzQKW5q4loEdLOSk4 + FtuLkIC2BL0QxBps7INSrtFqj16AA9Bj8siBQwNd9GR7jxlSJse2dAOGeqWChFl5QP228MRS0JOP + 5/D5jTjmIa8DjcCOgnK9BdHcW+0zerAthoYGE/vMg1lUeIi9d4BeKRf3fDREDlKOibIySQXS2xZQ + dl7O4WvMQI9YBlkBvikW6jiIHXPBtJqNHVl0TAF9BQ8t2xZaFEA4q1F1e7ZTLomahkTlI/snjjNJ + 77UUhOC4rimXHr3v1F3LpWzHFvWg8HY0FkOpdcOOAAcerj0BB+GmVYH19uCqjE4SWa7Znsywi65E + sFClzABty7QhcCScX3XyfGmq3Tpl8rTBYGklNmbardXN0izD8+keZqp7wXIGofd+H38+LraPTcpx + LXv8GK85sLSrTCgxlCUWjckM6PMI4M9wQP2rmzApxy7pSuM9hSJ4cTm/2Amal5s9gacHVKOiPwFm + 19PqA8mVI0X2cnKFxqJtyb1wJ6OT+t6n/UhiVyOH5p3KaK9kZCtK3arm0FBOmXd3XafVjPByfnM1 + v0Yzeh79BwAA//8DAJHY5rDgBAAA headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c99b9ca525c1c-SJC + - 8cd6e7f11c8ccf13-SJC Connection: - keep-alive Content-Encoding: @@ -4547,14 +3495,14 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:56 GMT + - Fri, 04 Oct 2024 17:31:33 GMT Server: - cloudflare Set-Cookie: - - __cf_bm=IILXIMFwKOCQyKIe4t968EFupyUvRYsQBF.htt_DAKY-1727451716-1.0.1.1-F1yqwTS4CuwVLYANhXnSyGZFgAr0L.AzGv5eOsnzBFQ9NRL2_1YMX04RRJxatmgDNjoIdL1XQYOm7V.JI7BKPA; - path=/; expires=Fri, 27-Sep-24 16:11:56 GMT; domain=.api.openai.com; HttpOnly; + - __cf_bm=NsjDI05lNfgrFiCHUJ0j2F7Nx8mYF8Qn2.yOzWwWPKQ-1728063093-1.0.1.1-2SVj8JCVVw9iKLvhg.8KIUb._prXm079gKonT82cpggvX.Ozlj8rlOtdngc6DLslf7OYWnLIdVGAGC0F7jyugA; + path=/; expires=Fri, 04-Oct-24 18:01:33 GMT; domain=.api.openai.com; HttpOnly; Secure; SameSite=None - - _cfuvid=b8zaetoDNOecUNc4DfrZLUwwHg_5euumayxjJ2pW7tA-1727451716043-0.0.1.1-604800000; + - _cfuvid=.woyY1hdz0ZXWSPTNLXq52.QG9_nc5s2X8z17x_dbDM-1728063093529-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None Transfer-Encoding: - chunked @@ -4567,7 +3515,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "2349" + - "1945" openai-version: - "2020-10-01" strict-transport-security: @@ -4577,73 +3525,94 @@ interactions: x-ratelimit-limit-tokens: - "30000000" x-ratelimit-remaining-requests: - - "9998" + - "9999" x-ratelimit-remaining-tokens: - - "29998965" + - "29998515" x-ratelimit-reset-requests: - - 9ms + - 6ms x-ratelimit-reset-tokens: - 2ms x-request-id: - - req_db32ef9a454b07da72281b0c98abd634 + - req_e4ea4aa187060f7ab0b9d99ea4c93ae6 status: code: 200 message: OK - request: body: - '{"messages": [{"role": "system", "content": "Answer in a direct and concise - tone. Your audience is an expert, so be highly specific. If there are ambiguous - terms or acronyms, first define them."}, {"role": "user", "content": "Summarize - the excerpt below to help answer a question.\n\nExcerpt from wellawatteUnknownyearaperspectiveon - pages 12-14: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew - D. White. A perspective on explanations of molecular prediction models. Unknown - journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, doi:10.26434/chemrxiv-2022-qfv02.\n\n----\n\n - relationships\nin training data.101 Counterfactuals create local (instance-level), - actionable explanations.\nActionability of an explanation suggest which features - can be altered to change the outcome.\nFor example, changing a hydrophobic functional - group in a molecule to a hydrophilic group\nto increase solubility.\nCounterfactual - generation is a demanding task as it requires gradient optimization over\ndiscrete - features that represents a molecule. Recent work by Fu et al. 102 and Shen et - al. 103\npresent two techniques which allow continuous gradient-based optimization. - Although, these\nmethodologies are shown to circumvent the issue of discrete - molecular optimization, counter-\nfactual explanation based model interpretation - still remains unexplored compared to other\n12\npost-hoc methods.\nCF-GNNExplainer104 - is a counterfactual explanation generating method based on GN-\nNExplainer69 - for graph data. This method generate counterfactuals by perturbing the input\ndata - (removing edges in the graph), and keeping account of perturbations which lead - to\nchanges in the output.\nHowever, this method is only applicable to graph-based - models\nand can generate infeasible molecular structures. Another related work - by Numeroso and\nBacciu 105 focus on generating counterfactual explanations - for deep graph networks. Their\nmethod MEG (Molecular counterfactual Explanation - Generator) uses a reinforcement learn-\ning based generator to create molecular - counterfactuals (molecular graphs).\nWhile this\nmethod is able to generate - counterfactuals through a multi-objective reinforcement learner,\nthis is not - a universal approach and requires training the generator for each task.\nWork - by Wellawatte et al. 9 present a model agnostic counterfactual generator MMACE\n(Molecular - Model Agnostic Counterfactual Explanations) which does not require training\nor - computing gradients. This method firstly populates a local chemical space through - ran-\ndom string mutations of SELFIES106 molecular representations using the - STONED algo-\nrithm.107 Next, the labels (predictions) of the molecules in the - local space are generated\nusing the model that needs to be explained. Finally, - the counterfactuals are identified and\nsorted by their similarities \u2013 - Tanimoto distance96 between ECFP4 fingerprints.97 Unlike the\nCF-GNNExplainer104 - and MEG105 methods, the MMACE algorithm ensures that generated\nmolecules are - valid, owing to the surjective property of SELFIES. Additionally, the MMACE\nmethod - can be applied to both regression and classification models. However, like most - XAI\nmethods for molecular prediction, MMACE does not account for the chemical - stability of\npredicted counterfactuals.\nTo circumvent this drawback, Wellawatte - et al. 9 propose an-\nother approach, which identift counterfactuals through - a similarity search on the PubChem\ndatabase.108\n13\nSimilarity to adjacent - fields\nTangential examples to counterfactual explanations are adversarial training - and matched\nmolecular pairs. Adversarial perturbations are used d\n\n----\n\nQuestion: - Are counterfactuals actionable? [yes/no]\n\nDo not directly answer the question, - instead summarize to give evidence to help answer the question. Stay detailed; - report specific numbers, equations, or direct quotes (marked with quotation - marks). Reply \"Not applicable\" if the excerpt is irrelevant. At the end of - your response, provide an integer score from 1-10 on a newline indicating relevance - to question. Do not explain your score.\n\nRelevant Information Summary (about - 100 words):"}], "model": "gpt-4o-2024-08-06", "stream": false, "temperature": - 0.0}' + '{"messages": [{"role": "system", "content": "Provide a summary of the relevant + information that could help answer the question based on the excerpt. Respond + with the following JSON format:\n\n{\n \"summary\": \"...\",\n \"relevance_score\": + \"...\"\n}\n\nwhere `summary` is relevant information from text - about 100 + words words and `relevance_score` is the relevance of `summary` to answer question + (out of 10).\n"}, {"role": "user", "content": "Excerpt from wellawatteUnknownyearaperspectiveon + pages 15-18: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew + D. White. A perspective on explanations of molecular prediction models. Journal + of Chemical Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\n----\n\nin is a critical aspect in drug\ndevelopment + and discovery.120 Small molecule blood-brain barrier (BBB) permeation is a\nclassification + problem routinely assessed with DL models.121,122 To explain why DL models\nwork, + we trained two models a random forest (RF) model123 and a Gated Recurrent Unit\nRecurrent + Neural Network (GRU-RNN). Then we explained the RF model with generated\ncounterfactuals + explanations using the MMACE9 and the GRU-RNN with descriptor expla-\nnations.10 + Both the models were trained on the dataset developed by Martins et al. 124. + The\nRF model was implemented in Scikit-learn125 using Mordred molecular descriptors126 + as the\ninput features. The GRU-RNN model was implemented in Keras.127 See Wellawatte + et al. 9\nand Gandhi and White 10 for more details.\nAccording to the counterfactuals + of the instance molecule in figure 1, we observe that the\nmodifications to + the carboxylic acid group enable the negative example molecule to permeate\nthe + BBB. Experimental findings by Fischer et al. 120 show that the BBB permeation + of\nmolecules are governed by hydrophobic interactions and surface area. The + carboxylic group is\na hydrophilic functional group which hinders hydrophobic + interactions and addition of atoms\nenhances the surface area. This proves the + advantage of using counterfactual explanations,\nas they suggest actionable + modification to the molecule to make it cross the BBB.\nIn Figure 2 we show + descriptor explanations generated for Alprozolam, a molecule that\npermeates + the BBB, using the method described by Gandhi and White 10.\nWe see that\npredicted + permeability is positively correlated with the aromaticity of the molecule, + while\n15\nnegatively correlated with the number of hydrogen bonds donors and + acceptors. A similar\nstructure-property relationship for BBB permeability is + proposed in more mechanistic stud-\nies.128\u2013130 The substructure attributions + indicates a reduction in hydrogen bond donors and\nacceptors. These descriptor + explanations are quantitative and interpretable by chemists.\nFinally, we can + use a natural language model to summarize the findings into a written\nexplanation, + as shown in the printed text in Figure 2.\nFigure 1: Counterfactuals of a molecule + which cannot permeate the blood-brain barrier.\nSimilarity is the Tanimoto similarity + of ECFP4 fingerprints.131 Red indicates deletions and\ngreen indicates substitutions + and addition of atoms. Republished from Ref.9 with permission\nfrom the Royal + Society of Chemistry.\nSolubility prediction\nSmall molecule solubility prediction + is a classic cheminformatics regression challenge and is\nimportant for chemical + process design, drug design and crystallization.133\u2013136 In our previous\nworks,9,10 + we implemented and trained an RNN model in Keras to predict solubilities (log\nmolarity) + of small molecules.127 The AqSolDB curated database137 was used to train the\nRNN + model.\nIn this task, counterfactuals are based on equation 6. Figure 3 illustrates + the generated\nlocal chemical space and the top four counterfactuals. Based + on the counterfactuals, we ob-\nserve that the modifications to the ester group + and other heteroatoms play an important role\nin solubility. These findings + align with known experimental and basic chemical intuition.134\nFigure 4 shows + a quantitative measurement of how substructures are contributing to the pre-\n16\nFigure + 2: Descriptor explanations along with natural language explanation obtained + for BBB\npermeability of Alprozolam molecule. The green and red bars show descriptors + that influ-\nence predictions positively and negatively, respectively. Dotted + yellow lines show significance\nthreshold (\u03b1 = 0.05) for the t-statistic. + Molecular descriptors show molecule-level proper-\nties that are important for + the prediction. ECFP and MACCS descriptors indicate which\nsubstructures influence + model predictions. MACCS explanations lead to text explanations\nas shown. Republished + from Ref.10 with permission from authors. SMARTS annotations for\nMACCS descriptors + were created using SMARTSviewer (smartsview.zbh.uni-hamburg.de,\nCopyright: + ZBH, Center for Bioinformatics Hamburg) developed by Schomburg et al. 132.\n17\ndiction. + For example, we see that adding acidic and basic groups as well as hydrogen + bond\nacceptors, increases solubility. Substructure importance from ECFP97 and + MACCS138 de-\nscriptors indicate that adding heteroatoms increases solubility, + while adding rings structures\nmakes the molecule less soluble. Although these + are established hypotheses, it is interesting\nto see they can be derived purely + from the data via DL and XAI.\nFigure 3: Generated chemical space for solubility + prediction using the RNN model. The\nchemical space is a 2D projection of the + pairwise Tanimoto similarities of the local coun-\nterfactuals. Each data point + is colored by solubility. Top 4 counterfactuals are shown here.\nRepublished + from Ref.9 with permission from the Royal Society of Chemistry.\nGeneralizing + XAI \u2013 interpreting scent-structure relationships\nIn this example, we show + how non\n\n----\n\nQuestion: Are counterfactuals actionable? [yes/no]\n\n"}], + "model": "gpt-4o-2024-08-06", "stream": false, "temperature": 0.0}' headers: accept: - application/json @@ -4652,7 +3621,7 @@ interactions: connection: - keep-alive content-length: - - "4236" + - "6014" content-type: - application/json host: @@ -4674,29 +3643,30 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: !!binary | - H4sIAAAAAAAAA3xTTW/cOAy9z68gdOoCdjCZmWSS3IJsUvSQ9rBb9NAsBrRMW9qVRUGk0wyK/PdC - nq/ksL0YMB/59PhI/pwBGN+aGzDWodohhfr2bv3l8ba7vfz6bbVcLj7h8hv5h68RLxr3l6lKBTf/ - ktVD1ZnlIQVSz3EH20yoVFjP14v16uJ8fb6agIFbCqWsT1qvuF7MF6t6flXPL/eFjr0lMTfwfQYA - 8HP6FomxpRdzA/PqEBlIBHsyN8ckAJM5lIhBES+KUU11Ai1HpTipvuMxKuUOrY4YBDATtCQ2+4Za - QIGU+dm3PvbwZAJbDPDBx8JoqQ70TOGPCtCWjrEJBPSSAkYs/3L2ZOBvR0fYB69b4A4Q7Ltn31aB - F2hp4Ciai3XQbEHGvifRIuKH89ZBR6hjJgGLERoCDEqZWlAG6zD2BOoIeFTLA1Ugo3Wll4Fb320L - DYLbtpmT48Zb6Ma4kxigzzwm8BEQBg5kx0CF9Zjvg7fAcQr6WMYrBMJh3HV3NjVML5ZyUmi92FGE - BJ4xex4FBlLHrUDHGXqKlHHq6r0dUhXqME6u3z3UHz9/vi8G+Ui5gsf7jxVgbOHx8fbuvgJC6+CH - Vwet7zrKFBUwpcxoHcmUGfzgdT8T+JMkeZ0cEjoIqibDDrojKwmoQ/3NoOoGhVqYFhl8SUqZ9DjD - QCJTOpfBlLvA/YRYHWVILFo7tgcFZ0/xKV693dJM3ShYjiSOIezjr8e1D9ynzI3s8WO889GL25TJ - cCwrLsrJTOjrDOCf6bzGdxdjUuYh6Ub5P4qF8Gq93PGZ00Gf0PPFAVVWDCfg+vry/8o2LSn6IG+u - 1Owk+tifGOZHnVOjRraiNGw6H/vir98dbZc2F/OL+WJ5aZvWzF5nvwAAAP//AwCk3gJjvQQAAA== + H4sIAAAAAAAAA2xTwW4TMRC95ytGvgBSUiVpKG1uBCrBBVVQRAWLEq892XXxeqwZb9tQ9d+Rd5M0 + pb34MM/v+c143v0AQDmr5qBMrZNpoh+9P6++fm6+//xYxWn55e+3i6sfl/5c8Kq9/nShhplB5TWa + tGMdGWqix+Qo9LBh1Amz6uTd9HR8cjw+m3ZAQxZ9plUxjWY0mo6ns9H4dDQ+2RJrcgZFzeHXAADg + vjuzxWDxTs1hPNxVGhTRFar5/hKAYvK5orSIk6RDUsNH0FBIGDrXq9XqWigU4b4IAIWStmk0bwo1 + h0J9oDYk5LU2qdUe8C56HXTuTkAzQvaCFrTJJV16PILLGgHvDHJMYJ2YVgQFaroF80RM4BYZoRW0 + kKiXdgE0sA6WGlgToyToxvRKIDJaZ/qXGSvN1oUKSk9kRyVnZqmZHTK8XiwWbyAiN9g5PYLFJsu4 + 9SZTUo1gNJd0t/HOgDbOQsXUxiHc1s7U4ATqjWWKtesuBAt17pP3dSqdAZd76RuXYa/6X3/SVhVK + ejIfMLUOFQqkWqfM8BawRzQ05NG0HvM8tv6xU14sFnmwTsBiQ0ES69RpIMTOg9Ee2uS8Sxug9TMn + LuzM5Al0s3Bm+42Jdu9qBkncmtQydnVtaoc3CBbFMVqITBE5OZQhSGtq0Fk6b3j+xN5x2Zk4KtSw + XydGjzc6GFyKIcZ+rc4KVYSHIqxWq8OtZFy3onMoQuv9tv6wX3NPVWQqZYvv62sXnNTLbINCXmlJ + FFWHPgwAfndxap8kREWmJqZloj8YsuBk2seyy8YuwYfwbIsmStofALPJyfAFyaXFpJ2Xg0wqo02N + 9pE7Hhz09/zZlyT6Hl2onqkMtkpKNpKwWa5dqJAjuz7l67jEtzg7mxzj6bEaPAz+AQAA//8DAEDe + nRDuBAAA headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c99b9dc2b67f9-SJC + - 8cd6e7f9eb0dcf0e-SJC Connection: - keep-alive Content-Encoding: @@ -4704,15 +3674,9 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:56 GMT + - Fri, 04 Oct 2024 17:31:34 GMT Server: - cloudflare - Set-Cookie: - - __cf_bm=wK.6ukfHg1BLQhOmEKuQGt_bKH23H_IyHb9et6bcrRk-1727451716-1.0.1.1-gF3JQa3K_8aTqBqVfjUjhCerwSA.mWieSmxg11iaMMZpQ6.vcJjTDvp7uDWw83y0BpYZLj3VW0EOX1H4aY8Ibg; - path=/; expires=Fri, 27-Sep-24 16:11:56 GMT; domain=.api.openai.com; HttpOnly; - Secure; SameSite=None - - _cfuvid=ssBRY_76Fejx4hGYkLB9Fim3aLOPd2XHAFZCyLFemj8-1727451716089-0.0.1.1-604800000; - path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None Transfer-Encoding: - chunked X-Content-Type-Options: @@ -4724,7 +3688,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "1940" + - "1664" openai-version: - "2020-10-01" strict-transport-security: @@ -4736,71 +3700,92 @@ interactions: x-ratelimit-remaining-requests: - "9999" x-ratelimit-remaining-tokens: - - "29998974" + - "29998541" x-ratelimit-reset-requests: - 6ms x-ratelimit-reset-tokens: - 2ms x-request-id: - - req_32ac99c82d71b5fd14ec43ff24a3ff1d + - req_e987cdf6c4a94350da3ede17995d8b93 status: code: 200 message: OK - request: body: - '{"messages": [{"role": "system", "content": "Answer in a direct and concise - tone. Your audience is an expert, so be highly specific. If there are ambiguous - terms or acronyms, first define them."}, {"role": "user", "content": "Summarize - the excerpt below to help answer a question.\n\nExcerpt from wellawatteUnknownyearaperspectiveon - pages 26-28: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew - D. White. A perspective on explanations of molecular prediction models. Unknown - journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, doi:10.26434/chemrxiv-2022-qfv02.\n\n----\n\nability - and Transparency. 2018; pp 77\u201391.\n(20) Lapuschkin, S.; W\u00a8aldchen, - S.; Binder, A.; Montavon, G.; Samek, W.; M\u00a8uller, K.-R.\nUnmasking Clever - Hans predictors and assessing what machines really learn. Nature\ncommunications - 2019, 10, 1\u20138.\n(21) DeGrave, A. J.; Janizek, J. D.; Lee, S.-I. AI for - radiographic COVID-19 detection\nselects shortcuts over signal. Nature Machine - Intelligence 2021, 3, 610\u2013619.\n(22) Goodman, B.; Flaxman, S. European - Union regulations on algorithmic decision-\nmaking and a \u201cright to explanation\u201d. - AI Magazine 2017, 38, 50\u201357.\n(23) ACT, A. I. European Commission. On Artificial - Intelligence: A European Approach\nto Excellence and Trust. 2021, COM/2021/206.\n(24) - Blueprint for an AI Bill of Rights, The White House. 2022; https://www.whitehouse.\ngov/ostp/ai-bill-of-rights/.\n(25) - Miller, T. Explanation in artificial intelligence: Insights from the social - sciences. Ar-\ntificial intelligence 2019, 267, 1\u201338.\n26\n(26) Murdoch, - W. J.; Singh, C.; Kumbier, K.; Abbasi-Asl, R.; Yu, B. Definitions, meth-\nods, - and applications in interpretable machine learning. Proceedings of the National\nAcademy - of Sciences of the United States of America 2019, 116, 22071\u201322080.\n(27) - Gunning, D.; Aha, D. DARPA\u2019s Explainable Artificial Intelligence (XAI) - Program.\nAI Magazine 2019, 40, 44\u201358.\n(28) Biran, O.; Cotton, C. Explanation - and justification in machine learning: A survey.\nIJCAI-17 workshop on explainable - AI (XAI). 2017; pp 8\u201313.\n(29) Palacio, S.; Lucieri, A.; Munir, M.; Ahmed, - S.; Hees, J.; Dengel, A. Xai handbook:\nTowards a unified framework for explainable - ai. Proceedings of the IEEE/CVF Inter-\nnational Conference on Computer Vision. - 2021; pp 3766\u20133775.\n(30) Kuhn, D. R.; Kacker, R. N.; Lei, Y.; Simos, D. - E. Combinatorial Methods for Ex-\nplainable AI. 2020 IEEE International Conference - on Software Testing, Verification\nand Validation Workshops (ICSTW) 2020, 167\u2013170.\n(31) - Seshadri, A.; Gandhi, H. A.; Wellawatte, G. P.; White, A. D. Why does that molecule\nsmell? - ChemRxiv 2022,\n(32) Das, A.; Rad, P. Opportunities and challenges in explainable - artificial intelligence\n(xai): A survey. arXiv preprint arXiv:2006.11371 2020,\n(33) - Machlev, R.; Heistrene, L.; Perl, M.; Levy, K. Y.; Belikov, J.; Mannor, S.; - Levron, Y.\nExplainable Artificial Intelligence (XAI) techniques for energy - and power systems:\nReview, challenges and opportunities. Energy and AI 2022, - 9, 100169.\n(34) Koh, P. W.; Liang, P. Understanding black-box predictions via - influence functions.\nInternational Conference on Machine Learning. 2017; pp - 1885\u20131894.\n(35) Ribeiro, M. T.; Singh, S.; Guestrin, C. \u201d Why should - i trust you?\u201d Explaining the\npredictions of any classifier. Proceedings - of the 22nd ACM SIGKDD international\n27\nconference on knowledge discovery - and data mining. San Diego, CA, USA, 2016; pp\n1135\u20131144.\n(36) Dhurandhar, - A.; Chen, P.-Y.; Luss, R.; Tu, C.-C.; Ting, P.; Shanmugam, K.; Das, P.\nExplanations - based on the missing: Towards contrastive explanations with pertinent\nnegatives. - Advances i\n\n----\n\nQuestion: Are counterfactuals actionable? [yes/no]\n\nDo - not directly answer the question, instead summarize to give evidence to help - answer the question. Stay detailed; report specific numbers, equations, or direct - quotes (marked with quotation marks). Reply \"Not applicable\" if the excerpt - is irrelevant. At the end of your response, provide an integer score from 1-10 - on a newline indicating relevance to question. Do not explain your score.\n\nRelevant - Information Summary (about 100 words):"}], "model": "gpt-4o-2024-08-06", "stream": - false, "temperature": 0.0}' + '{"messages": [{"role": "system", "content": "Provide a summary of the relevant + information that could help answer the question based on the excerpt. Respond + with the following JSON format:\n\n{\n \"summary\": \"...\",\n \"relevance_score\": + \"...\"\n}\n\nwhere `summary` is relevant information from text - about 100 + words words and `relevance_score` is the relevance of `summary` to answer question + (out of 10).\n"}, {"role": "user", "content": "Excerpt from wellawatteUnknownyearaperspectiveon + pages 13-15: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew + D. White. A perspective on explanations of molecular prediction models. Journal + of Chemical Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\n----\n\nnt-based optimization. Although, these\nmethodologies + are shown to circumvent the issue of discrete molecular optimization, counter-\nfactual + explanation based model interpretation still remains unexplored compared to + other\n12\npost-hoc methods.\nCF-GNNExplainer104 is a counterfactual explanation + generating method based on GN-\nNExplainer69 for graph data. This method generate + counterfactuals by perturbing the input\ndata (removing edges in the graph), + and keeping account of perturbations which lead to\nchanges in the output.\nHowever, + this method is only applicable to graph-based models\nand can generate infeasible + molecular structures. Another related work by Numeroso and\nBacciu 105 focus + on generating counterfactual explanations for deep graph networks. Their\nmethod + MEG (Molecular counterfactual Explanation Generator) uses a reinforcement learn-\ning + based generator to create molecular counterfactuals (molecular graphs).\nWhile + this\nmethod is able to generate counterfactuals through a multi-objective reinforcement + learner,\nthis is not a universal approach and requires training the generator + for each task.\nWork by Wellawatte et al. 9 present a model agnostic counterfactual + generator MMACE\n(Molecular Model Agnostic Counterfactual Explanations) which + does not require training\nor computing gradients. This method firstly populates + a local chemical space through ran-\ndom string mutations of SELFIES106 molecular + representations using the STONED algo-\nrithm.107 Next, the labels (predictions) + of the molecules in the local space are generated\nusing the model that needs + to be explained. Finally, the counterfactuals are identified and\nsorted by + their similarities \u2013 Tanimoto distance96 between ECFP4 fingerprints.97 + Unlike the\nCF-GNNExplainer104 and MEG105 methods, the MMACE algorithm ensures + that generated\nmolecules are valid, owing to the surjective property of SELFIES. + Additionally, the MMACE\nmethod can be applied to both regression and classification + models. However, like most XAI\nmethods for molecular prediction, MMACE does + not account for the chemical stability of\npredicted counterfactuals.\nTo circumvent + this drawback, Wellawatte et al. 9 propose an-\nother approach, which identift + counterfactuals through a similarity search on the PubChem\ndatabase.108\n13\nSimilarity + to adjacent fields\nTangential examples to counterfactual explanations are adversarial + training and matched\nmolecular pairs. Adversarial perturbations are used during + training to deceive the model\nto expose the vulnerabilities of a model109,110 + whereas counterfactuals are applied post-hoc.\nTherefore, the main difference + between adversarial and counterfactual examples are in the\napplication, although + both are derived from the same optimization problem.100 Grabocka\net al. 111 + have developed a method named Adversarial Training on EXplanations (ATEX)\nwhich + improves model robustness via exposure to adversarial examples. While there + are\nconceptual disparities, we note that the counterfactual and adversarial + explanations are\nequivalent mathematical objects.\nMatched molecular pairs + (MMPs) are pairs of molecules that differ structurally at only\none site by + a known transformation.112,113 MMPs are widely used in drug discovery and\nmedicinal + chemistry as these facilitate fast and easy understanding of structure-activity + re-\nlationships.114\u2013116 Counterfactuals and MMP examples intersect if + the structural change is\nassociated with a significant change in the properties. + In the case the associated changes in\nthe properties are non-significant, the + two molecules are known as bioisosteres.117,118 The con-\nnection between MMPs + and adversarial training examples has been explored by van Tilborg\net al. 119. + MMPs which belong to the counterfactual category are commonly used in outlier\nand + activity cliff detection.113 This approach is analogous to counterfactual explanations,\nas + the common objective is to uncover learned knowledge pertaining to structure-property\nrelationships.70\nApplications\nModel + interpretation is certainly not new and a common step in ML in chemistry, but + XAI for\nDL models is becoming more important60,66\u201369,73,88,104,105 Here + we illustrate some practical\nexamples drawn from our published work on how + model-agnostic XAI can be utilized to\n14\ninterpret black-box models and connect + the explanations to structure-property relationships.\nThe methods are \u201cMolecular + Model Agnostic Counterfactual Explanations\u201d (MMACE)9\nand \u201cExplaining + molecular properties with natural language\u201d.10 Then we demonstrate how\ncounterfactuals + and descriptor explanations can propose structure-property relationships in\nthe + domain of molecular scent.31\nBlood-brain barrier permeation prediction\nThe + passive diffusion of drugs from the blood stream to the brain is a critical + aspect in drug\ndevelopment and discovery.120 Small molecule blood-brain barrier + (BBB) permeation is a\nclassification problem routinely assessed with DL models.121,122 + To explain why DL models\nwork, we trained two models a random fore\n\n----\n\nQuestion: + Are counterfactuals actionable? [yes/no]\n\n"}], "model": "gpt-4o-2024-08-06", + "stream": false, "temperature": 0.0}' headers: accept: - application/json @@ -4809,7 +3794,7 @@ interactions: connection: - keep-alive content-length: - - "4328" + - "6033" content-type: - application/json host: @@ -4831,24 +3816,31 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: !!binary | - H4sIAAAAAAAAA3SQzW6DMBCE7zyF5XOoMCFAuFVVT62I1FbqoamQYxbixtiubZRWUd694ieQHHrx - Yb6d8eyePIQwL3GGMNtTxxot/PuHZLN5Waft8ZC3/Pn4neePhLC39zh4fcKLzqF2X8DcxXXHVKMF - OK7kgJkB6qBLJUmYRCuSkLgHjSpBdLZaOz9SfhiEkR+kfhCPxr3iDCzO0IeHEEKn/u0qyhJ+cIaC - xUVpwFpaA86mIYSwUaJTMLWWW0elw4sZMiUdyL51rhyiWgvO6E7AVm4luZ40ULWWdkVlK8Son6ev - haq1UTs78kmvuOR2XxigVsnuG+uUxj09ewh99iu2N62xNqrRrnDqALILJCQNh0A8X3XG0cicclTc - uOL/XEUJjnJhry6Fh4pc1nNEMPXsF8X21zpoiorLGow2fDhcpQtYQbQmS0iX2Dt7fwAAAP//AwBR - H080QQIAAA== + H4sIAAAAAAAAAwAAAP//bFTBbttGEL3rKwZ7pgRJFhxLt0BQHaBw0BYpeigLabgckuMsd9mdoRzV + 8L8HS8qyUufCw76dx/fezOzzBMBwaTZgbINq285NP+7qPz7dH/Xxz1/Xuqy++N93rtB5g7/p1pss + VYTikay+Vs1saDtHyuEM20iolFgXH5Z389ub+XoxAG0oyaWyutPpKkyX8+VqOr+bzm/PhU1gS2I2 + 8PcEAOB5+CaJvqRvZgPz7PWkJRGsyWwulwBMDC6dGBRhUfRqsjfQBq/kB9WHw+FRgs/9c+4BciN9 + 22I85WYDudmG3ivFCq326IC+dQ49JncC7KENjmzvMEIXqWSbABiMCWAk6IVK0AC9LykmEeWIXl0X + KE5Qk6eIyr4GdEox/eJIIJY8Rg4ygwfSJpQCjr8SbH+Z3n/+vEti2FOExPuwu3+lIbA/yBaoQoQ6 + YtdMC0ySRokZFL2CNnSCFk/QxVD2loB9RShcOLryJxp7q30kmcGXhuDh4eN2B+2gKkulXUjExQn+ + IufwCVUJSAHdLLvoEjii4/KdvCfWJvQKkf7tOaYUxpQ0Inv2dQbYdY4tJk0aoAjaQKQ6kkhKPPm3 + LjW6YotXTZjBp/BER4oZsEIZSMAHBbSDgiEW21DLFh2IYsGO9TSD7f/0pVYKt5yC0ABYHikKRh4m + AtO8pyyTqJIiH6mEKoYWQqfc8n+joC6GwlF7Dr3kqqKYRujsLN0Zkj0Nf8NhNga/7FOLQMgLQagS + 0ZHLFBJ74brRNIkazpEV1OCRwzgTl6ZNU4Mo6gkiuXF8G+5klptsHPpIjo7oLe3Fhkjj8N/lJvcv + uT8cDte7E6nqBdPq+t658/nLZRldqJNXOeOX84o9S7OPhBJ8WjzR0JkBfZkA/DMsff/DHpsuhrbT + vYav5BPhYrm6GwnN2ztzBa/WZ1SDorsCbtYfsp9Q7ktSZCdXL4exaBsq32rnkyt/73/7M4rRI/v6 + HcvkzGTkJErtvmJfU+wij29R1e2X1Wp+W6wXixszeZl8BwAA//8DAI1f7haUBQAA headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c99c9cbc767f9-SJC + - 8cd6e7f11d7715d2-SJC Connection: - keep-alive Content-Encoding: @@ -4856,9 +3848,15 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:56 GMT + - Fri, 04 Oct 2024 17:31:34 GMT Server: - cloudflare + Set-Cookie: + - __cf_bm=mZRCVaODgltuJNofK_Ph0pu_SQ.YYv1oPTPge3e8Rro-1728063094-1.0.1.1-Rk9SKz2EwdtepGL6Vamj2XF1NEK22sxoUUIxpvjsho1FwqswzzHGV6_ZC.lSEr1yaXVTzv1PEMknxjvY1.C4Dg; + path=/; expires=Fri, 04-Oct-24 18:01:34 GMT; domain=.api.openai.com; HttpOnly; + Secure; SameSite=None + - _cfuvid=gNsUEFFDYQAxPUKe_pnJXA7wzUoSR6gk28rhbLN9e94-1728063094809-0.0.1.1-604800000; + path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None Transfer-Encoding: - chunked X-Content-Type-Options: @@ -4870,7 +3868,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "132" + - "2800" openai-version: - "2020-10-01" strict-transport-security: @@ -4880,73 +3878,95 @@ interactions: x-ratelimit-limit-tokens: - "30000000" x-ratelimit-remaining-requests: - - "9999" + - "9998" x-ratelimit-remaining-tokens: - - "29998967" + - "29998538" x-ratelimit-reset-requests: - - 6ms + - 8ms x-ratelimit-reset-tokens: - 2ms x-request-id: - - req_d59432c0fd036ecd248c7ef42ea11f55 + - req_38e22cc250f03597d42e3491fdd4fc95 status: code: 200 message: OK - request: body: - '{"messages": [{"role": "system", "content": "Answer in a direct and concise - tone. Your audience is an expert, so be highly specific. If there are ambiguous - terms or acronyms, first define them."}, {"role": "user", "content": "Summarize - the excerpt below to help answer a question.\n\nExcerpt from wellawatteUnknownyearaperspectiveon - pages 4-5: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew D. - White. A perspective on explanations of molecular prediction models. Unknown - journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, doi:10.26434/chemrxiv-2022-qfv02.\n\n----\n\ncation, - interpretations can be categorized as global or local\ninterpretations on the - basis of \u201cwhat is being explained?\u201d. For example, counterfactuals - are\nlocal interpretations, as these can explain only a given instance. The - second classification is\nbased on the relation between the model and the interpretation - \u2013 is interpretability post-hoc\n(extrinsic) or intrinsic to the model?.32,33 - An intrinsic XAI method is part of the model\nand is self-explanatory32 These - are also referred to as white-box models to contrast them\nwith non-interpretable - black box models.28 An extrinsic method is one that can be applied\npost-training - to any model.33 Post-hoc methods found in the literature focus on interpreting\nmodels - through 1) training data34 and feature attribution,35 2) surrogate models10 - and, 3)\ncounterfactual9 or contrastive explanations.36\nOften, what is a \u201cgood\u201d - explanation and what are the required components of an ex-\nplanation are debated.32,37,38 - Palacio et al. 29 state that the lack of a standard framework\nhas caused the - inability to evaluate the interpretability of a model. In physical sciences,\nwe - may instead consider if the explanations somehow reflect and expand our understanding\nof - physical phenomena. For example, Oviedo et al. 39 propose that a model explanation\ncan - be evaluated by considering its agreement with physical observations, which - they term\n\u201ccorrectness.\u201d For example, if an explanation suggests - that polarity affects solubility of a\nmolecule, and the experimental evidence - strengthen the hypothesis, then the explanation\nis assumed \u201ccorrect\u201d. - In instances where such mechanistic knowledge is sparse, expert bi-\nases and - subjectivity can be used to measure the correctness.40 Other similar metrics - of\ncorrectness such as \u201cexplanation satisfaction scale\u201d can be found - in the literature.41,42 In a\nrecent study, Humer et al. 43 introduced CIME - an interactive web-based tool that allows the\nusers to inspect model explanations. - The aim of this study is to bridge the gap between\nanalysis of XAI methods. - Based on the above discussion, we identify that an agreed upon\n4\nevaluation - metric is necessary in XAI. We suggest the following attributes can be used - to\nevaluate explanations. However, the relative importance of each attribute - may depend on\nthe application - actionability may not be as important as faithfulness - when evaluating the\ninterpretability of a static physics based model. Therefore, - one can select relative importance\nof each attribute based on the application.\n\u2022 - Actionable. Is it clear how we could change the input features to modify the - output?\n\u2022 Complete. Does the explanation completely account for the prediction? - Did features\nnot included in the explanation really contribute zero effect - to the prediction?44\n\u2022 Correct. Does the explanation agree with hypothesized - or known underlying physical\nmechanism?39\n\u2022 Domain Applicable. Does the - explanation use language and concepts of domain ex-\nperts?\n\u2022 Fidelity/Faithful. - Does the explanation ag\n\n----\n\nQuestion: Are counterfactuals actionable? - [yes/no]\n\nDo not directly answer the question, instead summarize to give evidence - to help answer the question. Stay detailed; report specific numbers, equations, - or direct quotes (marked with quotation marks). Reply \"Not applicable\" if - the excerpt is irrelevant. At the end of your response, provide an integer score - from 1-10 on a newline indicating relevance to question. Do not explain your - score.\n\nRelevant Information Summary (about 100 words):"}], "model": "gpt-4o-2024-08-06", - "stream": false, "temperature": 0.0}' + '{"messages": [{"role": "system", "content": "Provide a summary of the relevant + information that could help answer the question based on the excerpt. Respond + with the following JSON format:\n\n{\n \"summary\": \"...\",\n \"relevance_score\": + \"...\"\n}\n\nwhere `summary` is relevant information from text - about 100 + words words and `relevance_score` is the relevance of `summary` to answer question + (out of 10).\n"}, {"role": "user", "content": "Excerpt from wellawatteUnknownyearaperspectiveon + pages 24-27: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew + D. White. A perspective on explanations of molecular prediction models. Journal + of Chemical Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\n----\n\nf Rochester for providing computational\nresources.\nReferences\n(1) + Choudhary, K.; DeCost, B.; Chen, C.; Jain, A.; Tavazza, F.; Cohn, R.; Park, + C. W.;\nChoudhary, A.; Agrawal, A.; Billinge, S. J.; Holm, E.; Ong, S. P.; Wolverton, + C.\nRecent advances and applications of deep learning methods in materials science. + npj\nComputational Materials 2022, 8.\n(2) Keith, J. A.; Vassilev-Galindo, V.; + Cheng, B.; Chmiela, S.; Gastegger, M.; M\u00a8uller, K.-\nR.; Tkatchenko, A. + Combining Machine Learning and Computational Chemistry for\nPredictive Insights + Into Chemical Systems. Chemical Reviews 2021, 121, 9816\u20139872,\nPMID: 34232033.\n(3) + Goh, G. B.; Hodas, N. O.; Vishnu, A. Deep learning for computational chemistry.\nJournal + of Computational Chemistry 2017, 38, 1291\u20131307.\n(4) Deringer, V. L.; Caro, + M. A.; Cs\u00b4anyi, G. Machine Learning Interatomic Potentials as\nEmerging + Tools for Materials Science. Advanced Materials 2019, 31, 1902765.\n(5) Faber, + F. A.; Hutchison, L.; Huang, B.; Gilmer, J.; Schoenholz, S. S.; Dahl, G. E.;\nVinyals, + O.; Kearnes, S.; Riley, P. F.; von Lilienfeld, O. A. Prediction Errors of Molec-\nular + Machine Learning Models Lower than Hybrid DFT Error. Journal of Chemical\nTheory + and Computation 2017, 13, 5255\u20135264, PMID: 28926232.\n24\n(6) Duch, W.; + Swaminathan, K.; Meller, J. Artificial Intelligence Approaches for Rational\nDrug + Design and Discovery. Current Pharmaceutical Design 2007, 13, 1497\u20131508.\n(7) + Dara, S.; Dhamercherla, S.; Jadav, S. S.; Babu, C. M.; Ahsan, M. J.; darasuresh, + S. D.;\nDara, S. Machine Learning in Drug Discovery: A Review. Artificial Intelligence + Review\n123, 55, 1947\u20131999.\n(8) Gupta, R.; Srivastava, D.; Sahu, M.; Tiwari, + S.; Ambasta, R. K.; Kumar, P. Artifi-\ncial intelligence to deep learning: machine + intelligence approach for drug discovery.\nMolecular diversity 2021, 25, 1315\u20131360.\n(9) + Wellawatte, G. P.; Seshadri, A.; White, A. D. Model agnostic generation of counter-\nfactual + explanations for molecules. Chemical Science 2022, 13, 3697\u20133705.\n(10) + Gandhi, H. A.; White, A. D. Explaining structure-activity relationships using + locally\nfaithful surrogate models. chemrxiv 2022,\n(11) Gormley, A. J.; Webb, + M. A. Machine learning in combinatorial polymer chemistry.\nNature Reviews Materials + 2021,\n(12) Gomes, C. P.; Fink, D.; Dover, R. B. V.; Gregoire, J. M. Computational + sustainability\nmeets materials science. Nature Reviews Materials 2021,\n(13) + On scientific understanding with artificial intelligence. Nature Reviews Physics + 2022\n4:12 2022, 4, 761\u2013769.\n(14) Arrieta, A. B.; D\u00b4\u0131az-Rodr\u00b4\u0131guez, + N.; Ser, J. D.; Bennetot, A.; Tabik, S.; Barbado, A.;\nGarcia, S.; Gil-Lopez, + S.; Molina, D.; Benjamins, R.; Chatila, R.; Herrera, F. Explain-\nable Artificial + Intelligence (XAI): Concepts, Taxonomies, Opportunities and Chal-\nlenges toward + Responsible AI. Information Fusion 2019, 58, 82\u2013115.\n(15) Murdoch, W. + J.; Singh, C.; Kumbier, K.; Abbasi-Asl, R.; Yu, B. Interpretable machine\nlearning: + definitions, methods, and applications. ArXiv 2019, abs/1901.04592.\n25\n(16) + Boobier, S.; Osbourn, A.; Mitchell, J. B. Can human experts predict solubility + better\nthan computers? Journal of cheminformatics 2017, 9, 1\u201314.\n(17) + Lee, J. D.; See, K. A. Trust in automation: Designing for appropriate reliance. + Human\nFactors 2004, 46, 50\u201380.\n(18) Bolukbasi, T.; Chang, K.-W.; Zou, + J. Y.; Saligrama, V.; Kalai, A. T. Man is to com-\nputer programmer as woman + is to homemaker? debiasing word embeddings. Advances\nin neural information + processing systems 2016, 29.\n(19) Buolamwini, J.; Gebru, T. Gender Shades: + Intersectional Accuracy Disparities in\nCommercial Gender Classification. Proceedings + of the 1st Conference on Fairness,\nAccountability and Transparency. 2018; pp + 77\u201391.\n(20) Lapuschkin, S.; W\u00a8aldchen, S.; Binder, A.; Montavon, + G.; Samek, W.; M\u00a8uller, K.-R.\nUnmasking Clever Hans predictors and assessing + what machines really learn. Nature\ncommunications 2019, 10, 1\u20138.\n(21) + DeGrave, A. J.; Janizek, J. D.; Lee, S.-I. AI for radiographic COVID-19 detection\nselects + shortcuts over signal. Nature Machine Intelligence 2021, 3, 610\u2013619.\n(22) + Goodman, B.; Flaxman, S. European Union regulations on algorithmic decision-\nmaking + and a \u201cright to explanation\u201d. AI Magazine 2017, 38, 50\u201357.\n(23) + ACT, A. I. European Commission. On Artificial Intelligence: A European Approach\nto + Excellence and Trust. 2021, COM/2021/206.\n(24) Blueprint for an AI Bill of + Rights, The White House. 2022; https://www.whitehouse.\ngov/ostp/ai-bill-of-rights/.\n(25) + Miller, T. Explanation in artificial intelligence: Insights from the social + sciences. Ar-\ntificial intelligence 2019, 267, 1\u201338.\n26\n(26) Murdoch, + W. J.; Singh, C.; Kumbier, K.; Abbasi-Asl, R.; Yu, B. Definitions, meth-\nods, + and applications in interpretable machine learning. Proceedings of the National\nAcademy + of Sciences of the United States of America 2019, 116, 22071\u201322080.\n(27) + Gunning, D.; Aha, D. DARPA\u2019s Explainable Artificial Intelligence (XAI) + Program.\nAI Magazine 2019, 40, 44\u201358.\n(28) Biran, O.; Cotton, C. Explanation + and justifi\n\n----\n\nQuestion: Are counterfactuals actionable? [yes/no]\n\n"}], + "model": "gpt-4o-2024-08-06", "stream": false, "temperature": 0.0}' headers: accept: - application/json @@ -4955,7 +3975,7 @@ interactions: connection: - keep-alive content-length: - - "4304" + - "6149" content-type: - application/json host: @@ -4977,29 +3997,29 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: !!binary | - H4sIAAAAAAAAAwAAAP//dFNdbxMxEHzPr1j5OamS0HyQF1SKEAiJSgjxUYKijb13t+Dznuy9JqHq - f0e+fLVUvNzDjmduZuy97wEYdmYBxlaotm784Op6dvPx9S2/5dp/233Rdzff30yvP9TXn8a3N6af - GbL+RVaPrAsrdeNJWcIetpFQKauOZuPZ5WQ0G006oBZHPtPKRgeXMhgPx5eD4XwwnB6IlbClZBbw - owcAcN99s8XgaGsWMOwfJzWlhCWZxekQgIni88RgSpwUg5r+GbQSlELn+nNFQFtLsVGwqFRK5D+U - gINSbCIp5jAJMEHpZY0eJIIXi74PG9YKrLT5aIFWW/QJ2FFQLphc5nQn/xXrQ00YOJSgFe2Ato1H - DiDB7wAhNWS5YAscsnFLF5BNKm0VHCfbpkQpMwFVI69bpQSFRKA79C1q1u0kw/FvHKxvXZ4vzZXN - Q1x76i8NbCq2FWD6nfqwNO8TsIL1hBEq2cCGcjrvwFYYSur+yaFpFQpCbWO2IVCL42LXgdJq0+qr - pYGvFfs94ViuE0oQRDtvbFn9DpKiEmwq0orisyYxEuDZbqfmqODAeQZSPImzNMB147nrBvWZ2j7J - OkcKiR3FfEEnNnCxv4wmyh07OrRQtuzyFYCEQ87c4vMO0FZMdwQIjhJn6UNl+Vq7Ui6WYRnmjx9h - pKJNmHcgtN4f5g+nV+2lbKKs0wE/zXP+VK0iYZKQX3BSaUyHPvQAfnbb0z5ZCNNEqRtdqfymkAXn - s+lez5z39YyORqMDqqLoz8DL+ex/tJUjRfbp0RKavUUO5VlhePLZBTVpl5TqVcGhzAvC+50smtVk - OBmOX0zt2pneQ+8vAAAA//8DAMNSLCScBAAA + H4sIAAAAAAAAAwAAAP//fFNNb9swDL3nVxC69OIETlL0I7duWDEMGPbRAgU6Dwkj05ZaWTJEOmlQ + 5L8PcpI264pddOAjHx/Fx+cBgLKlmoHSBkU3rRtefap/fvm+vtPX9+g+uHp6j9+uN1fhVm5+WJWl + irB8IC2HqpEOTetIbPA7WEdCocQ6Pp9c5GfT/HLaA00oyaWyupXhaRhO8snpML8Y5mf7QhOsJlYz + +DUAAHju3yTRl/SkZpBnh0hDzFiTmr0kAagYXIooZLYs6EVlr6AOXsj3qheLxQMHX/jnwgMUirum + wbgp1AwKdWsI6ElTbAUiVRTJa2JAWIf4CMsN3JFzuEYRyuCG2GAZbQboS7gzVgiCh5OvaVLA2gcW + q6EmTxHTD0GoQIfOC8UKtXTogJ5ah75HGaoQoQmOdOeIT6Dtls6yoRKsh4+GGqvRwY22SVSKTfLJ + ZAS3xjJwV9fEwiAG5b9NMBJ0vCMVQ9B/zZMkbfveGKGNVFrda+73xhmsjdUGbNM6S6kNbXoq7LNw + 6XpFbQwrW1pfg/VsayMMIQI6oZj6r4hTlj7MwhsWangEn8OaVhSzXtFhAWUgBh+k12+1FbcBFhSC + tSExFN/MyW8EZeAIV0kMh4YAm6WtOyubUaGy3e4jOVqh1zRnHSLtPHBeqMJvC79YLI4tFKnqGJOD + fefcPr598aQLdRvDkvf4S7yy3rKZR0IOPvmPJbSqR7cDgN+997u/7KzaGJpW5hIeySfC8UU+3hGq + 13M7gscHVIKgOwIux5PsHcp5SYLW8dEBKY3aUPlamw+O5vu37XsUuxmtr/9hGeyZ1G7h88r6mmIb + 7e4kq3Y+qU7zs+XleDxVg+3gDwAAAP//AwBeR2LVmwQAAA== headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c99c2b896176d-SJC + - 8cd6e7ff3b63cf13-SJC Connection: - keep-alive Content-Encoding: @@ -5007,7 +4027,7 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:56 GMT + - Fri, 04 Oct 2024 17:31:35 GMT Server: - cloudflare Transfer-Encoding: @@ -5021,7 +4041,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "1470" + - "1446" openai-version: - "2020-10-01" strict-transport-security: @@ -5033,71 +4053,93 @@ interactions: x-ratelimit-remaining-requests: - "9999" x-ratelimit-remaining-tokens: - - "29998968" + - "29998530" x-ratelimit-reset-requests: - 6ms x-ratelimit-reset-tokens: - 2ms x-request-id: - - req_75fc6debc124b86df16f89e61e53f2fe + - req_e796a97b20ac8b7881b3e833f63a2004 status: code: 200 message: OK - request: body: - '{"messages": [{"role": "system", "content": "Answer in a direct and concise - tone. Your audience is an expert, so be highly specific. If there are ambiguous - terms or acronyms, first define them."}, {"role": "user", "content": "Summarize - the excerpt below to help answer a question.\n\nExcerpt from wellawatteUnknownyearaperspectiveon - pages 5-7: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew D. - White. A perspective on explanations of molecular prediction models. Unknown - journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, doi:10.26434/chemrxiv-2022-qfv02.\n\n----\n\nlanation - use language and concepts of domain ex-\nperts?\n\u2022 Fidelity/Faithful. Does - the explanation agree with the black box model?\n\u2022 Robust. Does the explanation - change significantly with small changes to the model or\ninstance being explained?\n\u2022 - Sparse/Succinct. Is the explanation succinct?\nWe present an example evaluation - of the SHAP explanation method based on the above\nattributes.44 Shapley values - were proposed as a local explanation method based on feature\nattribution, as - they offer a complete explanation - each feature is assigned a fraction of\nthe - prediction value.44,45 Completeness is a clearly measurable and well-defined - metric, but\nyields explanations with many components. Yet Shapley values are - not actionable nor sparse.\nThey are non-sparse as every feature has a non-zero - attribution and not-actionable because\nthey do not provide a set of features - which changes the outcome.46 Ribeiro et al. 35 proposed\na surrogate model method - that aims to provide sparse/succinct explanations that have high\n5\nfidelity - to the original model. In Wellawatte et al. 9 we argue that counterfactuals - are \u201cbet-\nter\u201d explanations because they are actionable and sparse. - We highlight that, evaluation of\nexplanations is a difficult task because explanations - are fundamentally for and by humans.\nTherefore, these evaluations are subjective, - as they depend on \u201ccomplex human factors and\napplication scenarios.\u201d37\nSelf-explaining - models\nA self-explanatory model is one that is intrinsically interpretable - to an expert.47 Two com-\nmon examples found in the literature are linear regression - models and decision trees (DT).\nIntrinsic models can be found in other XAI - applications acting as surrogate models (proxy\nmodels) due to their transparent - nature.48,49 A linear model is described by the equation\n1 where, W\u2019s - are the weight parameters and x\u2019s are the input features associated with - the\nprediction \u02c6y. Therefore, we observe that the weights can be used - to derive a complete expla-\nnation of the model - trained weights quantify - the importance of each feature.47 DT models\nare another type of self-explaining - models which have been used in classification and high-\nthroughput screening - tasks. Gajewicz et al. 50 used DT models to classify nanomaterials\nthat identify - structural features responsible for surface activity. In another study by Han\net - al. 51, a DT model was developed to filter compounds by their bioactivity based - on the\nchemical fingerprints.\n\u02c6y = \u03a3iWixi\n(1)\nRegularization techniques - such as EXPO52 and RRR53 are designed to enhance the black-\nbox model interpretability.54 - Although one can argue that \u201csimplicity\u201d of models are posi-\ntively - correlated with interpretability, this is based on how the interpretability - is evaluated.\nFor example, Lipton 55 argue that, from the notion of \u201csimulatability\u201d - (the degree to which a\nhuman can predict the outcome based on inputs), self-explanatory - linear models, rule-based\n6\nsystems, and DT\u2019s can be claimed uninterpretable. - A human can pred\n\n----\n\nQuestion: Are counterfactuals actionable? [yes/no]\n\nDo - not directly answer the question, instead summarize to give evidence to help - answer the question. Stay detailed; report specific numbers, equations, or direct - quotes (marked with quotation marks). Reply \"Not applicable\" if the excerpt - is irrelevant. At the end of your response, provide an integer score from 1-10 - on a newline indicating relevance to question. Do not explain your score.\n\nRelevant - Information Summary (about 100 words):"}], "model": "gpt-4o-2024-08-06", "stream": - false, "temperature": 0.0}' + '{"messages": [{"role": "system", "content": "Provide a summary of the relevant + information that could help answer the question based on the excerpt. Respond + with the following JSON format:\n\n{\n \"summary\": \"...\",\n \"relevance_score\": + \"...\"\n}\n\nwhere `summary` is relevant information from text - about 100 + words words and `relevance_score` is the relevance of `summary` to answer question + (out of 10).\n"}, {"role": "user", "content": "Excerpt from wellawatteUnknownyearaperspectiveon + pages 21-24: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew + D. White. A perspective on explanations of molecular prediction models. Journal + of Chemical Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\n----\n\nhat the \u201ccorrectness\u201d of + the explanations strongly depends on\nthe accuracy of the black-box model.\nA + molecular counterfactual is one with a minimal distance from a base molecular, + but\nwith contrasting chemical properties. In the above examples, we used Tanimoto + similar-\nity96 of ECFP4 fingreprints97 as distance, although this should be + explored in the future.\nCounterfactual explanations are useful because they + are represented as chemical structures\n(familiar to domain experts), sparse, + and are actionable. A few other popular examples of\ncounterfactual on graph + methods are GNNExplainer, MEG and CF-GNNExplainer.69,104,105\nThe descriptor + explanation method developed by Gandhi and White 10 fits a self-explaining\n21\nsurrogate + model to explain the black-box model. This is similar to the GraphLIME87 method,\nalthough + we have the flexibility to use explanation features other than subgraphs. Futher-\nmore, + we show that natural language combined with chemical descriptor attributions + can\ncreate explanations useful for chemists, thus enhancing the accessibility + of DL in chemistry.\nLastly, we examined if XAI can be used beyond interpretation. + Work by Seshadri et al. 31 use\nMMACE and surrogate model explanations to analyze + the structure-property relationships\nof scent. They recovered known structure-property + relationships for molecular scent purely\nfrom explanations, demonstrating the + usefulness of a two step process: fit an accurate model\nand then explain it.\nChoosing + among the plethora of XAI methods described here is still an open question.\nIt + remains to be seen if there will ever be a consensus benchmark, since this field + sits on\nthe intersection of human-machine interaction, machine learning, and + philosophy (i.e., what\nconstitutes an explanation?). Our current advice is + to consider first the audience \u2013 domain\nexperts or ML experts or non-experts + \u2013 and what the explanations should accomplish. Are\nthey meant to inform + data selection or model building, how a prediction is used, or how the\nfeatures + can be changed to affect the outcome. The second consideration is what access + you\nhave to the underlying model. The ability to have model derivatives or + propagate gradients\nto the input to models informs the XAI method.\nConclusion + and outlook\nWe should seek to explain molecular property prediction models + because users are more\nlikely to trust explained predictions, and explanations + can help assess if the model is learning\nthe correct underlying chemical principles. + We also showed that black-box modeling first,\nfollowed by XAI, is a path to + structure-property relationships without needing to trade\nbetween accuracy + and interpretability. However, XAI in chemistry has some major open\nquestions, + that are also related to the black-box nature of the deep learning.\nSome are\n22\nhighlighted + below:\n\u2022 Explanation representation: How is an explanation presented \u2013 + text, a molecule, attri-\nbutions, a concept, etc?\n\u2022 Molecular distance: + in XAI approaches such as counterfactual generation, the \u201cdis-\ntance\u201d + between two molecules is minimized. Molecular distance is subjective. Possibil-\nities + are distance based on molecular properties, synthesis routes, and direct structure\ncomparisons.\n\u2022 + Regulations: As black-box models move from research to industry, healthcare, + and\nenvironmental settings, we expect XAI to become more important to explain + decisions\nto chemists or non-experts and possibly be legally required. Explanations + may need\nto be tuned for be for doctors instead of chemists or to satisfy a + legal requirement.\n\u2022 Chemical space: Chemical space is the set of molecules + that are realizable; \u201crealiz-\nable\u201d can be defined from purchasable + to synthesizable to satisfied valences. What is\nmost useful? Can an explanation + consider nearby impossible molecules? How can we\ngenerate local chemical spaces + centered around a specific molecule for finding counter-\nfactuals or other + instance explanations? Similarly, can \u201cactivity cliffs\u201d be connected\nto + explanations and the local chemical space.149\n\u2022 Evaluating XAI : there + is a lack of a systematic framework (quantitative or qualitative)\nto evaluate + correctness and applicability of an explanation. Can there be a universal\nframework, + or should explanations be chosen and evaluated based on the audience and\ndomain? + For example, work by Rasmussen et al. 58 attempts to focus on comparing\nfeature + attribution XAI methods via Crippen\u2019s logP scores.\n23\nAcknowledgements\nResearch + reported in this work was supported by the National Institute of General Medical\nSciences + of the National Institutes of Health under award number R35GM137966. This work\nwas + supported by the NSF under awards 1751471 and 1764415. We thank the Center for\nIntegrated + Research Computing at the University of Rochester for providing computational\nresources.\nReferences\n(1) + Choudhary, K.; DeCost, B.; Chen, C.; Jain, A.; Tavazza, F.; Cohn, R.; Park, + C. W.;\nChoudhary, A.; Agrawal, A.; Billinge, S. J.; Holm, E.; Ong, S. P.; Wolverton, + C.\nRecent advances and \n\n----\n\nQuestion: Are counterfactuals actionable? + [yes/no]\n\n"}], "model": "gpt-4o-2024-08-06", "stream": false, "temperature": + 0.0}' headers: accept: - application/json @@ -5106,7 +4148,7 @@ interactions: connection: - keep-alive content-length: - - "4313" + - "6084" content-type: - application/json host: @@ -5128,29 +4170,29 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: !!binary | - H4sIAAAAAAAAAwAAAP//dFNRb9MwEH7vrzj5Oa2aUtZtbwgJBEJCgkk8MFRdnEti5viM7wwraP8d - Oc26ToKXyLnvvvN35/v+LACMa801GDug2jH65avXu48fby43TLvf77//qLf28sXbLzefPry59L9M - VRjcfCerj6yV5TF6UsfhCNtEqFSq1rvNbvuy3tUXEzByS77Q+qjLLS836812ub5cri9m4sDOkphr - +LoAAPgzfYvE0NK9uYZ19RgZSQR7MtenJACT2JeIQREnikFN9QRaDkphUn0zENC9pRQVWic2i5CA - luhP9BlLK8Ad0H30GI6/I+nArUDHCUb2ZLPHBDFR6+wxoTQnFXRss7jQAwdA1eSarCTg3R1B51ry - Tg8VJG6yaCCRCjC0IBGTOD2s4J3CSKGULJJQ4fOA0dMBijSSCn4NzhPExD9dW+5BmB+AzgVXgIkg - sAJO+rDxBA1ZzEKl1QO0PMHcdZQAQaicoSPUnGi+2w4Y+ikfOKvlkVbwLkCZZULRakIw68BJAFOf - aeZxDkqpQ6sZvUxabk1DqpRuzblOeS6qJDasw7nq03xoBTeDE5Dc9yQq/77rOBk6r+CCuH5QgeYA - ri3T7Q5ldBLJus7Zuc/HghgAvVKaujt74nkEFYx4V+g60AhZqMt+2ouWrBPHYTnjMbGlslur23Ab - rs63MVGXBYsZQvZ+jj+c1ttzHxM3MuOneOeCk2GfCIVDWWVRjmZCHxYA3yYb5WfOMDHxGHWvfEeh - FLxazzYyT8Z9Quv6EVVW9GfAuv4vb9+SovNyZkdz1OhC/1RifRI6dWrkIErjvnOhpxSTO7qzi/tN - t11fNFd1/cIsHhZ/AQAA//8DACYReYOmBAAA + H4sIAAAAAAAAAwAAAP//bFPLbtswELz7KxY824H8aBr7VhQFihZogaC3qrDX1Epiwhe4qyRq4H8v + KPkVpBcednaGO8Pl6wRAmUptQOkWRbtoZ5++NPff3Ffd/3hoO1r/vHNzF/xc7r/3+l5NMyPsH0jL + iXWjg4uWxAQ/wjoRCmXV+cfFXXG7LNbLAXChIptpTZTZKswWxWI1K+5mxe2R2AajidUGfk8AAF6H + M4/oK3pRGyimp4ojZmxIbc5NACoFmysKmQ0LelHTC6iDF/LD1Lvd7oGDL/1r6QFKxZ1zmPpSbaBU + n0PnhVKNWjq0QC/RosfsjgETQUWsk9lTBciAOgO4twTGg7QEwzUvAqEGFyzpzmKCmKgyQysMGfAN + /GqpH/QSxURMXkZF3ZIzGi2wpE5Ll4in8Nwa3Q7dNTpjDSaQAFVwaHyekJLwFNBXQw9HTExTcPho + fJOnctAx1Z2FOiTofEUpx1NlNJNiyMkYtLYHtEIpA6ETHRyNo8LgiVxskc1f4sFqJ8Ya6bNV/SY0 + zmHEFJ7MeMV1SGyaVhj2/ZBUQpbccnYdU8huDDE8G2nBGW8cWqiGB9UEdQoOEPbIdAqYbko1HV8y + kaWn3LdlHRKNL7ouVekPpd/tdtcLkajuGPM++s7aY/1w3jAbmpjCno/4uV4bb7jdJkIOPm8TS4hq + QA8TgD/DJndvllPFFFyUrYRH8llwvvhwNwqqy+e5wOvjnisJgvaKtlydaG8UtxUJGstXv0Fp1C1V + F24xubL3/tb/SYwWjW/eqUyOSop7FnLb2viGUkxm/F913C7qVXG7X8/nSzU5TP4BAAD//wMAeUBx + qWgEAAA= headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c99cc7f8867f9-SJC + - 8cd6e7fbaece1590-SJC Connection: - keep-alive Content-Encoding: @@ -5158,7 +4200,7 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:57 GMT + - Fri, 04 Oct 2024 17:31:35 GMT Server: - cloudflare Transfer-Encoding: @@ -5172,7 +4214,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "988" + - "2467" openai-version: - "2020-10-01" strict-transport-security: @@ -5184,71 +4226,94 @@ interactions: x-ratelimit-remaining-requests: - "9999" x-ratelimit-remaining-tokens: - - "29998968" + - "29998534" x-ratelimit-reset-requests: - 6ms x-ratelimit-reset-tokens: - 2ms x-request-id: - - req_2ef8dc3cb05442e7f16a209a9e6146cc + - req_ecd17610ccfe6af76d113b8f02791f31 status: code: 200 message: OK - request: body: - '{"messages": [{"role": "system", "content": "Answer in a direct and concise - tone. Your audience is an expert, so be highly specific. If there are ambiguous - terms or acronyms, first define them."}, {"role": "user", "content": "Summarize - the excerpt below to help answer a question.\n\nExcerpt from wellawatteUnknownyearaperspectiveon - pages 21-22: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew - D. White. A perspective on explanations of molecular prediction models. Unknown - journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, doi:10.26434/chemrxiv-2022-qfv02.\n\n----\n\nscussion\nWe - have shown two post-hoc XAI applications based on molecular counterfactual expla-\nnations9 - and descriptor explanations.10 These methods can be used to explain black-box\nmodels - whose input is a molecule. These two methods can be applied for both classification\nand - regression tasks. Note that the \u201ccorrectness\u201d of the explanations - strongly depends on\nthe accuracy of the black-box model.\nA molecular counterfactual - is one with a minimal distance from a base molecular, but\nwith contrasting - chemical properties. In the above examples, we used Tanimoto similar-\nity96 - of ECFP4 fingreprints97 as distance, although this should be explored in the - future.\nCounterfactual explanations are useful because they are represented - as chemical structures\n(familiar to domain experts), sparse, and are actionable. - A few other popular examples of\ncounterfactual on graph methods are GNNExplainer, - MEG and CF-GNNExplainer.69,104,105\nThe descriptor explanation method developed - by Gandhi and White 10 fits a self-explaining\n21\nsurrogate model to explain - the black-box model. This is similar to the GraphLIME87 method,\nalthough we - have the flexibility to use explanation features other than subgraphs. Futher-\nmore, - we show that natural language combined with chemical descriptor attributions - can\ncreate explanations useful for chemists, thus enhancing the accessibility - of DL in chemistry.\nLastly, we examined if XAI can be used beyond interpretation. - Work by Seshadri et al. 31 use\nMMACE and surrogate model explanations to analyze - the structure-property relationships\nof scent. They recovered known structure-property - relationships for molecular scent purely\nfrom explanations, demonstrating the - usefulness of a two step process: fit an accurate model\nand then explain it.\nChoosing - among the plethora of XAI methods described here is still an open question.\nIt - remains to be seen if there will ever be a consensus benchmark, since this field - sits on\nthe intersection of human-machine interaction, machine learning, and - philosophy (i.e., what\nconstitutes an explanation?). Our current advice is - to consider first the audience \u2013 domain\nexperts or ML experts or non-experts - \u2013 and what the explanations should accomplish. Are\nthey meant to inform - data selection or model building, how a prediction is used, or how the\nfeatures - can be changed to affect the outcome. The second consideration is what access - you\nhave to the underlying model. The ability to have model derivatives or - propagate gradients\nto the input to models informs the XAI method.\nConclusion - and outlook\nWe should seek to explain molecular property prediction models - because users are more\nlikely to trust explained predictions, and explanations - can help assess if the model is learning\nthe correct underlying chemical principles. - We also showed that black-box modeling first,\nfollowed by XAI, is a path to - structure-property relationships without needing to trade\nbetween accuracy - and interpretability. However, XAI in chemistry has some maj\n\n----\n\nQuestion: - Are counterfactuals actionable? [yes/no]\n\nDo not directly answer the question, - instead summarize to give evidence to help answer the question. Stay detailed; - report specific numbers, equations, or direct quotes (marked with quotation - marks). Reply \"Not applicable\" if the excerpt is irrelevant. At the end of - your response, provide an integer score from 1-10 on a newline indicating relevance - to question. Do not explain your score.\n\nRelevant Information Summary (about - 100 words):"}], "model": "gpt-4o-2024-08-06", "stream": false, "temperature": - 0.0}' + '{"messages": [{"role": "system", "content": "Provide a summary of the relevant + information that could help answer the question based on the excerpt. Respond + with the following JSON format:\n\n{\n \"summary\": \"...\",\n \"relevance_score\": + \"...\"\n}\n\nwhere `summary` is relevant information from text - about 100 + words words and `relevance_score` is the relevance of `summary` to answer question + (out of 10).\n"}, {"role": "user", "content": "Excerpt from wellawatteUnknownyearaperspectiveon + pages 1-3: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew D. + White. A perspective on explanations of molecular prediction models. Journal + of Chemical Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\n----\n\nA Perspective on Explanations of Molecular\nPrediction + Models\nGeemi P. Wellawatte,\u2020\nHeta A. Gandhi,\u2021\nAditi Seshadri,\u2021 + and\nAndrew\nD. White\u2217,\u2021\n\u2020Department of Chemistry, University + of Rochester, Rochester, NY, 14627\n\u2021Department of Chemical Engineering, + University of Rochester, Rochester, NY, 14627\n\u00b6Vial Health Technology, + Inc., San Francisco, CA 94111\nE-mail: andrew.white@rochester.edu\nAbstract\nChemists + can be skeptical in using deep learning (DL) in decision making, due to\nthe + lack of interpretability in \u201cblack-box\u201d models. Explainable artificial + intelligence\n(XAI) is a branch of AI which addresses this drawback by providing + tools to interpret\nDL models and their predictions. We review the principles + of XAI in the domain of\nchemistry and emerging methods for creating and evaluating + explanations. Then we\nfocus on methods developed by our group and their applications + in predicting solubil-\nity, blood-brain barrier permeability, and the scent + of molecules. We show that XAI\nmethods like chemical counterfactuals and descriptor + explanations can explain DL pre-\ndictions while giving insight into structure-property + relationships. Finally, we discuss\nhow a two-step process of developing a black-box + model and explaining predictions can\nuncover structure-property relationships.\n1\nIntroduction\nDeep + learning (DL) is advancing the boundaries of computational chemistry because + it can\naccurately model non-linear structure-function relationships.1\u20133 + Applications of DL can be\nfound in a broad spectrum spanning from quantum computing4,5 + to drug discovery6\u201310 to\nmaterials design.11,12 According to Kre 13, DL + models can contribute to scientific discovery\nin three \u201cdimensions\u201d + - 1) as a \u2018computational microscope\u2019 to gain insight which are not\nattainable + through experiments 2) as a \u2018resource of inspiration\u2019 to motivate + scientific thinking\n3) as an \u2018agent of understanding\u2019 to uncover + new observations. However, the rationale of\na DL prediction is not always apparent + due to the model architecture consisting a large\nparameter count.14,15 DL models + are thus often termed\u201cblack box\u201d models. We can only\nreason about + the input and output of an DL model, not the underlying cause that leads to\na + specific prediction.\nIt is routine in chemistry now for DL to exceed human + level performance \u2014 humans are\nnot good at predicting solubility from + structure for example161 \u2014 and so understanding how\na model makes predictions + can guide hypotheses. This is in contrast to a topic like finding\na stop sign + in an image, where there is little new to be learned about visual perception\nby + explaining a DL model. However, the black box nature of DL has its own limitations.\nUsers + are more likely to trust and use predictions from a model if they can understand + why\nthe prediction was made.17 Explaining predictions can help developers of + DL models ensure\nthe model is not learning spurious correlations.18,19 Two + infamous examples are, 1)neural\nnetworks that learned to recognize horses by + looking for a photographer\u2019s watermark20 and,\n2) neural networks that + predicted a COVID-19 diagnoses by looking at the font choice\non medical images.21 + As a result, there is an emerging regulatory framework for when any\ncomputer + algorithms impact humans.22\u201324 Although we know of no examples yet in chemistry,\none + can assume the use of AI in predicting toxicity, carcinogenicity, and environmental\npersistence + will require rationale for the predictions due to regulatory consequences.\n1there + does happen to be one human solubility savant, participant 11, who matched machine + performance\n2\nEXplainable Artificial Intelligence (XAI) is a field of growing + importance that aims to\nprovide model interpretations of DL predictions Three + terms highly associated with XAI are,\ninterpretability, justifications and + explainability. Miller 25 defines that interpretability of a\nmodel refers to + the degree of human understandability intrinsic within the model. Murdoch\net + al. 26 clarify that interpretability can be perceived as \u201cknowledge\u201d + which provide insight\nto a particular problem.\nJustifications are quantitative + metrics tell the users \u201cwhy the\nmodel should be trusted,\u201d like test + error.27 Justifications are evidence which defend why a\nprediction is trustworthy.25 + An \u201cexplanation\u201d is a description on why a certain prediction was\nmade.9,28 + Interpretability and explanation are often used interchangeably. Arrieta et + al. 14\ndistinguish that interpretability is a passive characteristic of a model, + whereas explainability\nis an active characteristic which is used to clarify + the internal decision-making process.\nNamely, an explanation is extra information + that gives the context and a cause for one or\nmore predictions.29 We adopt + the same nomenclature in this perspective.\nAccuracy and interpretability are + two attractive characteristics of DL models. However,\nDL models are often highly + accurate and less interpretable.28,30 XAI provides a way to avoid\nthat trade-off + in chemical property prediction. XAI can be viewed as a\n\n----\n\nQuestion: + Are counterfactuals actionable? [yes/no]\n\n"}], "model": "gpt-4o-2024-08-06", + "stream": false, "temperature": 0.0}' headers: accept: - application/json @@ -5257,7 +4322,7 @@ interactions: connection: - keep-alive content-length: - - "4246" + - "6156" content-type: - application/json host: @@ -5279,29 +4344,30 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: !!binary | - H4sIAAAAAAAAAwAAAP//fJNNaxtBDIbv/hViLm3BNrbjxIlvJQk0tCEU0kOpi5Fn5N2p54uRtrUJ - +e9ldh3bKW0vC6t3JD3ilZ56AMoaNQelaxTtkxu8v549PHwy+PH+Qxp9/nU3+RK+Xk9ubmez+9sb - 1S8ZcfWDtLxkDXX0yZHYGDpZZ0KhUnU8m8ym5+PZ+KIVfDTkSlqVZDCNg8loMh2MLgeji31iHa0m - VnP41gMAeGq/BTEY2qo5jPovEU/MWJGaHx4BqBxdiShktiwYRPWPoo5BKLTUjzUBbTXlJGAs64aZ - GKQmaJggrsFHR7pxmEHHJgjlNWpp0AFtk8OAZVYGZEDwJHU0ILHTbICVQ70ZrOIW2nkZbDgpmDIZ - q0sBEOQND+FOgAWlJUD5f8dMsFAN07pxsCKNhVdq2rVKppSJKQiZwqZr8lajA5bcaGkyMbxdo7fO - Yi7AJvrCS9tEWfhdHzhhZuoDBtMWxJYTV46GCwWPtWXgpqqI5a+sDBoDrAiMzaTF7QBTcpYMxAwe - g02NK4tReqOuLf0kMMQ2lxeN6OiJ++BxY0NVpvKnAHBqGjqOUNuqdraqpbPO+hSzYNCtgyWCWjcZ - 9e7l/w9jii+GhLK3Yd8RFkrHXOADMS/UPpPplQ390svtuhyUE0qwgTsiQ4mCgeJyTV2/NwyZnMWV - dVZ2w0VYhMvTBc20bhjLfYTGuX38+bDxLlYpxxXv9UN8bYPlepkJOYay3SwxqVZ97gF8by+reXUs - KuXokywlbiiUgpfnF109dbzlozoeT/eqREF3FK5mo3+lLQ0JWscnB6o6RBuqY4XRgbMdVPGOhfxy - bUNFOWXb3es6LemcplfjM7o8U73n3m8AAAD//wMAaAurb7gEAAA= + H4sIAAAAAAAAAwAAAP//bFTBbhs5DL37Kwhd2gJjY+wYbupb0qS7wQYLdLGHLeqFIUucEVuNJIic + JEaQf1+Mxk6cZi8DiE98fHwi53ECoMiqNSjjtJgu+enFdfvXH8u7+bfLr188Xveri8/uT3t5+Zux + tlbVkBF3P9DIMWtmYpc8CsUwwiajFhxY5x8X5/XqrP60LEAXLfohrU0yXcbpol4sp/X5tF4dEl0k + g6zW8H0CAPBYvoPEYPFBraGujpEOmXWLav18CUDl6IeI0szEooOo6gU0MQiGovpxEwA2ivuu03m/ + UWvYqL8dAj4YzEnAEpueGRnEIfSMEBu4fkheU9A7j3CRhRoypD3cBEHvqcVgEN7/c3HzASiAcdgR + S95XkHQWMr3X2e8HCEceCi1YxAQedS6n91e3H6BYxO8gZbRkBk95BjcCHYZygA7FRcvg6SeOZYz2 + YGIfBHOjjfTaM+hgwSKbTEliHmsGXRgquHdkHDj06SgGrm5PK5b0lOMdWQQKTK0TBgoSgSX3RvqM + 05Rjwix7yOhHZkeJZ/B7vMc7zFXxTvBBwEZkCFFKNTIkfg8sWhDuHYrD/FZ+RtBFy2D3DIbHaaLp + GYghhkJNQ0bKKHpHnmRfREvuWe5jFkcBmYd3u7o9mFoB922LLIPZ4rT8YgsF43s7gL/IqYqeDnUQ + kAjG60zN/pVhWZc+xOkAljIaKY9tyQxtHlspOmcbVY3zl9HjnQ4Gt2xixnEOP27UJjydDm7Gpmc9 + 7E3ovT/En543wcc25bjjA/4cbygQu21GzTEMU88Skyro0wTg37Jx/aslUinHLslW4k8MA+F8sTqs + nHpZ8lP47IBKFO1PgLPzI/KKcmtRNHk+WVtltHFoX3LryUl/b8v+H8XYI4X2DcvkwKR4z4LdtqHQ + DlND44+gSdtFs6xXu0/z+ZmaPE3+AwAA//8DAH76bjsRBQAA headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c99cd1de4176d-SJC + - 8cd6e806c86e15d2-SJC Connection: - keep-alive Content-Encoding: @@ -5309,7 +4375,7 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:57 GMT + - Fri, 04 Oct 2024 17:31:36 GMT Server: - cloudflare Transfer-Encoding: @@ -5323,7 +4389,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "987" + - "1402" openai-version: - "2020-10-01" strict-transport-security: @@ -5335,71 +4401,94 @@ interactions: x-ratelimit-remaining-requests: - "9999" x-ratelimit-remaining-tokens: - - "29998973" + - "29998527" x-ratelimit-reset-requests: - 6ms x-ratelimit-reset-tokens: - 2ms x-request-id: - - req_25abef45e5a8ca421f8900cf5d52a9e5 + - req_416f4840276b0f148caa877322d15b4a status: code: 200 message: OK - request: body: - '{"messages": [{"role": "system", "content": "Answer in a direct and concise - tone. Your audience is an expert, so be highly specific. If there are ambiguous - terms or acronyms, first define them."}, {"role": "user", "content": "Summarize - the excerpt below to help answer a question.\n\nExcerpt from wellawatteUnknownyearaperspectiveon - pages 15-17: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew - D. White. A perspective on explanations of molecular prediction models. Unknown - journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, doi:10.26434/chemrxiv-2022-qfv02.\n\n----\n\n - on the dataset developed by Martins et al. 124. The\nRF model was implemented - in Scikit-learn125 using Mordred molecular descriptors126 as the\ninput features. - The GRU-RNN model was implemented in Keras.127 See Wellawatte et al. 9\nand - Gandhi and White 10 for more details.\nAccording to the counterfactuals of the - instance molecule in figure 1, we observe that the\nmodifications to the carboxylic - acid group enable the negative example molecule to permeate\nthe BBB. Experimental - findings by Fischer et al. 120 show that the BBB permeation of\nmolecules are - governed by hydrophobic interactions and surface area. The carboxylic group - is\na hydrophilic functional group which hinders hydrophobic interactions and - addition of atoms\nenhances the surface area. This proves the advantage of using - counterfactual explanations,\nas they suggest actionable modification to the - molecule to make it cross the BBB.\nIn Figure 2 we show descriptor explanations - generated for Alprozolam, a molecule that\npermeates the BBB, using the method - described by Gandhi and White 10.\nWe see that\npredicted permeability is positively - correlated with the aromaticity of the molecule, while\n15\nnegatively correlated - with the number of hydrogen bonds donors and acceptors. A similar\nstructure-property - relationship for BBB permeability is proposed in more mechanistic stud-\nies.128\u2013130 - The substructure attributions indicates a reduction in hydrogen bond donors - and\nacceptors. These descriptor explanations are quantitative and interpretable - by chemists.\nFinally, we can use a natural language model to summarize the - findings into a written\nexplanation, as shown in the printed text in Figure - 2.\nFigure 1: Counterfactuals of a molecule which cannot permeate the blood-brain - barrier.\nSimilarity is the Tanimoto similarity of ECFP4 fingerprints.131 Red - indicates deletions and\ngreen indicates substitutions and addition of atoms. - Republished from Ref.9 with permission\nfrom the Royal Society of Chemistry.\nSolubility - prediction\nSmall molecule solubility prediction is a classic cheminformatics - regression challenge and is\nimportant for chemical process design, drug design - and crystallization.133\u2013136 In our previous\nworks,9,10 we implemented - and trained an RNN model in Keras to predict solubilities (log\nmolarity) of - small molecules.127 The AqSolDB curated database137 was used to train the\nRNN - model.\nIn this task, counterfactuals are based on equation 6. Figure 3 illustrates - the generated\nlocal chemical space and the top four counterfactuals. Based - on the counterfactuals, we ob-\nserve that the modifications to the ester group - and other heteroatoms play an important role\nin solubility. These findings - align with known experimental and basic chemical intuition.134\nFigure 4 shows - a quantitative measurement of how substructures are contributing to the pre-\n16\nFigure - 2: Descriptor explanations along with natural language explanation obtained - for BBB\npermeability of Alprozolam molecule. The green and red bars show descriptors - t\n\n----\n\nQuestion: Are counterfactuals actionable? [yes/no]\n\nDo not directly - answer the question, instead summarize to give evidence to help answer the question. - Stay detailed; report specific numbers, equations, or direct quotes (marked - with quotation marks). Reply \"Not applicable\" if the excerpt is irrelevant. - At the end of your response, provide an integer score from 1-10 on a newline - indicating relevance to question. Do not explain your score.\n\nRelevant Information - Summary (about 100 words):"}], "model": "gpt-4o-2024-08-06", "stream": false, - "temperature": 0.0}' + '{"messages": [{"role": "system", "content": "Provide a summary of the relevant + information that could help answer the question based on the excerpt. Respond + with the following JSON format:\n\n{\n \"summary\": \"...\",\n \"relevance_score\": + \"...\"\n}\n\nwhere `summary` is relevant information from text - about 100 + words words and `relevance_score` is the relevance of `summary` to answer question + (out of 10).\n"}, {"role": "user", "content": "Excerpt from wellawatteUnknownyearaperspectiveon + pages 32-35: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew + D. White. A perspective on explanations of molecular prediction models. Journal + of Chemical Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\n----\n\nty Techniques for Graph Convolutional + Net-\nworks. 2019; https://arxiv.org/abs/1905.13686.\n(75) Hochuli, J.; Helbling, + A.; Skaist, T.; Ragoza, M.; Koes, D. R. Visualizing convolutional\nneural network + protein-ligand scoring. Journal of Molecular Graphics and Modelling\n2018, 84, + 96\u2013108.\n(76) Rodr\u00b4\u0131guez-P\u00b4erez, R.; Bajorath, J. Interpretation + of Compound Activity Predictions\nfrom Complex Machine Learning Models Using + Local Approximations and Shapley\nValues. Journal of Medicinal Chemistry 2020, + 63, 8761\u20138777, PMID: 31512867.\n(77) Wojtuch, A.; Jankowski, R.; Podlewska, + S. How can SHAP values help to shape\n32\nmetabolic stability of chemical compounds? + Journal of Cheminformatics 2021, 13,\n1\u201320.\n(78) Mastropietro, A.; Pasculli, + G.; Feldmann, C.; Rodr\u00b4\u0131guez-P\u00b4erez, R.; Bajorath, J. Edge-\nSHAPer: + Bond-Centric Shapley Value-Based Explanation Method for Graph Neural\nNetworks. + iScience 2022, 25, 105043.\n(79) White, A. D. Deep learning for molecules and + materials. Living Journal of Computa-\ntional Molecular Science 2022, 3.\n(80) + \u02d8Strumbelj, E.; Kononenko, I. Explaining prediction models and individual + predictions\nwith feature contributions. Knowledge and Information Systems 2014, + 41, 647\u2013665.\n(81) Erhan, D.; Bengio, Y.; Courville, A.; Vincent, P. Visualizing + Higher-Layer Features of\na Deep Network. Technical Report, Univerist\u00b4e + de Montr\u00b4eal 2009,\n(82) Weber, J. K.; Morrone, J. A.; Bagchi, S.; Pabon, + J. D.; gu Kang, S.; Zhang, L.;\nCornell, W. D. Simplified, interpretable graph + convolutional neural networks for small\nmolecule activity prediction. Journal + of Computer-Aided Molecular Design 2022, 36,\n391\u2013404.\n(83) Riniker, S.; + Landrum, G. A. Similarity maps - A visualization strategy for molecular\nfingerprints + and machine-learning methods. Journal of Cheminformatics 2013, 5, 1\u20137.\n(84) + Humer, C.; Heberle, H.; Montanari, F.; Wolf, T.; Huber, F.; Henderson, R.; Hein-\nrich, + J.; Streit, M. ChemInformatics Model Explorer (CIME): exploratory analysis of\nchemical + model explanations. Journal of Cheminformatics 2022, 14, 1\u201314.\n(85) McGrath, + T.; Kapishnikov, A.; Toma\u02c7sev, N.; Pearce, A.; Wattenberg, M.; Hass-\nabis, + D.; Kim, B.; Paquet, U.; Kramnik, V. Acquisition of chess knowledge in Al-\nphaZero. + Proceedings of the National Academy of Sciences 2022, 119, e2206625119.\n33\n(86) + Bajusz, D.; R\u00b4acz, A.; H\u00b4eberger, K. Why is Tanimoto index an appropriate + choice for\nfingerprint-based similarity calculations? Journal of Cheminformatics + 2015, 7, 1\u201313.\n(87) Huang, Q.; Yamada, M.; Tian, Y.; Singh, D.; Yin, D.; + Chang, Y. GraphLIME:\nLocal Interpretable Model Explanations for Graph Neural + Networks. CoRR 2020,\nabs/2001.06216.\n(88) Sokol, K.; Flach, P. A. LIMEtree: + Interactively Customisable Explanations Based on\nLocal Surrogate Multi-output + Regression Trees. CoRR 2020, abs/2005.01427.\n(89) Whitmore, L. S.; George, + A.; Hudson, C. M. Mapping chemical performance on molec-\nular structures using + locally interpretable explanations. 2016; https://arxiv.org/\nabs/1611.07443.\n(90) + Mehdi, S.; Tiwary, P. Thermodynamics of Interpretation. 2022,\n(91) H\u00a8ofler, + M. Causal inference based on counterfactuals. BMC Medical Research Method-\nology + 2005, 5, 1\u201312.\n(92) Woodward, J.; Hitchcock, C. Explanatory Generalizations, + Part I: A Counterfactual\nAccount. No\u02c6us 2003, 37, 1\u201324.\n(93) Frisch, + M. F. Theories, models, and explanation; University of California, Berkeley,\n1998.\n(94) + Reutlinger, A. Is There A Monist Theory of Causal and Non-Causal Explanations?\nThe + Counterfactual Theory of Scientific Explanation. Philosophy of Science 2016, + 83,\n733\u2013745.\n(95) Lewis, D. Causation. The journal of philosophy 1974, + 70, 556\u2013567.\n(96) Tanimoto, T. T. Elementary mathematical theory of classification + and prediction.\nInternal IBM Technical Report 1958,\n34\n(97) Rogers, D.; Hahn, + M. Extended-Connectivity Fingerprints. Journal of Chemical In-\nformation and + Modeling 2010, 50, 742\u2013754, PMID: 20426451.\n(98) Mohapatra, S.; An, J.; + G\u00b4omez-Bombarelli, R. Chemistry-informed macromolecule\ngraph representation + for similarity computation, unsupervised and supervised learn-\ning. Machine + Learning: Science and Technology 2022, 3, 015028.\n(99) Doshi-Velez, F.; Kortz, + M.; Budish, R.; Bavitz, C.; Gershman, S.; O\u2019Brien, D.;\nScott, K.; Schieber, + S.; Waldo, J.; Weinberger, D.; Weller, A.; Wood, A. Account-\nability of AI + Under the Law: The Role of Explanation. SSRN Electronic Journal\n2017,\n(100) + Wachter, S.; Mittelstadt, B.; Russell, C. Counterfactual explanations without + opening\nthe black box: Automated decisions and the GDPR. Harv. JL & Tech. 2017, + 31, 841.\n(101) Jim\u00b4enez-Luna, J.; Grisoni, F.; Schneider, G. Drug discovery + with explainable artificial\nintelligence. Nature Machine Intelligence 2020 + 2:10 2020, 2, 573\u2013584.\n(102) Fu, T.; Gao, W.; Xiao, C.; Yasonik, J.; Coley, + C. W.; Sun, J. Differentiable Scaffold-\ning Tree for Molecule Optimization. + International Conference on Learning Represen-\ntations. 2022.\n(103) Shen, + C.; Krenn, M.; Eppel, S.; Aspuru-Guzik, A. Deep molecular dreaming: inverse\nmachine + learning \n\n----\n\nQuestion: Are counterfactuals actionable? [yes/no]\n\n"}], + "model": "gpt-4o-2024-08-06", "stream": false, "temperature": 0.0}' headers: accept: - application/json @@ -5408,7 +4497,7 @@ interactions: connection: - keep-alive content-length: - - "4238" + - "6160" content-type: - application/json host: @@ -5430,30 +4519,30 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: !!binary | - H4sIAAAAAAAAAwAAAP//fFRNb9tIDL37VxA6dQHZsBM3X7e4e2kuRbE97KJdGNSI0rAdDQczVBqj - yH9fULKTNMX2IgHDeeR7j+T8WABU3FY3UDmP6oYUlrfvLj98+Ha1u/vz/p/zvwM21I3jx+2d3NKB - qtoQ0nwlpyfUysmQAilLnMMuEypZ1s3l2eX27eZyczEFBmkpGKxPutzK8mx9tl2ur5briyPQCzsq - 1Q18XgAA/Ji+RjG29FDdwLo+nQxUCvZU3TxdAqiyBDupsBQuilGr+jnoJCrFifUnT0APjnJSSFnu - uaUCZL/oCNSjgpMxKuUOnY4YCmAmQGcasQm0gvcKRVGpzNcHabljh3ahgAqoJ3CYG3k4BHaAjlvo - s4wJOALCIIHcGOxOBJpyAqsBE+XB7JsyNEGkXTYZOUKDOTNleLPb7f6oAcsrjkAPKWA8Uihj31PR - F5zBeYw9TewoejSpc7GGA+thBX8lcpOKEA71VB/blg0P0gGqDAU4WncLWQWrTOYM1iD3lJ0MHPsJ - 6A9tluTZtEfUMZOleGXK5EcN3z07D956nMsJKQ07YJM3KygQyVnP8wE6ybDb7U5WscQV3B6Zztw5 - QpEwzsIgZWp5ylL/0leOrbWNftNGKkr52DyMLXhSyjLbYWPh8ugYQw0YuI/mwHdWb+2gzANFxQCd - 1Yl9mRI4T4O5bPpGnvl/8lRsKNFWqUBLg8Si+TQIabLBMJhSYHfsmZn6q6LTdGH+WdDqS/wSr1/u - RKZuLGgrGccQjuePT0sWpE9ZmnKMP513HLn4vQ2CRFuoopKqKfq4APh3Wubxp/2sUpYh6V7lG0VL - eHV9Meernp+P5+jm/PoYVVEMLwLr87f/h9u3pMihvHgUqpkjx/45xfqJ6KS0KoeiNOw7jj3llHl+ - I7q0P+u264vmerM5rxaPi/8AAAD//wMAbVHCmSwFAAA= + H4sIAAAAAAAAAwAAAP//bFTBbtswDL3nKwgdhhVwAifN2iS3YRtWYMAOa7EBmYdAkWlbqyx6ItU2 + K/Lvg+y0TddeDIhPJN/TI30/AlC2VCtQptFi2s6N33+qv31Z03qxbr+bq4oupxHXef71w8fy3WeV + pQza/kYjD1kTQ23nUCz5ATYBtWCqOj2fLfKz03w574GWSnQpre5kPKfxLJ/Nx/linJ8dEhuyBlmt + 4OcIAOC+/yaKvsQ7tYI8e4i0yKxrVKvHSwAqkEsRpZkti/aisifQkBf0Pev7wgMUimPb6rAr1AoK + ddUg4J3B0AkErDCgN8jAeINBO7ilcM0Q0CVlIAR41zntdVLNQBW05NBEpwN0AUtrEgC9YM7AeuNi + aX0N0hAjSKMFSssmMoOh6AVDpY1E7XgClx0aW1mjndtlYAVa9EOfgcV2BxdFUSiqHAZ4O8vzdyeg + fQk/iMpbHUp4AxdWTGPIXPf46cnQsiITGciD0ZG1A+sPQvv0B0kUdlCjT7rt34PCyIn9C6pXDTIe + aHGsa2QZOv13E3RAiIwlWA9sbBJUWfP8FYUg+hJDsq4cKPavmE4dJfOsdkBRDLXIE7ig2+ROBnLk + XUnI4En60tZYcTtg0YJw26A0GF6lpnu/9NZhBg71zWAVwp+I3HOgDn0iaFNqF1AGaludNJHvL/cT + didpGqRBG5LgpPdY5KRQ2TB9AR3eaG9ww4YCDlN4XqjC74/HNmCVrFIr8NG5Q3z/uAeO6i7Qlg/4 + Y7yy3nKzCaiZfJp5FupUj+5HAL/6fYvPVkh1gdpONkLX6Lnf3rPZUFA9rfgRPFseUCHR7ghYLKfZ + KyU3JYq2jo+WVhltGiyfcvPRkb6XbV8rMWi0vn5RZXSopHjHgu2msr5O7tnhN1B1m+n8dLtdzJcz + o0b70T8AAAD//wMABn+Pyg8FAAA= headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c99c969105c1c-SJC + - 8cd6e8057b3bcf0e-SJC Connection: - keep-alive Content-Encoding: @@ -5461,7 +4550,7 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:58 GMT + - Fri, 04 Oct 2024 17:31:36 GMT Server: - cloudflare Transfer-Encoding: @@ -5475,7 +4564,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "1889" + - "1765" openai-version: - "2020-10-01" strict-transport-security: @@ -5487,73 +4576,94 @@ interactions: x-ratelimit-remaining-requests: - "9999" x-ratelimit-remaining-tokens: - - "29998974" + - "29998531" x-ratelimit-reset-requests: - 6ms x-ratelimit-reset-tokens: - 2ms x-request-id: - - req_e2638adada7d4bd806097f0f99594bf7 + - req_a77b91711dfe250fe6c09856b4dc4ef8 status: code: 200 message: OK - request: body: - '{"messages": [{"role": "system", "content": "Answer in a direct and concise - tone. Your audience is an expert, so be highly specific. If there are ambiguous - terms or acronyms, first define them."}, {"role": "user", "content": "Summarize - the excerpt below to help answer a question.\n\nExcerpt from wellawatteUnknownyearaperspectiveon - pages 20-21: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew - D. White. A perspective on explanations of molecular prediction models. Unknown - journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, doi:10.26434/chemrxiv-2022-qfv02.\n\n----\n\ntics - Hamburg) de-\nveloped by Schomburg et al. 132.\n19\nthe \u2018fruity\u2019 scent. - There are some exceptions though, like tert-amyl acetate which has a\n\u2018camphoraceous\u2019 - rather than \u2018fruity\u2019 scent.140,141\nIn Seshadri et al. 31, we trained - a GNN model to predict the scent of molecules and utilized\ncounterfactuals9 - and descriptor explanations10 to quantify scent-structure relationships. The\nMMACE - method was modified to account for the multi-label aspect of scent prediction. - This\nmodification defines molecules that differed from the instance molecule - by only the selected\nscent as counterfactuals. For instance, counterfactuals - of the jasmone molecule would be false\nfor the \u2018jasmine\u2019 scent but - would still be positive for \u2018woody,\u2019 \u2018floral\u2019 and \u2018herbal\u2019 - scents.\nFigure 5: Counterfactual for the 2,4 decadienal molecule.\nThe counterfactual - indicates\nstructural changes to ethyl benzoate that would result in the model - predicting the molecule\nto not contain the \u2018fruity\u2019 scent. The Tanimoto96 - similarity between the counterfactual and\n2,4 decadienal is also provided. - Republished with permission from authors.31\nThe molecule 2,4-decadienal, which - is known to have a \u2018fatty\u2019 scent, is analyzed in Fig-\nure 5.142,143 - The resulting counterfactual, which has a shorter carbon chain and no carbonyl\ngroups, - highlights the influence of these structural features on the \u2018fatty\u2019 - scent of 2,4 deca-\ndienal. To generalize to other molecules, Seshadri et al. - 31 applied the descriptor attribution\nmethod to obtain global explanations - for the scents. The global explanation for the \u2018fatty\u2019\nscent was - generated by gathering chemical spaces around many \u2018fatty\u2019 scented - molecules.\nThe resulting natural language explanation is: \u201cThe molecular - property \u201cfatty scent\u201d can\nbe explained by the presence of a heptanyl - fragment, two CH2 groups separated by four\n20\nbonds, and a C=O double bond, - as well as the lack of more than one or two O atoms.\u201d31\nThe importance - of a heptanyl fragment aligns with that reported in the literature, as \u2018fatty\u2019\nmolecules - often have a long carbon chain.144 Furthermore, the importance of a C=O dou-\nble - bond is supported by the findings reported by Licon et al. 145, where in addition - to a\n\u201clarger carbon-chain skeleton\u201d, they found that \u2018fatty\u2019 - molecules also had \u201caldehyde or acid\nfunctions\u201d.145 For the \u2018pineapple\u2019 - scent, the following natural language explanation was ob-\ntained: \u201cThe - molecular property \u201cpineapple scent\u201d can be explained by the presence - of ester,\nethyl/ether O group, alkene/ether O group, and C=O double bond, as - well as the absence of\nan Aromatic atom.\u201d31 Esters, such as ethyl 2-methylbutyrate, - are present in many pineap-\nple volatile compounds.146,147 The combination - of a C=O double bond with an ether could\nalso correspond to an ester group. - Additionally, aldehydes and ketones, which contain C=O\ndouble bonds, are also - common in pineapple volatile compounds.146,148\nDiscussion\nWe have shown two - post-hoc XAI applications based on molecular counterfactual expla-\nnation\n\n----\n\nQuestion: - Are counterfactuals actionable? [yes/no]\n\nDo not directly answer the question, - instead summarize to give evidence to help answer the question. Stay detailed; - report specific numbers, equations, or direct quotes (marked with quotation - marks). Reply \"Not applicable\" if the excerpt is irrelevant. At the end of - your response, provide an integer score from 1-10 on a newline indicating relevance - to question. Do not explain your score.\n\nRelevant Information Summary (about - 100 words):"}], "model": "gpt-4o-2024-08-06", "stream": false, "temperature": - 0.0}' + '{"messages": [{"role": "system", "content": "Provide a summary of the relevant + information that could help answer the question based on the excerpt. Respond + with the following JSON format:\n\n{\n \"summary\": \"...\",\n \"relevance_score\": + \"...\"\n}\n\nwhere `summary` is relevant information from text - about 100 + words words and `relevance_score` is the relevance of `summary` to answer question + (out of 10).\n"}, {"role": "user", "content": "Excerpt from wellawatteUnknownyearaperspectiveon + pages 6-8: Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew D. + White. A perspective on explanations of molecular prediction models. Journal + of Chemical Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\n----\n\nion and not-actionable because\nthey + do not provide a set of features which changes the outcome.46 Ribeiro et al. + 35 proposed\na surrogate model method that aims to provide sparse/succinct explanations + that have high\n5\nfidelity to the original model. In Wellawatte et al. 9 we + argue that counterfactuals are \u201cbet-\nter\u201d explanations because they + are actionable and sparse. We highlight that, evaluation of\nexplanations is + a difficult task because explanations are fundamentally for and by humans.\nTherefore, + these evaluations are subjective, as they depend on \u201ccomplex human factors + and\napplication scenarios.\u201d37\nSelf-explaining models\nA self-explanatory + model is one that is intrinsically interpretable to an expert.47 Two com-\nmon + examples found in the literature are linear regression models and decision trees + (DT).\nIntrinsic models can be found in other XAI applications acting as surrogate + models (proxy\nmodels) due to their transparent nature.48,49 A linear model + is described by the equation\n1 where, W\u2019s are the weight parameters and + x\u2019s are the input features associated with the\nprediction \u02c6y. Therefore, + we observe that the weights can be used to derive a complete expla-\nnation + of the model - trained weights quantify the importance of each feature.47 DT + models\nare another type of self-explaining models which have been used in classification + and high-\nthroughput screening tasks. Gajewicz et al. 50 used DT models to + classify nanomaterials\nthat identify structural features responsible for surface + activity. In another study by Han\net al. 51, a DT model was developed to filter + compounds by their bioactivity based on the\nchemical fingerprints.\n\u02c6y + = \u03a3iWixi\n(1)\nRegularization techniques such as EXPO52 and RRR53 are designed + to enhance the black-\nbox model interpretability.54 Although one can argue + that \u201csimplicity\u201d of models are posi-\ntively correlated with interpretability, + this is based on how the interpretability is evaluated.\nFor example, Lipton + 55 argue that, from the notion of \u201csimulatability\u201d (the degree to + which a\nhuman can predict the outcome based on inputs), self-explanatory linear + models, rule-based\n6\nsystems, and DT\u2019s can be claimed uninterpretable. + A human can predict the outcome given\nthe inputs only if the input features + are interpretable. Therefore, a linear model which takes\nin non-descriptive + inputs may not be as transparent. On the other hand, a linear model\nis not + innately accurate as they fail to capture non-linear relationships in data, + limiting is\napplicability. Similarly, a DT is a rule-based model and lacks + physics informed knowledge.\nTherefore, an existing drawback is the trade-off + between the degree of understandability and\nthe accuracy of a model. For example, + an intrinsic model (linear regression or decision trees)\ncan be described through + the trainable parameters, but it may fail to \u201ccorrectly\u201d capture\nnon-linear + relations in the data.\nAttribution methods\nFeature attribution methods explain + black box predictions by assigning each input feature\na numerical value, which + indicates its importance or contribution to the prediction. Feature\nattributions + provide local explanations, but can be averaged or combined to explain multi-\nple + instances. Atom-based numerical assignments are commonly referred to as heatmaps.56\nSheridan + 57 describes an atom-wise attribution method for interpreting QSAR models. Re-\ncently, + Rasmussen et al. 58 showed that Crippen logP models serve as a benchmark for\nheatmap + approaches. Other most widely used feature attribution approaches in the litera-\nture + are gradient based methods,59,60 Shapley Additive exPlanations (SHAP),44 and + layer-\nwise relevance prorogation.61\nGradient based approaches are based on + the hypothesis that gradients for neural net-\nworks are analogous to coefficients + for regression models.62 Class activation maps (CAM),63\ngradCAM,64 smoothGrad,,65 + and integrated gradients62 are examples of this method. The\nmain idea behind + feature attributions with gradients can be represented with equation 2.\n\u2206\u02c6f(\u20d7x)\n\u2206xi\n\u2248\u2202\u02c6f(\u20d7x)\n\u2202xi\n(2)\n7\nwhere + \u02c6f(x) is the black-box model and\n\u2206\u02c6f(\u20d7x)\n\u2206xi\nare + used as our attributions. The left-\nhand side of equation 2 says that we attribute + each input feature xi by how much one unit\nchange in it would affect the output + of \u02c6f(x). If \u02c6f(x) is a linear surrogate model, then this\nmethod + reconciles with LIME.35 In DL models, \u2207xf(x), suffers from the shattered + gradients\nproblem.62 This means directly computing the quantity leads to numeric + problems. The\ndifferent gradient based approaches are mostly distinguishable + based on how the gradient is\napproximated.\nGradient based explanations have + been widely used to interpret chemistry predictions.60,66\u201370\nMcCloskey + et al. 60 used graph convolutional networks (GCNs) to predict protein-ligand\nbinding + and explained the binding logic for these predictions using integrated gradients.\nPope + et al. 66 and Jim\u00b4enez-Luna et al. 67 show application of gradCAM and integrated + gradi-\nents to explain molecular prope\n\n----\n\nQuestion: Are counterfactuals + actionable? [yes/no]\n\n"}], "model": "gpt-4o-2024-08-06", "stream": false, + "temperature": 0.0}' headers: accept: - application/json @@ -5562,7 +4672,7 @@ interactions: connection: - keep-alive content-length: - - "4438" + - "6176" content-type: - application/json host: @@ -5584,30 +4694,29 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: !!binary | - H4sIAAAAAAAAA3RTy24bORC86ysac5YESVbixy0IkCwSxLuH7F7WgdBDNmeY5bAH7KZtJTDgz3B+ - z1+yICXLioNcBpiu6mb1o75PABpvmwtoTI9qhjHM3rw9/fOy++fjt/78wx/DX98+fn7/4dPf1+31 - p607a6Ylg9uvZPQpa254GAOp57iDTSJUKlWXp6vT9avl6fJVBQa2FEpaN+pszbPVYrWeLc5mi9f7 - xJ69IWku4N8JAMD3+i0So6Xb5gIW06fIQCLYUXNxIAE0iUOJNCjiRTFqM30GDUelWFV/7gno1lAa - FawXk0VIQHuCLATswHCOSsmh0YxBwEcYE1lv1McOBg5kcsAEYiiqQJYSRnh/eQm1xzm8fVEBE4El - 5yNZQHkqQQLWO0ep5LvEQxXhYxFv6MCCdgscw7aiQoGMkt09Pod3nIBusaxg+otwdjXnK8rA8ajg - DedgoSVwGITAcaq8x/uHQvWRHu9/7B6ANiuMLF799Y74eP9ww2y308J5vH9wgROG+ofRlkhPqcVw - KCFzKBPHiGErvopaTdczSwatp4gBpOebsgBUEE3ZaE4YwPQYO5IpSDZ9mRoWYlJKYDC1HAvDx/oq - tkJlZGV5FdsG6BLnUabgowu5ol6lKkbV7UFeUecFJHcdie5lvBykwXICfO0tAZpy69iGuirf9Spl - Qz5ab7BeiIxkvPPmuJuBbQlhyRWIRJYsKAOG0tBu1k9HxlHmV/Eqnh0fcCKXBYt/Yg5hH787OCJw - NyZuZY8f4s5HL/0mEQrHcv2iPDYVvZsAfKnOyz+ZqRkTD6NulP+jWAqen5/s6jXPXn9Gl+u9Lxtl - xXAELE9+m7expOiDHDm42Wn0sXsusTgIrZ02shWlYeN87CiNye8M7cbNyq0Xr9vz5fKkmdxN/gcA - AP//AwDzfvso2QQAAA== + H4sIAAAAAAAAAwAAAP//dFPBbtswDL3nKwhdekkCJ027JrcCHbBhPQ0t0GEZAlqmba2yJIhUlq7I + vw+W0zRFu4sPfOR7fPTT8whAmUqtQOkWRXfBTq4/N99vb+5vv92UzY97Sn93Xx7m+s/D9cVjXapx + P+HL36TlZWqqfRcsifFugHUkFOpZZ5/mV8XlebG8yEDnK7L9WBNksvCTeTFfTIqrSXF5GGy90cRq + BT9HAADP+duv6CraqRUU45dKR8zYkFodmwBU9LavKGQ2LOhEjV9B7Z2Qy1s/rx3AWnHqOoxPa7WC + tbprCWinKQaByrBOzMQgLYH2TlMQ8DVon5xQrFFLQstg3EuH0C530C5YdNgfg6H2ETpvSSeLEUKk + yugegXwInsJXAYxNykIo7+gxZm42FUWq4KwkEYpnb0VK0piY+kWe8kTppQXMQlhaAnQVcMDINIW7 + 1jBwahpi+Y9oiH5rKgIEpmypJpQUjzuiA92ia7Ii+CTadzSGDh+Na/padyLeKxLk46BlD61pWmua + VobTcspJMlsCl0XyCbdoE0rPdmp0DMiDyYoCuQq8gyF5O2hThw56Cz5yNowhWKPzJLAmh9F4nq7V + ePj1kSxt0WnasPaRhggs12rt9qeZiVQnxj6yLll7qO+PIbS+CdGXfMCP9do4w+0mErJ3feBYfFAZ + 3Y8AfuWwpzf5VSH6LshG/CO5nnB2PrsaCNXr+zqBi9kBFS9oT4DFbDn+gHJTkaCxfPJilEbdUvU6 + W4xO/L2X/Yhi8Ghc845ldGBS/MRC3aY2rqEYohneYB0283pRXJbL2excjfajfwAAAP//AwAz7V0o + jAQAAA== headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c99c84da3252d-SJC + - 8cd6e809fa1dcf13-SJC Connection: - keep-alive Content-Encoding: @@ -5615,7 +4724,7 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:41:58 GMT + - Fri, 04 Oct 2024 17:31:36 GMT Server: - cloudflare Transfer-Encoding: @@ -5629,7 +4738,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "2157" + - "1392" openai-version: - "2020-10-01" strict-transport-security: @@ -5641,13 +4750,13 @@ interactions: x-ratelimit-remaining-requests: - "9999" x-ratelimit-remaining-tokens: - - "29998954" + - "29998527" x-ratelimit-reset-requests: - 6ms x-ratelimit-reset-tokens: - 2ms x-request-id: - - req_6afb578836c2390464966ed7361e5365 + - req_6a1ac0aff8e764cdd823a71c348d0e11 status: code: 200 message: OK @@ -5657,70 +4766,59 @@ interactions: tone. Your audience is an expert, so be highly specific. If there are ambiguous terms or acronyms, first define them."}, {"role": "user", "content": "Answer the question below with the context.\n\nContext (with relevance scores):\n\nwellawatteUnknownyearaperspectiveon - pages 11-12: Counterfactual explanations are described as actionable in the - context of XAI (Explainable Artificial Intelligence) for chemistry. They are - used to determine \"which smallest change could alter the outcome of an instance - of interest,\" indicating their actionable nature. The excerpt explains that - counterfactuals are generated by minimizing the vector distance \\(d(x, x'')\\) - between features, subject to a change in prediction \\(\\hat{f}(x) \\neq \\hat{f}(x'')\\) - for classification tasks, and \\(|\\hat{f}(x) - \\hat{f}(x'')| \\geq \\Delta\\) - for regression tasks. This suggests that counterfactuals provide \"intuitive - understanding of predictions\" and can uncover spurious relationships, making - them actionable at the instance level.\n\n9\nFrom Geemi P. Wellawatte, Heta - A. Gandhi, Aditi Seshadri, and Andrew D. White. A perspective on explanations - of molecular prediction models. Unknown journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, - doi:10.26434/chemrxiv-2022-qfv02.\n\nwellawatteUnknownyearaperspectiveon pages - 15-17: The excerpt provides evidence that counterfactuals are actionable. It - states that modifications to the carboxylic acid group in a molecule can enable - it to permeate the blood-brain barrier (BBB), as counterfactual explanations - suggest actionable changes to enhance permeability. Specifically, the addition - of atoms increases surface area, overcoming the hydrophilic nature of the carboxylic - group, which hinders hydrophobic interactions necessary for BBB permeation. - Additionally, in solubility prediction, counterfactuals indicate that modifications - to the ester group and heteroatoms are crucial, aligning with experimental findings - and chemical intuition. These examples demonstrate the practical applicability - of counterfactuals in molecular modifications.\n\n9\nFrom Geemi P. Wellawatte, - Heta A. Gandhi, Aditi Seshadri, and Andrew D. White. A perspective on explanations - of molecular prediction models. Unknown journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, - doi:10.26434/chemrxiv-2022-qfv02.\n\nwellawatteUnknownyearaperspectiveon pages - 5-7: The excerpt discusses the evaluation of explanation methods for molecular - prediction models, focusing on attributes like fidelity, robustness, and sparsity. - It mentions that Shapley values, while providing a complete explanation, are - not actionable because they do not offer a set of features that change the outcome. - In contrast, the authors argue that counterfactuals are \"better\" explanations - because they are both actionable and sparse. This suggests that counterfactuals - provide actionable insights by identifying specific changes that can alter the - prediction outcome, making them useful for decision-making processes.\n\n9\nFrom + pages 10-13: Counterfactual explanations are actionable as they provide intuitive + understanding of predictions and suggest which features can be altered to change + the outcome. For example, changing a hydrophobic functional group in a molecule + to a hydrophilic group to increase solubility. This actionability indicates + that counterfactuals can guide modifications to achieve desired changes in predictions, + making them a useful tool for explainable AI (XAI) in chemistry.\nFrom Geemi + P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew D. White. A perspective + on explanations of molecular prediction models. Journal of Chemical Theory and + Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, doi:10.1021/acs.jctc.2c01235.\n\nwellawatteUnknownyearaperspectiveon + pages 18-21: The excerpt discusses the use of counterfactuals in explaining + molecular prediction models, particularly in scent prediction. Counterfactuals + are used to identify structural changes in molecules that would alter their + predicted properties, such as scent. For example, a counterfactual for the molecule + 2,4-decadienal, which has a ''fatty'' scent, suggests structural changes that + would result in a different scent prediction. This indicates that counterfactuals + can provide actionable insights by suggesting specific molecular modifications + to achieve desired properties.\nFrom Geemi P. Wellawatte, Heta A. Gandhi, Aditi + Seshadri, and Andrew D. White. A perspective on explanations of molecular prediction + models. Journal of Chemical Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\nwellawatteUnknownyearaperspectiveon pages 15-18: + Counterfactual explanations are indeed actionable. The excerpt discusses how + counterfactuals were used to explain a random forest model''s predictions regarding + blood-brain barrier (BBB) permeation. By modifying the carboxylic acid group, + which is hydrophilic and hinders hydrophobic interactions, the counterfactuals + suggested actionable changes that could enable a molecule to permeate the BBB. + This demonstrates the practical utility of counterfactuals in suggesting modifications + to molecular structures to achieve desired properties, such as increased permeability.\nFrom Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew D. White. A - perspective on explanations of molecular prediction models. Unknown journal, - Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, doi:10.26434/chemrxiv-2022-qfv02.\n\nwellawatteUnknownyearaperspectiveon - pages 12-14: Counterfactuals are described as providing \"local (instance-level), - actionable explanations.\" The actionability of a counterfactual explanation - is demonstrated by suggesting which features can be altered to change the outcome, - such as modifying a hydrophobic functional group in a molecule to a hydrophilic - one to increase solubility. The excerpt discusses various methods for generating - counterfactuals, including CF-GNNExplainer, MEG, and MMACE, each with different - approaches and limitations. Despite these methods, the excerpt notes that counterfactual - explanation-based model interpretation is less explored compared to other post-hoc - methods.\n\n8\nFrom Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and - Andrew D. White. A perspective on explanations of molecular prediction models. - Unknown journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, - doi:10.26434/chemrxiv-2022-qfv02.\n\nwellawatteUnknownyearaperspectiveon pages - 35-36: The excerpt references several works related to counterfactual explanations, - which are a method for providing interpretability in AI models. Specifically, discuss - counterfactual explanations in the context of automated decisions and the General - Data Protection Regulation (GDPR), suggesting their potential role in legal - accountability. and Numeroso & Bacciu (2020) explore counterfactual explanations - for Graph Neural Networks, indicating their applicability in complex model interpretability. - Freiesleben (2022) examines the relationship between counterfactual explanations - and adversarial examples, which may imply actionability in terms of model robustness - and decision-making.\n\n8\nFrom Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, - and Andrew D. White. A perspective on explanations of molecular prediction models. - Unknown journal, Unknown year. URL: https://doi.org/10.26434/chemrxiv-2022-qfv02, - doi:10.26434/chemrxiv-2022-qfv02.\n\nValid keys: wellawatteUnknownyearaperspectiveon - pages 11-12, wellawatteUnknownyearaperspectiveon pages 15-17, wellawatteUnknownyearaperspectiveon - pages 5-7, wellawatteUnknownyearaperspectiveon pages 12-14, wellawatteUnknownyearaperspectiveon - pages 35-36\n\n----\n\nQuestion: Are counterfactuals actionable? [yes/no]\n\nWrite + perspective on explanations of molecular prediction models. Journal of Chemical + Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\nwellawatteUnknownyearaperspectiveon pages 21-24: + Counterfactual explanations are described as actionable in the context of molecular + prediction models. They are represented as chemical structures, which are familiar + to domain experts, and are sparse, making them useful for understanding and + potentially altering outcomes. The text emphasizes the utility of counterfactuals + in providing actionable insights by contrasting chemical properties with minimal + distance from a base molecule.\nFrom Geemi P. Wellawatte, Heta A. Gandhi, Aditi + Seshadri, and Andrew D. White. A perspective on explanations of molecular prediction + models. Journal of Chemical Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\nwellawatteUnknownyearaperspectiveon pages 6-8: + The excerpt discusses the concept of counterfactuals in the context of explanations + for molecular prediction models. It argues that counterfactuals are considered + ''better'' explanations because they are both actionable and sparse. This suggests + that counterfactuals provide a set of features that can change the outcome, + making them actionable. The text also highlights the subjective nature of evaluating + explanations, as they depend on complex human factors and application scenarios.\nFrom + Geemi P. Wellawatte, Heta A. Gandhi, Aditi Seshadri, and Andrew D. White. A + perspective on explanations of molecular prediction models. Journal of Chemical + Theory and Computation, Unknown year. URL: https://doi.org/10.1021/acs.jctc.2c01235, + doi:10.1021/acs.jctc.2c01235.\n\nValid keys: wellawatteUnknownyearaperspectiveon + pages 10-13, wellawatteUnknownyearaperspectiveon pages 18-21, wellawatteUnknownyearaperspectiveon + pages 15-18, wellawatteUnknownyearaperspectiveon pages 21-24, wellawatteUnknownyearaperspectiveon + pages 6-8\n\n----\n\nQuestion: Are counterfactuals actionable? [yes/no]\n\nWrite an answer based on the context. If the context provides insufficient information reply \"I cannot answer.\"For each part of your answer, indicate which sources most support it via citation keys at the end of sentences, like (Example2012Example @@ -5739,7 +4837,7 @@ interactions: connection: - keep-alive content-length: - - "6452" + - "5582" content-type: - application/json host: @@ -5761,35 +4859,34 @@ interactions: x-stainless-runtime: - CPython x-stainless-runtime-version: - - 3.12.6 + - 3.12.1 method: POST uri: https://api.openai.com/v1/chat/completions response: body: string: !!binary | - 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 headers: CF-Cache-Status: - DYNAMIC CF-RAY: - - 8c9c99d72a4a22de-SJC + - 8cd6e813db92230a-SJC Connection: - keep-alive Content-Encoding: @@ -5797,14 +4894,14 @@ interactions: Content-Type: - application/json Date: - - Fri, 27 Sep 2024 15:42:02 GMT + - Fri, 04 Oct 2024 17:31:39 GMT Server: - cloudflare Set-Cookie: - - __cf_bm=LWPff5zX3ICbbT9QScjPn280Ah9S0inGrZ6ybIIewDI-1727451722-1.0.1.1-q5KgaN4N5L0dHLZN75tHjBW_AtJ5vsnl6zmfkPZuX3nQb6ofrTsGnI.tov8..L6pDl6EchlzSw2ix2jwjXBTjQ; - path=/; expires=Fri, 27-Sep-24 16:12:02 GMT; domain=.api.openai.com; HttpOnly; + - __cf_bm=fAVtLQKo_XdaEefy4ERbK3I.nw64KSOcdXYbwYOddHw-1728063099-1.0.1.1-x2GGg.rHzUu7w.Uqmwt7ncEoFuILmK36pjnYaiHx5tkbiRekJbahNmPLwOMgQXQag3tqFOLNJC3.pK0wPQzWgQ; + path=/; expires=Fri, 04-Oct-24 18:01:39 GMT; domain=.api.openai.com; HttpOnly; Secure; SameSite=None - - _cfuvid=PWVdd0wya80sePSgKjRZyOELFVjKfBs7ecUlL0T1EI0-1727451722792-0.0.1.1-604800000; + - _cfuvid=HF7UufgdpbluKchhJJGTkKtLz4HVndyy5FdI4E1qFqs-1728063099932-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None Transfer-Encoding: - chunked @@ -5817,7 +4914,7 @@ interactions: openai-organization: - future-house-xr4tdh openai-processing-ms: - - "3986" + - "2780" openai-version: - "2020-10-01" strict-transport-security: @@ -5829,13 +4926,13 @@ interactions: x-ratelimit-remaining-requests: - "9999" x-ratelimit-remaining-tokens: - - "29998421" + - "29998630" x-ratelimit-reset-requests: - 6ms x-ratelimit-reset-tokens: - - 3ms + - 2ms x-request-id: - - req_9670a7a1e5925640b8feb8354787ee0e + - req_3c3be9ae3d91412d611fea4a56a8d10e status: code: 200 message: OK diff --git a/tests/test_paperqa.py b/tests/test_paperqa.py index 106a583e..6a2d6f7a 100644 --- a/tests/test_paperqa.py +++ b/tests/test_paperqa.py @@ -840,7 +840,9 @@ def test_pdf_reader_match_doc_details(stub_data_dir: Path) -> None: fields=["author", "journal"], ) doc_details = next(iter(docs.docs.values())) - assert doc_details.dockey == "5300ef1d5fb960d7" + # Crossref is non-deterministic in its ordering for results + # thus we need to capture both possible dockeys + assert doc_details.dockey in {"d7763485f06aabde", "5300ef1d5fb960d7"} assert isinstance(doc_details, DocDetails) # note year is unknown because citation string is only parsed for authors/title/doi # AND we do not request it back from the metadata sources @@ -852,7 +854,10 @@ def test_pdf_reader_match_doc_details(stub_data_dir: Path) -> None: "Aditi Seshadri", "Andrew D. White", } - assert doc_details.doi == "10.26434/chemrxiv-2022-qfv02" + assert doc_details.doi in { + "10.1021/acs.jctc.2c01235", + "10.26434/chemrxiv-2022-qfv02", + } num_retries = 3 for _ in range(num_retries): answer = docs.query("Are counterfactuals actionable? [yes/no]") From 45fe0f837b5022211e7f39852162f3b2ad37b33b Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Fri, 4 Oct 2024 10:51:59 -0700 Subject: [PATCH 18/20] move debug.json settings under parsing heading --- paperqa/configs/debug.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/paperqa/configs/debug.json b/paperqa/configs/debug.json index 160aeb2d..722f8ba2 100644 --- a/paperqa/configs/debug.json +++ b/paperqa/configs/debug.json @@ -10,11 +10,10 @@ "max_concurrent_requests": 5 }, "parsing": { - "use_doc_details": false - }, - "prompts": { - "use_json": false, "use_doc_details": false, "defer_embedding": true + }, + "prompts": { + "use_json": false } } From 5f8948e641891b41a71237c38cc4374fc27a7c7e Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Fri, 4 Oct 2024 12:39:57 -0700 Subject: [PATCH 19/20] ensure test_gather_evidence_rejects_empty_docs uses the paper stub directory --- tests/test_agents.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_agents.py b/tests/test_agents.py index c4e93945..4f1fce55 100644 --- a/tests/test_agents.py +++ b/tests/test_agents.py @@ -311,7 +311,9 @@ async def test_propagate_options(agent_test_settings: Settings) -> None: @pytest.mark.asyncio -async def test_gather_evidence_rejects_empty_docs() -> None: +async def test_gather_evidence_rejects_empty_docs( + agent_test_settings: Settings, +) -> None: # Patch GenerateAnswerTool._arun so that if this tool is chosen first, we # don't give a 'cannot answer' response. A 'cannot answer' response can # lead to an unsure status, which will break this test's assertions. Since @@ -325,14 +327,12 @@ async def test_gather_evidence_rejects_empty_docs() -> None: autospec=True, ) as mock_gen_answer: mock_gen_answer.__doc__ = original_doc - settings = Settings( - agent=AgentSettings( - tool_names={"gather_evidence", "gen_answer"}, max_timesteps=3 - ) + agent_test_settings.agent = AgentSettings( + tool_names={"gather_evidence", "gen_answer"}, max_timesteps=3 ) response = await agent_query( query=QueryRequest( - query="Are COVID-19 vaccines effective?", settings=settings + query="Are COVID-19 vaccines effective?", settings=agent_test_settings ), docs=Docs(), ) From 546e6d23e837a7a694ac355d902dccabb1d16525 Mon Sep 17 00:00:00 2001 From: Michael Skarlinski Date: Fri, 4 Oct 2024 14:30:13 -0700 Subject: [PATCH 20/20] ensure test_gather_evidence_rejects_empty_docs uses the paper stub directory --- tests/test_agents.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/test_agents.py b/tests/test_agents.py index 4f1fce55..d561afb2 100644 --- a/tests/test_agents.py +++ b/tests/test_agents.py @@ -35,7 +35,7 @@ make_status, ) from paperqa.docs import Docs -from paperqa.settings import AgentSettings, Settings +from paperqa.settings import AgentSettings, IndexSettings, Settings from paperqa.types import Answer, Context, Doc, Text from paperqa.utils import extract_thought, get_year, md5sum @@ -328,7 +328,13 @@ async def test_gather_evidence_rejects_empty_docs( ) as mock_gen_answer: mock_gen_answer.__doc__ = original_doc agent_test_settings.agent = AgentSettings( - tool_names={"gather_evidence", "gen_answer"}, max_timesteps=3 + tool_names={"gather_evidence", "gen_answer"}, + max_timesteps=3, + search_count=agent_test_settings.agent.search_count, + index=IndexSettings( + paper_directory=agent_test_settings.agent.index.paper_directory, + index_directory=agent_test_settings.agent.index.index_directory, + ), ) response = await agent_query( query=QueryRequest(