{"id":28412597,"url":"https://github.com/reterics/suhana","last_synced_at":"2026-04-29T21:31:16.321Z","repository":{"id":291320534,"uuid":"977276115","full_name":"Reterics/suhana","owner":"Reterics","description":"Self-hosted AI assistant with memory, pluggable LLMs (LLaMA/OpenAI), command execution, and a FastAPI-based API.","archived":false,"fork":false,"pushed_at":"2025-06-14T20:53:36.000Z","size":4553,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-14T21:43:53.238Z","etag":null,"topics":["fastapi","llama3","openai","python"],"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/Reterics.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-05-03T20:28:25.000Z","updated_at":"2025-06-14T20:53:39.000Z","dependencies_parsed_at":"2025-05-28T19:57:35.494Z","dependency_job_id":"7af97c3c-a09a-451f-88fe-c9ad0d4bb810","html_url":"https://github.com/Reterics/suhana","commit_stats":null,"previous_names":["reterics/suhana"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Reterics/suhana","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reterics%2Fsuhana","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reterics%2Fsuhana/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reterics%2Fsuhana/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reterics%2Fsuhana/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Reterics","download_url":"https://codeload.github.com/Reterics/suhana/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reterics%2Fsuhana/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261685431,"owners_count":23194103,"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","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":["fastapi","llama3","openai","python"],"created_at":"2025-06-02T23:14:37.578Z","updated_at":"2026-04-29T21:31:16.316Z","avatar_url":"https://github.com/Reterics.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"![suhana_right.png](assets/logos/suhana_right.png)\n\n[![Python](https://img.shields.io/badge/Python-3.12%2B-blue?logo=python)](https://www.python.org/)\n[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)\n[![Self-hosted](https://img.shields.io/badge/self--hosted-yes-brightgreen)]()\n[![Powered by](https://img.shields.io/badge/LLM-Ollama%20%7C%20OpenAI-9cf)]()\n[![codecov](https://codecov.io/gh/Reterics/suhana/branch/main/graph/badge.svg?token=CPMSMW0JWS)](https://codecov.io/gh/Reterics/suhana)\n[![wakatime](https://wakatime.com/badge/user/7280a0d0-d60b-4521-a63b-d823468d18b7/project/46d7daa1-e4ae-4c9c-88f7-40193f7d5e7a.svg)](https://wakatime.com/badge/user/7280a0d0-d60b-4521-a63b-d823468d18b7/project/46d7daa1-e4ae-4c9c-88f7-40193f7d5e7a)\n\n\u003e Suhana _(수하나)_ is your self-hosted AI companion: a modular chat agent with a personality, local knowledge base, and the ability to run commands — all without giving away your data.\n\n\n![screenshot.png](assets/screenshot.png)\n\n---\n\n## ✨ Features\n\n- 🤖 **Chat with a personality** – Suhana remembers you and responds in character\n- 🔍 **Search local knowledge** – markdown, code, and notes in `/knowledge` folder\n- 🔄 **Pluggable AI engines** – supports [Ollama](https://ollama.com) (🦙) and OpenAI (🤖)\n- 🧠 **Memory-aware** – Suhana evolves with you via `!remember` and `profile.json`\n- 🔊 **Voice input/output** – speak naturally to Suhana and hear her reply (Whisper + Coqui)\n- 🔒 **Self-hosted \u0026 portable** – no cloud dependencies, runs on macOS/Windows/Linux\n- ⚡ **Execute commands** – define your own actions like `send_message()` or `update_profile()`\n\n---\n\n## 🚀 Quick Start\n\n### 1. Clone the project\n\n```bash\ngit clone https://github.com/Reterics/suhana.git\ncd suhana\n```\n\n### 2. Install Python + Ollama (if not already installed)\n\nYou need **Python 3.11+** installed. Then choose one of the following:\n\n\n#### ✅ Option A: [Ollama](https://ollama.com) — run models locally (recommended)\n\n1. **Install Ollama**:\n   - macOS / Windows: [https://ollama.com/download](https://ollama.com/download)\n   - Linux:\n     ```bash\n     curl -fsSL https://ollama.com/install.sh | sh\n     ```\n\n2. Start a model:\n   ```bash\n   ollama run llama3\n   ```\n   \u003e Other available models include:\n   \u003e\n   \u003e - `mistral` – lightweight and fast\n   \u003e - `llama3` – larger and more capable\n   \u003e - `gemma` – Google’s open model\n   \u003e - `phi` – compact and smart\n   \u003e - `codellama` – optimized for coding tasks\n   \u003e - `llava` – for multimodal (image + text) input\n\n3. You can change model in `settings.template.json` or at runtime.\n\n---\n\n#### 🤖 Option B: OpenAI — run via cloud API\n\n1. Add your OpenAI key in a `.env` file:\n   ```dotenv\n   OPENAI_API_KEY=sk-...\n   ```\n\n2. Set model and backend:\n   ```json\n   {\n     \"llm_backend\": \"openai\",\n     \"openai_model\": \"gpt-4\"\n   }\n   ```\n\n\u003e You can switch between engines at runtime using `!switch ollama` or `!switch openai`.\n\n### 3. Run the Setup Script\n\n#### 🐧 macOS / Linux:\n```bash\n./setup.sh\n```\n\n#### 🪟 Windows (CMD or PowerShell):\n```cmd\nsetup.bat\n```\n\n\u003e This will create a virtualenv, install runtime dependencies from `requirements.txt`, and auto-generate `settings.json` and `profile.json` if missing.\n\n---\n\n### 4. Ingest your knowledge files\n\nPut `.md`, `.txt`, or `.code` files into `/knowledge`, then run:\n\n```bash\npython ingest.py\n```\n\n---\n\n### 5. Chat with Suhana\n\n```bash\npython main.py\n```\n\nYou’ll see:\n\n```\nHello, I'm Suhana 🦙 — powered by: OLLAMA (llama3)\n```\n\n---\n\n## 🛠 Example Commands\n\n| Command         | Description                             |\n|----------------|-----------------------------------------|\n| `!engine`       | Show the current model + backend        |\n| `!switch openai`| Switch between Ollama and OpenAI        |\n| `!exit`         | Leave the session                       |\n| `help`          | Show available tools and commands       |\n| `!remember fact`| Add a memory fact                       |\n| `!recall`       | List all memory facts                   |\n| `!forget keyword`| Remove memory entries matching keyword |\n\n## 🧰 Available Tools\n\nSuhana comes with a variety of built-in tools that extend its capabilities:\n\n| Tool           | Description                             | Example Usage                        |\n|----------------|-----------------------------------------|--------------------------------------|\n| `help`         | Lists available tools and commands      | \"help\" or \"what can you do?\"         |\n| `get_date`     | Tells the current date                  | \"what is the date today?\"            |\n| `get_time`     | Tells the current time                  | \"what is the time now?\"              |\n| `add_note`     | Adds a personal note or reminder        | \"remember to buy milk\"               |\n| `list_notes`   | Lists all stored notes by date          | \"show my notes\"                      |\n| `update_profile`| Updates user preferences or profile    | \"set preference theme to dark\"       |\n| `web_search`   | Searches the web using various engines  | \"search for Python programming\"      |\n| `calculator`   | Performs basic math calculations        | \"calculate 2 + 2 * 3\"                |\n| `weather`      | Gets current weather for a location     | \"what's the weather in New York?\"    |\n\n### Web Search\n\nThe web search tool supports multiple search engines:\n\n```\nsearch for Python programming           # Uses DuckDuckGo by default\nsearch with bing for machine learning   # Uses Bing search engine\nsearch with brave for climate change    # Uses Brave search engine\n```\n\n### Calculator\n\nThe calculator tool supports various mathematical operations and functions:\n\n- Basic arithmetic: `+`, `-`, `*`, `/`, `**` (power), `%` (modulo), `//` (floor division)\n- Functions: `abs`, `round`, `min`, `max`, `sum`, `sin`, `cos`, `tan`, `sqrt`, `log`, `log10`, `exp`\n- Constants: `pi`, `e`\n\nExample: \"calculate sin(pi/2) + sqrt(16)\"\n\n---\n\n## 🧩 Folder Structure\n\n```\nsuhana/\n├─ engine/                # Core logic\n│  ├─ agent.py            # Main loop\n│  ├─ engine_config.py    # Settings and backend switching\n│  ├─ profile.py          # Memory and preferences\n│  ├─ history.py          # Summarization + trimming\n│  └─ backends/           # ollama.py / openai.py\n├─ knowledge/             # Your documents and notes\n├─ vectorstore/           # Auto-generated FAISS index\n├─ models/                # Prompt templates\n├─ assets/                # Logos and visuals\n├─ docs/                  # Documentation\n│  └─ architecture.md     # Component relationships diagram\n├─ ingest.py              # Knowledge indexer\n├─ main.py                # Entrypoint and setup runner\n├─ settings.template.json # Safe config defaults\n├─ profile.json           # Runtime user profile (generated)\n├─ settings.json          # Runtime config (generated)\n├─ .gitignore             # Excludes local state\n└─ setup.sh / setup.bat   # Easy one-step setup\n```\n\n---\n\n## 🧠 Memory Example\n\nA sample `profile.json`:\n\n```json\n{\n  \"name\": \"Attila\",\n  \"preferences\": {\n    \"communication_style\": \"technical, friendly\"\n  },\n  \"memory\": [\n    { \"type\": \"fact\", \"content\": \"Attila prefers local models over cloud ones.\" }\n  ]\n}\n```\n\n---\n\n## 🧠 Model Support\n\n| Engine   | Status                   | Notes                              |\n|----------|--------------------------|------------------------------------|\n| Ollama   | ✅ Required if selected   | llama3, mistral, gemma, phi, etc.  |\n| OpenAI   | ✅ Optional               | Requires API key                   |\n| LocalHF  | 🔜 Planned                | Hugging Face local models          |\n\n---\n\n## 🧪 Testing\n\n### Installing Development Dependencies\n\nFor testing and development, you'll need additional dependencies:\n\n```bash\npip install -r requirements-dev.txt\n```\n\nThis will install both runtime dependencies and development tools like pytest and pytest-cov.\n\n### Running Tests\n\nThe project uses pytest for testing. To run tests:\n\n```bash\n# Run all tests\npython -m pytest\n\n# Run specific test file\npython -m pytest tests/test_profile_meta.py\n\n# Run with verbose output\npython -m pytest -v\n\n# Run with coverage report\npython -m pytest --cov --cov-config=.coveragerc\n```\n\n### Code Coverage\n\nThe project includes code coverage reporting in the GitHub Actions CI pipeline. The coverage report is generated using pytest-cov and uploaded to Codecov.\n\nTo view the coverage report locally:\n\n```bash\npython -m pytest --cov --cov-config=.coveragerc --cov-report=html\n```\n\nThen open `coverage_html_report/index.html` in your browser.\n\n### Creating New Tests\n\n1. Create a new file in the `tests` directory with the naming pattern `test_\u003cmodule_name\u003e.py`\n2. Import the module/function to be tested\n3. Write test functions that assert expected behavior\n4. Use fixtures for common setup/teardown operations\n\n---\n\n## 🧪 Testing the FastAPI API\n\n### 1. Start the API server\n\nFrom the project root:\n\n```bash\nuvicorn engine.api_server:app --reload\n```\n\nIf `api_keys.json` does not exist, it will be created automatically using:\n\n- The `SUHANA_DEFAULT_API_KEY` from your `.env` file\n- Or a secure randomly generated key\n\n---\n\n### 2. Access the interactive Swagger UI\n\nOpen in your browser:\n\n```\nhttp://localhost:8000/docs\n```\n\nUse the `/query` endpoint, and set the `x-api-key` header.\n\n---\n\n### 3. Example request via `curl`\n\n```bash\ncurl -X POST http://localhost:8000/query \\\n  -H \"Content-Type: application/json\" \\\n  -H \"x-api-key: YOUR_API_KEY_HERE\" \\\n  -d '{\"input\": \"What is Suhana?\", \"backend\": \"ollama\"}'\n```\n\n---\n\n### 4. Example request via Python\n\n```python\nimport requests\n\nres = requests.post(\"http://localhost:8000/query\", json={\n    \"input\": \"Hello, who are you?\",\n    \"backend\": \"ollama\"\n}, headers={\n    \"x-api-key\": \"YOUR_API_KEY_HERE\"\n})\n\nprint(res.json())\n```\n\n---\n\n### 5. Notes\n\n- API keys are stored in `api_keys.json` (excluded from Git via `.gitignore`)\n- To customize the default dev key, define `SUHANA_DEFAULT_API_KEY` in your `.env`\n- All keys must be marked `\"active\": true` to be accepted\n- You can edit `api_keys.json` while the server is running — no restart needed\n\n\n---\n\n## 🛡 License\n\nMIT — use freely, modify locally, and share improvements.\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freterics%2Fsuhana","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freterics%2Fsuhana","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freterics%2Fsuhana/lists"}