divi 0.0.1.dev23__tar.gz → 0.0.1.dev47__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 (240) hide show
  1. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/PKG-INFO +1 -1
  2. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/graphql/package.json +2 -2
  3. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/graphql/src/datasources/datapark-api.ts +7 -1
  4. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/graphql/src/resolvers.ts +3 -0
  5. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/graphql/src/schema.graphql +13 -2
  6. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/graphql/src/types/types.d.ts +34 -4
  7. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(children)/[id]/components/Span.tsx +43 -7
  8. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(children)/[id]/components/trace-board.tsx +5 -0
  9. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(children)/[id]/components/trace-chart.tsx +4 -1
  10. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/usages/actions.ts +4 -2
  11. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/home/components/home-hero.tsx +1 -1
  12. divi-0.0.1.dev47/apps/web/lib/server/evaluation.ts +17 -0
  13. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/lib/server/span.ts +27 -3
  14. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/lib/types/span.d.ts +5 -1
  15. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/package.json +9 -8
  16. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/__init__.py +5 -2
  17. divi-0.0.1.dev47/divi/decorators/collect.py +34 -0
  18. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/decorators/obs_openai.py +21 -5
  19. divi-0.0.1.dev47/divi/decorators/observable.py +91 -0
  20. divi-0.0.1.dev47/divi/decorators/observe.py +47 -0
  21. divi-0.0.1.dev47/divi/evaluation/__init__.py +4 -0
  22. divi-0.0.1.dev47/divi/evaluation/evaluate.py +61 -0
  23. divi-0.0.1.dev47/divi/evaluation/evaluator.py +174 -0
  24. divi-0.0.1.dev47/divi/evaluation/prompts.py +19 -0
  25. divi-0.0.1.dev47/divi/evaluation/scores.py +8 -0
  26. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/proto/trace/v1/trace.proto +3 -0
  27. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/proto/trace/v1/trace_pb2.py +3 -3
  28. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/proto/trace/v1/trace_pb2.pyi +2 -0
  29. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/datapark/datapark.py +21 -3
  30. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/init.py +5 -2
  31. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/session/session.py +1 -1
  32. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/session/setup.py +7 -4
  33. divi-0.0.1.dev47/divi/signals/__init__.py +3 -0
  34. divi-0.0.1.dev47/divi/signals/span.py +83 -0
  35. divi-0.0.1.dev47/divi/signals/trace.py +79 -0
  36. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/package.json +1 -1
  37. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/pnpm-lock.yaml +868 -780
  38. divi-0.0.1.dev47/services/internal/app/datapark/handler/evaluation.go +147 -0
  39. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/app/datapark/handler/openai.go +4 -3
  40. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/app/datapark/handler/trace.go +56 -13
  41. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/app/datapark/router/router.go +3 -0
  42. divi-0.0.1.dev47/services/internal/pkg/model/score.go +16 -0
  43. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/pkg/model/trace.go +2 -2
  44. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/pb/trace.pb.go +12 -6
  45. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/turbo.json +2 -1
  46. divi-0.0.1.dev47/uv.lock +654 -0
  47. divi-0.0.1.dev23/divi/config/config.py +0 -0
  48. divi-0.0.1.dev23/divi/decorators/observable.py +0 -119
  49. divi-0.0.1.dev23/divi/signals/__init__.py +0 -3
  50. divi-0.0.1.dev23/divi/signals/trace/__init__.py +0 -3
  51. divi-0.0.1.dev23/divi/signals/trace/trace.py +0 -151
  52. divi-0.0.1.dev23/uv.lock +0 -654
  53. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/.air.toml +0 -0
  54. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/.dockerignore +0 -0
  55. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/.github/dependabot.yml +0 -0
  56. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/.gitignore +0 -0
  57. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/LICENSE +0 -0
  58. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/README.md +0 -0
  59. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/README.md +0 -0
  60. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/docs/README.md +0 -0
  61. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/docs/concepts/session.mdx +0 -0
  62. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/docs/development/roadmap.mdx +0 -0
  63. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/docs/docs.json +0 -0
  64. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/docs/favicon.ico +0 -0
  65. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/docs/images/researcher-angel.png +0 -0
  66. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/docs/images/scholar-angel.png +0 -0
  67. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/docs/introduction.mdx +0 -0
  68. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/docs/package.json +0 -0
  69. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/docs/quickstart/trace.mdx +0 -0
  70. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/docs/snippets/snippet-intro.mdx +0 -0
  71. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/docs/tutorials/openai.mdx +0 -0
  72. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/graphql/Dockerfile +0 -0
  73. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/graphql/README.md +0 -0
  74. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/graphql/codegen.ts +0 -0
  75. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/graphql/src/datasources/auth-api.ts +0 -0
  76. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/graphql/src/index.ts +0 -0
  77. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/graphql/src/types/context.d.ts +0 -0
  78. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/graphql/src/types/response.d.ts +0 -0
  79. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/graphql/tsconfig.json +0 -0
  80. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/.gitignore +0 -0
  81. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/README.md +0 -0
  82. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/@modal/(.)traces/[id]/page.tsx +0 -0
  83. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/@modal/default.tsx +0 -0
  84. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/actions.ts +0 -0
  85. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/components/columns.tsx +0 -0
  86. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/components/create-dialog.tsx +0 -0
  87. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/components/data-table-cell-viewer.tsx +0 -0
  88. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/components/data-table-toolbar.tsx +0 -0
  89. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/components/data-table.tsx +0 -0
  90. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/components/delete-dialog.tsx +0 -0
  91. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/data/data.tsx +0 -0
  92. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/data/schema.ts +0 -0
  93. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/layout.tsx +0 -0
  94. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/page.tsx +0 -0
  95. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/components/app-sidebar.tsx +0 -0
  96. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/components/nav-main.tsx +0 -0
  97. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/components/nav-secondary.tsx +0 -0
  98. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/components/nav-user.tsx +0 -0
  99. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/components/site-header.tsx +0 -0
  100. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/layout.tsx +0 -0
  101. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/account/components/account-form.tsx +0 -0
  102. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/account/page.tsx +0 -0
  103. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/appearance/components/appearance-form.tsx +0 -0
  104. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/appearance/page.tsx +0 -0
  105. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/components/profile-form.tsx +0 -0
  106. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/components/sidebar-nav.tsx +0 -0
  107. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/layout.tsx +0 -0
  108. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/page.tsx +0 -0
  109. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(children)/[id]/components/responsive-resizable.tsx +0 -0
  110. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(children)/[id]/page.tsx +0 -0
  111. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/components/columns.tsx +0 -0
  112. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/components/data-table-row-action.tsx +0 -0
  113. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/components/data-table-toolbar.tsx +0 -0
  114. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/components/data-table.tsx +0 -0
  115. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/data/data.tsx +0 -0
  116. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/data/schema.ts +0 -0
  117. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/layout.tsx +0 -0
  118. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/page.tsx +0 -0
  119. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/usages/components/usage-board.tsx +0 -0
  120. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/usages/components/usage-chart.tsx +0 -0
  121. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/usages/layout.tsx +0 -0
  122. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/dashboard/usages/page.tsx +0 -0
  123. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/favicon.ico +0 -0
  124. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/home/components/home-header.tsx +0 -0
  125. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/home/page.tsx +0 -0
  126. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/layout.tsx +0 -0
  127. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/login/components/login-form.tsx +0 -0
  128. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/login/page.tsx +0 -0
  129. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/page.tsx +0 -0
  130. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/signup/components/signup-form.tsx +0 -0
  131. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/app/signup/page.tsx +0 -0
  132. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/components/ApolloWrapper.tsx +0 -0
  133. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/components/Highter.tsx +0 -0
  134. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/components/Modal.tsx +0 -0
  135. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/components/calendar.tsx +0 -0
  136. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/components/data-table-column-header.tsx +0 -0
  137. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/components/data-table-faceted-filter.tsx +0 -0
  138. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/components/data-table-pagination.tsx +0 -0
  139. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/components/data-table-row.tsx +0 -0
  140. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/components/data-table-view-options.tsx +0 -0
  141. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/components/date-picker.tsx +0 -0
  142. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/components/mode-switcher.tsx +0 -0
  143. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/components/theme-provider.tsx +0 -0
  144. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/components.json +0 -0
  145. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/hooks/actionState.ts +0 -0
  146. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/hooks/apolloClient.ts +0 -0
  147. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/lib/callback/toast-callback.ts +0 -0
  148. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/lib/callback/with-callback.ts +0 -0
  149. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/lib/server/README.md +0 -0
  150. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/lib/server/auth.ts +0 -0
  151. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/lib/server/cookies.ts +0 -0
  152. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/lib/server/openai.ts +0 -0
  153. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/lib/types/state.d.ts +0 -0
  154. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/lib/types/usage.d.ts +0 -0
  155. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/lib/utils.ts +0 -0
  156. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/middleware.ts +0 -0
  157. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/next-env.d.ts +0 -0
  158. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/next.config.ts +0 -0
  159. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/postcss.config.mjs +0 -0
  160. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/public/peeking-angel.png +0 -0
  161. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/public/thinking-angel.png +0 -0
  162. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/tsconfig.json +0 -0
  163. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/apps/web/vercel.json +0 -0
  164. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/biome.json +0 -0
  165. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/compose-dev.yml +0 -0
  166. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/decorators/__init__.py +0 -0
  167. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/proto/common/v1/common.proto +0 -0
  168. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/proto/common/v1/common_pb2.py +0 -0
  169. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/proto/common/v1/common_pb2.pyi +0 -0
  170. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/proto/core/health/v1/health_service.proto +0 -0
  171. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/proto/core/health/v1/health_service_pb2.py +0 -0
  172. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/proto/core/health/v1/health_service_pb2.pyi +0 -0
  173. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/proto/core/health/v1/health_service_pb2_grpc.py +0 -0
  174. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/proto/metric/v1/metric.proto +0 -0
  175. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/proto/metric/v1/metric_pb2.py +0 -0
  176. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/proto/metric/v1/metric_pb2.pyi +0 -0
  177. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/__init__.py +0 -0
  178. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/auth/__init__.py +0 -0
  179. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/auth/auth.py +0 -0
  180. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/auth/init.py +0 -0
  181. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/auth/tokman.py +0 -0
  182. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/core/__init__.py +0 -0
  183. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/core/core.py +0 -0
  184. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/core/finish.py +0 -0
  185. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/core/init.py +0 -0
  186. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/datapark/__init__.py +0 -0
  187. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/datapark/init.py +0 -0
  188. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/finish.py +0 -0
  189. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/services/service.py +0 -0
  190. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/session/__init__.py +0 -0
  191. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/session/teardown.py +0 -0
  192. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/divi/utils.py +0 -0
  193. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/docker-compose.yml +0 -0
  194. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/docs/README.md +0 -0
  195. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/docs/developer_tools.md +0 -0
  196. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/docs/images/architecture.svg +0 -0
  197. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/docs/images/favicon.ico +0 -0
  198. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/docs/images/og-image.png +0 -0
  199. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/docs/images/storage.svg +0 -0
  200. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/docs/package_readme.md +0 -0
  201. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/go.work +0 -0
  202. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/go.work.sum +0 -0
  203. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/hatch.toml +0 -0
  204. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/packages/README.md +0 -0
  205. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/pnpm-workspace.yaml +0 -0
  206. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/pyproject.toml +0 -0
  207. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/scripts/README.md +0 -0
  208. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/scripts/hatch_build.py +0 -0
  209. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/scripts/key_build.py +0 -0
  210. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/scripts/proto_build.py +0 -0
  211. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/README.md +0 -0
  212. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/go.mod +0 -0
  213. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/go.sum +0 -0
  214. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/app/auth/handler/api.go +0 -0
  215. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/app/auth/handler/api_key.go +0 -0
  216. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/app/auth/handler/auth.go +0 -0
  217. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/app/auth/handler/user.go +0 -0
  218. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/app/auth/router/router.go +0 -0
  219. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/app/core/.keep +0 -0
  220. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/app/datapark/handler/api.go +0 -0
  221. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/app/datapark/handler/metric.go +0 -0
  222. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/app/datapark/handler/session.go +0 -0
  223. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/app/datapark/handler/usage.go +0 -0
  224. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/pkg/auth/auth.go +0 -0
  225. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/pkg/auth/middleware.go +0 -0
  226. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/pkg/config/config.go +0 -0
  227. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/pkg/database/connect.go +0 -0
  228. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/pkg/database/database.go +0 -0
  229. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/pkg/model/api_key.go +0 -0
  230. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/pkg/model/openai.go +0 -0
  231. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/pkg/model/session.go +0 -0
  232. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/pkg/model/usage.go +0 -0
  233. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/internal/pkg/model/user.go +0 -0
  234. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/pb/common.pb.go +0 -0
  235. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/pb/health_service.pb.go +0 -0
  236. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/pb/health_service_grpc.pb.go +0 -0
  237. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/services/pb/metric.pb.go +0 -0
  238. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/tests/__init__.py +0 -0
  239. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/tests/unit_tests/decorators/test_obs_openai.py +0 -0
  240. {divi-0.0.1.dev23 → divi-0.0.1.dev47}/tests/unit_tests/decorators/test_observable.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: divi
