<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Anay Nayak on Medium]]></title>
        <description><![CDATA[Stories by Anay Nayak on Medium]]></description>
        <link>https://medium.com/@anaynayak?source=rss-8915f7d8b12d------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*R5RMRKxGI8pyEVBMAb8EZg.png</url>
            <title>Stories by Anay Nayak on Medium</title>
            <link>https://medium.com/@anaynayak?source=rss-8915f7d8b12d------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 03:00:20 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@anaynayak/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Eliminating Flaky Tests: Using VCR tests for LLMs]]></title>
            <link>https://anaynayak.medium.com/eliminating-flaky-tests-using-vcr-tests-for-llms-a3feabf90bc5?source=rss-8915f7d8b12d------2</link>
            <guid isPermaLink="false">https://medium.com/p/a3feabf90bc5</guid>
            <category><![CDATA[testing]]></category>
            <category><![CDATA[evaluation]]></category>
            <category><![CDATA[llmops]]></category>
            <category><![CDATA[llm]]></category>
            <dc:creator><![CDATA[Anay Nayak]]></dc:creator>
            <pubDate>Mon, 24 Feb 2025 13:01:55 GMT</pubDate>
            <atom:updated>2025-02-24T15:09:55.572Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="A vintage 1980s cassette tape floating in mid-air" src="https://cdn-images-1.medium.com/max/1024/0*0qH1jMh3jkQiAgm7" /></figure><p>Testing LLM applications is inherently challenging. Unlike traditional software, where deterministic outputs are expected for given inputs, LLM responses can vary significantly, making it hard to validate their correctness.</p><p>LLM evaluation frameworks like <a href="https://github.com/confident-ai/deepeval">Deepeval</a>/<a href="https://github.com/explodinggradients/ragas">Ragas</a>/<a href="https://github.com/deepchecks/deepchecks">Deepcheck</a> measure the quality of responses using automated scoring or human feedback which make them expensive, slow and a bit inconsistent. They are crucial as integration tests and better mechanisms exist for testing application code changes faster.</p><p>An approach which provides robust unit tests involves regression testing your code against responses from the LLM. This is where record/replay testing frameworks like <a href="https://github.com/kiwicom/pytest-recording">pytest-recording</a>/<a href="https://github.com/kevin1024/vcrpy">VCR.py</a> help tremendously. By capturing LLM responses and replaying them during test runs, developers can ensure that the test fails only if the input passed to the LLM changes.</p><h3>How do record/replay tests help?</h3><p>VCR.py provides a record/replay mechanism that captures API responses during a test run and reuses them in future executions. If you’ve been using pytest, this is available as a decorator via the pytest-recording library. This technique works well for LLM-based applications because:</p><ol><li>The tests run once with live LLM API calls and and subsequent test runs replay the recorded responses instead of making live calls.</li><li>If the API request payload (request url, body, headers) changes in any way, the tests fail. This provides an opportunity to identify if this is a regression in application behavior and accordingly update the recordings.</li></ol><h3>Practical Example</h3><p>Consider the following function that interacts with an LLM to generate responses:</p><pre>import openai<br><br>def generate_response(prompt: str) -&gt; str:<br>    response = openai.ChatCompletion.create(<br>        model=&quot;o3-mini&quot;,<br>        messages=[{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: prompt}]<br>    )<br>    return response[&quot;choices&quot;][0][&quot;message&quot;][&quot;content&quot;]</pre><p>To test this function using pytest-recording, install the plugin and write a test:</p><pre>import pytest<br>from myapp import generate_response<br><br>@pytest.mark.vcr()<br>def test_generate_response():<br>    response = generate_response(&quot;What is pytest?&quot;)<br>    assert &quot;testing framework&quot; in response.lower()</pre><p>This generates a cassette in yaml format which records the entire interaction and is used for subsequent test runs automatically. These should be pushed to version control so that all team members have the exact same behavior.</p><blockquote>Note: Cassettes need to be explicitly<a href="https://github.com/kiwicom/pytest-recording">¹</a> created using pytest --record-mode=once or with<em>--record-mode=rewrite</em></blockquote><pre>interactions:<br>- request:<br>    body: &#39;{&quot;messages&quot;:[{&quot;role&quot;:&quot;user&quot;,&quot;content&quot;:&quot;What is pytest?&quot;}],&quot;model&quot;:&quot;o3-mini&quot;}&#39;<br>    headers:<br>      content-type:<br>      - application/json<br>      user-agent:<br>      - OpenAI/Python 1.63.2<br>    method: POST<br>    uri: https://api.openai.com/v1/chat/completions<br>  response:<br>    body:<br>      string: &quot;{\n  \&quot;id\&quot;: \&quot;chatcmpl-B3ljAwsvwZ8zV4UbkASdW1P1TzPRA\&quot;,\n  \&quot;object\&quot;:<br>        \&quot;chat.completion\&quot;,\n  \&quot;created\&quot;: 1740238148,\n  \&quot;model\&quot;: \&quot;o3-mini-2025-01-31\&quot;,\n<br>        \ \&quot;choices\&quot;: [\n    {\n      \&quot;index\&quot;: 0,\n      \&quot;message\&quot;: {\n        \&quot;role\&quot;:<br>        \&quot;assistant\&quot;,\n        \&quot;content\&quot;: \&quot;pytest is a testing framework for Python<br>        that makes it easy to write and run tests for your code. \&quot;,\n        \&quot;refusal\&quot;: null\n      },\n      \&quot;finish_reason\&quot;:<br>        \&quot;stop\&quot;\n    }\n  ],\n  \&quot;usage\&quot;: {\n    \&quot;prompt_tokens\&quot;: 10,\n    \&quot;completion_tokens\&quot;:<br>        419,\n    \&quot;total_tokens\&quot;: 429,\n    \&quot;prompt_tokens_details\&quot;: {\n      \&quot;cached_tokens\&quot;:<br>        0,\n      \&quot;audio_tokens\&quot;: 0\n    },\n    \&quot;completion_tokens_details\&quot;:<br>        {\n      \&quot;reasoning_tokens\&quot;: 192,\n      \&quot;audio_tokens\&quot;: 0,\n      \&quot;accepted_prediction_tokens\&quot;:<br>        0,\n      \&quot;rejected_prediction_tokens\&quot;: 0\n    }\n  },\n  \&quot;service_tier\&quot;:<br>        \&quot;default\&quot;,\n  \&quot;system_fingerprint\&quot;: \&quot;fp_42bfad963b\&quot;\n}\n&quot;<br>    headers:<br>      Content-Type:<br>      - application/json<br>    status:<br>      code: 200<br>      message: OK<br>version: 1</pre><p>⚠️ <strong>The default config will log everything to the YAML as is (inclusive of credentials).</strong> You must override the VCR configuration to redact authentication headers<strong>,</strong> decompress gzipped response amongst other things. See the sample repository in the References section for a working example.</p><h3>Bonus: Using Record/Replay to Explore LLM Capabilities</h3><p>Beyond testing, record/replay can help developers better understand LLM behavior:</p><ol><li><strong>Function Calling</strong>: While OpenAI’s documentation explains <a href="https://platform.openai.com/docs/guides/function-calling">function calling</a> quite clearly, If you’ve been curious how it actually passes this through, record/replay tests are a quick way to validate the same.</li><li>Comparing Model Versions: Detect subtle changes when switching between LLM versions.</li></ol><iframe src="https://flo.uri.sh/visualisation/21788021/embed" width="700" height="575" frameborder="0" scrolling="no"><a href="https://medium.com/media/b183418e8b8fcd5032ecfc9a15f0fb55/href">https://medium.com/media/b183418e8b8fcd5032ecfc9a15f0fb55/href</a></iframe><h3>Conclusion</h3><p>Given record/replay tests capture and reuse LLM responses, they are ideal for detecting unintended prompt regressions and isolating non-LLM-related issues (e.g., code changes, input handling). In contrast, LLM evaluation tests assess response quality dynamically, focusing on overall system performance rather than isolating LLM-specific regressions from external factors.</p><p>Resources:</p><ol><li><a href="https://github.com/anaynayak/llm-vcr-tests">Sample repository</a></li><li><a href="https://github.com/kevin1024/vcrpy">VCR.py</a></li><li><a href="https://github.com/kiwicom/pytest-recording">pytest-recording</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a3feabf90bc5" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reproducibility in ML: The Role of Data Versioning]]></title>
            <link>https://medium.com/inspiredbrilliance/reproducibility-in-ml-the-role-of-data-versioning-b5a504bea8b4?source=rss-8915f7d8b12d------2</link>
            <guid isPermaLink="false">https://medium.com/p/b5a504bea8b4</guid>
            <category><![CDATA[data-version-control]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[mlops]]></category>
            <category><![CDATA[data-versioning]]></category>
            <dc:creator><![CDATA[Anay Nayak]]></dc:creator>
            <pubDate>Thu, 06 Feb 2025 17:17:21 GMT</pubDate>
            <atom:updated>2025-02-19T10:12:56.350Z</atom:updated>
            <content:encoded><![CDATA[<p>Once you’ve run machine learning models in production, <strong>reproducibility</strong> becomes one of the non-negotiable aspects of delivery since the baseline performance of the model has already been defined. The ability to replicate results, debug issues, and improve models requires that all experiments are easily traceable. Unlike traditional software development, where versioning source code is sufficient to reproduce builds, ML workflows can degrade significantly with changes to the data, its distribution as well changes to any preprocessing steps.</p><p>In this article, we’ll explore what data versioning entails, the challenges it addresses, and how it can be easily integrated into your ML workflow.</p><h3>How is data versioning different?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ehJPnBZ9beXWs3eG" /><figcaption>Data versioning v/s code versioning (with DVC as an example)</figcaption></figure><p>The aspects of the right side of the diagram look very similar to packaging a service:</p><ol><li><strong>CI pipeline: </strong>Individual stages of the pipeline e.g. test/build/promote have not been displayed in the image above.</li><li><strong>Experimentation</strong>: You can experiment with different variants by using a feature toggle.</li><li><strong>Code changes</strong>: If you’d run into any issues, you’d rollback your code so that it continues to function as before.</li></ol><p><strong>Things that are different:</strong></p><ol><li><strong>Training pipeline: </strong>The <a href="https://scikit-learn.org/stable/model_persistence.html">artifact</a> in an ML project is heavily influenced by the code, configuration and data. Changes to any of them affects the model weights and hence prediction accuracy significantly. In certain cases, the model may no longer be relevant if the data changes significantly.</li><li><strong>Experimentation</strong>: Depending on the complexity and desired accuracy of the problem, the experimentation cycle can even go on for several months. Through this window, it is essential to be able to identify the best model. Managing this effectively in a wiki/document is not sustainable since different types of changes are involved:<br> a. <strong>Code changes:</strong> Apply different pre-processing steps<br> b. <strong>Configuration changes:</strong> Experiments done with combinations of hyper parameters<br> c. <strong>Data: </strong>The distribution of the data, its schema and more can all change over time.</li><li><strong>Metric tracking: </strong>Data quality metrics and any evaluation metrics can be tracked via data versioning so that there is full traceability.</li><li><strong>Collaboration: </strong>The complexities associated with collaboration over code have mostly been solved by git and other version control tools. Data and configuration add additional layers to the problem since the traceability of an artifact, its accuracy and the corresponding data/config becomes a challenge.</li></ol><p>Data versioning solves these problems by providing capabilities similar to git:</p><ol><li>Dataset Versioning: Track changes to raw, processed and intermediate datasets.</li><li>Leverage metadata for context: The input datasets, the code and the config parameters and the output need to be linked together for each run of an experiment. This provides full traceability and reproducibility of the results.</li><li>Storage strategies: The code repository only has a reference to a commit/ref of the data version repository. The actual files are centrally managed on object stores like S3/GCS.</li></ol><h3>Lifecycle with data versioning</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*PD6NoBxj-49yAYhE" /><figcaption>Data versioning lifecycle</figcaption></figure><p>Tool considerations</p><p>Few popular tools in this space include <strong>DVC, GitLFS, doIt, LakeFS</strong>. These tools provide an excellent interface over hand-rolling your own tooling over object stores like S3. Choosing an appropriate tool requires one to think about a few aspects:</p><ol><li><strong>Dataset size</strong>: With larger datasets, depending on the underlying storage representation, the data storage requirements may grow multi-fold and some tools do not handle this effectively. Appropriate data retention policies should be set up so that unreferenced data can be safely removed.</li><li><strong>Team collaboration</strong>: Multiple individuals may work on the same problem statement requiring close collaboration.</li><li><strong>Access control</strong>: For sensitive datasets like financial datasets, access control and auditing capabilities are required.</li><li><strong>Tool Integration</strong>: Integration with other systems like Experimentation (MLFlow / Kubeflow etc), Visualisation of run metrics, model packaging etc.</li><li><strong>Infrastructure</strong>: Some data versioning tools require additional data stores to manage state which adds to the infrastructure footprint.</li></ol><iframe src="https://flo.uri.sh/visualisation/21463785/embed" width="700" height="575" frameborder="0" scrolling="no"><a href="https://medium.com/media/7c47ea39089b9edf5c848379e20e0cfe/href">https://medium.com/media/7c47ea39089b9edf5c848379e20e0cfe/href</a></iframe><p>Detailed comparisons have been done by <a href="https://neptune.ai/blog/best-data-version-control-tools">Neptune</a>, <a href="https://dagshub.com/blog/best-data-version-control-tools/">Dagshub</a>, <a href="https://www.deepchecks.com/how-to-choose-a-data-versioning-tool-for-your-ml-project/">Deepchecks</a>, and <a href="https://lakefs.io/blog/dvc-vs-git-vs-dolt-vs-lakefs/">LakeFS</a>. Please be aware that this is a rapidly evolving space and the examples and references given here are only meant to give you an idea.</p><h4>Conclusion</h4><p>Data versioning plays a key role in building reliable, reproducible, and scalable machine learning systems. By tracking changes to datasets and associating them with experiments and model versions, teams can streamline their development cycles and bring in auditability and traceability. Validating the capabilities of data versioning on small, critical datasets can help teams validate and benefit from its capabilities.</p><p>Thanks to <a href="https://www.linkedin.com/in/ajinkyakhot/">Ajinkya</a>, <a href="https://msync.org/">Jaju</a>, <a href="https://www.linkedin.com/in/rhushikesh-apte-685a5948/">Rhushikesh</a> and <a href="https://www.linkedin.com/in/swapnil-sankla-30525225/">Swapnil</a> for reviewing early drafts and providing detailed feedback. <a href="https://www.linkedin.com/in/ajinkyakhot/">Ajinkya</a>, <a href="https://www.linkedin.com/in/harshad-nawathe-76762618/">Harshad</a>, <a href="http://linkedin.com/in/venkatesh-perabhattula-12106a114">PV</a>, <a href="https://www.linkedin.com/in/preethi-srinivasan-3a221915/">Preethi</a> and <a href="https://www.linkedin.com/in/sanketpathak64/">Sanket</a> for building internal ML accelerators and sharing their experiences with these tools.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b5a504bea8b4" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inspiredbrilliance/reproducibility-in-ml-the-role-of-data-versioning-b5a504bea8b4">Reproducibility in ML: The Role of Data Versioning</a> was originally published in <a href="https://medium.com/inspiredbrilliance">inspiringbrilliance</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[12 Factor Spark Applications]]></title>
            <link>https://medium.com/inspiredbrilliance/12-factor-spark-applications-eccb78bdc371?source=rss-8915f7d8b12d------2</link>
            <guid isPermaLink="false">https://medium.com/p/eccb78bdc371</guid>
            <category><![CDATA[big-data]]></category>
            <category><![CDATA[spark]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[data-engineering]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Anay Nayak]]></dc:creator>
            <pubDate>Fri, 30 Apr 2021 05:00:09 GMT</pubDate>
            <atom:updated>2021-05-04T04:43:12.894Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IS_st5mIWaFf8Mm_z3rAKg.png" /><figcaption>12 Factor Spark Application</figcaption></figure><h4>Time-tested principles for building robust Spark applications</h4><p>Spark is a distributed data processing engine that is widely used in batch processing and stream processing platforms. Building such platforms comes with a fair share of challenges beyond those required for continuous delivery in the microservices world such as data drift, bad data, and data security.</p><p>Similar to the <a href="https://12factor.net/">Twelve-Factor app</a> that is an outstanding methodology/set of principles for building web apps, we at Sahaj have realized over time that a set of concepts/patterns can be applied to building data processing applications using frameworks like Spark. Through this article, we attempt to document these observations that we believe can serve as ideal practices for defining a basic structure to build production-grade Spark applications.</p><h3>I. Codebase</h3><blockquote>One codebase tracked in revision control, many deploys.</blockquote><p>Ensure that the code is version controlled and changes are promoted from a lower environment (dev/qa) to a higher environment. This ensures that you can test changes before rolling them out and in case of any issues, you can easily rollback. It further provides a traceable artifact for investigating issues.</p><h3>II. Dependencies</h3><blockquote>Explicitly declare and isolate dependencies.</blockquote><p>There are several choices for declaring and locking dependencies. To pin dependencies (inclusive of transitive dependencies) to specific versions and have a reproducible build, tools such as Poetry/Pipenv are available in Python, and in Java/Scala, sbt, Gradle, and Maven do the same.</p><p>In the Python ecosystem, several libraries rely on binary dependencies directly installed in the system. In such scenarios, use containerized images to ensure that the system dependencies are packaged into a tested image and are promoted across environments.</p><h3><strong>III. Config</strong></h3><blockquote>Store config in the environment.</blockquote><p>Spark lets you <a href="https://spark.apache.org/docs/latest/configuration.html#available-properties">override several parameters at runtime</a> via environment variables or command line parameters to tweak application parameters and handle changes in data volume or infrastructure without changing code.</p><p>For other configurations, parameterise using named CLI args. Every language has libraries for processing command-line arguments that can validate the types as well as supported values and ensure that the application doesn’t run with junk values.</p><p>Externalise secrets and access them at runtime. Use tools like Vault, AWS Secrets Manager and service roles to ensure that keys can be easily rotated.</p><h3>IV. Backing services</h3><blockquote>Treat backing services as attached resources.</blockquote><p>Spark provides abstractions for dealing with various data sources such as JDBC, HDFS, S3 etc. By treating these as resources and externalising configuration, you can avail simplified testing, pluggable resources, and reduced vendor lock-in. Use custom connectors, readers instead of directly interacting with external sources like http/ftp using client libraries so that the spark job focuses primarily on business logic.</p><p>Build/Use abstractions that make it easier to run jobs locally with minimal external dependencies. For example, Instead of relying on a shared s3/dev database location, treat them as attached resources so that locally it can be swapped with the filesystem/stub apis.</p><p>For infra services such as performance metrics, Spark supports configurable <em>sinks</em> so that key metrics are pushed to systems such as Prometheus, StatsD, and Ganglia.</p><h3>V. Build, release, run</h3><blockquote>Strictly separate build and run stages.</blockquote><p>For Spark applications, during the build stage, you should create a packaged artifact inclusive of all dependencies. For Python, this involves creating a wheel for your target system. For Scala/Java, it involves creating an uber jar using tools like <a href="https://github.com/johnrengelman/shadow">shadow</a>. To reiterate, using a containerized image isolates any system dependencies and helps with reproducible builds that can be promoted from one environment to another.</p><p>Invest heavily in writing tests and clean code practices to provide safety nets as well as to avoid data bugs. Depending on the data, the cost of data bugs can be astronomical and fixing it would involve recomputing the data along with any derived insights. Run tests automatically in a pipeline before building the artifact.</p><p>If the configuration is fully externalised, the release stage is mostly a no-op and a workflow orchestrator can ensure that the right configuration is applied and used in each environment.</p><h3>VI. Data Schema</h3><blockquote>Validate data schema and semantics</blockquote><p>Prefer data formats such as Parquet/Avro/ORC so that schema is implicitly a part of the data and schema does not need to be explicitly managed/specified across separate data jobs. For CSV/JSON, explicitly specify the schema so that unintentional changes are caught early.</p><p>Create separate schema versions whenever the semantics of existing columns have changed or columns have been introduced/deleted. The intent is to avoid unintentional impact on downstream consumers.</p><p>Fail fast! Validate schema and data semantics as part of your job for all inputs so that unintentional changes are caught early. Frameworks such as Deequ, GreatExpectations let you integrate checks into your data pipeline.</p><h3>VII. Immutability</h3><blockquote>Prefer atomic, repeatable jobs with partitioned data</blockquote><p>Immutability in data is similar to immutability in programming. Since tasks can fail for various reasons, it is important to ensure that the re-computation doesn’t corrupt the output state. Partition your data so that older/irrelevant data can be phased out easily. For batch processing, fail on presence of existing data and write to a separate output location for each run.</p><p>For a deterministic model/job, this also helps in rolling out newer versions of the model since they can be easily compared against a previous model for a given input.</p><p>Write each application as an atomic job that does one thing well. This ensures that a rerun on failure doesn’t affect anything else. Compose multiple jobs using a workflow orchestrator.</p><h3>VIII. Scalability</h3><blockquote>Scale out horizontally with balanced tasks</blockquote><p>For Spark applications, leverage parallelisation and balanced tasks to ensure that the tasks can scale with additional infrastructure. Use CPU/memory/disk optimally and monitor systems to ensure infrastructure usage scales on the basis of data.</p><p>Don’t collect data on the driver node which might exceed the resources available to a single node. Instead, identify mechanisms of distributing the processing across all nodes. For example, Spark lets you define user defined functions (UDF) which can do complex model/algorithmic processing on your data across nodes/tasks. If you need to collate and create a single artifact (e.g. a geojson file) , this can be done in a separate stage which unifies smaller parts with different infrastructure considerations.</p><h3>IX. Disposability</h3><blockquote>Idempotent tasks with no side-effects on re-run</blockquote><p>Given the distributed nature of Spark, be wary of issues that arise due to intermittent availability of backing services and the implications of rerunning tasks and side-effects such as updating data stores/HTTP endpoints.</p><p>Cloud infrastructure makes it easy to spawn on-demand infrastructure with spot pricing which further helps reduce cost and manage immutable infrastructure. However, this also increases the odds of infrastructure instances being terminated on short notice.</p><h3>X. Dev/prod parity</h3><blockquote>Keep development, staging, and production as similar as possible.</blockquote><p>As far as possible, keep the environment similar as it helps ensure that cluster sizing, debugging, model validation etc., can all be done in the dev environment.</p><p>However, concerns such as cost, privacy, time etc., might lead to choosing alternatives such as sampling and anonymisation of data for test environments. Scale down infrastructure/configuration proportionately if you choose to sample. This offers a good middle ground where data on dev still lets you know of data bottlenecks and other issues before they hit the production environment.</p><h3>XI. Observability</h3><blockquote>Provide insights into runtime application behaviour</blockquote><p>Use structured logging to provide visibility into the application behaviour. The event logs and spark history server provide detailed insight into the processed tasks and can help in identifying unbalanced tasks, their duration, DAG visualisation, shuffle issues etc.</p><p>Publish infrastructure and spark metrics to monitoring systems so that the infrastructure can be effectively utilised and issues due to incorrectly configured system resources can be investigated.</p><h3>XII. Data Quality</h3><blockquote>Define data quality checks to safeguard against data drift</blockquote><p>In addition to testing, running data quality checks in your data pipeline helps ensure that any degradation due to Data Drift is caught early before downstream jobs consume the data.</p><p>Define a measure of accuracy for any models and ensure the accuracy score meets a static/dynamic threshold.</p><p>Choose actionable data quality metrics which can be acted upon to avoid alert fatigue and noise.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=eccb78bdc371" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inspiredbrilliance/12-factor-spark-applications-eccb78bdc371">12 Factor Spark Applications</a> was originally published in <a href="https://medium.com/inspiredbrilliance">inspiringbrilliance</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Data science-led, game-changing solutions to disrupt OOH media]]></title>
            <link>https://medium.com/inspiredbrilliance/data-science-led-game-changing-solutions-to-disrupt-ooh-media-3745aa366b0c?source=rss-8915f7d8b12d------2</link>
            <guid isPermaLink="false">https://medium.com/p/3745aa366b0c</guid>
            <category><![CDATA[disruptive-innovation]]></category>
            <category><![CDATA[platform]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[big-data]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Anay Nayak]]></dc:creator>
            <pubDate>Mon, 15 Feb 2021 05:04:23 GMT</pubDate>
            <atom:updated>2021-03-09T13:06:24.428Z</atom:updated>
            <content:encoded><![CDATA[<p>Out Of Home advertising has seen rapid growth in the UK. In 2019, OOH advertising revenue rose 7.6% from 2018 to £<a href="https://www.outsmart.org.uk/sites/default/files/UK%20Out%20of%20Home%20Revenue%20-%202020%20Q4.pdf">1.3bn</a>. However, OOH, by and large, has operated as an offline channel until recently.</p><p>OOH agencies have been traditionally managing and running campaigns manually. From campaign planning to media buying, pricing, placement and tracking, every step of the process is manual. The lack of industry standards add another layer of complexity by creating information silos that in turn make measurement and accountability complicated. A wholesome reimagining of the medium has long been overdue.</p><p>Today, disruptive brands that adopt OOH require data-driven campaigns to adapt to dynamic aspects of audience behaviour. OOH needs to leverage digitization and data-led insights to transform itself into a near real-time medium to deliver responsive and geographically tailored campaigns.</p><p><a href="https://talonoutdoor.com/">Talon</a>, a specialist OOH agency with more than 30% market share, partnered with <a href="https://sahaj.ai/">Sahaj</a> to build a holistic platform that could make the entire cycle of planning, buying, implementation and ROI attribution of campaigns scalable, intuitive, and automated. By doing so, they would effectively lay down the foundation for a path-breaking, data-led disruptive framework that would yield significantly better results for brands.</p><p>This led to the creation of two innovative platforms - <strong>Plato and Ada.</strong></p><blockquote>Plato, an automated trading platform, aggregates all OOH inventory into a single, intuitive campaign planning and delivery system. It allows users to explore, plan, check availability, reserve, and trade paper and digital inventory across multiple markets through direct integrations with media owners and industry systems.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ucf5egHx4MmAAg1DV96Rcw.png" /></figure><p>Plato has direct integrations with multiple media owners and industry systems. It uses more than a dozen web services, a document store running heavy geospatial queries with dense geo-location data and fast messaging queues to distribute the load with elastic infrastructure to rapidly ingest, process, and store data to the tune of a billion data points for optimized brand/business radius searches.</p><p>Plato increased the efficiency of Talon’s planning and buying teams by at least 50%. Users can now plan and book a campaign in just 5 minutes!</p><blockquote>Ada, unlike Plato that aggregates the universe of inventory of OOH media in the UK, uses multiple data science models to analyse billions of device-level audience data points, real-world locations and advertising inventory to enable granular segmentation of audience, intelligent decision-making, campaign management and track ROI.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CChRivP1_hhnM5IHpVKE5Q.png" /></figure><p>It leverages state-of-the-art data science models and technologies like Airflow, Apache Spark, Terraform, PostgreSQL, and Micronaut/Spring to recognise, classify and relay behaviors near-real time for a cohort of people.</p><p>Navigating the OOH landscape with Talon’s Ada has been hugely successful for businesses such as McDonald’s and Starbucks who have used it for their brand building campaigns.</p><p>To launch Starbucks’ new Blonde Espresso Roast, Ada built a custom behavioural audience profile of frequent visitors to high street coffee houses over a 6-month-period. The best performing large format digital inventory was then selected for OOH media buy. Finally, the campaign was measured against brand metrics to determine its effectiveness.</p><p><strong>Starbucks’ campaign impact</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kgeiThsan15l0ZaCI-DDaQ.png" /></figure><p>To drive sustained awareness of the Saver Menu for McDonald’s, Ada created insights about how people travel and how to effectively reach and engage them on the go using billions of data points alongside information about real world places. The campaign was then executed using a blend of 6 sheets and kiosks to drive cost effective reach nationally and bursts were aligned with payday every month when sales spike.</p><p><strong>McDonald’s campaign impact</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uM9PmDD4iQyoiI5ziNDQ_w.png" /></figure><h3>Our View</h3><p>As audience planning, delivery, and measurement become increasingly data-driven, advertising strategies derived from behaviours will assume significance for the agility they offer. Operational costs of running a campaign will reduce considerably.</p><p>Technology will play a pivotal role in enabling us to navigate the ever-evolving landscape of OOH media. Game-changers such as Ada will enable media owners to react faster to audiences and the changing dynamics with their surroundings — the pandemic being a classic example — and thus focus on impactful delivery. While the idea of delivering targeted content in OOH is exciting enough by itself, there will be a push to provide qualitative attribution by cross-pollinating data from target businesses, OOH environments, and other data sources.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3745aa366b0c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inspiredbrilliance/data-science-led-game-changing-solutions-to-disrupt-ooh-media-3745aa366b0c">Data science-led, game-changing solutions to disrupt OOH media</a> was originally published in <a href="https://medium.com/inspiredbrilliance">inspiringbrilliance</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Ways to Accelerate Your Data Science Journey]]></title>
            <link>https://medium.com/inspiredbrilliance/ways-to-accelerate-your-data-science-journey-e72e3d91120b?source=rss-8915f7d8b12d------2</link>
            <guid isPermaLink="false">https://medium.com/p/e72e3d91120b</guid>
            <category><![CDATA[agile]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[delivery]]></category>
            <dc:creator><![CDATA[Anay Nayak]]></dc:creator>
            <pubDate>Tue, 24 Nov 2020 05:25:59 GMT</pubDate>
            <atom:updated>2020-11-24T05:31:33.061Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*B6kRZlE6C3KyRu0N" /><figcaption>Photo by <a href="https://unsplash.com/@gustavocpo?utm_source=medium&amp;utm_medium=referral">gustavo Campos</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>There are innovative use cases that are currently driven using Data Science, and given the cheap cost of storage and cloud infrastructure, it is tempting for enterprises both big and small to start this journey. While the rest of engineering has reached a phase where Agile/Agility has become an abused term, Data Science, still needs to catch up on a lot of practices.</p><p>Here are three ways to accelerate your Data Science journey:</p><h4>Iterate on the models</h4><p>For any new model, start with simple, explainable models with a measure of accuracy and roll it out to your users. Improve the model in subsequent cycles based on any new observations and stop once the cost exceeds the benefit. If required, build capabilities to A/B test your models.</p><p>Timebox exploration for your hypotheses so that you don’t get lost in data. You will discover new patterns/outliers in our data, note them, and see if it makes sense to analyse these further for future business use cases.</p><p>Rather than spending more time choosing the best model, pick one that provides acceptable accuracy and then improve over time. Delaying a feature for minor improvements prevents you from discovering other aspects in production.</p><h4>Work with Stakeholders and business users</h4><p>Involve business users early and often for data analysis and validation. Provide access to users via interactive widgets/dashboards so that they can explore and come back with specific data points for any issues.</p><p>Ensure that your stakeholders are aware of the difference in approach for rolling out a model. Given that a lot of things can be exploratory, data analysis discovery/steps play an important role in addition to the outcome. Agree on what is an acceptable accuracy threshold. For some models, you can start with enabling people in their roles and later evolve to provide direct recommendations.</p><h4>Faster delivery</h4><p>Do not delay confidence-building measures like testing and validation to get to a deliverable faster. Instead, leverage them to evolve the model frequently. For systems dealing with big data, fixing a broken model costs more in time, money and reputation.</p><p>Leverage on-demand immutable cloud infrastructure to reduce upfront infrastructure costs and to run larger workloads faster. While the cost for running it with more infrastructure is higher, you save on the overall time to ship the model.</p><p>Avoid silos and have Data Scientists and Data Engineers working closely on all aspects. All of them possess specific skills and can benefit hugely from cross-pollination that in turn would improve the rate as well as the quality of what is delivered. Reduce cycle time for your models by having more people work on it simultaneously rather than running one stream per person.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e72e3d91120b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inspiredbrilliance/ways-to-accelerate-your-data-science-journey-e72e3d91120b">Ways to Accelerate Your Data Science Journey</a> was originally published in <a href="https://medium.com/inspiredbrilliance">inspiringbrilliance</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AWS X-Ray for distributed tracing]]></title>
            <link>https://anaynayak.medium.com/aws-x-ray-for-distributed-tracing-b914c16a03ba?source=rss-8915f7d8b12d------2</link>
            <guid isPermaLink="false">https://medium.com/p/b914c16a03ba</guid>
            <category><![CDATA[cloudwatch]]></category>
            <category><![CDATA[distributed-tracing]]></category>
            <category><![CDATA[distributed-systems]]></category>
            <category><![CDATA[aws]]></category>
            <dc:creator><![CDATA[Anay Nayak]]></dc:creator>
            <pubDate>Tue, 11 Sep 2018 14:56:12 GMT</pubDate>
            <atom:updated>2018-09-11T14:56:12.727Z</atom:updated>
            <content:encoded><![CDATA[<p>We currently use quite a few AWS services and use AWS X-ray for distributed tracing. It has worked very well given that it provides an easy mechanism to record traces, visualise calls across services and analyse issues across distributed applications. It has SDKs for several languages which makes the integration trivial.</p><p>X-ray lets us filter traces by latency, status codes, failure/error and a lot more.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*XggW9ZMhk1R5RYeh.jpg" /><figcaption>Default AWS Service <a href="https://aws.amazon.com/xray/details/">map view</a></figcaption></figure><h3>Trace Inbound HTTP Calls</h3><p>We can easily <a href="https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-middleware.html">configure</a> the SDK middleware to intercept inbound requests. This adds basic information to the trace which includes the HTTP method, timing and a few more HTTP headers. The segment name can be configured to respect the Host header. The alternative is to specify a static name for the node.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/991/1*J5H0Nb93iie2ErvUjIY24g.png" /><figcaption>Inbound HTTP request trace in X-ray</figcaption></figure><p>We can also force sampling by passing a custom header with the request X-<strong>Amzn-Trace-Id</strong> with the value as <strong>Sampled=1</strong> . This feature isn’t documented but the SDK libraries typically look for this header in the incoming request.</p><h3>Override Sampling Rules</h3><p>By default, the first request every second and 5% of any additional requests are sampled. However if we have certain routes which are triggered less often but are important to monitor, we can tweak the sampling rules based on url pattern, service_name and http method. We use this to increase the sampling to 100% for important low traffic integration endpoints. See <a href="https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-configuration.html#xray-sdk-nodejs-configuration-sampling">https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-configuration.html#xray-sdk-nodejs-configuration-sampling</a> for an example in NodeJS.</p><p>With 2.0.0 version of the X-Ray SDKs, the sampling rules can now be managed from the web console itself allowing us to tweak the rules on runtime without redeploying the application.</p><p>A maximum of 1000 traces can be seen at a time in the list view. The data is retained for one month and traces can be seen for a time window between 5 mins to 6 hours.</p><h3>Trace Outbound HTTP Calls</h3><p>Outbound HTTP calls from the application can be traced as a sub-segment. This allows us to easily trace requests which exceed a specified duration or have been failing with a particular status code. This usually involves replacing the http client with an equivalent instrumented client. See <a href="https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-httpclients.html">https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-httpclients.html</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6B9Y8Pg0R2wLxvJdsJ9W4Q.png" /><figcaption>X-ray trace with outbound call to remote host</figcaption></figure><h3>Capture Custom Metadata Per Trace</h3><p>Using the AWS X-ray SDK, we can <a href="https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-segment.html">add custom metadata and annotations</a>.</p><p>The default X-ray HTTP instrumentation doesn’t log the query parameters. This can be easily incorporated in the application code by using some middleware/interceptor to add additional metadata attributes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/596/1*prcNbnfJWzidZTljp5NAHA.png" /><figcaption>Custom metadata for a trace</figcaption></figure><p>We use a custom requestId annotation which lets us map requests from X-ray to those in our logs. This helps us investigate the issue further.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yhKwP8tikRqocRhEXaIdhw.png" /><figcaption>Custom annotations can be used for grouping/filtering records</figcaption></figure><p>Annotations are more powerful since they are searchable via filter expressions and also allow us to group the traces by an annotation. Metadata however are only displayed with each trace.</p><h3>Capture Custom Sub-Segments</h3><p>We use <a href="https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-subsegments.html">custom sub-segments</a> to capture any background tasks executed in a separate thread. This makes it easy to visualise the time taken for background processing.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/391/1*7gAHcvUFmCUvEgVc94_Q_Q.png" /></figure><h3>Trace calls to AWS Services</h3><p>The X-ray SDK automatically captures calls to other AWS services. The attributes reported can be customised using a whitelist file. In our case, knowing the path to the S3 file is useful. This can be tweaked using the whitelist. E.g. <a href="https://github.com/aws/aws-xray-sdk-node/blob/master/packages/core/lib/resources/aws_whitelist.json">https://github.com/aws/aws-xray-sdk-node/blob/master/packages/core/lib/resources/aws_whitelist.json</a> which can be set from a TracingHandler. With X-ray 2.x versions of the Java SDK, the S3 file path is tracked automatically using the same mechanism.</p><h3>SQL Queries</h3><p>SQL queries associated with an application can be traced by using an <a href="https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-sqlclients.html">instrumented database client</a>. We don’t use this currently but this can be quite useful.</p><h3>Colorise the X-Ray Service map</h3><p>Lastly, the default X-ray service map only highlights nodes for throttled/failed requests. We use a lot of AWS components and this makes it difficult to identify hot spots. I wanted a color scale depending upon requests/sec per node and so I ended up writing a <a href="https://chrome.google.com/webstore/detail/aws-x-ray-service-map/ggjelhbpihojpnkdlhdbllkfmbljjkhd?hl=en">Chrome extension</a> for the same.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iZF501c4D64c_BZMLU1HFA.png" /><figcaption>Colorised AWS X-Ray service map</figcaption></figure><p>The service map currently cannot be combined with filter queries. This would have been quite useful to filter nodes only invoked in a particular flow/application.</p><p>Overall, AWS X-ray provides us with insights into our services without the hassles of maintaining the corresponding infrastructure.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b914c16a03ba" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>