<?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"><channel><title><![CDATA[Mukund Murali's blog]]></title><description><![CDATA[Mukund Murali's blog]]></description><link>https://blog.mukundmurali.in</link><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 20:55:34 GMT</lastBuildDate><atom:link href="https://blog.mukundmurali.in/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><atom:link rel="first" href="https://blog.mukundmurali.in/rss.xml"/><item><title><![CDATA[How to Build a Private, Agentic Workflow with Claude  Code and Ollama]]></title><description><![CDATA[<h1>Introduction: Bridging Cloud Power and Local Control</h1>
<p>In the hyper-accelerated world of AI-assisted engineering, developers face a critical dilemma: <strong>intelligence vs. privacy</strong>. How do you leverage the elite reasoning of flagship models like Claude without surrendering your proprietary source code to the cloud?</p>
<p>This guide resolves that tension by building a <strong>Hybrid AI Workflow</strong>. We are merging two powerhouse ecosystems:</p>
<ol>
<li><strong>Claude Code:</strong> An agentic CLI that provides deep reasoning, multi-step planning, and autonomous file manipulation.</li>
<li><strong>Ollama:</strong> A local model engine that ensures your most sensitive code never leaves your workstation.</li>
</ol>
<p>By using Claude for high-level architectural guidance and Ollama for local execution and private validation, we create a development loop that is both immensely powerful and completely secure. This post details the exact setup to make this synergy work seamlessly.</p>
<h1>Understanding Claude Code</h1>
<p>![[Pasted image 20260412070456.png]]</p>
<p>To make the concept easier to grasp, think of this setup as a car. In this analogy, <strong>Claude Code is the cars body and dashboard</strong>, while the <strong>LLM is the engine</strong>.</p>
<p>The "body" (Claude Code) provides the interface, the tools, and the logic for interacting with your files and terminal. But without an "engine" (the LLM) to provide the reasoning power, the car won't move. You can swap the engine depending on your needs:</p>
<ul>
<li><strong>Local LLMs (via Ollama):</strong> Like a custom-built engine in your own garage. It gives you complete control and privacy, running entirely on your local hardware.</li>
<li><strong>Anthropics Native Models:</strong> Like a high-performance engine from a professional racing team. You access it via API (Claude 3.5/4.x models), offering peak intelligence but requiring an external connection.</li>
<li><strong>Third-Party Hosts:</strong> Like a leased engine from a service provider, offering flexibility across different providers.</li>
</ul>
<p>What makes Claude Code unique is its <strong>agentic workflow</strong>. It doesn't just answer questions; it can "see" your codebase, execute commands, and iterate on code until a task is complete. By pairing this sophisticated "body" with a local "engine" via Ollama, you get the best of both worlds: high-level autonomy with local privacy.</p>
<h1>Strategic Tradeoffs: Finding Your Ideal AI Workflow</h1>
<p>Before diving into the setup, it is crucial to understand that integrating these two systems involves several architectural tradeoffs. No single solution is perfect; the right choice depends entirely on your project's constraints.</p>
<h3>🛡 1. Data Privacy and Security (The Biggest Tradeoff)</h3>
<ul>
<li><strong>Cloud LLMs (e.g., Claude):</strong> Offer best-in-class performance and massive model sizes, but your prompts and context are processed on a third-party server. This is unsuitable for handling highly sensitive, regulated, or proprietary data.</li>
<li><strong>Local LLMs (via Ollama):</strong> Offer <strong>maximum privacy</strong>. Since the model runs entirely on your machine, data never leaves your local environment. This is mandatory for compliance (HIPAA, GDPR, etc.) or working with unreleased IP. However, the model performance ceiling is dictated by your hardware.</li>
</ul>
<h3>🛠 2. Tooling Depth and Integration Complexity</h3>
<ul>
<li><strong>Cloud LLMs (Claude Code):</strong> Are designed to be 'agentic' within a structured toolset. They are excellent at understanding multi-step development tasks, calling external APIs, and managing complex project logic because the tool definitions are part of their prompt context.</li>
<li><strong>Local LLMs (Ollama):</strong> While Ollama supports running various models, making them reliably execute complex, multi-step, system-level tooling (like a full compiler/interpreter chain) often requires more explicit, prompt-level instruction engineering or building custom wrappers, as they don't inherently possess the same high-level agentic framework that Claude's tool-use system provides out-of-the-box.</li>
</ul>
<h3>🚀 3. Model Performance vs. Resource Requirements</h3>
<ul>
<li><strong>Cloud LLMs:</strong> Access to the absolute cutting edge (e.g., Opus 4.6) with minimal local overhead.</li>
<li><strong>Local LLMs:</strong> The quality is gated by the model size and your hardware (RAM, GPU VRAM). You might have to settle for smaller, more efficient models (like CodeLlama or Phi-3) that still perform well enough for the task, even if they don't match the flagship cloud models' peak capability.</li>
</ul>
<p><strong>Summary:</strong> 
 * <strong>1. Local LLM (Ollama):</strong>
   * <strong>The Pro:</strong> Absolute data privacy and zero usage costs.
   * <strong>The Con:</strong> Performance is strictly limited by your local hardware (GPU/RAM) and
    the size of the model your machine can handle.</p>
<p> * <strong>2. Third-Party Hosting APIs (e.g., OpenRouter, Groq):</strong>
   * <strong>The Pro:</strong> Generally more cost-efficient than native APIs while offering high speeds.
   * <strong>The Con:</strong> While providers offer privacy terms, data still leaves your network to
    an external server. Performance can be inconsistent depending on the provider's
    current traffic and hardware.</p>
<p> * <strong>3. Native LLM APIs (Anthropic/Claude):</strong>
   * <strong>The Pro:</strong> The "Gold Standard." You get the highest reasoning capabilities, the
    fastest response times, and the largest context windows available.
   * <strong>The Con:</strong> This is the most expensive option and carries the highest data privacy
    risk, as your prompts are processed directly on the vendor's environment.</p>
