{"id":16390301,"url":"https://github.com/ekshaks/langchoice","last_synced_at":"2025-11-04T02:04:26.212Z","repository":{"id":192732497,"uuid":"684062475","full_name":"ekshaks/langchoice","owner":"ekshaks","description":"\"if-then-else\" over topics made up of free-form sentences. Build conversations, not LLM chains!","archived":false,"fork":false,"pushed_at":"2023-09-06T13:33:48.000Z","size":22,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-04T17:05:46.579Z","etag":null,"topics":["conversational-agents","conversational-ai","conversational-bots","embedding-similarity","flowchart","gpt","if-then-else","large-language-models","switch-case","vector-database"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ekshaks.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}},"created_at":"2023-08-28T11:30:00.000Z","updated_at":"2024-09-18T00:48:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"bd3c27ec-cef5-4a3a-a9fe-628b83deb5b1","html_url":"https://github.com/ekshaks/langchoice","commit_stats":null,"previous_names":["ekshaks/langchoice"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekshaks%2Flangchoice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekshaks%2Flangchoice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekshaks%2Flangchoice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekshaks%2Flangchoice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ekshaks","download_url":"https://codeload.github.com/ekshaks/langchoice/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240221337,"owners_count":19767442,"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":["conversational-agents","conversational-ai","conversational-bots","embedding-similarity","flowchart","gpt","if-then-else","large-language-models","switch-case","vector-database"],"created_at":"2024-10-11T04:42:46.075Z","updated_at":"2025-11-04T02:04:25.453Z","avatar_url":"https://github.com/ekshaks.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\n![License](https://img.shields.io/github/license/ekshaks/langchoice)\n![PyPi](https://img.shields.io/pypi/v/langchoice)\n\nPyPI: \u003ca href=\"https://pypi.org/project/langchoice/\" target=\"_blank\"\u003ehttps://pypi.org/project/langchoice\u003c/a\u003e\u003c/br\u003e\n\n\n## 🤖 About LangChoice\n\n`switch-case`, but for free-form sentences. A one-liner for `if-then-else` over similar sentences.\n\nThe LangChoice library allows you to condition your structured programs over natural language sentence predicates or triggers. Makes it easy to define conditional flows over user inputs without implementing the sentence *match* operator over and over again.\n\n\n## 📦 Installation\n```\npip install langchoice\n```\n\n## 🧪 Getting Started\n\nSuppose we want to detect if an incoming user message *triggered* belongs to one of the following (*greeting*, *politics*) topics. Do this in a few lines using `langchoice`.\n\nFirst define the text messages that define each topic category (a message group).\n\n```python\ntriggers =\\\n'''\ngreeting:\n    - hello\n    - hi\n    - what's up?\n\npolitics:\n    - what are your political beliefs?\n    - thoughts on the president?\n    - left wing\n    - right wing\n'''\n```\n\n1. Set up a `LangStore` data container.\n\n```python\ndata = yaml.safe_load(triggers)\nS = LangStore(data)\n```\n\n2. On receiving a user message `user_msg`, simply match with topics!\n\n```python\nmatch S.match(user_msg, threshold=1.2, debug=True): \n    case 'greeting', _ : #user_msg matches the greeting message cluster\n        say_hello()\n    case 'politics', _ : #user_msg matches the politics message cluster\n        change_topic()\n    case x :\n        print(x)\n        print(f'No defined triggers detected. Ask an LLM for response.')\n```\n\nAdd or remove sentences from each topic or introduce new topics. Works on-the-fly!\n\nSupports multiple matching modes:\n\n* `S.match` returns the topic of nearest message.\n* Use `S.match_centroid` to instead find the nearest topic *centroid* .\n* (Optional) Provide thresholds for the *no-topic-matches* case:\n    - `S.match` returns `None` if the nearest topic distance is greater than the threshold.\n\n\n## Debug and More!\n\n* Use `debug=True` and `debug_k=5` to \n    - display distance of `user_msg` to different topics.\n    - Get match scores for each message group to debug what went wrong.\n\n\nComing Soon!\n- In built assertions, which fail if the execution fails to match the expected topic / group.\n* Compute the thresholds automatically for pre-specified message groups against a query evaluation set\n* Fine-tune embeddings to *separate* message clusters better.\n\n\n### Implement a Conversation Flow with Message-based Routing\n\nThe langchoice package enables you to make controlled chatbot flows as well as build guardrails very quickly.\n\nThe key motivation is to allow users to have maximal control when designing the bot:\n- add/update messages on demand\n- route user messages to owner states or modules\n- more control over conversation flow, without losing ability to chitchat\n- build conversations, not (worry about) LLM chains!\n\nCheck out the sales lead filtering and appointment-booking bots under [examples](examples/).\n\n\n## Roadmap\n\n- [ ] match variants\n    - [ ] hybrid match - match regex separately\n    - [ ] local S.match (based on state tag)\n    - [ ] match type='item' (default) | type='group' (centroid) | ...\n- [ ] allow switching under-the-hood sentence encoders\n- [ ] fine-tune based on in-topic and irrelevant messages\n\n\n\n## Author\n\nNishant Sinha, Founder, Consulting Scientist, OffNote Labs. \n\nFor insights on Generative AI evolution and applications, follow on [Linkedin](https://www.linkedin.com/in/nishant-sinha-a610311/), and read our articles on [Substack](https://offnote.substack.com/).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekshaks%2Flangchoice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fekshaks%2Flangchoice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekshaks%2Flangchoice/lists"}