lionagi 0.8.4__tar.gz → 0.8.6__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.
Files changed (255) hide show
  1. {lionagi-0.8.4 → lionagi-0.8.6}/PKG-INFO +1 -1
  2. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/__init__.py +6 -0
  3. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/ReAct/ReAct.py +40 -8
  4. lionagi-0.8.6/lionagi/operations/ReAct/utils.py +92 -0
  5. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/_act/act.py +8 -0
  6. lionagi-0.8.6/lionagi/operations/interpret/interpret.py +74 -0
  7. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/operate/operate.py +7 -1
  8. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/endpoints/base.py +11 -0
  9. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/imodel.py +11 -0
  10. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/exa_/search.py +4 -4
  11. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/perplexity_/chat_completions.py +4 -0
  12. lionagi-0.8.6/lionagi/service/providers/perplexity_/models.py +144 -0
  13. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/session/branch.py +102 -11
  14. lionagi-0.8.6/lionagi/tools/__init__.py +0 -0
  15. lionagi-0.8.6/lionagi/tools/base.py +12 -0
  16. lionagi-0.8.6/lionagi/tools/reader.py +244 -0
  17. lionagi-0.8.6/lionagi/tools/types.py +3 -0
  18. lionagi-0.8.6/lionagi/version.py +1 -0
  19. {lionagi-0.8.4 → lionagi-0.8.6}/pyproject.toml +5 -1
  20. {lionagi-0.8.4 → lionagi-0.8.6}/uv.lock +1462 -237
  21. lionagi-0.8.4/lionagi/operations/ReAct/utils.py +0 -28
  22. lionagi-0.8.4/lionagi/operations/interpret/interpret.py +0 -43
  23. lionagi-0.8.4/lionagi/version.py +0 -1
  24. {lionagi-0.8.4 → lionagi-0.8.6}/.env.example +0 -0
  25. {lionagi-0.8.4 → lionagi-0.8.6}/.github/FUNDING.yml +0 -0
  26. {lionagi-0.8.4 → lionagi-0.8.6}/.github/dependabot.yml +0 -0
  27. {lionagi-0.8.4 → lionagi-0.8.6}/.github/workflows/ci.yml +0 -0
  28. {lionagi-0.8.4 → lionagi-0.8.6}/.github/workflows/codeql.yml +0 -0
  29. {lionagi-0.8.4 → lionagi-0.8.6}/.github/workflows/docs.yml +0 -0
  30. {lionagi-0.8.4 → lionagi-0.8.6}/.github/workflows/release.yml +0 -0
  31. {lionagi-0.8.4 → lionagi-0.8.6}/.gitignore +0 -0
  32. {lionagi-0.8.4 → lionagi-0.8.6}/.pre-commit-config.yaml +0 -0
  33. {lionagi-0.8.4 → lionagi-0.8.6}/CODE_OF_CONDUCT.md +0 -0
  34. {lionagi-0.8.4 → lionagi-0.8.6}/CONTRIBUTING.md +0 -0
  35. {lionagi-0.8.4 → lionagi-0.8.6}/LICENSE +0 -0
  36. {lionagi-0.8.4 → lionagi-0.8.6}/README.md +0 -0
  37. {lionagi-0.8.4 → lionagi-0.8.6}/cookbooks/ch01_get_started.md +0 -0
  38. {lionagi-0.8.4 → lionagi-0.8.6}/cookbooks/ch02_concepts.md +0 -0
  39. {lionagi-0.8.4 → lionagi-0.8.6}/dev_tools/count_code_base_lines.py +0 -0
  40. {lionagi-0.8.4 → lionagi-0.8.6}/docs/Makefile +0 -0
  41. {lionagi-0.8.4 → lionagi-0.8.6}/docs/_static/custom.css +0 -0
  42. {lionagi-0.8.4 → lionagi-0.8.6}/docs/_templates/layout.html +0 -0
  43. {lionagi-0.8.4 → lionagi-0.8.6}/docs/conf.py +0 -0
  44. {lionagi-0.8.4 → lionagi-0.8.6}/docs/index.rst +0 -0
  45. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/action.rst +0 -0
  46. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/adapter.rst +0 -0
  47. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/branch.rst +0 -0
  48. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/branch_operations.rst +0 -0
  49. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/concepts.rst +0 -0
  50. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/element_id.rst +0 -0
  51. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/event.rst +0 -0
  52. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/form.rst +0 -0
  53. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/graph.rst +0 -0
  54. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/index.rst +0 -0
  55. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/instruct.rst +0 -0
  56. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/lib_file.rst +0 -0
  57. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/lib_nested.rst +0 -0
  58. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/lib_package.rst +0 -0
  59. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/lib_schema.rst +0 -0
  60. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/lib_validate.rst +0 -0
  61. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/log.rst +0 -0
  62. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/mail.rst +0 -0
  63. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/message.rst +0 -0
  64. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/models.rst +0 -0
  65. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/operative_step.rst +0 -0
  66. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/pile.rst +0 -0
  67. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/processor.rst +0 -0
  68. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/progression.rst +0 -0
  69. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/service.rst +0 -0
  70. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/session.rst +0 -0
  71. {lionagi-0.8.4 → lionagi-0.8.6}/docs/modules/utils.rst +0 -0
  72. {lionagi-0.8.4 → lionagi-0.8.6}/docs/tutorials/get_started.rst +0 -0
  73. {lionagi-0.8.4 → lionagi-0.8.6}/docs/tutorials/get_started_pt2.rst +0 -0
  74. {lionagi-0.8.4 → lionagi-0.8.6}/docs/tutorials/get_started_pt3.rst +0 -0
  75. {lionagi-0.8.4 → lionagi-0.8.6}/docs/tutorials/index.rst +0 -0
  76. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/_class_registry.py +0 -0
  77. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/_errors.py +0 -0
  78. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/_types.py +0 -0
  79. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/__init__.py +0 -0
  80. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/file/__init__.py +0 -0
  81. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/file/chunk.py +0 -0
  82. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/file/file_ops.py +0 -0
  83. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/file/params.py +0 -0
  84. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/file/process.py +0 -0
  85. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/file/save.py +0 -0
  86. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/nested/__init__.py +0 -0
  87. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/nested/flatten.py +0 -0
  88. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/nested/nfilter.py +0 -0
  89. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/nested/nget.py +0 -0
  90. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/nested/ninsert.py +0 -0
  91. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/nested/nmerge.py +0 -0
  92. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/nested/npop.py +0 -0
  93. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/nested/nset.py +0 -0
  94. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/nested/unflatten.py +0 -0
  95. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/nested/utils.py +0 -0
  96. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/package/__init__.py +0 -0
  97. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/package/imports.py +0 -0
  98. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/package/management.py +0 -0
  99. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/package/params.py +0 -0
  100. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/package/system.py +0 -0
  101. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/parse.py +0 -0
  102. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/schema/__init__.py +0 -0
  103. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/schema/as_readable.py +0 -0
  104. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/schema/extract_code_block.py +0 -0
  105. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/schema/extract_docstring.py +0 -0
  106. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/schema/function_to_schema.py +0 -0
  107. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/schema/json_schema.py +0 -0
  108. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/token_transform/__init__.py +0 -0
  109. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/token_transform/llmlingua.py +0 -0
  110. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/token_transform/perplexity.py +0 -0
  111. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/token_transform/synthlang.py +0 -0
  112. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/validate/__init__.py +0 -0
  113. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/validate/common_field_validators.py +0 -0
  114. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/validate/fuzzy_match_keys.py +0 -0
  115. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/validate/fuzzy_validate_mapping.py +0 -0
  116. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/validate/string_similarity.py +0 -0
  117. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/libs/validate/validate_boolean.py +0 -0
  118. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/ReAct/__init__.py +0 -0
  119. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/__init__.py +0 -0
  120. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/_act/__init__.py +0 -0
  121. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/brainstorm/__init__.py +0 -0
  122. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/brainstorm/brainstorm.py +0 -0
  123. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/brainstorm/prompt.py +0 -0
  124. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/chat/__init__.py +0 -0
  125. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/chat/chat.py +0 -0
  126. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/communicate/__init__.py +0 -0
  127. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/communicate/communicate.py +0 -0
  128. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/instruct/__init__.py +0 -0
  129. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/instruct/instruct.py +0 -0
  130. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/interpret/__init__.py +0 -0
  131. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/manager.py +0 -0
  132. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/operate/__init__.py +0 -0
  133. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/parse/__init__.py +0 -0
  134. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/parse/parse.py +0 -0
  135. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/plan/__init__.py +0 -0
  136. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/plan/plan.py +0 -0
  137. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/plan/prompt.py +0 -0
  138. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/select/__init__.py +0 -0
  139. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/select/select.py +0 -0
  140. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/select/utils.py +0 -0
  141. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/translate/__init__.py +0 -0
  142. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/translate/translate.py +0 -0
  143. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/types.py +0 -0
  144. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operations/utils.py +0 -0
  145. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/__init__.py +0 -0
  146. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/action/__init__.py +0 -0
  147. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/action/function_calling.py +0 -0
  148. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/action/manager.py +0 -0
  149. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/action/request_response_model.py +0 -0
  150. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/action/tool.py +0 -0
  151. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/action/utils.py +0 -0
  152. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/forms/__init__.py +0 -0
  153. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/forms/base.py +0 -0
  154. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/forms/flow.py +0 -0
  155. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/forms/form.py +0 -0
  156. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/forms/report.py +0 -0
  157. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/instruct/__init__.py +0 -0
  158. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/instruct/base.py +0 -0
  159. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/instruct/instruct.py +0 -0
  160. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/instruct/instruct_collection.py +0 -0
  161. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/instruct/node.py +0 -0
  162. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/instruct/prompts.py +0 -0
  163. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/instruct/reason.py +0 -0
  164. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/manager.py +0 -0
  165. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/models/__init__.py +0 -0
  166. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/models/field_model.py +0 -0
  167. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/models/model_params.py +0 -0
  168. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/models/note.py +0 -0
  169. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/models/operable_model.py +0 -0
  170. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/models/schema_model.py +0 -0
  171. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/operative.py +0 -0
  172. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/step.py +0 -0
  173. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/strategies/__init__.py +0 -0
  174. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/strategies/base.py +0 -0
  175. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/strategies/concurrent.py +0 -0
  176. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/strategies/concurrent_chunk.py +0 -0
  177. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/strategies/concurrent_sequential_chunk.py +0 -0
  178. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/strategies/params.py +0 -0
  179. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/strategies/sequential.py +0 -0
  180. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/strategies/sequential_chunk.py +0 -0
  181. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/strategies/sequential_concurrent_chunk.py +0 -0
  182. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/strategies/utils.py +0 -0
  183. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/operatives/types.py +0 -0
  184. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/__init__.py +0 -0
  185. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/_concepts.py +0 -0
  186. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/adapters/__init__.py +0 -0
  187. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/adapters/adapter.py +0 -0
  188. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/adapters/json_adapter.py +0 -0
  189. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/adapters/pandas_/__init__.py +0 -0
  190. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/adapters/pandas_/csv_adapter.py +0 -0
  191. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/adapters/pandas_/excel_adapter.py +0 -0
  192. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/adapters/pandas_/pd_dataframe_adapter.py +0 -0
  193. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/adapters/pandas_/pd_series_adapter.py +0 -0
  194. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/adapters/types.py +0 -0
  195. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/generic/__init__.py +0 -0
  196. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/generic/element.py +0 -0
  197. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/generic/event.py +0 -0
  198. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/generic/log.py +0 -0
  199. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/generic/pile.py +0 -0
  200. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/generic/processor.py +0 -0
  201. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/generic/progression.py +0 -0
  202. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/graph/__init__.py +0 -0
  203. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/graph/edge.py +0 -0
  204. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/graph/graph.py +0 -0
  205. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/graph/node.py +0 -0
  206. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/mail/__init__.py +0 -0
  207. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/mail/exchange.py +0 -0
  208. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/mail/mail.py +0 -0
  209. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/mail/mailbox.py +0 -0
  210. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/mail/manager.py +0 -0
  211. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/mail/package.py +0 -0
  212. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/__init__.py +0 -0
  213. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/action_request.py +0 -0
  214. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/action_response.py +0 -0
  215. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/assistant_response.py +0 -0
  216. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/base.py +0 -0
  217. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/instruction.py +0 -0
  218. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/manager.py +0 -0
  219. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/message.py +0 -0
  220. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/system.py +0 -0
  221. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/templates/README.md +0 -0
  222. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/templates/action_request.jinja2 +0 -0
  223. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/templates/action_response.jinja2 +0 -0
  224. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/templates/assistant_response.jinja2 +0 -0
  225. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/templates/instruction_message.jinja2 +0 -0
  226. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/templates/system_message.jinja2 +0 -0
  227. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/messages/templates/tool_schemas.jinja2 +0 -0
  228. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/protocols/types.py +0 -0
  229. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/__init__.py +0 -0
  230. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/endpoints/__init__.py +0 -0
  231. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/endpoints/chat_completion.py +0 -0
  232. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/endpoints/match_endpoint.py +0 -0
  233. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/endpoints/rate_limited_processor.py +0 -0
  234. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/endpoints/token_calculator.py +0 -0
  235. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/manager.py +0 -0
  236. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/__init__.py +0 -0
  237. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/anthropic_/__init__.py +0 -0
  238. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/anthropic_/messages.py +0 -0
  239. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/exa_/__init__.py +0 -0
  240. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/exa_/models.py +0 -0
  241. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/exa_/types.py +0 -0
  242. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/groq_/__init__.py +0 -0
  243. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/groq_/chat_completions.py +0 -0
  244. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/openai_/__init__.py +0 -0
  245. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/openai_/chat_completions.py +0 -0
  246. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/openrouter_/__init__.py +0 -0
  247. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/openrouter_/chat_completions.py +0 -0
  248. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/perplexity_/__init__.py +0 -0
  249. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/providers/types.py +0 -0
  250. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/service/types.py +0 -0
  251. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/session/__init__.py +0 -0
  252. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/session/session.py +0 -0
  253. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/settings.py +0 -0
  254. {lionagi-0.8.4 → lionagi-0.8.6}/lionagi/utils.py +0 -0
  255. {lionagi-0.8.4 → lionagi-0.8.6}/prompts/doc_style.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lionagi
