{"id":25805673,"url":"https://github.com/scriptogre/functional-chatbots","last_synced_at":"2026-03-13T00:33:05.278Z","repository":{"id":242022270,"uuid":"808261761","full_name":"scriptogre/functional-chatbots","owner":"scriptogre","description":"The repository for the Functional LLM Chatbots workshop from DjangoCon Europe 2024.","archived":false,"fork":false,"pushed_at":"2024-08-25T14:05:11.000Z","size":19430,"stargazers_count":15,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"0-start-here","last_synced_at":"2025-09-29T00:29:35.550Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scriptogre.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-30T17:49:23.000Z","updated_at":"2025-04-26T19:24:28.000Z","dependencies_parsed_at":"2025-02-27T20:14:09.864Z","dependency_job_id":"803a9707-26b9-44d8-b2da-aa5a78eb499f","html_url":"https://github.com/scriptogre/functional-chatbots","commit_stats":null,"previous_names":["scriptogre/functional-chatbots"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/scriptogre/functional-chatbots","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptogre%2Ffunctional-chatbots","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptogre%2Ffunctional-chatbots/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptogre%2Ffunctional-chatbots/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptogre%2Ffunctional-chatbots/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scriptogre","download_url":"https://codeload.github.com/scriptogre/functional-chatbots/tar.gz/refs/heads/0-start-here","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptogre%2Ffunctional-chatbots/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30451595,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-12T21:31:01.033Z","status":"ssl_error","status_checked_at":"2026-03-12T21:30:43.161Z","response_time":114,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-02-27T19:39:15.797Z","updated_at":"2026-03-13T00:33:05.255Z","avatar_url":"https://github.com/scriptogre.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Functional Chatbots - DjangoCon Europe 2024\n\n\u003cimg src=\"https://cdn.jsdelivr.net/gh/scriptogre/functional-chatbots-assets@main/0-start-here/application_final_version.gif\" width=800 alt=\"Showcase\"/\u003e\n\n`README.md` contains: \n- Setup instructions\n- Project details (tools, project structure)\n\n`PROGRESS.md` includes:\n- Task at hand\n- Some context\n- Extra challenges\n- Next steps\n\n**Note**: Read the `PROGRESS.md` file every time you switch branches.\n\n# Requirements\n\n### Tools\n\n- [Git](https://git-scm.com/downloads) (to clone the repository)\n- [Docker Desktop](https://www.docker.com/products/docker-desktop/)\n- [Python (if not using Docker)](https://www.python.org/downloads/)\n- GroqCloud [account](https://console.groq.com/login) and [API key](https://console.groq.com/keys) (Free access to LLama 3)\n\n### Knowledge\n\nThis workshop will be easier for you if you're familiar with:\n- Django\n- HTMX\n- OpenAI's API\n- TailwindCSS\n\nI tried to keep things simple, but there are lots to cover in only 50 minutes.\n\n# Getting Started\n\n1. Clone the repository:\n    ```\n    git clone https://github.com/scriptogre/functional-chatbots.git\n    ```\n2. Rename `.env.example` to `.env`\n3. Update `GROQ_API_KEY` with your GroqCloud API key \n4. Run `docker compose up` to start the project\n5. Open browser at `http://localhost:8000`\n\n# Project Structure\n\n**Warning:** This project is unconventional. Enjoy the ride!\n\n# Django-Ninja\n\n\u003ca href=\"https://django-ninja.dev/\"\u003e\n    \u003cimg src=\"https://cdn.jsdelivr.net/gh/scriptogre/functional-chatbots-assets@main/0-start-here/django_ninja.webp\" alt=\"Django-Ninja\" width=700 /\u003e\n\u003c/a\u003e\n\n\u003e Wait, what?! You want to render templates with Django-Ninja?\n\n### Why Django-Ninja?\n\nWhy not?\n\n1. **It's less verbose**, with intuitive syntax inspired by FastAPI.\n2. **It's more performant**, thanks to being  built on top of Starlette.\n3. **It's still Django**, so we can benefit from the included batteries when needed.\n\nBesides, it uses **Pydantic**.\n\n[Instructor](https://python.useinstructor.com/) also uses Pydantic. This will come in handy later.\n\n# htmx\n\n\u003ca href=\"https://htmx.org\"\u003e\n    \u003cimg src=\"https://cdn.jsdelivr.net/gh/scriptogre/functional-chatbots-assets@main/0-start-here/htmx.webp\" alt=\"HTMX\" width=700/\u003e\n\u003c/a\u003e\n\nWe'll use [htmx](https://htmx.org/) to easily add interactivity to our project, like updating chat messages, or\ncreating/updating/deleting pizza orders - without writing any JavaScript.\n\n### Why htmx?\n\n\u003ca href=\"https://grugbrain.dev/\"\u003e\n    \u003cimg src=\"https://cdn.jsdelivr.net/gh/scriptogre/functional-chatbots-assets@main/0-start-here/grug.webp\" alt=\"Grug Brain Developer\" width=200/\u003e\n\u003c/a\u003e\n\n\u003e Grug from [The Grug Brained Developer](https://grugbrain.dev/) by Carson Gross (creator of [htmx](https://htmx.org/)). Love the article.\n\ncomplexity _bad_\n\n# JinjaX\n\n\u003ca href=\"https://jinjax.scaletti.dev/\"\u003e  \n    \u003cimg src=\"https://cdn.jsdelivr.net/gh/scriptogre/functional-chatbots-assets@main/0-start-here/jinjax.webp\" alt=\"JinjaX Logo\" width=\"700\"/\u003e\n\u003c/a\u003e\n\nWe'll use [JinjaX](https://jinjax.scaletti.dev/) in our templates, an experimental project that's essentially Jinja2 with JSX-like syntax for components.\n\n### Why JinjaX?\n\nBecause paired with htmx, we can do stuff like:\n\n```html  \n\u003cChatContainer\n        hx-get=\"/chat-messages\"\n        hx-trigger=\"chatMessagesUpdated from:body\"\n\u003e\n   \u003cChatMessage role=\"user\"\u003e\n      I personally love the simplicity of templates with JinjaX.\n   \u003c/ChatMessage\u003e\n\u003c/ChatContainer\u003e  \n```\n\nWhich is a joy to read and write.\n\nMost importantly, it enables keeping **behaviour** (`hx-*` attributes) explicit, while abstracting **structure**.\n\nI've written a [blog about JinjaX](https://tanulchristian.dev/blogs/will_jinjax_replace_django_templates), if you're curious.\n\n\u003ca href=\"https://tanulchristian.dev/blogs/will_jinjax_replace_django_templates\"\u003e  \n    \u003cimg src=\"https://cdn.jsdelivr.net/gh/scriptogre/functional-chatbots-assets/0-start-here/blog_snippet.webp\" alt=\"JinjaX Blog Snippet\" width=\"500\"/\u003e  \n\u003c/a\u003e  \n\nSimilar projects include:\n- [`django-components`](https://github.com/EmilStenstrom/django-components/)\n- [`slippers`](https://github.com/mixxorz/slippers)\n- [`django-template-partials`](https://github.com/carltongibson/django-template-partials) _(Hi Carlton! Love your projects 💚)_\n\n# TailwindCSS\n\nWe'll use TailwindCSS for styling.\n\n### Why TailwindCSS?\n\nBecause paired with JinjaX, we can do stuff like:\n```html\n\u003cChatContainer class=\"group\"\u003e\n\n   ...\n\n   \u003cChatPlaceholder class=\"group-has-[.chat-message]:hidden\" /\u003e\n\n\u003c/ChatContainer\u003e\n```\n\nWhich is very expressive. \n\nWe can hide classes that are part of the component, while keeping context-specific classes visible.\n\nBy creating custom variants (like `hover:` or `dark:`), we can also do stuff like this:\n```html\n\u003c!-- This shows only when assistant generates responses --\u003e\n\u003cChatMessage class=\"hidden htmx-request-on-[#trigger-assistant]:block\"\u003e\n   Typing...\n\u003c/ChatMessage\u003e\n```\n\nCSS is very powerful nowadays.\n\nSmooth transitions, animations, and even conditional displaying can be achieved with it (e.g. `group-has-[.chat-message]:hidden`).\n\nTailwindCSS makes it easier to harness that power.\n\n| Tools              | Less JavaScript |\n|--------------------|-----------------|\n| htmx               | 80%             |\n| htmx + TailwindCSS | 99%             |\n\n# GroqCloud API\n\n\u003ca href=\"https://www.groq.com/\"\u003e  \n    \u003cimg src=\"https://cdn.jsdelivr.net/gh/scriptogre/functional-chatbots-assets/0-start-here/groq.webp\" alt=\"Groq\" width=\"700\"/\u003e  \n\u003c/a\u003e  \n\nWe'll use **GroqCloud**'s free API to interact with **LLama 3 70B**, an open-source model.\n\n### Why GroqCloud?\n\n#### It's **FAST**.\n\nFaster than any other LLM API I've used.\n\n#### It's **FREE**.\n\nOther services like OpenAI, Anthropic, or Google Gemini were paid. I didn't want you to pay for a workshop.\n\n#### It's ENOUGH for our needs.\nTheir free tier offers **30 requests per minute**. That's 1 request every 2 seconds.\n\n# Instructor\n\n\u003ca href=\"https://python.useinstructor.com/\"\u003e  \n   \u003cimg src=\"https://cdn.jsdelivr.net/gh/scriptogre/functional-chatbots-assets/0-start-here/instructor.webp\" alt=\"Instructor Logo\" width=\"700\"/\u003e\n\u003c/a\u003e\n\nInstructor is a Python library that does the heavy lifting for getting structured responses from LLMs.\n\n### Why Instructor?\n\nIt has support for Groq's API, and it will save us from a lot of effort (and boilerplate).\n\n### Make sure to also check out this branch's `PROGRESS.md` file\n\n# Feedback\n\nThis was my first workshop. \n\nI'd love to her your thoughts. I'd appreciate to know whether I should pursue this further or stop\nwasting people's time.\n\n## Scan this QR code to provide feedback\n\n...please 👉👈\n\n\u003ca href=\"https://docs.google.com/forms/d/e/1FAIpQLSfgmNqBbr7Uxp7Xji-y_JRYibKdQune3mM0JUkcpj54yww0GQ/viewform\" target=\"_blank\"\u003e\n \u003cimg src=\"https://cdn.jsdelivr.net/gh/scriptogre/functional-chatbots-assets/feedback-form-qr-code.png\" alt=\"Feedback Form QR Code\" width=\"500\"/\u003e\n\u003c/a\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscriptogre%2Ffunctional-chatbots","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscriptogre%2Ffunctional-chatbots","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscriptogre%2Ffunctional-chatbots/lists"}