{"id":32454218,"url":"https://github.com/moodlehq/asero","last_synced_at":"2026-04-19T03:01:46.327Z","repository":{"id":314919832,"uuid":"1057297406","full_name":"moodlehq/asero","owner":"moodlehq","description":"A very simple semantic router, using max scores and cosine similarity, to provide basic intent detection / classification wherever needed to.","archived":false,"fork":false,"pushed_at":"2026-03-17T18:44:55.000Z","size":80,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-18T08:07:17.200Z","etag":null,"topics":["ai","classification","embeddings","experiment","intent","python","research","router","semantic"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/moodlehq.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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":null,"dco":null,"cla":null}},"created_at":"2025-09-15T14:36:18.000Z","updated_at":"2026-03-17T18:40:33.000Z","dependencies_parsed_at":"2025-09-15T17:38:01.639Z","dependency_job_id":"0d8fdf6d-2eea-4805-afdf-aed88d3f3cf7","html_url":"https://github.com/moodlehq/asero","commit_stats":null,"previous_names":["moodlehq/asero"],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/moodlehq/asero","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moodlehq%2Fasero","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moodlehq%2Fasero/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moodlehq%2Fasero/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moodlehq%2Fasero/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/moodlehq","download_url":"https://codeload.github.com/moodlehq/asero/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moodlehq%2Fasero/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31992822,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T20:23:30.271Z","status":"online","status_checked_at":"2026-04-19T02:00:07.110Z","response_time":55,"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":["ai","classification","embeddings","experiment","intent","python","research","router","semantic"],"created_at":"2025-10-26T07:55:41.826Z","updated_at":"2026-04-19T03:01:46.049Z","avatar_url":"https://github.com/moodlehq.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Asero - Semantic Router for Intent Classification\n\nA(nother) semantic routing system that classifies user queries into hierarchical categories using OpenAI embeddings and cosine similarity.\n\n## Features\n\n- Hierarchical intent routing with configurable similarity thresholds\n- Automatic embedding caching for performance optimization\n- YAML-based configuration for routing tree structure\n- Transactional updates to routing configuration\n- OpenAI embedding model integration\n\n## Requirements\n- Python 3.12 and up.\n- Access to any Open AI compatible endpoint (Ollama, LiteLLM, ...) with some embeddings model available.\n\n## Quick start\n\n1. Install it with `pip install .`\n2. Setup the `.env` file (start with the provided `dotenv.template`one).\n3. Optionally, edit the `router_example.yaml` to define your routes.\n4. Play with the routes using the `asero` CLI command.\n5. That's all!\n\n## Development\n\n1. Install development dependencies: `pip install .[dev]`\n2. Enable up pre-commit hooks: `pre-commit install`\n3. Setup the `.env` file (start with the provided `dotenv.template`one).\n4. Hack, hack, hack (the `asero` CLI command, that runs `main.py`, should be enough)\n5. Test, test, test. Try to cover as much as possible always.\n\n(see the [Contributing](#Contributing) section for more details)\n\n## CLI commands\n\n### `augment` — generate an evaluation dataset via LLM\n\nUses a configured LLM (accessed through any OpenAI-compatible endpoint) to synthetically paraphrase every utterance in your router YAML, producing a JSON file ready for `asero --evaluate` or `asero --optimise`.\n\n```\naugment [--input-file \u003crouter.yaml\u003e] [--output-file \u003cout.json\u003e] [--model \u003cname\u003e] [--variations N] [--limit N]\n```\n\n- **`--input-file`** — router YAML to read utterances from (defaults to `$ROUTER_YAML_FILE`).\n- **`--output-file`** — destination JSON file (defaults to `\u003cinput-stem\u003e_eval.json`).\n- **`--model`** — LLM model name at the configured endpoint (default: `llama3.3-70b`).\n- **`--variations`** — number of paraphrases to generate per utterance (default: `5`).\n- **`--limit`** — process only the first N utterances; `0` means all (default: `0`).\n\nRequires `OPENAI_API_KEY` and `OPENAI_BASE_URL` to be set (e.g. via `.env`). The script validates that the requested model is available at the endpoint before starting.\n\nRun `augment --help` for full details.\n\n### `asero --evaluate` — measure top-K accuracy and MRR on a dataset\n\nRuns the current router against a JSON eval file and reports top-K accuracy and MRR(K+1).\n\n```\nasero --evaluate \u003cpath to eval file\u003e [--metric top1|top2|top3|top4|top5]\n```\n\n- **`--evaluate`** — path to the JSON evaluation file (produced by `augment`).\n- **`--metric`** — which top-K level to report as the headline accuracy figure (default: `top1`).\n\nThe evaluation runs in *eval mode*: all routing thresholds are disabled so every query always returns scores, giving a true picture of the embedding quality independent of threshold tuning.\n\n### `asero --optimise` — tune per-route similarity thresholds\n\nSearches for the threshold values that maximise the chosen accuracy metric on a dataset, then optionally writes the results back to the router YAML.\n\n```\nasero --optimise \u003cpath to eval file\u003e [--metric top1|top2|top3|top4|top5] [--write]\n```\n\n- **`--optimise`** — path to the JSON evaluation file (produced by `augment`).\n- **`--metric`** — accuracy metric to maximise during the search (default: `top1`).\n- **`--write`** — when set, the optimised thresholds are written back to the router YAML file; without this flag the results are printed but not persisted.\n\n## Use as library\n\nDon't forget to configure the `.env` file (see \"Quick start\" above).\n\n```python\nfrom asero import config as asero_config\nfrom asero.router import SemanticRouter\n\n# Load the configuration from a YAML file (see router_example.yaml)\nconfig = asero_config.get_config(\"path/to/valid/router.yaml\")\n\n# Create a router instance\nrouter = SemanticRouter(config)\n\n# Start making queries (explore options in the SemanticRouter class)\nmatches = router.top_n_routes(query=\"Hi!\")\n\n# Or, for async contexts:\nmatches = await router.atop_n_routes(query=\"Hi!\")\n\n# Print the top matches (route, score, depth, leaf)\n[print(match) for match in matches]\n```\n\nWill output something like:\n```\n('router_example/greetings/neutral', 0.9999999999999999, 3, True)\n('router_example/chitchat', 0.48668323180162615, 2, True)\n```\n\n\n## License\n\nThis project is licensed under the BSD 3-Clause License. See the [LICENSE](LICENSE) file for more information.\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for more details.\n\n## Code of Conduct\n\nPlease note that this project adheres to a [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you agree to uphold this code.\n\n----\n© 2025 Moodle Research Team\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoodlehq%2Fasero","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoodlehq%2Fasero","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoodlehq%2Fasero/lists"}