<h3>Step 1: Install Ollama (The Local Engine)</h3>
<p>Ollama is an indispensable tool that simplifies running and managing open-source LLMs locally. It abstracts away the complexity of running various models (Llama, Mistral, etc.) into a single, easy-to-use command-line interface.</p>
<p><strong>Prerequisites:</strong> Ollama is required to serve as the local backend for models we want to use in conjunction with Claude Code.</p>
<p>To install Ollama, run the official script in your terminal:</p>
<pre><code class="language-bash">curl -fsSL https://ollama.com/install.sh | sh
</code></pre>
<p>This command downloads and executes the installer, setting up the necessary services and making the <code>ollama</code> command available in your shell.</p>
<h1>Increase the context memory size</h1>
<p>If you are using a Modelfile, ensure you set the <code>num_ctx</code> parameter to at least <code>32768</code> (32k) or higher, depending on your hardware VRAM. This ensures that when Claude Code queries your local model, it has enough room to "see" the entire relevant code block in a single pass.</p>
<p><strong>How to optimise for code:</strong></p>
<p>![[Pasted image 20260411215635.png]]</p>
<p>When working with code, "Context is King." A standard 2,048 or 4,096 token window is rarely enough to hold a modern projects file structure, let alone the contents of multiple source files and their dependencies. </p>
<p>To prevent your local engine from "forgetting" the beginning of your file as it reads the end, you must manually increase the context window in Ollama. This allows the model to maintain a larger "active memory" of your codebase.</p>
<h1>Install Claude Code</h1>
<pre><code>curl -fsSL https://claude.ai/install.sh | bash
</code></pre>
<pre><code class="language-ad-note">Post downloading Claude Code open it with Ollama rather than opening in directly from the termial using the below command. 
</code></pre>
<h1>Open Claude code using Ollama :</h1>
<pre><code>ollama launch claude
</code></pre>
<p>![[Pasted image 20260411220132.png]]</p>
<h1>Alternatives for Claude Code</h1>
<p>Here are the best alternatives in 2026, grouped by type. Many developers mix tools (e.g., an IDE for daily work + a terminal agent for heavy lifting). Top contenders often include Cursor, OpenAI's Codex (or Codex CLI), GitHub Copilot, and open-source options like Cline or Aider, pi agent etc.</p>
<table>
<thead>
<tr>
<th>Tool</th>
<th>Type</th>
<th>Pricing (approx.)</th>
<th>Primary Strength</th>
</tr>
</thead>
<tbody><tr>
<td>Claude Code</td>
<td>Terminal CLI Agent</td>
<td>$20/mo (Pro)</td>
<td>Deep reasoning, complex multi-file tasks, high autonomy</td>
</tr>
<tr>
<td>Pi (Coding Agent)</td>
<td>Open-source Terminal CLI</td>
<td>Free (bring your own keys)</td>
<td>Minimal &amp; token-efficient, highly customizable via extensions/SDK</td>
</tr>
<tr>
<td>Codex CLI</td>
<td>Terminal CLI Agent</td>
<td>$20/mo (via OpenAI subscription)</td>
<td>Speed &amp; efficiency, strong Terminal-Bench performance</td>
</tr>
<tr>
<td>Cursor</td>
<td>AI-Native IDE</td>
<td>Free / $20/mo Pro</td>
<td>Polished daily workflow, autocomplete + agent mode</td>
</tr>
<tr>
<td>Aider</td>
<td>Open-source Terminal Tool</td>
<td>Free (bring your own key)</td>
<td>Excellent git-native workflow, lightweight</td>
</tr>
<tr>
<td>Cline / Continue.dev</td>
<td>Open-source IDE/CLI Ext.</td>
<td>Free (bring your own key)</td>
<td>Highly customizable, supports local/cheap models</td>
</tr>
<tr>
<td>Gemini CLI</td>
<td>Terminal CLI Agent</td>
<td>Generous free / paid tiers</td>
<td>Large context, cost-effective for big codebases</td>
</tr>
</tbody></table>
<h1>Conclusion</h1>
<p>The synergy between Claude Code and Ollama represents a significant shift in AI-assisted development. We are moving away from simple "chat with your code" interfaces toward autonomous, local-first development loops.</p>
<p>By following this setup, youve unlocked a workflow that respects your data privacy without sacrificing the sophisticated reasoning of an agentic CLI. Whether you choose to use local models for sensitive internal tools or switch to cloud models for complex architectural refactors, you now have the ultimate hybrid development environment.</p>
<p>As local models continue to close the gap with their cloud counterparts, this local-first approach will likely become the standard for professional software engineering. Happy coding!</p>
]]></description><link>https://blog.mukundmurali.in/how-to-build-a-private-agentic-workflow-with-claude-code-and-ollama</link><guid isPermaLink="true">https://blog.mukundmurali.in/how-to-build-a-private-agentic-workflow-with-claude-code-and-ollama</guid><category><![CDATA[claude-code]]></category><category><![CDATA[agentic AI]]></category><category><![CDATA[ollama]]></category><category><![CDATA[terminal]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Mukund Murali]]></dc:creator></item><item><title><![CDATA[🧠 Build a No-Code OCR App Using OCI Generative AI and Streamlit]]></title><description><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747195276283/b39d59c0-4a4b-4b41-b1d5-33ec53f65fce.png" alt class="image--center mx-auto" /></p>
<p>👋 Introduction If you're a developer, cloud architect, or AI enthusiast who liked <a target="_blank" href="https://github.com/Nutlope/llama-ocr">llama OCR</a>, this post is for you. In this tutorial, you'll build a simple, <strong>llama OCR</strong> (Optical Character Recognition)** web app that:</p>
<ul>
<li><p>Uses <strong>OCI Generative AIs Vision LLMs for meta</strong></p>
</li>
<li><p>Extracts structured text from images (like receipts, scanned forms)</p>
</li>
<li><p>Runs locally on your machine with <strong>Streamlit</strong></p>
</li>
<li><p>Doesnt require any front-end coding</p>
</li>
</ul>
<h2 id="heading-who-is-this-for">🎯 Who Is This For?</h2>
<p>This app is ideal for:</p>
<ul>
<li><p>Oracle Cloud (OCI) users exploring <strong>GenAI Vision models</strong></p>
</li>
<li><p>Developers who want to prototype <strong>document AI</strong> tools</p>
</li>
<li><p>Data teams that frequently handle scanned invoices, receipts, or forms</p>
</li>
<li><p>Anyone looking to integrate <strong>LLM + OCR</strong> in a no-code UI</p>
</li>
</ul>
<h2 id="heading-what-youll-build"> What You'll Build</h2>
<p>A web UI that allows you to:</p>
<ul>
<li><p>Upload an image (receipt, invoice, screenshot) in the application.</p>
</li>
<li><p>Get the extracted <strong>Markdown</strong> output from the image using LLM</p>
</li>
<li><p>View and copy the structured text</p>
</li>
</ul>
<h2 id="heading-why-oci-gen-ai-service">🏛 Why OCI Gen AI service?</h2>
<p>While there are many cloud providers offering Generative AI services, heres why <strong>Oracle Cloud Infrastructure (OCI)</strong> stands out for this project:</p>
<h3 id="heading-enterprise-grade-security">🔒 Enterprise-Grade Security</h3>
<p>Oracle offers built-in <strong>data residency, encryption, and compartment isolation</strong>, making it ideal for industries handling sensitive scanned documents like finance, healthcare, or government.</p>
<h3 id="heading-cost-effective-genai">💰 Cost-Effective GenAI</h3>
<p>OCIs <strong>flexible pricing</strong> and <strong>pay-as-you-go</strong> options for Generative AI inference make it more affordable than comparable solutions on other hyperscalers.</p>
<h3 id="heading-native-llm-support"> Native LLM Support</h3>
<p>OCI hosts <strong>open-source LLMs</strong> like <strong>Meta LLaMA 3</strong>, <strong>Mistral</strong>, and <strong>Command R</strong> directly in your region. This means <strong>lower latency</strong> and no external API keys or SaaS contracts needed.</p>
<h3 id="heading-full-stack-integration">🧱 Full Stack Integration</h3>
<p>From <strong>Object Storage</strong> to <strong>Data Science</strong>, <strong>Monitoring</strong>, and <strong>Vault</strong>, everything plugs in natively. You can integrate OCR output with downstream analytics, automation, or data pipelines with ease.</p>
<h3 id="heading-developer-friendly">🔧 Developer Friendly</h3>
<ul>
<li><p>One config file (~/.oci/config)</p>
</li>
<li><p>No API gateway hoops</p>
</li>
<li><p>Full Python SDK and CLI support</p>
</li>
<li><p>IAM-based access control If youre already on OCI, this setup takes you from raw image to structured text in minutes.</p>
</li>
</ul>
<h2 id="heading-prerequisites">🛠 Prerequisites</h2>
<ul>
<li><p> ~<a target="_blank" href="https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/cliinstall.htm">OCI CLI configured</a>~ (~/.oci/config)</p>
</li>
<li><p> Access to <strong>OCI Generative AI Service</strong> in of the regions mentioned below</p>
</li>
<li><p> A Vision-capable model deployed (like meta.llama-3.2-90b-vision-instruct)</p>
</li>
<li><p> Python 3.8+</p>
</li>
<li><p> Install required Python packages</p>
</li>
</ul>
<h2 id="heading-regions-with-generative-ai">Regions with Generative AI</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Region Name</td><td>Location</td><td>Region Identifier</td><td>Region Key</td></tr>
</thead>
<tbody>
<tr>
<td>Brazil East (Sao Paulo)</td><td>Sao Paulo</td><td>sa-saopaulo-1</td><td>GRU</td></tr>
<tr>
<td>Germany Central (Frankfurt)</td><td>Frankfurt</td><td>eu-frankfurt-1</td><td>FRA</td></tr>
<tr>
<td>Japan Central (Osaka)</td><td>Osaka</td><td>ap-osaka-1</td><td>KIX</td></tr>
<tr>
<td>UAE East (Dubai)</td><td>Dubai</td><td>me-dubai-1</td><td>DXB</td></tr>
<tr>
<td>UK South (London)</td><td>London</td><td>uk-london-1</td><td>LHR</td></tr>
<tr>
<td>US Midwest (Chicago)</td><td>Chicago</td><td>us-chicago-1</td><td>ORD</td></tr>
</tbody>
</table>
</div><h2 id="heading-setting-up-a-virtual-environment-windows-amp-macoslinux">💻 Setting Up a Virtual Environment (Windows &amp; macOS/Linux)</h2>
<p>Creating a virtual environment helps isolate dependencies and ensures your Streamlit OCR app doesnt interfere with other Python projects on your system.</p>
<h3 id="heading-for-windows">For Windows:</h3>
<h4 id="heading-open-command-prompt-cmd-or-powershell">Open <strong>Command Prompt (cmd)</strong> or <strong>PowerShell</strong>:</h4>
<pre><code class="lang-python"><span class="hljs-comment">#Navigate to your project folder</span>
cd path\\to\\your\\project

<span class="hljs-comment">#Create a virtual environment</span>
python -m venv venv

<span class="hljs-comment">#Activate the virtual environment</span>
venv\\Scripts\\activate

<span class="hljs-comment">#Install dependencies</span>
pip install streamlit oci
</code></pre>
<h3 id="heading-for-macoslinux">For macOS/Linux:</h3>
<p>Open <strong>Terminal</strong>:</p>
<pre><code class="lang-python"><span class="hljs-comment">#Navigate to your project directory</span>
cd ~/path/to/your/project

<span class="hljs-comment">#Create a virtual environment</span>
python3 -m venv venv

<span class="hljs-comment"># Activate the virtual environment</span>
source venv/bin/activate

<span class="hljs-comment"># Install dependencies</span>
pip install streamlit oci
</code></pre>
<p>Once you're done, launch the app with:</p>
<pre><code class="lang-python">streamlit run ocr_vision_app.py
</code></pre>
<p>Find the full code in the github : <a target="_blank" href="https://github.com/mukundmurali-mm/llama-ocr-oci.git">mukundmurali-mm/llama-ocr-oci: Use llama OCR for extracting texts using OCI Gen AI services</a></p>
]]></description><link>https://blog.mukundmurali.in/build-a-no-code-ocr-app-using-oci-generative-ai-and-streamlit</link><guid isPermaLink="true">https://blog.mukundmurali.in/build-a-no-code-ocr-app-using-oci-generative-ai-and-streamlit</guid><category><![CDATA[AI]]></category><category><![CDATA[Meta]]></category><category><![CDATA[LLaMa]]></category><category><![CDATA[OCI]]></category><dc:creator><![CDATA[Mukund Murali]]></dc:creator></item><item><title><![CDATA[Unlocking AI Potential: The Model Context Protocol (MCP) Revolution]]></title><description><![CDATA[<h1 id="heading-what-is-mcp">What is MCP ?</h1>
<p>Model context protocol (MCP)</p>
<ul>
<li><p>It is a protocol that allows LLMs to access custom tools and services.</p>
</li>
<li><p>If your LLM wants to talk to an agent for a specific task then with MCP it is easy to integrate the LLM to this Agent.</p>
</li>
</ul>
<h1 id="heading-why-mcp-is-needed">Why MCP is needed ?</h1>
<p>MCP solves the following challenges in the current way of connecting LLMs to AI Agents:</p>
<ul>
<li><p><strong>Vendor lock-in</strong>: LLMs are tied to specific AI Agent providers, making it difficult to switch providers.</p>
</li>
<li><p><strong>Security</strong>: LLMs need to access data and services which can lead to security issues.</p>
</li>
<li><p><strong>Integration complexity</strong>: LLMs need to integrate with different AI Agents, which can be complex and time-consuming.</p>
</li>
</ul>
<h1 id="heading-general-architecture">General Architecture</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743344001155/aa3e8f4c-5d5a-4def-babe-3891296ac8b3.png" alt class="image--center mx-auto" /></p>
<aside>
📖
<blockquote>
<p>At its core, MCP follows a client-server architecture where a host application can connect to multiple servers</p>
</blockquote>
</aside>

