{"id":24746497,"url":"https://github.com/itelnov/skeernir","last_synced_at":"2025-10-10T14:33:04.013Z","repository":{"id":273367962,"uuid":"919474801","full_name":"itelnov/skeernir","owner":"itelnov","description":"UI to deploy locally agents and customise interaction with them","archived":false,"fork":false,"pushed_at":"2025-07-03T10:13:26.000Z","size":14345,"stargazers_count":12,"open_issues_count":9,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-03T10:39:27.448Z","etag":null,"topics":["agents","ai","fastapi","htmx","jinja2-templates","langchain","langgraph","llamacpp","localai","ollama","ui","vllm"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/itelnov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null}},"created_at":"2025-01-20T13:07:58.000Z","updated_at":"2025-05-18T22:54:03.000Z","dependencies_parsed_at":"2025-07-03T10:42:14.135Z","dependency_job_id":null,"html_url":"https://github.com/itelnov/skeernir","commit_stats":null,"previous_names":["itelnov/skeernir"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/itelnov/skeernir","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itelnov%2Fskeernir","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itelnov%2Fskeernir/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itelnov%2Fskeernir/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itelnov%2Fskeernir/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/itelnov","download_url":"https://codeload.github.com/itelnov/skeernir/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itelnov%2Fskeernir/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279004176,"owners_count":26083688,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["agents","ai","fastapi","htmx","jinja2-templates","langchain","langgraph","llamacpp","localai","ollama","ui","vllm"],"created_at":"2025-01-28T04:23:49.494Z","updated_at":"2025-10-10T14:32:59.004Z","avatar_url":"https://github.com/itelnov.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003cimg src=\"static/assets/logo.png\" alt=\"drawing\" width=\"50\"/\u003e Skeernir\n\n![Python](https://img.shields.io/badge/python-3.11%2B-blue.svg)\n![License](https://img.shields.io/badge/license-MIT-orange.svg)\n![Version](https://img.shields.io/badge/version-0.1.0-red.svg)\n\u003c!-- ![Stars](https://img.shields.io/github/stars/itelnov/skeernir.svg)\n![Forks](https://img.shields.io/github/forks/itelnov/skeernir.svg)\n![Issues](https://img.shields.io/github/issues/itelnov/skeernir.svg) --\u003e\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Installation](#Installation)\n\n####\nOh great! Just what we needed - yet another UI for locally deployed models... BUT this time it's for your **Agents!** How thrilling.\n##### :exclamation: The project in an intensive development phase :exclamation:\n\n### What’s the deal?  \n- Build your AI Agents as fancy graphs with the oh-so-powerful [Langgraph](https://python.langchain.com/docs/langgraph).  \n- Pair it with a super lightweight, crystal-clear UI! Forget bloated npm packages and convoluted JavaScript frameworks. Nope, this beauty runs on clean Python and [FastAPI](https://fastapi.tiangolo.com/) for the back-end, while the front-end rocks HTML, [HTMX](https://htmx.org/), and [Tailwind CSS](https://tailwindcss.com/). Oh, and a sprinkle of vanilla JS—because who doesn’t love a bit of extra fun?  \n- Customize the UI for your Agents’ output—go wild! Use the MIT-licensed code to implement whatever your heart desires or play around predefined tools and pretty simple Jinja templates to render your Agent's inner workings.  \n\n\u003cdiv style=\"text-align: center;\"\u003e\n    \u003cimg src=\"static/assets/demo1c.gif\" alt=\"drawing\" width=\"712\"/\u003e\n    \u003cimg src=\"static/assets/demo2c.gif\" alt=\"drawing\" width=\"712\"/\u003e\n\u003c/div\u003e\n\n### Why does this even exist?  \nHonestly? This project came to life to dodge the *joys* of Gradio or Streamlit integration. It’s a quick-and-dirty code base for prototyping agentic solutions without those pesky limitations. If you’re an AI dev like me, who prefers to avoid the murky waters of web development, you might actually find this pretty useful (or not :broken_heart: ).  \n\nOh, and contributions? Yes, please. Toxic comments? Even better—bring them on. \n\n### How does it work? \n\nCreate file with in [src/graphs](src/graphs) and define function which returns your compiled graph. Decorate it using `@tool_graph`. Add config `.json` file in [configs](configs) folder if needed.\n`@tool_graph` decorator takes the next arguments:\n- `name` - string name of your Agent, the config filename should be the same \n- `tag` - some tag, will be appended to the name. Its up to you how to tag your agents\n- `att_modals` - define modalities your Agent might work with. For now only \"text\" and \"image\" are available. By default `att_modals=['text']`\n\nSee example for simple chatbot with gpt-4o-mini:\n\n```python\nfrom langgraph.graph import MessagesState, StateGraph, START, END\nfrom langchain_openai import ChatOpenAI\nfrom langgraph.checkpoint.memory import MemorySaver\n\nfrom src.registry import tool_graph\n\n@tool_graph(name='gpt-4o-mini-default', tag=\"chat/vision API\", att_modals=['text', 'image'])\ndef get_openaigpt(api_token=None, **kwargs):\n    \n    memory = MemorySaver()\n    kwargs.pop(\"port\", None)\n    sampling_data = kwargs.pop(\"sampling\", {})\n\n    model = ChatOpenAI(\n        streaming=True,\n        api_key=api_token,\n        model=\"gpt-4o-mini-2024-07-18\",\n        **kwargs)\n    \n    # Define the function that calls the model\n    async def call_model(state: MessagesState):\n        response = await model.ainvoke(state[\"messages\"], **sampling_data)\n        return {\"messages\": response}\n\n    # Define a new graph\n    workflow = StateGraph(MessagesState)\n    workflow.add_node(\"chatbot\", call_model)\n    workflow.add_edge(START, \"chatbot\")\n    workflow.add_edge(\"chatbot\", END)\n    return workflow.compile(checkpointer=memory), model\n```\n\nIn addition to compiled graph the function returns client instance to properly clean memory when you switch to another graph, however it's not obligatory. \n\nFor this simple case the config file `configs/gpt-4o-mini-default.json` should contain:\n\n```json\n{\n    \"api_token\": \"\u003cyour token api\u003e\"\n}\n```\nGraph will be available in UI.\n\n\u003cimg src=\"static/assets/scr1.png\" alt=\"drawing\" width=\"512\"/\u003e \n\n\n#### Find more examples with [Llama.cpp](https://github.com/ggerganov/llama.cpp), [Ollama](https://github.com/ollama/ollama) and [vLLM](https://github.com/vllm-project/vllm) in [src/graphs](src/graphs). \n\n#### Take a look on [src/graphs/corrective_rag/corrective_rag.md](src/graphs/corrective_rag/corrective_rag.md) and [src/graphs/corrective_rag_example.py](src/graphs/corrective_rag_example.py) to integrate Agent's outputs into the Skeernir interface (right-side panel on demo gifs)!\n\n:rocket::rocket::rocket: **More ready-to-use Agents and examples coming soon!**\n\n\n## Features\n- Working Spaces by user auth.\n- Conversation History (keeps your attachments and Agents outputs!)\n- Run llama.cpp / Ollama / vLLM servers in subprocess and terminate it\n- Code highlighting and streaming\n- Exctract text from PDF, PowerPoint, Word, Excel, etc. using [MarkItDown](https://github.com/microsoft/markitdown)\nfrom attachments\n\n## TODO\n- More Agents! (Presentation Maker and Helper for this repo)\n- Video in attachments\n- Speach-to-text\n- Text-to-speach\n- Documentation\n\n## Installation\n\nHere's what you need to do to get your environment set up and get started:\n\n\n1. Create a new conda environment with Python 3.11:\n```console\nconda create --name my_env python=3.11 \nconda activate my_env\n```\n\n2. (Optional) Prepare for Graph's LLM\n\nUpdate packages and install `ccache` and `cmake`:\n\n```console\napt-get update\napt-get install ccache\napt-get install cmake\n\n```\nInstall Llama.cpp to use llama.cpp server. See [Llama.cpp](https://github.com/ggerganov/llama.cpp) for detailed instructions.\nThe same to [Ollama](https://github.com/ggerganov/llama.cpp) or [vLLM](https://github.com/vllm-project/vllm) \n\nYou can communicate with your models and tools as you prefer, just implement your [Langgraph](https://python.langchain.com/docs/langgraph) Graph based on your previous projects or based on [examples](src/graphs) provided. \nFor instance if you're going to work with LLM models using llama.cpp python bindings, perform the following steps:\n\nIn your newly created conda environment, install llama-cpp-python:\n\n```console\npip install llama-cpp-python --upgrade --force-reinstall --no-cache-dir\n```\nIf GPU on board:\n\n```console\nCMAKE_ARGS=\"-DGGML_CUDA=on\" pip install llama-cpp-python --upgrade --force-reinstall --no-cache-dir\n```\nPrepare locally deployed models, refer to the following Python scripts as examples:\n\n* [src/graphs/llama3_2_vision_11b_on_ollama_server.py](src/graphs/llama3_2_vision_11b_on_ollama_server.py)\n* [src/graphs/phi3_5_mini_instruct_on_llamacpp_server.py](src/graphs/llama3_2_vision_11b_on_ollama_server.py)\n\nand corresponding .json files in [configs](configs). **Don't forget to add your token api into configs!!!** (see [here](#how-does-it-work))\n\nGrab those **GGUF files** (or whatever other format you fancy).  \nUsing Ollama? Don’t sweat it—models will magically pull themselves if they’re not already there.  \n\n3. Clone repo:\n\n```console\ngit clone https://github.com/itelnov/skeernir.git\ncd skeernir\n```\n\n4. Install all dependencies from the requirements.txt file:\n\n```console\npip install -r requirements.txt --no-cache-dir\n```\n\n5. **Create .env with next environment variables:**\n\n```.env\nSKEERNIR_PORT = \"\u003cport you prefer\u003e\"\nLLAMA_CPP_PATH = \"\u003cyour path to llama.cpp bin \u003e/llama.cpp/build/bin/\"\nVLLM_PATH = \"\u003cyour path to vllm\u003e\nSQLALCHEMY_DATABASE_URL = \"sqlite:///./chat.db\" # if db located in project root or change according your needs\n```\n\n6. Run app \n\n```concole \npython main.py\n```\n\nHow you deploy or configure your clients for APIs is totally on you. Want to run your LLMs or VLMs? Fine, just make sure you’ve got all the necessary packages installed (looking at you, [Llama.cpp](https://github.com/ggerganov/llama.cpp) and [Ollama](https://github.com/ggerganov/llama.cpp)).  \n\n**Heads up:** This project isn’t here to hold your hand with deploying AI models locally. Nope, it’s laser-focused on your **Agents** and UI to work with them. So, if you’re into that, welcome aboard!  \n\n### Project depends on\n- [Langchain](https://github.com/langchain-ai/langchain)\n- [Langgraph](https://python.langchain.com/docs/langgraph)\n- [FastAPI](https://fastapi.tiangolo.com/)\n- [HTMX](https://htmx.org/)\n- [Tailwind CSS](https://tailwindcss.com/)\n- [Prism](https://github.com/PrismJS/prism?tab=readme-ov-file)\n- [MarkItDown](https://github.com/microsoft/markitdown)\n- [Sqlalchemy](https://www.sqlalchemy.org/)\n\n... \n\nand off course such projects like:\n- [Llama.cpp](https://github.com/ggerganov/llama.cpp)\n- [Ollama](https://github.com/ollama/ollama)\n- [vLLM](https://github.com/vllm-project/vllm)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitelnov%2Fskeernir","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fitelnov%2Fskeernir","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitelnov%2Fskeernir/lists"}