<?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[Quantrium.ai - Medium]]></title>
        <description><![CDATA[This is Quantrium’s official tech blog. A blog on how technology enables us to develop great software applications for our clients. - Medium]]></description>
        <link>https://medium.com/quantrium-tech?source=rss----41710727e242---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Quantrium.ai - Medium</title>
            <link>https://medium.com/quantrium-tech?source=rss----41710727e242---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 13 Nov 2026 17:57:08 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/quantrium-tech" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Enterprises Don’t Have a Data Problem — They Have an Access Problem]]></title>
            <link>https://medium.com/quantrium-tech/enterprises-dont-have-a-data-problem-they-have-an-access-problem-bfe9ee22bcca?source=rss----41710727e242---4</link>
            <guid isPermaLink="false">https://medium.com/p/bfe9ee22bcca</guid>
            <category><![CDATA[enterprise-technology]]></category>
            <category><![CDATA[ai-chatbot]]></category>
            <category><![CDATA[secure-access]]></category>
            <category><![CDATA[mcp-protocol]]></category>
            <category><![CDATA[agentic-rag]]></category>
            <dc:creator><![CDATA[Maria Philna Aruja]]></dc:creator>
            <pubDate>Sun, 01 Feb 2026 05:29:48 GMT</pubDate>
            <atom:updated>2026-02-01T05:29:47.456Z</atom:updated>
            <content:encoded><![CDATA[<h4>QUANTRIUM GUIDES</h4><h3>Enterprises Don’t Have a Data Problem — They Have an Access Problem</h3><h4>Why Secure, Agentic Access Is the New Enterprise Interface</h4><figure><img alt="A background image with hands on a laptop overlayed with Secure Trust Icon with Icons and text for Secure Agentic Access, Retrieval Augmented Generation, Model Context Protocol and Continuous Feedback." src="https://cdn-images-1.medium.com/max/1024/1*1GfA9MQ9hIbfHbNmejhlNg.png" /><figcaption>Secure Agentic Access — New Enterprise Interface</figcaption></figure><h3>The Missing Link: Accessing Enterprise Knowledge</h3><p>Not lack of information, but access to information, is the biggest productivity problem in modern enterprises.</p><p>Here’s a scenario that plays out in offices everywhere.</p><ul><li>A project manager is looking for information on the technology stack for a client’s project.</li><li>A new hire wants to understand the company’s leave policy.</li><li>A sales lead is searching for last quarter’s performance metrics.</li></ul><p>The information exists. Somewhere. Buried in a PDF sitting in someone’s Google Drive. Locked away in a PostgreSQL database that only the IT team can query, or fragmented across Confluence pages, SharePoint folders, and legacy systems that haven’t been updated in months.</p><p>Every enterprise sits on a goldmine of internal data, such as HR policies, project documentation, technical specifications, and financial reports. But that data lives in silos: PDFs, DOCX files, HTML pages, relational databases like MySQL and SQL Server, and NoSQL systems like MongoDB.</p><p>When someone needs an answer, they usually face two poor options.</p><p><strong>Option one:</strong> Spend hours hunting through folders and documents, hoping the version is current.</p><p><strong>Option two:</strong> Raise a ticket with IT and wait for someone to write and validate a SQL query.</p><blockquote>Neither of these scales.</blockquote><p>For non-technical teams, this friction is constant. Why should a marketing manager understand database schemas? Why should an HR specialist navigate complex folder hierarchies to answer routine questions?</p><p>This isn’t just inefficiency; it’s a fundamental disconnect between the data organizations already have and their ability to actually use it.</p><blockquote>This is where the Enterprise Agent comes in.</blockquote><h3>From Search to Conversation and Then to Action</h3><p>Traditional enterprise search tools stop at retrieval. They help you <em>find</em> documents, but do not <em>understand</em> or <em>use</em> the information inside them.</p><p>Large Language Models changed expectations. Employees now expect to ask questions in natural language and get direct, contextual answers. But deploying LLMs naively inside an enterprise quickly exposes real limitations:</p><ul><li>Hallucinated or incomplete answers</li><li>Outdated context</li><li>No grounding in internal systems</li><li>Serious security and compliance risks</li></ul><p>Retrieval-Augmented Generation (RAG) addresses part of this problem by grounding responses in enterprise data. But <strong>RAG alone is not enough</strong>. Enterprises need orchestration.</p><ul><li>They need governance.</li><li>They need agents that can reason across systems — not just retrieve text.</li></ul><h3>How Quantrium Is Solving the Access Problem</h3><p>At Quantrium, we’re addressing this challenge in a phased, pragmatic way, starting where enterprises feel the pain most and scaling systematically.</p><p>At the core of our approach is a simple idea: enterprise knowledge should be unified semantically, not physically.</p><p>The Enterprise Agent platform is built around three foundational layers:</p><ol><li>Data Ingestion and Integration</li><li>Retrieval and Reasoning with RAG</li><li>Continuous Feedback and Improvement</li></ol><h3>Structured Data Without the Bottlenecks</h3><p>Phase One delivers production-grade access to structured data stored in SQL databases, specifically MySQL, PostgreSQL, and Microsoft SQL Server. This is where critical business data often lives and where access is typically restricted to a small technical group.</p><p>Our goal is straightforward:</p><blockquote>“Make structured data accessible to non-technical users without compromising security, control, or accountability.”</blockquote><p>The Enterprise Agent platform securely connects to existing enterprise data sources and creates a unified semantic representation of enterprise knowledge. Raw data never leaves the enterprise boundary. Only schemas, metadata, and contextual signals are embedded for retrieval.</p><p>Phase One emphasizes secure access, schema-aware query generation, full observability, and simple containerized deployment within the enterprise’s environment.</p><h3>How It Works Under the Hood</h3><p>The system uses a Retrieval-Augmented Generation (RAG) pipeline designed for schema-aware reasoning. During ingestion:</p><ul><li>Database schemas (tables, columns, relationships, metadata) are read</li><li>This information is chunked and embedded</li><li>Embeddings are stored in Qdrant</li></ul><p>No raw data is exposed externally; only contextual representations required for retrieval are accessed.</p><p>When a user submits a natural-language question:</p><ol><li>The query is embedded</li><li>Relevant schema context is retrieved</li><li>The LLM generates a SQL query grounded in enterprise-specific schemas and constraints</li></ol><p>Users can either:</p><ul><li>View and download results directly through the application, or</li><li>Receive the generated SQL query itself, for teams that prefer manual execution</li></ul><h3>A note on accuracy</h3><blockquote>Like any AI-assisted system, generated queries require review. Complex joins or nuanced business logic may need iteration. The interface is intentionally designed to support verification rather than blind execution.</blockquote><blockquote>Either way, the dependency on IT tickets is dramatically reduced, without sacrificing oversight.</blockquote><h3>Continuous Feedback and Improvement</h3><p>The Enterprise Agent maintains conversational context and supports user feedback on generated results.</p><p>This feedback loop helps to:</p><ul><li>Improve query disambiguation</li><li>Increase first-attempt answer accuracy</li><li>Refine retrieval quality over time</li></ul><blockquote>The system is designed to improve through real enterprise usage rather than static prompts.</blockquote><h3>Expanding the Scope: From Data Access to Agentic Workflows</h3><p>From structured data, the system expands incrementally:</p><ul><li><strong>Phase Two:</strong> Question answering from PDFs and unstructured documents</li><li><strong>Phase Three:</strong> Native support for NoSQL systems such as MongoDB</li><li><strong>Phase Four:</strong> A fully agentic approach where the Enterprise Agent reasons across multiple systems and MCP servers</li></ul><blockquote>And this is where the real enterprise challenge emerges — because answering real questions rarely involves a single system.</blockquote><h3>The Integration Problem: Why Connectivity Matters</h3><p>Enterprise knowledge doesn’t live in one place. A question like <em>“What’s the status of the Johnson project?”</em> might require accessing:</p><ul><li>Project management tools</li><li>Recent documents</li><li>Repository / Release notes</li><li>Internal communications</li></ul><p>Traditionally, connecting these systems is expensive and brittle. Each integration requires custom development, ongoing maintenance, and careful handling of authentication and permissions.</p><p>As the number of systems grows, integration complexity explodes into an N×M problem.</p><blockquote>This is where the <strong>Model Context Protocol (MCP)</strong> changes the equation.</blockquote><h3>MCP: A Standard for AI to System Connectivity</h3><p>The Model Context Protocol (MCP) is an open standard introduced in late 2024 that provides a consistent way for AI systems to interact with external tools and data sources.</p><p>Instead of building bespoke integrations for every combination of AI application and system, MCP allows integrations to be built once and reused across compatible clients.</p><p>At a high level:</p><ul><li><strong>MCP Servers</strong> expose data and functionality from external systems</li><li><strong>MCP Clients</strong> (like the Enterprise Agent) consume those capabilities via a standard protocol</li></ul><blockquote>The protocol has seen rapid adoption and is now managed by the Linux Foundation’s <a href="https://aaif.io/">Agentic AI Foundation</a>, which is a strong signal of its trajectory as shared industry infrastructure.</blockquote><h3>Quantrium’s MCP Servers: Enterprise-Ready by Design</h3><p>Quantrium has developed a suite of enterprise-grade MCP servers that integrate seamlessly with the Enterprise Agent.</p><p>Each MCP server:</p><ul><li>Handles authentication and permissions</li><li>Translates queries into system-specific operations</li><li>Enforces access controls and auditing</li><li>Exposes a consistent, governed interface to the agent</li></ul><p>When an employee asks a question, the Enterprise Agent can route requests to one or more MCP servers, synthesize the retrieved information, and present a coherent response without the user needing to know which systems were consulted.</p><h3>Deployment Model</h3><p>All MCP servers are designed to run inside the enterprise’s own infrastructure:</p><ul><li>Sensitive data stays within organizational boundaries</li><li>Identity integrates with existing access management</li><li>Audit logs provide visibility into data usage</li></ul><blockquote>This is not a SaaS black box. It’s a deployable infrastructure that enterprises control.</blockquote><h3>What This Changes for Enterprise Teams</h3><p>The combination of the Enterprise Agent and MCP servers creates a practical “single interface” for everyday enterprise questions.</p><p><strong>What it enables:</strong></p><ul><li>Natural-language access to multiple internal systems</li><li>Faster answers to routine questions</li><li>Reduced context switching and tool hopping</li></ul><p><strong>What it doesn’t replace:</strong></p><ul><li>Human judgment</li><li>Review for high-stakes decisions</li></ul><p>In early deployments, the value is most visible in the long tail of routine requests: policy lookups, status checks, historical data retrieval, and cross-referencing information across systems.</p><blockquote>This is where productivity gains compound quietly but meaningfully.</blockquote><h3>Where We Are Today</h3><p>Quantrium is validating this approach through pilot deployments with enterprise clients.</p><p>The roadmap continues:</p><ul><li>Structured data access is live and evolving</li><li>Unstructured document support is being developed</li><li>NoSQL connectivity is planned</li><li>MCP server coverage is expanding across enterprise systems</li></ul><p>Each phase builds on the same core idea: enterprise data should be secure and usable.</p><blockquote>When access becomes intuitive and controlled, information stops being a bottleneck and starts becoming an accelerator.</blockquote><h3>Technical Notes</h3><p>For readers interested in implementation details:</p><ul><li><strong>LLM:</strong> OpenAI GPT-4o</li><li><strong>Vector Database:</strong> Qdrant</li><li><strong>Orchestration:</strong> Dapr Agents</li><li><strong>Backend:</strong> Python, FastAPI</li><li><strong>Frontend:</strong> Vue.js</li><li><strong>Observability:</strong> OpenTelemetry with SigNoz</li></ul><p>The MCP servers are built using the official Python SDK and follow the protocol specification for tools, resources, and prompts to ensure long-term ecosystem compatibility.</p><p>Stay tuned for more…</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bfe9ee22bcca" width="1" height="1" alt=""><hr><p><a href="https://medium.com/quantrium-tech/enterprises-dont-have-a-data-problem-they-have-an-access-problem-bfe9ee22bcca">Enterprises Don’t Have a Data Problem — They Have an Access Problem</a> was originally published in <a href="https://medium.com/quantrium-tech">Quantrium.ai</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[An Overview of Microservices Design Patterns]]></title>
            <link>https://medium.com/quantrium-tech/an-overview-of-microservices-design-patterns-837becd16ca2?source=rss----41710727e242---4</link>
            <guid isPermaLink="false">https://medium.com/p/837becd16ca2</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[microservices]]></category>
            <category><![CDATA[microservice-architecture]]></category>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[microservices-pattern]]></category>
            <dc:creator><![CDATA[Anidhya Bhatnagar]]></dc:creator>
            <pubDate>Fri, 02 May 2025 16:21:49 GMT</pubDate>
            <atom:updated>2025-05-02T16:21:48.984Z</atom:updated>
            <content:encoded><![CDATA[<h4>QUANTRIUM GUIDES</h4><h4>Optimizing Microservices with Proven Architectural Patterns</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1PSMRQQQWTR34dxLaOmoKg.jpeg" /><figcaption>Microservices Design Patterns — An Overview</figcaption></figure><p>In today’s modern world, smart applications are required to be flexible, scalable, and fault tolerant. Microservices architecture enables you to achieve this by decomposing monolithic systems into independent services. However, by using design patterns you can manage microservices effectively and address various challenges like — service communication, data consistency, and resilience.</p><p>This guide introduces <strong>37 essential microservices patterns</strong>, grouped into seven categories. In each pattern, you will see decision-making insights which will help you to choose and apply the right patterns based on your system needs.</p><p>First, let’s list down the seven categories of Microservices Design Patterns:</p><ol><li>Decomposition Patterns</li><li>Communication Patterns</li><li>Data Management Patterns</li><li>Resilience Patterns</li><li>Observability Patterns</li><li>Security Patterns</li><li>Deployment Patterns</li></ol><h3>1. Decomposition Patterns</h3><p>Decomposition patterns helps you in the transition from monolithic to microservices-based architectures. They define clear service boundaries between the services based on domains (scope of business), subdomains (business functions), or transactional needs (atomic units of work). Following are the four patterns that are classified as decomposition patterns.</p><h4>1.1. Domain-Driven Design (DDD)</h4><p>Domain-Driven Design (DDD) is a methodology for structuring software based on business domains. It breaks applications into smaller, self-contained microservices, each representing a bounded context (subdomain) — a clearly defined responsibility within a domain. This approach ensures high cohesion within services and reduces tight coupling between them.</p><blockquote>E-commerce platforms like Amazon use DDD by separating services such as Order Management, Inventory, and Payment Processing, allowing teams to develop, deploy, and scale these independently.</blockquote><h4>1.2. Strangler Fig Pattern</h4><p>The Strangler Fig Pattern allows you to carry out a gradual migration from a monolithic system to microservices. Instead of rebuilding the entire system at once, new features are implemented as microservices while progressively replacing legacy components. This reduces migration risk and avoids downtime.</p><blockquote>A banking system modernizing its customer onboarding process could start by implementing a new microservice for digital KYC (Know Your Customer) while keeping legacy systems for existing users. Over time, all onboarding processes are transitioned to microservices.</blockquote><h4>1.3. Smart Endpoints, Dumb Pipes</h4><p>This pattern ensures that business logic resides within microservices, while communication channels remain lightweight. “Smart Endpoints” refers to each microservice responsible for its own logic, data management and interactions. “Dumb Pipes” refers to infrastructure (such as message queues or network) which simply facilitates communication between services. It is an anti-pattern which discourages the use of complex middleware (e.g., Enterprise Service Buses) that centralize logic, reducing bottlenecks and improving system scalability.</p><blockquote>Ride-sharing apps like Uber follow this approach, where the services like Rider Matching, Pricing, and Payments communicate via simple REST or gRPC calls rather than relying on a heavyweight central broker.</blockquote><h4>1.4. Self-Contained Systems</h4><p>Self-Contained Systems (SCS) advocate for fully independent microservices that handle their own UI, logic, and database like an autonomous unit. This reduces dependencies and allows teams to build, deploy, and scale services independently while enhancing the overall system resilience.</p><blockquote>Media streaming platform like Netflix implement the separate microservices for User Profiles, Content Recommendations, and Video Playback, each running independently to ensure reliability and scalability.</blockquote><h4>Decision-making Insights</h4><p>Selecting the right decomposition pattern is crucial for maintainability and scalability. The table below provides insights into when each pattern is most effective.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d77d2686edf46462b8a81d85497f91b9/href">https://medium.com/media/d77d2686edf46462b8a81d85497f91b9/href</a></iframe><h3>2. Communication Patterns</h3><p>Communication patterns define how microservices interact, ensuring efficiency, reliability, and fault tolerance. Communication Patterns can be broadly categorised as Synchronous or Asynchronous. The right communication strategy prevents bottlenecks and ensures seamless data flow between services.</p><h4>2.1. API Gateway</h4><p>An API Gateway acts as a centralized entry point for client requests, handling authentication, logging, rate limiting, request transformation, and routing to appropriate microservices. It can facilitates both <em>synchronous communication</em>, where requests are processed in real-time with immediate responses, or <em>asynchronous communication</em>, where requests are queued and processed later using event-driven mechanisms. Hence, the API Gateway pattern simplifies client interactions while enhancing security by shielding internal services from direct exposure.</p><blockquote>E-commerce platforms like Amazon use API Gateways to manage requests from web, mobile, and third-party applications, ensuring secure and optimized access to services like product listings, cart management, and payments.</blockquote><h4>2.2. Service Mesh</h4><p>A Service Mesh is a dedicated infrastructure layer that manages service-to-service communication. While it facilitates both synchronous and asynchronous communication, it was primarily designed for synchronous communication. It provides load balancing, traffic control, encryption, and observability, reducing the complexity of managing inter-service interactions. Common implementations include Istio and Linkerd.</p><blockquote>Large-scale applications like Netflix use a Service Mesh to handle thousands of microservices (using tools developed internally like Ribbon, Eureka, and Zuul) for traffic management ensuring secure and efficient traffic management without adding logic to individual services.</blockquote><h4>2.3. Remote Procedure Invocation (RPI)</h4><p>Remote Procedure Invocation (RPI) is an synchronous communication pattern which enables direct communication between services using protocols like HTTP/REST or gRPC. In RPI pattern, a service calls an API exposed by another service and waits for a response before proceeding. It ensures real-time responses but can introduce failure risks if the dependent service is slow or unavailable.</p><blockquote>A payment gateways like Stripe relies on RPI to verify transactions in real time. When a user initiates a payment, Stripe’s microservices immediately validate the request before processing it.</blockquote><h4>2.4. Messaging Pattern</h4><p>Messaging pattern enables asynchronous communication using message brokers like RabbitMQ, Apache Kafka, or AWS SQS. It allows services to communicate without waiting for an immediate response. Services send messages to a queue, allowing decoupling and resilience even if a receiving service is down.</p><blockquote>Ride-sharing apps like Uber use messaging to handle trip status updates. When a driver updates their location, the event is published to Kafka, allowing passenger apps, maps, and billing systems to process the update asynchronously.</blockquote><h4>2.5. Service Registry</h4><p>A Service Registry pattern is an asynchronous communication pattern. It maintains a dynamic directory of active microservices, enabling automatic discovery and load balancing. This ensures that services can find and communicate with each other without hardcoded configurations.</p><blockquote>Microservices platforms like Netflix use a Service Registry (e.g., Eureka) to dynamically register and deregister services based on availability, ensuring efficient service discovery across its architecture.</blockquote><h4>2.6. Backends for Frontends (BFF)</h4><p>The Backends for Frontends (BFF) pattern can be implemented in both synchronous and asynchronous ways. It creates custom backends for different client types (e.g., web, mobile, IoT) to optimize performance. This ensures that each frontend receives data in a format suited to its needs, reducing unnecessary processing on the client side.</p><blockquote>Streaming services like Spotify use BFFs to tailor API responses for different devices — providing a lighter response for mobile apps while delivering more detailed data to the desktop web interface.</blockquote><h4>2.7. API Composition</h4><p>The API Composition pattern can implement either synchronous or asynchronous communication. It aggregates the data from multiple microservices into a single response, reducing the number of direct calls clients need to make to those services separately. This pattern is useful when building dashboards or reports requiring data from multiple services.</p><blockquote>A finance app like Mint aggregates data from bank accounts, credit cards, and investment platforms into a single user-friendly view, using API Composition to fetch and combine information.</blockquote><h4>2.8. Consumer-Driven Contracts</h4><p>Consumer-Driven Contracts (CDC) pattern is primarily suited for asynchronous communication, however, it can be used with synchronous communication as well. It ensures backward compatibility by allowing consumers (clients) to define expectations for an API’s response format. This prevents breaking changes when APIs evolve.</p><blockquote>Retail companies using third-party payment APIs (e.g., PayPal, Stripe) rely on CDCs to ensure that API changes do not disrupt their checkout systems, helping to maintain seamless payment processing.</blockquote><h4>2.9. Event-Driven Architecture</h4><p>In an Event-Driven Architecture, services communicate by emitting and responding to events instead of making direct API calls. It is primarily a asynchronous communication pattern. It improves scalability and responsiveness by allowing services to act independently.</p><blockquote>E-commerce sites like Amazon use event-driven architectures for order processing. When a customer places an order, an “Order Placed” event is triggered to services for inventory updates, payment processing, and shipment scheduling without requiring direct communication.</blockquote><h4>Decision-making Insights</h4><p>Choosing the right communication pattern depends on factors like performance needs, system reliability, and scalability. While synchronous methods (RPI, API Gateway) provide immediate responses, asynchronous methods (Messaging, Event-Driven Architecture) enhance resilience and decoupling. The table below provides insights into when each pattern is most effective.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/73c763f53ff2b24d1c87fe19e883f5b4/href">https://medium.com/media/73c763f53ff2b24d1c87fe19e883f5b4/href</a></iframe><h3>3. Data Management Patterns</h3><p>Data management patterns ensure data consistency, integrity, and scalability in microservices architectures. Since each microservice often manages its own data, these patterns help maintain efficient access, synchronization, and resilience.</p><h4>3.1. Database Per Service</h4><p>In Database Per Service pattern, each microservice owns its own database, preventing direct data sharing between services. This approach reduces tight coupling, allows independent scaling, and enables teams to choose the most suitable database for their needs. However, it requires careful handling of data consistency across services.</p><blockquote>E-commerce platforms like Amazon use this pattern where order management, inventory, and payment services each have separate databases, allowing them to scale independently without performance bottlenecks.</blockquote><h4>3.2. Saga Pattern</h4><p>The Saga Pattern manages distributed transactions across multiple microservices by breaking them into smaller, independent local transactions within each microservice. It is useful for long-running transactions and if one step fails, compensating transactions ensure data consistency instead of rolling back everything.</p><p>There are two common approaches:</p><ul><li><strong>Choreography — </strong>Each service listens for events and reacts accordingly. It is used when no single microservice controls all steps of the Saga.</li><li><strong>Orchestration —</strong> A central controller coordinates the flow of transactions i.e., all steps of the Saga.</li></ul><blockquote>In a travel booking system, separate services handle flight reservations, hotel bookings, and payments. If payment fails, previously confirmed bookings are automatically canceled using a compensating transaction.</blockquote><h4>3.3. Event Sourcing</h4><p>The Event Sourcing pattern records changes to a system’s state as a series of immutable events, instead of storing only the latest state. The system can be reconstructed by replaying events and easy rollbacks as well as it provides a detailed audit trail that can help compliance and regulatory requirements.</p><blockquote>Banking and financial applications (e.g., Revolut) use Event Sourcing to track all transactions and balance changes, ensuring transparency and enabling fraud detection by analyzing past events.</blockquote><h4>3.4. Command Query Responsibility Segregation (CQRS)</h4><p>CQRS separates write operations (commands) from read operations (queries), allowing each to be optimized independently. This is useful in the systems which has high read-to-write ratios, thus, improving performance and scalability.</p><blockquote>A social media platform like Twitter uses CQRS to handle millions of read requests efficiently while processing relatively fewer write operations (tweets, likes, comments).</blockquote><h4>3.5. Polyglot Persistence</h4><p>In Polyglot Persistence pattern, microservices are not restricted to a single type of database. In this pattern, each service and even different parts of the same microservice, you can choose the most suitable database technology (SQL, NoSQL, graph, time-series, etc.) based on its needs.</p><blockquote>A leading e-commerce platform like eBay uses MongoDB for product catalogs (flexible schema), PostgreSQL for order processing (relational consistency), Redis for caching recent searches (fast key-value lookups) and Elasticsearch for full-text search (high-speed indexing).</blockquote><h4>3.6. Data Sharding</h4><p>Data Sharding pattern splits large datasets into smaller, manageable partitions (shards) and distributing them across multiple database instances. This sharding improves performance, reduce load, and enables parallel processing. Sharding strategies are generally based on a predefined logic (e.g., geographic region, user ID range).</p><blockquote>Facebook shards its massive MySQL user database by User ID ranges across multiple servers based on geographic location, ensuring faster response times and efficient horizontal scaling. Additionally, it developed TAO (The Associations and Objects), which is a distributed data store and is optimized for handling billions of real-time social graph queries.</blockquote><h4>3.7. API Composition for Data</h4><p>Instead of directly querying multiple databases, in API Composition for Data pattern the data is aggregated from multiple microservices into a single response by a central orchestrator (or composer) and present it as a single unified API. This simplifies client interactions and improves efficiency in data access. It works best when the data retrieval process is light and does not uses complex joins. If complex joins are needed, CQRS or Database Per Service patterns might be better alternatives.</p><blockquote>Goldman Sachs’ Marcus Bank uses API Composition to consolidate financial data from multiple sources to their customer’s banking dashboard and ensures that their customers can view balances, transactions, and loans in real-time.</blockquote><h4>Decision-making Insights</h4><p>Choosing the right data management pattern depends upon scalability needs, performance requirements, and consistency constraints. While Database Per Service enables independence. Techniques like Event Sourcing, Saga, and CQRS ensures data consistency and efficient processing in distributed environments. The table below provides insights into when each pattern is most effective.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/29ba2a8f2d02e9ec52b4bf59202d6250/href">https://medium.com/media/29ba2a8f2d02e9ec52b4bf59202d6250/href</a></iframe><h3>4. Resilience Patterns</h3><p>Resilience patterns help microservices handle failures gracefully, ensuring that even when parts of the system fail, the overall application remains functional. These patterns minimize downtime, prevent cascading failures, and optimize system recovery.</p><h4>4.1. Circuit Breaker</h4><p>The Circuit Breaker pattern prevents a failing service from being overloaded with repeated requests. When the failures crosses a defined threshold, the circuit opens which temporarily blocks further calls. This gives the failing service enough time to recover before resuming operations.</p><blockquote>Netflix implemented the Circuit Breaker pattern in their recommendation engine through their Open-source library <strong>Hystrix</strong>, which is designed to handle latency and fault tolerance in distributed systems. At Netflix, if the recommendation engine becomes unresponsive, Hystrix opens a circuit breaker and stop requests, ensuring the rest of the system (like video playback) continues to work smoothly. However, now Netflix has moved from Hystrix to more advanced resilience strategies such as adaptive concurrency limits and server-side load balancing.</blockquote><h4>4.2. Bulkhead Pattern</h4><p>Inspired by compartmentalized ship design, this pattern isolates services or resources so that a failure in one part does not bring down the entire system. By limiting resource usage per service, it ensures critical functions remain operational.</p><blockquote>Microsoft Azure Service — Fabric uses the Bulkhead Pattern to isolate different microservices running on a distributed cloud infrastructure. For example, in a financial application, separate activities are handled by separate microservices for user authentication, payment processing, and fraud detection. So, even if the fraud detection service experiences a failure, authentication and payment processing remain fully operational and keep providing uninterrupted service for customers.</blockquote><h4>4.3. Retry Pattern</h4><p>The Retry pattern improves the system resilience by automatically retrying failed requests after a short delay, often using exponential backoff-where the wait time keeps on increasing after each failure. This pattern helps to avoid immediate failures and provides efficient way to handle temporary issues like network congestion or temporary service downtime.</p><blockquote>E-commerce checkout systems (like Amazon) or payment processors like Stripe uses Retry pattern to handle payment failures. If a payment request fails due to network issues, the system retries a few times before notifying the user.</blockquote><h4>4.4. Timeout Pattern</h4><p>The Timeout pattern sets a maximum wait time for each request, otherwise the service will keep waiting indefinitely for a response. If the response doesn’t arrive within this maximum wait time, the request is terminated, preventing resource exhaustion.</p><blockquote>In e-commerce platforms like Amazon, the payment gateway service has a specific timeout limit while processing the transactions. If a request to the payment provider takes too long due to server issues or network delays — the system automatically cancels the transaction and notify the user to retry with a different payment method.</blockquote><h4>4.5. Temporal Coupling</h4><p>The Temporal Coupling pattern avoids any bottlenecks and failures by making interactions between services asynchronous whenever possible. When the services are tightly linked in real-time, requiring immediate responses, unresponsiveness or slowness in any service may lead to bottlenecks and failures for other services which are waiting for a response. Hence, Temporal Coupling pattern ensures continued system’s functioning and improving reliability.</p><blockquote>Domino’s Pizza reduces temporal coupling by processing orders asynchronously. When a customer places an order, it is queued instead of waiting for real-time confirmation. The restaurant processes it independently while the system updates the user. Even if kitchen prep or driver assignment is delayed, the app remains responsive, ensuring seamless tracking and a smooth user experience.</blockquote><h4>4.6. Cross-Cutting Concerns</h4><p>Cross-cutting concerns, such as logging, authentication, security, and monitoring, are functionalities that span multiple components within a microservices architecture. By implementing Cross-Cutting Concerns pattern, these concerns are managed centrally, preventing code duplication and ensuring consistency across services.</p><blockquote>Netflix, implements centralized logging to handle cross-cutting concerns effectively. By aggregating logs from various services into a unified system, Netflix ensures consistent monitoring and troubleshooting across its platform. This approach enhances operational efficiency and maintains a seamless user experience.</blockquote><h4>4.7. Fail-Fast Principle</h4><p>The Fail-Fast Principle ensures that errors or invalid conditions in the system are detected early-on and stops processing immediately. This avoids unnecessary processing and wastage of resource. Furthermore, this allows faster recovery of the failed service.</p><blockquote>High-Frequency Trading (HFT) firms, such as Citadel Securities and Jump Trading, the decisions are made in microseconds. These firms implement fail-fast mechanisms that immediately halt processing upon detecting anomalies or invalid conditions, preventing potential cascading failures and conserving computational resources.</blockquote><h4>Decision-making Insight</h4><p>Resilience patterns ensure high availability and reliability in microservices-based systems. Circuit Breakers and Bulkheads prevent cascading failures, Retries and Timeouts improve responsiveness, and Fail-Fast and Asynchronous Design optimize resource usage. The table below provides insights into when each pattern is most effective.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5f308d92a73d1ce5f084dc1b2cd1f69d/href">https://medium.com/media/5f308d92a73d1ce5f084dc1b2cd1f69d/href</a></iframe><h3>5. Observability Patterns</h3><p>Observability patterns help developers to monitor, troubleshoot, debug, and enhance microservices-based systems. These patterns make sure that any issues such as failures or performance slowdowns are traced quickly and dealt efficiently. Hence, leading to a reliable and smooth experience for users.</p><h4>5.1. Distributed Tracing</h4><p>Distributed Tracing pattern helps by following the user requests across the services by assigning a unique identifier (Trace ID) to it. When the request flows through multiple microservices, distributed tracing helps in identifying slow components and performance bottlenecks enabling efficient debugging and performance analysis.</p><blockquote>In food delivery apps like Uber Eats, an order request triggers multiple services — restaurant, payment, delivery, and notifications. If is a delay in an order update, distributed tracing tools like Jaeger or Zipkin help engineers find specific service causing the lag. Jaeger developed by Uber is now a Cloud Native Computing Foundation (CNCF) graduated project. Similarly, Zipkin was developed by Twitter.</blockquote><h4>5.2. Log Aggregation</h4><p>Log Aggregation pattern centralizes logs into a single, searchable system, making it easier to track errors, detect patterns, and debug issues across microservices. Storing, managing and analyzing logs generated by each microservice separately is inefficient and hampers effectiveness.</p><blockquote>Netflix employes the ELK stack — Elasticsearch, Logstash and Kibana to collect and aggregate the logs from different microservices (authentication, content recommendation, streaming, etc.) in one place. This centralized aggregated logging approach helps engineers to quickly search logs to identify what went wrong in case of failures.</blockquote><h4>5.3. Health Check</h4><p>The Health Check pattern exposes an endpoint (e.g., /health) that reports if a service is operational or failing. Monitoring tools utilize this endpoint to proactively restart, alert, or redirect traffic when an issue is detected.</p><blockquote>Google Cloud Platform (GCP) utilizes health checks in its Managed Instance Groups (MIGs). When a virtual machine (VM) instance fails a health check, the MIG automatically recreates the instance to ensure continuous availability and reliability of applications.</blockquote><p>Observability patterns turn microservices into transparent, manageable systems. Distributed tracing finds bottlenecks, log aggregation simplifies debugging, and health checks ensure automatic recovery from failures. The table below provides insights into when each pattern is most effective.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d19042e73230e346a9c2593ad87a16af/href">https://medium.com/media/d19042e73230e346a9c2593ad87a16af/href</a></iframe><h3>6. Security Patterns</h3><p>Security patterns protect microservices from vulnerabilities, unauthorized access, and data breaches. Since microservices communicate over networks, they need robust security mechanisms to ensure only legitimate users and services can access data and functionalities. This can be ensured by implementing strong encryption, API gateways, identity management, and service-to-service authentication, reducing the risk of cyber threats.</p><h4>6.1. Token-Based Authentication</h4><p>Instead of handling usernames and passwords repeatedly, token-based authentication uses a secure, time-limited token to verify users and services. Common formats include JWT (JSON Web Tokens) and OAuth tokens.</p><blockquote>A mobile banking app issues a JWT token when a user logs in. This token is then attached to every request (e.g., checking balance, transferring money), allowing seamless authentication without requiring repeated logins.</blockquote><h4>6.2. API Security Gateway</h4><p>An API security gateway acts as a protective layer between clients and microservices. It handles authentication, authorization, rate limiting, and encryption, ensuring that only valid requests reach backend services.</p><blockquote>In e-commerce platforms like Flipkart or Amazon, an API gateway ensures that the users are authenticated before accessing their order history. The payment APIs are encrypted to protect credit card details and rate limits prevent bots from overwhelming the system with fake requests. Tools like Kong, Apigee, AWS API Gateway, etc. can be configured and utilised for this.</blockquote><h4>6.3. Zero Trust Security</h4><p>Traditional security models trust anything inside the network — but Zero Trust assumes no one is trustworthy by default. It requires continuous verification of every request, even if it comes from an internal service.</p><p>Key Principles of Zero Trust are:</p><ul><li><strong>Least Privilege — </strong>Each service gets only the access it absolutely needs.</li><li><strong>Multi-Factor Authentication (MFA) — </strong>Users must verify identity with passwords and biometrics.</li><li><strong>End-to-End Encryption — </strong>Data is always protected, even within internal networks.</li></ul><blockquote>A healthcare system following Zero Trust ensures that the doctor accessing patient records must authenticate every time, even within the hospital network. Communication from all services is encrypted and validated, preventing unauthorized data access.</blockquote><p>Security in microservices requires layered protection where Token-based authentication secures users and services, API gateways act as centralized security enforcers, whereas Zero Trust ensures continuous verification, eliminating blind trust. The table below provides insights into when each pattern is most effective.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4f0ee2ac3d2588443688c5950de0b029/href">https://medium.com/media/4f0ee2ac3d2588443688c5950de0b029/href</a></iframe><h3>7. Deployment Patterns</h3><p>Deployment patterns reduce risk and improve flexibility when releasing microservices. They help teams test, monitor, and roll out updates safely without disrupting users.</p><h4>7.1. Sidecar Pattern</h4><p>Instead of cluttering a microservice with extra functionalities (like logging, security, or monitoring), the sidecar pattern deploys these functionalities as separate but closely attached services. This keeps the core microservice clean and focused.</p><blockquote>In Netflix’s microservices architecture, a sidecar service collects logs and metrics from each microservice without modifying its code. Tools like Envoy and Istio commonly implement this pattern.</blockquote><h4>7.2. Shadow Deployment</h4><p>A shadow deployment introduces a new version of a service alongside the existing one, without affecting users. It mirrors real traffic to the new version to monitor performance before fully switching over.</p><blockquote>Pizza (small) teams at Amazon first deploys a new feature/experiment in shadow mode. This allows engineers to compare real-time results with the old feature without affecting customers.</blockquote><h4>7.3. Canary Deployment</h4><p>Instead of releasing updates all at once, canary deployment rolls them out gradually to a small subset of users before expanding. If issues arise, the rollout can be paused or rolled back.</p><blockquote>Facebook tests new features on a small percentage of users before making them available to everyone. If feedback is positive, they expand the rollout.</blockquote><h4>7.4. Blue-Green Deployment</h4><p>This method maintains two identical environments:</p><ul><li><strong>Blue</strong> (current version) serves live traffic.</li><li><strong>Green</strong> (new version) is tested in parallel.</li></ul><p>Once the new version is verified, traffic is switched from blue to green, ensuring zero downtime. If issues occur, switching back to blue is instant.</p><blockquote>A banking app deploying a critical security update uses blue-green deployment to ensure a seamless transition with no downtime for customers.</blockquote><p>While, Sidecar pattern keeps microservices lightweight by handling cross-cutting concerns separately, the Shadow deployment tests new versions with real traffic before rollout, whereas, Canary deployment gradually releases updates, reducing risk and Blue-green deployment ensures instant rollback, preventing downtime. The table below provides insights into when each pattern is most effective.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5f1cca560b80c836b15fdeede642e207/href">https://medium.com/media/5f1cca560b80c836b15fdeede642e207/href</a></iframe><h3>Conclusion</h3><p>Successfully adopting microservices isn’t just about breaking an application into smaller services — it’s about using the right patterns to ensure scalability, resilience, and maintainability. Each pattern plays a crucial role in solving common challenges, from efficient communication and data management to fault tolerance and security.</p><p>By strategically combining these patterns, teams can build robust, high-performing systems that thrive in modern cloud environments. The key is to choose patterns that align with your specific needs, ensuring a balance between flexibility, reliability, and performance.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=837becd16ca2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/quantrium-tech/an-overview-of-microservices-design-patterns-837becd16ca2">An Overview of Microservices Design Patterns</a> was originally published in <a href="https://medium.com/quantrium-tech">Quantrium.ai</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Technical Frameworks for building Agentic AI Systems]]></title>
            <link>https://medium.com/quantrium-tech/technical-frameworks-for-building-agentic-ai-systems-8bb5d9bd23d9?source=rss----41710727e242---4</link>
            <guid isPermaLink="false">https://medium.com/p/8bb5d9bd23d9</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[crew-ai]]></category>
            <category><![CDATA[phidata]]></category>
            <category><![CDATA[langgraph]]></category>
            <category><![CDATA[agentic-ai]]></category>
            <dc:creator><![CDATA[Sai Chaitanya Bandaru]]></dc:creator>
            <pubDate>Tue, 25 Mar 2025 05:15:30 GMT</pubDate>
            <atom:updated>2025-07-02T14:58:12.598Z</atom:updated>
            <content:encoded><![CDATA[<h4>QUANTRIUM GUIDES</h4><h4><em>Building Scalable and Adaptive AI Agents with Modern Frameworks</em></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E2xMOjDGtp5ViUerd3aR_w.jpeg" /></figure><p>In our previous article titled <strong><em>“</em></strong><a href="https://medium.com/quantrium-tech/what-is-agentic-ai-and-why-all-the-hype-ec4e5fd43813"><strong><em>What Is Agentic AI and Why All the Hype?</em></strong></a><strong><em>”</em></strong>, we explored the foundational concepts of Agentic AI, its core components, and how it stands apart from other AI paradigms like Generative AI and Traditional AI. We discussed how Agentic AI systems excel in autonomous decision-making, proactive behavior, and adaptability.</p><p>If you haven’t read that article yet, we highly recommend giving it a look before diving into this one. While it’s not a prerequisite, it will provide valuable context to better understand the technical frameworks discussed here.</p><p>As AI technology advances, selecting the right type of AI for a given problem is more crucial than ever. Two key paradigms, <strong>Agentic AI</strong> and <strong>Generative AI</strong>, offer distinct capabilities. Agentic AI excels in autonomous decision-making and goal-oriented tasks, while Generative AI is best suited for content creation, pattern recognition, and synthesis of new ideas. But how do you determine which one is best for your specific needs?</p><p>In this article, we’ll explore technical frameworks that empower developers to build robust Agentic AI systems, with a focus on<strong> PhiData, CrewAI, and LangGraph. </strong>These frameworks provide powerful tools for constructing autonomous agents capable of handling complex workflows and dynamic environments.</p><h3>How to Choose the Right AI?</h3><p>Selecting the right AI system depends on the nature of your problem. Here’s a checklist to help determine whether your use case requires an Agentic AI system.</p><p><strong>Checklist</strong></p><ul><li>Do you need autonomous decision-making?</li><li>Do you require actions to be taken without human intervention?</li><li>Does your system need to adapt to changing tasks and environments?</li><li>Do you need a system capable of handling a dynamic workflow?</li><li>Do you want the AI to proactively perceive and respond to inputs from multiple sources?</li><li>Does your system require real-time adaptation based on incoming data?</li><li>Do you need AI to collaborate with other AI agents or systems to achieve complex goals?</li><li>Are you looking for AI to execute multi-step tasks with minimal human supervision?</li></ul><p>Now, let’s apply this checklist to different scenarios and determine which type of AI is best suited for each case.</p><h4>Case 1: Fully Autonomous IT Incident Resolution System</h4><p>A large enterprise faces frequent IT incidents, such as server failures and network issues. They need a system that can detect, diagnose, and resolve these issues autonomously, without human intervention.</p><p><strong>Checklist</strong></p><ul><li>Do you need autonomous decision-making? ✔ <strong>Yes</strong></li><li>Do you require actions to be taken without human intervention? ✔ <strong>Yes</strong></li><li>Does your system need to adapt to changing tasks and environments? ✔ <strong>Yes</strong></li><li>Do you need a system capable of handling a dynamic workflow? ✔ <strong>Yes</strong></li><li>Do you want the AI to proactively perceive and respond to inputs from multiple sources? ✔ <strong>Yes</strong></li><li>Does your system require real-time adaptation based on incoming data? ✔ <strong>Yes</strong></li><li>Do you need AI to collaborate with other AI agents or systems to achieve complex goals? ✔ <strong>Yes</strong></li><li>Are you looking for AI to execute multi-step tasks with minimal human supervision? ✔ <strong>Yes</strong></li></ul><p>This system requires <strong>Agentic AI</strong>, as it must autonomously detect, diagnose, and resolve IT issues, adapt to new problems, and operate dynamically without human intervention.</p><h3>Case 2: AI-Powered Marketing Content Generator</h3><p>A marketing team wants to automate content creation for social media, blogs, and product descriptions using AI. The AI must generate engaging, high-quality content, but human reviewers will decide which content to use.</p><p><strong>Checklist</strong></p><ul><li>Do you need autonomous decision-making? ❌ <strong>No </strong>(Humans make the final decision)</li><li>Do you require actions to be taken without human intervention? ❌ <strong>No </strong>(AI assists but doesn’t act independently)</li><li>Does your system need to adapt to changing tasks and environments? ❌ <strong>No </strong>(The task — content creation — remains the same)</li><li>Do you need a system capable of handling a dynamic workflow? ❌ <strong>No </strong>(Workflow is structured and requires human oversight)</li><li>Do you want the AI to proactively perceive and respond to inputs from multiple sources? ✔ <strong>Yes </strong>(AI may use different data sources for content)</li><li>Does your system require real-time adaptation based on incoming data? ❌ <strong>No </strong>(Static content generation doesn’t need real-time changes)</li><li>Do you need AI to collaborate with other AI agents or systems to achieve complex goals? ❌ <strong>No </strong>(AI works independently)</li><li>Are you looking for AI to execute multi-step tasks with minimal human supervision? ❌ <strong>No </strong>(Humans oversee the final output)</li></ul><p><strong>Generative AI</strong> is the best fit for this case. The AI assists with content creation but doesn’t act autonomously or adapt dynamically — it supports human creativity rather than replacing decision-making.</p><h3>Case 3: AI-Driven Customer Support Assistant</h3><p>A company wants an AI-powered customer support assistant that can handle FAQs with static responses while also escalating urgent issues autonomously, ensuring a conversational and natural flow.</p><p><strong>Checklist</strong></p><ul><li>Do you need autonomous decision-making? ✔ <strong>Yes</strong> (For issue escalation and handling FAQs)</li><li>Do you require actions to be taken without human intervention? ✔ <strong>Yes </strong>(AI responds automatically and escalates when needed)</li><li>Does your system need to adapt to changing tasks and environments? ❌ <strong>No</strong> (Most responses are predefined, except escalations)</li><li>Do you need a system capable of handling a dynamic workflow? ✔ <strong>Yes</strong> (Customer queries vary, requiring adaptable conversations)</li><li>Do you want the AI to proactively perceive and respond to inputs from multiple sources? ✔ <strong>Yes</strong> (AI needs to process customer queries from multiple channels)</li><li>Does your system require real-time adaptation based on incoming data? ✔ <strong>Yes</strong> (AI must adjust responses based on customer input)</li><li>Do you need AI to collaborate with other AI agents or systems to achieve complex goals? ❌ No (Primarily a single-agent task)</li><li>Are you looking for AI to execute multi-step tasks with minimal human supervision? ✔ <strong>Yes</strong> (Handles conversations and escalations without constant oversight)</li></ul><p>This use case is <strong>partially agentic</strong>. The AI autonomously manages conversations and escalations but still relies on predefined rules for many responses. A <strong>hybrid approach</strong> combining <strong>Agentic AI + Generative AI</strong> is ideal, where Generative AI handles conversational interactions, while Agentic AI manages decision-making for escalations.</p><h3>Final Takeaways</h3><ul><li><strong>Agentic AI</strong> is best for systems requiring <strong>autonomous decision-making, real-time adaptation, and dynamic workflows</strong>.</li><li><strong>Generative AI</strong> excels at <strong>content creation and structured tasks where human oversight is required</strong>.</li><li><strong>Hybrid AI</strong> works well when <strong>both adaptability and creativity are needed</strong>, such as in AI-driven customer support.</li></ul><p>By applying this checklist to different cases, you can determine the right AI approach for your needs.</p><h3>Technical Frameworks for Agentic AI</h3><p>Agentic AI frameworks are gaining traction due to their ability to automate complex tasks with adaptability and decision-making capabilities. This guide covers three prominent frameworks: <strong>PhiData</strong>, <strong>CrewAI</strong>, and <strong>LangGraph</strong>, providing practical insights for implementing AI agents using these tools.</p><p><strong>Phidata (now Agno)</strong>: Phidata, recently rebranded as Agno, is an open-source framework for building multimodal AI agents and workflows. It allows developers to create agents equipped with memory, knowledge, tools, and reasoning capabilities, supporting various data types such as text, images, audio, and video.</p><p><strong>CrewAI</strong>: CrewAI is a lean, Python-based framework designed to orchestrate role-playing AI agents that collaborate to tackle complex tasks. Independent of other agent frameworks, it offers both high-level simplicity and precise low-level control, enabling the creation of autonomous AI agents tailored to diverse scenarios.</p><p><strong>LangGraph</strong>: Developed by LangChain, LangGraph is a low-level orchestration framework designed for building controllable AI agents. It enables the creation of stateful, multi-actor applications with large language models (LLMs), facilitating complex task automation and custom LLM-backed experiences.</p><h3>Hands-on Implementation Guide</h3><p>Regardless of the <strong>Agentic AI framework</strong> you choose, the core implementation steps remain the same. Follow this structured approach to build and deploy your agentic system effectively.</p><p><strong>Step 1: Define the Problem Statement</strong></p><p>Clearly outline the objectives of your AI agent. (Eg: Coordinating multiple agents for data scraping and analysis)</p><p><strong>Step 2: Create an Agent</strong></p><p>Develop the AI agent to execute tasks based on the defined objectives.</p><p><strong>Step 3: Integrate the Necessary Tools</strong></p><p>Equip your agent with the appropriate tools to enhance its functionality and task execution.</p><p><strong>Step 4: Add an LLM (if required)</strong></p><p>If natural language understanding or generation is needed, integrate a <strong>Large Language Model (LLM)</strong> to improve the agent’s capabilities.</p><p><strong>Step 5: Monitor the Agentic System</strong></p><p>Evaluate the initial performance of the system to ensure it functions as expected.</p><p><strong>Step 6: Optimize with Feedback or Human-in-the-Loop</strong></p><p>If improvements are needed, incorporate <strong>feedback loops</strong> or <strong>human oversight</strong> to enhance accuracy and efficiency.</p><h3>Creating a simple finance agent using Phidata</h3><p>Lets create a simple Finance agent supported by YFinance Tool in phidata. This is an <strong>episodic</strong> <strong>task</strong> (that have a terminal state). The results can directly printed on terminal.</p><p><strong>Install Phidata</strong></p><pre>pip install -U phidata==2.7.9</pre><p><strong>Requirements</strong></p><ol><li><strong>LLM </strong>— Add llm keys in env and configure the keys (the below code uses <strong>OpenAI</strong>)</li><li><strong>Tools </strong>— YFinanceTools for Finance agent</li></ol><p><strong>Install Tools</strong></p><p>Install yfinance library for YFinanceTools</p><pre>pip install yfinance==0.2.52</pre><p><strong>Create a Finance Agent</strong></p><p>Create a file finance_agent.py</p><pre>from phi.agent import Agent<br>from phi.model.openai import OpenAIChat<br>from phi.tools.yfinance import YFinanceTools<br><br>finance_agent = Agent( <br>    name=&quot;Finance Agent&quot;, # name for the agent <br>    model=OpenAIChat(id=&quot;gpt-4o&quot;), # llm model<br>    tools=[YFinanceTools(stock_price=True, analyst_recommendations=True, company_info=True, company_news=True)],  # tools for the agent<br>    instructions=[&quot;Use tables to display data&quot;],  # list of instructions<br>    show_tool_calls=True, # logs the AI tool calls<br>    markdown=True, # formats in Markdown for structured text<br>)<br>finance_agent.print_response(&quot;Summarize analyst recommendations for NVDA&quot;, stream=True)</pre><p><strong>Run the agent</strong></p><pre>python finance_agent.py</pre><p>This is an episodic task which prints the info on the terminal.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tn8t1QgQEZzQVB-hI56ZEg.png" /></figure><h4>Advantages</h4><ul><li><strong>Ease of Building</strong> — Designed for quick and simple development.</li><li><strong>Wide Range of Tools</strong> — Offers a variety of built-in <a href="https://docs.phidata.com/tools/introduction">tools </a>and supports custom tool creation.</li><li><strong>Playground</strong> — Provides an interactive playground for testing and building agents.</li><li><strong>Structured Agent Creation</strong> — PhiData agents have well-defined fields, making them easy to set up.</li><li><strong>Memory Support</strong> — Includes a <a href="https://docs.phidata.com/vectordb/introduction"><strong>vector database</strong></a> for storing and retrieving information.</li><li><strong>Embeddings &amp; Chunking</strong> — Supports efficient data processing and retrieval.</li><li><strong>Multi-Agent Collaboration</strong> — Allows multiple agents to work together.</li></ul><h4><strong>Drawbacks</strong></h4><ul><li><strong>Performance Limitations</strong> — The <strong>PhiData Playground crashes</strong> during heavy, continuous tasks due to load and complexity.</li><li><strong>Limited Visualization</strong> — No built-in visualization tools for better workflow monitoring.</li><li><strong>Working Transparency</strong> — Debugging tools are available, but <strong>understanding dynamic workflows can be difficult</strong> due to limited interpretability.</li></ul><h3>2. CrewAI — Building a Finance Agent</h3><p>Lets create a Agentic AI system with defined tasks for analyzing and reporting the stock market. Since its not a simple task we are going for multi-agent system for better performance and task delegation.</p><p><strong>Install CrewAI</strong></p><pre>pip install crewai==0.108.0</pre><p><strong>Setup API Keys</strong></p><p>CrewAI requires API keys for integrating with:</p><ul><li><strong>LLMs</strong> (e.g., OpenAI, Anthropic, etc.)</li><li><strong>Databases</strong> (for data storage and retrieval)</li></ul><p><strong>Components of a CrewAI Agent</strong></p><ul><li><strong>Role</strong>: Defines the agent’s primary function (e.g., <em>Financial Analyst</em>, <em>Reporting Specialist</em>).</li><li><strong>Goal</strong>: Outlines the agent’s intended outcome or objective (e.g., <em>Analyze NVDA stock performance</em>).</li><li><strong>Backstory</strong>: Provides context about the agent’s expertise, experience, or specialization to guide its behavior.</li><li><strong>Tools</strong>: Specifies the resources, APIs, or services the agent will use to achieve its goal (e.g., <em>YFinance</em>, <em>Google Docs</em>).</li></ul><p><strong>Build a Finance Agent</strong></p><pre>from crewai import Crew, Agent, Task<br>from openai import OpenAI<br><br>finance_agent = Agent(<br>    role=&quot;Financial Analyst&quot;,<br>    goal=&quot;Analyze NVDA stock performance and provide insights&quot;,<br>    backstory=&quot;An experienced financial analyst with expertise in stock market trends, known for delivering precise insights to guide investment strategies.&quot;,<br>    tools=[&quot;YFinance&quot;, &quot;AlphaVantage&quot;],<br>    model=OpenAI(&quot;gpt-4o&quot;),<br>)<br><br>reporting_agent = Agent(<br>    role=&quot;Reporting Specialist&quot;,<br>    goal=&quot;Generate a detailed report on NVDA performance&quot;,<br>    backstory=&quot;A skilled technical writer with extensive experience in financial reporting, adept at transforming data into clear, actionable insights.&quot;,<br>    tools=[&quot;Google Docs&quot;, &quot;Markdown&quot;],<br>    model=OpenAI(&quot;gpt-4o&quot;),<br>)<br><br>analysis_task = Task(<br>    description=&quot;Summarize analyst recommendations for NVDA&quot;,<br>    agent=finance_agent<br>)<br><br>report_task = Task(<br>    description=&quot;Create a structured report with insights&quot;,<br>    agent=reporting_agent<br>)<br><br>crew = Crew(agents=[finance_agent, reporting_agent], tasks=[analysis_task, report_task])<br>crew.kickoff()</pre><p><strong>Run the CrewAI Agent</strong></p><pre>python crewai_agent.py</pre><h4><strong>Observations</strong></h4><ul><li>CrewAI adopts a <strong>collaborative agent model</strong> where multiple agents can coordinate tasks.</li><li>Ideal for <strong>multi-step workflows</strong> that require agents to share information and refine decisions.</li></ul><h4><strong>Advantages</strong></h4><ul><li><strong>Robust Collaboration:</strong> CrewAI excels in <strong>multi-agent orchestration</strong>, enabling teamwork across specialized agents.</li><li><strong>Flexible Workflows:</strong> Supports complex, sequential decision-making processes.</li><li><strong>Human-in-the-Loop Support:</strong> Enables seamless human oversight during crucial decision points.</li><li><strong>Dynamic Role Assignment:</strong> Agents can adapt their roles and switch tasks as objectives evolve.</li></ul><h4>Drawbacks</h4><ul><li><strong>Setup Complexity:</strong> Requires API keys, model configurations, and additional dependencies.</li><li><strong>Learning Curve:</strong> Building multi-agent workflows may require more effort compared to PhiData.</li><li><strong>Execution Overhead:</strong> Managing multiple agents may introduce performance overhead for smaller tasks.</li></ul><h3>3. Creating a chatbot using LangGraph</h3><p>Lets create a chatbot using LangGraph with Anthropic</p><p><strong>Install LangGraph</strong></p><pre>pip install langgraph==0.3.7</pre><p><strong>Requirements</strong></p><p>LLM — requires API keys (used Anthropic for the code below)</p><p><strong>Initialize an LLM</strong></p><p>Create a file langgraph_workflow.py and add the following</p><pre>from langchain_anthropic import ChatAnthropic<br><br>llm = ChatAnthropic(model=&quot;claude-3-5-sonnet-20240620&quot;)</pre><p><strong>Create a LangGraph Workflow</strong></p><p>LangGraph is designed for workflow automation by defining nodes (steps) and edges (transitions) in the process.</p><pre>from typing import Annotated<br>from typing_extensions import TypedDict<br>from langgraph.graph import StateGraph, START, END<br>from langgraph.graph.message import add_messages<br><br>class State(TypedDict):<br>    # Messages have the type &quot;list&quot;. The `add_messages` function<br>    # in the annotation defines how this state key should be updated<br>    # (in this case, it appends messages to the list, rather than overwriting them)<br>    messages: Annotated[list, add_messages]<br><br>def chatbot(state: State):<br>    return {&quot;messages&quot;: [llm.invoke(state[&quot;messages&quot;])]}<br><br>graph_builder = StateGraph(State)<br><br># first arg is the unique node name, second arg is the function or object that <br># will be called whenever the node is used.<br>graph_builder.add_node(&quot;chatbot&quot;, chatbot)<br>graph_builder.add_edge(START, &quot;chatbot&quot;)<br>graph_builder.add_edge(&quot;chatbot&quot;, END)<br><br>graph = graph_builder.compile()</pre><p><strong>Visualize the workflow</strong></p><pre>with open(&quot;data/chat_bot_workflow.png&quot;, &quot;wb&quot;) as f:<br>    f.write(graph.get_graph().draw_mermaid_png())</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/107/1*4nuHRISDExiwRq_jl6rCMA.png" /><figcaption>Chat bot workflow</figcaption></figure><p><strong>Stream the updates</strong></p><pre>def stream_graph_updates(user_input: str):<br>    for event in graph.stream({&quot;messages&quot;: [{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: user_input}]}):<br>        for value in event.values():<br>            print(&quot;Assistant:&quot;, value[&quot;messages&quot;][-1].content)<br><br>while True:<br>    try:<br>        user_input = input(&quot;User: &quot;)<br>        if user_input.lower() in [&quot;quit&quot;, &quot;exit&quot;, &quot;q&quot;]:<br>            print(&quot;Goodbye!&quot;)<br>            break<br><br>        stream_graph_updates(user_input)<br>    except Exception:<br>        # fallback if input() is not available<br>        user_input = &quot;What do you know about LangGraph?&quot;<br>        print(&quot;User: &quot; + user_input)<br>        stream_graph_updates(user_input)<br>        break</pre><p><strong>Run the LangGraph Workflow</strong></p><pre>python langgraph_workflow.py</pre><h4>Observations</h4><ul><li>LangGraph is designed for <strong>structured workflow automation</strong>.</li><li>Each node represents a <strong>task</strong> or <strong>decision point</strong>, and edge transitions to control the workflow and also making it easy to visualize complex processes.</li></ul><h4>Advantages</h4><ul><li><strong>Clear Workflow Design:</strong> Nodes and edges simplify creating structured automation pipelines.</li><li><strong>Flexible Execution:</strong> Can dynamically adapt to different data inputs or logic paths.</li><li><strong>Modular Design:</strong> Encourages reusable code through modular task definitions.</li></ul><h4>Drawbacks</h4><ul><li><strong>Limited Tooling Integration:</strong> Compared to PhiData or CrewAI, LangGraph may require more custom code for specific data sources or APIs.</li></ul><h3>Comparative Summary</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/723/1*iXe3DMZxROR6_F3gAEv5dA.png" /></figure><h3>Conclusion</h3><p>This technical deep dive is not aimed at identifying the “best” framework but rather exploring the strengths, limitations, and ideal use cases for each. Each framework excels in different scenarios:</p><ul><li><strong>PhiData</strong> is best suited for simple tasks requiring <strong>quick implementation</strong> and minimal overhead. Its lightweight nature makes it ideal for straightforward, episodic workflows.</li><li><strong>CrewAI</strong> is the optimal choice for <strong>multi-agent collaboration</strong>, especially when tasks demand dynamic coordination, role management, and adaptable workflows.</li><li><strong>LangGraph</strong> stands out for its <strong>visual workflow design</strong> and clear process control, making it ideal for structured automation with defined steps and conditions.</li></ul><p>In essence, there’s no universal “best” framework — the right choice hinges on your project’s complexity, data flow, and adaptability needs. Combining these frameworks strategically can unlock powerful Agentic AI solutions for enterprise-scale applications.</p><p>These observations are based on our research. However, as AI frameworks continue to evolve, future upgrades may impact their capabilities. This technical article may not remain valid over time, and it is recommended to stay updated with the latest advancements.</p><p>This article is co‑authored by Yash Goel and me, combining our expertise in Agentic AI systems. Yash Goel contributed significantly by analyzing technical frameworks and providing insightful comparisons among them.</p><p><strong>References:</strong></p><ol><li><a href="https://www.langchain.com/langgraph?utm_source=chatgpt.com">https://www.langchain.com/langgraph</a></li><li><a href="https://docs.phidata.com/introduction?utm_source=chatgpt.com">https://docs.phidata.com/introduction</a></li><li><a href="https://docs.crewai.com/introduction?utm_source=chatgpt.com">https://docs.crewai.com</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8bb5d9bd23d9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/quantrium-tech/technical-frameworks-for-building-agentic-ai-systems-8bb5d9bd23d9">Technical Frameworks for building Agentic AI Systems</a> was originally published in <a href="https://medium.com/quantrium-tech">Quantrium.ai</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What Is Agentic AI and Why All the Hype?]]></title>
            <link>https://medium.com/quantrium-tech/what-is-agentic-ai-and-why-all-the-hype-ec4e5fd43813?source=rss----41710727e242---4</link>
            <guid isPermaLink="false">https://medium.com/p/ec4e5fd43813</guid>
            <category><![CDATA[agentic-workflow]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[agentic-ai-systems]]></category>
            <category><![CDATA[agentic-ai]]></category>
            <category><![CDATA[generative-ai-use-cases]]></category>
            <dc:creator><![CDATA[Sai Chaitanya Bandaru]]></dc:creator>
            <pubDate>Wed, 19 Mar 2025 03:01:48 GMT</pubDate>
            <atom:updated>2025-07-02T14:52:51.538Z</atom:updated>
            <content:encoded><![CDATA[<h4>QUANTRIUM GUIDES</h4><h4>Understanding the Rise of Autonomous AI Systems</h4><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/1*a0GI5MVJwkiW_Q6Sbwp6Bw.jpeg" /><figcaption>Agentic AI</figcaption></figure><p>The recent surge in interest around Agentic AI stems from its potential to revolutionise various industries by automating complex processes and enhancing efficiency. For instance, companies like ServiceNow and Salesforce are developing AI agents to autonomously handle tasks in customer service, HR, IT, and marketing, thereby increasing productivity and reducing operational costs.</p><p>Similarly, in healthcare, AI agents are being utilised to manage administrative tasks, assist in clinical trials, and support physicians in patient care, addressing challenges such as physician burnout and staffing shortages.</p><p>Since the start of 2025, there’s been a surge in hype around <strong>Agentic AI</strong>, along with plenty of speculation about whether AI could eventually replace humans. But what exactly is Agentic AI, and how does it differ from Generative AI? Let’s explore.</p><h3>What’s Agentic AI?</h3><p>Agentic AI refers to autonomous systems capable of dynamic learning, interacting within complex environments, and making decisions independently. Unlike Generative AI, which primarily creates content based on input, Agentic AI can act proactively, take initiative, and adapt to evolving situations without constant human guidance.</p><h3>Agentic AI vs. Other AI Paradigms</h3><p>Here we have compared the three generations of AI depicting evolution of AI over time:</p><ol><li>Agentic AI (3rd Gen),</li><li>Generative AI (2nd Gen)</li><li>Traditional AI (1st Gen)</li></ol><h4>Agentic AI vs Generative AI vs Traditional AI</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*etzDkkIcNJu3FGFYsyA9xg.png" /><figcaption>Agentic AI vs Generative AI vs Traditional AI</figcaption></figure><p>In simple terms:</p><ul><li><strong>Agentic AI</strong> → Proactive, autonomous, decision-making.</li><li><strong>Generative AI</strong> → Content creation, responsive, dependent on prompts.</li><li><strong>Traditional AI</strong> → To solve tasks based on specific rules and pre-defined logic.</li></ul><p>This ability to independently navigate and respond to complex environments is what sets Agentic AI apart and why it’s generating so much excitement.</p><h3>How is Agentic AI different from Generative AI?</h3><p>While Agentic AI promises autonomous decision-making, <strong>LLM + API setups</strong> (alongside RAG and similar architectures) already deliver immense value as highly capable <strong>Generative AI systems</strong>. Here is a detailed comparison.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/725/1*24YBjsna4fQLaqBQcS5mDA.png" /><figcaption>Agentic AI System vs LLM+API System</figcaption></figure><h4>Example: Research Assistant Task</h4><p><strong>Agentic AI:</strong></p><ul><li>One agent autonomously finds relevant sources, another summarizes the content, and a third fact-checks for accuracy.</li><li>The agents work together, refining outputs and continuously improving the final result — all without constant human intervention.</li></ul><p><strong>LLM + API:</strong></p><ul><li>The user manually requests information, summarizes the findings, and verifies accuracy step by step.</li><li>Each stage requires explicit API calls and human oversight, making the process more hands-on and time-consuming.</li></ul><h4>When to Use Each Approach</h4><p><strong>Use Agentic AI when:</strong></p><ul><li>You need <strong>autonomous, multi-step decision-making.</strong></li><li>Tasks require <strong>collaboration among AI agents.</strong></li><li>Adaptability and <strong>self-improvement</strong> are important.</li></ul><p><strong>Use LLM + API when:</strong></p><ul><li>You need <strong>simple, transactional AI responses.</strong></li><li>The task is <strong>well-defined and does not require adaptability.</strong></li><li>You can manually <strong>orchestrate API calls</strong> efficiently.</li></ul><h3>Components of Agentic AI</h3><p>Agentic AI systems have several interconnected components that work together to enable intelligent behavior. Each component plays a crucial role in the overall functioning of the AI system, and they must interact seamlessly to achieve desired outcomes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/727/1*ldOSQLjYA3vZmgLXt1Tn6w.png" /><figcaption>Components of Agentic AI</figcaption></figure><p><strong>Perception Module</strong> — Captures and interprets real-world data using AI techniques like vision and NLP.</p><p><strong>Cognition Module</strong> — Analyzes information, makes decisions, and plans actions based on learned patterns.</p><p><strong>Action Module</strong> — Executes decisions by performing digital or physical tasks autonomously</p><h3>Why Is There So Much Hype Around Agentic AI?</h3><p>The buzz around Agentic AI isn’t just noise — it’s driven by the tangible benefits these systems bring to organizations. Let’s break down the key factors fueling its rising popularity:</p><ul><li><strong>Automation Needs:</strong> Companies are eager to streamline operations and minimize manual effort, making autonomous systems a powerful asset for boosting efficiency.</li><li><strong>Adaptability:</strong> Agentic AI can adjust to evolving environments and shifting data, ensuring it stays relevant and effective in a variety of scenarios.</li><li><strong>Enhanced Decision-Making:</strong> These systems can analyze complex data and make informed decisions without human intervention, helping businesses act faster and more strategically.</li><li><strong>Scalability:</strong> Agentic AI handles growing workloads with ease, scaling operations without a linear increase in costs or resource demands.</li><li><strong>Cost-Effectiveness:</strong> By automating repetitive tasks and reducing reliance on human oversight, organizations can cut operational expenses while maintaining high performance.</li></ul><p>With these capabilities, it’s easy to see why businesses across industries are eager to explore Agentic AI. But what about its impact on our day-to-day lives?</p><h3>How Can Agentic AI Make Our Lives Easier?</h3><p>Agentic AI isn’t just a futuristic concept — it’s a game-changer for simplifying tasks, boosting productivity, and freeing us up to focus on what truly matters. Here’s how it can transform both work and personal life:</p><ul><li><strong>Automate Workflows:</strong> Seamlessly handle repetitive tasks, from scheduling meetings to managing customer inquiries, freeing up valuable time for more meaningful work.</li><li><strong>Focus on High-Impact Work:</strong> By handling time-consuming, low-value tasks, Agentic AI allows people to concentrate on strategic, creative, and high-priority initiatives.</li><li><strong>Generate &amp; Refine Content:</strong> Create, edit, and optimize content effortlessly — whether it’s drafting reports, crafting emails, or refining presentations.</li><li><strong>Intelligent Data Gathering &amp; Analysis:</strong> Collect and process data from various sources (like voice commands, text, or even receipts) to make faster, more accurate decisions — sometimes even outperforming humans in complex scenarios.</li></ul><p>From personal assistants to workplace optimization, Agentic AI has the potential to revolutionize how we manage time and resources. However, as with any powerful technology, it comes with its own set of challenges.</p><h3>Can We Trust Agentic AI Completely?</h3><p>While Agentic AI holds incredible promise, it’s not without its limitations. Understanding these potential pitfalls is essential for organizations to adopt the technology responsibly.</p><ul><li><strong>The Illusion of Control:</strong> Enterprises may feel in control when setting up AI agents, but many of these systems operate as black boxes. Without proper oversight, AI-driven decisions can become unpredictable — and in highly regulated sectors like finance or healthcare, even small missteps can have serious consequences.<br>😇 <em>Implement robust monitoring and feedback loops to ensure continuous human oversight and mitigate unexpected outcomes.</em></li><li><strong>The Maintenance Challenge:</strong> Although Agentic AI systems promise rapid deployment and adaptive learning, they often lack robust maintenance frameworks. Most automation work happens after deployment, and small process tweaks can cause unintended side effects, turning continuous improvement into a complex challenge.<br>😇<em> Establish clear update and retraining protocols to ensure the AI evolves safely and aligns with changing business needs.</em></li><li><strong>The Reliability Mirage:</strong> Even with error rates as low as 1–5%, inaccuracies in high-stakes environments like banking or legal compliance are unacceptable. A single misstep can lead to financial losses, reputational damage, or legal complications, making complete trust in AI a risky bet.<br>😇 <em>Use AI as an assistive tool for decision support rather than a fully autonomous solution in high-risk areas.</em></li><li><strong>The Governance Gap:</strong> The rise of “shadow AI” — unauthorized or fragmented AI use across organizations — mirrors past issues with shadow IT. Without centralized governance, businesses face compliance breaches, inconsistent processes, and a fragmented tech landscape that’s difficult to manage.<br>😇 <em>Create a centralized AI governance team to set policies, track AI usage, and ensure compliance across the enterprise.</em></li><li><strong>The Learning Dilemma:</strong> Agentic AI lacks structured lifecycle management, which can cause processes to become outdated over time. Without a clear change management strategy, organizations risk AI systems making decisions based on obsolete information, diminishing long-term effectiveness.<br>😇 <em>Implement lifecycle management practices, including regular audits and periodic retraining, to keep AI systems aligned with evolving goals and data.</em></li></ul><h3>Final Thoughts</h3><p>Agentic AI is undeniably powerful technology that promises to reshape industries, streamline workflows, and even make our daily lives more convenient. But with great power comes great responsibility. For businesses and individuals alike, balancing excitement with caution is key.</p><p>By understanding both the potential and the limitations of Agentic AI, we can harness its strengths while mitigating its risks. With the right mix of innovation, governance, and continuous oversight, Agentic AI can be an extraordinary tool for progress.</p><p>So, can we trust Agentic AI completely? Maybe not yet. But can we leverage it to build a smarter, more efficient future? Absolutely.</p><p>This article is co‑authored by Yash Goel and me, bringing together our shared expertise in Agentic AI research. In particular, Yash Goel played a key role in identifying real-world use cases, and providing thoughtful comparisons between different AI paradigms which were essential to shaping the article’s core insights.</p><p><strong>References</strong></p><ol><li><a href="https://www.youtube.com/watch?v=xOS0BhhdUbo">https://www.youtube.com/watch?v=xOS0BhhdUbo</a></li><li><a href="https://www.uipath.com/ai/agentic-ai">https://www.uipath.com/ai/agentic-ai</a></li><li><a href="https://aisera.com/blog/agentic-ai/">https://aisera.com/blog/agentic-ai/</a></li><li><a href="https://www.automationanywhere.com/rpa/agentic-ai#:~:text=Despite%20their%20autonomy%2C%20agentic%20AI,judgment%20or%20deep%20contextual%20understanding">https://www.automationanywhere.com/rpa/agentic-ai#:~:text=Despite%20their%20autonomy%2C%20agentic%20AI,judgment%20or%20deep%20contextual%20understanding</a>.</li><li><a href="https://scet.berkeley.edu/the-next-next-big-thing-agentic-ais-opportunities-and-risks/">https://scet.berkeley.edu/the-next-next-big-thing-agentic-ais-opportunities-and-risks/</a></li><li><a href="https://markovate.com/blog/agentic-ai-architecture/">https://markovate.com/blog/agentic-ai-architecture/</a></li><li><a href="https://nexustrade.io/blog/you-are-an-absolute-moron-for-believing-in-the-hype-of-ai-agents-20250111">https://nexustrade.io/blog/you-are-an-absolute-moron-for-believing-in-the-hype-of-ai-agents-20250111</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ec4e5fd43813" width="1" height="1" alt=""><hr><p><a href="https://medium.com/quantrium-tech/what-is-agentic-ai-and-why-all-the-hype-ec4e5fd43813">What Is Agentic AI and Why All the Hype?</a> was originally published in <a href="https://medium.com/quantrium-tech">Quantrium.ai</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Writing cleaner Python code with Sphinx docstrings]]></title>
            <link>https://medium.com/quantrium-tech/write-cleaner-python-code-with-sphinx-docstrings-952c9afb6771?source=rss----41710727e242---4</link>
            <guid isPermaLink="false">https://medium.com/p/952c9afb6771</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[docstring]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[code]]></category>
            <dc:creator><![CDATA[Bhargav Sridhar]]></dc:creator>
            <pubDate>Thu, 13 Mar 2025 16:16:41 GMT</pubDate>
            <atom:updated>2025-08-12T20:51:18.123Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://medium.com/quantrium-tech">QUANTRIUM GUIDES</a></h4><h4><em>Structuring, automating, and improving documentation of your Python projects</em></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/945/1*9p2ARvezxeZjI8i6LLYtCw.png" /><figcaption>Image generated by DALL-E, OpenAI</figcaption></figure><p>In one of my previous articles, I highlighted the key skills to build and excel in various roles in the data domain:</p><p><a href="https://ai.gopubby.com/opportunities-in-the-data-market-an-overview-4318a1dfd0cd">Exploring the opportunities in the data market</a></p><p>Programming and software development are essential skills for building a successful career in engineering roles (related to data). As a data, machine learning (ML) or AI engineer, a strong foundation in Object-Oriented Programming, classes, and user-defined functions is crucial for writing efficient code and developing robust data pipelines.</p><p>Additionally, developing reusable functions and modular components is paramount as they play an important role in maintainability and scalability for such data-driven projects. <strong>Docstrings</strong> act as structured function descriptions, enhancing code readability and clarity. They make it easier to understand the code, extend and re-purpose functions across different projects, and improve both collaboration and efficiency.</p><p>Building on this foundation, this article introduces the most popular <strong>Sphinx docstring format</strong>, demonstrating how it enhances code documentation and clear function descriptions. Through practical examples, you’ll see how to make use of <strong>Sphinx-style docstrings</strong>. I have used VS Code editor to create my classes and functions along with the docstrings, demonstrating how they help you to make your functions more intuitive and easier to understand.</p><p>The Sphinx docstrings format follows a structured approach to document functions, ensuring clarity in their purpose, inputs, outputs, and potential errors.</p><h4>Standard Sphinx Docstrings Format</h4><pre>&quot;&quot;&quot;<br>&lt;Function summary&gt;<br>    <br>:param [parameter_name]: [parameter description]<br>:type [parameter_name]: [parameter datatype](, optional)<br>.<br>.<br>.<br><br>:raises [exception type]: [exception description]<br>.<br>.<br>.<br><br>:returns: [description]<br>:rtype: [datatype of output returned]<br>&quot;&quot;&quot;</pre><p>This format provides a consistent and professional way to document code while making it easier for developers to understand function’s behavior in one glance. Additionally, it enables automatic generation of API documentation, which is widely used in Python and data-driven projects to faciliate collaboration and improve maintainability.</p><h3>Docstrings in Action — Python</h3><p>Before diving into examples, ensure that the python docstring extension is installed in VS Code (as shown in Figure 1). This extension streamlines the process of adding structured docstrings to your functions and classes.</p><h4>Setting up Sphinx Docstrings Format in VS Code</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VJrAbTutFUgwh1aV-sgAIQ.png" /><figcaption>Figure 1: Installing Python docstring extension in VS Code (Image by author)</figcaption></figure><p>To enable the Sphinx-style docstrings by default, follow these steps (illustrated in Figure 2).</p><ul><li>Go to File &gt; Preferences &gt; Settings</li><li>Search for autoDocstring.docstringFormat</li><li>Change the format to sphinx</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-7KUtNmhDOf1Zuy_zXu5Ug.png" /><figcaption>Figure 2: Specifying Sphinx docstring format in VS Code (Image by author)</figcaption></figure><p>Once configured, you can automatically generate well-structured docstrings.</p><h3>Applying Docstrings to an OCR Project</h3><p>To see docstrings in action, let’s revisit an Optical Character Recognition (OCR) project I previously worked on using docTR OCR.</p><p><a href="https://medium.com/quantrium-tech/text-extraction-using-doctr-ocr-471e417764d5">Extracting text from an image using docTR OCR</a></p><p>We will rewrite the same functionality using Object-Oriented Programming (OOP) principles and structured Sphinx Docstrings.</p><p>First, let’s import the necessary modules.</p><pre>from doctr.models import ocr_predictor<br>from doctr.io import DocumentFile<br>import PIL<br>from PIL import ImageDraw<br>import math<br>import json</pre><p>Now, let’s define the DocTROCR class, which leverages the docTR OCR model to extract text from documents. The class follows an object-oriented approach, with well-structured Sphinx docstrings for auto-generated documentation.</p><h4>DocTROCR Class</h4><pre>class DocTROCR:<br>    &quot;&quot;&quot;<br>    Class to extract text from a document using docTR OCR model.<br><br>    :param file_path: path to the image file<br>    :type file_path: `str`<br>    &quot;&quot;&quot;<br>    def __init__(self, file_path):<br>        &quot;&quot;&quot;Constructor method<br>        &quot;&quot;&quot;<br>        self.file_path = file_path<br>        self.model = ocr_predictor(det_arch = &#39;db_resnet50&#39;,    <br>            reco_arch = &#39;crnn_vgg16_bn&#39;, <br>            pretrained = True<br>        ) <br><br>    def convert_coordinates(self, geometry, page_dim):<br>        &quot;&quot;&quot;<br>        Function to convert geometric coordinates to graphical coordinates.<br><br>        :param geometry: list of coordinates in geometric form ([(x_min, y_min), (x_max, y_max)])<br>        :type geometry: `list`<br>        :param page_dim: dimensions of the page ([dim_y, dim_x])<br>        :type page_dim: `list`<br><br>        :raises Exception: If an error occurs while converting coordinates<br><br>        :return: list of coordinates in graphical format ([x_min, x_max, y_min, y_max]) <br>        :rtype: `list`<br>        &quot;&quot;&quot;<br>        try:<br>            dim_x = page_dim[1]<br>            dim_y = page_dim[0]<br>            (x_min, y_min) = geometry[0]<br>            (x_max, y_max) = geometry[1]<br>            x_min = math.floor(x_min * dim_x)<br>            x_max = math.ceil(x_max * dim_x)<br>            y_min = math.floor(y_min * dim_y)<br>            y_max = math.ceil(y_max * dim_y)<br>            return [x_min, x_max, y_min, y_max]<br>        except Exception as ex:<br>            raise Exception(<br>                f&quot;Error in converting coordinates: {ex}&quot;<br>            )<br><br>    def get_graphical_coordinates(self, output):<br>        &quot;&quot;&quot;<br>        Function to get graphical coordinates of the text.<br><br>        :param output: OCR output obtained from the model<br>        :type output: `dict`<br><br>        :raises Exception: If an error occurs while getting graphical coordinates<br><br>        :return: list of graphical coordinates of the text<br>        :rtype: `list`<br>        &quot;&quot;&quot;<br>        try:<br>            page_dim = output[&#39;pages&#39;][0][&quot;dimensions&quot;]<br>            text_coordinates = []<br>            for obj1 in output[&#39;pages&#39;][0][&quot;blocks&quot;]:<br>                for obj2 in obj1[&quot;lines&quot;]:<br>                    for obj3 in obj2[&quot;words&quot;]:                <br>                        converted_coordinates = self.convert_coordinates(<br>                                                obj3[&quot;geometry&quot;],page_dim<br>                                                )<br>                        print(&quot;{}: {}&quot;.format(converted_coordinates,<br>                                            obj3[&quot;value&quot;]<br>                                            )<br>                            )<br>                        text_coordinates.append(converted_coordinates)<br>            return text_coordinates<br><br>        except Exception as ex: <br>            raise Exception(<br>                f&quot;Error in getting graphical coordinates: {ex}&quot;<br>            )<br><br>    def get_ocr_output(self):<br>        &quot;&quot;&quot;<br>        Function to get the output of the OCR model.<br><br>        :raises Exception: If an error occurs while getting OCR output<br><br>        :return: OCR output<br>        :rtype: `dict`<br>        &quot;&quot;&quot;<br>        try:<br>            img = DocumentFile.from_images(self.file_path)<br>            result = self.model(img)<br>            self.output = result.export()<br>            return self.output<br>        except Exception as ex:<br>            raise Exception(<br>                f&quot;Error in getting OCR output: {ex}&quot;<br>            )<br>    <br>    def show_ocr_output(self):<br>        &quot;&quot;&quot;<br>        Function to display the output of the OCR model.<br><br>        :raises Exception: If an error occurs while displaying OCR output<br>        &quot;&quot;&quot;<br>        try:<br>            for obj1 in self.output[&#39;pages&#39;][0][&quot;blocks&quot;]:<br>                for obj2 in obj1[&quot;lines&quot;]:<br>                    for obj3 in obj2[&quot;words&quot;]:<br>                        print(&quot;{}: {}&quot;.format(obj3[&quot;geometry&quot;],obj3[&quot;value&quot;]))<br>        except Exception as ex:<br>            raise Exception(<br>                f&quot;Error in displaying OCR output: {ex}&quot;<br>            )<br><br>    def write_ocr_output(self, output):<br>        &quot;&quot;&quot;<br>        Function to write the output to a JSON file.<br><br>        :param output: OCR output obtained from the model<br>        :type output: `dict`<br><br>        :raises Exception: If an error occurs while writing output to a JSON file<br>        &quot;&quot;&quot;<br>        try:<br>            with open(&quot;path/docTROCR_sample_output.json&quot;, &quot;w&quot;) as f:<br>                f.write(json.dumps(output, indent=1))<br>            f.close()<br>        except Exception as ex:<br>            raise Exception(<br>                f&quot;Error in writing output: {ex}&quot;<br>            )<br>        <br>    def draw_bounding_boxes(self, image, bound):<br>        &quot;&quot;&quot;<br>        Function to draw bounding boxes on the image.&quot;<br><br>        :param image: image on which bounding boxes are to be drawn<br>        :type image: `PIL.Image`<br>        :param bound: list of bounding boxes<br>        :type bound: `list`<br><br>        :raises Exception: If an error occurs while drawing bounding boxes<br><br>        :return: image with bounding boxes drawn<br>        :rtype: `PIL.Image`<br>        &quot;&quot;&quot;<br>        try:<br>            draw = ImageDraw.Draw(image)<br>            for b in bound:<br>                p0, p1, p2, p3 = [b[0],b[2]], [b[1],b[2]], \<br>                                [b[1],b[3]], [b[0],b[3]]<br>                draw.line([*p0,*p1,*p2,*p3,*p0], fill=&#39;blue&#39;, width=2)<br>            return image<br>        except Exception as ex:<br>            raise Exception(<br>                f&quot;Error in drawing bounding boxes: {ex}&quot;<br>            )</pre><p>By integrating Sphinx docstrings, we have transformed the OCR extraction class into a well-documented, readable, and maintainable Python module. Hence, the structured docstrings provide:</p><ul><li>clearly defined function purpose, parameters, return types, and exceptions.</li><li>automated API documentation for improved projected scalability.</li><li>improved collaboration between the developers and code reusability.</li></ul><p>It is a structured and efficient way to document Python code and bridges the gap between code and documentation.</p><h3>Final Thoughts</h3><p>Adopting docstrings best practices also ensures that documentation stays updated with the codebase, benefiting individual developers and larger teams associated with your project. Try implementing Sphinx docstrings in your existing or future projects, and share your thoughts or queries in the comments. Stay tuned for similar content. Happy Coding!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=952c9afb6771" width="1" height="1" alt=""><hr><p><a href="https://medium.com/quantrium-tech/write-cleaner-python-code-with-sphinx-docstrings-952c9afb6771">Writing cleaner Python code with Sphinx docstrings</a> was originally published in <a href="https://medium.com/quantrium-tech">Quantrium.ai</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Bother About O(nlog⁡n) vs O(n²)?]]></title>
            <link>https://medium.com/quantrium-tech/why-bother-about-o-nlog-n-vs-o-n%C2%B2-233cb7d8c3d1?source=rss----41710727e242---4</link>
            <guid isPermaLink="false">https://medium.com/p/233cb7d8c3d1</guid>
            <category><![CDATA[time-complexity]]></category>
            <category><![CDATA[sorting-algorithms]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[python]]></category>
            <dc:creator><![CDATA[Naveen Gabriel]]></dc:creator>
            <pubDate>Wed, 05 Feb 2025 17:29:58 GMT</pubDate>
            <atom:updated>2025-02-06T04:46:32.580Z</atom:updated>
            <content:encoded><![CDATA[<h4>Quantrium Guides</h4><h4><em>The Hidden Costs of Ignoring Algorithmic Complexity in Sorting</em></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/853/1*tkv776tvuAr0rP0UEJ0seA.png" /></figure><p>If you’ve ever looked into sorting algorithms, you’ve likely seen this classic comparison:</p><ul><li><strong>O(nlogn) sorts: </strong>Merge Sort, Heap Sort, and Quick Sort (on average)</li><li><strong>O(n²) sorts:</strong> Bubble Sort, Selection Sort, and Insertion Sort</li></ul><blockquote>And then, the cliche conclusion:<br>“<em>For large datasets, always use O(nlogn)!”</em></blockquote><p>But why does this <strong>actually</strong> matter? Is O(nlog⁡n) that much better? Let’s take a closer look.</p><h3>A Curious Look: How Fast Sorting Algorithm Grow</h3><p>Let’s take a <strong>concrete</strong> comparison to see how the complexities scale with large data sizes. Consider sorting <strong>1 million elements.</strong></p><p>If we use an O(n²) algorithm, the worst case gives: <br> n² = (10⁶)² = 10¹²</p><p>If we use an O(nlogn) algorithm, assuming base-2 logarithm:<br> nlog₂⁡n = 10⁶ * log₂(10⁶)</p><p>Since log₂(10⁶) ≈ 20, this simplifies to : 10⁶×20=2×10⁷</p><p>Now, let’s <strong>compare these numbers </strong>: 10¹²(quadratic) vs 2×10⁷(log-linear)<br>That’s a <strong>50,000x faster!</strong></p><p>Imagine an algorithm that runs in <strong>1 second</strong> for O(nlog⁡n) sort.</p><ul><li>If you use an O(n²) sort instead, you’d wait <strong>about 14 hours</strong> for the same data size!</li><li>When n becomes 10⁹, O(n²) would take 9,250 hours to solve whereas O(nlogn) would take just 8.3 hours!</li></ul><h3>The Computational Paradox</h3><p>Even if Moore’s Law held indefinitely, pushing computational power forward, algorithms would still hit a wall where they become unusable. The growth rate isn’t just about current speed — it’s about the <strong>fundamental physics</strong> of computation.</p><p><strong><em>This is why algorithmic improvements are often more valuable than raw hardware advancements.</em></strong></p><h3>Why Some Sorting Algorithms Avoid O(nlogn)</h3><p>So, why don’t we <strong>always</strong> use O(nlog⁡n) sorting algorithms?</p><p>One big reason is <strong>space complexity</strong>. Many of the fastest sorting algorithms, like <strong>Merge Sort</strong>, require <strong>extra memory</strong> proportional to the input size O(n), making them problematic for <strong>large datasets</strong>.</p><p>Most programming languages provide built-in sorting functions, but not all of them are truly <strong>in-place</strong>.</p><p><strong>Why Merge Sort Might Be Bad in Some Cases</strong><br>While Merge Sort is often seen as a safe choice due to its worst-case guarantee of O(nlog⁡n), it can be inefficient in memory-limited environments due to the extra O(n) space requirement. This is why Python’s sort() (Timsort) and C++&#39;s std::sort() (Introsort) combine <strong>Quick Sort + Heap Sort + Insertion Sort</strong> for <strong>in-place</strong> efficiency.</p><h3>Surprising Takeaway</h3><p>In many practical applications, especially those involving large-scale datasets, even an O(nlog⁡n) algorithm can start to show inefficiencies once the dataset reaches a certain size. That is because, the real-world systems are never perfect, and the overhead of managing large datasets in memory, caching, and hardware limitations can shift the balance.</p><blockquote>The true magic is in understanding the nuances of both time and space complexities and choosing the right algorithm not just based on theoretical performance but also based on how your application will scale and interact with the system as a whole.</blockquote><h3>Final Thought</h3><p>The difference between <strong>O(nlogn)</strong> and <strong>O(n²)</strong> isn’t just a technical detail — it defines what problems can be solved within a human lifetime. Understanding these differences allows better decisions in designing algorithms, choosing data structures, and performance optimization.</p><p>So next time you encounter a sorting algorithm, ask yourself: <em>Is it O(nlogn) or O(n²)?</em> The answer could mean the difference between completing a task in seconds or dragging-on for centuries.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=233cb7d8c3d1" width="1" height="1" alt=""><hr><p><a href="https://medium.com/quantrium-tech/why-bother-about-o-nlog-n-vs-o-n%C2%B2-233cb7d8c3d1">Why Bother About O(nlog⁡n) vs O(n²)?</a> was originally published in <a href="https://medium.com/quantrium-tech">Quantrium.ai</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PostgreSQL 17: VACUUM Overhaul and More]]></title>
            <link>https://medium.com/quantrium-tech/postgresql-17-vacuum-overhaul-and-more-886aa8d0c74a?source=rss----41710727e242---4</link>
            <guid isPermaLink="false">https://medium.com/p/886aa8d0c74a</guid>
            <category><![CDATA[database]]></category>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[postgresql-17]]></category>
            <dc:creator><![CDATA[Anidhya Bhatnagar]]></dc:creator>
            <pubDate>Sun, 03 Nov 2024 10:52:32 GMT</pubDate>
            <atom:updated>2024-11-03T10:52:32.888Z</atom:updated>
            <content:encoded><![CDATA[<h4>Quantrium Insights</h4><h4>Deep dive into VACUUM revamp and key enhancements</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zqOJPRNnHXQjZwCMPJcW4A.jpeg" /><figcaption>PostgreSQL 17 — A deep dive into key enhancements</figcaption></figure><p>On September 26, 2024, PostgreSQL 17 got released with host of new features and improvements. This latest version continues to solidify PostgreSQL’s position as a leading open-source database management system. Let’s straight dive into the significant enhancements to the VACUUM process and other key areas.</p><h3>VACUUM Improvements</h3><p>In PostgreSQL 17, the most notable upgrade is the overhaul of the VACUUM process — the process which is critical for maintaining database health and performance. Wait! does that mean there is a significant improvement in performance? Let’s find out!</p><h4>TidStore — Dramatic Reduction in Memory Consumption</h4><p>In PostgreSQL 17 a new internal memory structure is introduced for VACUUM which dramatically reduces the memory consumption. This new system called <strong>TidStore</strong> has replaced the previous array-based approach, which results in:</p><ul><li>Up to 20x reduction in memory usage during VACUUM operations</li><li>Elimination of the previous 1GB memory usage limit for vacuuming tables</li><li>Improved overall vacuuming performance</li></ul><h4>Enhanced Monitoring</h4><p>In PostgreSQL 17 new columns are added to the pg_stat_progress_vacuum system view which provides better insights to the VACUUM process:</p><ul><li>dead_tuple_bytes: Shows the amount of space occupied by dead tuples</li><li>num_dead_item_ids: Replaces the previous num_dead_tuples column</li></ul><p>With these updates, the database administrators will be able to track the progress and efficiency of VACUUM operations more accurately.</p><h4>Faster Index Cleanup</h4><p>Index cleanup process removes dead index entries from indexes during VACUUM operations. In the new version, the speed of index cleanup during VACUUM got a significant improvement by changing the mechanism for removing dead tuples, now it uses the TidStore to collect dead tuples from the heap and clean up the index more efficiently.</p><p><em>Cleaning indexes can be resource-intensive task, especially for tables with many or large indexes.</em></p><h3>Other Significant Upgrades</h3><p>While the VACUUM improvements are substantial and impressive, the PostgreSQL 17 offers several other key enhancements:</p><h4>JSON Capabilities</h4><p>This one is my favorite, PostgreSQL 17 expands its JSON support with new features that align with the SQL/JSON standard:</p><ul><li>Introduction of the JSON_TABLE() function, which converts JSON data into a table representation</li><li>New JSON constructors and query functions like JSON_EXISTS(), JSON_QUERY(), and JSON_VALUE()</li></ul><p>In the current technology landscape, the JSON is the defacto widely used standard data format, these additions make working with JSON data in PostgreSQL more flexible and powerful, bridging the gap between relational and document-based data models.</p><h4>Performance Improvements</h4><p>In this release, several performance enhancements have been implemented:</p><ul><li>Improved I/O performance with a new streaming I/O interface, benefiting sequential scans and ANALYZE operations</li><li>Better handling of IN clauses with B-tree indexes, leading to faster query execution</li><li>Optimizations for IS NULL and IS NOT NULL clauses, reducing unnecessary evaluations</li></ul><h4>Logical Replication Enhancements</h4><p>In PostgreSQL Logical Replication refers to a method of replicating data objects and their changes based on the replication identity (usually a primary key) of the objects. PostgreSQL 17 introduced following improvements to logical replication:</p><ul><li>Failover control for high availability environments</li><li>Preservation of replication slots during major version upgrades (from version 17 onwards)</li><li>Introduction of pg_createsubscriber, a utility for creating logical replicas from physical standbys</li></ul><h4>Incremental Backup Support</h4><p>The most awaited significant addition is the support for incremental backups:</p><ul><li>New --incremental option in pg_basebackup for creating incremental backups</li><li>Introduction of pg_combinebackup for manipulating base and incremental backups</li></ul><p><em>This feature is particularly valuable for large databases where full backups are time-consuming and resource-intensive.</em></p><h4>MERGE Command Enhancements</h4><p>The MERGE command which was introduced in PostgreSQL 15, now receives further improvements:</p><ul><li>Addition of the RETURNING clause, allowing retrieval of modified rows</li><li>Support for updating views using the MERGE command</li></ul><h3>Summary</h3><p>PostgreSQL 17 brings substantial improvements across various areas, with noteworthy VACUUM enhancements. These upgrades collectively contribute to better performance, increased flexibility, and improved manageability of PostgreSQL databases. As organizations continue to deal with growing data volumes and complex workloads, these enhancements make PostgreSQL 17 an even more attractive option for enterprise database needs.</p><blockquote>This is not an exhaustive list of enhancements, there are various other significant improvements in SQL, Security, Storage, etc. you can take a look at complete list <a href="https://www.postgresql.org/docs/17/release-17.html">here</a> and the following references.</blockquote><h4>References:</h4><ul><li><a href="https://www.alibabacloud.com/blog/new-features-you-should-not-miss-in-apsaradb-rds-for-postgresql-17_601679">https://www.alibabacloud.com/blog/new-features-you-should-not-miss-in-apsaradb-rds-for-postgresql-17_601679</a></li><li><a href="https://www.postgresql.org/about/news/postgresql-17-released-2936/">https://www.postgresql.org/about/news/postgresql-17-released-2936/</a></li><li><a href="https://andyatkinson.com/postgresql-17-json-table-merge-returning-updatable-views">https://andyatkinson.com/postgresql-17-json-table-merge-returning-updatable-views</a></li><li><a href="https://www.postgresql.org/docs/current/release-17.html">https://www.postgresql.org/docs/current/release-17.html</a></li><li><a href="https://www.postgresql.org/about/news/postgresql-17-beta-1-released-2865/">https://www.postgresql.org/about/news/postgresql-17-beta-1-released-2865/</a></li><li><a href="https://www.postgresql.fastware.com/blog/postgresql-17-and-trends-and-innovations-to-watch">https://www.postgresql.fastware.com/blog/postgresql-17-and-trends-and-innovations-to-watch</a></li><li><a href="https://www.enterprisedb.com/blog/exploring-postgresql-17-new-features-enhancements">https://www.enterprisedb.com/blog/exploring-postgresql-17-new-features-enhancements</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=886aa8d0c74a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/quantrium-tech/postgresql-17-vacuum-overhaul-and-more-886aa8d0c74a">PostgreSQL 17: VACUUM Overhaul and More</a> was originally published in <a href="https://medium.com/quantrium-tech">Quantrium.ai</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Demystifying Python’s Garbage Collector: Cleaning Up the Mess]]></title>
            <link>https://medium.com/quantrium-tech/demystifying-pythons-garbage-collector-cleaning-up-the-mess-767662076ff5?source=rss----41710727e242---4</link>
            <guid isPermaLink="false">https://medium.com/p/767662076ff5</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[optimization]]></category>
            <category><![CDATA[garbage-collection]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[garbage-collector]]></category>
            <dc:creator><![CDATA[Anidhya Bhatnagar]]></dc:creator>
            <pubDate>Sat, 21 Oct 2023 13:44:29 GMT</pubDate>
            <atom:updated>2023-10-21T13:44:29.833Z</atom:updated>
            <content:encoded><![CDATA[<h4>QUANTRIUM DEEP DIVE</h4><h4>A Closer Look at the Garbage Collector</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lfvxhNVLDij15ZE7qN70-w.jpeg" /></figure><h3>Abstract</h3><p>This article explores Python’s Garbage Collector (GC), a key feature for automated memory management. It discusses the GC’s design principles, including reference counting and its role in handling cyclic references. It also explores the Generational GC approach, which optimizes memory management by categorizing objects into generations based on their lifespan. Finally, it highlights the importance of GC optimization in real-world applications with frequent object generation and disposal, and shows how it can improve memory management and reduce performance overhead.</p><h3>Introduction</h3><p>Python, a popular programming language known for its simplicity and flexibility, offers a significant advantage: <strong><em>automatic memory management</em></strong>.</p><blockquote>Garbage collection is a technique for automatic memory management. It tracks objects in memory and deallocates them when they are no longer needed. This frees up memory for other programs to use and prevents memory leaks.</blockquote><p>Python’s garbage collector (GC) is important because it frees programmers from having to manually manage memory. This article will explore how the GC works and its role in memory management.</p><h3>What is Python’s Garbage Collector?</h3><p>In Python, the Garbage Collector is a built-in feature with it’s primary role to identify and remove objects that are no longer referenced and freeing up memory for other data. This process helps prevent memory leaks and keeps Python applications running efficiently.</p><h3>Garbage Collector Design</h3><p>Python uses reference counting to track how many references an object has. When the reference count reaches zero, the object is deallocated. This scheme covers most cases, but it doesn’t handle reference cycles.</p><blockquote>Cyclic reference cycles are situations where objects reference each other, preventing reference counts from reaching zero.</blockquote><p>For instance, consider a container object, container, holding a reference to itself. Even when you remove your reference to it, the reference count never reaches zero due to its internal reference.</p><p>Python’s garbage collector handles reference cycles by using a <em>cyclic garbage collector</em>. A cyclic garbage collector is a type of garbage collector that can detect and break reference cycles.</p><h3>Memory Layout and Object Structure</h3><p>Following is the representation of the normal C structure which supports a regular Python object:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3W-L3DZgDHFTXjdlZIVSkg.jpeg" /><figcaption>Python Garbage Collector: Object Memory Regular Layout</figcaption></figure><p>Memory layout in Python is altered to accommodate garbage collection. Two extra fields are added to the memory layout of objects: _gc_next and _gc_prev.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lddvHPHjP5sBRnAipqJCKw.jpeg" /><figcaption>Python Garbage Collector: Object Memory Altered Layout</figcaption></figure><p>These fields are used to maintain doubly linked lists of all objects tracked by the garbage collector. These lists partition objects into generations and support efficient operations for moving, adding, and removing objects during collection.</p><h3>The Reference Counting Approach</h3><p>The fundamental mechanism behind Python’s GC is reference counting. Every Python object has an associated reference count. When an object’s reference count drops to zero, it means there are no references to that object, making it eligible for removal.</p><p>Consider this example:</p><pre>a = [1, 2, 3]<br>b = a</pre><p>In this case, both a and b reference the same list. If we assign a new value to a or b, the reference count decreases by 1. When both a and b are reassigned to different values, the reference count drops to zero, and the list can be removed by the GC.</p><h3>The Cyclic Reference Problem</h3><p>While reference counting is effective for most situations, it has limitations, particularly with circular references. Circular references occur when two or more objects reference each other, preventing their reference counts from dropping to zero.</p><p>For instance:</p><pre>python<br>class Node:<br> def __init__(self):<br> self.next = None<br><br>node1 = Node()<br>node2 = Node()<br><br>node1.next = node2<br>node2.next = node1</pre><p>In this example, node1 and node2 reference each other, and their reference counts never reach zero. This is where Python’s Garbage Collector comes into play.</p><h3>The Generational GC Approach</h3><p>To address the cyclic reference problem, Python utilizes a generational GC approach. It is one of the algorithm which used to optimize memory management. In this approach, objects are divided into three generations: Young, Middle-Aged, and Old.</p><ul><li>Young objects are newly created and are considered short-lived.</li><li>Middle-Aged objects have survived a few Garbage Collection cycles.</li><li>Old objects are long-lived and have survived multiple GC cycles.</li></ul><p>The GC gives more attention to Young objects since they are likely to become unreachable sooner. As objects survive more GC cycles, they are promoted to older generations.</p><p>Let’s take a deeper dive into Generational GC approach:</p><h4>The Generational Hypothesis</h4><p>The generational GC approach is based on the generational hypothesis, which assumes that most objects die young. In other words, newly created objects are more likely to become garbage soon, while objects that have survived multiple garbage collection cycles are more likely to remain in use for a longer time.</p><h4>Generational Segregation</h4><p>In Python, memory is divided into multiple generations, typically three: Generation 0 (young), Generation 1 (middle-aged) and Generation 2(old). Objects start in Generation 0, and if they survive a garbage collection cycle, they are promoted to Generation 1 and when the same object survive next garbage collection cycle, it is promoted to Generation 2.</p><h4>Collection Frequency</h4><p>The garbage collector in Python is designed to collect Generation 0 more frequently than Generation 1 or Generation 2 because of the generational hypothesis. This reduces the overhead of collecting objects that are likely to become garbage shortly.</p><h4>Collection Algorithm</h4><p>Generational GC in Python uses two primary algorithms for collection:</p><ol><li><strong>Young Generation Collection:</strong> The collector frequently checks Generation 0 for objects that are no longer referenced. This is often done using techniques like reference counting or more sophisticated methods like the tri-color algorithm.</li><li><strong>Old Generation Collection:</strong> Generation 1 and Generation 2 are collected less frequently because older objects are assumed to have a longer lifespan. When a collection does occur in Generation 1 or Generation 2, it’s often more expensive as it involves traversing more objects.</li></ol><h4>Garbage Collector Modules</h4><p>Python provides modules like gc that allow you to interact with and configure the garbage collector. You can manually trigger a collection using gc.collect(), and you can adjust the collection thresholds and other settings.</p><h4>Tuning and Optimization</h4><p>Python’s generational garbage collection can be tuned and optimized for specific applications. You can adjust the collection frequency and thresholds using the gc module, but you should be cautious and only do this when necessary.</p><p>To determine the appropriate timing for execution, the collector maintains a record of object allocations and deallocations since the previous collection. When the difference between allocations and deallocations surpasses the predefined threshold_0 value, the garbage collection process is triggered.</p><p>Initially, the collector focuses on inspecting objects in Generation 0. However, if Generation 0 has undergone more examinations than Generation 1 since the last check, the collector extends its inspection to include Generation 1. These configurable thresholds are accessible for review and adjustment via the gc.get_threshold() function.</p><pre>&gt;&gt;&gt; import gc<br>&gt;&gt;&gt; gc.get_threshold()<br>(700, 10, 10)</pre><p>The Generation 2 is bit more complex. Unlike the customizable thresholds for Generation 0 and Generation 1, the garbage collector (GC) will only initiate a full collection of the oldest generation when a specific condition is met:</p><blockquote>the ratio of pending long-lived objects to the total long-lived objects exceeds a fixed threshold (hard-set at 25%).</blockquote><p>This is because while partial collections (which target younger and mid-level generations) consistently inspect a roughly consistent number of objects based on the set thresholds, the cost of a full collection is directly related to the total count of long-lived objects, which can potentially be extremely high.</p><p>In practical terms, frequently performing full collections after every fixed number of object creations can severely degrade performance in scenarios where many long-lived objects are created and stored (e.g., constructing a substantial list of objects tracked by the GC can lead to quadratic performance issues instead of the expected linear performance).</p><p>Instead, using the mentioned ratio provides a more balanced approach:</p><blockquote>each full garbage collection becomes more expensive as the total object count increases, but the frequency of these expensive operations decreases, resulting in an overall performance that scales linearly with the number of objects (meaning that as the number of objects grows, the impact of each full garbage collection is lessened).</blockquote><h3>Manual Garbage Collection</h3><p>While Python’s GC system is automatic and efficient, developers can also manually trigger Garbage Collection using the gc module. This is useful in cases where memory needs to be managed more explicitly.</p><p>To manually run Garbage Collection, you can use the gc.collect() method. Here’s an example:</p><pre>import gc<br><br># …your code…<br><br>gc.collect() # Explicitly run Garbage Collection</pre><h3>A Real World Example of GC Optimization</h3><p>Let’s consider a web application that experiences high traffic and continuously generates short-lived objects, such as request and response objects, user sessions, and database query results. In such a scenario, frequent garbage collection can lead to performance overhead.</p><p>To optimize performance in this case, the GC configuration can be adjusted:</p><h4>Generational GC Configuration</h4><p>You can tune the generational GC approach to control how often it runs in different generations of objects. For example, you can increase the collection frequency of Generation 0 to collect short-lived objects more aggressively, reducing the overhead of checking and cleaning them. This ensures that the most commonly generated objects are quickly collected, minimizing memory fragmentation.</p><h4>Threshold Adjustments</h4><p>You can adjust the garbage collection thresholds for both the number of allocations and the frequency of examinations between generations. For short-lived objects, you can lower these thresholds to trigger more frequent but quicker collections.</p><h4>Manual Collection</h4><p>If you know when certain objects are no longer needed, you can manually trigger the GC at the right time using the gc.collect() function. For example, you might want to run manual collection after processing a user&#39;s request and releasing associated resources.</p><h4>Disabling or Reducing GC</h4><p>In extreme cases, if your application can manage memory explicitly, you can temporarily disable or reduce the impact of the GC with the gc.disable() function. Use this with caution and only for specific, short-lived scenarios.</p><blockquote>You can configure the GC to manage the frequent creation and disposal of short-lived objects efficiently, reducing the chances of performance problems due to garbage collection.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=767662076ff5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/quantrium-tech/demystifying-pythons-garbage-collector-cleaning-up-the-mess-767662076ff5">Demystifying Python’s Garbage Collector: Cleaning Up the Mess</a> was originally published in <a href="https://medium.com/quantrium-tech">Quantrium.ai</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Automated spaCy Re-training]]></title>
            <link>https://medium.com/quantrium-tech/automated-spacy-re-training-f668056d0ecb?source=rss----41710727e242---4</link>
            <guid isPermaLink="false">https://medium.com/p/f668056d0ecb</guid>
            <category><![CDATA[naturallanguageprocessing]]></category>
            <category><![CDATA[automation-software]]></category>
            <category><![CDATA[ner]]></category>
            <category><![CDATA[spacy]]></category>
            <category><![CDATA[named-entity-recognition]]></category>
            <dc:creator><![CDATA[Priyanshu Sankhala]]></dc:creator>
            <pubDate>Sun, 17 Sep 2023 14:03:57 GMT</pubDate>
            <atom:updated>2023-09-17T14:03:57.076Z</atom:updated>
            <content:encoded><![CDATA[<h4>QUANTRIUM GUIDES</h4><h4>Save time and boost accuracy with automated spaCy re-training</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eCqLmryf4bwrAfkgCgn4sA.png" /></figure><h3>Introduction</h3><p>Spacy is a popular NLP library that can be used for a variety of tasks, such as Named Entity Recognition (NER), Text Classification, and Sentiment Analysis. spaCy has exceptional NER capabilities which is a crucial component in Natural Language Processing (NLP) applications. It enables the identification and categorization of entities within text, such as names of people, organizations, locations, dates, and more.</p><p>When you train the NER models on a specific dataset, they excel. However, as time goes on, the data landscape evolves. New names, entities, and patterns emerge, making it essential to adapt your NER models to stay effective.</p><p>We delved deeper into spaCy’s capabilities and discovered an exciting breakthrough: automating the re-training process. Let’s see — how?</p><h3>Why Automated?</h3><p>Let’s consider that you are working on a project where you’re using NER to extract information from user reviews for a restaurant recommendation system. You will see that the names of new restaurants, local businesses, and even emerging food trends constantly change. To keep up your model up-to-date manually can be time-consuming and error-prone.</p><p>Manually training and re-training NER models can be arduous, involving data preprocessing, entity annotation, and feature engineering. Additionally, it’s not scalable and requires efforts everytime the model is retrained. Automation streamlines this process and often yields better model performance.</p><p>The spaCy provide features that can be used to retrain the model and the process can be automated. The benefits include:</p><ul><li><strong>Increased efficiency:</strong> It can save a significant amount of time and efforts, especially, for large datasets or datasets that are constantly changing.</li><li><strong>Improved accuracy:</strong> It can improve the accuracy of spaCy models because the models are constantly being updated with new data.</li><li><strong>Reduced manual intervention: </strong>Automation can reduce the need for manual intervention and frees up time for the ML Engineers to focus on other tasks.</li></ul><h3>The Automated Process — A Closer Look</h3><p>Automated updation of your NER model periodically with new data, enables it to adapt to the evolving language and entities in your domain. Here’s how it works:</p><h4>Data Collection</h4><p>Setup a pipeline which continuously gather new text data that represents the domain or context in which your NER model operates. This data should include examples of entities you want your model to recognize.</p><h4>Data Preprocessing</h4><p>Add a data preprocessing stage to your pipeline where the new data is prepared by cleaning and formatting it, ensuring it’s in a suitable format for NER training. This step will require manual review or annotation of the training data. Once prepared, combine your existing training data with the new data, creating a comprehensive dataset for retraining in .spacy format.</p><h4>Initiating Automated Retraining</h4><p>Once the training data is generated, for automatic retraining we can initiate the update functions feature in spacy as soon as the files are updated or added. It leverages pre-defined hyperparameters and training configurations to optimize the model to new patterns and changes in the input data, leading to a upgraded model with improved performance.</p><h4>Performance Monitoring and Model Selection</h4><p>After retraining, add an stage to your pipeline which does the constant monitoring of the model’s performance using metrics like precision, recall, and F1-score. And if the model’s performance is unsatisfactory, the then it should trigger retraining with a different set of hyperparameters or you may need to switch to a different architecture to enhance the model’s capabilities.</p><h3>Use Cases for Automated Spacy Re-training</h3><p>At Quantrium, we have used custom, trained from scratch spaCy model on our specific classes and data to automate various processes with document intelligence in Finance and Insurance Industry. For example, extraction and identification of various keys and values in:</p><ul><li>Paystubs or Salary Slips</li><li>Financial Statements (such as Balance Sheet, Profit &amp; Loss and Cash Flow statements)</li><li>Tax Documents (such as Income Tax Returns, Form 26AS, W-2 and 1099 Forms)</li><li>Bank Statements and Passbooks</li><li>Insurance Claim Documents (Insurer, Insured Person, Amount, Charges, Penalty, X12 Codes, etc.)</li></ul><p>Automated retraining with spaCy is a powerful strategy for maintaining the accuracy and relevance of your NER models. In the ever-evolving world of text data, staying up-to-date is not a luxury but a necessity. Embrace automation and watch your NER models shine in accuracy and adaptability, providing better insights and performance in your NLP applications.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f668056d0ecb" width="1" height="1" alt=""><hr><p><a href="https://medium.com/quantrium-tech/automated-spacy-re-training-f668056d0ecb">Automated spaCy Re-training</a> was originally published in <a href="https://medium.com/quantrium-tech">Quantrium.ai</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Improving PPOCR Recognition Time in Python]]></title>
            <link>https://medium.com/quantrium-tech/optimizing-ppocr-recognition-time-in-python-59f9f6206926?source=rss----41710727e242---4</link>
            <guid isPermaLink="false">https://medium.com/p/59f9f6206926</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[computer-vision]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Bhargav Sridhar]]></dc:creator>
            <pubDate>Mon, 29 Aug 2022 12:07:57 GMT</pubDate>
            <atom:updated>2025-01-21T14:40:43.441Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://medium.com/quantrium-tech">QUANTRIUM GUIDES</a></h4><h4>Utilizing multiprocessing and Colab GPU for PPOCR recognition</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*-ucve-FHHwWExSyLUqe0fQ.png" /></figure><h3>Introduction</h3><p>Over the last few months, I have been writing some articles on <strong>Optical Character Recognition (OCR)</strong> using Python. But, one of the challenges faced even today with OCR in Python is the recognition time taken by some OCR models. We can find some of the OCR models (such as easyOCR, docTROCR, etc.) performing very fast when implemented with a <strong>Graphical Processing Unit (GPU)</strong>.</p><p>If you had gone through my article on integrating multiple OCR models (which can be found <a href="https://medium.com/quantrium-tech/integrating-multiple-ocr-models-to-perform-detection-and-recognition-separately-using-python-f2c73743e1e0">here</a>), you would have noticed recognition models such as PPOCR, pytesseract, etc., which perform recognition coordinate-wise. A major drawback with these recognition models is that, since they recognize the text coordinate-wise, their recognition time is much higher than recognition models like easyOCR, which takes the list of all coordinates and images at a time to perform recognition.</p><p>Also, if you try performing recognition using PPOCR using a Google Colab GPU directly, you may observe that the GPU is not consumed at all by the recognition model and a warning pops out in some time stating that the GPU is not consumed. Also, GPU availability in such platforms is very limited. However, there is a procedure to perform PPOCR recognition by consuming the Colab GPU, which I have explained in the upcoming sections. PPOCR documentation can be found <a href="https://pypi.org/project/paddleocr/">here</a>.</p><p>I have also explained how PPOCR recognition can be done using <strong>multiprocessing</strong>, which is a basic solution with which one can start and try improving the process even further.</p><p>We will test the recognition using all the methods with the following image (in fact, I used the same image in my docTROCR article. The article can be found in this <a href="https://medium.com/quantrium-tech/text-extraction-using-doctr-ocr-471e417764d5">link</a>):-</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/621/1*dggnQA_B-mJTP8I-abv6ag.png" /><figcaption>Test image — PPOCR recognition</figcaption></figure><h3>Implementing PPOCR recognition with ordinary CPU</h3><p>For comparison purposes, we will first check and record the time taken by ordinary CPU for PPOCR recognition.</p><p>The following installations should be made:</p><pre>!pip install &quot;paddleocr&gt;=2.0.1&quot;<br>!pip install paddlepaddle</pre><p>After the above installations, the following imports and definitions should be made:</p><pre>from paddleocr import PaddleOCR<br>ocr = PaddleOCR(lang=&#39;en&#39;)</pre><p>To obtain the detection coordinates, I have explained the complete procedure in the articles whose links I have shared above. Now using the text_coordinates, we will perform PPOCR recognition:</p><pre>import cv2<br>import time<br>img_path = &lt;&gt; #define your image path here<br>start = time.time()<br>for coord in text_coordinates:<br>    x_min, y_min, x_max, y_max = coord[0], coord[2], \<br>                                 coord[1], coord[3]<br>    if x_min &gt;= 0 and x_max &gt;= 0 and \<br>       y_min &gt;= 0 and y_max &gt;= 0:<br>        im2 =cv2.imread(img_path)<br>        cropped = im2[y_min: y_max, x_min: x_max]<br>        text = ocr.ocr(cropped, det=False, cls=False)<br>end = time.time()<br>print(f&quot;Time taken with ordinary CPU: {end-start} sec&quot;)</pre><p>The following output was obtained in my case:</p><pre>Time taken with ordinary CPU: 11.89705514907837 sec</pre><h3>PPOCR recognition with multiprocessing</h3><p>The installations for this are the same as the previous one. The following additional imports need to be made:</p><pre>from multiprocessing import Pool<br>from functools import partial<br>pool = Pool(processes=8)</pre><p>More about multiprocessing can be understood from its documentation which can be found <a href="https://docs.python.org/3/library/multiprocessing.html">here</a>.</p><p>Now, we will implement the recognition in a slightly different way:</p><pre>def perform_ocr_recognition(coord, im2):<br>    text = &quot;&quot;<br>    x_min, y_min, x_max, y_max = coord[0], coord[2], \ <br>                                 coord[1], coord[3]<br>    <br>    if x_min &gt;= 0 and x_max &gt;= 0 and \<br>       y_min &gt;= 0 and y_max &gt;= 0:<br>        cropped = im2[y_min: y_max, x_min: x_max]<br>        text = ocr.ocr(cropped, det=False, cls=False)<br>        return {str(coord): text[0][0]}<br>img = cv2.imread(img_path)<br>start = time.time()<br>text_output = pool.map(partial(perform_ocr_recognition, im2=img),<br>                  text_coordinates<br>              )<br>end = time.time()<br>print(f&quot;Time taken with multiprocessing: {end-start} sec&quot;)</pre><p>The <strong>partial</strong> module is used to fix an argument throughout the process (especially in a loop). In our case, the image array would remain the same for the entire recognition process. That is why I declare it as a fixed argument and loop through the text coordinates outside the partial method.</p><p>The <strong>map</strong> function is used to automatically append the output of each iteration to a list. You can obtain the coordinate and text as dictionary objects and this can be checked by printing out the <em>text_output</em> variable.</p><p>The following output was obtained in my case (and it will vary for different users and systems):-</p><pre>Time taken with multiprocessing: 7.432933568954468 sec</pre><h3>PPOCR recognition with Colab GPU</h3><p>The following installations have to be made:-</p><pre>!pip install &quot;paddleocr&gt;=2.0.1&quot;<br>!pip install paddlepaddle<br>!python -m pip install paddlepaddle-gpu #or python3</pre><p>The <strong>paddlepaddle-gpu</strong> can be used to implement PPOCR by utilizing GPU (especially when you have GPU-CUDA set up in your platform). More information on installing this on your system can be found in the <a href="https://pypi.org/project/paddlepaddle/">paddlepaddle documentation</a>.</p><p>The imports and implementation are the same as that of ordinary CPU:-</p><pre>from paddleocr import PaddleOCR<br>import cv2<br>import time<br>ocr = PaddleOCR(lang=&#39;en&#39;)<br>img_path = &lt;&gt; #define your image path here<br>start = time.time()<br>for coord in text_coordinates:<br>    x_min, y_min, x_max, y_max = coord[0], coord[2], \<br>                                 coord[1], coord[3]<br>    if x_min &gt;= 0 and x_max &gt;= 0 and \<br>       y_min &gt;= 0 and y_max &gt;= 0:<br>        im2 =cv2.imread(img_path)<br>        cropped = im2[y_min: y_max, x_min: x_max]<br>        text = ocr.ocr(cropped, det=False, cls=False)<br>end = time.time()<br>print(f&quot;Time taken with GPU: {end-start} sec&quot;)</pre><p>The following output was obtained in my case:-</p><pre>Time taken with GPU: 0.5593817234039307 sec</pre><p>Now let us try to understand the observations in the final section.</p><h3>Observations and Conclusion</h3><p>From the above experiments, the following observations are quite clear:-</p><ul><li>Ordinary CPU has taken more time when compared to the other methods. This is due to the iteration of each coordinate and a single process is utilized to recognize all coordinates in order;</li><li>With multiprocessing, PPOCR recognition has executed faster than that of ordinary CPU, even though the time taken is still on the higher side. This is because multiple coordinates are recognized parallelly with the help of multiple processes utilized at the same time. But when testing with a large dataset, multiprocessing could save a lot of time than ordinary CPU execution;</li><li>As expected, recognition with GPU was the quickest, but implementation was a bit different when compared to the other OCR tools;</li></ul><p>Thus, I hope I have given you an idea of improving the PPOCR recognition process. In most cases, GPU availability would be low and hence multiprocessing may serve as a good starting point to increase PPOCR recognition speed. However with a GPU availability, one could install the paddlepaddle-gpu which serves specifically for the PPOCR model and optimize the time as shown in the previous sections. I would be more than willing to acknowledge questions and clarifications related to the topic which can be posted through the comments. Hope you have found this article useful. Thanks!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=59f9f6206926" width="1" height="1" alt=""><hr><p><a href="https://medium.com/quantrium-tech/optimizing-ppocr-recognition-time-in-python-59f9f6206926">Improving PPOCR Recognition Time in Python</a> was originally published in <a href="https://medium.com/quantrium-tech">Quantrium.ai</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>