<ul>
<li><p><strong>MCP Hosts</strong>: Programs like Claude Desktop, IDEs, or AI tools that want to access data through MCP</p>
</li>
<li><p><strong>MCP Clients</strong>: Protocol clients that maintain 1:1 connections with servers</p>
</li>
<li><p><strong>MCP Servers</strong>: Lightweight programs that each expose specific capabilities through the standardized Model Context Protocol</p>
</li>
<li><p><strong>Local Data Sources</strong>: Your computers files, databases, and services that MCP servers can securely access</p>
</li>
<li><p><strong>Remote Services</strong>: External systems available over the internet (e.g., through APIs) that MCP servers can connect to</p>
</li>
</ul>
<h1 id="heading-mcp-example">MCP Example :</h1>
<h1 id="heading-mcp-data-interface-for-oci-object-storage">🧠 MCP Data Interface for OCI Object Storage</h1>
<p>This project is a <strong>Model Context Protocol (MCP)</strong>-based API interface for <strong>Oracle Cloud Infrastructure (OCI) Object Storage</strong>. It allows AI agents, tools like Ollama, and natural language interfaces to programmatically list and read objects from OCI buckets via structured JSON requests.</p>
<hr />
<h2 id="heading-features">📌 Features</h2>
<ul>
<li><p> List objects in an OCI bucket</p>
</li>
<li><p> Read and return file contents from a bucket</p>
</li>
<li><p> Minimal and easy-to-extend MCP-style API</p>
</li>
<li><p> FastAPI-powered Python server</p>
</li>
<li><p> CLI-driven backend using <code>oci os</code> commands</p>
</li>
</ul>
<hr />
<h2 id="heading-use-cases">📦 Use Cases</h2>
<p>This MCP server is ideal for:</p>
<ul>
<li><p><strong>AI/LLM agents</strong> needing data from OCI buckets</p>
</li>
<li><p><strong>Streamlit or LangChain apps</strong> accessing cloud storage</p>
</li>
<li><p><strong>FinOps or Security tools</strong> fetching bucket inventories</p>
</li>
<li><p><strong>Conversational UIs</strong> querying cloud resources</p>
</li>
<li><p><strong>Cloud-native notebooks</strong> fetching <code>.csv</code>, <code>.json</code>, etc. for ML</p>
</li>
</ul>
<h3 id="heading-read-more-and-get-the-source-code-from-my-github-repo">Read more and get the source code from my Github repo :</h3>
<p><a target="_blank" href="https://github.com/mukundmurali-mm/MCP">MCP</a></p>
]]></description><link>https://blog.mukundmurali.in/unlocking-ai-potential-the-model-context-protocol-mcp-revolution</link><guid isPermaLink="true">https://blog.mukundmurali.in/unlocking-ai-potential-the-model-context-protocol-mcp-revolution</guid><category><![CDATA[AI]]></category><category><![CDATA[mcp server]]></category><dc:creator><![CDATA[Mukund Murali]]></dc:creator></item><item><title><![CDATA[How to Create a Smart Research Assistant Using OCI AI Agents]]></title><description><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741091443260/3e9dfd3b-b2bc-4080-87d3-d5336c46c53e.png" alt class="image--center mx-auto" /></p>
<p>In today's rapidly evolving technological landscape, artificial intelligence has become an integral part of how we conduct research and analyze information. This simple solution helps you setup a research assistant chatbot which will help you to converse with your document.</p>
<h2 id="heading-project-overview"><strong>Project Overview</strong></h2>
<p>Oracle Cloud Infrastructure's AI Agents provide robust, scalable, and secure AI capabilities that can transform how businesses conduct research and analyze information. Our application leverages these capabilities through a sleek, user-friendly interface built with Streamlit, making advanced AI interactions accessible to everyone.</p>
<h2 id="heading-pre-requisites"><strong>Pre-requisites</strong></h2>
<ul>
<li><p>Create the OCI AI Agent endpoints.</p>
</li>
<li><p>Create the data source with Bucket with All objects option selected.</p>
</li>
<li><p>Create the Bucket in the same compartment as OCI AI Agent.</p>
</li>
<li><p>IAM policies for authorization - <a target="_blank" href="https://docs.oracle.com/en-us/iaas/Content/generative-ai-agents/iam-policies.htm">https://docs.oracle.com/en-us/iaas/Content/generative-ai-agents/iam-policies.htm</a></p>
</li>
</ul>
<h2 id="heading-key-features"><strong>Key Features</strong></h2>
<ul>
<li><p>Seamless Authentication: The application integrates smoothly with OCI's authentication system, using your existing OCI CLI config credentials for secure access.</p>
</li>
<li><p>Interactive Chat Interface: Built with Streamlit, the application provides a responsive and intuitive chat experience that feels natural and engaging.</p>
</li>
<li><p>Session Persistence: Your chat history is maintained throughout your session, allowing for contextual conversations and easy reference to previous interactions.</p>
</li>
<li><p>Enterprise-Ready: With built-in error handling and user feedback mechanisms, the application is designed for reliability and professional use.</p>
</li>
<li><p>Data Privacy: All Files are securely stored in OCI Object Storage Bucket.</p>
</li>
</ul>
<h2 id="heading-limitation"><strong>Limitation</strong></h2>
<ul>
<li><p>Currently OCI AI Agents supports only TXT and PDF format files.</p>
</li>
<li><p>The maximum size for a file to be ingested is 100 MB.</p>
</li>
<li><p>Your tenancy must have the US Midwest (Chicago) region. Generative AI Agents is only available in this region.</p>
</li>
<li><p>Your OCI AI Agents and Buckets should be in the same compartment(This is a limitation for this application alone and not a general OCI AI Agent limitation).</p>
</li>
</ul>
<h2 id="heading-technical-implementation"><strong>Technical Implementation</strong></h2>
<p>The application is built using Python and leverages several key technologies:</p>
<ul>
<li><p>Streamlit: For creating a responsive and modern web interface</p>
</li>
<li><p>OCI Python SDK: For seamless integration with Oracle Cloud Infrastructure</p>
</li>
<li><p>Python 3.7+: Ensuring compatibility with modern Python features</p>
</li>
</ul>
<h2 id="heading-getting-started"><strong>Getting Started</strong></h2>
<h3 id="heading-setting-up-the-application-is-straightforward">Setting up the application is straightforward:</h3>
<p>1. Create and activate a Python virtual environment:</p>
<pre><code class="lang-python">python -m venv .venv 
source .venv/bin/activate  <span class="hljs-comment"># On macOS/Linux</span>
</code></pre>
<p>or</p>
<pre><code class="lang-python">.venv\Scripts\activate  <span class="hljs-comment"># On Windows</span>
</code></pre>
<p>2. Install the required dependencies using pip:</p>
<pre><code class="lang-python">pip install -r requirements.txt
</code></pre>
<p>3. Configure your OCI credentials in the OCI CLI config profile (~/.oci/config)</p>
<p>4. Save the below code inside the virtual env(ex: app.py) and run the application</p>
<pre><code class="lang-python">Streamlit run app.py
</code></pre>
<p>5. Pass in your required parameters in the application and start chatting.</p>
<p><em>P.S: whenever there is a new object added or exiting object is deleted to the bucket which needs to be part of this Application then run 'create Injection job' once the object is uploaded/deleted.</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741091742855/5e644579-e4f4-42fa-8608-73025eb9982a.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-code"><strong>Code</strong></h2>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> streamlit <span class="hljs-keyword">as</span> st
<span class="hljs-keyword">import</span> oci
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> time
<span class="hljs-comment"># Set page configuration with OCI favicon</span>
st.set_page_config(
    page_title=<span class="hljs-string">"OCI AI Research Assistant"</span>,
    page_icon=<span class="hljs-string">"https://www.oracle.com/favicon.ico"</span>,
    layout=<span class="hljs-string">"wide"</span>
)
<span class="hljs-keyword">from</span> oci.config <span class="hljs-keyword">import</span> from_file
<span class="hljs-keyword">from</span> oci.generative_ai_agent_runtime.generative_ai_agent_runtime_client <span class="hljs-keyword">import</span> GenerativeAiAgentRuntimeClient
<span class="hljs-keyword">from</span> oci.generative_ai_agent_runtime.models.chat_details <span class="hljs-keyword">import</span> ChatDetails
<span class="hljs-keyword">from</span> oci.generative_ai_agent <span class="hljs-keyword">import</span> GenerativeAiAgentClient
<span class="hljs-keyword">from</span> oci.generative_ai_agent.models <span class="hljs-keyword">import</span> CreateDataIngestionJobDetails
<span class="hljs-keyword">from</span> oci.object_storage <span class="hljs-keyword">import</span> ObjectStorageClient
<span class="hljs-keyword">from</span> oci.object_storage.models <span class="hljs-keyword">import</span> CreateBucketDetails
<span class="hljs-keyword">from</span> tempfile <span class="hljs-keyword">import</span> NamedTemporaryFile
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">initialize_oci_clients</span>(<span class="hljs-params">profile_name=<span class="hljs-string">"DEFAULT"</span>, agent_endpoint_id=None</span>):</span>
    <span class="hljs-string">"""Initialize OCI clients with the specified profile and create a session"""</span>
    <span class="hljs-keyword">try</span>:
        st.write(<span class="hljs-string">f"Attempting to load config profile: <span class="hljs-subst">{profile_name}</span>"</span>)
        config = from_file(profile_name=profile_name)
        st.write(<span class="hljs-string">"Config loaded successfully"</span>)
        st.write(<span class="hljs-string">f"Using region: <span class="hljs-subst">{config.get(<span class="hljs-string">'region'</span>)}</span>"</span>)

        <span class="hljs-comment"># Use the appropriate service endpoint based on your region</span>
        service_endpoint = <span class="hljs-string">"https://agent-runtime.generativeai.us-chicago-1.oci.oraclecloud.com"</span>
        st.write(<span class="hljs-string">f"Using service endpoint: <span class="hljs-subst">{service_endpoint}</span>"</span>)

        <span class="hljs-comment"># Initialize GenAI client with service endpoint</span>
        genai_client = GenerativeAiAgentRuntimeClient(
            config,
            service_endpoint=service_endpoint
        )

        <span class="hljs-comment"># Create a session if agent_endpoint_id is provided and session doesn't exist</span>
        <span class="hljs-keyword">if</span> agent_endpoint_id <span class="hljs-keyword">and</span> <span class="hljs-string">'chat_session_id'</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> st.session_state:
            <span class="hljs-keyword">try</span>:
                create_session_response = genai_client.create_session(
                    create_session_details=oci.generative_ai_agent_runtime.models.CreateSessionDetails(
                        display_name=<span class="hljs-string">"USER_Session"</span>,
                        description=<span class="hljs-string">"User Session"</span>),
                    agent_endpoint_id=agent_endpoint_id)
                st.session_state.chat_session_id = create_session_response.data.id
                st.write(<span class="hljs-string">"Chat session created successfully"</span>)
            <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
                st.error(<span class="hljs-string">f"Error creating chat session: <span class="hljs-subst">{str(e)}</span>"</span>)

        <span class="hljs-comment"># Initialize Object Storage client</span>
        object_storage_client = ObjectStorageClient(config)

        <span class="hljs-comment"># Initialize Identity client</span>
        identity_client = oci.identity.IdentityClient(config)

        st.write(<span class="hljs-string">"OCI clients initialized"</span>)
        <span class="hljs-keyword">return</span> genai_client, object_storage_client, identity_client, config
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        st.error(<span class="hljs-string">f"Error initializing OCI clients: <span class="hljs-subst">{str(e)}</span>"</span>)
        st.error(<span class="hljs-string">"Please check if your OCI config file (~/.oci/config) exists and contains the correct profile"</span>)
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>, <span class="hljs-literal">None</span>, <span class="hljs-literal">None</span>, <span class="hljs-literal">None</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">list_objects</span>(<span class="hljs-params">object_storage_client, namespace, bucket_name</span>):</span>
    <span class="hljs-string">"""List objects in a bucket"""</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># Send the request to service with minimal required parameters</span>
        list_objects_response = object_storage_client.list_objects(
            namespace_name=namespace,
            bucket_name=bucket_name,
            fields=<span class="hljs-string">"name,size,timeCreated"</span>  <span class="hljs-comment"># Only fetch essential fields</span>
        )
        <span class="hljs-keyword">return</span> list_objects_response.data.objects
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        st.error(<span class="hljs-string">f"Error listing objects: <span class="hljs-subst">{str(e)}</span>"</span>)
        <span class="hljs-keyword">return</span> []
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">upload_file</span>(<span class="hljs-params">object_storage_client, namespace, bucket_name, file</span>):</span>
    <span class="hljs-string">"""Upload a file to object storage"""</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># Read the file content</span>
        file_content = file.read()

        <span class="hljs-comment"># Upload the file to Object Storage using put_object</span>
        put_object_response = object_storage_client.put_object(
            namespace_name=namespace,
            bucket_name=bucket_name,
            object_name=file.name,
            put_object_body=file_content,
            content_type=file.type <span class="hljs-keyword">if</span> hasattr(file, <span class="hljs-string">'type'</span>) <span class="hljs-keyword">else</span> <span class="hljs-literal">None</span>
        )
        <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        st.error(<span class="hljs-string">f"Error uploading file: <span class="hljs-subst">{str(e)}</span>"</span>)
        <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">delete_object</span>(<span class="hljs-params">object_storage_client, namespace, bucket_name, object_name</span>):</span>
    <span class="hljs-string">"""Delete an object from object storage"""</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># Send the delete request to service</span>
        object_storage_client.delete_object(
            namespace_name=namespace,
            bucket_name=bucket_name,
            object_name=object_name
        )
        <span class="hljs-comment"># Verify deletion by trying to get object metadata</span>
        <span class="hljs-keyword">try</span>:
            object_storage_client.head_object(
                namespace_name=namespace,
                bucket_name=bucket_name,
                object_name=object_name
            )
            st.error(<span class="hljs-string">f"Failed to delete <span class="hljs-subst">{object_name}</span>. Object still exists."</span>)
            <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
        <span class="hljs-keyword">except</span>:
            <span class="hljs-comment"># If we get an error trying to get the object, it means it's deleted</span>
            <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        st.error(<span class="hljs-string">f"Error deleting object: <span class="hljs-subst">{str(e)}</span>"</span>)
        <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">list_data_sources</span>(<span class="hljs-params">profile_name, compartment_id</span>):</span>
    <span class="hljs-string">"""List available data sources"""</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># Initialize the GenerativeAiAgent client</span>
        config = from_file(profile_name=profile_name)
        generative_ai_agent_client = GenerativeAiAgentClient(config)

        <span class="hljs-comment"># List data sources</span>
        response = generative_ai_agent_client.list_data_sources(
            compartment_id=compartment_id,
            lifecycle_state=<span class="hljs-string">"ACTIVE"</span>
        )

        <span class="hljs-keyword">return</span> response.data.items <span class="hljs-keyword">if</span> response.data <span class="hljs-keyword">else</span> []
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        st.error(<span class="hljs-string">f"Error listing data sources: <span class="hljs-subst">{str(e)}</span>"</span>)
        <span class="hljs-keyword">return</span> []
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_ingestion_job</span>(<span class="hljs-params">profile_name, compartment_id, data_source_id</span>):</span>
    <span class="hljs-string">"""Create a data ingestion job"""</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># Initialize the GenerativeAiAgent client</span>
        config = from_file(profile_name=profile_name)
        generative_ai_agent_client = GenerativeAiAgentClient(config)

        <span class="hljs-comment"># Create the ingestion job</span>
        response = generative_ai_agent_client.create_data_ingestion_job(
            create_data_ingestion_job_details=CreateDataIngestionJobDetails(
                compartment_id=compartment_id,
                data_source_id=data_source_id,
                display_name=<span class="hljs-string">f"Ingestion-Job-<span class="hljs-subst">{int(time.time())}</span>"</span>,  <span class="hljs-comment"># Unique name using timestamp</span>
                description=<span class="hljs-string">"Data ingestion job created from Research Assistant"</span>
            )
        )

        <span class="hljs-keyword">return</span> response.data
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        st.error(<span class="hljs-string">f"Error creating ingestion job: <span class="hljs-subst">{str(e)}</span>"</span>)
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_chat_response</span>(<span class="hljs-params">client, agent_endpoint_id, message</span>):</span>
    <span class="hljs-string">"""Get response from the chat agent"""</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># Validate agent endpoint ID</span>
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> agent_endpoint_id <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> agent_endpoint_id.strip():
            st.error(<span class="hljs-string">"Agent Endpoint ID is required"</span>)
            <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

        <span class="hljs-comment"># Ensure we have a session ID</span>
        <span class="hljs-keyword">if</span> <span class="hljs-string">'chat_session_id'</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> st.session_state:
            <span class="hljs-comment"># Create a new session if we don't have one</span>
            <span class="hljs-keyword">try</span>:
                create_session_response = client.create_session(
                    create_session_details=oci.generative_ai_agent_runtime.models.CreateSessionDetails(
                        display_name=<span class="hljs-string">"USER_Session"</span>,
                        description=<span class="hljs-string">"User Session"</span>),
                    agent_endpoint_id=agent_endpoint_id)
                st.session_state.chat_session_id = create_session_response.data.id
            <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
                st.error(<span class="hljs-string">f"Error creating chat session: <span class="hljs-subst">{str(e)}</span>"</span>)
                <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

        <span class="hljs-comment"># Send the chat request</span>
        response = client.chat(
            agent_endpoint_id=agent_endpoint_id,
            chat_details=ChatDetails(
                user_message=message,
                should_stream=<span class="hljs-literal">False</span>,  <span class="hljs-comment"># Set to False for now until we implement streaming properly</span>
                session_id=st.session_state.chat_session_id
            )
        )

        <span class="hljs-comment"># Debug: Print response structure</span>
        st.write(<span class="hljs-string">"Response data attributes:"</span>, dir(response.data))

        <span class="hljs-comment"># Return the response - accessing the correct attribute</span>
        <span class="hljs-keyword">return</span> response.data.message
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        st.error(<span class="hljs-string">f"Error getting chat response: <span class="hljs-subst">{str(e)}</span>"</span>)
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    <span class="hljs-string">"""Main function for the OCI AI Research Assistant application"""</span>
    st.title(<span class="hljs-string">"OCI AI Research Assistant"</span>)

    <span class="hljs-comment"># Configuration Section in Sidebar</span>
    <span class="hljs-keyword">with</span> st.sidebar:
        st.header(<span class="hljs-string">"Configuration"</span>)

        <span class="hljs-comment"># Display available profiles from ~/.oci/config</span>
        config_file = os.path.expanduser(<span class="hljs-string">"~/.oci/config"</span>)
        available_profiles = []

        <span class="hljs-keyword">if</span> os.path.exists(config_file):
            <span class="hljs-keyword">with</span> open(config_file, <span class="hljs-string">'r'</span>) <span class="hljs-keyword">as</span> f:
                content = f.read()
                profiles = [line.strip(<span class="hljs-string">'['</span>).strip(<span class="hljs-string">']'</span>) <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> content.split(<span class="hljs-string">'\n'</span>) <span class="hljs-keyword">if</span> line.strip().startswith(<span class="hljs-string">'['</span>)]
                available_profiles = profiles

        <span class="hljs-comment">#st.write("Available profiles:", ", ".join(available_profiles))</span>

        <span class="hljs-comment"># OCI Configuration</span>
        profile_name = st.selectbox(
            <span class="hljs-string">"OCI Profile Name"</span>,
            options=available_profiles,
            index=available_profiles.index(<span class="hljs-string">"DEFAULT"</span>) <span class="hljs-keyword">if</span> <span class="hljs-string">"DEFAULT"</span> <span class="hljs-keyword">in</span> available_profiles <span class="hljs-keyword">else</span> <span class="hljs-number">0</span>
        )
        agent_endpoint_id = st.text_input(<span class="hljs-string">"Agent Endpoint ID"</span>)
        compartment_id = st.text_input(<span class="hljs-string">"Compartment ID"</span>)

        <span class="hljs-comment"># Object Storage Configuration</span>
        namespace = st.text_input(<span class="hljs-string">"Namespace Name"</span>)
        bucket_name = st.text_input(<span class="hljs-string">"Bucket Name"</span>)

        <span class="hljs-comment"># Initialize button</span>
        <span class="hljs-keyword">if</span> st.button(<span class="hljs-string">"Initialize Clients"</span>):
            <span class="hljs-comment"># Validate required inputs</span>
            <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> agent_endpoint_id <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> agent_endpoint_id.strip():
                st.error(<span class="hljs-string">"Agent Endpoint ID is required"</span>)
                <span class="hljs-keyword">return</span>

            <span class="hljs-comment"># Store all inputs in session state</span>
            st.session_state.profile_name = profile_name
            st.session_state.agent_endpoint_id = agent_endpoint_id
            st.session_state.compartment_id = compartment_id
            st.session_state.namespace = namespace
            st.session_state.bucket_name = bucket_name

            <span class="hljs-comment"># Initialize OCI clients with agent endpoint ID</span>
            genai_client, object_storage_client, identity_client, config = initialize_oci_clients(
                profile_name=profile_name,
                agent_endpoint_id=agent_endpoint_id
            )

            <span class="hljs-keyword">if</span> all([genai_client, object_storage_client, identity_client]):
                st.session_state.genai_client = genai_client
                st.session_state.object_storage_client = object_storage_client
                st.session_state.identity_client = identity_client
                st.session_state.config = config
                st.success(<span class="hljs-string">"OCI clients and chat session initialized successfully!"</span>)

    <span class="hljs-comment"># Main content area for chat</span>
    <span class="hljs-keyword">if</span> hasattr(st.session_state, <span class="hljs-string">'genai_client'</span>):
        st.markdown(<span class="hljs-string">"""
        Welcome to your AI Research Assistant! Ask any question, and I'll help you find the information you need.
        """</span>)

        <span class="hljs-comment"># Initialize chat history if it doesn't exist</span>
        <span class="hljs-keyword">if</span> <span class="hljs-string">'messages'</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> st.session_state:
            st.session_state.messages = []
        <span class="hljs-comment"># Display chat history</span>
        <span class="hljs-keyword">for</span> message <span class="hljs-keyword">in</span> st.session_state.messages:
            <span class="hljs-keyword">with</span> st.chat_message(message[<span class="hljs-string">"role"</span>]):
                st.markdown(message[<span class="hljs-string">"content"</span>])
        <span class="hljs-comment"># Chat input</span>
        <span class="hljs-keyword">if</span> prompt := st.chat_input(<span class="hljs-string">"What would you like to research?"</span>):
            <span class="hljs-comment"># Add user message to chat history</span>
            st.session_state.messages.append({<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: prompt})

            <span class="hljs-comment"># Display user message</span>
            <span class="hljs-keyword">with</span> st.chat_message(<span class="hljs-string">"user"</span>):
                st.markdown(prompt)

            <span class="hljs-comment"># Get AI response</span>
            <span class="hljs-keyword">with</span> st.chat_message(<span class="hljs-string">"assistant"</span>):
                <span class="hljs-keyword">try</span>:
                    response = get_chat_response(
                        st.session_state.genai_client,
                        st.session_state.agent_endpoint_id,
                        prompt
                    )
                    <span class="hljs-keyword">if</span> response:
                        st.markdown(response)
                        <span class="hljs-comment"># Add assistant response to chat history</span>
                        st.session_state.messages.append({<span class="hljs-string">"role"</span>: <span class="hljs-string">"assistant"</span>, <span class="hljs-string">"content"</span>: response})
                <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
                    st.error(<span class="hljs-string">f"Error getting response: <span class="hljs-subst">{str(e)}</span>"</span>)

        <span class="hljs-comment"># Object Storage in Sidebar</span>
        <span class="hljs-keyword">if</span> hasattr(st.session_state, <span class="hljs-string">'object_storage_client'</span>):
            <span class="hljs-keyword">with</span> st.sidebar:
                st.markdown(<span class="hljs-string">"---"</span>)

                <span class="hljs-comment"># Ingestion Job Section</span>
                st.header(<span class="hljs-string">"Data Ingestion"</span>)

                <span class="hljs-comment"># List data sources</span>
                data_sources = list_data_sources(
                    st.session_state.profile_name,
                    st.session_state.compartment_id
                )

                <span class="hljs-keyword">if</span> data_sources:
                    <span class="hljs-comment"># Create a list of data source names and IDs for the selectbox</span>
                    data_source_options = {<span class="hljs-string">f"<span class="hljs-subst">{ds.display_name}</span> (<span class="hljs-subst">{ds.id}</span>)"</span>: ds.id <span class="hljs-keyword">for</span> ds <span class="hljs-keyword">in</span> data_sources}
                    selected_source = st.selectbox(
                        <span class="hljs-string">"Select Data Source"</span>,
                        options=list(data_source_options.keys())
                    )

                    <span class="hljs-keyword">if</span> st.button(<span class="hljs-string">"Create Ingestion Job"</span>, type=<span class="hljs-string">"primary"</span>):
                        <span class="hljs-keyword">with</span> st.spinner(<span class="hljs-string">"Creating ingestion job..."</span>):
                            result = create_ingestion_job(
                                st.session_state.profile_name,
                                st.session_state.compartment_id,
                                data_source_options[selected_source]
                            )
                            <span class="hljs-keyword">if</span> result:
                                st.success(<span class="hljs-string">f"Created ingestion job: <span class="hljs-subst">{result.id}</span>"</span>)
                <span class="hljs-keyword">else</span>:
                    st.warning(<span class="hljs-string">"No active data sources found in the compartment."</span>)

                st.markdown(<span class="hljs-string">"---"</span>)
                st.header(<span class="hljs-string">"Object Storage"</span>)

                <span class="hljs-comment"># Upload section</span>
                st.subheader(<span class="hljs-string">"Upload File"</span>)
                uploaded_file = st.file_uploader(<span class="hljs-string">"Choose a file to upload"</span>, key=<span class="hljs-string">"sidebar_uploader"</span>)
                <span class="hljs-keyword">if</span> uploaded_file <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
                    <span class="hljs-keyword">if</span> st.button(<span class="hljs-string">"Upload"</span>):
                        <span class="hljs-keyword">if</span> upload_file(st.session_state.object_storage_client, 
                                     st.session_state.namespace, 
                                     st.session_state.bucket_name, 
                                     uploaded_file):
                            st.success(<span class="hljs-string">f"File <span class="hljs-subst">{uploaded_file.name}</span> uploaded successfully!"</span>)
                            st.experimental_rerun()

                <span class="hljs-comment"># List Objects section</span>
                st.subheader(<span class="hljs-string">"Objects in Bucket"</span>)

                <span class="hljs-comment"># Get the current list of objects</span>
                objects = list_objects(
                    st.session_state.object_storage_client,
                    st.session_state.namespace,
                    st.session_state.bucket_name
                )

                <span class="hljs-comment"># Add refresh button</span>
                <span class="hljs-keyword">if</span> st.button(<span class="hljs-string">"Refresh Objects"</span>, type=<span class="hljs-string">"primary"</span>):
                    st.rerun()

                <span class="hljs-keyword">if</span> objects:
                    <span class="hljs-keyword">for</span> obj <span class="hljs-keyword">in</span> objects:
                        col1, col2 = st.columns([<span class="hljs-number">3</span>, <span class="hljs-number">1</span>])
                        <span class="hljs-keyword">with</span> col1:
                            st.write(<span class="hljs-string">f"📄 <span class="hljs-subst">{obj.name}</span>\n<span class="hljs-subst">{obj.size:,}</span> bytes"</span>)
                        <span class="hljs-keyword">with</span> col2:
                            delete_button_key = <span class="hljs-string">f"delete_<span class="hljs-subst">{obj.name}</span>"</span>
                            <span class="hljs-keyword">if</span> st.button(<span class="hljs-string">"🗑"</span>, key=delete_button_key, help=<span class="hljs-string">f"Delete <span class="hljs-subst">{obj.name}</span>"</span>):
                                <span class="hljs-keyword">try</span>:
                                    <span class="hljs-keyword">with</span> st.spinner(<span class="hljs-string">f"Deleting <span class="hljs-subst">{obj.name}</span>..."</span>):
                                        <span class="hljs-keyword">if</span> delete_object(
                                            st.session_state.object_storage_client,
                                            st.session_state.namespace,
                                            st.session_state.bucket_name,
                                            obj.name
                                        ):
                                            st.success(<span class="hljs-string">f"Deleted <span class="hljs-subst">{obj.name}</span>"</span>)
                                            st.rerun()
                                        <span class="hljs-keyword">else</span>:
                                            st.error(<span class="hljs-string">f"Failed to delete <span class="hljs-subst">{obj.name}</span>"</span>)
                                <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
                                    st.error(<span class="hljs-string">f"Error deleting <span class="hljs-subst">{obj.name}</span>: <span class="hljs-subst">{str(e)}</span>"</span>)
                        st.divider()
                <span class="hljs-keyword">else</span>:
                    st.info(<span class="hljs-string">"No objects found in this bucket"</span>)

                    st.markdown(response)
                    <span class="hljs-comment"># Add assistant response to chat history</span>
                    st.session_state.messages.append({<span class="hljs-string">"role"</span>: <span class="hljs-string">"assistant"</span>, <span class="hljs-string">"content"</span>: response})
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    main()
</code></pre>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>The OCI AI Research Assistant showcases how enterprise-grade AI can be made accessible and user-friendly. Whether you're conducting academic research, analyzing complex data, or building knowledge management solutions, this project provides a solid foundation for your AI-powered research endeavors.</p>
<p>New features will be added to this application in the future.</p>
]]></description><link>https://blog.mukundmurali.in/how-to-create-a-smart-research-assistant-using-oci-ai-agents</link><guid isPermaLink="true">https://blog.mukundmurali.in/how-to-create-a-smart-research-assistant-using-oci-ai-agents</guid><category><![CDATA[AI]]></category><category><![CDATA[OCI]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[research]]></category><dc:creator><![CDATA[Mukund Murali]]></dc:creator></item><item><title><![CDATA[Exploring Your Cloud with Steampipe and Powerpipe: An Overview with OCI Focus]]></title><description><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731208583927/a95dc693-a9c9-4d39-81fd-20e817690b19.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-introduction">Introduction</h2>
<p>This blog post explores Steampipe and Powerpipe, powerful tools for gaining insights into your cloud resources, particularly for Oracle Cloud Infrastructure (OCI). We'll cover the basics of Steampipe, Powerpipe, and their parent company Turbot, the supported cloud providers, and delve specifically into how these tools can be used with OCI and Terraform.</p>
<h2 id="heading-what-is-steampipe">What is Steampipe?</h2>
<p><strong>Steampipe</strong> is an open-source tool that enables users to query cloud APIs, code repositories, and other services using SQL. It acts as a universal translator, eliminating the need for specialized knowledge of various platforms and allowing you to leverage your existing SQL skills to interrogate your infrastructure. Steampipe essentially turns your cloud resources into a database that can be queried, analysed, and reported on.</p>
<h2 id="heading-what-is-powerpipe">What is Powerpipe?</h2>
<p><strong>Powerpipe</strong> builds upon Steampipe's functionality by providing a visual interface for creating dashboards and reports. It takes the raw data gathered by Steampipe and transforms it into easily understandable visualisations, making it easier to identify trends, potential security risks, and cost optimization opportunities. Powerpipe is particularly beneficial for DevOps, SecOps, and FinOps teams as it provides a consolidated view of cloud resources and their configurations.</p>
<h2 id="heading-what-is-turbot">What is Turbot?</h2>
<p>Steampipe and Powerpipe are products of <strong>Turbot</strong>, a company that provides cloud governance and automation solutions. Turbot offers both open-source and commercial products based on Steampipe and Powerpipe technology.</p>
<h2 id="heading-cloud-providers-supported-by-steampipe">Cloud Providers Supported by Steampipe</h2>
<p>Steampipe has a wide range of plugins that connect to various cloud providers and services. Some of the major supported cloud providers include:</p>
<ul>
<li><p><strong>Alibaba Cloud</strong></p>
</li>
<li><p><strong>Amazon Web Services (AWS)</strong></p>
</li>
<li><p><strong>Azure</strong></p>
</li>
<li><p><strong>DigitalOcean</strong></p>
</li>
<li><p><strong>Google Cloud Platform (GCP)</strong></p>
</li>
<li><p><strong>Heroku</strong></p>
</li>
<li><p><strong>IBM Cloud</strong></p>
</li>
<li><p><strong>Linode</strong></p>
</li>
<li><p><strong>Oracle Cloud Infrastructure (OCI)</strong></p>
</li>
<li><p><strong>Scaleway</strong></p>
</li>
<li><p><strong>Snowflake</strong></p>
</li>
</ul>
<h2 id="heading-focusing-on-oci-steampipe-powerpipe-and-terraform">Focusing on OCI: Steampipe, Powerpipe, and Terraform</h2>
<p>For <strong>Oracle Cloud Infrastructure (OCI)</strong>, Steampipe provides comprehensive coverage through its plugin. This plugin allows users to query various OCI services and resources using SQL. In addition to basic querying, Steampipe for OCI can be used for:</p>
<ul>
<li><p><strong>Compliance Checks:</strong> The <code>oci_compliance</code> mod allows you to run security and compliance checks against your OCI resources. It supports benchmarks like CIS, helping you identify misconfigurations and potential vulnerabilities.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731208891028/894d18fa-b191-4c3a-b7a3-8b42073eb01f.png" alt class="image--center mx-auto" /></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731208855213/1a5f9739-088a-4430-befb-7c1a3b035d92.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Insights and Reporting:</strong> The <code>oci_insights</code> mod provides pre-built dashboards for visualizing your OCI resources. This helps gain a better understanding of your cloud infrastructure and its configuration.</p>
</li>
<li><p><strong>Cost Optimization:</strong> The <code>oci_thrifty</code> mod focuses on finding unused and underutilized resources. This helps optimize your cloud spending and reduce costs.</p>
</li>
<li><p><strong>Terraform</strong> is a popular Infrastructure as Code (IaC) tool used to manage and provision cloud resources. The <code>terraform_oci_compliance</code> mod allows you to scan your Terraform code, plans, and state files for potential security misconfigurations before deploying to OCI.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731208709109/9022775f-ba5a-409c-a035-61bd84a0fde9.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<h2 id="heading-examples-and-use-cases-for-oci">Examples and Use Cases for OCI</h2>
<p>Let's illustrate the power of Steampipe with some practical examples for OCI:</p>
<ul>
<li><p><strong>Querying OCI Users:</strong> You can retrieve details about your OCI users with a simple SQL query like:</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">select</span> <span class="hljs-keyword">name</span>, <span class="hljs-keyword">id</span>, is_mfa_activated <span class="hljs-keyword">from</span> oci_identity_user;
</code></pre>
<p>  This query retrieves the name, ID, and MFA activation status of all OCI users.</p>
</li>
<li><p><strong>Checking for Publicly Accessible Buckets:</strong> To enhance security, you can identify object storage buckets that are publicly accessible using a query like:</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">select</span> <span class="hljs-keyword">name</span> <span class="hljs-keyword">from</span> oci_objectstorage_bucket <span class="hljs-keyword">where</span> public_access_type != <span class="hljs-string">'NoPublicAccess'</span>;
</code></pre>
<p>  This query lists the names of all buckets that allow some form of public access.</p>
</li>
<li><p><strong>Identifying Unused Compute Instances:</strong> For cost optimization, you can find compute instances that are potentially unused with a query like:</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">select</span> display_name, shape, time_created
  <span class="hljs-keyword">from</span> oci_core_instance
  <span class="hljs-keyword">where</span> state = <span class="hljs-string">'Stopped'</span>
  <span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> time_created <span class="hljs-keyword">desc</span>;
