{"id":2911,"date":"2025-10-21T01:21:46","date_gmt":"2025-10-21T01:21:46","guid":{"rendered":"https:\/\/blog.samarthya.me\/wps\/?p=2911"},"modified":"2025-10-21T01:21:48","modified_gmt":"2025-10-21T01:21:48","slug":"building-a-minimal-langchain-ollama-demo","status":"publish","type":"post","link":"https:\/\/blog.samarthya.me\/wps\/2025\/10\/21\/building-a-minimal-langchain-ollama-demo\/","title":{"rendered":"Building a Minimal LangChain + Ollama Demo"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full is-style-rounded\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/blog.samarthya.me\/wps\/wp-content\/uploads\/2025\/10\/llm-1.png\" alt=\"\" class=\"wp-image-2912\" srcset=\"https:\/\/blog.samarthya.me\/wps\/wp-content\/uploads\/2025\/10\/llm-1.png 1024w, https:\/\/blog.samarthya.me\/wps\/wp-content\/uploads\/2025\/10\/llm-1-150x150@2x.png 300w, https:\/\/blog.samarthya.me\/wps\/wp-content\/uploads\/2025\/10\/llm-1-150x150.png 150w, https:\/\/blog.samarthya.me\/wps\/wp-content\/uploads\/2025\/10\/llm-1-300x300@2x.png 600w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>This post walks through a tiny, practical example that uses <code>LangChain<\/code> primitives and a local <code>Ollama <\/code>server to run a prompt-based summarization. The project is intentionally small so you can learn the core ideas quickly: extracting prompts, initializing an LLM client, composing a chain, and running it locally.<\/p>\n\n\n\n<p>Repository used in this post:\u00a0<code><a href=\"https:\/\/github.com\/samarthya\/langchain-ollama-tutorial.git\" data-type=\"link\" data-id=\"https:\/\/github.com\/samarthya\/langchain-ollama-tutorial.git\">llangchain-tutorial<\/a><\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-youll-learn\">What you&#8217;ll learn<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>How to separate prompts from code for rapid iteration.<\/li>\n\n\n\n<li>How to initialize and call a local <code>Ollama <\/code>server from Python using\u00a0<code>ChatOllama<\/code>.<\/li>\n\n\n\n<li>The basics of composing a LangChain chain: PromptTemplate | LLM.<\/li>\n\n\n\n<li>How to structure code for clarity and reusability.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"why-use-a-local-runtime-ollama\">Why use a local runtime (Ollama)?<\/h2>\n\n\n\n<p>Local runtimes like Ollama let you iterate quickly without network latency and without sending data to a cloud provider \u2014 useful for testing, privacy, and cost control. In this demo we use Ollama as the model host and&nbsp;<code>ChatOllama<\/code>&nbsp;from the&nbsp;<code>langchain_ollama<\/code>&nbsp;integration to talk to it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"project-walkthrough\">Project walkthrough<\/h2>\n\n\n\n<p>Files we care about:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>main.py<\/code>\u00a0\u2014 entrypoint and orchestrator<\/li>\n\n\n\n<li><code>prompts\/summary_template.txt<\/code>\u00a0\u2014 extracted prompt template<\/li>\n\n\n\n<li><code>README.md<\/code>\u00a0\u2014 run instructions and a Mermaid flowchart<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"core-idea\">Core idea<\/h3>\n\n\n\n<p><code>main.py<\/code>&nbsp;follows a simple pattern:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Load environment variables (<code>OLLAMA_HOST<\/code>,\u00a0<code>OLLAMA_PORT<\/code>).<\/li>\n\n\n\n<li>Load a prompt template from\u00a0<code>prompts\/summary_template.txt<\/code>.<\/li>\n\n\n\n<li>Initialize a\u00a0<code>ChatOllama<\/code>\u00a0client using the host and port.<\/li>\n\n\n\n<li>Build a chain by composing a PromptTemplate with the LLM (<code>PromptTemplate(...) | llm<\/code>).<\/li>\n\n\n\n<li>Invoke the chain with\u00a0<code>chain.invoke(input={\"information\": information})<\/code>\u00a0and print the response.<\/li>\n<\/ol>\n\n\n\n<p>Keeping the prompt in a file makes it easy for non-developers to tweak the prompt text without touching code. The helper functions in&nbsp;<code>main.py<\/code>&nbsp;(<code>load_prompt<\/code>,&nbsp;<code>init_ollama_llm<\/code>,&nbsp;<code>build_chain<\/code>) make each step testable and reusable.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"prompt-template\">Prompt template<\/h3>\n\n\n\n<p>The prompt is intentionally simple and lives in&nbsp;<code>prompts\/summary_template.txt<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Given the information {information}, about the person I want you to create:\n    1. A short summary\n    2. Two interesting facts about them.\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"key-snippet-building-and-invoking-the-chain\">Key snippet: building and invoking the chain<\/h3>\n\n\n\n<pre class=\"wp-block-code has-luminous-vivid-amber-background-color has-background\"><code><em># load prompt<\/em>\nprompt_text = load_prompt(\"prompts\/summary_template.txt\")\n\n<em># init llm<\/em>\nllm = init_ollama_llm()\n\n<em># compose chain<\/em>\nchain = build_chain(prompt_text, &#91;\"information\"], llm)\n\n<em># invoke<\/em>\nresponse = chain.invoke(input={\"information\": information})\nprint(response.content)\n<\/code><\/pre>\n\n\n\n<p>Note: The keys in the&nbsp;<code>input<\/code>&nbsp;dict must match the&nbsp;<code>input_variables<\/code>&nbsp;declared when creating the PromptTemplate. Passing a different key (e.g.,&nbsp;<code>\"info\"<\/code>) without updating the template will raise a missing-variable error.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"how-to-run-the-demo\">How to run the demo<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Copy the env example and edit if necessary:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code has-black-color has-luminous-vivid-amber-background-color has-text-color has-background has-link-color wp-elements-f00885c2c3799ea0c79d90978ea168ea\"><code>cp .env.example .env\n<\/code><\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>Create a virtual environment and install dependencies:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code has-luminous-vivid-amber-background-color has-background\"><code>python -m venv .venv\nsource .venv\/bin\/activate\npip install -r requirements.txt\n<\/code><\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>Ensure Ollama is running and reachable (default:\u00a0<code>localhost:11434<\/code>). You can check:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code has-luminous-vivid-amber-background-color has-background\"><code>curl http:\/\/localhost:11434\/api\/models\ncurl http:\/\/localhost:11434\/api\/tags\n<\/code><\/pre>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li>Run the example:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code has-luminous-vivid-amber-background-color has-background\"><code>python main.py\n<\/code><\/pre>\n\n\n\n<p>You should see a short printed summary and two facts derived from the&nbsp;<code>information<\/code>&nbsp;sample in the repo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"common-pitfalls-and-debugging\">Common pitfalls and debugging<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Prompt variable mismatch: ensure the dict keys you pass to\u00a0<code>chain.invoke<\/code>\u00a0match the PromptTemplate&#8217;s\u00a0<code>input_variables<\/code>.<\/li>\n\n\n\n<li>Ollama connectivity: if the server isn&#8217;t running,\u00a0<code>curl<\/code>\u00a0the endpoints above and verify the host\/port.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"next-steps-and-experiments\">Next steps and experiments<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Add memory to the chain to keep conversation context across invocations.<\/li>\n\n\n\n<li>Swap\u00a0<code>ChatOllama<\/code>\u00a0for another provider (OpenAI, Anthropic) to compare behavior.<\/li>\n\n\n\n<li>Add unit tests: validate\u00a0<code>load_prompt<\/code>\u00a0and use a mocked LLM to ensure the prompt is formatted correctly.<\/li>\n\n\n\n<li>Create a small web UI to let users paste text and see summarization results.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<\/h2>\n\n\n\n<p>This project shows how to structure a small LangChain-based demo that talks to a local LLM runtime. The key takeaways are: keep prompts separate, build small reusable helpers, and use local runtimes for fast iteration.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This post walks through a tiny, practical example that uses LangChain primitives and a local Ollama server to run a prompt-based summarization. The project is intentionally small so you can learn the core ideas quickly: extracting prompts, initializing an LLM client, composing a chain, and running it locally. Repository used in this post:\u00a0llangchain-tutorial What you&#8217;ll [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":2913,"comment_status":"open","ping_status":"open","sticky":false,"template":"elementor_header_footer","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"categories":[34],"tags":[350,351,327],"class_list":["post-2911","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technical","tag-langchain","tag-llm","tag-ollama"],"_links":{"self":[{"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/posts\/2911","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/comments?post=2911"}],"version-history":[{"count":1,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/posts\/2911\/revisions"}],"predecessor-version":[{"id":2914,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/posts\/2911\/revisions\/2914"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/media\/2913"}],"wp:attachment":[{"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/media?parent=2911"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/categories?post=2911"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/tags?post=2911"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}