{"id":17167819,"url":"https://github.com/ericmjl/llamabot","last_synced_at":"2026-04-02T17:00:01.877Z","repository":{"id":150723447,"uuid":"623106151","full_name":"ericmjl/llamabot","owner":"ericmjl","description":"Pythonic class-based interface to LLMs","archived":false,"fork":false,"pushed_at":"2026-03-30T23:25:32.000Z","size":10691,"stargazers_count":179,"open_issues_count":29,"forks_count":36,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-03-31T01:35:27.795Z","etag":null,"topics":["cli","large-language-models","llm","python"],"latest_commit_sha":null,"homepage":"https://ericmjl.github.io/llamabot/","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/ericmjl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"docs/contributing/setup.md","funding":".github/FUNDING.yml","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":["ericmjl"],"patreon":"ericmjl"}},"created_at":"2023-04-03T17:53:50.000Z","updated_at":"2026-03-28T19:15:56.000Z","dependencies_parsed_at":"2023-09-24T16:35:23.262Z","dependency_job_id":"844caaad-70d0-45be-a7b8-610b8798c2a9","html_url":"https://github.com/ericmjl/llamabot","commit_stats":null,"previous_names":[],"tags_count":220,"template":false,"template_full_name":null,"purl":"pkg:github/ericmjl/llamabot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericmjl%2Fllamabot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericmjl%2Fllamabot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericmjl%2Fllamabot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericmjl%2Fllamabot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ericmjl","download_url":"https://codeload.github.com/ericmjl/llamabot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericmjl%2Fllamabot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31310994,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"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":["cli","large-language-models","llm","python"],"created_at":"2024-10-14T23:10:02.541Z","updated_at":"2026-04-02T17:00:01.870Z","avatar_url":"https://github.com/ericmjl.png","language":"Python","funding_links":["https://github.com/sponsors/ericmjl","https://patreon.com/ericmjl"],"categories":["Python"],"sub_categories":[],"readme":"# LlamaBot: A Pythonic bot interface to LLMs\n\nLlamaBot implements a Pythonic interface to LLMs,\nmaking it much easier to experiment with LLMs in a Jupyter notebook\nand build Python apps that utilize LLMs.\nAll models supported by [LiteLLM](https://github.com/BerriAI/litellm) are supported by LlamaBot.\n\n## Install LlamaBot\n\nTo install LlamaBot:\n\n```python\npip install llamabot==0.17.11\n```\n\nThis will give you the minimum set of dependencies for running LlamaBot.\n\nTo install all of the optional dependencies, run:\n\n```python\npip install \"llamabot[all]\"\n```\n\n## Get access to LLMs\n\n### Option 1: Using local models with Ollama\n\nLlamaBot supports using local models through Ollama.\nTo do so, head over to the [Ollama website](https://ollama.ai) and install Ollama.\nThen follow the instructions below.\n\n### Option 2: Use an API provider\n\n#### OpenAI\n\nIf you have an OpenAI API key, then configure LlamaBot to use the API key by running:\n\n```bash\nexport OPENAI_API_KEY=\"sk-your1api2key3goes4here\"\n```\n\n#### Mistral\n\nIf you have a Mistral API key, then configure LlamaBot to use the API key by running:\n\n```bash\nexport MISTRAL_API_KEY=\"your-api-key-goes-here\"\n```\n\n#### Other API providers\n\nOther API providers will usually specify an environment variable to set.\nIf you have an API key, then set the environment variable accordingly.\n\n### Option 3: Using local models with LMStudio\n\nLlamaBot supports using local models through LMStudio via LiteLLM.\nTo use LMStudio with LlamaBot:\n\n1. Install and set up [LMStudio](https://lmstudio.ai/)\n2. Load your desired model in LMStudio\n3. Start the local server in LMStudio (usually runs on `http://localhost:1234`)\n4. Set the environment variable for LMStudio's API base:\n\n```bash\nexport LM_STUDIO_API_BASE=\"http://localhost:1234\"\n```\n\n5. Use the model with LlamaBot using the `lm_studio/` prefix:\n\n```python\nimport llamabot as lmb\n\nsystem_prompt = \"You are a helpful assistant.\"\nbot = lmb.SimpleBot(\n    system_prompt,\n    model_name=\"lm_studio/your-model-name\"  # Use lm_studio/ prefix\n)\n```\n\nReplace `your-model-name` with the actual name of the model you've loaded in LMStudio. LlamaBot can use any model provider that LiteLLM supports, and LMStudio is one of the many supported providers.\n\n## How to use\n\n!!! tip \"Not sure which bot to use?\"\n    Check out the [**Which Bot Should I Use?**](docs/getting-started/which-bot.md) guide to help you choose the right bot for your needs.\n\n### SimpleBot\n\nThe simplest use case of LlamaBot\nis to create a `SimpleBot` that keeps no record of chat history.\nThis is effectively the same as a _stateless function_\nthat you program with natural language instructions rather than code.\nThis is useful for prompt experimentation,\nor for creating simple bots that are preconditioned on an instruction to handle texts\nand are then called upon repeatedly with different texts.\n\n#### Using `SimpleBot` with an API provider\n\nFor example, to create a Bot that explains a given chunk of text\nlike Richard Feynman would:\n\n```python\nimport llamabot as lmb\n\nsystem_prompt = \"You are Richard Feynman. You will be given a difficult concept, and your task is to explain it back.\"\nfeynman = lmb.SimpleBot(\n  system_prompt,\n  model_name=\"gpt-4.1-mini\"\n)\n```\n\nFor using GPT, you need to have the `OPENAI_API_KEY` environment variable configured. If you want to use `SimpleBot` with a local Ollama model, [check out this example](#using-simplebot-with-a-local-ollama-model)\n\nNow, `feynman` is callable on any arbitrary chunk of text and will return a rephrasing of that text in Richard Feynman's style (or more accurately, according to the style prescribed by the `system_prompt`).\nFor example:\n\n```python\nprompt = \"\"\"\nEnzyme function annotation is a fundamental challenge, and numerous computational tools have been developed.\nHowever, most of these tools cannot accurately predict functional annotations,\nsuch as enzyme commission (EC) number,\nfor less-studied proteins or those with previously uncharacterized functions or multiple activities.\nWe present a machine learning algorithm named CLEAN (contrastive learning–enabled enzyme annotation)\nto assign EC numbers to enzymes with better accuracy, reliability,\nand sensitivity compared with the state-of-the-art tool BLASTp.\nThe contrastive learning framework empowers CLEAN to confidently (i) annotate understudied enzymes,\n(ii) correct mislabeled enzymes, and (iii) identify promiscuous enzymes with two or more EC numbers—functions\nthat we demonstrate by systematic in silico and in vitro experiments.\nWe anticipate that this tool will be widely used for predicting the functions of uncharacterized enzymes,\nthereby advancing many fields, such as genomics, synthetic biology, and biocatalysis.\n\"\"\"\nfeynman(prompt)\n```\n\nThis will return something that looks like:\n\n```text\nAlright, let's break this down.\n\nEnzymes are like little biological machines that help speed up chemical reactions in our\nbodies. Each enzyme has a specific job, or function, and we use something called an\nEnzyme Commission (EC) number to categorize these functions.\n\nNow, the problem is that we don't always know what function an enzyme has, especially if\nit's a less-studied or new enzyme. This is where computational tools come in. They try\nto predict the function of these enzymes, but they often struggle to do so accurately.\n\nSo, the folks here have developed a new tool called CLEAN, which stands for contrastive\nlearning–enabled enzyme annotation. This tool uses a machine learning algorithm, which\nis a type of artificial intelligence that learns from data to make predictions or\ndecisions.\n\nCLEAN uses a method called contrastive learning. Imagine you have a bunch of pictures of\ncats and dogs, and you want to teach a machine to tell the difference. You'd show it\npairs of pictures, some of the same animal (two cats or two dogs) and some of different\nanimals (a cat and a dog). The machine would learn to tell the difference by contrasting\nthe features of the two pictures. That's the basic idea behind contrastive learning.\n\nCLEAN uses this method to predict the EC numbers of enzymes more accurately than\nprevious tools. It can confidently annotate understudied enzymes, correct mislabeled\nenzymes, and even identify enzymes that have more than one function.\n\nThe creators of CLEAN have tested it with both computer simulations and lab experiments,\nand they believe it will be a valuable tool for predicting the functions of unknown\nenzymes. This could have big implications for fields like genomics, synthetic biology,\nand biocatalysis, which all rely on understanding how enzymes work.\n```\n\n#### Using `SimpleBot` with a Local Ollama Model\n\nIf you want to use an Ollama model hosted locally,\nthen you would use the following syntax:\n\n```python\nimport llamabot as lmb\n\nsystem_prompt = \"You are Richard Feynman. You will be given a difficult concept, and your task is to explain it back.\"\nbot = lmb.SimpleBot(\n    system_prompt,\n    model_name=\"ollama_chat/llama2:13b\"\n)\n```\n\nSimply specify the `model_name` keyword argument following the `\u003cprovider\u003e/\u003cmodel name\u003e` format. For example:\n\n* `ollama_chat/` as the prefix, and\n* a model name from the [Ollama library of models](https://ollama.ai/library)\n\nAll you need to do is make sure Ollama is running locally;\nsee the [Ollama documentation](https://ollama.ai/) for more details.\n(The same can be done for the `QueryBot` class below!)\n\nThe `model_name` argument is optional. If you don't provide it, Llamabot will try to use the default model. You can configure that in the `DEFAULT_LANGUAGE_MODEL` environment variable.\n\n### SimpleBot with memory for chat functionality\n\nIf you want chat functionality with memory, you can use SimpleBot with ChatMemory. This allows the bot to remember previous conversations:\n\n```python\nimport llamabot as lmb\n\n# Create a bot with memory\nsystem_prompt = \"You are Richard Feynman. You will be given a difficult concept, and your task is to explain it back.\"\n\n# For simple linear memory (fast, no LLM calls)\nmemory = lmb.ChatMemory()\n\n# For intelligent threading (uses LLM for smart connections)\n# memory = lmb.ChatMemory.threaded(model=\"gpt-4o-mini\")\n\nfeynman = lmb.SimpleBot(\n    system_prompt,\n    memory=memory,\n    model_name=\"gpt-4.1-mini\"\n)\n\n# Have a conversation\nresponse1 = feynman(\"Can you explain quantum mechanics?\")\nprint(response1)\n\n# The bot remembers the previous conversation\nresponse2 = feynman(\"Can you give me a simpler explanation?\")\nprint(response2)\n```\n\nThe ChatMemory system provides intelligent conversation memory that can maintain context across multiple interactions. It supports both linear memory (fast, no LLM calls) and graph-based memory with intelligent threading (uses LLM to connect related conversation topics).\n\n**Note**: For RAG (Retrieval-Augmented Generation) with document stores, use `QueryBot` with a document store instead of SimpleBot with memory. SimpleBot's memory parameter is specifically for conversational memory, while QueryBot is designed for document retrieval and question answering.\n\nFor more details on chat memory, see the [Chat Memory component documentation](reference/components/chat_memory.md).\n\n### ToolBot\n\nToolBot is a specialized bot designed for single-turn tool execution and function calling. It analyzes user requests and selects the most appropriate tool to execute, making it perfect for automation tasks and data analysis workflows.\n\n```python\nimport llamabot as lmb\nfrom llamabot.components.tools import write_and_execute_code\n\n# Create a ToolBot with code execution capabilities\nbot = lmb.ToolBot(\n    system_prompt=\"You are a data analysis assistant.\",\n    model_name=\"gpt-4.1\",\n    tools=[write_and_execute_code(globals_dict=globals())],\n    memory=lmb.ChatMemory(),\n)\n\n# Create some data\nimport pandas as pd\nimport numpy as np\ndata = pd.DataFrame({\n    'x': np.random.randn(100),\n    'y': np.random.randn(100)\n})\n\n# Use the bot to analyze the data\nresponse = bot(\"Calculate the correlation between x and y in the data DataFrame\")\nprint(response)\n```\n\nToolBot is ideal for:\n* **Data analysis workflows** where you need to execute custom code\n* **Automation tasks** that require specific function calls\n* **API integrations** that need to call external services\n* **Single-turn function calling** scenarios\n\n### QueryBot\n\nQueryBot lets you query a collection of documents.\nQueryBot now works with a docstore that you create first, making it more modular.\n\nHere's how to use QueryBot with a docstore:\n\n```python\nimport llamabot as lmb\nfrom pathlib import Path\n\n# First, create a docstore and add your documents\ndocstore = lmb.LanceDBDocStore(table_name=\"eric_ma_blog\")\ndocstore.add_documents([\n    Path(\"/path/to/blog/post1.txt\"),\n    Path(\"/path/to/blog/post2.txt\"),\n    # ... more documents\n])\n\n# Then, create a QueryBot with the docstore\nbot = lmb.QueryBot(\n  system_prompt=\"You are an expert on Eric Ma's blog.\",\n  docstore=docstore,\n  # Optional:\n  # model_name=\"gpt-4.1-mini\"\n  # or\n  # model_name=\"ollama_chat/mistral\"\n)\n\nresult = bot(\"Do you have any advice for me on career development?\")\n```\n\nYou can also use an existing docstore:\n\n```python\nimport llamabot as lmb\n\n# Load an existing docstore\ndocstore = lmb.LanceDBDocStore(table_name=\"eric_ma_blog\")\n\n# Create QueryBot with the existing docstore\nbot = lmb.QueryBot(\n  system_prompt=\"You are an expert on Eric Ma's blog\",\n  docstore=docstore,\n  # Optional:\n  # model_name=\"gpt-4.1-mini\"\n  # or\n  # model_name=\"ollama_chat/mistral\"\n)\n\nresult = bot(\"Do you have any advice for me on career development?\")\n```\n\nFor more explanation about the `model_name`, see [the examples with `SimpleBot`](#using-simplebot-with-a-local-ollama-model).\n\n### StructuredBot\n\nStructuredBot is designed for getting structured, validated outputs from LLMs.\nUnlike SimpleBot, StructuredBot enforces Pydantic schema validation and provides\nautomatic retry logic when the LLM doesn't produce valid output.\n\n```python\nimport llamabot as lmb\nfrom pydantic import BaseModel\nfrom typing import List\n\nclass Person(BaseModel):\n    name: str\n    age: int\n    hobbies: List[str]\n\n# Create a StructuredBot with your Pydantic model\nbot = lmb.StructuredBot(\n    system_prompt=\"Extract person information from text.\",\n    pydantic_model=Person,\n    model_name=\"gpt-4o\"\n)\n\n# The bot will return a validated Person object\nperson = bot(\"John is 25 years old and enjoys hiking and photography.\")\nprint(person.name)  # \"John\"\nprint(person.age)   # 25\nprint(person.hobbies)  # [\"hiking\", \"photography\"]\n```\n\nStructuredBot is perfect for:\n* **Data extraction** from unstructured text\n* **API responses** that need to match specific schemas\n* **Form processing** with validation\n* **Structured outputs** for downstream processing\n\n### ImageBot\n\nWith the release of the OpenAI API updates,\nas long as you have an OpenAI API key,\nyou can generate images with LlamaBot:\n\n```python\nimport llamabot as lmb\n\nbot = lmb.ImageBot()\n# Within a Jupyter/Marimo notebook:\nurl = bot(\"A painting of a dog.\")\n\n# Or within a Python script\nfilepath = bot(\"A painting of a dog.\")\n\n# Now, you can do whatever you need with the url or file path.\n```\n\nIf you're in a Jupyter/Marimo notebook,\nyou'll see the image show up magically as part of the output cell as well.\n\n### Working with images and user input\n\nYou can easily pass images to your bots using `lmb.user()` with image file paths.\nThis is particularly useful for vision models that can analyze, describe, or answer questions about images:\n\n```python\nimport llamabot as lmb\n\n# Create a bot that can analyze images\nvision_bot = lmb.SimpleBot(\n    \"You are an expert image analyst. Describe what you see in detail.\",\n    model_name=\"gpt-4o\"  # Use a vision-capable model\n)\n\n# Pass an image file path using lmb.user()\nresponse = vision_bot(lmb.user(\"/path/to/your/image.jpg\"))\nprint(response)\n\n# You can also combine text and images\nresponse = vision_bot(lmb.user(\n    \"What colors are prominent in this image?\",\n    \"/path/to/your/image.jpg\"\n))\nprint(response)\n```\n\nThe `lmb.user()` function automatically detects image files (PNG, JPG, JPEG, GIF, WebP)\nand converts them to the appropriate format for the model.\nYou can use local file paths or even image URLs.\n\n### Developer Messages with `lmb.dev()`\n\nFor development and debugging scenarios, you can use `lmb.dev()` to create developer messages that provide context about code changes, debugging instructions, or development tasks:\n\n```python\nimport llamabot as lmb\n\n# Create a bot for code development\ndev_bot = lmb.SimpleBot(\n    \"You are a helpful coding assistant. Help with development tasks.\",\n    model_name=\"gpt-4o-mini\"\n)\n\n# Use dev() for development context\nresponse = dev_bot(lmb.dev(\"Add error handling to this function\"))\nprint(response)\n\n# Combine multiple development instructions\nresponse = dev_bot(lmb.dev(\n    \"Refactor this code to be more modular\",\n    \"Add comprehensive docstrings\",\n    \"Follow PEP8 style guidelines\"\n))\nprint(response)\n```\n\n**When to use `lmb.dev()`:**\n* **Development tasks**: Code refactoring, debugging, testing\n* **Code review**: Providing feedback on code quality\n* **Documentation**: Adding docstrings, comments, or README updates\n* **Debugging**: Describing issues or requesting fixes\n\n**Message Type Hierarchy:**\n* `lmb.system()` - Bot behavior and instructions\n* `lmb.user()` - User input and questions\n* `lmb.dev()` - Development context and tasks\n\n### Experimentation\n\nAutomagically record your prompt experimentation locally on your system\nby using llamabot's `Experiment` context manager:\n\n```python\nimport llamabot as lmb\n\n@lmb.prompt(\"system\")\ndef sysprompt():\n    \"\"\"You are a funny llama.\"\"\"\n\n@lmb.prompt(\"user\")\ndef joke_about(topic):\n    \"\"\"Tell me a joke about {{ topic }}.\"\"\"\n\n@lmb.metric\ndef response_length(response) -\u003e int:\n    return len(response.content)\n\nwith lmb.Experiment(name=\"llama_jokes\") as exp:\n    # You would have written this outside of the context manager anyways!\n    bot = lmb.SimpleBot(sysprompt(), model_name=\"gpt-4o\")\n    response = bot(joke_about(\"cars\"))\n    _ = response_length(response)\n```\n\nAnd now they will be viewable in the locally-stored message logs:\n\n![](cli/log-viewer/experiments.webp)\n\n## CLI Demos\n\nLlamabot comes with CLI demos of what can be built with it and a bit of supporting code.\n\nAnd here is one where I use `llamabot`'s `SimpleBot` to create a bot\nthat automatically writes commit messages for me.\n\n[![Watch the terminal session on Asciinema](https://asciinema.org/a/594334.png)](https://asciinema.org/a/594334)\n\n## Contributing\n\n### New features\n\nNew features are welcome!\nThese are early and exciting days for users of large language models.\nOur development goals are to keep the project as simple as possible.\nFeatures requests that come with a pull request will be prioritized;\nthe simpler the implementation of a feature (in terms of maintenance burden),\nthe more likely it will be approved.\n\n### Bug reports\n\nPlease submit a bug report using the issue tracker.\n\n### Questions/Discussions\n\nPlease use the issue tracker on GitHub.\n\n## Contributors\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/RenaLu\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/12033704?v=4?s=100\" width=\"100px;\" alt=\"Rena Lu\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eRena Lu\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#code-RenaLu\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://giessel.com\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/1160997?v=4?s=100\" width=\"100px;\" alt=\"andrew giessel\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eandrew giessel\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#ideas-andrewgiessel\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"#design-andrewgiessel\" title=\"Design\"\u003e🎨\u003c/a\u003e \u003ca href=\"#code-andrewgiessel\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/aidanbrewis\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/83365064?v=4?s=100\" width=\"100px;\" alt=\"Aidan Brewis\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAidan Brewis\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#code-aidanbrewis\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://ericmjl.github.io/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/2631566?v=4?s=100\" width=\"100px;\" alt=\"Eric Ma\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eEric Ma\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#ideas-ericmjl\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"#design-ericmjl\" title=\"Design\"\u003e🎨\u003c/a\u003e \u003ca href=\"#code-ericmjl\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://stackoverflow.com/users/116/mark-harrison\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/7154?v=4?s=100\" width=\"100px;\" alt=\"Mark Harrison\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMark Harrison\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#ideas-marhar\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/reka\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/382113?v=4?s=100\" width=\"100px;\" alt=\"reka\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ereka\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#doc-reka\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#code-reka\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/anujsinha3\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/21972901?v=4?s=100\" width=\"100px;\" alt=\"anujsinha3\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eanujsinha3\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#code-anujsinha3\" title=\"Code\"\u003e��\u003c/a\u003e \u003ca href=\"#doc-anujsinha3\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/ElliotSalisbury\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/2605537?v=4?s=100\" width=\"100px;\" alt=\"Elliot Salisbury\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eElliot Salisbury\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#doc-ElliotSalisbury\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://eefricker.github.io\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/65178728?v=4?s=100\" width=\"100px;\" alt=\"Ethan Fricker, PhD\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eEthan Fricker, PhD\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#doc-eefricker\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://speakerdeck.com/eltociear\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/22633385?v=4?s=100\" width=\"100px;\" alt=\"Ikko Eltociear Ashimine\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eIkko Eltociear Ashimine\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#doc-eltociear\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/amirmolavi\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/19491452?v=4?s=100\" width=\"100px;\" alt=\"Amir Molavi\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAmir Molavi\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#infra-amirmolavi\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e \u003ca href=\"#doc-amirmolavi\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fericmjl%2Fllamabot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fericmjl%2Fllamabot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fericmjl%2Fllamabot/lists"}