payi 0.1.0a39__tar.gz → 0.1.0a40__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of payi might be problematic. Click here for more details.

Files changed (165) hide show
  1. payi-0.1.0a40/.release-please-manifest.json +3 -0
  2. {payi-0.1.0a39 → payi-0.1.0a40}/CHANGELOG.md +8 -0
  3. {payi-0.1.0a39 → payi-0.1.0a40}/PKG-INFO +2 -1
  4. {payi-0.1.0a39 → payi-0.1.0a40}/pyproject.toml +2 -1
  5. {payi-0.1.0a39 → payi-0.1.0a40}/requirements-dev.lock +12 -1
  6. {payi-0.1.0a39 → payi-0.1.0a40}/requirements.lock +12 -1
  7. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_version.py +1 -1
  8. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/lib/AnthropicInstrumentor.py +40 -2
  9. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/lib/OpenAIInstrumentor.py +39 -2
  10. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/lib/instrument.py +21 -4
  11. payi-0.1.0a39/.release-please-manifest.json +0 -3
  12. {payi-0.1.0a39 → payi-0.1.0a40}/.gitignore +0 -0
  13. {payi-0.1.0a39 → payi-0.1.0a40}/CONTRIBUTING.md +0 -0
  14. {payi-0.1.0a39 → payi-0.1.0a40}/LICENSE +0 -0
  15. {payi-0.1.0a39 → payi-0.1.0a40}/README.md +0 -0
  16. {payi-0.1.0a39 → payi-0.1.0a40}/SECURITY.md +0 -0
  17. {payi-0.1.0a39 → payi-0.1.0a40}/api.md +0 -0
  18. {payi-0.1.0a39 → payi-0.1.0a40}/bin/check-release-environment +0 -0
  19. {payi-0.1.0a39 → payi-0.1.0a40}/bin/publish-pypi +0 -0
  20. {payi-0.1.0a39 → payi-0.1.0a40}/examples/.keep +0 -0
  21. {payi-0.1.0a39 → payi-0.1.0a40}/mypy.ini +0 -0
  22. {payi-0.1.0a39 → payi-0.1.0a40}/noxfile.py +0 -0
  23. {payi-0.1.0a39 → payi-0.1.0a40}/release-please-config.json +0 -0
  24. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/__init__.py +0 -0
  25. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_base_client.py +0 -0
  26. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_client.py +0 -0
  27. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_compat.py +0 -0
  28. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_constants.py +0 -0
  29. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_exceptions.py +0 -0
  30. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_files.py +0 -0
  31. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_models.py +0 -0
  32. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_qs.py +0 -0
  33. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_resource.py +0 -0
  34. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_response.py +0 -0
  35. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_streaming.py +0 -0
  36. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_types.py +0 -0
  37. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_utils/__init__.py +0 -0
  38. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_utils/_logs.py +0 -0
  39. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_utils/_proxy.py +0 -0
  40. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_utils/_reflection.py +0 -0
  41. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_utils/_streams.py +0 -0
  42. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_utils/_sync.py +0 -0
  43. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_utils/_transform.py +0 -0
  44. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_utils/_typing.py +0 -0
  45. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/_utils/_utils.py +0 -0
  46. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/lib/.keep +0 -0
  47. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/lib/Instruments.py +0 -0
  48. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/lib/Stopwatch.py +0 -0
  49. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/lib/helpers.py +0 -0
  50. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/py.typed +0 -0
  51. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/__init__.py +0 -0
  52. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/billing_models.py +0 -0
  53. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/categories/__init__.py +0 -0
  54. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/categories/categories.py +0 -0
  55. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/categories/resources.py +0 -0
  56. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/experiences/__init__.py +0 -0
  57. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/experiences/experiences.py +0 -0
  58. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/experiences/properties.py +0 -0
  59. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/experiences/types/__init__.py +0 -0
  60. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/experiences/types/limit_config.py +0 -0
  61. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/experiences/types/types.py +0 -0
  62. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/ingest.py +0 -0
  63. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/limits/__init__.py +0 -0
  64. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/limits/limits.py +0 -0
  65. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/limits/tags.py +0 -0
  66. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/price_modifiers.py +0 -0
  67. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/requests/__init__.py +0 -0
  68. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/requests/properties.py +0 -0
  69. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/requests/requests.py +0 -0
  70. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/resources/requests/result.py +0 -0
  71. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/__init__.py +0 -0
  72. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/billing_model.py +0 -0
  73. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/billing_model_create_params.py +0 -0
  74. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/billing_model_list_response.py +0 -0
  75. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/billing_model_update_params.py +0 -0
  76. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/categories/__init__.py +0 -0
  77. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/categories/resource_create_params.py +0 -0
  78. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/categories/resource_list_response.py +0 -0
  79. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/category_delete_resource_response.py +0 -0
  80. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/category_delete_response.py +0 -0
  81. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/category_list_resources_response.py +0 -0
  82. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/category_list_response.py +0 -0
  83. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/category_resource_response.py +0 -0
  84. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/category_response.py +0 -0
  85. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/cost_data.py +0 -0
  86. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/cost_details.py +0 -0
  87. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/default_response.py +0 -0
  88. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/experience_instance_response.py +0 -0
  89. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/experiences/__init__.py +0 -0
  90. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/experiences/experience_type.py +0 -0
  91. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/experiences/properties_response.py +0 -0
  92. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/experiences/property_create_params.py +0 -0
  93. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/experiences/type_create_params.py +0 -0
  94. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/experiences/type_list_params.py +0 -0
  95. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/experiences/type_list_response.py +0 -0
  96. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/experiences/type_update_params.py +0 -0
  97. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/experiences/types/__init__.py +0 -0
  98. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/experiences/types/limit_config_create_params.py +0 -0
  99. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/ingest_response.py +0 -0
  100. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/ingest_units_params.py +0 -0
  101. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limit_create_params.py +0 -0
  102. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limit_history_response.py +0 -0
  103. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limit_list_params.py +0 -0
  104. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limit_reset_params.py +0 -0
  105. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limit_response.py +0 -0
  106. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limit_update_params.py +0 -0
  107. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limits/__init__.py +0 -0
  108. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limits/limit_tags.py +0 -0
  109. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limits/tag_create_params.py +0 -0
  110. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limits/tag_create_response.py +0 -0
  111. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limits/tag_delete_response.py +0 -0
  112. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limits/tag_list_response.py +0 -0
  113. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limits/tag_remove_params.py +0 -0
  114. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limits/tag_remove_response.py +0 -0
  115. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limits/tag_update_params.py +0 -0
  116. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/limits/tag_update_response.py +0 -0
  117. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/paged_limit_list.py +0 -0
  118. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/pay_i_common_models_api_router_header_info_param.py +0 -0
  119. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/price_modifier.py +0 -0
  120. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/price_modifier_create_params.py +0 -0
  121. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/price_modifier_retrieve_response.py +0 -0
  122. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/price_modifier_update_params.py +0 -0
  123. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/requests/__init__.py +0 -0
  124. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/requests/property_create_params.py +0 -0
  125. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/requests/request_result.py +0 -0
  126. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/requests_data.py +0 -0
  127. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/shared/__init__.py +0 -0
  128. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/shared/evaluation_response.py +0 -0
  129. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/shared/pay_i_common_models_budget_management_cost_details_base.py +0 -0
  130. {payi-0.1.0a39 → payi-0.1.0a40}/src/payi/types/total_cost_data.py +0 -0
  131. {payi-0.1.0a39 → payi-0.1.0a40}/tests/__init__.py +0 -0
  132. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/__init__.py +0 -0
  133. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/categories/__init__.py +0 -0
  134. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/categories/test_resources.py +0 -0
  135. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/experiences/__init__.py +0 -0
  136. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/experiences/test_properties.py +0 -0
  137. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/experiences/test_types.py +0 -0
  138. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/experiences/types/__init__.py +0 -0
  139. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/experiences/types/test_limit_config.py +0 -0
  140. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/limits/__init__.py +0 -0
  141. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/limits/test_tags.py +0 -0
  142. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/requests/__init__.py +0 -0
  143. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/requests/test_properties.py +0 -0
  144. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/requests/test_result.py +0 -0
  145. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/test_billing_models.py +0 -0
  146. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/test_categories.py +0 -0
  147. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/test_experiences.py +0 -0
  148. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/test_ingest.py +0 -0
  149. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/test_limits.py +0 -0
  150. {payi-0.1.0a39 → payi-0.1.0a40}/tests/api_resources/test_price_modifiers.py +0 -0
  151. {payi-0.1.0a39 → payi-0.1.0a40}/tests/conftest.py +0 -0
  152. {payi-0.1.0a39 → payi-0.1.0a40}/tests/sample_file.txt +0 -0
  153. {payi-0.1.0a39 → payi-0.1.0a40}/tests/test_client.py +0 -0
  154. {payi-0.1.0a39 → payi-0.1.0a40}/tests/test_deepcopy.py +0 -0
  155. {payi-0.1.0a39 → payi-0.1.0a40}/tests/test_extract_files.py +0 -0
  156. {payi-0.1.0a39 → payi-0.1.0a40}/tests/test_files.py +0 -0
  157. {payi-0.1.0a39 → payi-0.1.0a40}/tests/test_models.py +0 -0
  158. {payi-0.1.0a39 → payi-0.1.0a40}/tests/test_qs.py +0 -0
  159. {payi-0.1.0a39 → payi-0.1.0a40}/tests/test_required_args.py +0 -0
  160. {payi-0.1.0a39 → payi-0.1.0a40}/tests/test_response.py +0 -0
  161. {payi-0.1.0a39 → payi-0.1.0a40}/tests/test_streaming.py +0 -0
  162. {payi-0.1.0a39 → payi-0.1.0a40}/tests/test_transform.py +0 -0
  163. {payi-0.1.0a39 → payi-0.1.0a40}/tests/test_utils/test_proxy.py +0 -0
  164. {payi-0.1.0a39 → payi-0.1.0a40}/tests/test_utils/test_typing.py +0 -0
  165. {payi-0.1.0a39 → payi-0.1.0a40}/tests/utils.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.1.0-alpha.40"
