<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dmitriy Trunov</title>
    <description>The latest articles on DEV Community by Dmitriy Trunov (@dmitriy_trunov_9a09a497b1).</description>
    <link>https://dev.to/dmitriy_trunov_9a09a497b1</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535387%2F39f588b0-8140-4e85-93b8-6946a135a92a.png</url>
      <title>DEV Community: Dmitriy Trunov</title>
      <link>https://dev.to/dmitriy_trunov_9a09a497b1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dmitriy_trunov_9a09a497b1"/>
    <language>en</language>
    <item>
      <title>Two Ways of Knowing: Building an Agentic RAG Explorer for LLM Zoomcamp Capstones.</title>
      <dc:creator>Dmitriy Trunov</dc:creator>
      <pubDate>Mon, 17 Aug 2026 14:37:21 +0000</pubDate>
      <link>https://dev.to/dmitriy_trunov_9a09a497b1/two-ways-of-knowing-building-an-agentic-rag-explorer-for-llm-zoomcamp-capstones-3kpg</link>
      <guid>https://dev.to/dmitriy_trunov_9a09a497b1/two-ways-of-knowing-building-an-agentic-rag-explorer-for-llm-zoomcamp-capstones-3kpg</guid>
      <description>&lt;p&gt;&lt;em&gt;A technical deep-dive into an agentic RAG assistant built for the LLM Zoomcamp 2026 capstone — the architecture, five real production bugs, and what a race-condition stress test taught me about spend caps.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsif1n8kv31oqme1r06cy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsif1n8kv31oqme1r06cy.png" alt=" " width="799" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem with many GitHub repos&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The LLM Zoomcamp 2026 cohort produced over 300 capstone submissions — real RAG projects, each with its own GitHub repo, README, dependency manifest, and a whole course leaderboard score. Browsing that by hand doesn’t scale. So I built a chatbot over the whole corpus to obbtain the all themes, used technology, and library.&lt;/p&gt;

&lt;p&gt;_But the questions people actually ask about a corpus like this split cleanly into two kinds, and they need fundamentally different retrieval:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;”What does project X do? How does it implement reranking?” — a content question. Answer it by finding and grounding on the right README excerpt.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;”Which libraries are most common? What’s the top-scored project? Who’s the leaderboard’s top scorer?” — an aggregation question over the corpus’s structured metadata: score, votes, pass/fail, theme, declared dependencies, each author’s total course score._&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The second category is the interesting one, because it’s exactly where naive RAG quietly breaks. Ask an LLM to “count” or “rank” over a pile of retrieved text chunks, and it will confidently produce a plausible-sounding wrong answer — not because the model is bad, but because counting isn’t a retrieval problem. It’s a database problem wearing a chat interface.&lt;/p&gt;

&lt;p&gt;And there’s a subtler trap hiding in that second category: “top-scored project” and “top of the leaderboard” sound like the same question. They aren’t. A project’s own score and its author’s total course score (homeworks + project + learning-in-public) are genuinely different numbers, and conflating them is a real, plausible failure mode — one I actually hit and had to fix (more on that below).&lt;/p&gt;

&lt;p&gt;Solving this well means routing each question to the right retrieval mechanism, not picking one strategy and forcing every question through it.&lt;/p&gt;

&lt;p&gt;Architecture: one router, two ways of knowing&lt;/p&gt;

&lt;p&gt;The ingestion side is what you’d expect from a RAG pipeline — scrape the listing pages, crawl every submitted repo’s markdown via the GitHub API, chunk by heading, cache everything to disk. Theme and tech-stack classification run as OpenAI Batch API jobs (bulk, offline, ~50% cheaper than synchronous calls) rather than one API call per project in the hot path.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr4915bdesac5xohpelsq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr4915bdesac5xohpelsq.png" alt=" " width="800" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The interesting part is the runtime query path. Instead of one retrieval strategy, there’s an agentic router sitting in front of two completely different tools: &lt;code&gt;search_docs&lt;/code&gt; (hybrid keyword+vector search, RRF-fused, cross-encoder reranked, LLM-query-rewritten) and eleven parameterized, hand-written SQL functions-never LLM-generated SQL.&lt;/p&gt;

