{"id":19591308,"url":"https://github.com/humanloop/humanloop-python","last_synced_at":"2025-04-27T13:32:06.398Z","repository":{"id":258230379,"uuid":"818259827","full_name":"humanloop/humanloop-python","owner":"humanloop","description":"Official Python SDK for the Humanloop API","archived":false,"fork":false,"pushed_at":"2025-04-21T12:50:19.000Z","size":2114,"stargazers_count":7,"open_issues_count":5,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-21T13:46:07.507Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/humanloop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2024-06-21T12:54:04.000Z","updated_at":"2025-04-16T09:10:48.000Z","dependencies_parsed_at":"2024-10-26T20:57:24.624Z","dependency_job_id":"2fc03335-d226-495b-a7e5-d94214d28d25","html_url":"https://github.com/humanloop/humanloop-python","commit_stats":null,"previous_names":["humanloop/humanloop-python"],"tags_count":82,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanloop%2Fhumanloop-python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanloop%2Fhumanloop-python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanloop%2Fhumanloop-python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanloop%2Fhumanloop-python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/humanloop","download_url":"https://codeload.github.com/humanloop/humanloop-python/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251145578,"owners_count":21543069,"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":"2024-11-11T08:28:28.244Z","updated_at":"2025-04-27T13:32:05.668Z","avatar_url":"https://github.com/humanloop.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Humanloop Python Library\n\n[![fern shield](https://img.shields.io/badge/%F0%9F%8C%BF-Built%20with%20Fern-brightgreen)](https://buildwithfern.com?utm_source=github\u0026utm_medium=github\u0026utm_campaign=readme\u0026utm_source=https%3A%2F%2Fgithub.com%2Fhumanloop%2Fhumanloop-python)\n[![pypi](https://img.shields.io/pypi/v/humanloop)](https://pypi.python.org/pypi/humanloop)\n\nThe Humanloop Python library provides convenient access to the Humanloop API from Python.\n\n## Installation\n\n```sh\npip install humanloop\n```\n\n## Reference\n\nA full reference for this library is available [here](https://github.com/humanloop/humanloop-python/blob/master/reference.md).\n\n## Usage\n\nInstantiate and use the client with the following:\n\n```python\nimport datetime\n\nfrom humanloop import Humanloop\n\nclient = Humanloop(\n    api_key=\"YOUR_API_KEY\",\n)\nclient.prompts.log(\n    path=\"persona\",\n    prompt={\n        \"model\": \"gpt-4\",\n        \"template\": [\n            {\n                \"role\": \"system\",\n                \"content\": \"You are {{person}}. Answer questions as this person. Do not break character.\",\n            }\n        ],\n    },\n    messages=[{\"role\": \"user\", \"content\": \"What really happened at Roswell?\"}],\n    inputs={\"person\": \"Trump\"},\n    created_at=datetime.datetime.fromisoformat(\n        \"2024-07-19 00:29:35.178000+00:00\",\n    ),\n    provider_latency=6.5931549072265625,\n    output_message={\n        \"content\": \"Well, you know, there is so much secrecy involved in government, folks, it's unbelievable. They don't want to tell you everything. They don't tell me everything! But about Roswell, it’s a very popular question. I know, I just know, that something very, very peculiar happened there. Was it a weather balloon? Maybe. Was it something extraterrestrial? Could be. I'd love to go down and open up all the classified documents, believe me, I would. But they don't let that happen. The Deep State, folks, the Deep State. They’re unbelievable. They want to keep everything a secret. But whatever the truth is, I can tell you this: it’s something big, very very big. Tremendous, in fact.\",\n        \"role\": \"assistant\",\n    },\n    prompt_tokens=100,\n    output_tokens=220,\n    prompt_cost=1e-05,\n    output_cost=0.0002,\n    finish_reason=\"stop\",\n)\n```\n\n## Async Client\n\nThe SDK also exports an `async` client so that you can make non-blocking calls to our API.\n\n```python\nimport asyncio\nimport datetime\n\nfrom humanloop import AsyncHumanloop\n\nclient = AsyncHumanloop(\n    api_key=\"YOUR_API_KEY\",\n)\n\n\nasync def main() -\u003e None:\n    await client.prompts.log(\n        path=\"persona\",\n        prompt={\n            \"model\": \"gpt-4\",\n            \"template\": [\n                {\n                    \"role\": \"system\",\n                    \"content\": \"You are {{person}}. Answer questions as this person. Do not break character.\",\n                }\n            ],\n        },\n        messages=[\n            {\"role\": \"user\", \"content\": \"What really happened at Roswell?\"}\n        ],\n        inputs={\"person\": \"Trump\"},\n        created_at=datetime.datetime.fromisoformat(\n            \"2024-07-19 00:29:35.178000+00:00\",\n        ),\n        provider_latency=6.5931549072265625,\n        output_message={\n            \"content\": \"Well, you know, there is so much secrecy involved in government, folks, it's unbelievable. They don't want to tell you everything. They don't tell me everything! But about Roswell, it’s a very popular question. I know, I just know, that something very, very peculiar happened there. Was it a weather balloon? Maybe. Was it something extraterrestrial? Could be. I'd love to go down and open up all the classified documents, believe me, I would. But they don't let that happen. The Deep State, folks, the Deep State. They’re unbelievable. They want to keep everything a secret. But whatever the truth is, I can tell you this: it’s something big, very very big. Tremendous, in fact.\",\n            \"role\": \"assistant\",\n        },\n        prompt_tokens=100,\n        output_tokens=220,\n        prompt_cost=1e-05,\n        output_cost=0.0002,\n        finish_reason=\"stop\",\n    )\n\n\nasyncio.run(main())\n```\n\n## Exception Handling\n\nWhen the API returns a non-success status code (4xx or 5xx response), a subclass of the following error\nwill be thrown.\n\n```python\nfrom humanloop.core.api_error import ApiError\n\ntry:\n    client.prompts.log(...)\nexcept ApiError as e:\n    print(e.status_code)\n    print(e.body)\n```\n\n## Streaming\n\nThe SDK supports streaming responses, as well, the response will be a generator that you can loop over.\n\n```python\nimport datetime\n\nfrom humanloop import Humanloop\n\nclient = Humanloop(\n    api_key=\"YOUR_API_KEY\",\n)\nresponse = client.prompts.call_stream(\n    version_id=\"string\",\n    environment=\"string\",\n    path=\"string\",\n    id=\"string\",\n    messages=[\n        {\n            \"content\": \"string\",\n            \"name\": \"string\",\n            \"tool_call_id\": \"string\",\n            \"role\": \"user\",\n            \"tool_calls\": [\n                {\n                    \"id\": \"string\",\n                    \"type\": \"function\",\n                    \"function\": {\"name\": \"string\"},\n                }\n            ],\n        }\n    ],\n    prompt={\"model\": \"string\"},\n    inputs={\"string\": {\"key\": \"value\"}},\n    source=\"string\",\n    metadata={\"string\": {\"key\": \"value\"}},\n    start_time=datetime.datetime.fromisoformat(\n        \"2024-01-15 09:30:00+00:00\",\n    ),\n    end_time=datetime.datetime.fromisoformat(\n        \"2024-01-15 09:30:00+00:00\",\n    ),\n    source_datapoint_id=\"string\",\n    trace_parent_id=\"string\",\n    user=\"string\",\n    prompts_call_stream_request_environment=\"string\",\n    save=True,\n    provider_api_keys={\n        \"openai\": \"string\",\n        \"ai_21\": \"string\",\n        \"mock\": \"string\",\n        \"anthropic\": \"string\",\n        \"bedrock\": \"string\",\n        \"cohere\": \"string\",\n        \"openai_azure\": \"string\",\n        \"openai_azure_endpoint\": \"string\",\n    },\n    num_samples=1,\n    return_inputs=True,\n    logprobs=1,\n    suffix=\"string\",\n)\nfor chunk in response:\n    yield chunk\n```\n\n## Pagination\n\nPaginated requests will return a `SyncPager` or `AsyncPager`, which can be used as generators for the underlying object.\n\n```python\nfrom humanloop import Humanloop\n\nclient = Humanloop(\n    api_key=\"YOUR_API_KEY\",\n)\nresponse = client.prompts.list(\n    size=1,\n)\nfor item in response:\n    yield item\n# alternatively, you can paginate page-by-page\nfor page in response.iter_pages():\n    yield page\n```\n\n## Advanced\n\n### Retries\n\nThe SDK is instrumented with automatic retries with exponential backoff. A request will be retried as long\nas the request is deemed retriable and the number of retry attempts has not grown larger than the configured\nretry limit (default: 2).\n\nA request is deemed retriable when any of the following HTTP status codes is returned:\n\n- [408](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) (Timeout)\n- [429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) (Too Many Requests)\n- [5XX](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) (Internal Server Errors)\n\nUse the `max_retries` request option to configure this behavior.\n\n```python\nclient.prompts.log(..., request_options={\n    \"max_retries\": 1\n})\n```\n\n### Timeouts\n\nThe SDK defaults to a 60 second timeout. You can configure this with a timeout option at the client or request level.\n\n```python\n\nfrom humanloop import Humanloop\n\nclient = Humanloop(\n    ...,\n    timeout=20.0,\n)\n\n\n# Override timeout for a specific method\nclient.prompts.log(..., request_options={\n    \"timeout_in_seconds\": 1\n})\n```\n\n### Custom Client\n\nYou can override the `httpx` client to customize it for your use-case. Some common use-cases include support for proxies\nand transports.\n```python\nimport httpx\nfrom humanloop import Humanloop\n\nclient = Humanloop(\n    ...,\n    httpx_client=httpx.Client(\n        proxies=\"http://my.test.proxy.example.com\",\n        transport=httpx.HTTPTransport(local_address=\"0.0.0.0\"),\n    ),\n)\n```\n\n## Contributing\n\nWhile we value open-source contributions to this SDK, this library is generated programmatically.\nAdditions made directly to this library would have to be moved over to our generation code,\notherwise they would be overwritten upon the next generated release. Feel free to open a PR as\na proof of concept, but know that we will not be able to merge it as-is. We suggest opening\nan issue first to discuss with us!\n\nOn the other hand, contributions to the README are always very welcome!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhumanloop%2Fhumanloop-python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhumanloop%2Fhumanloop-python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhumanloop%2Fhumanloop-python/lists"}