3
+ }
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.0-alpha.40 (2025-01-31)
4
+
5
+ Full Changelog: [v0.1.0-alpha.39...v0.1.0-alpha.40](https://github.com/Pay-i/pay-i-python/compare/v0.1.0-alpha.39...v0.1.0-alpha.40)
6
+
7
+ ### Features
8
+
9
+ * update units calculation ([a8dda4a](https://github.com/Pay-i/pay-i-python/commit/a8dda4a72b4fa6720e7e3b621f503e435630481f))
10
+
3
11
  ## 0.1.0-alpha.39 (2025-01-31)
4
12
 
5
13
  Full Changelog: [v0.1.0-alpha.38...v0.1.0-alpha.39](https://github.com/Pay-i/pay-i-python/compare/v0.1.0-alpha.38...v0.1.0-alpha.39)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: payi
3
- Version: 0.1.0a39
3
+ Version: 0.1.0a40
4
4
  Summary: The official Python library for the payi API
5
5
  Project-URL: Homepage, https://github.com/Pay-i/pay-i-python
6
6
  Project-URL: Repository, https://github.com/Pay-i/pay-i-python
@@ -27,6 +27,7 @@ Requires-Dist: distro<2,>=1.7.0
27
27
  Requires-Dist: httpx<1,>=0.23.0
28
28
  Requires-Dist: pydantic<3,>=1.9.0
29
29
  Requires-Dist: sniffio
30
+ Requires-Dist: tiktoken>=0.8.0
30
31
  Requires-Dist: typing-extensions<5,>=4.10
31
32
  Requires-Dist: wrapt>=1.17.2
32
33
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "payi"
3
- version = "0.1.0-alpha.39"
3
+ version = "0.1.0-alpha.40"
4
4
  description = "The official Python library for the payi API"
5
5
  dynamic = ["readme"]
6
6
  license = "Apache-2.0"
@@ -15,6 +15,7 @@ dependencies = [
15
15
  "distro>=1.7.0, <2",
16
16
  "sniffio",
17
17
  "wrapt>=1.17.2",
18
+ "tiktoken>=0.8.0",
18
19
  ]
19
20
  requires-python = ">= 3.8"
20
21
  classifiers = [
@@ -7,7 +7,6 @@
7
7
  # all-features: true
8
8
  # with-sources: false
9
9
  # generate-hashes: false
10
- # universal: false
11
10
 
12
11
  -e file:.
13
12
  annotated-types==0.6.0
@@ -20,6 +19,9 @@ argcomplete==3.1.2
20
19
  certifi==2023.7.22
21
20
  # via httpcore
22
21
  # via httpx
22
+ # via requests
23
+ charset-normalizer==3.4.1
24
+ # via requests
23
25
  colorlog==6.7.0
24
26
  # via nox
25
27
  dirty-equals==0.6.0
@@ -42,6 +44,7 @@ httpx==0.28.1
42
44
  idna==3.4
43
45
  # via anyio
44
46
  # via httpx
47
+ # via requests
45
48
  importlib-metadata==7.0.0
46
49
  iniconfig==2.0.0
47
50
  # via pytest
@@ -77,6 +80,10 @@ python-dateutil==2.8.2
77
80
  # via time-machine
78
81
  pytz==2023.3.post1
79
82
  # via dirty-equals
83
+ regex==2024.11.6
84
+ # via tiktoken
85
+ requests==2.32.3
86
+ # via tiktoken
80
87
  respx==0.22.0
81
88
  rich==13.7.1
82
89
  ruff==0.6.9
@@ -87,6 +94,8 @@ six==1.16.0
87
94
  sniffio==1.3.0
88
95
  # via anyio
89
96
  # via payi
97
+ tiktoken==0.8.0
98
+ # via payi
90
99
  time-machine==2.9.0
91
100
  tomli==2.0.2
92
101
  # via mypy
@@ -98,6 +107,8 @@ typing-extensions==4.12.2
98
107
  # via pydantic
99
108
  # via pydantic-core
100
109
  # via pyright
110
+ urllib3==2.3.0
111
+ # via requests
101
112
  virtualenv==20.24.5
102
113
  # via nox
103
114
  wrapt==1.17.2
@@ -7,7 +7,6 @@
7
7
  # all-features: true
8
8
  # with-sources: false
9
9
  # generate-hashes: false
10
- # universal: false
11
10
 
12
11
  -e file:.
13
12
  annotated-types==0.6.0
@@ -18,6 +17,9 @@ anyio==4.4.0
18
17
  certifi==2023.7.22
19
18
  # via httpcore
20
19
  # via httpx
20
+ # via requests
21
+ charset-normalizer==3.4.1
22
+ # via requests
21
23
  distro==1.8.0
22
24
  # via payi
23
25
  exceptiongroup==1.2.2
@@ -31,17 +33,26 @@ httpx==0.28.1
31
33
  idna==3.4
32
34
  # via anyio
33
35
  # via httpx
36
+ # via requests
34
37
  pydantic==2.10.3
35
38
  # via payi
36
39
  pydantic-core==2.27.1
37
40
  # via pydantic
41
+ regex==2024.11.6
42
+ # via tiktoken
43
+ requests==2.32.3
44
+ # via tiktoken
38
45
  sniffio==1.3.0
39
46
  # via anyio
40
47
  # via payi
48
+ tiktoken==0.8.0
49
+ # via payi
41
50
  typing-extensions==4.12.2
42
51
  # via anyio
43
52
  # via payi
44
53
  # via pydantic
45
54
  # via pydantic-core
55
+ urllib3==2.3.0
56
+ # via requests
46
57
  wrapt==1.17.2
47
58
  # via payi
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "payi"
4
- __version__ = "0.1.0-alpha.39" # x-release-please-version
4
+ __version__ = "0.1.0-alpha.40" # x-release-please-version
@@ -1,6 +1,7 @@
1
1
  import logging
2
- from typing import Any
2
+ from typing import Any, Union
3
3
 
4
+ import tiktoken
4
5
  from wrapt import wrap_function_wrapper # type: ignore
5
6
 
6
7
  from payi.types import IngestUnitsParams
@@ -49,6 +50,7 @@ def chat_wrapper(
49
50
  return instrumentor.chat_wrapper(
50
51
  "system.anthropic",
51
52
  process_chunk,
53
+ process_request,
52
54
  process_synchronous_response,
53
55
  wrapped,
54
56
  instance,
@@ -62,7 +64,9 @@ def process_chunk(chunk: Any, ingest: IngestUnitsParams) -> None:
62
64
  usage = chunk.message.usage
63
65
  units = ingest["units"]
64
66
 
65
- units["text"] = Units(input=usage.input_tokens, output=0)
67
+ input = PayiInstrumentor.update_for_vision(usage.input_tokens, units)
68
+
69
+ units["text"] = Units(input=input, output=0)
66
70
 
67
71
  if hasattr(usage, "cache_creation_input_tokens") and usage.cache_creation_input_tokens > 0:
68
72
  text_cache_write = usage.cache_creation_input_tokens
@@ -91,7 +95,41 @@ def process_synchronous_response(response: Any, ingest: IngestUnitsParams, log_p
91
95
  text_cache_read = usage.cache_read_input_tokens
92
96
  units["text_cache_read"] = Units(input=text_cache_read, output=0)
93
97
 
98
+ input = PayiInstrumentor.update_for_vision(input, units)
99
+
94
100
  units["text"] = Units(input=input, output=ouptut)
95
101
 
96
102
  if log_prompt_and_response:
97
103
  ingest["provider_response_json"] = response.to_json()
104
+
105
+ def has_image_and_get_texts(encoding: tiktoken.Encoding, content: Union[str, 'list[Any]']) -> 'tuple[bool, int]':
106
+ if isinstance(content, str):
107
+ return False, 0
108
+ elif isinstance(content, list): # type: ignore
109
+ has_image = any(item.get("type") == "image" for item in content)
110
+ if has_image is False:
111
+ return has_image, 0
112
+
113
+ token_count = sum(len(encoding.encode(item.get("text", ""))) for item in content if item.get("type") == "text")
114
+ return has_image, token_count
115
+
116
+ def process_request(ingest: IngestUnitsParams, kwargs: Any) -> None:
117
+ messages = kwargs.get("messages")
118
+ if not messages or len(messages) == 0:
119
+ return
120
+
121
+ estimated_token_count = 0
122
+ has_image = False
123
+
124
+ enc = tiktoken.get_encoding("cl100k_base")
125
+
126
+ for message in messages:
127
+ msg_has_image, msg_prompt_tokens = has_image_and_get_texts(enc, message.get('content', ''))
128
+ if msg_has_image:
129
+ has_image = True
130
+ estimated_token_count += msg_prompt_tokens
131
+
132
+ if not has_image or estimated_token_count == 0:
133
+ return
134
+
135
+ ingest["units"][PayiInstrumentor.estimated_prompt_tokens] = Units(input=estimated_token_count, output=0)
@@ -1,8 +1,9 @@
1
1
  import json
2
2
  import logging
3
- from typing import Any
3
+ from typing import Any, Union
4
4
  from importlib.metadata import version
5
5
 
6
+ import tiktoken
6
7
  from wrapt import wrap_function_wrapper # type: ignore
7
8
 
8
9
  from payi.types import IngestUnitsParams
@@ -38,6 +39,7 @@ def chat_wrapper(
38
39
  return instrumentor.chat_wrapper(
39
40
  "system.openai",
40
41
  process_chat_chunk,
42
+ process_request,
41
43
  process_chat_synchronous_response,
42
44
  wrapped,
43
45
  instance,
@@ -84,6 +86,41 @@ def add_usage_units(usage: "dict[str, Any]", units: "dict[str, Units]") -> None:
84
86
  if input_cache != 0:
85
87
  units["text_cache_read"] = Units(input=input_cache, output=0)
86
88
 
87
- input -= input_cache
89
+ input = PayiInstrumentor.update_for_vision(input - input_cache, units)
88
90
 
89
91
  units["text"] = Units(input=input, output=output)
92
+
93
+ def has_image_and_get_texts(encoding: tiktoken.Encoding, content: Union[str, 'list[Any]']) -> 'tuple[bool, int]':
94
+ if isinstance(content, str):
95
+ return False, 0
96
+ elif isinstance(content, list): # type: ignore
97
+ has_image = any(item.get("type") == "image_url" for item in content)
98
+ if has_image is False:
99
+ return has_image, 0
100
+
101
+ token_count = sum(len(encoding.encode(item.get("text", ""))) for item in content if item.get("type") == "text")
102
+ return has_image, token_count
103
+
104
+ def process_request(ingest: IngestUnitsParams, kwargs: Any) -> None:
105
+ messages = kwargs.get("messages")
106
+ if not messages or len(messages) == 0:
107
+ return
108
+
109
+ estimated_token_count = 0
110
+ has_image = False
111
+
112
+ try:
113
+ enc = tiktoken.encoding_for_model(kwargs.get("model"))
114
+ except KeyError:
115
+ enc = tiktoken.get_encoding("o200k_base")
116
+
117
+ for message in messages:
118
+ msg_has_image, msg_prompt_tokens = has_image_and_get_texts(enc, message.get('content', ''))
119
+ if msg_has_image:
120
+ has_image = True
121
+ estimated_token_count += msg_prompt_tokens
122
+
123
+ if not has_image or estimated_token_count == 0:
124
+ return
125
+
126
+ ingest["units"][PayiInstrumentor.estimated_prompt_tokens] = Units(input=estimated_token_count, output=0)
@@ -10,12 +10,15 @@ from wrapt import ObjectProxy # type: ignore
10
10
 
11
11
  from payi import Payi, AsyncPayi
12
12
  from payi.types import IngestUnitsParams
13
+ from payi.types.ingest_units_params import Units
13
14
 
14
15
  from .Stopwatch import Stopwatch
15
16
  from .Instruments import Instruments
16
17
 
17
18
 
18
19
  class PayiInstrumentor:
20
+ estimated_prompt_tokens: str = "estimated_prompt_tokens"
21
+
19
22
  def __init__(
20
23
  self,
21
24
  payi: Union[Payi, AsyncPayi, None] = None,
@@ -204,11 +207,12 @@ class PayiInstrumentor:
204
207
  self,
205
208
  category: str,
206
209
  process_chunk: Callable[[Any, IngestUnitsParams], None],
210
+ process_request: Optional[Callable[[IngestUnitsParams, Any], None]],
207
211
  process_synchronous_response: Optional[Callable[[Any, IngestUnitsParams, bool], None]],
208
212
  wrapped: Any,
209
213
  instance: Any,
210
214
  args: Any,
211
- kwargs: Any,
215
+ kwargs: 'dict[str, Any]',
212
216
  ) -> Any:
213
217
  context = self.get_context()
214
218
 
@@ -226,7 +230,7 @@ class PayiInstrumentor:
226
230
 
227
231
  return wrapped(*args, **kwargs)
228
232
 
229
- ingest: IngestUnitsParams = {"category": category, "resource": kwargs.get("model"), "units": {}}
233
+ ingest: IngestUnitsParams = {"category": category, "resource": kwargs.get("model"), "units": {}} # type: ignore
230
234
 
231
235
  # blocked_limit = next((limit for limit in (context.get('limit_ids') or []) if limit in self._blocked_limits), None)
232
236
  # if blocked_limit:
@@ -235,8 +239,10 @@ class PayiInstrumentor:
235
239
  # f_back excludes the current frame, strip() cleans up whitespace and newlines
236
240
  stack = [frame.strip() for frame in traceback.format_stack(current_frame.f_back)] # type: ignore
237
241
 
238
- # TODO add back once feature is in prod
239
- # ingest['properties'] = { 'system.stack_trace': json.dumps(stack) }
242
+ ingest['properties'] = { 'system.stack_trace': json.dumps(stack) }
243
+
244
+ if process_request:
245
+ process_request(ingest, kwargs)
240
246
 
241
247
  sw = Stopwatch()
242
248
  stream = kwargs.get("stream", False)
@@ -354,6 +360,17 @@ class PayiInstrumentor:
354
360
  if experience_id is not None:
355
361
  extra_headers["xProxy-Experience-ID"] = experience_id
356
362
 
363
+ @staticmethod
364
+ def update_for_vision(input: int, units: 'dict[str, Units]') -> int:
365
+ if PayiInstrumentor.estimated_prompt_tokens in units:
366
+ prompt_token_estimate: int = units.pop(PayiInstrumentor.estimated_prompt_tokens)["input"] # type: ignore
367
+ vision = input - prompt_token_estimate
368
+ if (vision > 0):
369
+ units["vision"] = Units(input=vision, output=0)
370
+ input = prompt_token_estimate
371
+
372
+ return input
373
+
357
374
  @staticmethod
358
375
  def payi_wrapper(func: Any) -> Any:
359
376
  def _payi_wrapper(o: Any) -> Any:
@@ -1,3 +0,0 @@
1
- {
2
- ".": "0.1.0-alpha.39"
3
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes