RSSAmplifier

Blog

Krystian Safjan's Blog

Data Scientist and Team Leader writing about Machine Learning, MLOps, and Python

safjan.comRSS feed ↗30 posts

Latest posts

The Real Cost of Model Migration - What Swapping LLMs Actually Requires

Model deprecations are routine. What they expose underneath - unmeasured quality, model-coupled prompts, unversioned behavior - rarely is. Here's what a migration actually requires, from evaluation to prompt portability to rollout, based on doing this a few times the hard way.

The illusion of control in AI-assisted engineering

The illusion of control in AI-assisted engineering Dashboards are green. Reviews complete on time. Audits pass. And the organization is slowly losing track of what its own systems actually do. I keep running into this in teams that use AI-assisted engineering a …

Version Your Vectors - Index Versioning as the Missing Layer in RAG Observability and Compliance

Your RAG answered correctly yesterday. Today, it contradicts itself. Nothing obvious changed — except the index. Retrieval drift is silent, cumulative, and rarely audited. This piece explains how to make it observable and reproducible - what must be versioned beyond vectors, how to enable point-in-time reconstruction, and when lightweight metadata is enough. Includes practical tracing patterns,…

Publishing a Python CLI Tool to Homebrew

Overview Homebrew distribution lets users install your Python CLI with brew install your-tool . The process: create a GitHub "tap" repository, generate a Ruby formula file, test it, and publish. Prerequisites Your package must be on PyPI with an sdist (source distribution), not …

The limiting factor at work isn't writing code anymore

In a Hacker News discussion on the article Management as AI Superpower by Ethan Mollick, I came across a comment that resonated strongly with a realization I’ve had recently while coding with a factory.ai droid: The limiting factor at work …

Using MLflow-RAGAS Integration Without Tracing

Option 1: Static Data Approach (Recommended) Key Points Option 2: Simple predict_fn (No Tracing Decorator) Comparison: When to Use Each Approach Complete Working Example Recommendation You can use MLflow's RAGAS integration to calculate evaluation scores and log them to experiments without implementing …

RAG Evaluation with RAGAS and MLflow - A Practical Guide

A comprehensive tutorial demonstrating RAG evaluation using RAGAS metrics through MLflow integration. Learn to build a minimal RAG pipeline with LangChain, create golden evaluation datasets, and systematically assess retrieval quality using Faithfulness, Context Precision, Context Recall, and Factual Correctness metrics. Supports OpenAI, Azure OpenAI, and Ollama backends.

Working Faster with Git Worktrees and AI-Based Multi-Workflow Development

A practical, hands-on guide to turning a single codebase into a multi-workflow environment using Git worktrees, VS Code, and AI coding assistants. The tutorial shows how to isolate experiments, compare results, and speed up refactoring work with agents and Copilot.

Using Git Worktrees as Clean Rooms for AI-Assisted Coding

Learn how Git worktrees create isolated environments for AI-assisted coding, allowing you to keep your main development line clean while experimenting with AI suggestions in dedicated branches.

Avoiding Homebrew Upgrades That Require Sudo on macOS

Learn how to manage Homebrew upgrades on macOS to avoid sudo prompts, by differentiating between formulae and casks and using specific commands like --formula , --cask , and pinning problematic packages.

Understanding Python Protocols - Structural Subtyping in Practice

Learn how Python protocols using structural subtyping in PEP 544 allow for flexible, decoupled code by defining shapes through method signatures rather than class inheritance. Explore examples of implementing read-only attributes and optional methods within protocols.

Evolution of Type Hints in Python — From Comments to Inline Typing and Beyond

Learn about the evolution of type hints in Python, from initial comments to modern inline typing and key features introduced in each major version, enabling powerful static type checking with tools like mypy and pyright.

Keeping performance results in a separate Git branch using `git checkout --orphan`

Learn how to use git checkout --orphan to create a separate Git branch with no history, ideal for storing performance results or other generated content independently from your codebase. Discover the process and benefits of using orphan branches, including an example GitHub Actions workflow for publishing test results.

