From ad9777bc2d16c2a812d512bcc3e874ffb553c46e Mon Sep 17 00:00:00 2001 From: Michael Ekstrand Date: Tue, 31 Dec 2024 13:36:37 -0600 Subject: [PATCH 1/7] add a LensKit proxy logger to filter by default --- lenskit/lenskit/logging/__init__.py | 15 ++++++++++++++- lenskit/lenskit/logging/_proxy.py | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 lenskit/lenskit/logging/_proxy.py diff --git a/lenskit/lenskit/logging/__init__.py b/lenskit/lenskit/logging/__init__.py index 184968bc1..ef9e05663 100644 --- a/lenskit/lenskit/logging/__init__.py +++ b/lenskit/lenskit/logging/__init__.py @@ -7,6 +7,7 @@ import structlog +from ._proxy import LenskitProxyLogger from .config import LoggingConfig, basic_logging from .progress import Progress, item_progress, set_progress_impl from .tasks import Task @@ -22,16 +23,28 @@ "trace", ] -get_logger = structlog.stdlib.get_logger _trace_debug = os.environ.get("LK_TRACE", "no").lower() == "debug" +def get_logger(name) -> structlog.stdlib.BoundLogger: + """ + Get a logger. This works like :func:`structlog.stdlib.get_logger`, except + the returned proxy logger is quiet (only WARN and higher messages) if + structlog has not been configured. LensKit code should use this instead of + obtaining loggers from Structlog directly. + """ + return LenskitProxyLogger(None, logger_factory_args=[name]) # type: ignore + + def trace(logger: structlog.stdlib.BoundLogger, *args: Any, **kwargs: Any): """ Emit a trace-level message, if LensKit tracing is enabled. Trace-level messages are more fine-grained than debug-level messages, and you usually don't want them. + This function does not work on the lazy proxies returned by + :func:`get_logger` and similar — it only works on bound loggers. + Stability: Caller """ diff --git a/lenskit/lenskit/logging/_proxy.py b/lenskit/lenskit/logging/_proxy.py new file mode 100644 index 000000000..fa6d96e09 --- /dev/null +++ b/lenskit/lenskit/logging/_proxy.py @@ -0,0 +1,22 @@ +import logging +from typing import Any + +import structlog +from structlog._config import BoundLoggerLazyProxy + +_fallback_wrapper = structlog.make_filtering_bound_logger(logging.WARNING) + + +class LenskitProxyLogger(BoundLoggerLazyProxy): + """ + Lazy proxy logger for LensKit. This is based on Structlog's lazy proxy, + with using a filtering logger by default when structlog is not configured. + """ + + def bind(self, **new_values: Any): + if structlog.is_configured: + self._wrapper_class = None + else: + self._wrapper_class = _fallback_wrapper + + return super().bind(**new_values) From 7607abfafea4a4b5d42e0f0ca362375ee26075ca Mon Sep 17 00:00:00 2001 From: Michael Ekstrand Date: Tue, 31 Dec 2024 13:42:40 -0600 Subject: [PATCH 2/7] use get_logger across the codebae --- lenskit/lenskit/data/movielens.py | 5 +++-- lenskit/lenskit/knn/item.py | 5 ++--- lenskit/lenskit/knn/user.py | 3 ++- lenskit/lenskit/logging/__init__.py | 12 +----------- lenskit/lenskit/logging/_proxy.py | 10 ++++++++++ lenskit/lenskit/logging/monitor.py | 3 ++- lenskit/lenskit/logging/progress/_rich.py | 3 ++- lenskit/lenskit/logging/resource.py | 5 +++-- lenskit/lenskit/logging/tasks.py | 4 ++-- lenskit/lenskit/logging/worker.py | 3 ++- lenskit/lenskit/parallel/pool.py | 5 ++--- lenskit/lenskit/parallel/worker.py | 5 +++-- lenskit/lenskit/pipeline/__init__.py | 4 ++-- lenskit/lenskit/testing/_movielens.py | 4 ++-- 14 files changed, 38 insertions(+), 33 deletions(-) diff --git a/lenskit/lenskit/data/movielens.py b/lenskit/lenskit/data/movielens.py index 581a27e4c..c57adc3fa 100644 --- a/lenskit/lenskit/data/movielens.py +++ b/lenskit/lenskit/data/movielens.py @@ -17,12 +17,13 @@ import numpy as np import pandas as pd -import structlog + +from lenskit.logging import get_logger from .convert import from_interactions_df from .dataset import Dataset -_log = structlog.stdlib.get_logger(__name__) +_log = get_logger(__name__) LOC: TypeAlias = Path | tuple[ZipFile, str] diff --git a/lenskit/lenskit/knn/item.py b/lenskit/lenskit/knn/item.py index ec0c62e01..f06e8d004 100644 --- a/lenskit/lenskit/knn/item.py +++ b/lenskit/lenskit/knn/item.py @@ -14,7 +14,6 @@ import warnings import numpy as np -import structlog import torch from scipy.sparse import csr_array from typing_extensions import Optional, override @@ -22,14 +21,14 @@ from lenskit import util from lenskit.data import Dataset, FeedbackType, ItemList, QueryInput, RecQuery, Vocabulary from lenskit.diagnostics import DataWarning -from lenskit.logging import trace +from lenskit.logging import get_logger, trace from lenskit.logging.progress import item_progress_handle, pbh_update from lenskit.math.sparse import normalize_sparse_rows, safe_spmv from lenskit.parallel import ensure_parallel_init from lenskit.pipeline import Component, Trainable from lenskit.util.torch import inference_mode -_log = structlog.stdlib.get_logger(__name__) +_log = get_logger(__name__) MAX_BLOCKS = 1024 diff --git a/lenskit/lenskit/knn/user.py b/lenskit/lenskit/knn/user.py index fa117ff29..839cb6acd 100644 --- a/lenskit/lenskit/knn/user.py +++ b/lenskit/lenskit/knn/user.py @@ -24,11 +24,12 @@ from lenskit.data import Dataset, FeedbackType, ItemList, QueryInput, RecQuery from lenskit.data.vocab import Vocabulary from lenskit.diagnostics import DataWarning +from lenskit.logging import get_logger from lenskit.math.sparse import normalize_sparse_rows, safe_spmv, torch_sparse_to_scipy from lenskit.parallel.config import ensure_parallel_init from lenskit.pipeline import Component, Trainable -_log = structlog.stdlib.get_logger(__name__) +_log = get_logger(__name__) class UserKNNScorer(Component, Trainable): diff --git a/lenskit/lenskit/logging/__init__.py b/lenskit/lenskit/logging/__init__.py index ef9e05663..c9a8a84c3 100644 --- a/lenskit/lenskit/logging/__init__.py +++ b/lenskit/lenskit/logging/__init__.py @@ -7,7 +7,7 @@ import structlog -from ._proxy import LenskitProxyLogger +from ._proxy import get_logger from .config import LoggingConfig, basic_logging from .progress import Progress, item_progress, set_progress_impl from .tasks import Task @@ -26,16 +26,6 @@ _trace_debug = os.environ.get("LK_TRACE", "no").lower() == "debug" -def get_logger(name) -> structlog.stdlib.BoundLogger: - """ - Get a logger. This works like :func:`structlog.stdlib.get_logger`, except - the returned proxy logger is quiet (only WARN and higher messages) if - structlog has not been configured. LensKit code should use this instead of - obtaining loggers from Structlog directly. - """ - return LenskitProxyLogger(None, logger_factory_args=[name]) # type: ignore - - def trace(logger: structlog.stdlib.BoundLogger, *args: Any, **kwargs: Any): """ Emit a trace-level message, if LensKit tracing is enabled. Trace-level diff --git a/lenskit/lenskit/logging/_proxy.py b/lenskit/lenskit/logging/_proxy.py index fa6d96e09..f7c9fcd8f 100644 --- a/lenskit/lenskit/logging/_proxy.py +++ b/lenskit/lenskit/logging/_proxy.py @@ -7,6 +7,16 @@ _fallback_wrapper = structlog.make_filtering_bound_logger(logging.WARNING) +def get_logger(name: str) -> structlog.stdlib.BoundLogger: + """ + Get a logger. This works like :func:`structlog.stdlib.get_logger`, except + the returned proxy logger is quiet (only WARN and higher messages) if + structlog has not been configured. LensKit code should use this instead of + obtaining loggers from Structlog directly. + """ + return LenskitProxyLogger(None, logger_factory_args=[name]) # type: ignore + + class LenskitProxyLogger(BoundLoggerLazyProxy): """ Lazy proxy logger for LensKit. This is based on Structlog's lazy proxy, diff --git a/lenskit/lenskit/logging/monitor.py b/lenskit/lenskit/logging/monitor.py index 3ac3ea851..1fd555b53 100644 --- a/lenskit/lenskit/logging/monitor.py +++ b/lenskit/lenskit/logging/monitor.py @@ -24,6 +24,7 @@ import structlog import zmq +from ._proxy import get_logger from .tasks import Task SIGNAL_ADDR = "inproc://lenskit-monitor-signal" @@ -258,7 +259,7 @@ def _handle_log_message(self): logger = logging.getLogger(name) logger.handle(rec) elif engine == "structlog": - logger = structlog.get_logger(name) + logger = get_logger(name) data = json.loads(data) method = getattr(logger, data["method"]) method(**data["event"]) diff --git a/lenskit/lenskit/logging/progress/_rich.py b/lenskit/lenskit/logging/progress/_rich.py index 37cf765a8..3db1d4e62 100644 --- a/lenskit/lenskit/logging/progress/_rich.py +++ b/lenskit/lenskit/logging/progress/_rich.py @@ -21,9 +21,10 @@ from typing_extensions import override from .._console import console, get_live +from .._proxy import get_logger from ._base import Progress -_log = structlog.stdlib.get_logger("lenskit.logging.progress") +_log = get_logger("lenskit.logging.progress") _pb_lock = Lock() _progress: ProgressImpl | None = None _active_bars: dict[UUID, RichProgress] = {} diff --git a/lenskit/lenskit/logging/resource.py b/lenskit/lenskit/logging/resource.py index 98e8391d1..d66ee563f 100644 --- a/lenskit/lenskit/logging/resource.py +++ b/lenskit/lenskit/logging/resource.py @@ -10,10 +10,11 @@ from dataclasses import dataclass from pathlib import Path -import structlog import torch -_log = structlog.get_logger(__name__) +from ._proxy import get_logger + +_log = get_logger(__name__) @dataclass diff --git a/lenskit/lenskit/logging/tasks.py b/lenskit/lenskit/logging/tasks.py index 6222d8ba5..b1be75635 100644 --- a/lenskit/lenskit/logging/tasks.py +++ b/lenskit/lenskit/logging/tasks.py @@ -12,12 +12,12 @@ from typing import Annotated, Any from uuid import UUID, uuid4 -import structlog from pydantic import BaseModel, BeforeValidator, Field, SerializeAsAny +from ._proxy import get_logger from .resource import ResourceMeasurement, reset_linux_hwm -_log = structlog.stdlib.get_logger(__name__) +_log = get_logger(__name__) _active_tasks: list[Task] = [] diff --git a/lenskit/lenskit/logging/worker.py b/lenskit/lenskit/logging/worker.py index 5bf4883af..4587b5969 100644 --- a/lenskit/lenskit/logging/worker.py +++ b/lenskit/lenskit/logging/worker.py @@ -21,6 +21,7 @@ import zmq from structlog.typing import EventDict +from ._proxy import get_logger from .config import CORE_PROCESSORS, active_logging_config, log_warning from .monitor import get_monitor from .processors import add_process_info @@ -28,7 +29,7 @@ from .tracing import lenskit_filtering_logger _active_context: WorkerContext | None = None -_log = structlog.stdlib.get_logger(__name__) +_log = get_logger(__name__) @dataclass diff --git a/lenskit/lenskit/parallel/pool.py b/lenskit/lenskit/parallel/pool.py index f33168d24..e0a6a2ae5 100644 --- a/lenskit/lenskit/parallel/pool.py +++ b/lenskit/lenskit/parallel/pool.py @@ -11,10 +11,9 @@ from multiprocessing.context import SpawnContext, SpawnProcess from multiprocessing.managers import SharedMemoryManager -import structlog from typing_extensions import Any, Generic, Iterable, Iterator, override -from lenskit.logging.tasks import Task +from lenskit.logging import Task, get_logger from lenskit.logging.worker import WorkerContext, WorkerLogConfig from . import worker @@ -22,7 +21,7 @@ from .invoker import A, InvokeOp, M, ModelOpInvoker, R from .serialize import shm_serialize -_log = structlog.stdlib.get_logger(__name__) +_log = get_logger(__name__) def multiprocess_executor( diff --git a/lenskit/lenskit/parallel/worker.py b/lenskit/lenskit/parallel/worker.py index af5b02c23..c85bb8f8f 100644 --- a/lenskit/lenskit/parallel/worker.py +++ b/lenskit/lenskit/parallel/worker.py @@ -12,13 +12,14 @@ from dataclasses import dataclass from typing import Any -import structlog from typing_extensions import Generic +from lenskit.logging import get_logger + from .invoker import A, InvokeOp, M, R from .serialize import SHMData, shm_deserialize -_log = structlog.get_logger(__name__) +_log = get_logger(__name__) __work_context: WorkerData diff --git a/lenskit/lenskit/pipeline/__init__.py b/lenskit/lenskit/pipeline/__init__.py index 0cc783e91..66c177e2e 100644 --- a/lenskit/lenskit/pipeline/__init__.py +++ b/lenskit/lenskit/pipeline/__init__.py @@ -16,10 +16,10 @@ from types import FunctionType, UnionType from uuid import NAMESPACE_URL, uuid4, uuid5 -import structlog from typing_extensions import Any, Literal, Self, TypeAlias, TypeVar, cast, overload from lenskit.data import Dataset +from lenskit.logging import get_logger from . import config from .components import ( # type: ignore # noqa: F401 @@ -51,7 +51,7 @@ "topn_pipeline", ] -_log = structlog.stdlib.get_logger(__name__) +_log = get_logger(__name__) # common type var for quick use T = TypeVar("T") diff --git a/lenskit/lenskit/testing/_movielens.py b/lenskit/lenskit/testing/_movielens.py index 08901830b..7443e02e6 100644 --- a/lenskit/lenskit/testing/_movielens.py +++ b/lenskit/lenskit/testing/_movielens.py @@ -7,7 +7,6 @@ import numpy as np import pandas as pd -import structlog from pyprojroot import here import pytest @@ -17,10 +16,11 @@ from lenskit.data import Dataset, ItemListCollection, UserIDKey, from_interactions_df from lenskit.data.lazy import LazyDataset from lenskit.data.movielens import load_movielens, load_movielens_df +from lenskit.logging import get_logger from lenskit.pipeline import RecPipelineBuilder from lenskit.splitting import TTSplit, simple_test_pair -_log = structlog.stdlib.get_logger("lenskit.testing") +_log = get_logger("lenskit.testing") ml_test_dir = here("data/ml-latest-small") ml_100k_zip = here("data/ml-100k.zip") From 5fb7e43b0ed64855aaf09e9ae93590a54bb77f13 Mon Sep 17 00:00:00 2001 From: Michael Ekstrand Date: Tue, 31 Dec 2024 13:44:31 -0600 Subject: [PATCH 3/7] document using the logger --- docs/guide/logging.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/guide/logging.rst b/docs/guide/logging.rst index cb179424e..f01e5c5d9 100644 --- a/docs/guide/logging.rst +++ b/docs/guide/logging.rst @@ -9,6 +9,7 @@ LensKit provides support code for logging and progress reporting. This code lives in the :py:mod:`lenskit.logging` package and provides several capabilities: +- Logger acquisition functions with useful defaults. - Backend-independent progress reporting, with colorful progress bars (via Rich_) on terminals. - Easy logging configuration for recommender scripts, supporting log files and @@ -74,6 +75,15 @@ are run by other tools like DVC. level; this allows you to send ``DEBUG`` messages to the file while only ``INFO`` messages go to the console. +Emitting Log Messages +~~~~~~~~~~~~~~~~~~~~~ + +When writing LensKit code that needs to emit log messages, use LensKit's +:func:`~lenskit.logging.get_logger` function. This wraps Structopt's +``get_logger`` in a proxy that has more useful LensKit defaults (only emitting +warnings and errors when logging has not been configured). The resulting logger +can be used like any other Structlog or standard library logger. + Progress Reporting ~~~~~~~~~~~~~~~~~~ From 14b59af19bdc4ff480c8c2cccd405c99351b18e0 Mon Sep 17 00:00:00 2001 From: Michael Ekstrand Date: Tue, 31 Dec 2024 13:47:42 -0600 Subject: [PATCH 4/7] document using bind --- docs/guide/logging.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/guide/logging.rst b/docs/guide/logging.rst index f01e5c5d9..a7fa50987 100644 --- a/docs/guide/logging.rst +++ b/docs/guide/logging.rst @@ -84,6 +84,12 @@ When writing LensKit code that needs to emit log messages, use LensKit's warnings and errors when logging has not been configured). The resulting logger can be used like any other Structlog or standard library logger. +Structlog loggers are *lazy*, resolving their configurations when they are +*bound* with variables. When emitting many log messages in a loop or function, +we recommend calling :meth:`structlog.typing.BindableLogger.bind` to get a bound +logger with the configuration resolved, which will be much faster for repeated +fine-grained logging messages. + Progress Reporting ~~~~~~~~~~~~~~~~~~ From 62c44023e5f38dbb50b40bb8acba55d05b6e8413 Mon Sep 17 00:00:00 2001 From: Michael Ekstrand Date: Tue, 31 Dec 2024 14:20:35 -0600 Subject: [PATCH 5/7] fix monitor logger --- lenskit/lenskit/logging/monitor.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lenskit/lenskit/logging/monitor.py b/lenskit/lenskit/logging/monitor.py index 1fd555b53..6e4ddf0f0 100644 --- a/lenskit/lenskit/logging/monitor.py +++ b/lenskit/lenskit/logging/monitor.py @@ -21,7 +21,6 @@ from typing import Protocol, runtime_checkable from uuid import UUID, uuid4 -import structlog import zmq from ._proxy import get_logger @@ -30,7 +29,7 @@ SIGNAL_ADDR = "inproc://lenskit-monitor-signal" REFRESH_INTERVAL = 5 -_log = structlog.stdlib.get_logger(__name__) +_log = get_logger(__name__) _monitor_lock = threading.Lock() _monitor_instance: Monitor | None = None From d928c8418e36a770c54da813ccaa56d0f1fde4bb Mon Sep 17 00:00:00 2001 From: Michael Ekstrand Date: Tue, 31 Dec 2024 14:20:46 -0600 Subject: [PATCH 6/7] fix proxy logger --- lenskit/lenskit/logging/_proxy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lenskit/lenskit/logging/_proxy.py b/lenskit/lenskit/logging/_proxy.py index f7c9fcd8f..512a25e3c 100644 --- a/lenskit/lenskit/logging/_proxy.py +++ b/lenskit/lenskit/logging/_proxy.py @@ -24,7 +24,7 @@ class LenskitProxyLogger(BoundLoggerLazyProxy): """ def bind(self, **new_values: Any): - if structlog.is_configured: + if structlog.is_configured(): self._wrapper_class = None else: self._wrapper_class = _fallback_wrapper From 80fb41bb25a7f3b27533a01a82658783e92d32c6 Mon Sep 17 00:00:00 2001 From: Michael Ekstrand Date: Tue, 31 Dec 2024 14:24:09 -0600 Subject: [PATCH 7/7] no log config in getting started --- docs/guide/GettingStarted.ipynb | 67 ++++++++++++++------------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/docs/guide/GettingStarted.ipynb b/docs/guide/GettingStarted.ipynb index c8f8957bc..2644c28d4 100644 --- a/docs/guide/GettingStarted.ipynb +++ b/docs/guide/GettingStarted.ipynb @@ -68,26 +68,6 @@ "from pyprojroot.here import here" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We also need to set up logging, both to unify it and to silence noisy debug-level messages. When running LensKit from a script, you usually want to use `INFO`-level logging, and to use the `LoggingConfig` class for more flexibility." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "import logging\n", - "\n", - "from lenskit.logging import basic_logging\n", - "\n", - "basic_logging(logging.WARNING)" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -99,7 +79,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -178,7 +158,7 @@ "4 1 5 3.0 889751712" ] }, - "execution_count": 5, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -199,7 +179,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -216,7 +196,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -242,11 +222,20 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/michael/Documents/LensKit/lkpy/lenskit/lenskit/als/_explicit.py:94: UserWarning: Sparse CSR tensor support is in beta state. If you miss a functionality in the sparse tensor support, please submit a feature request to https://github.com/pytorch/pytorch/issues. (Triggered internally at /Users/runner/miniforge3/conda-bld/libtorch_1733624403138/work/aten/src/ATen/SparseCsrTensorImpl.cpp:55.)\n", + " rmat = rmat.to_sparse_csr()\n" + ] + } + ], "source": [ "# test data is organized by user\n", "all_test = ItemListCollection(UserIDKey)\n", @@ -282,7 +271,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -302,7 +291,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -340,15 +329,15 @@ " \n", " \n", " ALS\n", - " 0.128447\n", - " 0.091585\n", - " 0.196082\n", + " 0.129831\n", + " 0.096835\n", + " 0.208196\n", " \n", " \n", " II\n", - " 0.093132\n", - " 0.035806\n", - " 0.104097\n", + " 0.096751\n", + " 0.035333\n", + " 0.104951\n", " \n", " \n", "\n", @@ -357,11 +346,11 @@ "text/plain": [ " NDCG RBP RecipRank\n", "model \n", - "ALS 0.128447 0.091585 0.196082\n", - "II 0.093132 0.035806 0.104097" + "ALS 0.129831 0.096835 0.208196\n", + "II 0.096751 0.035333 0.104951" ] }, - "execution_count": 10, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -372,12 +361,12 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { - "image/png": "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r9tvv71fFgoAAK5Or/8Qzt13360//vGPqqmp0eeffy5J+u53v6tJkyb5fXEAAKDveh17t9utgQMH6s4779Sdd97pGT9//rza29v9+odjAABA3/XqA3pvvvmmkpKS9PXXX/s89vXXX+uuu+7S22+/7bfFAQCAvutV7IuLi/WTn/xE3/nOd3we+853vqPly5dr8+bNflscAADou17F/pNPPtHUqVMv+fh9992njz/+uK9rAgAAftSr2J8+fVpdXV2XfPzcuXM6ffp0nxcFAAD8p1exv+2223TkyJFLPn7kyBHFxsb2eVEAAMB/ehX7f/qnf1J+fr7+8pe/+DzW1NSkVatWad68eX5bHAAA6LteffVuxYoV2rdvn7773e9q/vz5GjdunBwOh2pra/Xaa68pJiZGK1as6K+1AgCAq9Cr2A8aNEiHDx9WXl6eSktLPe/PR0ZGav78+Vq7dq0GDRrULwsFAABXp9c/qhMREaGioiJt2bJFLS0tsixLw4YN8/x0LgAACCy9jv1Fra2tOnHihBwOh4KCgrz+rj0AAAgcvfqAniR9+umnuu++++R0OpWcnKy7775bt956q77//e97/a17AAAQGHp1Zt/U1KQpU6Zo2LBh2rBhg8aPHy/LsvTHP/5R27dvV1pamj755BPdeuut/bVeAADQS72K/c9//nPFxsbq8OHDCg8P94zPmDFDixcv1r333quf//znKiws9PtCAQDA1enVZfzy8nItX77cK/QX3XTTTVq2bJneffddvy0OAAD0Xa9i/8UXX2jy5MmXfDwpKUlffPFFnxcFAAD8p1exP3PmzGX/Xv2gQYPU3t7e50UBAAD/6fVX786cOdPjZXxJcrvdsiyrz4sCAAD+06vYW5alsWPHXvZxflwHAIDA0qvYf/DBB/21DgAA0E96FfspU6b01zoAAEA/6VXsBwwY8K2X6R0Oh7q6uvq0KAAA4D+9iv2bb755yccqKir0i1/8gg/oAQAQYHoV+zlz5viMffbZZ8rLy9Pbb7+tRx99VM8995zfFgcAAPqu138I56I///nPeuKJJzRhwgR1dXWppqZGr776qkaNGuXP9QEAgD7qdezb2tq0fPly3X777fr000/1/vvv6+2331ZiYmJ/rA8AAPRRry7jv/jii3rhhRcUHR2t3bt393hZHwAABJZexX7FihW66aabdPvtt+vVV1/Vq6++2uO8N954wy+LAwAAfder2C9YsIBfyAMA4DrTq9i/8sor/bQMAADQX6760/gAAOD6QOwBADAcsQcAwHDEHgAAwxF7AAAMR+wBADAcsQcAwHC2x76oqEhxcXEKDw+Xy+XSoUOHLjv/4MGDcrlcCg8P1+jRo7V161afOX/961/15JNPavjw4QoPD1d8fLzKysr66xAAAAhotsa+tLRU2dnZys/PV3V1tdLS0jRz5kzV19f3OL+urk6zZs1SWlqaqqurtXLlSi1ZskR79+71zOns7NTf//3f6/jx4/rVr36lY8eOafv27Ro5cuS1OiwAAAJKr35Bz982bNighQsXatGiRZKkjRs36t1331VxcbEKCwt95m/dulWjRo3Sxo0bJUnx8fE6cuSI1q9fr3nz5kmSduzYoS+//FIVFRUKCQmRJMXGxl52HR0dHero6PDcd7vd/jg8AAACgm1n9p2dnaqqqlJ6errXeHp6uioqKnrcprKy0mf+9OnTdeTIEZ07d06S9NZbbyklJUVPPvmknE6nEhMTtXbtWnV3d19yLYWFhYqIiPDcYmJi+nh0AAAEDtti39LSou7ubjmdTq9xp9OppqamHrdpamrqcX5XV5daWlokSV988YV+9atfqbu7W2VlZVq1apVeeuklPf/885dcS15entra2jy3kydP9vHoAAAIHLZexpfk81f0LMu67F/W62n+346fP39et956q7Zt26agoCC5XC79+c9/1rp16/TTn/60x32GhYUpLCysL4cBAEDAsi32UVFRCgoK8jmLb25u9jl7vyg6OrrH+cHBwRo6dKgkafjw4QoJCVFQUJBnTnx8vJqamtTZ2anQ0FA/HwkAAIHNtsv4oaGhcrlcKi8v9xovLy9Xampqj9ukpKT4zN+/f7+SkpI8H8a755579Kc//Unnz5/3zPn88881fPhwQg8AuCHZ+tW73Nxcvfzyy9qxY4dqa2uVk5Oj+vp6ZWVlSbrwXvqCBQs887OysnTixAnl5uaqtrZWO3bsUElJiZYuXeqZs3jxYrW2turpp5/W559/rv/4j//Q2rVr9eSTT17z4wMAIBDY+p59RkaGWltbVVBQoMbGRiUmJqqsrMzzVbnGxkav79zHxcWprKxMOTk52rJli0aMGKFNmzZ5vnYnSTExMdq/f79ycnI0YcIEjRw5Uk8//bSWL19+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", + "image/png": "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oUO6//77e2SiAACgczr8dbkPPfSQ/vCHP6iiokKff/65JOnb3/62xo8f3+2TAwAAXdfh2Hs8HoWGhmrcuHEaN26cd/nVq1d16dIl/mIcAAB+pkMX6O3fv18JCQn66quv2rz21Vdf6cEHH9TBgwe7bXIAAKDrOhT7/Px8/fCHP9S3vvWtNq9961vf0vLly7V58+ZumxwAAOi6DsX+k08+0eTJk2/4+qOPPqqPP/64q3MCAADdqEOxv3DhglpaWm74+pUrV3ThwoUuTwoAAHSfDsX+vvvu04kTJ274+okTJxQdHd3lSQEAgO7Todj/4z/+o3JycvTnP/+5zWtut1urVq3SnDlzum1yAACg6zp0692KFSt04MABffvb39a8efM0atQoORwOVVZW6q233lJUVJRWrFjRU3MFAACd0KHY9+3bV8eOHVN2drYKCwu9v58PDw/XvHnztHbtWvXt27dHJgoAADqnw1+qExYWpry8PG3ZskX19fWyLEuDBg3yfnUuAADwLx2O/XUNDQ06e/asHA6HAgICfP6uPQAA8B8dukBPkj799FM9+uijcjqdmjhxoh566CHde++9+u53v+vzt+4BAIB/6NCRvdvt1qRJkzRo0CBt2LBBo0ePlmVZ+sMf/qDt27crOTlZn3zyie69996emi8AAOigDsX+5z//uaKjo3Xs2DGFhIR4l0+bNk2LFi3SI488op///OfKzc3t9okCAIDO6dBp/OLiYi1fvtwn9Nf16dNHy5Yt03vvvddtkwMAAF3XodifPn1aEyZMuOHrCQkJOn36dJcnBQAAuk+HYn/x4sWb/r36vn376tKlS12eFAAA6D4dvvXu4sWL7Z7GlySPxyPLsro8KQAA0H06FHvLsjRy5Mibvs6X6wAA4F86FPsPP/ywp+YBAAB6SIdiP2nSpJ6aBwAA6CEdin2vXr2+8TS9w+FQS0tLlyYFAAC6T4div3///hu+VlJSon/5l3/hAj0AAPxMh2I/a9asNss+++wzZWdn6+DBg3rmmWf0yiuvdNvkAABA13X4D+Fc97//+796/vnnNWbMGLW0tKiiokJvvvmmhg0b1p3zAwAAXdTh2Dc2Nmr58uW6//779emnn+qDDz7QwYMHFR8f3xPzAwAAXdSh0/ivvfaaXn31VUVGRmr37t3tntYHAAD+pUOxX7Fihfr06aP7779fb775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", "text/plain": [ "
" ]