&lt;p&gt;A “which libraries are most common” question never touches the model’s judgment about counting. It runs &lt;code&gt;COUNT(*) … GROUP BY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwpk2o6nlnl4c4294jdve.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwpk2o6nlnl4c4294jdve.png" alt=" " width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why an agentic router, not “just RAG plus a calculator tool”?&lt;/p&gt;

&lt;p&gt;The tool-calling loop itself is unremarkable — it’s the same shape as any OpenAI function-calling agent: feed the model a question and a set of tool schemas, let it pick zero or more tools, feed the results back, repeat until it produces a final answer instead of another tool call.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_turn&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_turns&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;llm_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;input_items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_tool_schemas&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;function_calls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;function_call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;function_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sources&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;all_sources&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tool_calls_log&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# ... execute each function_call, append results, loop again
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What actually matters is what’s in those eleven tool schemas — specifically, how much implicit intent you have to make explicit before the model reliably picks it up. Here’s a real example from this project. &lt;code&gt;most_common_libraries&lt;/code&gt; takes an optional &lt;code&gt;filter_top_scored_n&lt;/code&gt; parameter that restricts the aggregation to the top-N scored projects instead of the whole corpus. The first version of its description just documented what the parameter did. Ask “what are the most common libraries among the top-scored projects?” and the model would call the tool — but leave &lt;code&gt;filter_top_scored_n&lt;/code&gt; unset, silently answering for the entire corpus instead of the subset the question actually asked about. The count was real, correctly computed, exactly matching the SQL — and still the wrong answer, because it answered a different question than the one asked.&lt;/p&gt;

&lt;p&gt;The fix wasn’t code. It was making the qualifier explicit in the tool description itself:&lt;/p&gt;

&lt;p&gt;IMPORTANT: if the question says ‘top-scored’, ‘top projects’, ‘best projects’, or similar, you MUST set &lt;code&gt;filter_top_scored_n&lt;/code&gt; — leaving it null answers for ALL projects instead, which is a different (wrong) answer to that question.&lt;/p&gt;