3
- Version: 0.0.1.dev23
3
+ Version: 0.0.1.dev47
4
4
  Summary: The Agent Platform for Observability & Evaluation
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.11
@@ -13,7 +13,7 @@
13
13
  "@apollo/datasource-rest": "^6.4.1",
14
14
  "@apollo/server": "^4.12.0",
15
15
  "@apollo/utils.keyvaluecache": "^3.1.0",
16
- "graphql": "^16.10.0",
16
+ "graphql": "^16.11.0",
17
17
  "graphql-tag": "^2.12.6"
18
18
  },
19
19
  "devDependencies": {
@@ -21,7 +21,7 @@
21
21
  "@graphql-codegen/typescript": "^4.1.6",
22
22
  "@graphql-codegen/typescript-resolvers": "^4.5.0",
23
23
  "@workspace/typescript-config": "workspace:*",
24
- "nodemon": "^3.1.9",
24
+ "nodemon": "^3.1.10",
25
25
  "ts-node-dev": "^2.0.0",
26
26
  "typescript": "catalog:"
27
27
  }
@@ -1,5 +1,5 @@
1
1
  import type { FetchResponse } from '@/types/response';
2
- import type { ChatInput, Span, Trace, UsageResult } from '@/types/types';
2
+ import type { ChatInput, Score, Span, Trace, UsageResult } from '@/types/types';
3
3
  import { type AugmentedRequest, RESTDataSource } from '@apollo/datasource-rest';
