{"id":25438041,"url":"https://github.com/loopwork-ai/hype","last_synced_at":"2025-11-01T07:30:31.419Z","repository":{"id":256940286,"uuid":"855774103","full_name":"loopwork-ai/hype","owner":"loopwork-ai","description":"Write Python functions. Use them everywhere. HTTP, CLI, GUI, LLM (OMG)","archived":false,"fork":false,"pushed_at":"2025-01-28T18:19:27.000Z","size":174,"stargazers_count":30,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-14T02:39:22.320Z","etag":null,"topics":[],"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/loopwork-ai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2024-09-11T12:53:15.000Z","updated_at":"2025-02-11T22:34:10.000Z","dependencies_parsed_at":null,"dependency_job_id":"b4232e50-c284-4aad-a3e1-e56bc26dc748","html_url":"https://github.com/loopwork-ai/hype","commit_stats":null,"previous_names":["mattt/hype","loopwork-ai/hype"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopwork-ai%2Fhype","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopwork-ai%2Fhype/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopwork-ai%2Fhype/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopwork-ai%2Fhype/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/loopwork-ai","download_url":"https://codeload.github.com/loopwork-ai/hype/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239264787,"owners_count":19610065,"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":[],"created_at":"2025-02-17T09:28:35.063Z","updated_at":"2025-02-17T09:28:35.758Z","avatar_url":"https://github.com/loopwork-ai.png","language":"Python","readme":"# Hype 🆙\n\n\u003e [!WARNING]  \n\u003e This project is in early active development.\n\u003e Expect frequent updates and potential breaking changes.\n\nHype gives your Python functions super powers.\n\n```python hl_lines=\"5\"\nimport hype\nfrom pydantic import Field\n\n\n@hype.up\ndef divide(\n    x: int,\n    y: int = Field(gt=0),\n) -\u003e int:\n    \"\"\"\n    Divides one number by another.\n    :param x: The numerator\n    :param y: The denominator\n    :return: The quotient\n    \"\"\"\n    return x // y\n```\n\nHyped up functions look great to humans 💅\n\n```pycon\n\u003e\u003e\u003e divide\nFunction(name='divide', description='Divides one number by another.', input=(x: int, y: int), output=int)\n```\n\nThey look great to robots, too 🤖❤️\n\n```pycon\n\u003e\u003e\u003e divide.json_schema\n\"{'$defs': {'Input': { ... } } }\"\n```\n\nYou call them the same as you would any other function,\nexcept now you get the benefit of automatic input validation 🦺\n\n```pycon\n\u003e\u003e\u003e divide(4, 2)\n2\n\n\u003e\u003e\u003e divide(y=0)\nValidationError: 2 validation errors for divide\nx\n  Missing required argument [type=missing_argument, input_value=ArgsKwargs((), {'y': 0}), input_type=ArgsKwargs]\n    For further information visit https://errors.pydantic.dev/2.9/v/missing_argument\ny\n  Input should be greater than 0 [type=greater_than, input_value=0, input_type=int]\n    For further information visit https://errors.pydantic.dev/2.9/v/greater_than\n```\n\nHype gives Python functions a universal calling interface.\n\nRun hyped up functions from the command-line ⚙️\n\n```console\n# Hyped up functions are\n\n$ hype run example.py divide 9 3\n3\n\n# You can even run batch jobs\n$ python -c \"import json, random; print('\\n'.join(json.dumps({'x': random.randint(1,1000), 'y': random.randint(0,100)}) for _ in range(3)))\" \u003e input.jsonl\n$ cat input.jsonl\n{\"x\": 49, \"y\": 7}\n{\"x\": 438, \"y\": 73}\n{\"x\": 1, \"y\": 0}\n\n$ hype run example.py divide --input input.jsonl\n7\n6\nError: 1 validation error for divide\ny\n  Input should be greater than 0 [type=greater_than, input_value=0, input_type=int]\n    For further information visit https://errors.pydantic.dev/2.9/v/greater_than\n```\n\nOr serve them through an HTTP interface 🕸️\n\n```console\n$ hype serve example.py \u0026\nStarting server at http://127.0.0.1:4973\nLoading module...\n✓ Found 1 function\n✓ API server ready\n\n$ curl http://localhost:4973/openapi.json | jq .components.schemas.divide_Input\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"x\": {\n      \"type\": \"integer\",\n      \"title\": \"X\",\n      \"description\": \"The numerator\",\n      \"x-order\": 0\n    },\n    \"y\": {\n      \"type\": \"integer\",\n      \"exclusiveMinimum\": 0.0,\n      \"title\": \"Y\",\n      \"description\": \"The denominator\",\n      \"x-order\": 1\n    }\n  },\n  \"required\": [\n    \"x\",\n    \"y\"\n  ]\n}\n\n$ curl -i -X POST http://localhost:4973/divide \\\n          -H \"Content-Type: application/json\"  \\\n          -d '{\"x\": 99, \"y\": 3}'\nHTTP/1.1 200 OK\nContent-Length: 2\nContent-Type: application/json\n\n33\n```\n\nOr if ClickOps are more your thing,\nhype can automatically generate a Gradio app 🖱️\n\n```python\nfrom pydantic import BaseModel, Field, field_validator\nfrom textstat import flesch_reading_ease, lexicon_count\n\nimport hype\n\n\nclass TextAnalysis(BaseModel):\n    word_count: int = Field(description=\"Total number of words in text\")\n    reading_ease: float = Field(\n        description=\"Flesch reading ease score (0-100, higher is easier)\"\n    )\n\n    @field_validator('reading_ease')\n    def clamp_reading_ease(cls, v: float) -\u003e float:\n        return max(0, min(100, v))\n\n\n@hype.up\ndef analyze(\n    text: str = Field(\n        description=\"Text to analyze\",\n        max_length=10000,\n    ),\n) -\u003e TextAnalysis:\n    \"\"\"Performs sentiment and readability analysis on text.\"\"\"\n\n    word_count = lexicon_count(text)\n    reading_ease = flesch_reading_ease(text) if word_count \u003e 0 else 0\n\n    return TextAnalysis(\n        word_count=word_count,\n        reading_ease=reading_ease,\n    )\n\n\nif __name__ == \"__main__\":\n    hype.create_gradio_interface(analyze).launch()\n\n```\n\n```console\n$ uv run examples/text_analysis.py\n$ open http://127.0.0.1:7860\n```\n\n\u003cimg width=\"1243\" alt=\"Screenshot of example Gradio app created by Hype\" src=\"https://github.com/user-attachments/assets/d97e92ff-7469-4c80-a9e0-22b7657129e2\"/\u003e\n\nHyped up functions have tool definitions that you can pass to LLMs like\n[Claude](https://docs.anthropic.com/en/docs/build-with-claude/tool-use) and\n[ChatGPT](https://platform.openai.com/docs/guides/function-calling).\n\nFor example,\nlet's define a pair of functions to help answer a maths problem.\n\n```python\nimport hype\n\n@hype.up\ndef calculate(expression: str) -\u003e int | float:\n    \"\"\"\n    Performs basic arithmetic operations.\n    Supports addition, subtraction, multiplication, and division, and exponentiation.\n\n    :param expression: The mathematical expression to evaluate (e.g., '2 + 3 * 4').\n                       This expression uses Python syntax.\n    \"\"\"\n    ...\n\n@hype.up\ndef prime_factors(n: int) -\u003e set[int]:\n    \"\"\"\n    Determines whether a number is prime.\n\n    :param n: The number to check.\n    \"\"\"\n    ...\n```\n\nHyped up functions can be passed to `hype.create_anthropic_tools`\nto make them available as tools to Claude.\nYou can set an optional `result_type` to shape the language model's output.\n\nIn this example, we pass the `calculate` and `prime_factors` functions\nand set `result_type` to `bool` to indicate that we want a final\n`True` or `False` answer.\n\n```python\nimport anthropic\n\nclient = anthropic.Anthropic()\ntools = hype.create_anthropic_tools([calculate, prime_factors], result_type=bool)\n\nmessages: list[anthropic.types.MessageParam] = [\n    {\n        \"role\": \"user\",\n        \"content\": \"Is two to the power of 57 minus one prime?\",\n    }\n]\n\nfor message in messages:\n    print(message[\"content\"])\n\nwhile not tools.future.done():\n    response = client.messages.create(\n        model=\"claude-3-5-sonnet-20240620\",\n        max_tokens=2046,\n        messages=messages,\n        tools=tools,\n    )\n\n    for block in response.content:\n        print(block)\n\n    if response.stop_reason == \"tool_use\":\n        messages.append({\"role\": \"assistant\", \"content\": response.content})\n        for block in response.content:\n            if block.type == \"tool_use\":\n                messages.append(\n                    {\n                        \"role\": \"user\",\n                        \"content\": [tools(block)],\n                    }\n                )\n    else:\n        break\n\nresult = tools.future.result()\nprint(result, type(result)) # =\u003e False, bool\n```\n\nHere's a transcript of the exchange:\n\n\u003cdl\u003e\n  \u003cdt\u003e👤 Human\u003c/dt\u003e\n  \u003cdd\u003eIs two to the power of 88 minus one prime?\u003c/dd\u003e\n\n  \u003cdt\u003e🤖 AI\u003c/dt\u003e\n  \u003cdd\u003e\n    \u003cp\u003eTo answer this question, we need to perform a couple of steps:\u003c/p\u003e\n    \u003col\u003e\n      \u003cli\u003eCalculate 2^57 - 1\u003c/li\u003e\n      \u003cli\u003eCheck if the resulting number is prime\u003c/li\u003e\n    \u003c/ol\u003e\n    \u003cp\u003eLet's start with the calculation:\u003c/p\u003e\n    \u003ccode\u003e[tool_use name=\"calculate\" input={'expression': '2**57 - 1'}]\u003c/code\u003e\n  \u003c/dd\u003e\n\n  \u003cdt\u003e👤 Human\u003c/dt\u003e\n  \u003cdd\u003e\u003ccode\u003e[tool_use result=144115188075855871]\u003c/code\u003e\u003c/dd\u003e\n\n  \u003cdt\u003e🤖 AI\u003c/dt\u003e\n  \u003cdd\u003e\n    \u003cp\u003eNow that we have the result of 2^57 - 1, which is 144115188075855871, we need to check if this number is prime.\u003c/p\u003e\n    \u003cp\u003eWe can do this by finding its prime factors. If the number has only one prime factor (itself), then it is prime.\u003c/p\u003e\n    \u003cp\u003eLet's use the prime_factors function to check:\u003c/p\u003e\n    \u003ccode\u003e[tool_use name=\"prime_factors\" input={'n': 144115188075855871}]\u003c/code\u003e\n  \u003c/dd\u003e\n\n  \u003cdt\u003e👤 Human\u003c/dt\u003e\n  \u003cdd\u003e\u003ccode\u003e[tool_use result=[7, 32377, 635879915089]]\u003c/code\u003e\u003c/dd\u003e\n\n  \u003cdt\u003e🤖 AI\u003c/dt\u003e\n  \u003cdd\u003e\n    \u003cp\u003eThe prime_factors function returned [7, 32377, 635879915089], which means that 144115188075855871 (2^57 - 1) is not a prime number.\u003c/p\u003e\n    \u003ccode\u003e[tool_use name=\"__return__\" input={'result': False}]\u003c/code\u003e\n  \u003c/dd\u003e\n\u003c/dl\u003e\n\n\u003e [!TIP]\n\u003e There are other Python libraries out there for working with chat assistants,\n\u003e but many wrap client libraries in ways that take control away from you.\n\u003e\n\u003e Hype is designed with composability in mind, and doesn't get in your way.\n\nSee [examples/tool_use.py](/examples/tool_use.py)\nfor the full, working example.\n\n## Installation\n\n```console\npip install git+https://github.com/mattt/hype.git\n```\n\n## Tool Use Examples\n\n### Return typed outputs from AI assistants\n\nHype makes it easy to \u003cdfn\u003eshape\u003c/dfn\u003e outputs from a chat assistant.\n\nIn the previous example, we showed how to use tools to answer a math question,\nbut language models can do a lot on their own.\nSometimes all you need is a way to get a particular kind of answer.\n\nFor instance, GPT-4o excels at extracting structured information\nfrom natural language text,\nlike flight details from the body of an email.\n\nFirst, define a `FlightDetails` class.\nReally go to town with [Pydantic](https://docs.pydantic.dev/latest/).\nThe more precise and pedantic,\nthe better your results will be.\n\n```python\nfrom datetime import datetime\nfrom typing import Annotated\n\nfrom pydantic import BaseModel, Field, StringConstraints\n\nAirportCode = Annotated[str, StringConstraints(min_length=3, max_length=3, pattern=r'^[A-Z]+$')]\n\nclass FlightDetails(BaseModel):\n    origin: AirportCode = Field(\n        description=\"Three-letter IATA airport code for the departure airport.\"\n    )\n\n    destination: AirportCode = Field(\n        description=\"Three-letter IATA airport code for the arrival airport.\"\n    )\n\n    departure_time: datetime = Field(\n        description=\"When the flight is scheduled to depart from its origin\"\n    )\n\n    arrival_time: datetime = Field(\n        description=\"When the flight is scheduled to arrive at its destination\"\n    )\n\n    model_config = {\n        \"json_schema_extra\": {\n            \"examples\": [\n                {\n                    \"origin\": \"LAX\",\n                    \"destination\": \"JFK\",\n                    \"departure_time\": \"2023-06-15T08:00:00Z\",\n                    \"arrival_time\": \"2023-06-15T16:30:00Z\"\n                }\n            ]\n        }\n    }\n```\n\nFrom there,\nthe process is much the same as what we did before.\n\n```python\nfrom anthropic import Anthropic\nimport hype\n\nclient = Anthropic()\ntools = hype.create_anthropic_tools(result_type=FlightDetails)\n\nmessages: list[MessageParam] = [\n    {\n        \"role\": \"user\",\n        \"content\": \"\"\"\n            Extract the flight details from following email:\n\n\n            It's time to check in for your flight.\n            Use the app for smooth sailing and we'll see you soon!\n            Confirmation code: ABCDEF\n\n            Your trip details\n            Flight 420\n            Seat  10D\n            5:00 PM            6:30 PM\n            SFO                PDX\n            San Francisco      Portland, OR\n\n            Departure          Arrival\n            9/20/2023          9/20/2023\n            \"\"\",\n    }\n]\n\nresponse = client.messages.create(\n    model=\"claude-3-5-sonnet-20240620\",\n    max_tokens=2046,\n    messages=messages,\n    tools=tools,\n)\n\nif response.stop_reason == \"tool_use\":\n    for block in response.content:\n        if block.type == \"tool_use\":\n            result = tools(block)\n\nresult = tools.future.result()\nprint(result.model_dump_json(indent=2))\n```\n\n```json\n{\n  \"origin\": \"SFO\",\n  \"destination\": \"PDX\",\n  \"departure_time\": \"2023-09-20T17:00:00Z\",\n  \"arrival_time\": \"2023-09-20T18:30:00Z\"\n}\n```\n\nSee [examples/output_shaping.py](/examples/output_shaping.py)\nfor the full, working example.\n\n### Search the web and scrape webpages\n\nFind recipes with DuckDuckGo,\nscrape content from search results,\nconvert units to metric,\nand return structured output.\n\nSee [examples/web_scaping.py](/examples/web_scraping.py).\n\n### Perform retrival augmented generation (RAG) with vector store\n\nBuild up a database of documents in SQLite\nusing an extension for vector search,\nand use that to answer questions.\n\nSee [examples/rag.py](/examples/rag.py).\n\n### Extract structured information from images\n\nUse GPT-4o to extract board state from a picture of a Sudoku puzzle\nand use tools to solve it.\n\nSee [examples/sudoku.py](/examples/sudoku.py).\n\n### Build interactive tools\n\nBuild tools that get input from the user interactively.\n\nSee [examples/interactive.py](/examples/interactive.py).\n\n### Interact with macOS using AppleScript and Ollama\n\nA glimmer of how to build your own self-hosted, local-first personal assistant.\n\nSee [examples/system_events.py](/examples/system_events.py).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floopwork-ai%2Fhype","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Floopwork-ai%2Fhype","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floopwork-ai%2Fhype/lists"}