From cf87fdbc724d95dd0e785ca613170b0f8dfacc31 Mon Sep 17 00:00:00 2001 From: Philipp Acsany Date: Tue, 22 Sep 2026 20:45:15 +0000 Subject: [PATCH 1/2] Sample code for: How to Get Started With Jev in Python --- jev-python/.env.example | 1 + jev-python/.gitignore | 3 +++ jev-python/README.md | 15 ++++++++++++ jev-python/jev_desk.py | 49 +++++++++++++++++++++++++++++++++++++ jev-python/jev_noul.py | 43 ++++++++++++++++++++++++++++++++ jev-python/plain_python.py | 24 ++++++++++++++++++ jev-python/pyproject.toml | 7 ++++++ jev-python/requirements.txt | 1 + 8 files changed, 143 insertions(+) create mode 100644 jev-python/.env.example create mode 100644 jev-python/.gitignore create mode 100644 jev-python/README.md create mode 100644 jev-python/jev_desk.py create mode 100644 jev-python/jev_noul.py create mode 100644 jev-python/plain_python.py create mode 100644 jev-python/pyproject.toml create mode 100644 jev-python/requirements.txt diff --git a/jev-python/.env.example b/jev-python/.env.example new file mode 100644 index 0000000000..3675f13383 --- /dev/null +++ b/jev-python/.env.example @@ -0,0 +1 @@ +OPENROUTER_API_KEY=your-openrouter-api-key diff --git a/jev-python/.gitignore b/jev-python/.gitignore new file mode 100644 index 0000000000..35236e6333 --- /dev/null +++ b/jev-python/.gitignore @@ -0,0 +1,3 @@ +.env +.venv/ +__pycache__/ diff --git a/jev-python/README.md b/jev-python/README.md new file mode 100644 index 0000000000..c28447a936 --- /dev/null +++ b/jev-python/README.md @@ -0,0 +1,15 @@ +# How to Get Started With Jev in Python + +Sample code for the Real Python tutorial [How to Get Started With Jev in Python](https://realpython.com/jev-python/). + +## Setup + +Create a `.env` file with your OpenRouter API key (see `.env.example`), then run the scripts with uv: + +```console +$ uv run plain_python.py +$ uv run --env-file .env jev_noul.py +$ uv run --env-file .env jev_desk.py +``` + +uv reads `pyproject.toml` and installs `typesafe-sdk` on the first run. If you prefer pip, install the pinned dependency from `requirements.txt` instead. diff --git a/jev-python/jev_desk.py b/jev-python/jev_desk.py new file mode 100644 index 0000000000..539402d5b5 --- /dev/null +++ b/jev-python/jev_desk.py @@ -0,0 +1,49 @@ +import os +from pprint import pprint + +from typesafe_sdk import Choice, Noul, Score, TypeSafeClient + +client = TypeSafeClient( + api_key=os.environ["OPENROUTER_API_KEY"], + base_url="https://openrouter.ai/api", +) + +QUESTIONS = { + "desk": Choice( + instructions="Where should the info desk send the visitor?", + criteria={ + "ticket_counter": "Buying, changing, or refunding tickets.", + "lost_and_found": "Looking for something they lost.", + "immediate_help": "An emergency, an injury, or a missing person.", + }, + ), + "urgency": Score( + instructions="How urgent is the request of the visitor?", + criteria=[ + "Not urgent at all.", + "Should be handled today.", + "Should be handled within the next few minutes.", + "Needs to be handled right now.", + ], + ), + "needs_assistance": Noul( + instructions=( + "Does the visitor need a staff member to help them get around " + "the station, for example because of a wheelchair, heavy " + "luggage, or small children?" + ), + ), +} + + +def main(): + visitor_says = input("What does the visitor say? ") + r = client.system_one( + state={"visitor_says": visitor_says}, + questions=QUESTIONS, + ) + pprint(r.model_dump()["answers"]) + + +if __name__ == "__main__": + main() diff --git a/jev-python/jev_noul.py b/jev-python/jev_noul.py new file mode 100644 index 0000000000..b64026d51e --- /dev/null +++ b/jev-python/jev_noul.py @@ -0,0 +1,43 @@ +import os + +from typesafe_sdk import Noul, TypeSafeClient + +client = TypeSafeClient( + api_key=os.environ["OPENROUTER_API_KEY"], + base_url="https://openrouter.ai/api", +) + + +def respond(lost_something): + if lost_something: + print("You can find the lost and found counter on the right.") + else: + print("What can I help you with?") + + +def ask(): + while True: + answer = input("Did you lose something? ") + r = client.system_one( + state=answer, + questions={ + "lost_something": Noul( + instructions="Is the answer from the user affirmative?" + ), + }, + ) + lost_something = r.answers["lost_something"].noul + if lost_something > 0.8: + return True + if lost_something < 0.2: + return False + print("Sorry, I didn't get that.") + + +def main(): + lost_something = ask() + respond(lost_something) + + +if __name__ == "__main__": + main() diff --git a/jev-python/plain_python.py b/jev-python/plain_python.py new file mode 100644 index 0000000000..e88859b788 --- /dev/null +++ b/jev-python/plain_python.py @@ -0,0 +1,24 @@ +def respond(lost_something): + if lost_something: + print("You can find the lost and found counter on the right.") + else: + print("What can I help you with?") + + +def ask(): + while True: + answer = input("Did you lose something? (Y/N) ") + if answer == "Y": + return True + if answer == "N": + return False + print("Please answer with Y or N.") + + +def main(): + lost_something = ask() + respond(lost_something) + + +if __name__ == "__main__": + main() diff --git a/jev-python/pyproject.toml b/jev-python/pyproject.toml new file mode 100644 index 0000000000..5f0d62b1fe --- /dev/null +++ b/jev-python/pyproject.toml @@ -0,0 +1,7 @@ +[project] +name = "jev-python" +version = "0.1.0" +requires-python = ">=3.14" +dependencies = [ + "typesafe-sdk>=0.7.0", +] diff --git a/jev-python/requirements.txt b/jev-python/requirements.txt new file mode 100644 index 0000000000..52307ef000 --- /dev/null +++ b/jev-python/requirements.txt @@ -0,0 +1 @@ +typesafe-sdk==0.7.1 From 5a1847101466b1ba416ea8d0d613632a59ef07f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Zaczy=C5=84ski?= Date: Thu, 24 Sep 2026 05:27:15 +0000 Subject: [PATCH 2/2] Pin typesafe-sdk and align requires-python with the tutorial Co-Authored-By: Claude Opus 5.5 (1M context) --- jev-python/pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jev-python/pyproject.toml b/jev-python/pyproject.toml index 5f0d62b1fe..f5b5471ca6 100644 --- a/jev-python/pyproject.toml +++ b/jev-python/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "jev-python" version = "0.1.0" -requires-python = ">=3.14" +requires-python = ">=3.10" dependencies = [ - "typesafe-sdk>=0.7.0", + "typesafe-sdk==0.7.1", ]