divi 0.0.1.dev28__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.
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/PKG-INFO +1 -1
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/graphql/src/datasources/datapark-api.ts +7 -1
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/graphql/src/resolvers.ts +3 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/graphql/src/schema.graphql +13 -2
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/graphql/src/types/types.d.ts +34 -4
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(children)/[id]/components/Span.tsx +43 -7
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(children)/[id]/components/trace-board.tsx +5 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(children)/[id]/components/trace-chart.tsx +4 -1
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/usages/actions.ts +4 -2
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/home/components/home-hero.tsx +1 -1
- divi-0.0.1.dev47/apps/web/lib/server/evaluation.ts +17 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/lib/server/span.ts +27 -3
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/lib/types/span.d.ts +5 -1
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/__init__.py +3 -2
- divi-0.0.1.dev47/divi/decorators/collect.py +34 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/decorators/obs_openai.py +3 -2
- divi-0.0.1.dev47/divi/decorators/observable.py +91 -0
- divi-0.0.1.dev47/divi/decorators/observe.py +47 -0
- divi-0.0.1.dev47/divi/evaluation/evaluate.py +61 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/evaluation/evaluator.py +27 -14
- divi-0.0.1.dev47/divi/evaluation/prompts.py +19 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/proto/trace/v1/trace.proto +3 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/proto/trace/v1/trace_pb2.py +3 -3
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/proto/trace/v1/trace_pb2.pyi +2 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/datapark/datapark.py +21 -3
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/init.py +3 -1
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/session/session.py +1 -1
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/session/setup.py +2 -2
- divi-0.0.1.dev47/divi/signals/__init__.py +3 -0
- divi-0.0.1.dev47/divi/signals/span.py +83 -0
- divi-0.0.1.dev47/divi/signals/trace.py +79 -0
- divi-0.0.1.dev47/services/internal/app/datapark/handler/evaluation.go +147 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/app/datapark/handler/openai.go +4 -3
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/app/datapark/handler/trace.go +56 -13
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/app/datapark/router/router.go +3 -0
- divi-0.0.1.dev47/services/internal/pkg/model/score.go +16 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/pkg/model/trace.go +2 -2
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/pb/trace.pb.go +12 -6
- divi-0.0.1.dev47/uv.lock +654 -0
- divi-0.0.1.dev28/divi/decorators/observable.py +0 -124
- divi-0.0.1.dev28/divi/evaluation/evaluate.py +0 -57
- divi-0.0.1.dev28/divi/evaluation/prompts.py +0 -14
- divi-0.0.1.dev28/divi/signals/__init__.py +0 -3
- divi-0.0.1.dev28/divi/signals/trace/__init__.py +0 -3
- divi-0.0.1.dev28/divi/signals/trace/trace.py +0 -151
- divi-0.0.1.dev28/uv.lock +0 -654
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/.air.toml +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/.dockerignore +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/.github/dependabot.yml +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/.gitignore +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/LICENSE +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/README.md +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/README.md +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/docs/README.md +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/docs/concepts/session.mdx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/docs/development/roadmap.mdx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/docs/docs.json +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/docs/favicon.ico +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/docs/images/researcher-angel.png +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/docs/images/scholar-angel.png +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/docs/introduction.mdx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/docs/package.json +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/docs/quickstart/trace.mdx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/docs/snippets/snippet-intro.mdx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/docs/tutorials/openai.mdx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/graphql/Dockerfile +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/graphql/README.md +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/graphql/codegen.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/graphql/package.json +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/graphql/src/datasources/auth-api.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/graphql/src/index.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/graphql/src/types/context.d.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/graphql/src/types/response.d.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/graphql/tsconfig.json +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/.gitignore +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/README.md +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/@modal/(.)traces/[id]/page.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/@modal/default.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/actions.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/components/columns.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/components/create-dialog.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/components/data-table-cell-viewer.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/components/data-table-toolbar.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/components/data-table.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/components/delete-dialog.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/data/data.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/data/schema.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/layout.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/api-keys/page.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/components/app-sidebar.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/components/nav-main.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/components/nav-secondary.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/components/nav-user.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/components/site-header.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/layout.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/account/components/account-form.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/account/page.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/appearance/components/appearance-form.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/appearance/page.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/components/profile-form.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/components/sidebar-nav.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/layout.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/settings/page.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(children)/[id]/components/responsive-resizable.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(children)/[id]/page.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/components/columns.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/components/data-table-row-action.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/components/data-table-toolbar.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/components/data-table.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/data/data.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/data/schema.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/layout.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/traces/(overview)/page.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/usages/components/usage-board.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/usages/components/usage-chart.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/usages/layout.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/dashboard/usages/page.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/favicon.ico +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/home/components/home-header.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/home/page.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/layout.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/login/components/login-form.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/login/page.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/page.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/signup/components/signup-form.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/app/signup/page.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/components/ApolloWrapper.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/components/Highter.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/components/Modal.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/components/calendar.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/components/data-table-column-header.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/components/data-table-faceted-filter.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/components/data-table-pagination.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/components/data-table-row.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/components/data-table-view-options.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/components/date-picker.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/components/mode-switcher.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/components/theme-provider.tsx +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/components.json +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/hooks/actionState.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/hooks/apolloClient.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/lib/callback/toast-callback.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/lib/callback/with-callback.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/lib/server/README.md +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/lib/server/auth.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/lib/server/cookies.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/lib/server/openai.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/lib/types/state.d.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/lib/types/usage.d.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/lib/utils.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/middleware.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/next-env.d.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/next.config.ts +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/package.json +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/postcss.config.mjs +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/public/peeking-angel.png +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/public/thinking-angel.png +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/tsconfig.json +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/apps/web/vercel.json +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/biome.json +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/compose-dev.yml +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/decorators/__init__.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/evaluation/__init__.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/evaluation/scores.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/proto/common/v1/common.proto +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/proto/common/v1/common_pb2.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/proto/common/v1/common_pb2.pyi +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/proto/core/health/v1/health_service.proto +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/proto/core/health/v1/health_service_pb2.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/proto/core/health/v1/health_service_pb2.pyi +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/proto/core/health/v1/health_service_pb2_grpc.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/proto/metric/v1/metric.proto +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/proto/metric/v1/metric_pb2.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/proto/metric/v1/metric_pb2.pyi +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/__init__.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/auth/__init__.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/auth/auth.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/auth/init.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/auth/tokman.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/core/__init__.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/core/core.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/core/finish.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/core/init.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/datapark/__init__.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/datapark/init.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/finish.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/services/service.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/session/__init__.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/session/teardown.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/divi/utils.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/docker-compose.yml +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/docs/README.md +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/docs/developer_tools.md +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/docs/images/architecture.svg +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/docs/images/favicon.ico +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/docs/images/og-image.png +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/docs/images/storage.svg +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/docs/package_readme.md +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/go.work +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/go.work.sum +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/hatch.toml +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/package.json +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/packages/README.md +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/pnpm-lock.yaml +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/pnpm-workspace.yaml +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/pyproject.toml +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/scripts/README.md +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/scripts/hatch_build.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/scripts/key_build.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/scripts/proto_build.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/README.md +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/go.mod +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/go.sum +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/app/auth/handler/api.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/app/auth/handler/api_key.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/app/auth/handler/auth.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/app/auth/handler/user.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/app/auth/router/router.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/app/core/.keep +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/app/datapark/handler/api.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/app/datapark/handler/metric.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/app/datapark/handler/session.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/app/datapark/handler/usage.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/pkg/auth/auth.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/pkg/auth/middleware.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/pkg/config/config.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/pkg/database/connect.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/pkg/database/database.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/pkg/model/api_key.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/pkg/model/openai.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/pkg/model/session.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/pkg/model/usage.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/internal/pkg/model/user.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/pb/common.pb.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/pb/health_service.pb.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/pb/health_service_grpc.pb.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/services/pb/metric.pb.go +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/tests/__init__.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/tests/unit_tests/decorators/test_obs_openai.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/tests/unit_tests/decorators/test_observable.py +0 -0
- {divi-0.0.1.dev28 → divi-0.0.1.dev47}/turbo.json +0 -0
@@ -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:
|
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
|
256
|
-
end_time:
|
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']
|
553
|
-
end_time?: Resolver<ResolversTypes['
|
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
|
-
|
37
|
-
|
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-
|
167
|
+
<div className="flex items-start justify-between gap-4">
|
132
168
|
<span className="text-sm">{label}</span>
|
133
|
-
<span className="
|
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-
|
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(
|
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 {
|
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
|
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 {
|
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
|
/**
|
@@ -5,6 +5,7 @@ from .decorators import obs_openai, observable
|
|
5
5
|
from .evaluation import Evaluator, Score
|
6
6
|
from .services import Auth, Core, DataPark
|
7
7
|
from .session import Session
|
8
|
+
from .signals import Kind
|
8
9
|
|
9
10
|
name: str = "divi"
|
10
11
|
|
@@ -14,5 +15,5 @@ _auth: Optional[Auth] = None
|
|
14
15
|
_datapark: Optional[DataPark] = None
|
15
16
|
_evaluator: Optional[Evaluator] = None
|
16
17
|
|
17
|
-
__version__ = "0.0.1.
|
18
|
-
__all__ = ["proto", "obs_openai", "observable", "Score"]
|
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
|
+
)
|
@@ -6,6 +6,7 @@ from typing_extensions import Optional
|
|
6
6
|
|
7
7
|
from divi.decorators.observable import observable
|
8
8
|
from divi.evaluation.scores import Score
|
9
|
+
from divi.signals.span import Kind
|
9
10
|
from divi.utils import is_async
|
10
11
|
|
11
12
|
if TYPE_CHECKING:
|
@@ -21,7 +22,7 @@ def _get_observable_create(
|
|
21
22
|
) -> Callable:
|
22
23
|
@functools.wraps(create)
|
23
24
|
def observable_create(*args, stream: bool = False, **kwargs):
|
24
|
-
decorator = observable(kind=
|
25
|
+
decorator = observable(kind=Kind.llm, name=name, scores=scores)
|
25
26
|
return decorator(create)(*args, stream=stream, **kwargs)
|
26
27
|
|
27
28
|
# TODO Async Observable Create
|
@@ -30,7 +31,7 @@ def _get_observable_create(
|
|
30
31
|
|
31
32
|
def obs_openai(
|
32
33
|
client: C,
|
33
|
-
name: Optional[str] = "
|
34
|
+
name: Optional[str] = "Agent",
|
34
35
|
scores: Optional[list[Score]] = None,
|
35
36
|
) -> C:
|
36
37
|
"""Make OpenAI client observable."""
|
@@ -0,0 +1,91 @@
|
|
1
|
+
import functools
|
2
|
+
from typing import (
|
3
|
+
Any,
|
4
|
+
Callable,
|
5
|
+
Generic,
|
6
|
+
Mapping,
|
7
|
+
Optional,
|
8
|
+
ParamSpec,
|
9
|
+
Protocol,
|
10
|
+
TypeVar,
|
11
|
+
Union,
|
12
|
+
overload,
|
13
|
+
runtime_checkable,
|
14
|
+
)
|
15
|
+
|
16
|
+
from divi.decorators.observe import observe
|
17
|
+
from divi.evaluation.evaluate import evaluate_scores
|
18
|
+
from divi.evaluation.scores import Score
|
19
|
+
from divi.session import SessionExtra
|
20
|
+
from divi.signals.span import Kind, Span
|
21
|
+
|
22
|
+
R = TypeVar("R", covariant=True)
|
23
|
+
P = ParamSpec("P")
|
24
|
+
|
25
|
+
|
26
|
+
@runtime_checkable
|
27
|
+
class WithSessionExtra(Protocol, Generic[P, R]):
|
28
|
+
def __call__(
|
29
|
+
self,
|
30
|
+
*args: P.args,
|
31
|
+
session_extra: Optional[SessionExtra] = None, # type: ignore[valid-type]
|
32
|
+
**kwargs: P.kwargs,
|
33
|
+
) -> R: ...
|
34
|
+
|
35
|
+
|
36
|
+
@overload
|
37
|
+
def observable(func: Callable[P, R]) -> WithSessionExtra[P, R]: ...
|
38
|
+
|
39
|
+
|
40
|
+
@overload
|
41
|
+
def observable(
|
42
|
+
kind: Kind = Kind.function,
|
43
|
+
*,
|
44
|
+
name: Optional[str] = None,
|
45
|
+
scores: Optional[list[Score]] = None,
|
46
|
+
metadata: Optional[Mapping[str, Any]] = None,
|
47
|
+
) -> Callable[[Callable[P, R]], WithSessionExtra[P, R]]: ...
|
48
|
+
|
49
|
+
|
50
|
+
def observable(
|
51
|
+
*args, **kwargs
|
52
|
+
) -> Union[Callable, Callable[[Callable], Callable]]:
|
53
|
+
"""Observable decorator factory."""
|
54
|
+
|
55
|
+
kind = kwargs.pop("kind", Kind.function)
|
56
|
+
name = kwargs.pop("name", None)
|
57
|
+
metadata = kwargs.pop("metadata", None)
|
58
|
+
scores: list[Score] = kwargs.pop("scores", None)
|
59
|
+
|
60
|
+
def decorator(func):
|
61
|
+
@functools.wraps(func)
|
62
|
+
def wrapper(
|
63
|
+
*args, session_extra: Optional[SessionExtra] = None, **kwargs
|
64
|
+
):
|
65
|
+
# 1. init the span
|
66
|
+
span = Span(
|
67
|
+
kind=kind, name=name or func.__name__, metadata=metadata
|
68
|
+
)
|
69
|
+
|
70
|
+
# 2. observe the function
|
71
|
+
result = observe(
|
72
|
+
*args,
|
73
|
+
func=func,
|
74
|
+
span=span,
|
75
|
+
session_extra=session_extra,
|
76
|
+
**kwargs,
|
77
|
+
)
|
78
|
+
|
79
|
+
# 3. evaluate the scores if they are provided
|
80
|
+
messages = kwargs.get("messages", [])
|
81
|
+
evaluate_scores(messages, outputs=result, scores=scores)
|
82
|
+
|
83
|
+
return result
|
84
|
+
|
85
|
+
return wrapper
|
86
|
+
|
87
|
+
# Function Decorator
|
88
|
+
if len(args) == 1 and callable(args[0]) and not kwargs:
|
89
|
+
return decorator(args[0])
|
90
|
+
# Factory Decorator
|
91
|
+
return decorator
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import contextvars
|
2
|
+
from typing import (
|
3
|
+
Callable,
|
4
|
+
Optional,
|
5
|
+
)
|
6
|
+
|
7
|
+
from divi.decorators.collect import collect
|
8
|
+
from divi.session import SessionExtra
|
9
|
+
from divi.session.setup import setup
|
10
|
+
from divi.signals.span import Span
|
11
|
+
from divi.utils import extract_flattened_inputs
|
12
|
+
|
13
|
+
# ContextVar to store the extra information
|
14
|
+
# from the Session and parent Span
|
15
|
+
_SESSION_EXTRA = contextvars.ContextVar[Optional[SessionExtra]](
|
16
|
+
"_SESSION_EXTRA", default=None
|
17
|
+
)
|
18
|
+
|
19
|
+
|
20
|
+
def observe(
|
21
|
+
*args,
|
22
|
+
func: Callable,
|
23
|
+
span: Span,
|
24
|
+
session_extra: Optional[SessionExtra] = None,
|
25
|
+
**kwargs,
|
26
|
+
):
|
27
|
+
session_extra = setup(span, _SESSION_EXTRA.get() or session_extra)
|
28
|
+
# set current context
|
29
|
+
token = _SESSION_EXTRA.set(session_extra)
|
30
|
+
# execute the function
|
31
|
+
span.start()
|
32
|
+
result = func(*args, **kwargs)
|
33
|
+
span.end()
|
34
|
+
# recover parent context
|
35
|
+
_SESSION_EXTRA.reset(token)
|
36
|
+
|
37
|
+
# get the trace to collect data
|
38
|
+
trace = session_extra.get("trace")
|
39
|
+
# end the trace if it is the root span
|
40
|
+
if trace and not span.parent_span_id:
|
41
|
+
trace.end()
|
42
|
+
|
43
|
+
# collect inputs and outputs
|
44
|
+
inputs = extract_flattened_inputs(func, *args, **kwargs)
|
45
|
+
collect(span, inputs, result)
|
46
|
+
|
47
|
+
return result
|