</code></pre>
<p>  This query lists stopped instances, ordered by their creation time, allowing you to investigate instances that have been stopped for a long time.</p>
<h2 id="heading-oci-insights-dashboard-questions">OCI Insights Dashboard Questions</h2>
<p>  While the sources don't explicitly list the questions that OCI Insights dashboards answer, they do provide clues about their capabilities. Based on the information in the sources, here's a breakdown of potential questions these dashboards can help answer:</p>
<p>  <strong>Resource Inventory and Properties:</strong></p>
<ul>
<li><p><strong>How many resources do I have?</strong> This basic question can be answered across various resource types, providing a quick overview of your OCI footprint.</p>
</li>
<li><p><strong>How old are my resources?</strong> Understanding the age of resources can be helpful for lifecycle management and identifying potential candidates for decommissioning or upgrades.</p>
</li>
</ul>
</li>
</ul>
<p>    <strong>Security Posture:</strong></p>
<ul>
<li><p><strong>Are there any publicly accessible resources?</strong> This is a critical security question, as publicly accessible resources can pose significant risks. OCI Insights dashboards can likely help identify such resources, allowing you to take corrective actions.</p>
</li>
<li><p><strong>Is encryption enabled, and what keys are used for encryption?</strong> These dashboards can likely provide insights into the encryption status of resources, helping you assess your data protection measures.</p>
</li>
</ul>
<p>    <strong>Data Management:</strong></p>
<ul>
<li><strong>Is versioning enabled?</strong> This is particularly relevant for services like object storage, where versioning provides data recovery and protection against accidental deletions. OCI Insights dashboards can potentially show the versioning status of your resources.</li>
</ul>
<p>    <strong>Other Potential Insights:</strong></p>
<p>    The sources mention that OCI Insights dashboards are available for 10+ services, including Block Storage, Compute, Identity, Object Storage, VCN, and more. Given this breadth of coverage, it's likely that these dashboards can also help answer questions related to:</p>
<ul>
<li><p><strong>Resource utilization and performance:</strong> Dashboards could potentially show metrics related to CPU utilization, storage usage, network traffic, and other performance indicators.</p>
</li>
<li><p><strong>Cost allocation and trends:</strong> Insights into resource usage can be further used to analyse cost allocation and identify potential areas for optimisation.</p>
</li>
<li><p><strong>Compliance with specific standards:</strong> While the sources primarily focus on CIS benchmarks, it's possible that OCI Insights dashboards could also address compliance requirements for other standards, depending on the available mods and configurations.</p>
</li>
</ul>
<h2 id="heading-conclusion-and-next-steps">Conclusion and Next Steps</h2>
<p>Steampipe and Powerpipe are valuable tools for anyone working with cloud infrastructure, especially OCI. They provide a unified and intuitive way to query, analyZe, and visualize your cloud resources using the familiar SQL language. By leveraging these tools, you can gain a deeper understanding of your cloud infrastructure, improve security and compliance, and optimize costs.</p>
<p>To learn more about Steampipe and Powerpipe:</p>
<ul>
<li><p><a target="_blank" href="https://hub.steampipe.io/"><strong>Visit the Steampipe Hub</strong></a><strong>:</strong> Explore the various Steampipe plugins and their documentation.</p>
</li>
<li><p><a target="_blank" href="https://hub.powerpipe.io/#search"><strong>Visit the Powerpipe Hub</strong></a><strong>:</strong> Discover the available Powerpipe mods and see how they can be used to create insightful dashboards.</p>
</li>
<li><p><a target="_blank" href="https://turbot.com/pipes/docs"><strong>Explore Turbot's Website</strong></a><strong>:</strong> Find information about Turbot's products and solutions built on Steampipe and Powerpipe technology.</p>
</li>
</ul>
]]></description><link>https://blog.mukundmurali.in/exploring-your-cloud-with-steampipe-and-powerpipe-an-overview-with-oci-focus</link><guid isPermaLink="true">https://blog.mukundmurali.in/exploring-your-cloud-with-steampipe-and-powerpipe-an-overview-with-oci-focus</guid><category><![CDATA[steampipe]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Oracle Cloud]]></category><category><![CDATA[Terraform]]></category><dc:creator><![CDATA[Mukund Murali]]></dc:creator></item><item><title><![CDATA[Google's NotebookLM: A Second Brain for the AI Age]]></title><description><![CDATA[<p><strong>What is NotebookLM?</strong> NotebookLM is an AI-powered research tool developed by Google, designed to function as a personalized knowledge base powered by AI.</p>
<p><strong>Features and Capabilities</strong>:</p>
<ul>
<li><p><strong>Source Grounded AI:</strong> Unlike tools like Perplexity that rely on searching the open web, NotebookLM works by uploading your own documents, limiting its knowledge to the information you provide. This <strong>eliminates the risk of hallucinations</strong>, ensuring that the AI only generates responses grounded in your sources.</p>
</li>
<li><p><strong>Multimodal Support:</strong> NotebookLM can handle a variety of file formats, including Google Docs, Google Slides, PDFs, images, and even YouTube videos and audio files. This versatility makes it ideal for research projects involving diverse types of information.</p>
</li>
<li><p><strong>Extensive Context Window:</strong> It supports up to 50 sources with up to 200,000 words per file, allowing you to build a knowledge base of up to 4 million words. This is much larger than the context windows of many other AI tools, enabling more comprehensive analysis.</p>
</li>
<li><p><strong>Audio Overview Generation:</strong> One of the standout features is its ability to summarize your sources into a podcast-style discussion between two AI voices. This can provide an engaging and efficient way to consume large amounts of information, though it's important to note that this feature is more prone to hallucinations.</p>
</li>
<li><p><strong>Precise Citations:</strong> NotebookLM cites its sources with pinpoint accuracy, highlighting the specific text it's drawing from. This is particularly useful for academic research or any situation where verifying information is crucial.</p>
</li>
</ul>
<p><strong>Use Cases with Examples</strong>:</p>
<ul>
<li><p><strong>Keeping Up with Niche Information:</strong> Upload weekly transcriptions of YouTube videos or podcasts in your industry to get a quick summary and analysis.</p>
</li>
<li><p><strong>Client Relationship Management:</strong> Store transcripts of client calls to quickly recall past discussions, identify recurring themes, and gain insights into the relationship.</p>
</li>
<li><p><strong>Market and Competitive Research:</strong> Analyze competitor websites and marketing materials to uncover their messaging, target audience, and potential gaps in their approach.</p>
</li>
<li><p><strong>Content Research:</strong></p>
<ul>
<li><p><strong>YouTube Content Research:</strong> Analyze top-performing YouTube videos on a topic to identify common themes, effective hooks, and unique angles.</p>
</li>
<li><p><strong>Content Optimization:</strong> Analyze the top-ranking articles for a target keyword to identify main topics covered, semantic keywords, and opportunities to make your content more comprehensive and relevant.</p>
</li>
</ul>
</li>
<li><p><strong>Turning a Blog Article into a Podcast:</strong> Upload a blog article, generate an audio overview, and edit the transcript to create a podcast script in your own voice.</p>
</li>
<li><p><strong>Audience Research:</strong> Analyze LinkedIn comments on posts by influential figures in your niche to understand audience desires, pain points, and potential content ideas.</p>
</li>
<li><p><strong>Academic Paper Summarization:</strong> Upload a complex academic paper and ask the AI to summarize key findings, explain concepts in simpler terms, or extract specific information.</p>
</li>
<li><p><strong>Meeting Notes Analysis:</strong> Upload meeting transcripts to quickly extract key points, identify action items, and generate summaries or proposals.</p>
</li>
<li><p><strong>Writing Assistance:</strong></p>
<ul>
<li><p><strong>Idea Generation:</strong> Use NotebookLM to brainstorm related ideas or avenues of research based on your existing notes.</p>
</li>
<li><p><strong>Outlining and Structuring:</strong> Generate outlines, key points, and suggestions for improving your writing.</p>
</li>
<li><p><strong>Drafting and Rewriting:</strong> Ask the AI to rewrite your drafts based on specific instructions or sources.</p>
</li>
</ul>
</li>
</ul>
<p><strong>Limitations</strong>:</p>
<ul>
<li><p><strong>Beta Stage:</strong> Being in beta, NotebookLM can have occasional bugs and limitations.</p>
</li>
<li><p><strong>Limited Source Integration:</strong> Currently, it only supports uploading Google Docs and PDFs. You can't directly connect to other note-taking apps.</p>
</li>
<li><p><strong>Source Limit:</strong> The maximum of 20 sources might require you to consolidate documents or manually copy and paste text if you have a large number of sources.</p>
</li>
<li><p><strong>Challenges with Specific Tasks:</strong> Like many AI tools, NotebookLM can struggle with complex math, poorly formatted PDFs, and retrieving highly specific details.</p>
</li>
</ul>
<p><strong>Data Privacy</strong>:</p>
<ul>
<li><p><strong>Google Terms of Service Apply:</strong> Your use of NotebookLM is governed by Google's Terms of Service.</p>
</li>
<li><p><strong>No Personal Data Used for Training:</strong> Google emphasizes that your personal data is never used to train NotebookLM.</p>
</li>
<li><p><strong>Feedback Review for Consumer Accounts:</strong> If you choose to provide feedback while logged in with a consumer Google account, human reviewers may access your queries, uploads, and the AI's responses.</p>
</li>
<li><p><strong>Privacy for Workspace Users:</strong> For Google Workspace or Google Workspace for Education users, your interactions with NotebookLM are not reviewed by humans and are not used for AI model training.</p>
</li>
</ul>
<p><strong>Conclusion</strong>:</p>
<p>NotebookLM presents a powerful new way to research, learn, and create using your own knowledge base. By combining the power of large language models with a focus on source grounded AI, it offers a level of control and accuracy not found in traditional search engines or AI chatbots. While still in its early stages, NotebookLM has the potential to revolutionize how we work with information.</p>
<h2 id="heading-contrasting-notebooklm-with-chatgpt-and-perplexity">Contrasting NotebookLM with ChatGPT and Perplexity</h2>
<p>Here's a comparison of NotebookLM with ChatGPT like LLMs and Perplexity like answer engines, highlighting their key differences:</p>
<h3 id="heading-notebooklm">NotebookLM</h3>
<ul>
<li><p><strong>Focus:</strong> Acts as a personal AI research assistant, enabling users to interact with their uploaded documents.</p>
</li>
<li><p><strong>AI Model:</strong> Powered by Google's Gemini 1.5 Pro.</p>
</li>
<li><p><strong>Data Source:</strong> Utilizes a user-defined knowledge base, limited to the information within uploaded documents (up to 50 sources with a maximum of 4 million words).</p>
</li>
<li><p><strong>Key Features:</strong></p>
<ul>
<li><p>Supports diverse file formats like Google Docs, PDFs, images, YouTube videos, and audio files.</p>
</li>
<li><p>Generates podcast-style audio summaries of source materials.</p>
</li>
<li><p>Provides precise citations, linking responses back to the specific text in the uploaded documents.</p>
</li>
</ul>
</li>
<li><p><strong>Strengths:</strong></p>
<ul>
<li><p><strong>Source-grounded responses:</strong> Eliminates hallucinations by restricting the AI to user-provided information.</p>
</li>
<li><p><strong>Large context window:</strong> Facilitates comprehensive analysis by accommodating a vast knowledge base.</p>
</li>
<li><p><strong>Privacy-focused:</strong> Personal data is not used for training, and options exist for limiting human review of interactions.</p>
</li>
</ul>
</li>
<li><p><strong>Limitations:</strong></p>
<ul>
<li><p>Restricted to Google Docs and PDF uploads, lacking direct integration with other note-taking apps.</p>
</li>
<li><p>Limited to 20 sources, requiring manual consolidation for larger datasets.</p>
</li>
<li><p>May face challenges with specific tasks like complex math or poorly formatted PDFs.</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-chatgpt">ChatGPT</h3>
<ul>
<li><p><strong>Focus:</strong> Functions as a general-purpose conversational AI chatbot, capable of engaging in open-ended conversations and creative tasks.</p>
</li>
<li><p><strong>AI Model:</strong> Powered by OpenAI's large language models (e.g., GPT-3.5, GPT-4).</p>
</li>
<li><p><strong>Data Source:</strong> Trained on a massive dataset of text and code scraped from the internet, enabling it to generate human-like text on a wide range of topics.</p>
</li>
<li><p><strong>Key Features:</strong></p>
<ul>
<li>Excels in creative writing, text summarization, translation, code generation, and answering general knowledge questions.</li>
</ul>
</li>
<li><p><strong>Strengths:</strong></p>
<ul>
<li><p><strong>Vast knowledge base:</strong> Access to a broad range of information allows for responses on diverse subjects.</p>
</li>
<li><p><strong>Creative capabilities:</strong> Generative abilities make it suitable for tasks requiring imagination and language fluency.</p>
</li>
</ul>
</li>
<li><p><strong>Limitations:</strong></p>
<ul>
<li><p><strong>Prone to hallucinations:</strong> Can generate inaccurate or fabricated information due to its reliance on internet data.</p>
</li>
<li><p><strong>Limited control over sources:</strong> Users cannot restrict the AI to specific sources, making fact-checking more challenging.</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-perplexity">Perplexity</h3>
<ul>
<li><p><strong>Focus:</strong> Designed as an AI-powered search engine that provides answers to user queries alongside citations.</p>
</li>
<li><p><strong>AI Model:</strong> Leverages large language models for understanding and responding to queries.</p>
</li>
<li><p><strong>Data Source:</strong> Retrieves information from the internet, relying on its web search capabilities to answer questions.</p>
</li>
<li><p><strong>Key Features:</strong></p>
<ul>
<li><p>Presents answers in a concise and informative manner, often including bullet points and key takeaways.</p>
</li>
<li><p>Cites sources to provide transparency and allow for verification.</p>
</li>
</ul>
</li>
<li><p><strong>Strengths:</strong></p>
<ul>
<li><p><strong>Real-time information:</strong> Accesses up-to-date information from the web.</p>
</li>
<li><p><strong>Focus on source attribution:</strong> Emphasizes transparency by providing links to the sources used in its responses.</p>
</li>
</ul>
</li>
<li><p><strong>Limitations:</strong></p>
<ul>
<li><p><strong>Potential for bias:</strong> Results can be influenced by the ranking algorithms of search engines.</p>
</li>
<li><p><strong>Less control over knowledge scope:</strong> Users have less control over the specific sources the AI utilizes compared to NotebookLM.</p>
</li>
</ul>
</li>
</ul>
<p><strong>Key Differences in a Nutshell:</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature</td><td>NotebookLM</td><td>ChatGPT</td><td>Perplexity</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Data Source</strong></td><td>User-uploaded documents</td><td>Massive internet dataset</td><td>Web search results</td></tr>
<tr>
<td><strong>Hallucinations</strong></td><td>Eliminated</td><td>Prone</td><td>Possible</td></tr>
<tr>
<td><strong>Source Control</strong></td><td>High (user-defined)</td><td>Low</td><td>Moderate (can specify links)</td></tr>
<tr>
<td><strong>Context Window</strong></td><td>Large (up to 4 million words)</td><td>Variable, depending on the model</td><td>Limited by search engine capabilities</td></tr>
<tr>
<td><strong>Audio Summaries</strong></td><td>Yes</td><td>No</td><td>No</td></tr>
</tbody>
</table>
</div><p>In summary, NotebookLM distinguishes itself through its focus on source-grounded AI, enabling users to have focused conversations with their own knowledge base. This offers a level of accuracy and privacy not found in ChatGPT or Perplexity, making it a valuable tool for researchers, writers, and anyone seeking to leverage AI with their personal or professional data.</p>
]]></description><link>https://blog.mukundmurali.in/googles-notebooklm-a-second-brain-for-the-ai-age</link><guid isPermaLink="true">https://blog.mukundmurali.in/googles-notebooklm-a-second-brain-for-the-ai-age</guid><category><![CDATA[AI]]></category><category><![CDATA[NotebookLM]]></category><category><![CDATA[note-taking]]></category><dc:creator><![CDATA[Mukund Murali]]></dc:creator></item><item><title><![CDATA[Inbound NAT with Palo Alto in OCI]]></title><description><![CDATA[<p>This topic is with reference in accessing private resources like Load balancer through the untrust Vnic of NVA like Palo Alto. This is a general scenario when we have a firewall like Palo Alto inside OCI for monitoring North-south traffic. Also there are applications inside OCI which needs to be exposed to the internet for internet users to access it and we might need to use a reverse Proxy like Load balancer to expose it.</p>
<p>The problem in this scenario is, For monitoring all the north-south outbound traffic i.e. the egress internet traffic from the instances has to be sent to the Palo Alto so the ingress traffic cannot be directly to the Load balancer via the internet gateway because that would be asymmetric routing as the return traffic will be through Palo Alto. So the ingress traffic has to come through Untrust Vnic of the Palo Alto as that is the exit interface as well.</p>
<h1 id="heading-architecture">Architecture</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706444226752/65feaf31-b6e5-4de1-bfb0-952bf795db3c.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-nat-configuration-inside-palo-alto">NAT Configuration inside Palo Alto</h1>
<p>You can configure a direct D-NAT for this configuration to translate the untrust IP to the load balancer IP but the Palo alto just drops this traffic at the untrust VNIC itself and doesn't capture this traffic. The reason being forward session is not getting created. The solution for this is to create a <strong>SNAT</strong> with the Load balancer as the source and the untrust NIC as NAT IP with <strong>Bi-Directional</strong> checkbox checked.</p>
<h1 id="heading-palo-alto-configuration">Palo Alto Configuration</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706444278167/7e30b801-ce6c-4bba-a94c-649a2e846457.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-create-the-nat-policy">Create the NAT policy :</h2>
<ol>
<li><p>Select <strong>Policies &gt; NAT</strong> and click <strong>Add</strong></p>
</li>
<li><p>On the <strong>General</strong> tab, enter a descriptive <strong>Name</strong> for the NAT rule.</p>
</li>
<li><p>On the <strong>Original Packet</strong> tab, select the zone you created for your DMZ in the <strong>Source Zone</strong> section (click <strong>Add</strong> and then select the zone) and the zone you created for the external network from the <strong>Destination Zone</strong> list.</p>
</li>
<li><p>In the <strong>Source Address</strong> section, <strong>Add</strong> the address object you created for your internal web server address.</p>
</li>
<li><p>On the <strong>Translated Packet</strong> tab, select <strong>Static IP</strong> from the <strong>Translation Type</strong> list in the <strong>Source Address Translation</strong> section and then select the address object you created for your external web server address from the <strong>Translated Address</strong> list.</p>
</li>
<li><p>In the <strong>Bi-directional</strong> field, select <strong>Yes</strong>.</p>
</li>
<li><p>Click <strong>OK</strong>.</p>
</li>
<li><p>Click <strong>Commit</strong>.</p>
</li>
</ol>
<blockquote>
<p>This type of architecture is not limited to OCI and can be applied to other cloud services as well.</p>
</blockquote>
]]></description><link>https://blog.mukundmurali.in/inbound-nat-with-palo-alto-in-oci</link><guid isPermaLink="true">https://blog.mukundmurali.in/inbound-nat-with-palo-alto-in-oci</guid><category><![CDATA[Palo Alto Networks]]></category><category><![CDATA[OCI]]></category><category><![CDATA[Oracle Cloud]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[Mukund Murali]]></dc:creator></item><item><title><![CDATA[Prompt Engineering 101 - Getting Started]]></title><description><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>We already know what ChatGPT or Google's Bard is and how it helps us. In a nutshell, we give an input to these AI models and it gives us an corresponding output. This output can be relatively correct or incorrect to some instances. This depends upon the input we give and this is called the prompt.</p>
<p>The process of creating an efficient prompt is called as prompt engineering.</p>
<p>We will see what are the different types of Prompt Engineering techniques that we can leverage.</p>
<h1 id="heading-prompt-principles">Prompt Principles</h1>
<p>There are 2 principles which we need to take into consideration while working on it.</p>
<ol>
<li><p>Write clear and specific instructions.</p>
<ul>
<li><p>Using Delimiters : Prompting is just like asking a person something, we need to be clear and specific in what we want. In Prompt Engineering we are going to specify this with the help of delimiters (""", ```, &lt; &gt;, &lt;tag&gt;&lt;/tag&gt;) which are basically used to separate the section inside prompt. Delimiters are also used to prevent any kind of prompt injection.</p>
</li>
<li><p>Ask for a structured output.</p>
</li>
<li><p>Check if conditions are met.</p>
</li>
<li><p>Few short prompting, by giving few examples.</p>
</li>
</ul>
</li>
<li><p>Give the model time to think.</p>
<ul>
<li><p>Specify the set of steps to complete a task.</p>
</li>
<li><p>Instruct the model to work out its own solution before rushing to conclusion.</p>
</li>
</ul>
</li>
</ol>
<h1 id="heading-hallucination">Hallucination</h1>
<p>At times there will be scenario where the AI model will give incorrect answers but it never knows that its a wrong answer and the model assumes that this is the correct answer for the prompt given. This is often referred to as Hallucinations in AI.</p>
<h1 id="heading-iterative-process">Iterative Process</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705809795649/23e03b75-197b-494e-92f5-4e31ff0956a7.png" alt class="image--center mx-auto" /></p>
<ul>
<li>Give the idea as prompt.</li>
</ul>
<ul>
<li><p>Understand the output that is generated from that prompt.</p>
</li>
<li><p>Analyze if the desired output is generated or not.</p>
</li>
<li><p>Make the necessary changes in the prompt and re-input it as new prompt.</p>
</li>
</ul>
<h1 id="heading-summarizing-text">Summarizing Text</h1>
<p>Summarizing text prompt is generally used to brief a large set of text in few words to give its complete context. We can summarize a text with respect to specific context as well which later can be used as a email's body. for example: if you get a summary of a overall shipping operation then you can summarize the data with specific key values like the dates mentioned in it.</p>
<h1 id="heading-inferring-learning">Inferring learning</h1>
<p>Its a task where the model takes the input text and analyze it by extracting label and values using prompt engineering.</p>
<h2 id="heading-sentiment-analysis">Sentiment Analysis</h2>
<p>Sentiment analysis is a type of Inferring where you can take a text and understand on what level of emotion that text was written. This is generally used in product review analysis.</p>
<h3 id="heading-zero-shot-learning">Zero-Shot Learning</h3>
<p>In short, Zero-shot learning algorithm is getting an output without giving any example of labelled data to the prompt.</p>
<h3 id="heading-expanding">Expanding</h3>
<p>This is right opposite to what summarize text does, you give a set of instructions or steps to the AI model and the model will generate a large set of text for it. Generally used in generating email messages.</p>
<h1 id="heading-chatbot">Chatbot</h1>
<p>The most exciting use case of the LLM model is to use it to build a customer chatbot and make it act as a customer service agent to answer the questions of user input.</p>
<p>This is achieved with the help of a helper function which says the AI model to have a conversational interaction with the user to store the user inputs in its memory.</p>
<blockquote>
<p>Prompt engineering when used properly will help you extracting the best potential from LLM model and should be used in a responsible way which help in solving real time problems.</p>
</blockquote>
]]></description><link>https://blog.mukundmurali.in/prompt-engineering-101-getting-started</link><guid isPermaLink="true">https://blog.mukundmurali.in/prompt-engineering-101-getting-started</guid><category><![CDATA[#PromptEngineering]]></category><category><![CDATA[llm]]></category><category><![CDATA[chatgpt]]></category><category><![CDATA[bard]]></category><dc:creator><![CDATA[Mukund Murali]]></dc:creator></item></channel></rss>