Understanding the Language Server Protocol through a Minimal Working Example

Learn how the Language Server Protocol standardizes communication between code editors and language servers, enabling editors like VS Code to request features such as diagnostics and completions from a single server, simplifying development workflows.

Using CSS Variables for Dynamic and Reusable Styling

Learn how to use CSS variables for dynamic and reusable styling, enabling features like interactive UIs, easy theming, and design consistency across components. Discover practical usage examples and best practices while understanding limitations and browser support issues.

Bare Asterisk in Python Function Signatures - Keyword Only Arguments

Learn how to use the bare asterisk in Python function signatures to enforce keyword-only arguments, enhancing clarity and preventing argument order bugs in your code.

Six Weeks, Real Progress - Exploring Shape Up for Product Work

Shape Up replaces two-week sprints with six-week cycles, kills the backlog, and lets small teams decide how to build things. Here is when it works, when it doesn't, and what I think about it after digging in.

Simpler Parallelism with concurrent.futures

Learn how to simplify parallel and concurrent programming in Python using concurrent.futures , including executors for managing threads and processes, and futures for handling task results.

Threading vs Multiprocessing in Python - GIL Implications and Choosing the Right Tool

Learn about the Global Interpreter Lock (GIL) and how threading and multiprocessing in Python differ, with examples showing that multiprocessing is better for CPU-bound tasks due to GIL limitations.

asyncio Basics - async/await and When to Actually Use Them

Learn how async / await enables efficient concurrent programming by handling I/O waits without blocking, and discover various ways to run tasks concurrently, manage context managers, and handle timeouts.

Replacing Makefile with Invoke for Cross-Platform Python Tasks

Learn how switching from Make to Invoke improves cross-platform compatibility for Python project tasks, ensuring consistent behavior across macOS, Linux, and Windows.

Using OpenAI Python SDK with Local Ollama Models (and When to Opt for Alternatives)

Learn how to use the official openai Python package with local Ollama models and when it's better to opt for LiteLLM as a more unified alternative.

Building a Multi-Notebook Report with Quarto

Learn how to split a large Jupyter notebook into multiple notebooks and combine them into a cohesive report using Quarto's book project functionality for HTML, PDF, or EPUB formats.

Downgrade or Upgrade Your Python Version with uv

Learn how to downgrade or upgrade your project’s Python version using the uv tool, including steps for installing, pinning, and recreating your virtual environment.

Beyond Coverage - Building Truly Complete Test Suites with GitHub Copilot

This article explores how to move beyond simplistic code coverage metrics to build truly comprehensive test suites using GitHub Copilot. Drawing from practical experience, I demonstrate how AI-assisted testing can identify behavioral gaps, validate API contracts, generate maintainable tests, and address flaky tests - ultimately creating a sustainable quality assurance strategy focused on behaviors…

Understanding Python's `copy` vs `deepcopy` - When to Use Each

Learn when to use copy.copy() for shallow copying and copy.deepcopy() for deep copying in Python, understanding their differences and typical use cases.

Tracking Down zsh Alias Plugin Sources

Learn how to trace and identify the source of zsh aliases defined by plugins using verbose tracing and grep, enabling you to pinpoint exactly where custom aliases are created.

Guide to Managing VS Code Keyboard Shortcuts

Learn how VS Code handles context-dependent keyboard shortcuts, resolve conflicts using the Keyboard Shortcuts editor, and customize them for efficient coding.

Simple In-Memory Knowledge Graphs for Quick Graph Querying

As developers, we often reach for full-scale graph databases when simpler solutions would suffice. When your knowledge graph is modest in size, keeping it in memory can be both efficient and practical. Let's explore some powerful tools that make this approach work beautifully.

Quick Ways to Disable GitHub Actions Workflows Without Deletion

Learn three quick methods to temporarily disable GitHub Actions workflows without deleting them, including commenting out code, using manual triggers, and adding conditional logic.