&lt;p&gt;Tool descriptions are prompts. Implicit qualifiers a human reader would catch instantly — ‘top-scored’, clearly means ‘restrict the scope’, — need to be spelled out just as explicitly as any other instruction, or the model will happily run the wrong exact query with complete confidence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Five bugs that actually happened:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Everything above is the design that looks right on a whiteboard. Here’s what broke in practice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. CUDA wheels on a code path that never touches a GPU&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every embedding call in this project forces &lt;code&gt;device=”cpu”&lt;/code&gt; explicitly, in code, everywhere — &lt;code&gt;sentence-transformers&lt;/code&gt; on CPU, &lt;code&gt;CrossEncoder&lt;/code&gt; reranking on CPU. And yet &lt;code&gt;uv sync&lt;/code&gt; was still resolving &lt;code&gt;torch&lt;/code&gt;’s full CUDA build by default: &lt;code&gt;cuda-bindings&lt;/code&gt;, &lt;code&gt;cuda-toolkit&lt;/code&gt;, half a dozen &lt;code&gt;nvidia-*&lt;/code&gt; packages — several gigabytes of GPU tooling for a code path that never runs on a GPU, on any platform, including ARM (the &lt;code&gt;cuda-toolkit&lt;/code&gt; extras aren’t gated to exclude &lt;code&gt;aarch64&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The fix is a standard &lt;code&gt;uv&lt;/code&gt; pattern most people don’t reach for until it bites them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;
&lt;span class="nn"&gt;[tool.uv.sources]&lt;/span&gt;
&lt;span class="py"&gt;torch&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="py"&gt;index&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"pytorch-cpu"&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nn"&gt;[[tool.uv.index]]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"pytorch-cpu"&lt;/span&gt;
&lt;span class="py"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://download.pytorch.org/whl/cpu"&lt;/span&gt;
&lt;span class="py"&gt;explicit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One subtlety: this silently did nothing until &lt;code&gt;torch&lt;/code&gt; was also listed as a direct dependency in &lt;code&gt;pyproject.toml&lt;/code&gt;, not just a transitive one pulled in via &lt;code&gt;sentence-transformers&lt;/code&gt;. Once it was explicit, re-locking dropped 18 CUDA/nvidia/triton packages from &lt;code&gt;uv.lock&lt;/code&gt;, and &lt;code&gt;uv sync&lt;/code&gt; actually uninstalled them from the local environment. Smaller image, faster builds, no wasted disk on a code path that was never going to touch a GPU.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A killed connection took the whole app down until restart&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The router keeps one Postgres connection open for the process’s entire lifetime — avoiding a fresh-connection-per-query cost for a chat app that might field hundreds of questions. That’s a reasonable optimization, and it worked fine until a killed backend connection (&lt;code&gt;psycopg.errors.AdminShutdown&lt;/code&gt;) took down every subsequent query_projects call until the whole process was manually restarted. One dead connection, and the assistant stopped answering any structured question for anyone.&lt;/p&gt;

&lt;p&gt;The fix was reconnect-and-retry-once logic wrapped around every SQL tool call. But there was a second, quieter bug hiding underneath it: every one of those SQL tools is a read-only &lt;code&gt;SELECT&lt;/code&gt; that never calls &lt;code&gt;.commit()&lt;/code&gt;, and Postgres’s default &lt;code&gt;autocommit=False&lt;/code&gt; means each one silently opens a transaction that never closes. Left alone, the shared connection accumulates “idle in transaction” state — which then blocks unrelated &lt;code&gt;DROP TABLE&lt;/code&gt; statements running elsewhere in the same database. It happened twice before the pattern was obvious. The real fix was one line: roll back (never commit — nothing was written) after every single tool call, closing the implicit transaction immediately instead of leaving it open indefinitely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Three judge false-negatives, one root cause&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The live chat has an LLM-as-judge step that scores every answer’s relevance against the context it was actually grounded in. Three separate times, it flagged a correct answer as unsupported, and all three traced back to the same underlying mistake: the judge was being shown a derived view of the grounding data, not the real thing.&lt;/p&gt;

&lt;p&gt;Round one: aggregation answers (no retrieved document chunks) were judged against a hardcoded empty context string, so every purely-SQL-grounded answer looked ungrounded by construction. Round two: after fixing that by building context from the &lt;code&gt;sources&lt;/code&gt; list, a &lt;code&gt;score&lt;/code&gt;-only field left the judge unable to verify an &lt;code&gt;author_total_score&lt;/code&gt; field the answer legitimately cited, because that field simply wasn’t in the sources view. Round three, the sharpest one: aggregation-only tool results (a library count, say) have no &lt;code&gt;github_url&lt;/code&gt; to become a &lt;code&gt;sources&lt;/code&gt; entry — correctly, there’s nothing to link to — but that left the judge with nothing at all to check a fully correct count against, so it flagged genuinely accurate answers as hallucinated.&lt;/p&gt;

&lt;p&gt;All three converged on the same fix: stop trying to derive judge context from a UI-facing view of the answer (the sources list), and instead hand the judge the actual tool-call results the answering model itself saw — the real data, not a lossy projection of it built for a different purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The budget-cap race condition&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Write on Medium&lt;br&gt;
This is the one I’m proudest of catching before it mattered in production, because the naive version looked completely reasonable.&lt;/p&gt;

&lt;p&gt;A public demo needs a hard spend cap — otherwise it’s a free, unlimited ChatGPT proxy to anyone with the URL. The first version did the obvious thing: read the total spent so far from Postgres, compare it to the cap in Python, and only call the LLM if there was room left.&lt;/p&gt;

&lt;p&gt;That’s a classic time-of-check-to-time-of-use race. Under concurrent traffic, every simultaneous request reads “total is under the cap” before any of them commits their own cost. With enough concurrent visitors, the real total can blow straight past the cap — a $0.05 limit could, in the worst case, cost many times that if enough requests land in the same window.&lt;/p&gt;

&lt;p&gt;The fix replaces “read, compare, spend” with one atomic Postgres operation — a conservative reservation made before the LLM call, not a check made after:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;try_reserve_budget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RESERVATION_USD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
                UPDATE budget_ledger
                SET total_spent = total_spent + %s
                WHERE id = 1 AND total_spent + %s &amp;lt;= %s
                RETURNING total_spent
                &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because a turn’s real cost isn’t known until after the LLM responds, this reserves a conservative fixed upper bound up front and trues it up to the real cost afterward (or fully refunds it if the call fails) — but the cap enforcement itself is a single atomic &lt;code&gt;UPDATE … WHERE … RETURNING&lt;/code&gt;, which Postgres serializes across concurrent transactions the same way it serializes any other concurrent row update. There’s no gap between “check” and “spend” for a race to land in.&lt;/p&gt;

&lt;p&gt;I didn’t just reason about this — I stress-tested it against the real database. Fifty concurrent reservation attempts against a $0.05 cap, with $0.01 reservations:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;concurrent attempts: 50&lt;br&gt;
succeeded reservations: 5&lt;br&gt;
final ledger total: $0.0500 (cap was $0.05)&lt;br&gt;
PASS: ledger never exceeded the cap under concurrency&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Exactly five succeeded. The ledger landed at exactly the cap, not a cent over. The naive read-then-check version would have let far more than five through under the same load.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. The disk-exhaustion saga that took two fixes to actually fix&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Deploying to a small (2GB RAM, 20GB disk) EC2 instance, &lt;code&gt;docker compose up — build&lt;/code&gt; failed with “no space left on device” mid-build. The instance had 8GB free at the time — that should have been plenty for one ~1.6GB Python image.&lt;/p&gt;

&lt;p&gt;The first diagnosis looked right: &lt;code&gt;docker-compose.yaml&lt;/code&gt; built five separate images from the identical Dockerfile (one per service — &lt;code&gt;init-db&lt;/code&gt;, &lt;code&gt;load-projects&lt;/code&gt;, &lt;code&gt;build-index&lt;/code&gt;, &lt;code&gt;streamlit&lt;/code&gt;, &lt;code&gt;dashboard&lt;/code&gt;), each independently unpacking a multi-GB layer in parallel. Giving all five services a shared &lt;code&gt;image:&lt;/code&gt; tag seemed like the obvious fix — one name instead of five.&lt;/p&gt;

&lt;p&gt;It wasn’t enough. The retry failed with the exact same error. Compose was still building and exporting the image once per service definition, just landing on the same final tag — five redundant multi-gigabyte export operations racing for disk, instead of five distinct named images. The tag was shared; the work wasn’t.&lt;/p&gt;

&lt;p&gt;The actual fix: only one service keeps a &lt;code&gt;build:&lt;/code&gt; block. The other four reference the same &lt;code&gt;image:&lt;/code&gt; with no &lt;code&gt;build:&lt;/code&gt; of their own. Compose’s build phase — triggered by &lt;code&gt;— build&lt;/code&gt; — runs to completion for every service that owns a &lt;code&gt;build:&lt;/code&gt; block before it starts any containers at all; &lt;code&gt;depends_on&lt;/code&gt; only orders container start, not the build phase. So by the time the other four services start, the image the first one built already exists on disk, and they just use it — no rebuild attempted, no redundant export.&lt;/p&gt;

&lt;p&gt;The lesson, generalized past Docker: when a fix makes the symptom go away sometimes but the same failure mode returns under slightly different conditions, look for whether you actually eliminated the redundant work, or just gave the redundant work a nicer name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evaluating an agentic router&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Retrieval-quality evaluation for a fixed single-strategy RAG pipeline is well-trodden: hit-rate, MRR, precision@k against a ground-truth question set. An agentic router adds a layer on top of that — it’s not just “did retrieval find the right chunk,” it’s “did the router pick the right tool.”&lt;/p&gt;

&lt;p&gt;This project runs two evaluations at different depths. The deep one — comparing &lt;code&gt;keyword&lt;/code&gt;/&lt;code&gt;vector&lt;/code&gt;/&lt;code&gt;hybrid&lt;/code&gt;/&lt;code&gt;hybrid+rerank&lt;/code&gt; retrieval strategies and two answer-generation prompts against an LLM-generated ground-truth set, via the Batch API — is fully scaffolded but wasn’t run for this write-up; it needs a real API key budget I hadn’t allocated yet. No numbers invented to fill that gap.&lt;/p&gt;

&lt;p&gt;The one that did run is faster and, in practice, more useful day to day: a 30-question smoke eval, running every question from the app’s own example-questions sidebar through the live assistant — real retrieval, real SQL, real LLM calls — judged the same way a live chat turn is judged. It’s a regression check on the router’s tool-routing, not a substitute for the deeper eval, and it re-runs in under three minutes:&lt;/p&gt;

&lt;p&gt;30 questions — RELEVANT: 30 PARTLY_RELEVANT: 0 NON_RELEVANT: 0 missing: 0&lt;/p&gt;

&lt;p&gt;relevance_score: 1.0 | total cost: $0.0248 | avg response time: 5.64s&lt;/p&gt;

&lt;p&gt;This eval set earned its keep twice during development — it’s what caught the &lt;code&gt;filter_top_scored_n&lt;/code&gt; bug above, and separately caught a one-shot Docker Compose loader container silently reverting an &lt;code&gt;author_total_score&lt;/code&gt; field to NULL after a stale image was reused. A fast, always-current smoke eval that’s genuinely wired into your deploy process catches real regressions a slower, less-frequently-run ground-truth suite won’t.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardening for a public demo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Three small features made the difference between “a demo I can run locally” and “a demo I can actually hand someone a URL for”:&lt;/p&gt;

&lt;p&gt;A production flag that hides the ingestion trigger from public visitors — nobody browsing a public demo should be able to kick off a live re-crawl of 278 GitHub repos.&lt;br&gt;
The atomic budget cap described above.&lt;br&gt;
Answer-from-history caching: an exact-match repeat of a previously-asked question (unsurprisingly common when people click the same example question twice) answers instantly from the logged prior turn — no new LLM call, no new cost, and no budget reservation at all, since nothing is actually being spent.&lt;br&gt;
None of these are exotic. All three are the kind of thing that’s easy to skip when a project is “just a demo” — right up until it’s a public URL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What generalizes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A few things from this build feel true beyond this specific project:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tool descriptions are prompts, not documentation. An implicit qualifier a human reader catches instantly — “top-scored” clearly means “restrict the scope” — has to be spelled out as explicitly as any other instruction, or the model will run the &lt;em&gt;wrong&lt;/em&gt; exact query with complete confidence and no visible error.&lt;/li&gt;
&lt;li&gt;A judge needs the real grounding data, not a UI-shaped view of it. Every judge false-negative in this project traced back to feeding the judge something derived from the actual answer-generation context, built for a different purpose (usually, rendering source links), rather than the real tool output the answering model itself saw.&lt;/li&gt;
&lt;li&gt;Anything with a spend cap under concurrent traffic needs an atomic reservation, not a read-then-check. This is true well beyond LLM cost caps — any shared, capped resource checked by “read the total, compare, then act” has the same race, and it’s worth stress-testing with real concurrent load, not just reasoning about it on paper.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code is on &lt;a href="https://github.com/dim2e3/RAG-llm-zoomcamp-explorer" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;: &lt;/p&gt;

&lt;p&gt;Built as a capstone project for &lt;a href="https://github.com/DataTalksClub/llm-zoomcamp" rel="noopener noreferrer"&gt;[LLM Zoomcamp]&lt;/a&gt; 2026 cohort&lt;/p&gt;

</description>
      <category>rag</category>
      <category>ai</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>Begin your journey with Amazon Q Developer</title>
      <dc:creator>Dmitriy Trunov</dc:creator>
      <pubDate>Sun, 28 Sep 2025 19:07:04 +0000</pubDate>
      <link>https://dev.to/dmitriy_trunov_9a09a497b1/begin-your-journey-with-amazon-q-developer-4dp</link>
      <guid>https://dev.to/dmitriy_trunov_9a09a497b1/begin-your-journey-with-amazon-q-developer-4dp</guid>
      <description>&lt;p&gt;Last year, we heard too much about AI and AI technology. Names such as &lt;em&gt;ChatGPT, Claude&lt;/em&gt;, and &lt;em&gt;Deepseek&lt;/em&gt; are well-known in the internet community. Many people don't see themselves without their hints and help in everyday life. &lt;/p&gt;

&lt;p&gt;Almost all software developers are using tools like &lt;em&gt;Copilot&lt;/em&gt;, &lt;em&gt;Cursor&lt;/em&gt;, and &lt;em&gt;Windsurf&lt;/em&gt; in their working routines. However, in the development community, I encountered the ignorance of one tool that is worth paying attention to.&lt;br&gt;
This tool is named &lt;strong&gt;"Amazon Q Developer"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A former &lt;em&gt;Amazon&lt;/em&gt; product, "&lt;em&gt;CodeWhisperer&lt;/em&gt;", became a part of &lt;strong&gt;Amazon Q Developer&lt;/strong&gt;. It is a generative artificial intelligence (AI) powered conversational assistant that can help you understand, build, extend, and operate software applications. This product was made generally available on &lt;strong&gt;April 30, 2024&lt;/strong&gt;. Over the years of constant development and improvement, it has received many improvements and updates. It was full integration into the &lt;em&gt;AWS&lt;/em&gt; ecosystem, with major updates and milestones occurring throughout 2025. &lt;strong&gt;Amazon Q Developer&lt;/strong&gt; is built on &lt;em&gt;Amazon Bedrock&lt;/em&gt; and includes automated abuse detection implemented in &lt;em&gt;Amazon Bedrock&lt;/em&gt; to enforce safety, security, and the responsible use of AI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amazon Q&lt;/strong&gt; was provided in two versions - &lt;strong&gt;Amazon Q CLI&lt;/strong&gt; and &lt;strong&gt;Amazon Q extension&lt;/strong&gt; for development tools such as &lt;em&gt;Visual Studio Code&lt;/em&gt; and &lt;em&gt;JetBrains IDE&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's start with Amazon Q Developer extension for free.
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To do this, go to the website [AWS Skill Builder]&lt;a href="https://skillbuilder.aws/" rel="noopener noreferrer"&gt;https://skillbuilder.aws/&lt;/a&gt; and create a free &lt;strong&gt;AWS Builder ID&lt;/strong&gt; (no AWS account required).&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0tktg7b220c7hv1x2353.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0tktg7b220c7hv1x2353.png" alt="Create AWS SkillBuilder account" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Today, we are planning to start using &lt;strong&gt;Amazon Q&lt;/strong&gt; as an &lt;em&gt;IDE&lt;/em&gt; extension. I think you already have something installed on your computer. Download the extension for Visual Studio Code. Install the Amazon Q extension in VS Code.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1085wzzom1m5ozn961e0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1085wzzom1m5ozn961e0.png" alt="Install Amazon Q developer extentsion" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This procedure does not require you to have a &lt;em&gt;Builder ID&lt;/em&gt;. If you have not yet signed up for &lt;em&gt;Builder ID&lt;/em&gt;, you will have the opportunity to do so during the sign-in process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmvsq7rydka2bhiuasfpv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmvsq7rydka2bhiuasfpv.png" alt="Sign in with AWS SkillBuilder account" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose the &lt;strong&gt;Amazon Q&lt;/strong&gt; icon in your &lt;em&gt;IDE&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The icon will be on the side of the interface by default.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbvz4pfz871oz1wykqvt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbvz4pfz871oz1wykqvt.png" alt="Amazon Q developer icon" width="800" height="653"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow the instructions in your browser to authenticate with &lt;em&gt;Builder ID&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To begin using Amazon Q, choose the Amazon Q icon to chat with Amazon Q, or choose Amazon Q from the navigation bar at the bottom of your &lt;em&gt;IDE&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7mkhiydepda91dwtsbkn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7mkhiydepda91dwtsbkn.png" alt="Chat with Amazon Q Developer" width="800" height="1498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Nowadays, many developers are bound by NDA rules and are concerned that their code may end up on the other side. I came across a situation where some very experienced Amazon Q users don't know some subtleties of these settings. Let's tune some extension settings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25xj3nlfxt54re062trn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25xj3nlfxt54re062trn.png" alt="Amazon Q extension settings" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This setting allows you to customize the ability to send tracking information in AWS&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqase2gr6ifqn1udnmg3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqase2gr6ifqn1udnmg3.png" alt="Share Content with AWS" width="800" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpishvov9h0h896aprjs8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpishvov9h0h896aprjs8.png" alt="Send to AWS Telemetry" width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's explore some additional settings related to context. This is the most important part of &lt;strong&gt;Amazon Q Developer&lt;/strong&gt; that allows us to use our own context to provide AI with the most relevant questions.&lt;br&gt;
The local workspace context created by these settings helps Amazon Q deliver more accurate answers and speed up the work capabilities. Amazon Q maintains the context of your conversation within a given session to inform future responses. You can ask follow-up questions or refer to previous questions and responses throughout the duration of your session. To start a new conversation with Amazon Q, open a new tab in the panel. You can open up to 10 tabs at a time. Amazon Q doesn't retain context across different conversations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyw6ctcvgukpi1vl53gpl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyw6ctcvgukpi1vl53gpl.png" alt="Workspace Context" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can ask Amazon Q questions, update your code, and initiate actions with quick commands all from the Amazon Q chat panel in your IDE.&lt;/p&gt;

&lt;p&gt;To start chatting with Amazon Q, choose the Amazon Q icon from the navigation bar in your IDE and enter your question in the text bar. To start chatting with Amazon Q in Visual Studio, choose View from the main menu and then choose Amazon Q chat.&lt;/p&gt;

&lt;p&gt;When you ask Amazon Q a question, it uses the current file that is open in your IDE as context, including the programming language and the file path.&lt;/p&gt;

&lt;p&gt;If Amazon Q includes code in its response, you can copy the code or insert it directly into your file by choosing Insert at cursor. Amazon Q might include inline references to its sources in its response. To view a list of sources, expand the Sources section at the bottom of a response.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Chat commands&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can enter the following commands in the chat panel to access Amazon Q features, depending on your IDE.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmafjrw4lqy0f3q8zfo8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmafjrw4lqy0f3q8zfo8.png" alt="Amazon Q developer Chat Commands" width="726" height="1554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/transform&lt;/code&gt; - Use this command to update the code language version of an entire project. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;/dev&lt;/code&gt; - Use this command to get an implementation plan to develop a feature. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;/test&lt;/code&gt; - Use this command to generate unit tests for your code.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/review&lt;/code&gt; - Use this command to review your codebase for security vulnerabilities and code quality issues. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;/doc&lt;/code&gt; - Use this command to generate READMEs for your project base.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/clear&lt;/code&gt; - Use this command to clear a current conversation. This removes all previous conversations from the chat panel and clears the context that Amazon Q has about your previous conversation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/compact&lt;/code&gt; - Use this command to compact your chat history when the context window approaches its capacity limit. This creates a concise summary of your conversation while preserving essential information.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/help&lt;/code&gt; - Use this command to see an overview of what Amazon Q can and can't do, example questions, and quick commands&lt;/p&gt;

&lt;p&gt;Try out the &lt;strong&gt;Amazon Q developer&lt;/strong&gt; capabilities and share your first impressions. &lt;/p&gt;

&lt;p&gt;In the next articles, I will try to contribute to you some advanced interaction techniques with &lt;strong&gt;Amazon Q Developer&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