3
- Version: 0.8.4
3
+ Version: 0.8.6
4
4
  Summary: An Intelligence Operating System.
5
5
  Author-email: HaiyangLi <quantocean.li@gmail.com>
6
6
  License: Apache License
@@ -2,6 +2,8 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
+ import logging
6
+
5
7
  from pydantic import BaseModel, Field
6
8
 
7
9
  from . import _types as types
@@ -13,6 +15,9 @@ from .version import __version__
13
15
 
14
16
  LiteiModel = iModel
15
17
 
18
+ logger = logging.getLogger(__name__)
19
+ logger.setLevel(logging.INFO)
20
+
16
21
  __all__ = (
17
22
  "Session",
18
23
  "Branch",
@@ -24,4 +29,5 @@ __all__ = (
24
29
  "__version__",
25
30
  "BaseModel",
26
31
  "Field",
32
+ "logger",
27
33
  )
@@ -21,6 +21,10 @@ async def ReAct(
21
21
  branch: "Branch",
22
22
  instruct: Instruct | dict[str, Any],
23
23
  interpret: bool = False,
24
+ interpret_domain: str | None = None,
25
+ interpret_style: str | None = None,
26
+ interpret_sample: str | None = None,
27
+ interpret_kwargs: dict | None = None,
24
28
  tools: Any = None,
25
29
  tool_schemas: Any = None,
26
30
  response_format: type[BaseModel] | BaseModel = None,
@@ -29,6 +33,7 @@ async def ReAct(
29
33
  response_kwargs: dict | None = None,
30
34
  return_analysis: bool = False,
31
35
  analysis_model: iModel | None = None,
36
+ verbose_analysis: bool = False,
32
37
  **kwargs,
33
38
  ):
34
39
  # If no tools or tool schemas are provided, default to "all tools"
@@ -43,7 +48,11 @@ async def ReAct(
43
48
  instruct.to_dict()
44
49
  if isinstance(instruct, Instruct)
45
50
  else instruct
46
- )
51
+ ),
52
+ domain=interpret_domain,
53
+ style=interpret_style,
54
+ sample_writing=interpret_sample,
55
+ **(interpret_kwargs or {}),
47
56
  )