4
4
  import type { KeyValueCache } from '@apollo/utils.keyvaluecache';
5
5
 
@@ -30,6 +30,12 @@ export class DataParkAPI extends RESTDataSource {
30
30
  return await this.get<FetchResponse<Span[]>>(`/api/trace/${traceId}/spans`);
31
31
  }
32
32
 
33
+ async getScores(traceId: string) {
34
+ return await this.get<FetchResponse<Score[]>>(
35
+ `/api/trace/${traceId}/scores`
36
+ );
37
+ }
38
+
33
39
  async getChatInput(spanId: string) {
34
40
  return await this.get<FetchResponse<ChatInput>>(
35
41
  `/api/v1/chat/completions/${spanId}/input`
@@ -26,6 +26,9 @@ export const resolvers: Resolvers = {
26
26
  spans: async (_, { trace_id }, { dataSources }) => {
27
27
  return (await dataSources.dataparkAPI.getSpans(trace_id)).data;
28
28
  },
29
+ scores: async (_, { trace_id }, { dataSources }) => {
30
+ return (await dataSources.dataparkAPI.getScores(trace_id)).data;
31
+ },
29
32
  chat_input: async (_, { span_id }, { dataSources }) => {
30
33
  return (await dataSources.dataparkAPI.getChatInput(span_id)).data;
31
34
  },
@@ -20,6 +20,8 @@ type Query {
20
20
  end_time: Int
21
21
  group_by: GroupingKey
22
22
  ): [UsageResult!]
23
+ "Fetch all scores by trace id"
24
+ scores(trace_id: ID!): [Score!]
23
25
  }
24
26
 
25
27
  "GroupingKey is an enum that represents the key used to group usage results"
@@ -70,6 +72,7 @@ type Trace {
70
72
  enum Kind {
71
73
  SPAN_KIND_FUNCTION
72
74
  SPAN_KIND_LLM
75
+ SPAN_KIND_EVALUATION
73
76
  }
74
77
 
75
78
  "Span is a record of a single unit of work within a trace"
@@ -79,8 +82,8 @@ type Span {
79
82
  trace_id: ID!
80
83
  name: String!
81
84
  start_time: String!
82
- end_time: String!
83
- duration: Float!
85
+ end_time: NullTime!
86
+ duration: Float
84
87
  kind: Kind!
85
88
  metadata: [KeyValue!]
86
89
  }
@@ -113,6 +116,14 @@ type UsageResult {
113
116
  date: Int
114
117
  }
115
118
 
119
+ "Score is a record of a score for a trace"
120
+ type Score {
121
+ span_id: ID!
122
+ name: String!
123
+ score: Float!
124
+ representative_reasoning: String!
125
+ }
126
+
116
127
  "Mutation is a collection of mutations that can be made to the API"
117
128
  type Mutation {
118
129
  "Auth Mutations"
@@ -92,6 +92,7 @@ export type KeyValue = {
92
92
 
93
93
  /** Kind is an enum that represents the type of span */
94
94
  export enum Kind {
95
+ SpanKindEvaluation = 'SPAN_KIND_EVALUATION',
95
96
  SpanKindFunction = 'SPAN_KIND_FUNCTION',
96
97
  SpanKindLlm = 'SPAN_KIND_LLM'
97
98
  }
@@ -201,6 +202,8 @@ export type Query = {
201
202
  completion_usage?: Maybe<Array<UsageResult>>;
202
203
  /** Fetch current user */
203
204
  me: User;
205
+ /** Fetch all scores by trace id */
206
+ scores?: Maybe<Array<Score>>;
204
207
  /** Fetch all spans by trace id */
205
208
  spans?: Maybe<Array<Span>>;
206
209
  /** Fetch traces by session id */
@@ -224,6 +227,12 @@ export type QueryCompletion_UsageArgs = {
224
227
  };
225
228
 
226
229
 
230
+ /** Query is a collection of queries that can be made to the API */
231
+ export type QueryScoresArgs = {
232
+ trace_id: Scalars['ID']['input'];
233
+ };
234
+
235
+
227
236
  /** Query is a collection of queries that can be made to the API */
228
237
  export type QuerySpansArgs = {
229
238
  trace_id: Scalars['ID']['input'];
@@ -249,11 +258,20 @@ export type RevokeApiKeyResponse = MutationResponse & {
249
258
  success: Scalars['Boolean']['output'];
250
259
  };
251
260
 
261
+ /** Score is a record of a score for a trace */
262
+ export type Score = {
263
+ __typename?: 'Score';
264
+ name: Scalars['String']['output'];
265
+ representative_reasoning: Scalars['String']['output'];
266
+ score: Scalars['Float']['output'];
267
+ span_id: Scalars['ID']['output'];
268
+ };
269
+
252
270
  /** Span is a record of a single unit of work within a trace */
253
271
  export type Span = {
254
272
  __typename?: 'Span';
255
- duration: Scalars['Float']['output'];
256
- end_time: Scalars['String']['output'];
273
+ duration?: Maybe<Scalars['Float']['output']>;
274
+ end_time: NullTime;
257
275
  id: Scalars['ID']['output'];
258
276
  kind: Kind;
259
277
  metadata?: Maybe<Array<KeyValue>>;
@@ -405,6 +423,7 @@ export type ResolversTypes = {
405
423
  NullTime: ResolverTypeWrapper<NullTime>;
406
424
  Query: ResolverTypeWrapper<{}>;
407
425
  RevokeAPIKeyResponse: ResolverTypeWrapper<RevokeApiKeyResponse>;
426
+ Score: ResolverTypeWrapper<Score>;
408
427
  Span: ResolverTypeWrapper<Span>;
409
428
  String: ResolverTypeWrapper<Scalars['String']['output']>;
410
429
  Trace: ResolverTypeWrapper<Trace>;
@@ -433,6 +452,7 @@ export type ResolversParentTypes = {
433
452
  NullTime: NullTime;
434
453
  Query: {};
435
454
  RevokeAPIKeyResponse: RevokeApiKeyResponse;
455
+ Score: Score;
436
456
  Span: Span;
437
457
  String: Scalars['String']['output'];
438
458
  Trace: Trace;
@@ -536,6 +556,7 @@ export type QueryResolvers<ContextType = DataSourceContext, ParentType extends R
536
556
  chat_input?: Resolver<Maybe<ResolversTypes['ChatInput']>, ParentType, ContextType, RequireFields<QueryChat_InputArgs, 'span_id'>>;
537
557
  completion_usage?: Resolver<Maybe<Array<ResolversTypes['UsageResult']>>, ParentType, ContextType, RequireFields<QueryCompletion_UsageArgs, 'start_time'>>;
538
558
  me?: Resolver<ResolversTypes['User'], ParentType, ContextType>;
559
+ scores?: Resolver<Maybe<Array<ResolversTypes['Score']>>, ParentType, ContextType, RequireFields<QueryScoresArgs, 'trace_id'>>;
539
560
  spans?: Resolver<Maybe<Array<ResolversTypes['Span']>>, ParentType, ContextType, RequireFields<QuerySpansArgs, 'trace_id'>>;
540
561
  traces?: Resolver<Maybe<Array<ResolversTypes['Trace']>>, ParentType, ContextType, RequireFields<QueryTracesArgs, 'session_id'>>;
541
562
  user?: Resolver<ResolversTypes['User'], ParentType, ContextType, RequireFields<QueryUserArgs, 'id'>>;
@@ -548,9 +569,17 @@ export type RevokeApiKeyResponseResolvers<ContextType = DataSourceContext, Paren
548
569
  __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
549
570
  };
550
571
 
572
+ export type ScoreResolvers<ContextType = DataSourceContext, ParentType extends ResolversParentTypes['Score'] = ResolversParentTypes['Score']> = {
573
+ name?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
574
+ representative_reasoning?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
575
+ score?: Resolver<ResolversTypes['Float'], ParentType, ContextType>;
576
+ span_id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
577
+ __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
578
+ };
579
+
551
580
  export type SpanResolvers<ContextType = DataSourceContext, ParentType extends ResolversParentTypes['Span'] = ResolversParentTypes['Span']> = {
552
- duration?: Resolver<ResolversTypes['Float'], ParentType, ContextType>;
553
- end_time?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
581
+ duration?: Resolver<Maybe<ResolversTypes['Float']>, ParentType, ContextType>;
582
+ end_time?: Resolver<ResolversTypes['NullTime'], ParentType, ContextType>;
554
583
  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
555
584
  kind?: Resolver<ResolversTypes['Kind'], ParentType, ContextType>;
556
585
  metadata?: Resolver<Maybe<Array<ResolversTypes['KeyValue']>>, ParentType, ContextType>;
@@ -618,6 +647,7 @@ export type Resolvers<ContextType = DataSourceContext> = {
618
647
  NullTime?: NullTimeResolvers<ContextType>;
619
648
  Query?: QueryResolvers<ContextType>;
620
649
  RevokeAPIKeyResponse?: RevokeApiKeyResponseResolvers<ContextType>;
650
+ Score?: ScoreResolvers<ContextType>;
621
651
  Span?: SpanResolvers<ContextType>;
622
652
  Trace?: TraceResolvers<ContextType>;
623
653
  UpdateAPIKeyResponse?: UpdateApiKeyResponseResolvers<ContextType>;
@@ -1,5 +1,10 @@
1
+ import Highlighter from '@/components/Highter';
1
2
  import type { ExtendedSpan } from '@/lib/types/span';
2
3
  import { formatDate } from '@/lib/utils';
4
+ import {
5
+ Kind,
6
+ type Score,
7
+ } from '@workspace/graphql-client/src/types.generated';
3
8
  import {
4
9
  Accordion,
5
10
  AccordionContent,
@@ -16,7 +21,6 @@ import {
16
21
  } from '@workspace/ui/components/card';
17
22
  import { Timer } from 'lucide-react';
18
23
  import type * as React from 'react';
19
- import Highlighter from '@/components/Highter';
20
24
 
21
25
  interface SpanProps {
22
26
  span: ExtendedSpan;
@@ -30,11 +34,18 @@ export function Span({ span }: SpanProps) {
30
34
  <GeneralInfo span={span} />
31
35
  <Accordion
32
36
  type="multiple"
33
- defaultValue={['properties', 'Input', 'Output']}
37
+ defaultValue={['properties', 'Input', 'Output', 'scores']}
34
38
  >
35
39
  <AccordionProperties span={span} />
36
- <AccordionJsonCards name="Input" datas={messages} />
37
- <AccordionJsonCards name="Output" datas={choices} />
40
+ {span.kind === Kind.SpanKindLlm && (
41
+ <>
42
+ <AccordionJsonCards name="Input" datas={messages} />
43
+ <AccordionJsonCards name="Output" datas={choices} />
44
+ </>
45
+ )}
46
+ {span.kind === Kind.SpanKindEvaluation && (
47
+ <AccordionScores scores={span.scores ?? []} />
48
+ )}
38
49
  </Accordion>
39
50
  </>
40
51
  );
@@ -57,10 +68,35 @@ function GeneralInfo({ span }: SpanProps) {
57
68
  );
58
69
  }
59
70
 
71
+ function AccordionScores({ scores }: { scores: Score[] }) {
72
+ return (
73
+ <AccordionItem value="scores" className="px-4">
74
+ <AccordionTrigger className="hover:no-underline">Scores</AccordionTrigger>
75
+ <AccordionContent className="flex flex-col gap-3">
76
+ {scores.map((score) => (
77
+ <PropertyCard
78
+ title={score.name
79
+ .split('_')
80
+ .map((n) => n.charAt(0).toUpperCase() + n.slice(1).toLowerCase())
81
+ .join(' ')}
82
+ key={score.name}
83
+ >
84
+ <PropertyItem label="score" value={score.score} />
85
+ <PropertyItem
86
+ label="explanation"
87
+ value={score.representative_reasoning}
88
+ />
89
+ </PropertyCard>
90
+ ))}
91
+ </AccordionContent>
92
+ </AccordionItem>
93
+ );
94
+ }
95
+
60
96
  function AccordionProperties({ span }: SpanProps) {
61
97
  // TODO select the properties to show
62
98
  const startTime = formatDate(span.start_time);
63
- const endTime = formatDate(span.end_time);
99
+ const endTime = span.end_time.Valid ? formatDate(span.end_time.Time) : 'N/A';
64
100
  const usage = span.completion?.usage;
65
101
  // input should pop messages
66
102
  const { messages, ...inputs } = span.input ?? {};
@@ -128,9 +164,9 @@ function PropertyItem({
128
164
  value: string | number | boolean | null;
129
165
  }) {
130
166
  return (
131
- <div className="flex items-center justify-between">
167
+ <div className="flex items-start justify-between gap-4">
132
168
  <span className="text-sm">{label}</span>
133
- <span className="truncate font-light text-sm">{String(value)}</span>
169
+ <span className="break-words font-light text-sm">{String(value)}</span>
134
170
  </div>
135
171
  );
136
172
  }
@@ -16,6 +16,11 @@ export function TraceBoard({ spans, direction }: TraceBoardProps) {
16
16
  const selectAction = (_data: ExtendedSpan, index: number) => {
17
17
  setIndex(index);
18
18
  };
19
+ if (!spans || spans.length === 0) {
20
+ return (
21
+ <div className="flex h-full items-center justify-center">No data</div>
22
+ );
23
+ }
19
24
 
20
25
  return (
21
26
  <ResponsiveResizable
@@ -32,6 +32,9 @@ const chartConfig = {
32
32
  SPAN_KIND_LLM: {
33
33
  color: 'var(--chart-2)',
34
34
  },
35
+ SPAN_KIND_EVALUATION: {
36
+ color: 'var(--chart-3)',
37
+ },
35
38
  } satisfies ChartConfig;
36
39
 
37
40
  interface TraceWaterfallChartProps {
@@ -107,7 +110,7 @@ export function TraceWaterfallChart({
107
110
  <LabelList
108
111
  dataKey="name"
109
112
  position="insideLeft"
110
- className="fill-background"
113
+ className="fill-card"
111
114
  />
112
115
  </Bar>
113
116
  </BarChart>
@@ -8,7 +8,7 @@ import type {
8
8
  GroupingKey,
9
9
  UsageResult,
10
10
  } from '@workspace/graphql-client/src/types.generated';
11
- import { eachDayOfInterval, getUnixTime } from 'date-fns';
11
+ import { addDays, eachDayOfInterval, getUnixTime, startOfDay } from 'date-fns';
12
12
  import { cache } from 'react';
13
13
 
14
14
  export const getCompletionUsage = cache(
@@ -25,7 +25,9 @@ export const getCompletionUsage = cache(
25
25
  query: GetCompletionUsageDocument,
26
26
  variables: {
27
27
  startTime: getUnixTime(startTime),
28
- endTime: getUnixTime(endTime ?? new Date()),
28
+ endTime: getUnixTime(
29
+ endTime ? addDays(startOfDay(endTime), 1) : new Date()
30
+ ),
29
31
  groupBy,
30
32
  },
31
33
  context,
@@ -9,7 +9,7 @@ export default function HomeHero() {
9
9
  <div className="flex flex-col items-center justify-center gap-8 py-20 lg:py-40">
10
10
  <div>
11
11
  <Button variant="secondary" size="sm" className="gap-4" asChild>
12
- <Link href="https://docs.divine-agent.com">
12
+ <Link href="https://docs.divine-agent.com" target="_blank">
13
13
  Read our launch article <MoveRight className="h-4 w-4" />
14
14
  </Link>
15
15
  </Button>
@@ -0,0 +1,17 @@
1
+ import { query } from '@/hooks/apolloClient';
2
+ import { GetScoresDocument } from '@workspace/graphql-client/src/datapark/evaluation.generated';
3
+ import { cache } from 'react';
4
+ import { getAuthContext } from './auth';
5
+
6
+ export const getScores = cache(async (traceId: string) => {
7
+ const context = await getAuthContext();
8
+ if (!context) {
9
+ return null;
10
+ }
11
+ const { data } = await query({
12
+ query: GetScoresDocument,
13
+ variables: { traceId },
14
+ context,
15
+ });
16
+ return data?.scores;
17
+ });
@@ -2,9 +2,14 @@ import 'server-only';
2
2
  import { query } from '@/hooks/apolloClient';
3
3
  import type { Chat, ExtendedSpan } from '@/lib/types/span';
4
4
  import { GetSpansDocument } from '@workspace/graphql-client/src/datapark/traces.generated';
5
- import { Kind, type Span } from '@workspace/graphql-client/src/types.generated';
5
+ import {
6
+ Kind,
7
+ type Score,
8
+ type Span,
9
+ } from '@workspace/graphql-client/src/types.generated';
6
10
  import { cache } from 'react';
7
11
  import { getAuthContext } from './auth';
12
+ import { getScores } from './evaluation';
8
13
  import { getChat } from './openai';
9
14
 
10
15
  /**
@@ -31,7 +36,10 @@ export const getSpans = cache(async (traceId: string) => {
31
36
  export const getTraceChartData = cache(
32
37
  async (traceId: string): Promise<ExtendedSpan[]> => {
33
38
  // get spans for a trace
34
- let spans = await getSpans(traceId);
39
+ let [spans, scores] = await Promise.all([
40
+ getSpans(traceId),
41
+ getScores(traceId),
42
+ ]);
35
43
  if (!spans) {
36
44
  return [];
37
45
  }
@@ -39,12 +47,23 @@ export const getTraceChartData = cache(
39
47
  spans = sortSpans(spans);
40
48
  // get chat input and completion for LLM span
41
49
  const llmSpanIds = spans
42
- .filter((span) => span.kind === Kind.SpanKindLlm)
50
+ .filter((span) => span.kind === Kind.SpanKindLlm && span.end_time.Valid)
43
51
  .map((s) => s.id);
44
52
  const chats = await Promise.all(llmSpanIds.map((id) => getChat(id)));
45
53
  const chatsMap = new Map<string, Chat>(
46
54
  chats.map((chat) => [chat.span_id, chat])
47
55
  );
56
+ const scoresMap = new Map<string, Score[]>();
57
+ // group scores by span_id
58
+ if (scores) {
59
+ for (const score of scores) {
60
+ const spanId = score.span_id;
61
+ if (!scoresMap.has(spanId)) {
62
+ scoresMap.set(spanId, []);
63
+ }
64
+ scoresMap.get(spanId)?.push(score);
65
+ }
66
+ }
48
67
  // calculate relative start_time with milliseconds
49
68
  const startTime = new Date(spans[0]?.start_time).getTime();
50
69
  return spans.map((span) => {
@@ -54,6 +73,11 @@ export const getTraceChartData = cache(
54
73
  relative_start_time: new Date(span.start_time).getTime() - startTime,
55
74
  input: chat?.input,
56
75
  completion: chat?.completion,
76
+ duration: span.end_time.Valid
77
+ ? span.duration
78
+ : Date.now() - new Date(span.start_time).getTime(),
79
+ scores:
80
+ span.kind === Kind.SpanKindEvaluation ? scoresMap.get(span.id) : [],
57
81
  };
58
82
  });
59
83
  }
@@ -1,4 +1,7 @@
1
- import type { Span } from '@workspace/graphql-client/src/types.generated';
1
+ import type {
2
+ Score,
3
+ Span,
4
+ } from '@workspace/graphql-client/src/types.generated';
2
5
  import type { ChatInput } from '@workspace/graphql-client/src/types.generated';
3
6
  import type { ChatCompletion } from 'openai/resources/index.mjs';
4
7
 
@@ -10,6 +13,7 @@ export interface ExtendedSpan extends Span {
10
13
  relative_start_time: number;
11
14
  input?: ChatInput;
12
15
  completion?: ChatCompletion;
16
+ scores?: Score[];
13
17
  }
14
18
 
15
19
  /**
@@ -2,6 +2,7 @@
2
2
  "name": "@app/web",
3
3
  "private": true,
4
4
  "type": "module",
5
+ "packageManager": "pnpm@10.6.5",
5
6
  "scripts": {
6
7
  "dev": "next dev --turbopack --port 4001",
7
8
  "build": "next build",
@@ -9,18 +10,19 @@
9
10
  "analyze": "ANALYZE=true pnpm build"
10
11
  },
11
12
  "dependencies": {
12
- "@apollo/client": "^3.13.7",
13
+ "@apollo/client": "^3.13.8",
13
14
  "@apollo/experimental-nextjs-app-support": "^0.11.11",
14
15
  "@dnd-kit/core": "^6.3.1",
15
16
  "@dnd-kit/modifiers": "^9.0.0",
16
17
  "@dnd-kit/sortable": "^10.0.0",
17
18
  "@dnd-kit/utilities": "^3.2.2",
18
19
  "@hookform/resolvers": "^4.1.3",
19
- "@icons-pack/react-simple-icons": "^12.6.0",
20
+ "@icons-pack/react-simple-icons": "^12.7.0",
20
21
  "@tabler/icons-react": "^3.31.0",
21
- "@tanstack/react-table": "^8.21.2",
22
+ "@tanstack/react-table": "^8.21.3",
22
23
  "@workspace/graphql-client": "workspace:*",
23
24
  "@workspace/ui": "workspace:*",
25
+ "date-fns": "catalog:",
24
26
  "highlight.js": "^11.11.1",
25
27
  "lucide-react": "catalog:",
26
28
  "next": "catalog:",
@@ -28,12 +30,11 @@
28
30
  "react": "catalog:",
29
31
  "react-day-picker": "catalog:",
30
32
  "react-dom": "catalog:",
31
- "react-hook-form": "^7.55.0",
32
- "recharts": "^2.15.2",
33
+ "react-hook-form": "^7.56.1",
34
+ "recharts": "^2.15.3",
33
35
  "server-only": "^0.0.1",
34
36
  "sonner": "catalog:",
35
- "zod": "^3.24.2",
36
- "date-fns": "catalog:"
37
+ "zod": "^3.24.3"
37
38
  },
38
39
  "devDependencies": {
39
40
  "@types/highlightjs": "^9.12.6",
@@ -41,7 +42,7 @@
41
42
  "@types/react": "catalog:",
42
43
  "@types/react-dom": "catalog:",
43
44
  "@workspace/typescript-config": "workspace:*",
44
- "openai": "^4.93.0",
45
+ "openai": "^4.96.0",
45
46
  "typescript": "catalog:"
46
47
  }
47
48
  }
@@ -2,8 +2,10 @@ from typing import Optional
2
2
 
3
3
  from . import proto
4
4
  from .decorators import obs_openai, observable
5
+ from .evaluation import Evaluator, Score
5
6
  from .services import Auth, Core, DataPark
6
7
  from .session import Session
8
+ from .signals import Kind
7
9
 
8
10
  name: str = "divi"
9
11
 
@@ -11,6 +13,7 @@ _session: Optional[Session] = None
11
13
  _core: Optional[Core] = None
12
14
  _auth: Optional[Auth] = None
13
15
  _datapark: Optional[DataPark] = None
16
+ _evaluator: Optional[Evaluator] = None
14
17
 
15
- __version__ = "0.0.1.dev23"
16
- __all__ = ["proto", "obs_openai", "observable"]
18
+ __version__ = "0.0.1.dev47"
19
+ __all__ = ["proto", "obs_openai", "observable", "Score", "Kind"]
@@ -0,0 +1,34 @@
1
+ from typing import Any
2
+
3
+ from google.protobuf.message import Error
4
+ from openai.types.chat import ChatCompletion
5
+ from typing_extensions import Dict
6
+
7
+ import divi
8
+ from divi.evaluation.evaluator import EvaluationScore
9
+ from divi.signals.span import Span
10
+
11
+
12
+ def collect(span: Span, input: Dict[str, Any], result: Any):
13
+ if not divi._datapark or span.trace_id is None:
14
+ raise Error("divi._datapark or span.trace_id is None")
15
+ # TODO: collect inputs and outputs for SPAN_KIND_FUNCTION
16
+
17
+ # collect inputs and outputs for SPAN_KIND_LLM
18
+ if isinstance(result, ChatCompletion):
19
+ divi._datapark.create_chat_completion(
20
+ span_id=span.span_id,
21
+ trace_id=span.trace_id,
22
+ inputs=input,
23
+ completion=result,
24
+ )
25
+
26
+ # collect inputs and outputs for SPAN_KIND_EVALUATION
27
+ if isinstance(result, list) and all(
28
+ isinstance(x, EvaluationScore) for x in result
29
+ ):
30
+ divi._datapark.create_scores(
31
+ span_id=span.span_id,
32
+ trace_id=span.trace_id,
33
+ scores=result,
34
+ )
@@ -2,7 +2,11 @@ import functools
2
2
  from collections.abc import Callable
3
3
  from typing import TYPE_CHECKING, TypeVar, Union
4
4
 
5
+ from typing_extensions import Optional
6
+
5
7
  from divi.decorators.observable import observable
8
+ from divi.evaluation.scores import Score
9
+ from divi.signals.span import Kind
6
10
  from divi.utils import is_async
7
11
 
8
12
  if TYPE_CHECKING:
@@ -11,22 +15,34 @@ if TYPE_CHECKING:
11
15
  C = TypeVar("C", bound=Union["OpenAI", "AsyncOpenAI"])
12
16
 
13
17
 
14
- def _get_observable_create(create: Callable) -> Callable:
18
+ def _get_observable_create(
19
+ create: Callable,
20
+ name: Optional[str] = None,
21
+ scores: Optional[list[Score]] = None,
22
+ ) -> Callable:
15
23
  @functools.wraps(create)
16
24
  def observable_create(*args, stream: bool = False, **kwargs):
17
- decorator = observable(kind="llm")
25
+ decorator = observable(kind=Kind.llm, name=name, scores=scores)
18
26
  return decorator(create)(*args, stream=stream, **kwargs)
19
27
 
20
28
  # TODO Async Observable Create
21
29
  return observable_create if not is_async(create) else create
22
30
 
23
31
 
24
- def obs_openai(client: C) -> C:
32
+ def obs_openai(
33
+ client: C,
34
+ name: Optional[str] = "Agent",
35
+ scores: Optional[list[Score]] = None,
36
+ ) -> C:
25
37
  """Make OpenAI client observable."""
26
38
  client.chat.completions.create = _get_observable_create(
27
- client.chat.completions.create
39
+ client.chat.completions.create,
40
+ name=name,
41
+ scores=scores,
28
42
  )
29
43
  client.completions.create = _get_observable_create(
30
- client.completions.create
44
+ client.completions.create,
45
+ name=name,
46
+ scores=scores,
31
47
  )
32
48
  return client