From 2a61a4f52a6a3e97321152cf5637b86a3b2ed557 Mon Sep 17 00:00:00 2001 From: 120axuz Date: Sun, 2 Jul 2023 23:55:19 +0200 Subject: [PATCH 01/10] feat: add filter buttons in UI --- .../components/requests/RequestFilters.tsx | 49 +++++ .../requests/filters/FilterItem.tsx | 203 ++++++++++++++++++ apps/console/src/app/graphql/hooks/filters.ts | 52 ++++- apps/console/src/app/graphql/hooks/queries.ts | 14 +- apps/console/src/app/lib/constants/filters.ts | 9 + apps/console/src/app/lib/types/filters.ts | 27 +++ .../src/app/pages/requests/RequestsPage.tsx | 22 +- apps/console/src/app/pages/requests/types.ts | 10 + .../src/app/common/filters/filter.input.ts | 3 - .../src/app/reporting/utils/dql-utils.ts | 2 +- 10 files changed, 362 insertions(+), 29 deletions(-) create mode 100644 apps/console/src/app/components/requests/RequestFilters.tsx create mode 100644 apps/console/src/app/components/requests/filters/FilterItem.tsx create mode 100644 apps/console/src/app/lib/constants/filters.ts create mode 100644 apps/console/src/app/lib/types/filters.ts create mode 100644 apps/console/src/app/pages/requests/types.ts diff --git a/apps/console/src/app/components/requests/RequestFilters.tsx b/apps/console/src/app/components/requests/RequestFilters.tsx new file mode 100644 index 00000000..30d8c641 --- /dev/null +++ b/apps/console/src/app/components/requests/RequestFilters.tsx @@ -0,0 +1,49 @@ +import { RequestReportItem } from "../../pages/requests/types"; +import { Card } from "antd"; +import styled from "@emotion/styled"; +import { AddFilterItem, FilterItem } from "./filters/FilterItem"; +import { Typography } from "antd"; +import { useFiltersAndSortParams } from "../../graphql/hooks/filters"; + +const { Title } = Typography; + +const Box = styled.div` + padding: 10px 0; +`; + +const FiltersList = styled.div` + display: flex; +`; + +interface Props { + requests: RequestReportItem[]; +} + +export const RequestFilters = (props: Props) => { + const { filters, removeFilter, addFilter } = useFiltersAndSortParams(); + + return ( + + + + Filters: + + + {filters.map((filter) => ( + removeFilter(filter)} + /> + ))} + + + + + ); +}; diff --git a/apps/console/src/app/components/requests/filters/FilterItem.tsx b/apps/console/src/app/components/requests/filters/FilterItem.tsx new file mode 100644 index 00000000..9ff26464 --- /dev/null +++ b/apps/console/src/app/components/requests/filters/FilterItem.tsx @@ -0,0 +1,203 @@ +import styled from "@emotion/styled"; +import { Button, Form, Input, Select, Tag, Tooltip, Typography } from "antd"; +import { useCallback, useMemo, useState } from "react"; +import { CheckOutlined, CloseOutlined } from "@ant-design/icons"; +import { FilterInput, FilterOperator } from "../../../lib/types/filters"; +import { FILTER_FIELDS_ALLOW_LIST } from "../../../lib/constants/filters"; + +const { Text } = Typography; + +const FilterItemTag = styled(Tag)<{ formMode?: boolean }>` + display: flex; + align-items: center; + gap: 4px; + padding: ${({ formMode }) => (formMode ? "0px" : "4px 8px")}; + border: ${({ formMode }) => (formMode ? "none" : "1px solid #5FDD97")}; + background: ${({ formMode }) => + formMode ? "none" : "rgba(255, 255, 255, 0.04)"}; +`; + +interface Props extends FilterInput { + onRemoveFilter: () => void; +} + +export const FilterItem = ({ + field, + operator, + value, + onRemoveFilter, +}: Props) => { + const translatedField = useMemo(() => { + if (field.includes(".")) { + const fieldParts = field.split("."); + + return fieldParts.reduce((acc, part) => `${acc} ${part}`, ""); + } + + return field; + }, [field]); + + return ( + + {translatedField} + : {operator} : + {value} + + ); +}; + +const StyledForm = styled(Form)` + .ant-form-item-explain-error { + position: absolute; + } +`; + +export const AddFilterForm = ({ + onAdd, + onCancel, +}: { + onAdd: (input: FilterInput) => void; + onCancel: () => void; +}) => { + const [form] = Form.useForm(); + + const handleFormSubmit = () => { + onAdd(form.getFieldsValue()); + form.resetFields(); + }; + + return ( + + + ({ + value: FilterOperator[f], + label: f, + }))} + /> + + + + + + + + {({ getFieldsValue }) => { + const { field, operator, value } = getFieldsValue(); + const fieldsHasError = form + .getFieldsError() + .some((field) => field.errors.length > 0); + const formIsComplete = field && operator && value && !fieldsHasError; + return ( + + ); }; diff --git a/apps/console/src/app/lib/constants/filters.ts b/apps/console/src/app/lib/constants/filters.ts index 51def04d..17d2810d 100644 --- a/apps/console/src/app/lib/constants/filters.ts +++ b/apps/console/src/app/lib/constants/filters.ts @@ -1,9 +1,75 @@ -export const FILTER_FIELDS_ALLOW_LIST = new Set([ - "request.timestamp", - "response.timestamp", - "response.status", - "calculated.totalTokens", - "calculated.totalCost", - "calculated.duration", - "metadata.conversationId", -]); +export const FILTER_FIELDS_LIST = [ + { + value: "request.timestamp", + type: "string", + label: "Timestamp", + }, + { + value: "response.status", + type: "number", + label: "Status", + }, + { + value: "calculated.totalTokens", + type: "number", + label: "Total Tokens", + }, + { + value: "calculated.totalCost", + type: "number", + label: "Total Cost", + }, + { + value: "calculated.duration", + type: "number", + label: "Duration (ms)", + }, + { + value: "metadata.conversationId", + type: "string", + label: "Conversation ID", + }, +]; + + +export const NUMBER_FILTER_OPERATORS: { value: string; label: string }[] = [ + { + value: "eq", + label: "=", + }, + { + value: "neq", + label: "!=", + }, + { + value: "gt", + label: ">", + }, + { + value: "gte", + label: ">=", + }, + { + value: "lt", + label: "<", + }, + { + value: "lte", + label: "<=", + }, +]; + +export const STRING_FILTER_OPERATORS: { value: string; label: string }[] = [ + { + value: "eq", + label: "=", + }, + { + value: "neq", + label: "!=", + }, + { + value: "contains", + label: "LIKE", + } +]; From 5637b6a355357cc7e33a2e14e16d824f13b0cb0e Mon Sep 17 00:00:00 2001 From: Itay Elgazar Date: Sun, 9 Jul 2023 14:51:06 +0200 Subject: [PATCH 04/10] fix build & add loading state --- .../console/src/app/components/requests/RequestFilters.tsx | 7 ------- apps/console/src/app/lib/constants/filters.ts | 3 +-- apps/console/src/app/pages/requests/RequestsPage.tsx | 4 +--- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/apps/console/src/app/components/requests/RequestFilters.tsx b/apps/console/src/app/components/requests/RequestFilters.tsx index 19eafee1..5a61faa5 100644 --- a/apps/console/src/app/components/requests/RequestFilters.tsx +++ b/apps/console/src/app/components/requests/RequestFilters.tsx @@ -2,23 +2,16 @@ import { RequestReportItem } from "../../pages/requests/types"; import { Card, Space } from "antd"; import styled from "@emotion/styled"; import { AddFilterItem, FilterItem } from "./filters/FilterItem"; -import { Typography } from "antd"; import { useFiltersAndSortParams } from "../../lib/hooks/useFiltersAndSortParams"; import { NUMBER_FILTER_OPERATORS, STRING_FILTER_OPERATORS, } from "../../lib/constants/filters"; -const { Title } = Typography; - const Box = styled.div` padding: 10px 0; `; -const FiltersList = styled.div` - display: flex; -`; - interface Props { requests: RequestReportItem[]; } diff --git a/apps/console/src/app/lib/constants/filters.ts b/apps/console/src/app/lib/constants/filters.ts index 17d2810d..06bf3f36 100644 --- a/apps/console/src/app/lib/constants/filters.ts +++ b/apps/console/src/app/lib/constants/filters.ts @@ -31,7 +31,6 @@ export const FILTER_FIELDS_LIST = [ }, ]; - export const NUMBER_FILTER_OPERATORS: { value: string; label: string }[] = [ { value: "eq", @@ -71,5 +70,5 @@ export const STRING_FILTER_OPERATORS: { value: string; label: string }[] = [ { value: "contains", label: "LIKE", - } + }, ]; diff --git a/apps/console/src/app/pages/requests/RequestsPage.tsx b/apps/console/src/app/pages/requests/RequestsPage.tsx index 55010a0d..74e1b4ca 100644 --- a/apps/console/src/app/pages/requests/RequestsPage.tsx +++ b/apps/console/src/app/pages/requests/RequestsPage.tsx @@ -64,12 +64,9 @@ export const RequestsPage = () => { [reports?.paginatedRequests.data, currentReportId] ); - if (!reports || isLoading) return ; - const { data, pagination } = reports.paginatedRequests; const tableData = data?.map((report) => { - const type = report.provider; const isError = report.response.status >= 400; const response = isError ? JSON.stringify(report.response.body.error ?? {}) @@ -123,6 +120,7 @@ export const RequestsPage = () => { )} { From f7ceac1187263375f50987803ea8c782ab9a4acd Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Sat, 29 Jul 2023 13:06:30 +0200 Subject: [PATCH 05/10] fix: debugger attachment for example app --- .vscode/launch.json | 17 + .../task-generator-app/app/api/tasks/route.ts | 4 +- package-lock.json | 809 ------------------ package.json | 1 - 4 files changed, 19 insertions(+), 812 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..1a645358 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Attach - Examples - Task Generator App", + "port": 9230, + "request": "attach", + "skipFiles": ["/**"], + "type": "node", + // magic line to fix Unbound breakpoints: + "cwd": "${workspaceFolder}/examples/task-generator-app" + } + ] +} diff --git a/examples/task-generator-app/app/api/tasks/route.ts b/examples/task-generator-app/app/api/tasks/route.ts index 05ee12df..3984cf52 100644 --- a/examples/task-generator-app/app/api/tasks/route.ts +++ b/examples/task-generator-app/app/api/tasks/route.ts @@ -16,6 +16,7 @@ export async function POST(request: Request) { }, }); } catch (error) { + console.log("Failed to fetch prompt from Pezzo", error); return NextResponse.json( { message: error.message, @@ -28,14 +29,13 @@ export async function POST(request: Request) { try { const result = await openai.createChatCompletion(prompt); - console.log("result", result.data.choices); const parsed = JSON.parse(result.data.choices[0].message.content); return NextResponse.json(parsed, { headers: { "Content-Type": "application/json" }, }); } catch (error) { - console.error(error); + console.error(error.response.data); return NextResponse.json( { message: diff --git a/package-lock.json b/package-lock.json index 0a03bb90..0d181f9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -103,7 +103,6 @@ "@nrwl/workspace": "15.9.2", "@nx-tools/container-metadata": "^4.0.3", "@nx-tools/nx-container": "^4.0.3", - "@nx/webpack": "^16.0.3", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", "@svgr/webpack": "^6.1.2", "@swc/cli": "~0.1.55", @@ -8477,464 +8476,6 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/@nx/devkit": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-16.0.3.tgz", - "integrity": "sha512-DO4cq1tBtGB+XiHehvJEjYf7gJ/TgDfWuN9PJqcAGC7wxxlsS/4P6ZEr6kmlPjb1FHH6NLgtcp+R+D0zSpV6Ag==", - "dev": true, - "dependencies": { - "@nrwl/devkit": "16.0.3", - "ejs": "^3.1.7", - "ignore": "^5.0.4", - "semver": "7.3.4", - "tmp": "~0.2.1", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "nx": ">= 15 <= 17" - } - }, - "node_modules/@nx/devkit/node_modules/@nrwl/devkit": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-16.0.3.tgz", - "integrity": "sha512-DbSV0vgPc3n/1mP0rKnVgO+m+mNGWRyUjvYifD1IJEvY8qaTsakfqIheINNElK369D5AHrIajCc2FJFHb1OrMw==", - "dev": true, - "dependencies": { - "@nx/devkit": "16.0.3" - } - }, - "node_modules/@nx/js": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-16.0.3.tgz", - "integrity": "sha512-usi3vfP1f5EiwFPZ8GfY1VO3s+ymDxKhizS2vsRwsyOwctcxU0ZYxEfXytuMzOO0MPVYXA+Njqa8+dy9+QJiMg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.15.0", - "@babel/plugin-proposal-class-properties": "^7.14.5", - "@babel/plugin-proposal-decorators": "^7.14.5", - "@babel/plugin-transform-runtime": "^7.15.0", - "@babel/preset-env": "^7.15.0", - "@babel/preset-typescript": "^7.15.0", - "@babel/runtime": "^7.14.8", - "@nrwl/js": "16.0.3", - "@nx/devkit": "16.0.3", - "@nx/workspace": "16.0.3", - "@phenomnomnominal/tsquery": "~5.0.1", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "fast-glob": "3.2.7", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "minimatch": "3.0.5", - "source-map-support": "0.5.19", - "tree-kill": "1.2.2", - "tslib": "^2.3.0" - } - }, - "node_modules/@nx/js/node_modules/@nrwl/js": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-16.0.3.tgz", - "integrity": "sha512-uesZETyFjlAQUqSrOC1PLRMumxzH27mFLVw/adClBcQABpZHvMsb9LxazQf6LBNDfWMUw7fORJoB2iYFBL9yjQ==", - "dev": true, - "dependencies": { - "@nx/js": "16.0.3" - } - }, - "node_modules/@nx/js/node_modules/@phenomnomnominal/tsquery": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz", - "integrity": "sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA==", - "dev": true, - "dependencies": { - "esquery": "^1.4.0" - }, - "peerDependencies": { - "typescript": "^3 || ^4 || ^5" - } - }, - "node_modules/@nx/nx-darwin-arm64": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-16.0.3.tgz", - "integrity": "sha512-QBOlHVTSs6ZN86QoomFDsIhk9rhpCS7w7O6t4wSL4YyB09IqX0unvrsaLLoAx2iEbm+UOMc12klVKWoMQyhHwg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-darwin-x64": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-16.0.3.tgz", - "integrity": "sha512-h2ZjBCwt2Nv7+F9tKHl7Y/xFGn9YUJEkS5TzFTgTfvL9AP5O/8cqwiDebslxeZ7Choff5Slmkj+P2WhJhKa7qQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-16.0.3.tgz", - "integrity": "sha512-gJVkTxOPDdgDPwaMYKvjfcIrWnt1cMlD3tKe9j4jVWsddO9JFLRAtknhXiLFkdcgZwQPo8P1hvo7QgbavbuVSA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-16.0.3.tgz", - "integrity": "sha512-p1ZxZxosfso74aDrP+ofmzrqH3om4LpRAfLDN69L/4OMTT10qLsPpMShWpw9j1U+wZc5o05ZdTMCbeg4jx4Tug==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-linux-arm64-musl": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-16.0.3.tgz", - "integrity": "sha512-t2cQw84TyVdDATFK2R3NyG/LiweBiBLcneHuI8AFr0PSJSqof8BIHqX9NNB2L5z9j2XkEeMgsqnlXfQtOzNXJA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-linux-x64-gnu": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-16.0.3.tgz", - "integrity": "sha512-sKYP9RXAK+wZRXUIlOhqwvSOW6FJblJZPKKHXCWWq9dvAr3CXaWKr+Tt+7846fAX3Q+3hyckuAi6eEiT3XHMTA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-linux-x64-musl": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-16.0.3.tgz", - "integrity": "sha512-AcDWUAs+Tgy4M0bguehUmZTPKE97pYP9GCM8QPzeNJLWyjCfkwHSUImOa0C8+Vx33uRO7I6uPa6QGEoEv/TiFg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-16.0.3.tgz", - "integrity": "sha512-2aXeXYLOhyS0hrSqM5T0T4GK3EoQZZY7oyO4+ruk5f5JZq4LxmdJsrnkgBBR3FmPt7P/GT8vykgJuO9pUAWohQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-win32-x64-msvc": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-16.0.3.tgz", - "integrity": "sha512-/Ezru8nlrckLAQ4s7wEAW192DULgWj9YBqREQPV0ddzwjeVC0clsHSXguH8WzMwEU44+IFnqNMJrWK3mZCvZYA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/webpack": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-16.0.3.tgz", - "integrity": "sha512-3a8xboBvcvCz/kqRDJqxUEo9bJV9zp/W+oLtGd9+VsFdk7qSTY68eI5iJbef6bqUyAD48GRzugQRxDi5F/kc5g==", - "dev": true, - "dependencies": { - "@babel/core": "^7.15.0", - "@nrwl/webpack": "16.0.3", - "@nx/devkit": "16.0.3", - "@nx/js": "16.0.3", - "autoprefixer": "^10.4.9", - "babel-loader": "^9.1.2", - "chalk": "^4.1.0", - "chokidar": "^3.5.1", - "copy-webpack-plugin": "^10.2.4", - "css-loader": "^6.4.0", - "css-minimizer-webpack-plugin": "^3.4.1", - "dotenv": "~10.0.0", - "file-loader": "^6.2.0", - "fork-ts-checker-webpack-plugin": "7.2.13", - "ignore": "^5.0.4", - "less": "4.1.3", - "less-loader": "11.1.0", - "license-webpack-plugin": "^4.0.2", - "loader-utils": "^2.0.3", - "mini-css-extract-plugin": "~2.4.7", - "parse5": "4.0.0", - "postcss": "^8.4.14", - "postcss-import": "~14.1.0", - "postcss-loader": "^6.1.1", - "rxjs": "^6.5.4", - "sass": "^1.42.1", - "sass-loader": "^12.2.0", - "source-map-loader": "^3.0.0", - "style-loader": "^3.3.0", - "stylus": "^0.55.0", - "stylus-loader": "^7.1.0", - "terser-webpack-plugin": "^5.3.3", - "ts-loader": "^9.3.1", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", - "tsconfig-paths-webpack-plugin": "4.0.0", - "tslib": "^2.3.0", - "webpack": "^5.75.0", - "webpack-dev-server": "^4.9.3", - "webpack-node-externals": "^3.0.0", - "webpack-subresource-integrity": "^5.1.0" - } - }, - "node_modules/@nx/webpack/node_modules/@nrwl/webpack": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nrwl/webpack/-/webpack-16.0.3.tgz", - "integrity": "sha512-nLmv0qpPG3ydk/eZ1cn19S8TTzpHxQaQfjKCWt8+dUpog1Eo0ZxEVVaRWyZWDG3oY65Wq6hyKZ2GL1FYbcKgVA==", - "dev": true, - "dependencies": { - "@nx/webpack": "16.0.3" - } - }, - "node_modules/@nx/webpack/node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/webpack/node_modules/parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true - }, - "node_modules/@nx/webpack/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@nx/webpack/node_modules/rxjs/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@nx/workspace": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-16.0.3.tgz", - "integrity": "sha512-jy5a7Gu0p5JgVfVyrnvE5Hqy0A+57U1pl5R3U4XvNNa1848ibVnT3qMkb7s6S50nN6WWHwuCAsIMEV/w88OmRA==", - "dev": true, - "dependencies": { - "@nrwl/workspace": "16.0.3", - "@nx/devkit": "16.0.3", - "@parcel/watcher": "2.0.4", - "chalk": "^4.1.0", - "chokidar": "^3.5.1", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "dotenv": "~10.0.0", - "figures": "3.2.0", - "flat": "^5.0.2", - "ignore": "^5.0.4", - "minimatch": "3.0.5", - "npm-run-path": "^4.0.1", - "nx": "16.0.3", - "open": "^8.4.0", - "rxjs": "^6.5.4", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nx/workspace/node_modules/@nrwl/tao": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-16.0.3.tgz", - "integrity": "sha512-CAECe97eReR1vVf5iuv+Nw0msDJS/HtRBpkkN5e65lSJzEKdsOgpWtteU0QzexN/Spnah8Q/ByM14ii2P1xpCQ==", - "dev": true, - "dependencies": { - "nx": "16.0.3" - }, - "bin": { - "tao": "index.js" - } - }, - "node_modules/@nx/workspace/node_modules/@nrwl/workspace": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-16.0.3.tgz", - "integrity": "sha512-94mcNTttzv9IPKrA/uwGpb1gtIdZKaOJS0Pn/Ec72vEdqL+La6pUaYzEvrPSaBNlf6p+3ZzGYCtw03exar/GdQ==", - "dev": true, - "dependencies": { - "@nx/workspace": "16.0.3" - } - }, - "node_modules/@nx/workspace/node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/workspace/node_modules/nx": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/nx/-/nx-16.0.3.tgz", - "integrity": "sha512-Q76wS7oWsbxi7lxyhI9d10MOvNhbxjDU0J40gdg8DhIi8QWJ5q5SfkD5+Vn1mYy9AA7zyKUF8CGh2kYJMpWPpA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nrwl/tao": "16.0.3", - "@parcel/watcher": "2.0.4", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "^3.0.0-rc.18", - "@zkochan/js-yaml": "0.0.6", - "axios": "^1.0.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^7.0.2", - "dotenv": "~10.0.0", - "enquirer": "~2.3.6", - "fast-glob": "3.2.7", - "figures": "3.2.0", - "flat": "^5.0.2", - "fs-extra": "^11.1.0", - "glob": "7.1.4", - "ignore": "^5.0.4", - "js-yaml": "4.1.0", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "3.0.5", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "semver": "7.3.4", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "v8-compile-cache": "2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "16.0.3", - "@nx/nx-darwin-x64": "16.0.3", - "@nx/nx-linux-arm-gnueabihf": "16.0.3", - "@nx/nx-linux-arm64-gnu": "16.0.3", - "@nx/nx-linux-arm64-musl": "16.0.3", - "@nx/nx-linux-x64-gnu": "16.0.3", - "@nx/nx-linux-x64-musl": "16.0.3", - "@nx/nx-win32-arm64-msvc": "16.0.3", - "@nx/nx-win32-x64-msvc": "16.0.3" - }, - "peerDependencies": { - "@swc-node/register": "^1.4.2", - "@swc/core": "^1.2.173" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nx/workspace/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@nx/workspace/node_modules/rxjs/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/@octokit/auth-token": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", @@ -38182,356 +37723,6 @@ } } }, - "@nx/devkit": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-16.0.3.tgz", - "integrity": "sha512-DO4cq1tBtGB+XiHehvJEjYf7gJ/TgDfWuN9PJqcAGC7wxxlsS/4P6ZEr6kmlPjb1FHH6NLgtcp+R+D0zSpV6Ag==", - "dev": true, - "requires": { - "@nrwl/devkit": "16.0.3", - "ejs": "^3.1.7", - "ignore": "^5.0.4", - "semver": "7.3.4", - "tmp": "~0.2.1", - "tslib": "^2.3.0" - }, - "dependencies": { - "@nrwl/devkit": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-16.0.3.tgz", - "integrity": "sha512-DbSV0vgPc3n/1mP0rKnVgO+m+mNGWRyUjvYifD1IJEvY8qaTsakfqIheINNElK369D5AHrIajCc2FJFHb1OrMw==", - "dev": true, - "requires": { - "@nx/devkit": "16.0.3" - } - } - } - }, - "@nx/js": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-16.0.3.tgz", - "integrity": "sha512-usi3vfP1f5EiwFPZ8GfY1VO3s+ymDxKhizS2vsRwsyOwctcxU0ZYxEfXytuMzOO0MPVYXA+Njqa8+dy9+QJiMg==", - "dev": true, - "requires": { - "@babel/core": "^7.15.0", - "@babel/plugin-proposal-class-properties": "^7.14.5", - "@babel/plugin-proposal-decorators": "^7.14.5", - "@babel/plugin-transform-runtime": "^7.15.0", - "@babel/preset-env": "^7.15.0", - "@babel/preset-typescript": "^7.15.0", - "@babel/runtime": "^7.14.8", - "@nrwl/js": "16.0.3", - "@nx/devkit": "16.0.3", - "@nx/workspace": "16.0.3", - "@phenomnomnominal/tsquery": "~5.0.1", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "fast-glob": "3.2.7", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "minimatch": "3.0.5", - "source-map-support": "0.5.19", - "tree-kill": "1.2.2", - "tslib": "^2.3.0" - }, - "dependencies": { - "@nrwl/js": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-16.0.3.tgz", - "integrity": "sha512-uesZETyFjlAQUqSrOC1PLRMumxzH27mFLVw/adClBcQABpZHvMsb9LxazQf6LBNDfWMUw7fORJoB2iYFBL9yjQ==", - "dev": true, - "requires": { - "@nx/js": "16.0.3" - } - }, - "@phenomnomnominal/tsquery": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz", - "integrity": "sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA==", - "dev": true, - "requires": { - "esquery": "^1.4.0" - } - } - } - }, - "@nx/nx-darwin-arm64": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-16.0.3.tgz", - "integrity": "sha512-QBOlHVTSs6ZN86QoomFDsIhk9rhpCS7w7O6t4wSL4YyB09IqX0unvrsaLLoAx2iEbm+UOMc12klVKWoMQyhHwg==", - "dev": true, - "optional": true - }, - "@nx/nx-darwin-x64": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-16.0.3.tgz", - "integrity": "sha512-h2ZjBCwt2Nv7+F9tKHl7Y/xFGn9YUJEkS5TzFTgTfvL9AP5O/8cqwiDebslxeZ7Choff5Slmkj+P2WhJhKa7qQ==", - "dev": true, - "optional": true - }, - "@nx/nx-linux-arm-gnueabihf": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-16.0.3.tgz", - "integrity": "sha512-gJVkTxOPDdgDPwaMYKvjfcIrWnt1cMlD3tKe9j4jVWsddO9JFLRAtknhXiLFkdcgZwQPo8P1hvo7QgbavbuVSA==", - "dev": true, - "optional": true - }, - "@nx/nx-linux-arm64-gnu": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-16.0.3.tgz", - "integrity": "sha512-p1ZxZxosfso74aDrP+ofmzrqH3om4LpRAfLDN69L/4OMTT10qLsPpMShWpw9j1U+wZc5o05ZdTMCbeg4jx4Tug==", - "dev": true, - "optional": true - }, - "@nx/nx-linux-arm64-musl": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-16.0.3.tgz", - "integrity": "sha512-t2cQw84TyVdDATFK2R3NyG/LiweBiBLcneHuI8AFr0PSJSqof8BIHqX9NNB2L5z9j2XkEeMgsqnlXfQtOzNXJA==", - "dev": true, - "optional": true - }, - "@nx/nx-linux-x64-gnu": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-16.0.3.tgz", - "integrity": "sha512-sKYP9RXAK+wZRXUIlOhqwvSOW6FJblJZPKKHXCWWq9dvAr3CXaWKr+Tt+7846fAX3Q+3hyckuAi6eEiT3XHMTA==", - "dev": true, - "optional": true - }, - "@nx/nx-linux-x64-musl": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-16.0.3.tgz", - "integrity": "sha512-AcDWUAs+Tgy4M0bguehUmZTPKE97pYP9GCM8QPzeNJLWyjCfkwHSUImOa0C8+Vx33uRO7I6uPa6QGEoEv/TiFg==", - "dev": true, - "optional": true - }, - "@nx/nx-win32-arm64-msvc": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-16.0.3.tgz", - "integrity": "sha512-2aXeXYLOhyS0hrSqM5T0T4GK3EoQZZY7oyO4+ruk5f5JZq4LxmdJsrnkgBBR3FmPt7P/GT8vykgJuO9pUAWohQ==", - "dev": true, - "optional": true - }, - "@nx/nx-win32-x64-msvc": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-16.0.3.tgz", - "integrity": "sha512-/Ezru8nlrckLAQ4s7wEAW192DULgWj9YBqREQPV0ddzwjeVC0clsHSXguH8WzMwEU44+IFnqNMJrWK3mZCvZYA==", - "dev": true, - "optional": true - }, - "@nx/webpack": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-16.0.3.tgz", - "integrity": "sha512-3a8xboBvcvCz/kqRDJqxUEo9bJV9zp/W+oLtGd9+VsFdk7qSTY68eI5iJbef6bqUyAD48GRzugQRxDi5F/kc5g==", - "dev": true, - "requires": { - "@babel/core": "^7.15.0", - "@nrwl/webpack": "16.0.3", - "@nx/devkit": "16.0.3", - "@nx/js": "16.0.3", - "autoprefixer": "^10.4.9", - "babel-loader": "^9.1.2", - "chalk": "^4.1.0", - "chokidar": "^3.5.1", - "copy-webpack-plugin": "^10.2.4", - "css-loader": "^6.4.0", - "css-minimizer-webpack-plugin": "^3.4.1", - "dotenv": "~10.0.0", - "file-loader": "^6.2.0", - "fork-ts-checker-webpack-plugin": "7.2.13", - "ignore": "^5.0.4", - "less": "4.1.3", - "less-loader": "11.1.0", - "license-webpack-plugin": "^4.0.2", - "loader-utils": "^2.0.3", - "mini-css-extract-plugin": "~2.4.7", - "parse5": "4.0.0", - "postcss": "^8.4.14", - "postcss-import": "~14.1.0", - "postcss-loader": "^6.1.1", - "rxjs": "^6.5.4", - "sass": "^1.42.1", - "sass-loader": "^12.2.0", - "source-map-loader": "^3.0.0", - "style-loader": "^3.3.0", - "stylus": "^0.55.0", - "stylus-loader": "^7.1.0", - "terser-webpack-plugin": "^5.3.3", - "ts-loader": "^9.3.1", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", - "tsconfig-paths-webpack-plugin": "4.0.0", - "tslib": "^2.3.0", - "webpack": "^5.75.0", - "webpack-dev-server": "^4.9.3", - "webpack-node-externals": "^3.0.0", - "webpack-subresource-integrity": "^5.1.0" - }, - "dependencies": { - "@nrwl/webpack": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nrwl/webpack/-/webpack-16.0.3.tgz", - "integrity": "sha512-nLmv0qpPG3ydk/eZ1cn19S8TTzpHxQaQfjKCWt8+dUpog1Eo0ZxEVVaRWyZWDG3oY65Wq6hyKZ2GL1FYbcKgVA==", - "dev": true, - "requires": { - "@nx/webpack": "16.0.3" - } - }, - "dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true - }, - "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true - }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - } - } - }, - "@nx/workspace": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-16.0.3.tgz", - "integrity": "sha512-jy5a7Gu0p5JgVfVyrnvE5Hqy0A+57U1pl5R3U4XvNNa1848ibVnT3qMkb7s6S50nN6WWHwuCAsIMEV/w88OmRA==", - "dev": true, - "requires": { - "@nrwl/workspace": "16.0.3", - "@nx/devkit": "16.0.3", - "@parcel/watcher": "2.0.4", - "chalk": "^4.1.0", - "chokidar": "^3.5.1", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "dotenv": "~10.0.0", - "figures": "3.2.0", - "flat": "^5.0.2", - "ignore": "^5.0.4", - "minimatch": "3.0.5", - "npm-run-path": "^4.0.1", - "nx": "16.0.3", - "open": "^8.4.0", - "rxjs": "^6.5.4", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "dependencies": { - "@nrwl/tao": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-16.0.3.tgz", - "integrity": "sha512-CAECe97eReR1vVf5iuv+Nw0msDJS/HtRBpkkN5e65lSJzEKdsOgpWtteU0QzexN/Spnah8Q/ByM14ii2P1xpCQ==", - "dev": true, - "requires": { - "nx": "16.0.3" - } - }, - "@nrwl/workspace": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-16.0.3.tgz", - "integrity": "sha512-94mcNTttzv9IPKrA/uwGpb1gtIdZKaOJS0Pn/Ec72vEdqL+La6pUaYzEvrPSaBNlf6p+3ZzGYCtw03exar/GdQ==", - "dev": true, - "requires": { - "@nx/workspace": "16.0.3" - } - }, - "dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true - }, - "nx": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/nx/-/nx-16.0.3.tgz", - "integrity": "sha512-Q76wS7oWsbxi7lxyhI9d10MOvNhbxjDU0J40gdg8DhIi8QWJ5q5SfkD5+Vn1mYy9AA7zyKUF8CGh2kYJMpWPpA==", - "dev": true, - "requires": { - "@nrwl/tao": "16.0.3", - "@nx/nx-darwin-arm64": "16.0.3", - "@nx/nx-darwin-x64": "16.0.3", - "@nx/nx-linux-arm-gnueabihf": "16.0.3", - "@nx/nx-linux-arm64-gnu": "16.0.3", - "@nx/nx-linux-arm64-musl": "16.0.3", - "@nx/nx-linux-x64-gnu": "16.0.3", - "@nx/nx-linux-x64-musl": "16.0.3", - "@nx/nx-win32-arm64-msvc": "16.0.3", - "@nx/nx-win32-x64-msvc": "16.0.3", - "@parcel/watcher": "2.0.4", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "^3.0.0-rc.18", - "@zkochan/js-yaml": "0.0.6", - "axios": "^1.0.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^7.0.2", - "dotenv": "~10.0.0", - "enquirer": "~2.3.6", - "fast-glob": "3.2.7", - "figures": "3.2.0", - "flat": "^5.0.2", - "fs-extra": "^11.1.0", - "glob": "7.1.4", - "ignore": "^5.0.4", - "js-yaml": "4.1.0", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "3.0.5", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "semver": "7.3.4", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "v8-compile-cache": "2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - } - }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - } - } - }, "@octokit/auth-token": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", diff --git a/package.json b/package.json index 6c5583d8..2185fa9f 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,6 @@ "@nrwl/workspace": "15.9.2", "@nx-tools/container-metadata": "^4.0.3", "@nx-tools/nx-container": "^4.0.3", - "@nx/webpack": "^16.0.3", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", "@svgr/webpack": "^6.1.2", "@swc/cli": "~0.1.55", From 179ffceb2469b08b3552e17d50fc93a78b84a92e Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Sat, 29 Jul 2023 13:47:53 +0200 Subject: [PATCH 06/10] feat: reporting in PezzoOpenAI --- .../task-generator-app/app/api/tasks/route.ts | 9 +- libs/client/src/client/Pezzo.ts | 26 ++-- libs/client/src/client/PezzoOpenAI.ts | 112 ++++++++++++------ libs/client/src/types/prompts.ts | 9 +- 4 files changed, 93 insertions(+), 63 deletions(-) diff --git a/examples/task-generator-app/app/api/tasks/route.ts b/examples/task-generator-app/app/api/tasks/route.ts index 3984cf52..bc099b01 100644 --- a/examples/task-generator-app/app/api/tasks/route.ts +++ b/examples/task-generator-app/app/api/tasks/route.ts @@ -28,7 +28,14 @@ export async function POST(request: Request) { } try { - const result = await openai.createChatCompletion(prompt); + const result = await openai.createChatCompletion(prompt, { + variables: { + goal: "Become a chef", + }, + properties: { + traceId: "SomeTraceId123", + }, + }); const parsed = JSON.parse(result.data.choices[0].message.content); return NextResponse.json(parsed, { diff --git a/libs/client/src/client/Pezzo.ts b/libs/client/src/client/Pezzo.ts index e194b959..8acedd5b 100644 --- a/libs/client/src/client/Pezzo.ts +++ b/libs/client/src/client/Pezzo.ts @@ -38,10 +38,7 @@ export class Pezzo { }); } - async getPrompt( - promptName: string, - options?: GetPromptOptions - ): Promise<{ pezzo: Prompt }> { + async getPrompt(promptName: string): Promise<{ pezzo: Prompt }> { const url = new URL(`${this.options.serverUrl}/api/prompts/v2/deployment`); url.searchParams.append("name", promptName); url.searchParams.append("environmentName", this.options.environment); @@ -63,23 +60,14 @@ export class Pezzo { } } - let interpolatedContent: any = {}; - - if (options?.variables) { - if (data.type === PromptType.Prompt) { - interpolatedContent = { - prompt: interpolateVariables(data.content.prompt, options?.variables), - }; - } - } - const pezzoPrompt: Prompt = { - promptId: data.promptId, - promptVersionSha: data.promptVersionSha, - type: data.type, + metadata: { + promptId: data.promptId, + promptVersionSha: data.promptVersionSha, + type: data.type, + }, settings: data.settings, content: data.content, - interpolatedContent, }; return { @@ -87,7 +75,7 @@ export class Pezzo { }; } - async reportPromptExecutionV2(dto: ReportData) { + async reportPromptExecution(dto: ReportData) { await axios.post( `${this.options.serverUrl}/api/reporting/v2/request`, dto, diff --git a/libs/client/src/client/PezzoOpenAI.ts b/libs/client/src/client/PezzoOpenAI.ts index dccfffe9..d371f993 100644 --- a/libs/client/src/client/PezzoOpenAI.ts +++ b/libs/client/src/client/PezzoOpenAI.ts @@ -3,10 +3,12 @@ import { CreateChatCompletionRequest as OriginalCreateChatCompletionRequest, OpenAIApi, } from "openai"; -import { InjectPezzoProps } from "../types"; +import { InjectPezzoProps, ReportData } from "../types"; import { Pezzo } from "./Pezzo"; import { PromptType } from "../@generated/graphql/graphql"; -import { PromptService } from "@pezzo/types"; +import { PromptExecutionType, Provider } from "@pezzo/types"; +import { merge } from "../utils/helpers"; +import { interpolateVariables } from "../utils"; type CreateChatCompletionRequest = Omit< OriginalCreateChatCompletionRequest, @@ -19,6 +21,11 @@ type CreateChatCompletionRequest = Omit< type PezzoCreateChatCompletionRequest = InjectPezzoProps; +interface PezzoProps { + variables?: Record; + properties?: Record; +} + export class PezzoOpenAIApi extends OpenAIApi { constructor( private readonly pezzo: Pezzo, @@ -27,8 +34,10 @@ export class PezzoOpenAIApi extends OpenAIApi { super(...args); } + // @ts-expect-error Overriding the 2nd argument of the OpenAI createChatCompletion API override async createChatCompletion( _arg1: PezzoCreateChatCompletionRequest | CreateChatCompletionRequest, + pezzoProps?: PezzoProps, ...rest: Parameters[1] extends infer P ? P[] : never[] @@ -39,17 +48,27 @@ export class PezzoOpenAIApi extends OpenAIApi { const nativeOptions = { ...arg1 }; delete nativeOptions["pezzo"]; - const settings = - pezzoPrompt.settings[PromptService.OpenAIChatCompletion] ?? {}; + const settings = pezzoPrompt.settings; + + let interpolatedContent: any = {}; + + if (pezzoProps?.variables) { + if (pezzoPrompt.metadata.type === PromptType.Prompt) { + interpolatedContent = { + prompt: interpolateVariables( + pezzoPrompt.content.prompt, + pezzoProps.variables + ), + }; + } + } let messages: ChatCompletionRequestMessage[] = []; - if (pezzoPrompt.type === PromptType.Prompt) { - messages = [ - { role: "user", content: pezzoPrompt.interpolatedContent.prompt }, - ]; + if (pezzoPrompt.metadata.type === PromptType.Prompt) { + messages = [{ role: "user", content: interpolatedContent.prompt }]; } else if (pezzoPrompt.type === PromptType.Chat) { - messages = pezzoPrompt.interpolatedContent.messages; + // TODO: support chat type in the future } const requestBody: Partial = { @@ -58,48 +77,63 @@ export class PezzoOpenAIApi extends OpenAIApi { messages, }; - const requestTimestamp = new Date().toISOString(); - let result; let error; + let reportPayload: ReportData; + + const baseMetadata = { + environment: this.pezzo.options.environment, + }; + + const requestTimestamp = new Date().toISOString(); try { result = await super.createChatCompletion.call( this, ...[requestBody, ...rest.slice(1)] ); + const { _request, ...response } = result; + + reportPayload = { + provider: Provider.OpenAI, + type: PromptExecutionType.ChatCompletion, + metadata: merge(baseMetadata, pezzoPrompt.metadata), // TODO: merge pezzo metadata + properties: pezzoProps?.properties, + request: { + timestamp: requestTimestamp, + body: requestBody, + }, + response: { + timestamp: new Date().toISOString(), + body: response.data ?? response.response.data, + status: response.status ?? response.response.status, + }, + }; } catch (err) { error = err; - } - // const { request, ...response } = result; - const responseTimestamp = new Date().toISOString(); - - const baseMetadata = { - environment: this.pezzo.options.environment, - }; + reportPayload = { + provider: Provider.OpenAI, + type: PromptExecutionType.ChatCompletion, + metadata: merge(baseMetadata, pezzoPrompt.metadata), // TODO: merge pezzo metadata + properties: pezzoProps?.properties, + request: { + timestamp: requestTimestamp, + body: requestBody, + }, + response: { + timestamp: new Date().toISOString(), + body: err.data ?? err.response.data, + status: err.status ?? err.response.status, + }, + }; + } - // const reportPayload: ReportData = { - // provider: ProviderType.OpenAI, - // type: PromptExecutionType.ChatCompletion, - // metadata: merge(pezzo?.metadata ?? {}, baseMetadata), - // ...(pezzo?.properties && { properties: pezzo.properties }), - // request: { - // timestamp: requestTimestamp, - // body: requestBody, - // }, - // response: { - // timestamp: responseTimestamp, - // body: response.data ?? response.response.data, - // status: response.status ?? response.response.status, - // }, - // }; - - // try { - // await this.pezzo.reportPromptExecutionV2(reportPayload); - // } catch (error) { - // console.error("Failed to report prompt execution", error); - // } + try { + await this.pezzo.reportPromptExecution(reportPayload); + } catch (error) { + console.error("Failed to report prompt execution", error); + } if (error) { throw error; diff --git a/libs/client/src/types/prompts.ts b/libs/client/src/types/prompts.ts index 40bd931b..948bc8f1 100644 --- a/libs/client/src/types/prompts.ts +++ b/libs/client/src/types/prompts.ts @@ -13,12 +13,13 @@ export type GetPromptResult = { }; export interface Prompt { - promptId: string; - promptVersionSha: string; - type: PromptType; + metadata: { + promptId: string; + promptVersionSha: string; + type: PromptType; + }; settings: TSettings; content: PrompContent; - interpolatedContent: PrompContent; } export interface ReportPromptExecutionResult { From 2f0b338485bd34055eb93acda3482f5521afe098 Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Sat, 29 Jul 2023 15:22:05 +0200 Subject: [PATCH 07/10] rename "latency" to "duration" --- apps/console/src/app/components/requests/RequestDetails.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/console/src/app/components/requests/RequestDetails.tsx b/apps/console/src/app/components/requests/RequestDetails.tsx index c840ac20..20513435 100644 --- a/apps/console/src/app/components/requests/RequestDetails.tsx +++ b/apps/console/src/app/components/requests/RequestDetails.tsx @@ -86,7 +86,7 @@ export const RequestDetails = (props: Props) => { ), }, { - title: "Latency", + title: "Duration", description: ms(props.calculated.duration), }, ]} From eecefaa8c9bb178e18075563ac9a42a1fe0b9f94 Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Sat, 29 Jul 2023 15:23:44 +0200 Subject: [PATCH 08/10] functioning reporting without managing prompt --- .../requests/filters/FilterItem.tsx | 8 +- apps/console/src/app/lib/constants/filters.ts | 7 +- .../src/app/pages/requests/RequestsPage.tsx | 87 ++++++++++--------- .../pages/requests/UnmanagedPromptWarning.tsx | 11 +++ apps/console/src/app/pages/requests/types.ts | 7 +- .../task-generator-app/app/api/tasks/route.ts | 12 +-- libs/client/src/client/Pezzo.ts | 2 - libs/client/src/client/PezzoOpenAI.ts | 69 ++++++--------- .../client/src/utils/interpolate-variables.ts | 30 +++++++ libs/common/src/utils/index.ts | 1 - .../common/src/utils/interpolate-variables.ts | 9 -- package-lock.json | 2 - package.json | 2 - 13 files changed, 124 insertions(+), 123 deletions(-) create mode 100644 apps/console/src/app/pages/requests/UnmanagedPromptWarning.tsx delete mode 100644 libs/common/src/utils/interpolate-variables.ts diff --git a/apps/console/src/app/components/requests/filters/FilterItem.tsx b/apps/console/src/app/components/requests/filters/FilterItem.tsx index e52918a0..42b660be 100644 --- a/apps/console/src/app/components/requests/filters/FilterItem.tsx +++ b/apps/console/src/app/components/requests/filters/FilterItem.tsx @@ -85,7 +85,7 @@ export const AddFilterForm = ({ > - ); }} diff --git a/apps/console/src/app/lib/constants/filters.ts b/apps/console/src/app/lib/constants/filters.ts index 06bf3f36..f6d6cf59 100644 --- a/apps/console/src/app/lib/constants/filters.ts +++ b/apps/console/src/app/lib/constants/filters.ts @@ -1,7 +1,7 @@ export const FILTER_FIELDS_LIST = [ { value: "request.timestamp", - type: "string", + type: "date", label: "Timestamp", }, { @@ -24,11 +24,6 @@ export const FILTER_FIELDS_LIST = [ type: "number", label: "Duration (ms)", }, - { - value: "metadata.conversationId", - type: "string", - label: "Conversation ID", - }, ]; export const NUMBER_FILTER_OPERATORS: { value: string; label: string }[] = [ diff --git a/apps/console/src/app/pages/requests/RequestsPage.tsx b/apps/console/src/app/pages/requests/RequestsPage.tsx index 74e1b4ca..6d661b12 100644 --- a/apps/console/src/app/pages/requests/RequestsPage.tsx +++ b/apps/console/src/app/pages/requests/RequestsPage.tsx @@ -1,9 +1,7 @@ import { Divider, Drawer, Space, Table, Tag, Typography } from "antd"; import type { ColumnsType } from "antd/es/table"; import { useGetRequestReports } from "../../graphql/hooks/queries"; -import ms from "ms"; import { useMemo, useState } from "react"; -import { Loading3QuartersOutlined } from "@ant-design/icons"; import { DEFAULT_PAGE_SIZE, PAGE_SIZE_OPTIONS, @@ -12,43 +10,48 @@ import { RequestDetails } from "../../components/requests/RequestDetails"; import { toDollarSign } from "../../lib/utils/currency-utils"; import { RequestFilters } from "../../components/requests/RequestFilters"; import { RequestReportItem } from "./types"; +import { UnmanagedPromptWarning } from "./UnmanagedPromptWarning"; -const columns: ColumnsType = [ - { - title: "Timestamp", - dataIndex: "timestamp", - width: "20%", - }, - { - title: "Status", - dataIndex: "status", - }, - { - title: "Request", - dataIndex: "request", - width: "20%", - ellipsis: true, - }, - { - title: "Response", - dataIndex: "response", +const getTableColumns = ( + data: RequestReportItem[] +): ColumnsType => { + const columns: ColumnsType = [ + { + title: "Timestamp", + dataIndex: "timestamp", + width: "20%", + }, + { + title: "Status", + dataIndex: "status", + }, + { + title: "Duration", + dataIndex: "duration", + }, + { + title: "Total Tokens", + dataIndex: "totalTokens", + }, + { + title: "Cost", + dataIndex: "cost", + }, + ]; - width: "20%", - ellipsis: true, - }, - { - title: "Latency", - dataIndex: "latency", - }, - { - title: "Total Tokens", - dataIndex: "totalTokens", - }, - { - title: "Cost", - dataIndex: "cost", - }, -]; + const hasUnmanagedPrompts = data.some((r) => !r.promptId); + + if (hasUnmanagedPrompts) { + columns.unshift({ + title: "", + dataIndex: "promptId", + render: (promptId?: string) => !promptId && , + width: "40px", + align: "center", + }); + } + return columns; +}; export const RequestsPage = () => { const [size, setSize] = useState(DEFAULT_PAGE_SIZE); @@ -68,9 +71,6 @@ export const RequestsPage = () => { const tableData = data?.map((report) => { const isError = report.response.status >= 400; - const response = isError - ? JSON.stringify(report.response.body.error ?? {}) - : report.response.body?.choices?.[0].message.content; return { key: report.reportId, @@ -80,19 +80,20 @@ export const RequestsPage = () => { ) : ( Success ), - request: report.request.body?.messages?.[0]?.content ?? "N/A", - response: {response}, - latency: ms(report.calculated.duration), + duration: `${(report.calculated.duration / 1000).toFixed(2)}s`, totalTokens: report.calculated.totalTokens ?? 0, cost: report.calculated.totalCost ? toDollarSign(report.calculated.totalCost) : "$0.0000", + promptId: report.metadata?.promptId, }; }); const handleShowDetails = (record: RequestReportItem) => () => setCurrentReportId(record.key); + const columns = getTableColumns(tableData); + return (
diff --git a/apps/console/src/app/pages/requests/UnmanagedPromptWarning.tsx b/apps/console/src/app/pages/requests/UnmanagedPromptWarning.tsx new file mode 100644 index 00000000..88758d36 --- /dev/null +++ b/apps/console/src/app/pages/requests/UnmanagedPromptWarning.tsx @@ -0,0 +1,11 @@ +import { WarningOutlined } from "@ant-design/icons"; +import { Popover } from "antd"; +import colors from "tailwindcss/colors"; + +export const UnmanagedPromptWarning = () => { + return ( + This prompt is not managed by Pezzo}> + + + ); +}; diff --git a/apps/console/src/app/pages/requests/types.ts b/apps/console/src/app/pages/requests/types.ts index d82a80c3..67836b8c 100644 --- a/apps/console/src/app/pages/requests/types.ts +++ b/apps/console/src/app/pages/requests/types.ts @@ -1,10 +1,11 @@ +import { AllPrimitiveTypes } from "@pezzo/types"; + export interface RequestReportItem { key: string; timestamp: string; status: JSX.Element; - request: string; - response: JSX.Element; - latency: string; + duration: string; totalTokens?: number; cost?: string; + promptId?: AllPrimitiveTypes; } diff --git a/examples/task-generator-app/app/api/tasks/route.ts b/examples/task-generator-app/app/api/tasks/route.ts index bc099b01..0226e3f9 100644 --- a/examples/task-generator-app/app/api/tasks/route.ts +++ b/examples/task-generator-app/app/api/tasks/route.ts @@ -9,12 +9,7 @@ export async function POST(request: Request) { let prompt: GetPromptResult; try { - prompt = await pezzo.getPrompt("GenerateTasks", { - variables: { - goal, - numTasks, - }, - }); + prompt = await pezzo.getPrompt("GenerateTasks"); } catch (error) { console.log("Failed to fetch prompt from Pezzo", error); return NextResponse.json( @@ -30,7 +25,8 @@ export async function POST(request: Request) { try { const result = await openai.createChatCompletion(prompt, { variables: { - goal: "Become a chef", + goal, + numTasks, }, properties: { traceId: "SomeTraceId123", @@ -42,7 +38,7 @@ export async function POST(request: Request) { headers: { "Content-Type": "application/json" }, }); } catch (error) { - console.error(error.response.data); + console.error(error); return NextResponse.json( { message: diff --git a/libs/client/src/client/Pezzo.ts b/libs/client/src/client/Pezzo.ts index 8acedd5b..6bfe4445 100644 --- a/libs/client/src/client/Pezzo.ts +++ b/libs/client/src/client/Pezzo.ts @@ -1,8 +1,6 @@ import axios, { AxiosInstance } from "axios"; import { ReportData } from "../types"; import { Prompt } from "../types/prompts"; -import { interpolateVariables } from "../utils"; -import { PromptType } from "../@generated/graphql/graphql"; export interface PezzoClientOptions { serverUrl?: string; diff --git a/libs/client/src/client/PezzoOpenAI.ts b/libs/client/src/client/PezzoOpenAI.ts index d371f993..e29afab4 100644 --- a/libs/client/src/client/PezzoOpenAI.ts +++ b/libs/client/src/client/PezzoOpenAI.ts @@ -5,10 +5,9 @@ import { } from "openai"; import { InjectPezzoProps, ReportData } from "../types"; import { Pezzo } from "./Pezzo"; -import { PromptType } from "../@generated/graphql/graphql"; import { PromptExecutionType, Provider } from "@pezzo/types"; import { merge } from "../utils/helpers"; -import { interpolateVariables } from "../utils"; +import { interpolateVariablesRecursively } from "../utils"; type CreateChatCompletionRequest = Omit< OriginalCreateChatCompletionRequest, @@ -37,7 +36,7 @@ export class PezzoOpenAIApi extends OpenAIApi { // @ts-expect-error Overriding the 2nd argument of the OpenAI createChatCompletion API override async createChatCompletion( _arg1: PezzoCreateChatCompletionRequest | CreateChatCompletionRequest, - pezzoProps?: PezzoProps, + pezzoOptions?: PezzoProps, ...rest: Parameters[1] extends infer P ? P[] : never[] @@ -48,35 +47,26 @@ export class PezzoOpenAIApi extends OpenAIApi { const nativeOptions = { ...arg1 }; delete nativeOptions["pezzo"]; - const settings = pezzoPrompt.settings; + let managedMessages: ChatCompletionRequestMessage[] = []; - let interpolatedContent: any = {}; - - if (pezzoProps?.variables) { - if (pezzoPrompt.metadata.type === PromptType.Prompt) { - interpolatedContent = { - prompt: interpolateVariables( - pezzoPrompt.content.prompt, - pezzoProps.variables - ), - }; - } - } - - let messages: ChatCompletionRequestMessage[] = []; - - if (pezzoPrompt.metadata.type === PromptType.Prompt) { - messages = [{ role: "user", content: interpolatedContent.prompt }]; - } else if (pezzoPrompt.type === PromptType.Chat) { - // TODO: support chat type in the future + if (pezzoPrompt) { + managedMessages = [{ role: "user", content: pezzoPrompt.content.prompt }]; } const requestBody: Partial = { + messages: managedMessages, + ...(pezzoPrompt?.settings ?? {}), ...nativeOptions, - ...settings, - messages, }; + if (pezzoOptions?.variables) { + const messages = interpolateVariablesRecursively< + ChatCompletionRequestMessage[] + >(requestBody.messages, pezzoOptions.variables); + + requestBody.messages = messages; + } + let result; let error; let reportPayload: ReportData; @@ -87,6 +77,17 @@ export class PezzoOpenAIApi extends OpenAIApi { const requestTimestamp = new Date().toISOString(); + const baseReport = { + provider: Provider.OpenAI, + type: PromptExecutionType.ChatCompletion, + metadata: merge(baseMetadata, pezzoPrompt?.metadata), // TODO: merge pezzo metadata + properties: pezzoOptions?.properties, + request: { + timestamp: requestTimestamp, + body: requestBody, + }, + }; + try { result = await super.createChatCompletion.call( this, @@ -95,14 +96,7 @@ export class PezzoOpenAIApi extends OpenAIApi { const { _request, ...response } = result; reportPayload = { - provider: Provider.OpenAI, - type: PromptExecutionType.ChatCompletion, - metadata: merge(baseMetadata, pezzoPrompt.metadata), // TODO: merge pezzo metadata - properties: pezzoProps?.properties, - request: { - timestamp: requestTimestamp, - body: requestBody, - }, + ...baseReport, response: { timestamp: new Date().toISOString(), body: response.data ?? response.response.data, @@ -113,14 +107,7 @@ export class PezzoOpenAIApi extends OpenAIApi { error = err; reportPayload = { - provider: Provider.OpenAI, - type: PromptExecutionType.ChatCompletion, - metadata: merge(baseMetadata, pezzoPrompt.metadata), // TODO: merge pezzo metadata - properties: pezzoProps?.properties, - request: { - timestamp: requestTimestamp, - body: requestBody, - }, + ...baseReport, response: { timestamp: new Date().toISOString(), body: err.data ?? err.response.data, diff --git a/libs/client/src/utils/interpolate-variables.ts b/libs/client/src/utils/interpolate-variables.ts index d4f05de3..9b39b20a 100644 --- a/libs/client/src/utils/interpolate-variables.ts +++ b/libs/client/src/utils/interpolate-variables.ts @@ -7,3 +7,33 @@ export function interpolateVariables( variables.hasOwnProperty(key) ? String(variables[key]) : match ); } + +export function interpolateVariablesRecursively( + obj: Record, + variables: Record +): T { + const processValue = (value: any): any => { + if (typeof value === "string") { + return value.replace(/{\s*(\w+)\s*}/g, (match, key) => + Object.prototype.hasOwnProperty.call(variables, key) + ? String(variables[key]) + : match + ); + } else if (Array.isArray(value)) { + return value.map(processValue); + } else if (typeof value === "object" && value !== null) { + return processObj(value); + } else { + return value; + } + }; + + const processObj = (object: Record): Record => { + return Object.entries(object).reduce((newObject, [key, value]) => { + newObject[key] = processValue(value); + return newObject; + }, {} as Record); + }; + + return processValue(obj) as T; +} diff --git a/libs/common/src/utils/index.ts b/libs/common/src/utils/index.ts index 0b41fddb..4a2f3e0e 100644 --- a/libs/common/src/utils/index.ts +++ b/libs/common/src/utils/index.ts @@ -1,2 +1 @@ -export * from "./interpolate-variables"; export * from "./slugify"; diff --git a/libs/common/src/utils/interpolate-variables.ts b/libs/common/src/utils/interpolate-variables.ts deleted file mode 100644 index d4f05de3..00000000 --- a/libs/common/src/utils/interpolate-variables.ts +++ /dev/null @@ -1,9 +0,0 @@ -export function interpolateVariables( - text: string, - variables: Record -): string { - return text.replace(/{\s*(\w+)\s*}/g, (match, key) => - // eslint-disable-next-line no-prototype-builtins - variables.hasOwnProperty(key) ? String(variables[key]) : match - ); -} diff --git a/package-lock.json b/package-lock.json index 0d181f9c..6d496d98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,7 +60,6 @@ "joi": "^17.9.1", "kafkajs": "^2.2.4", "lottie-react": "^2.4.0", - "ms": "^2.1.3", "next": "^13.4.7", "openai": "^3.3.0", "pino": "^8.14.1", @@ -110,7 +109,6 @@ "@swc/jest": "0.2.20", "@testing-library/react": "14.0.0", "@types/jest": "^29.4.0", - "@types/ms": "^0.7.31", "@types/node": "18.14.2", "@types/react": "18.0.28", "@types/react-dom": "18.0.11", diff --git a/package.json b/package.json index 2185fa9f..08dc1fcc 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "joi": "^17.9.1", "kafkajs": "^2.2.4", "lottie-react": "^2.4.0", - "ms": "^2.1.3", "next": "^13.4.7", "openai": "^3.3.0", "pino": "^8.14.1", @@ -110,7 +109,6 @@ "@swc/jest": "0.2.20", "@testing-library/react": "14.0.0", "@types/jest": "^29.4.0", - "@types/ms": "^0.7.31", "@types/node": "18.14.2", "@types/react": "18.0.28", "@types/react-dom": "18.0.11", From c3f88dc8d56d9ca56724a4e06a3b91bba7d9d3d7 Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Sat, 29 Jul 2023 15:45:49 +0200 Subject: [PATCH 09/10] simplify types --- .../src/app/graphql/definitions/queries/requests.ts | 2 -- apps/console/src/app/graphql/hooks/queries.ts | 2 +- apps/console/src/app/graphql/types.ts | 5 +---- apps/console/src/app/pages/requests/RequestsPage.tsx | 2 +- apps/server/src/app/opensearch/create-indexes.ts | 11 ++++------- apps/server/src/app/opensearch/types.ts | 2 +- .../src/app/reporting/dto/report-request.dto.ts | 11 ++--------- .../reporting/object-types/request-report.model.ts | 6 ------ apps/server/src/app/reporting/reporting.service.ts | 5 ++--- .../src/app/reporting/utils/build-request-report.ts | 2 +- libs/client/src/client/PezzoOpenAI.ts | 12 ++++++++---- libs/client/src/types/observability.ts | 7 +++---- libs/types/src/request.ts | 4 +++- 13 files changed, 27 insertions(+), 44 deletions(-) diff --git a/apps/console/src/app/graphql/definitions/queries/requests.ts b/apps/console/src/app/graphql/definitions/queries/requests.ts index 9725dc09..cda58e00 100644 --- a/apps/console/src/app/graphql/definitions/queries/requests.ts +++ b/apps/console/src/app/graphql/definitions/queries/requests.ts @@ -7,11 +7,9 @@ export const GET_ALL_REQUESTS = graphql(/* GraphQL */ ` reportId request response - provider calculated properties metadata - type } pagination { page diff --git a/apps/console/src/app/graphql/hooks/queries.ts b/apps/console/src/app/graphql/hooks/queries.ts index 96e7e203..b91a8e67 100644 --- a/apps/console/src/app/graphql/hooks/queries.ts +++ b/apps/console/src/app/graphql/hooks/queries.ts @@ -102,7 +102,7 @@ export const useGetPromptVersion = ( }; const buildTypedRequestReportObject = (requestReport: RequestReport) => { - switch (requestReport.provider) { + switch (requestReport.metadata.providers) { case Provider.OpenAI: return requestReport as ReportRequestResponse; default: diff --git a/apps/console/src/app/graphql/types.ts b/apps/console/src/app/graphql/types.ts index 2bf9471a..6135dc6c 100644 --- a/apps/console/src/app/graphql/types.ts +++ b/apps/console/src/app/graphql/types.ts @@ -3,7 +3,6 @@ import { ObservabilityReportProperties, ObservabilityRequest, ObservabilityResponse, - PromptExecutionType, Provider, } from "@pezzo/types"; import { GraphQLError } from "graphql-request/build/esm/types"; @@ -19,10 +18,8 @@ export interface GraphQLErrorResponse { export interface ReportRequestResponse< TProviderType extends Provider | unknown = unknown > { - provider: Provider; - type: PromptExecutionType; properties?: ObservabilityReportProperties; - metadata?: ObservabilityReportMetadata; + metadata: ObservabilityReportMetadata; request: ObservabilityRequest; response: ObservabilityResponse; reportId: string; diff --git a/apps/console/src/app/pages/requests/RequestsPage.tsx b/apps/console/src/app/pages/requests/RequestsPage.tsx index 6d661b12..ecd3161e 100644 --- a/apps/console/src/app/pages/requests/RequestsPage.tsx +++ b/apps/console/src/app/pages/requests/RequestsPage.tsx @@ -113,7 +113,7 @@ export const RequestsPage = () => { id={currentReportId} request={currentReport.request} response={currentReport.response} - provider={currentReport.provider} + provider={currentReport.metadata.provider} calculated={currentReport.calculated} metadata={currentReport.metadata} properties={currentReport.properties} diff --git a/apps/server/src/app/opensearch/create-indexes.ts b/apps/server/src/app/opensearch/create-indexes.ts index 918ba3fe..8a065a38 100644 --- a/apps/server/src/app/opensearch/create-indexes.ts +++ b/apps/server/src/app/opensearch/create-indexes.ts @@ -74,12 +74,6 @@ export async function createRequestsIndex( }, }, }, - provider: { - type: "keyword", - }, - type: { - type: "keyword", - }, properties: { type: "object", }, @@ -91,7 +85,10 @@ export async function createRequestsIndex( promptVersionSha: { type: "keyword", }, - conversationId: { + provider: { + type: "keyword", + }, + type: { type: "keyword", }, }, diff --git a/apps/server/src/app/opensearch/types.ts b/apps/server/src/app/opensearch/types.ts index 82fddb81..3bf2e08a 100644 --- a/apps/server/src/app/opensearch/types.ts +++ b/apps/server/src/app/opensearch/types.ts @@ -1,3 +1,3 @@ export enum OpenSearchIndex { - Requests = "requests", + Requests = "requests-v1", } diff --git a/apps/server/src/app/reporting/dto/report-request.dto.ts b/apps/server/src/app/reporting/dto/report-request.dto.ts index 1b838a61..a251800e 100644 --- a/apps/server/src/app/reporting/dto/report-request.dto.ts +++ b/apps/server/src/app/reporting/dto/report-request.dto.ts @@ -1,7 +1,6 @@ -import { IsEnum, IsObject, IsOptional } from "class-validator"; +import { IsObject, IsOptional } from "class-validator"; import { Provider, - PromptExecutionType, ObservabilityReportProperties, ObservabilityReportMetadata, ObservabilityRequest, @@ -11,19 +10,13 @@ import { export class ReportRequestDto< TProviderType extends Provider | unknown = unknown > { - @IsEnum(Provider) - provider: Provider; - - @IsEnum(PromptExecutionType) - type: PromptExecutionType; - @IsObject() @IsOptional() properties?: ObservabilityReportProperties; @IsObject() @IsOptional() - metadata?: ObservabilityReportMetadata; + metadata: ObservabilityReportMetadata; @IsObject() request: ObservabilityRequest; diff --git a/apps/server/src/app/reporting/object-types/request-report.model.ts b/apps/server/src/app/reporting/object-types/request-report.model.ts index f3dacf8b..5cc26205 100644 --- a/apps/server/src/app/reporting/object-types/request-report.model.ts +++ b/apps/server/src/app/reporting/object-types/request-report.model.ts @@ -10,12 +10,6 @@ export class RequestReport { @Field(() => GraphQLJSONObject, { nullable: true }) calculated!: Record; - @Field(() => String, { nullable: false }) - provider!: string; - - @Field(() => String, { nullable: false }) - type!: string; - @Field(() => GraphQLJSONObject, { nullable: true }) properties!: Record; diff --git a/apps/server/src/app/reporting/reporting.service.ts b/apps/server/src/app/reporting/reporting.service.ts index f5fbcd1d..6759b23a 100644 --- a/apps/server/src/app/reporting/reporting.service.ts +++ b/apps/server/src/app/reporting/reporting.service.ts @@ -24,16 +24,15 @@ export class ReportingService { const reportId = randomUUID(); const { report, calculated } = buildRequestReport(dto); - const { provider, type, properties, metadata, request, response } = report; + const { properties, metadata, request, response } = report; return this.openSearchService.client.index({ index: OpenSearchIndex.Requests, body: { + timestamp: request.timestamp, ownership, reportId, calculated, - provider, - type, properties, metadata, request, diff --git a/apps/server/src/app/reporting/utils/build-request-report.ts b/apps/server/src/app/reporting/utils/build-request-report.ts index 0d5830ea..9b9cbe69 100644 --- a/apps/server/src/app/reporting/utils/build-request-report.ts +++ b/apps/server/src/app/reporting/utils/build-request-report.ts @@ -6,7 +6,7 @@ export const buildRequestReport = (dto: ReportRequestDto) => { const requestTimestamp = new Date(dto.request.timestamp); const responseTimestamp = new Date(dto.response.timestamp); const duration = responseTimestamp.getTime() - requestTimestamp.getTime(); - switch (dto.provider) { + switch (dto.metadata.provider) { case Provider.OpenAI: return buildOpenAIReport(dto, duration); default: diff --git a/libs/client/src/client/PezzoOpenAI.ts b/libs/client/src/client/PezzoOpenAI.ts index e29afab4..2e203e6a 100644 --- a/libs/client/src/client/PezzoOpenAI.ts +++ b/libs/client/src/client/PezzoOpenAI.ts @@ -3,7 +3,11 @@ import { CreateChatCompletionRequest as OriginalCreateChatCompletionRequest, OpenAIApi, } from "openai"; -import { InjectPezzoProps, ReportData } from "../types"; +import { + InjectPezzoProps, + ObservabilityReportMetadata, + ReportData, +} from "../types"; import { Pezzo } from "./Pezzo"; import { PromptExecutionType, Provider } from "@pezzo/types"; import { merge } from "../utils/helpers"; @@ -71,15 +75,15 @@ export class PezzoOpenAIApi extends OpenAIApi { let error; let reportPayload: ReportData; - const baseMetadata = { + const baseMetadata: Partial = { environment: this.pezzo.options.environment, + provider: Provider.OpenAI, + type: PromptExecutionType.ChatCompletion, }; const requestTimestamp = new Date().toISOString(); const baseReport = { - provider: Provider.OpenAI, - type: PromptExecutionType.ChatCompletion, metadata: merge(baseMetadata, pezzoPrompt?.metadata), // TODO: merge pezzo metadata properties: pezzoOptions?.properties, request: { diff --git a/libs/client/src/types/observability.ts b/libs/client/src/types/observability.ts index 68247350..94599d85 100644 --- a/libs/client/src/types/observability.ts +++ b/libs/client/src/types/observability.ts @@ -2,14 +2,13 @@ import { ValueType, PromptExecutionType, ProviderType } from "../types"; export type ObservabilityReportProperties = Record; export type ObservabilityReportMetadata = { - conversationId?: string; + provider: ProviderType; + type: PromptExecutionType; [key: string]: ValueType; }; export interface ReportData { - provider: ProviderType; - type: PromptExecutionType; - metadata?: ObservabilityReportMetadata; + metadata: ObservabilityReportMetadata; properties?: ObservabilityReportProperties; request: { timestamp: string; diff --git a/libs/types/src/request.ts b/libs/types/src/request.ts index 63453de2..a2681380 100644 --- a/libs/types/src/request.ts +++ b/libs/types/src/request.ts @@ -9,6 +9,7 @@ import { CreateChatCompletionRequest, ChatCompletionRequestMessage, } from "openai"; +import { PromptExecutionType } from "./prompt-execution-type"; type ExtractModelNames = T extends { model: infer M } ? M : never; export type AcceptedModels = ExtractModelNames< @@ -17,7 +18,8 @@ export type AcceptedModels = ExtractModelNames< export type ObservabilityReportProperties = RecursiveObject; export type ObservabilityReportMetadata = { - conversationId: string; + provider: Provider; + type: PromptExecutionType; [key: string]: AllPrimitiveTypes; }; From c93f568552f8720469a4eaba52ce6ebb5c178aaf Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Sat, 29 Jul 2023 15:55:24 +0200 Subject: [PATCH 10/10] remove comments in launch.json --- .vscode/launch.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 1a645358..75bc4511 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,7 +1,4 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { @@ -10,7 +7,6 @@ "request": "attach", "skipFiles": ["/**"], "type": "node", - // magic line to fix Unbound breakpoints: "cwd": "${workspaceFolder}/examples/task-generator-app" } ]