48
57
 
49
58
  # Convert Instruct to dict if necessary
@@ -52,10 +61,13 @@ async def ReAct(
52
61
  if isinstance(instruct, Instruct)
53
62
  else dict(instruct)
54
63
  )
55
- # Overwrite the "instruction" field with the interpreted string (if any)
56
- instruct_dict["instruction"] = instruction_str or instruct_dict.get(
57
- "instruction"
58
- )
64
+
65
+ # Overwrite "instruction" with the interpreted prompt (if any) plus a note about expansions
66
+ max_ext_info = f"\nIf needed, you can do up to {max_extensions or 0 if extension_allowed else 0} expansions."
67
+ instruct_dict["instruction"] = (
68
+ instruction_str
69
+ or (instruct_dict.get("instruction") or "") # in case it's missing
70
+ ) + max_ext_info
59
71
 
60
72
  # Prepare a copy of user-provided kwargs for the first operate call
61
73
  kwargs_for_operate = copy(kwargs)
@@ -73,6 +85,12 @@ async def ReAct(
73
85
  )
74
86
  analyses = [analysis]
75
87
 
88
+ # If verbose, show round #1 analysis
89
+ if verbose_analysis:
90
+ print(
91
+ f"ReAct Round #1 Analysis:\n {analysis.model_dump_json(indent=2)}",
92
+ )
93
+
76
94
  # Validate and clamp max_extensions if needed
77
95
  if max_extensions and max_extensions > 5:
78
96
  logging.warning("max_extensions should not exceed 5; defaulting to 5.")
@@ -80,6 +98,8 @@ async def ReAct(
80
98
 
81
99
  # Step 2: Possibly loop through expansions if extension_needed
82
100
  extensions = max_extensions
101
+ round_count = 1
102
+
83
103
  while (
84
104
  extension_allowed
85
105
  and analysis.extension_needed
@@ -95,16 +115,28 @@ async def ReAct(
95
115
  extensions=extensions
96
116
  )
97
117
 
118
+ operate_kwargs = copy(kwargs)
119
+ operate_kwargs["actions"] = True
120
+ operate_kwargs["reason"] = True
121
+ operate_kwargs["response_format"] = ReActAnalysis
122
+ operate_kwargs["action_strategy"] = analysis.action_strategy
123
+ if analysis.action_batch_size:
124
+ operate_kwargs["action_batch_size"] = analysis.action_batch_size
125
+
98
126
  analysis = await branch.operate(
99
127
  instruction=new_instruction,
100
- response_format=ReActAnalysis,
101
128
  tools=tools,
102
129
  tool_schemas=tool_schemas,
103
- reason=True,
104
- actions=True,
130
+ **operate_kwargs,
105
131
  )
106
132
  analyses.append(analysis)
133
+ round_count += 1
107
134
 
135
+ # If verbose, show round analysis
136
+ if verbose_analysis:
137
+ print(
138
+ f"ReAct Round #{round_count} Analysis:\n {analysis.model_dump_json(indent=2)}",
139
+ )
108
140
  if extensions:
109
141
  extensions -= 1
110
142
 
@@ -0,0 +1,92 @@
1
+ # Copyright (c) 2023 - 2024, HaiyangLi <quantocean.li at gmail dot com>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from typing import ClassVar, Literal
6
+
7
+ from pydantic import BaseModel, Field
8
+
9
+
10
+ class PlannedAction(BaseModel):
11
+ """
12
+ Short descriptor for an upcoming action/tool invocation the LLM wants to perform.
13
+ The model can hold multiple actions in a single round if needed.
14
+ """
15
+
16
+ action_type: str = Field(
17
+ ...,
18
+ description="The name or type of tool/action to invoke (e.g., 'search_exa', 'reader_tool').",
19
+ )
20
+ description: str = Field(
21
+ ...,
22
+ description="A short explanation of why or what is intended to achieve with this action.",
23
+ )
24
+
25
+
26
+ class ReActAnalysis(BaseModel):
27
+ """
28
+ Captures the ReAct chain-of-thought output each round:
29
+ 1) The LLM's 'analysis' (reasoning),
30
+ 2) A list of planned actions to perform before finalizing,
31
+ 3) Indication whether more expansions/rounds are needed,
32
+ 4) Additional tuning knobs: how to handle validation, how to execute actions, etc.
33
+ """
34
+
35
+ # Standard ReAct strings for controlling expansions:
36
+ FIRST_EXT_PROMPT: ClassVar[str] = (
37
+ "You can perform multiple reason-action steps for accuracy. "
38
+ "If you are not ready to finalize, set extension_needed to True. "
39
+ "You have up to {extensions} expansions. Please continue."
40
+ )
41
+ CONTINUE_EXT_PROMPT: ClassVar[str] = (
42
+ "Another round is available. You may do multiple actions if needed. "
43
+ "You have up to {extensions} expansions. Please continue."
44
+ )
45
+ ANSWER_PROMPT: ClassVar[str] = (
46
+ "Given your reasoning and actions, please now provide the final answer "
47
+ "to the user's request:\n\n{instruction}"
48
+ )
49
+
50
+ analysis: str = Field(
51
+ ...,
52
+ description="Free-form reasoning or chain-of-thought summary. Must be consistent with the plan.",
53
+ )
54
+
55
+ planned_actions: list[PlannedAction] = Field(
56
+ default_factory=list,
57
+ description=(
58
+ "One or more short descriptors of the tool calls or operations "
59
+ "the LLM wants to perform this round. For example, read the doc, "
60
+ "then run a search."
61
+ ),
62
+ )
63
+
64
+ extension_needed: bool = Field(
65
+ False,
66
+ description="Set True if more expansions are needed. If False, final answer is next.",
67
+ )
68
+
69
+ milestone: str | None = Field(
70
+ None,
71
+ description=(
72
+ "A sub-goal or mini-checkpoint to reach before finalizing. "
73
+ "E.g. 'Validate results from search_exa, then summarize outcomes.'"
74
+ ),
75
+ )
76
+
77
+ action_strategy: Literal["sequential", "concurrent", "batch"] = Field(
78
+ "concurrent",
79
+ description=(
80
+ "Specifies how to invoke the planned actions:\n"
81
+ "'sequential' => Each action is run in order, \n"
82
+ "'concurrent' => All actions run in parallel, \n"
83
+ "'batch' => Divide actions into async batches of N (if reasonable)."
84
+ ),
85
+ )
86
+
87
+ action_batch_size: int | None = Field(
88
+ None,
89
+ description=(
90
+ "provide if and only if action_strategy is 'batch', this specifies the number of actions to run in parallel per batch."
91
+ ),
92
+ )
@@ -18,6 +18,7 @@ async def _act(
18
18
  branch: "Branch",
19
19
  action_request: BaseModel | dict,
20
20
  suppress_errors: bool = False,
21
+ verbose_action: bool = False,
21
22
  ) -> "ActionResponseModel":
22
23
 
23
24
  _request = {}
@@ -35,6 +36,11 @@ async def _act(
35
36
 
36
37
  try:
37
38
  func_call = await branch._action_manager.invoke(_request)
39
+ if verbose_action:
40
+ print(
41
+ f"Action {_request['function']} invoked, status: {func_call.status}."
42
+ )
43
+
38
44
  except Exception as e:
39
45
  content = {
40
46
  "error": str(e),
@@ -43,6 +49,8 @@ async def _act(
43
49
  "branch": str(branch.id),
44
50
  }
45
51
  branch._log_manager.log(Log(content=content))
52
+ if verbose_action:
53
+ print(f"Action {_request['function']} failed, error: {str(e)}.")
46
54
  if suppress_errors:
47
55
  logging.error(
48
56
  f"Error invoking action '{_request['function']}': {e}"
@@ -0,0 +1,74 @@
1
+ # Copyright (c) 2023 - 2024, HaiyangLi <quantocean.li at gmail dot com>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from typing import TYPE_CHECKING
6
+
7
+ if TYPE_CHECKING:
8
+ from lionagi.session.branch import Branch
9
+
10
+
11
+ async def interpret(
12
+ branch: "Branch",
13
+ text: str,
14
+ domain: str | None = None,
15
+ style: str | None = None,
16
+ sample_writing: str | None = None,
17
+ **kwargs,
18
+ ) -> str:
19
+ instruction = """
20
+ You are given a user's raw instruction or question. Your task is to rewrite it into a clearer, more structured prompt for an LLM or system, making any implicit or missing details explicit.
21
+
22
+ Follow these guidelines:
23
+
24
+ 1. **Dissect the user's request**:
25
+ - If the user references a local file, note it clearly (e.g., "paper_file_path": "…").
26
+ - If the user might need external references or up-to-date data, mention that possibility.
27
+ - If the user's question is ambiguous, propose clarifications.
28
+
29
+ 2. **Be explicit about the user's final objective**:
30
+ - For example, if the user wants a comparison with other works, add that as a bullet point or sub-question.
31
+ - If the user wants a summary plus code snippet, highlight that in your structured prompt.
32
+
33
+ 3. **Do NOT produce final system actions**:
34
+ - You're not calling any tools directly here; only rewriting the user query to reflect potential next steps.
35
+ - If the user's request might require searching or doc reading, note it as an *option*, e.g. "Potential tool usage: {search, partial doc read}."
36
+
37
+ 4. **Return only the improved user prompt**:
38
+ - The final output should be a single text block or short JSON specifying the clarified user request.
39
+ - Keep it concise yet thorough.
40
+
41
+ For instance, if the user's original text is:
42
+ "Please read my local PDF on RL and compare it to the newest research methods from exa or perplexity."
43
+
44
+ A re-written version might be:
45
+ "**Task**:
46
+ - Summarize the local PDF (paper_file_path: 'myRLpaper.pdf').
47
+ - Compare its approach with recent reinforcement learning research found via exa/perplexity searches.
48
+ **Potential Tool Usage**:
49
+ - Doc reading (reader_tool)
50
+ - External search (search_exa, search_perplexity)
51
+ **Output**:
52
+ - A structured summary + comparative analysis."
53
+
54
+ Now, apply this rewriting to the input below. Return only the re-written prompt.
55
+ """
56
+ guidance = (
57
+ f"Domain hint: {domain or 'general'}. "
58
+ f"Desired style: {style or 'concise'}. "
59
+ )
60
+ if sample_writing:
61
+ guidance += f" Sample writing: {sample_writing}"
62
+
63
+ context = [f"User input: {text}"]
64
+
65
+ # Default temperature if none provided
66
+ kwargs["guidance"] = guidance + "\n" + kwargs.get("guidance", "")
67
+ kwargs["instruction"] = instruction + "\n" + kwargs.get("instruction", "")
68
+ kwargs["temperature"] = kwargs.get("temperature", 0.1)
69
+
70
+ refined_prompt = await branch.chat(
71
+ context=context,
72
+ **kwargs,
73
+ )
74
+ return str(refined_prompt)
@@ -50,6 +50,8 @@ async def operate(
50
50
  action_strategy: Literal[
51
51
  "sequential", "concurrent", "batch"
52
52
  ] = "concurrent",
53
+ action_batch_size: int = None,
54
+ verbose_action: bool = False,
53
55
  field_models: list[FieldModel] = None,
54
56
  exclude_fields: list | dict | None = None,
55
57
  request_params: ModelParams = None,
@@ -189,9 +191,13 @@ async def operate(
189
191
  if instruct.action_strategy
190
192
  else action_kwargs.get("strategy", "concurrent")
191
193
  )
194
+ if action_batch_size:
195
+ action_kwargs["batch_size"] = action_batch_size
192
196
 
193
197
  action_response_models = await branch.act(
194
- response_model.action_requests, **action_kwargs
198
+ response_model.action_requests,
199
+ verbose_action=verbose_action,
200
+ **action_kwargs,
195
201
  )
196
202
  # Possibly refine the operative with the tool outputs
197
203
  operative = Step.respond_operative(
@@ -61,6 +61,7 @@ class EndpointConfig(BaseModel):
61
61
  use_enum_values=True,
62
62
  )
63
63
 
64
+ name: str | None = None
64
65
  provider: str | None = None
65
66
  base_url: str | None = None
66
67
  endpoint: str
@@ -75,6 +76,7 @@ class EndpointConfig(BaseModel):
75
76
  requires_tokens: bool = False
76
77
  api_version: str | None = None
77
78
  allowed_roles: list[str] | None = None
79
+ request_options: type | None = None
78
80
 
79
81
 
80
82
  class EndPoint(ABC):
@@ -100,6 +102,11 @@ class EndPoint(ABC):
100
102
  config.update(kwargs)
101
103
  self.config = EndpointConfig(**config)
102
104
 
105
+ @property
106
+ def name(self) -> str | None:
107
+ """str | None: The name of the endpoint, if any."""
108
+ return self.config.name or self.endpoint
109
+
103
110
  @property
104
111
  def is_streamable(self) -> bool:
105
112
  """bool: Whether this endpoint supports streaming responses."""
@@ -185,6 +192,10 @@ class EndPoint(ABC):
185
192
  """bool: Indicates if this endpoint uses role-based messages."""
186
193
  return self.allowed_roles is not None
187
194
 
195
+ @property
196
+ def request_options(self) -> type | None:
197
+ return self.config.request_options
198
+
188
199
  def create_payload(self, **kwargs) -> dict:
189
200
  """Generates a request payload (and headers) for this endpoint.
190
201
 
@@ -5,6 +5,8 @@
5
5
  import os
6
6
  import warnings
7
7
 
8
+ from pydantic import BaseModel
9
+
8
10
  from .endpoints.base import APICalling, EndPoint
9
11
  from .endpoints.match_endpoint import match_endpoint
10
12
  from .endpoints.rate_limited_processor import RateLimitedAPIExecutor
@@ -266,6 +268,15 @@ class iModel:
266
268
  """
267
269
  return self.kwargs.get("model", "")
268
270
 
271
+ @property
272
+ def request_options(self) -> type[BaseModel] | None:
273
+ """type[BaseModel] | None: The request options model for the endpoint.
274
+
275
+ Returns:
276
+ The request options model if available; otherwise, None.
277
+ """
278
+ return self.endpoint.request_options
279
+
269
280
  def to_dict(self):
270
281
  kwargs = self.kwargs
271
282
  if "kwargs" in self.kwargs:
@@ -1,10 +1,8 @@
1
- from typing import TYPE_CHECKING, Literal
1
+ from typing import Literal
2
2
 
3
3
  from lionagi.service.endpoints.base import EndPoint
4
4
 
5
- if TYPE_CHECKING:
6
- from .models import ExaSearchRequest
7
-
5
+ from .models import ExaSearchRequest
8
6
 
9
7
  CATEGORY_OPTIONS = Literal[
10
8
  "article",
@@ -21,6 +19,7 @@ CATEGORY_OPTIONS = Literal[
21
19
  ]
22
20
 
23
21
  SEARCH_CONFIG = {
22
+ "name": "search_exa",
24
23
  "provider": "exa",
25
24
  "base_url": "https://api.exa.ai",
26
25
  "endpoint": "search",
@@ -47,6 +46,7 @@ SEARCH_CONFIG = {
47
46
  "type", # keyword, neural, auto
48
47
  "useAutoPrompt",
49
48
  },
49
+ "request_options": ExaSearchRequest,
50
50
  }
51
51
 
52
52
 
@@ -4,7 +4,10 @@
4
4
 
5
5
  from lionagi.service.endpoints.chat_completion import ChatCompletionEndPoint
6
6
 
7
+ from .models import PerplexityChatCompletionRequest
8
+
7
9
  CHAT_COMPLETION_CONFIG = {
10
+ "name": "search_perplexity",
8
11
  "provider": "perplexity",
9
12
  "base_url": "https://api.perplexity.ai",
10
13
  "endpoint": "chat/completions",
@@ -31,6 +34,7 @@ CHAT_COMPLETION_CONFIG = {
31
34
  "frequency_penalty",
32
35
  },
33
36
  "allowed_roles": ["user", "assistant"],
37
+ "request_options": PerplexityChatCompletionRequest,
34
38
  }
35
39
 
36
40
 
@@ -0,0 +1,144 @@
1
+ from enum import Enum
2
+ from typing import Any
3
+
4
+ from pydantic import BaseModel, Field, model_validator
5
+
6
+
7
+ class PerplexityRole(str, Enum):
8
+ """Roles allowed in Perplexity's messages."""
9
+
10
+ system = "system"
11
+ user = "user"
12
+ assistant = "assistant"
13
+
14
+
15
+ class PerplexityMessage(BaseModel):
16
+ """
17
+ A single message in the conversation.
18
+ `role` can be 'system', 'user', or 'assistant'.
19
+ `content` is the text for that conversation turn.
20
+ """
21
+
22
+ role: PerplexityRole = Field(
23
+ ...,
24
+ description="The role of the speaker. Must be system, user, or assistant.",
25
+ )
26
+ content: str = Field(..., description="The text content of this message.")
27
+
28
+
29
+ class PerplexityChatCompletionRequest(BaseModel):
30
+ """
31
+ Represents the request body for Perplexity's Chat Completions endpoint.
32
+ Endpoint: POST https://api.perplexity.ai/chat/completions
33
+ """
34
+
35
+ model: str = Field(
36
+ ...,
37
+ description="The model name, e.g. 'llama-3.1-sonar-small-128k-online'.",
38
+ )
39
+ messages: list[PerplexityMessage] = Field(
40
+ ..., description="A list of messages forming the conversation so far."
41
+ )
42
+
43
+ # Optional parameters
44
+ frequency_penalty: float | None = Field(
45
+ default=None,
46
+ gt=0,
47
+ description=(
48
+ "Multiplicative penalty > 0. Values > 1.0 penalize repeated tokens more strongly. "
49
+ "Value=1.0 means no penalty. Incompatible with presence_penalty."
50
+ ),
51
+ )
52
+ presence_penalty: float | None = Field(
53
+ default=None,
54
+ ge=-2.0,
55
+ le=2.0,
56
+ description=(
57
+ "Penalizes tokens that have appeared so far (range -2 to 2). "
58
+ "Positive values encourage talking about new topics. Incompatible with frequency_penalty."
59
+ ),
60
+ )
61
+ max_tokens: int | None = Field(
62
+ default=None,
63
+ description=(
64
+ "Maximum number of completion tokens. If omitted, model generates tokens until it "
65
+ "hits stop or context limit."
66
+ ),
67
+ )
68
+ return_images: bool | None = Field(
69
+ default=None,
70
+ description="If True, attempt to return images (closed beta feature).",
71
+ )
72
+ return_related_questions: bool | None = Field(
73
+ default=None,
74
+ description="If True, attempt to return related questions (closed beta feature).",
75
+ )
76
+ search_domain_filter: list[Any] | None = Field(
77
+ default=None,
78
+ description=(
79
+ "List of domains to limit or exclude in the online search. Example: ['example.com', '-twitter.com']. "
80
+ "Supports up to 3 entries. (Closed beta feature.)"
81
+ ),
82
+ )
83
+ search_recency_filter: str | None = Field(
84
+ default=None,
85
+ description=(
86
+ "Returns search results within a specified time interval: 'month', 'week', 'day', or 'hour'."
87
+ ),
88
+ )
89
+ stream: bool | None = Field(
90
+ default=None,
91
+ description=(
92
+ "If True, response is returned incrementally via Server-Sent Events (SSE)."
93
+ ),
94
+ )
95
+ temperature: float | None = Field(
96
+ default=None,
97
+ ge=0.0,
98
+ lt=2.0,
99
+ description=(
100
+ "Controls randomness of sampling, range [0, 2). Higher => more random. "
101
+ "Defaults to 0.2."
102
+ ),
103
+ )
104
+ top_k: int | None = Field(
105
+ default=None,
106
+ ge=0,
107
+ le=2048,
108
+ description=(
109
+ "Top-K filtering. 0 disables top-k filtering. If set, only the top K tokens are considered. "
110
+ "We recommend altering either top_k or top_p, but not both."
111
+ ),
112
+ )
113
+ top_p: float | None = Field(
114
+ default=None,
115
+ ge=0.0,
116
+ le=1.0,
117
+ description=(
118
+ "Nucleus sampling threshold. We recommend altering either top_k or top_p, but not both."
119
+ ),
120
+ )
121
+
122
+ @model_validator(mode="before")
123
+ def validate_penalties(cls, values):
124
+ """
125
+ Disallow using both frequency_penalty != 1.0 and presence_penalty != 0.0 at once,
126
+ since the docs say they're incompatible.
127
+ """
128
+ freq_pen = values.get("frequency_penalty", 1.0)
129
+ pres_pen = values.get("presence_penalty", 0.0)
130
+
131
+ # The doc states frequency_penalty is incompatible with presence_penalty.
132
+ # We'll enforce that if presence_penalty != 0, frequency_penalty must be 1.0
133
+ # or vice versa. Adjust logic as needed.
134
+ if pres_pen != 0.0 and freq_pen != 1.0:
135
+ raise ValueError(
136
+ "presence_penalty is incompatible with frequency_penalty. "
137
+ "Please use only one: either presence_penalty=0 with freq_pen !=1, "
138
+ "or presence_penalty!=0 with freq_pen=1."
139
+ )
140
+ return values
141
+
142
+ def to_dict(self) -> dict:
143
+ """Return a dict suitable for JSON serialization and sending to Perplexity API."""
144
+ return self.model_dump(exclude_none=True)