From 819474697d04bde8bfa58267c6add9dc978baf07 Mon Sep 17 00:00:00 2001 From: flxkm522 Date: Mon, 12 Oct 2026 17:51:00 +0900 Subject: [PATCH 1/2] feat(engine): consolidate the engine PRs into one, reviewed and refactored Squash of the redrob-code ENGINE work that was spread across seven open PRs into a single change on develop. The Electron/desktop app and the build-off/Quality-Lab stack move to the alpha/desktop branch separately and are not part of this. Rolled up: - #67 insights route + /v1/chat/completions (serve the OpenAI face for real, forward x-redrob-session to the Console). - #68 regenerate the JS SDK that had fallen behind the routes. - #69-#74 the media tools and endpoints: image_generate (edit / reference images), speech_generate (mp3), POST /redrob/speech and POST /redrob/transcribe, all on the engine own Redrob credential. - #79 the shared on-device labellers (route-labeller, work-labeller) as source workspace packages, consumed downstream by Cowork/Office/Design. Integration fix found by combining the PRs: - packages/server/src/routes.ts: the chat-completion handler reads LLMClient inside the request, so it was a per-request requirement of the embedded API that Layer.provide(serviceLayer) did not discharge, leaking as a residual requirement and flipping the web.handler signature so the untouched sdk-next caller stopped type-checking. LLMClient is a global service, so it is now provided once via HttpRouter.provideRequest inside makeRoutes. Review + lean/documentation pass (behaviour-preserving): - image_generate / speech_generate: size-limit messages derive from their constants instead of hand-kept 10 MB / 50 MB literals (drift-proof). - speech_generate: characters() uses [...text].length (idiomatic code-point count). - core/insights.ts: tightened the ErrorEnvelope describe() union guard (identical runtime behaviour). - plugin/host.ts: removed a misleading comment on skill.list; it matches the uniform mutable() pattern now. - docs/LOCAL-ENGINE-API.md: documented the shipped /redrob/speech and /redrob/transcribe endpoints (sections 1c, 1d). Verified: bun turbo typecheck 20/20; bun install --frozen-lockfile clean; engine tool/server tests 42/42; core 6/6; work-labeller 77/77. --- .github/workflows/publish-labellers.yml | 120 ++++ .github/workflows/test.yml | 41 +- bun.lock | 245 ++++++- docs/LOCAL-ENGINE-API.md | 45 ++ .../client/src/generated-effect/client.ts | 542 +++++++------- packages/client/src/generated/client.ts | 16 + packages/client/src/generated/types.ts | 10 + packages/core/src/insights.ts | 92 +++ packages/core/src/plugin/host.ts | 2 +- packages/core/src/plugin/skill.ts | 16 +- packages/core/test/config/skill.test.ts | 7 +- packages/core/test/insights.test.ts | 107 +++ packages/core/test/plugin/skill.test.ts | 9 +- packages/protocol/src/api.ts | 2 + packages/protocol/src/groups/insights.ts | 36 + packages/redrob/src/redrob/transcription.ts | 163 +++++ .../routes/instance/httpapi/groups/control.ts | 58 +- .../instance/httpapi/handlers/control.ts | 46 +- .../server/routes/instance/httpapi/server.ts | 5 +- packages/redrob/src/tool/image_generate.ts | 272 +++++++ packages/redrob/src/tool/image_generate.txt | 10 + packages/redrob/src/tool/registry.ts | 23 +- packages/redrob/src/tool/speech_generate.ts | 219 ++++++ packages/redrob/src/tool/speech_generate.txt | 10 + .../chat-completion-session-header.test.ts | 26 + .../test/server/httpapi-exercise/index.ts | 75 ++ .../redrob/test/server/httpapi-speech.test.ts | 184 +++++ .../test/server/httpapi-transcribe.test.ts | 200 ++++++ .../redrob/test/tool/image_generate.test.ts | 271 +++++++ packages/redrob/test/tool/registry.test.ts | 33 + .../redrob/test/tool/speech_generate.test.ts | 193 +++++ packages/route-labeller/.gitignore | 2 + packages/route-labeller/NOTICE.md | 7 + packages/route-labeller/README.md | 50 ++ packages/route-labeller/eval/held-out.json | 662 ++++++++++++++++++ packages/route-labeller/package.json | 84 +++ .../scripts/build-prototypes.ts | 55 ++ packages/route-labeller/scripts/evaluate.ts | 43 ++ .../route-labeller/scripts/prepare-model.ts | 18 + packages/route-labeller/src/encoder.ts | 145 ++++ packages/route-labeller/src/guide.ts | 276 ++++++++ packages/route-labeller/src/index.ts | 24 + packages/route-labeller/src/labeller.ts | 116 +++ packages/route-labeller/src/lexical.ts | 88 +++ packages/route-labeller/src/lexicon.json | 632 +++++++++++++++++ packages/route-labeller/src/manifest.json | 22 + packages/route-labeller/src/node.ts | 113 +++ packages/route-labeller/src/prototypes.json | 1 + packages/route-labeller/src/types.ts | 71 ++ packages/route-labeller/src/wordpiece.ts | 169 +++++ packages/route-labeller/tsconfig.json | 21 + packages/route-labeller/tsup.config.ts | 15 + packages/schema/src/insights.ts | 44 ++ packages/sdk/js/src/v2/gen/sdk.gen.ts | 169 +++++ packages/sdk/js/src/v2/gen/types.gen.ts | 396 +++++++++++ packages/server/src/handlers.ts | 2 + .../server/src/handlers/chat-completion.ts | 32 +- packages/server/src/handlers/insights.ts | 61 ++ packages/server/src/routes.ts | 12 +- packages/work-labeller/NOTICE.md | 9 + packages/work-labeller/README.md | 71 ++ .../work-labeller/bench/webview/README.md | 13 + packages/work-labeller/bench/webview/run.mjs | 57 ++ packages/work-labeller/bench/webview/spike.ts | 51 ++ packages/work-labeller/model/eval/review.md | 27 + .../model/eval/work-samples.test.ts | 51 ++ .../work-labeller/model/eval/work-samples.ts | 456 ++++++++++++ .../work-labeller/model/prototypes.test.ts | 25 + packages/work-labeller/model/prototypes.ts | 169 +++++ .../work-labeller/model/scripts/evaluate.py | 266 +++++++ .../work-labeller/model/scripts/export.ts | 8 + .../model/scripts/requirements.txt | 4 + packages/work-labeller/model/scripts/train.py | 184 +++++ .../work-labeller/model/train/contrast.ts | 217 ++++++ packages/work-labeller/model/train/index.ts | 146 ++++ .../model/train/sheet-code-design.ts | 470 +++++++++++++ .../work-labeller/model/train/train.test.ts | 50 ++ packages/work-labeller/model/train/tuning.ts | 269 +++++++ packages/work-labeller/model/train/types.ts | 2 + packages/work-labeller/model/train/write-a.ts | 338 +++++++++ packages/work-labeller/model/train/write-b.ts | 272 +++++++ packages/work-labeller/package.json | 73 ++ packages/work-labeller/src/classifier.ts | 159 +++++ packages/work-labeller/src/download.ts | 205 ++++++ packages/work-labeller/src/facts.ts | 77 ++ packages/work-labeller/src/index.ts | 28 + packages/work-labeller/src/labeler.ts | 169 +++++ packages/work-labeller/src/manifest.json | 15 + packages/work-labeller/src/node.ts | 116 +++ packages/work-labeller/src/recorder.ts | 242 +++++++ packages/work-labeller/src/sha256.ts | 49 ++ packages/work-labeller/src/sync.ts | 65 ++ packages/work-labeller/src/unigram.ts | 214 ++++++ packages/work-labeller/src/vocabulary.ts | 41 ++ packages/work-labeller/src/work-head.json | 1 + .../work-labeller/test/classifier.test.ts | 174 +++++ packages/work-labeller/test/download.test.ts | 141 ++++ .../test/fixtures/unigram-parity.json | 10 + packages/work-labeller/test/labels.test.ts | 34 + packages/work-labeller/test/unigram.test.ts | 25 + packages/work-labeller/tsconfig.json | 21 + packages/work-labeller/tsup.config.ts | 15 + 102 files changed, 11134 insertions(+), 303 deletions(-) create mode 100644 .github/workflows/publish-labellers.yml create mode 100644 packages/core/src/insights.ts create mode 100644 packages/core/test/insights.test.ts create mode 100644 packages/protocol/src/groups/insights.ts create mode 100644 packages/redrob/src/redrob/transcription.ts create mode 100644 packages/redrob/src/tool/image_generate.ts create mode 100644 packages/redrob/src/tool/image_generate.txt create mode 100644 packages/redrob/src/tool/speech_generate.ts create mode 100644 packages/redrob/src/tool/speech_generate.txt create mode 100644 packages/redrob/test/server/chat-completion-session-header.test.ts create mode 100644 packages/redrob/test/server/httpapi-speech.test.ts create mode 100644 packages/redrob/test/server/httpapi-transcribe.test.ts create mode 100644 packages/redrob/test/tool/image_generate.test.ts create mode 100644 packages/redrob/test/tool/speech_generate.test.ts create mode 100644 packages/route-labeller/.gitignore create mode 100644 packages/route-labeller/NOTICE.md create mode 100644 packages/route-labeller/README.md create mode 100644 packages/route-labeller/eval/held-out.json create mode 100644 packages/route-labeller/package.json create mode 100644 packages/route-labeller/scripts/build-prototypes.ts create mode 100644 packages/route-labeller/scripts/evaluate.ts create mode 100644 packages/route-labeller/scripts/prepare-model.ts create mode 100644 packages/route-labeller/src/encoder.ts create mode 100644 packages/route-labeller/src/guide.ts create mode 100644 packages/route-labeller/src/index.ts create mode 100644 packages/route-labeller/src/labeller.ts create mode 100644 packages/route-labeller/src/lexical.ts create mode 100644 packages/route-labeller/src/lexicon.json create mode 100644 packages/route-labeller/src/manifest.json create mode 100644 packages/route-labeller/src/node.ts create mode 100644 packages/route-labeller/src/prototypes.json create mode 100644 packages/route-labeller/src/types.ts create mode 100644 packages/route-labeller/src/wordpiece.ts create mode 100644 packages/route-labeller/tsconfig.json create mode 100644 packages/route-labeller/tsup.config.ts create mode 100644 packages/schema/src/insights.ts create mode 100644 packages/server/src/handlers/insights.ts create mode 100644 packages/work-labeller/NOTICE.md create mode 100644 packages/work-labeller/README.md create mode 100644 packages/work-labeller/bench/webview/README.md create mode 100644 packages/work-labeller/bench/webview/run.mjs create mode 100644 packages/work-labeller/bench/webview/spike.ts create mode 100644 packages/work-labeller/model/eval/review.md create mode 100644 packages/work-labeller/model/eval/work-samples.test.ts create mode 100644 packages/work-labeller/model/eval/work-samples.ts create mode 100644 packages/work-labeller/model/prototypes.test.ts create mode 100644 packages/work-labeller/model/prototypes.ts create mode 100644 packages/work-labeller/model/scripts/evaluate.py create mode 100644 packages/work-labeller/model/scripts/export.ts create mode 100644 packages/work-labeller/model/scripts/requirements.txt create mode 100644 packages/work-labeller/model/scripts/train.py create mode 100644 packages/work-labeller/model/train/contrast.ts create mode 100644 packages/work-labeller/model/train/index.ts create mode 100644 packages/work-labeller/model/train/sheet-code-design.ts create mode 100644 packages/work-labeller/model/train/train.test.ts create mode 100644 packages/work-labeller/model/train/tuning.ts create mode 100644 packages/work-labeller/model/train/types.ts create mode 100644 packages/work-labeller/model/train/write-a.ts create mode 100644 packages/work-labeller/model/train/write-b.ts create mode 100644 packages/work-labeller/package.json create mode 100644 packages/work-labeller/src/classifier.ts create mode 100644 packages/work-labeller/src/download.ts create mode 100644 packages/work-labeller/src/facts.ts create mode 100644 packages/work-labeller/src/index.ts create mode 100644 packages/work-labeller/src/labeler.ts create mode 100644 packages/work-labeller/src/manifest.json create mode 100644 packages/work-labeller/src/node.ts create mode 100644 packages/work-labeller/src/recorder.ts create mode 100644 packages/work-labeller/src/sha256.ts create mode 100644 packages/work-labeller/src/sync.ts create mode 100644 packages/work-labeller/src/unigram.ts create mode 100644 packages/work-labeller/src/vocabulary.ts create mode 100644 packages/work-labeller/src/work-head.json create mode 100644 packages/work-labeller/test/classifier.test.ts create mode 100644 packages/work-labeller/test/download.test.ts create mode 100644 packages/work-labeller/test/fixtures/unigram-parity.json create mode 100644 packages/work-labeller/test/labels.test.ts create mode 100644 packages/work-labeller/test/unigram.test.ts create mode 100644 packages/work-labeller/tsconfig.json create mode 100644 packages/work-labeller/tsup.config.ts diff --git a/.github/workflows/publish-labellers.yml b/.github/workflows/publish-labellers.yml new file mode 100644 index 0000000000..dd401ab676 --- /dev/null +++ b/.github/workflows/publish-labellers.yml @@ -0,0 +1,120 @@ +# Publish the shared on-device labellers (`@redrob-labs/route-labeller`, `@redrob-labs/work-labeller`) +# to npm from redrob-code, which is their single source of truth. Cowork, Office and Design consume +# them downstream. +# +# Modelled on publish-sdk.yml and DELIBERATELY SEPARATE from release.yml for the same reason: that +# workflow reaches the Apple and Windows signing credentials, and an npm-token problem must not turn +# a signed binary release red. +# +# `workflow_dispatch` only, and dry-run by DEFAULT, because the first publish of a public package +# under this scope is not reversible: npm allows unpublishing a new version only within 72 hours, and +# a name, once taken, stays taken. Pick which package to publish with the `package` input. +# +# Unlike the SDK, these packages carry an intrinsic `version` in their own package.json (not tied to +# a CLI release), so there is no version injection: `publishConfig.exports` already swaps `src` for +# `dist` at pack time, and `prepublishOnly` builds `dist`. Bump the package's `version` in a normal +# PR before dispatching this. +# +# NPM_TOKEN MUST BE 2FA-EXEMPT (a classic AUTOMATION token, or a granular token with Read and write +# on the scope). npm enforces two-factor on publish and an interactive OTP cannot be supplied by CI; +# this is the same constraint documented at length in publish-sdk.yml. +name: publish-labellers + +on: + workflow_dispatch: + inputs: + package: + description: "Which labeller to publish." + required: true + type: choice + options: + - "@redrob-labs/route-labeller" + - "@redrob-labs/work-labeller" + dry_run: + description: "Build and pack, but publish nothing." + required: false + default: true + type: boolean + +concurrency: + group: publish-labellers-${{ github.event.inputs.package }} + cancel-in-progress: false + +permissions: + contents: read + +jobs: + publish: + runs-on: ubuntu-latest + # Pinned to this repository's immutable id, matching release.yml and publish-sdk.yml: a fork must + # never publish under this scope, and a rename must not silently switch the guard off. + if: github.repository_id == '1371675259' + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + ref: develop + fetch-depth: 0 + + - uses: ./.github/actions/setup-bun + + - id: resolve + env: + PACKAGE: ${{ inputs.package }} + run: | + set -euo pipefail + case "$PACKAGE" in + "@redrob-labs/route-labeller") dir="packages/route-labeller" ;; + "@redrob-labs/work-labeller") dir="packages/work-labeller" ;; + *) echo "::error::unknown package $PACKAGE"; exit 1 ;; + esac + version="$(cd "$dir" && node -p "require('./package.json').version")" + if [ "$version" = "0.0.0" ]; then + echo "::error::$PACKAGE is still at 0.0.0 — bump its package.json version in a PR before publishing" + exit 1 + fi + echo "dir=$dir" >> "$GITHUB_OUTPUT" + echo "version=$version" >> "$GITHUB_OUTPUT" + echo "publishing $PACKAGE@$version from $dir" >> "$GITHUB_STEP_SUMMARY" + + - name: Build + working-directory: ${{ steps.resolve.outputs.dir }} + run: bun run build + + # Checks the token AUTHENTICATES, not merely that it is non-empty — see publish-sdk.yml for why + # a green emptiness check is worse than none. `whoami` cannot prove the token is 2FA-exempt; only + # the publish itself discovers EOTP. + - name: Check the npm token authenticates + if: ${{ !inputs.dry_run }} + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: | + set -euo pipefail + if [ -z "${NPM_TOKEN:-}" ]; then + echo "::error::NPM_TOKEN is not set for this repository or its organization" + exit 1 + fi + echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc + if ! who="$(npm whoami 2>&1)"; then + echo "::error::NPM_TOKEN did not authenticate: $who" + exit 1 + fi + echo "authenticated as $who (2FA exemption is only provable by the publish itself)" + + - name: Publish + working-directory: ${{ steps.resolve.outputs.dir }} + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + DRY_RUN: ${{ inputs.dry_run }} + run: | + set -euo pipefail + if [ -n "${NPM_TOKEN:-}" ]; then + echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc + fi + if [ "$DRY_RUN" = "true" ]; then + echo "dry run — packing only, publishing nothing" + bun pm pack + ls -la ./*.tgz + else + bun publish --access public + fi diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 47e2550435..f506b25edf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -157,9 +157,42 @@ jobs: working-directory: packages/redrob run: bun run test:httpapi + labellers: + name: labellers (linux) + runs-on: ubuntu-latest + timeout-minutes: 20 + defaults: + run: + shell: bash + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + + - name: Setup Node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "24" + + - name: Setup Bun + uses: ./.github/actions/setup-bun + + - name: Configure git identity + run: | + git config --global user.email "bot@code.redrob.ai" + git config --global user.name "redrob" + + # The shared on-device labellers (route-labeller, work-labeller) live here as source + # and are consumed by Cowork, Office and Design downstream, so their suites gate here. + # Tests resolve the package `src` via the `development` export condition. route-labeller + # ships no unit suite (its checks are the `eval` + prototype scripts); work-labeller + # carries the 77-test classifier/tokeniser/dataset suite under test/ and model/. + - name: Run work-labeller tests + working-directory: packages/work-labeller + run: bun --conditions=development test test model + unit: name: unit (linux) - needs: [engine, core, httpapi] + needs: [engine, core, httpapi, labellers] # `always()` so a failing dependency still reports here rather than leaving the required # check permanently "expected" — a skipped required check never resolves and blocks the # pull request with no visible failure to fix. @@ -169,11 +202,11 @@ jobs: - name: Report run: | set -euo pipefail - printf 'engine %s\ncore %s\nhttpapi %s\n' \ - "${{ needs.engine.result }}" "${{ needs.core.result }}" "${{ needs.httpapi.result }}" + printf 'engine %s\ncore %s\nhttpapi %s\nlabellers %s\n' \ + "${{ needs.engine.result }}" "${{ needs.core.result }}" "${{ needs.httpapi.result }}" "${{ needs.labellers.result }}" # A matrix dependency reports one aggregated result, so a single red shard makes # `needs.engine.result` a failure. - for result in "${{ needs.engine.result }}" "${{ needs.core.result }}" "${{ needs.httpapi.result }}"; do + for result in "${{ needs.engine.result }}" "${{ needs.core.result }}" "${{ needs.httpapi.result }}" "${{ needs.labellers.result }}"; do if [ "$result" != "success" ]; then echo "::error::a linux test job did not succeed" exit 1 diff --git a/bun.lock b/bun.lock index 94ec851482..ade0a3eb68 100644 --- a/bun.lock +++ b/bun.lock @@ -435,6 +435,25 @@ "why-is-node-running": "3.2.2", }, }, + "packages/route-labeller": { + "name": "@redrob-labs/route-labeller", + "version": "0.0.0", + "devDependencies": { + "@types/node": "catalog:", + "@typescript/native-preview": "catalog:", + "onnxruntime-node": "1.23.0", + "tsup": "^8.5.0", + "typescript": "catalog:", + }, + "peerDependencies": { + "onnxruntime-node": ">=1.20.0", + "onnxruntime-web": ">=1.20.0", + }, + "optionalPeers": [ + "onnxruntime-node", + "onnxruntime-web", + ], + }, "packages/schema": { "name": "@redrob-code/schema", "dependencies": { @@ -539,6 +558,28 @@ "@typescript/native-preview": "catalog:", }, }, + "packages/work-labeller": { + "name": "@redrob-labs/work-labeller", + "version": "0.0.0", + "dependencies": { + "zod": "catalog:", + }, + "devDependencies": { + "@types/node": "catalog:", + "@typescript/native-preview": "catalog:", + "onnxruntime-node": "1.23.0", + "tsup": "^8.5.0", + "typescript": "catalog:", + }, + "peerDependencies": { + "onnxruntime-node": ">=1.20.0", + "onnxruntime-web": ">=1.20.0", + }, + "optionalPeers": [ + "onnxruntime-node", + "onnxruntime-web", + ], + }, }, "trustedDependencies": [ "esbuild", @@ -1032,6 +1073,8 @@ "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4", "", { "os": "win32", "cpu": "x64" }, "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ=="], + "@napi-rs/lzma-linux-x64-gnu": ["@napi-rs/lzma-linux-x64-gnu@1.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ=="], + "@nodable/entities": ["@nodable/entities@3.0.0", "", {}, "sha512-8L9xFeTYKhm49xfIypoe2W5wV1m/3Z58kT+7kR9A8OyFxcPduI4VmxaUMQyKYrRjUoLLSXv6EKKID5Tvj9cUVw=="], "@npm/types": ["@npm/types@1.0.2", "", {}, "sha512-KXZccTDEnWqNrrx6JjpJKU/wJvNeg9BDgjS0XhmlZab7br921HtyVbsYzJr4L+xIvjdJ20Wh9dgxgCI2a5CEQw=="], @@ -1312,8 +1355,62 @@ "@redrob-code/tui": ["@redrob-code/tui@workspace:packages/tui"], + "@redrob-labs/route-labeller": ["@redrob-labs/route-labeller@workspace:packages/route-labeller"], + "@redrob-labs/sdk": ["@redrob-labs/sdk@workspace:packages/sdk/js"], + "@redrob-labs/work-labeller": ["@redrob-labs/work-labeller@workspace:packages/work-labeller"], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.64.0", "", { "os": "android", "cpu": "arm" }, "sha512-FLLpX941CD/7aBvX3GqLGBM9OvY5PGXTryPJkG5r5/OuBpZpV5k45Uo3RxAvqd35tsyc3hH1bhtz921IKzoIzg=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.64.0", "", { "os": "android", "cpu": "arm64" }, "sha512-iI32XM/jnDYJsvx5ai/za/7gWO9XoSeFFtU06/ZCaRgyilfJOjaopD3nOpk2WrTCGOyeDt4hleUiGOAnd5tHNg=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.64.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-dRBZlbt2sEtF8Mn4MODThze9fIPdDoOhVSlXMAKy5dQbOYK9pOOoPY4Fat3OTtr0+8zbJo5TTZwlsfxY/kDNJg=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.64.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Y3whrJOMucfkhgNkvcM93M6j8C53iEAMmPMYD99C6G1kUy4ELigLWk9ar2/4aCBSRgsql0zdlOemLgW2m5GZgQ=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.64.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-S6S1GEzPjFF6IONYJX3AKt/799+8RgBgCcwRnUo+Ep1IvBxUbw5M51iU0TDdK2NWWVnSvCQ8yi6Em0fGASMOng=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.64.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Ed1DPoFENkXj4IGzSB12SesV40iP6LxCCrbTIkSGIQBpOOxpBM+0kj62lmaeIHfMWTDoddqTOtqc7s8LYfn+Pw=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.64.0", "", { "os": "linux", "cpu": "arm" }, "sha512-J/6xhutJPtFyIkmHdf4olOdHHKH5kOJNumojdWn+Elv5ICEYTVOa362Vw27TxsK0BLzb1le3EDlO3UbvFK1lnQ=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.64.0", "", { "os": "linux", "cpu": "arm" }, "sha512-G4L/Nnx59d2LvDoV/P4S5lZ7oVLT6hodOHMacqjiq2LL2gts86KbkEBTYL53+fBt0odhf7XPIbIATGoYiJctxg=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.64.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-zF16pvJDEUksGYRbfnXne7pdklAyj2XDmJeYKgP93oq0cUyX9Y8O7lUo1R+IY1GagP/YBvCEDCe7eEcAKpw//g=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.64.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-nIggWn8n+w12+R5lsV+PYYoUY8vuObxPAQqJI7WES+9v0qspYuAHoZMfYM0yLxlipasT5BY9ht5W8t5c/rSCkg=="], + + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.64.0", "", { "os": "linux", "cpu": "none" }, "sha512-WLOTiHPzszP0dxIMsHpFeDSOSB5I49Mj8K4+yKE3H1X/D0JRG5XZ5jrctJLMjnUc/LUzaKiwq6EHWNJ8pup8PA=="], + + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.64.0", "", { "os": "linux", "cpu": "none" }, "sha512-35RK9aRhh7g7Pmeu5gQ01aCvrhXzj9LoBE6xtUcEH1ns+nyTaSzxSpADmBQINu4QiTDGvmQYwo1j5hlg1rRXFw=="], + + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.64.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-RqTfnpoTjuWfPAmqK5p2edt2AMCDJWm6oTn7sKfmyx+6tRga0ip05SJ977o6udTcIiDeF/CJMUfkaN4gtWt6Aw=="], + + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.64.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-RQjZPigjxFvFZDijG6rjlSXxhRaTf9zLYVpGK+lVcga64oMqP1GbgVqCb46eHTTceSIgp89Ja0y5aPe3GFBYHg=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.64.0", "", { "os": "linux", "cpu": "none" }, "sha512-tjL58mgQcTRnDRpeky+Sth1MKQeYi2Ct6r3Luq9E5aTSjnM/i/JbozqZkKqp9thM5+oDSZxo+05f9kdQedfTGA=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.64.0", "", { "os": "linux", "cpu": "none" }, "sha512-ictoRyVaoZ8C67myHef+8hhCa6IplXJJ/xUCkVCxziV4zxMZh+jvhkhGsPBLqj1S72fnqD0QH5zL4lcaa4X7DQ=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.64.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-8aVvZ2hfr9RLFzBQkQNmYeHLDja8fLeQAmLt757zdKN/B+8L809KlLJKctQjS22wZotptV8G6o7fVPuAs8S1tQ=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.64.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2dEF8GAcDKwshUfydD+GhosppNyBzhVUHkdFF3CXd3FpOkzj/RZzF5aoEtzklujklT5qFVRU2GK/cFeLaTNKVg=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.64.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3XHTvoo2hKkh0MiOfS7SkhHjMaaWF7P4F3drocZZaho/Z8w7h/jpnuBHm91BOQLfvrKHs1yR+zir4E8RI3XzTQ=="], + + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.64.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HKtkzodL4a3KFWDXDoO61cRynAWTR3LnAE0oGtfG9lcNFpNuVYUFOByxDgNqEvic9rvaQbAj+SFwTEWDptRaIw=="], + + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.64.0", "", { "os": "none", "cpu": "arm64" }, "sha512-JBsxqiY16uyyCujtoC3s7zL+SrYyNElptD7K4V+KUoJ2V8/XG3hPWpheK+SuPwNh1cikJvIZmIdsrYXvD6PLJw=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.64.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-S5Qrijh37qhnUYQ0ay8WN3LuWeKjow7wTUyCOPMZtnXiBXYXdsZETI6ZLfYnQAKovltckPLBFdNeD61P2rJc7g=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.64.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-zbZ6iMmLFEsCtTdc2/y1F/cDFVNNCPF7Ae8PCT/wdPE//hGwYp6r+MyCLMFX+kOeIe09Pz6ASfnnfpSTN1FJQQ=="], + + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.64.0", "", { "os": "win32", "cpu": "x64" }, "sha512-L6Hw69oNpuYaOr1zCG30v0/DqKYCSRwodPGwIcVZ/6f8SOzq9rxtL/xNVI5MO4wjli+Ko0ErK9uHJL3mNPt8wQ=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.64.0", "", { "os": "win32", "cpu": "x64" }, "sha512-nl+CTWIgOGszQmUz/kanfgrfFZ4qiwxKIfT/ryl3N3Ewk5tqizmYtNXiqb7Bu/fDtNgu1kyxdFiAUJNur3iysg=="], + "@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="], "@shikijs/engine-javascript": ["@shikijs/engine-javascript@4.2.0", "", { "dependencies": { "@shikijs/types": "4.2.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.6" } }, "sha512-fjETeq1k5ffyXqRgS6+3hpvqseLalp1kjNfRbXpUgWR8FpZ1CmQfiNHovc5lncYjt/Vg5JK/WJEmLahjwMa0og=="], @@ -1490,6 +1587,8 @@ "@types/cross-spawn": ["@types/cross-spawn@6.0.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA=="], + "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], + "@types/express": ["@types/express@4.17.25", "", { "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "^1" } }, "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw=="], "@types/express-serve-static-core": ["@types/express-serve-static-core@4.19.9", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg=="], @@ -1592,6 +1691,8 @@ "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "adm-zip": ["adm-zip@0.5.18", "", {}, "sha512-ufJnssQGbxzLNS1Ho9bCtX4rQKCCvoVuDLHoJyc3F9dOGDB4BkWs2Ci0kv53lqocAEQ/Cbi+I2XCsNYGqVYqng=="], + "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], "ai": ["ai@6.0.168", "", { "dependencies": { "@ai-sdk/gateway": "3.0.104", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-2HqCJuO+1V2aV7vfYs5LFEUfxbkGX+5oa54q/gCCTL7KLTdbxcCu5D7TdLA5kwsrs3Szgjah9q6D9tpjHM3hUQ=="], @@ -1608,6 +1709,8 @@ "ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], + "anynum": ["anynum@1.0.1", "", {}, "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A=="], "archiver": ["archiver@7.0.1", "", { "dependencies": { "archiver-utils": "^5.0.2", "async": "^3.2.4", "buffer-crc32": "^1.0.0", "readable-stream": "^4.0.0", "readdir-glob": "^1.1.2", "tar-stream": "^3.0.0", "zip-stream": "^6.0.1" } }, "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ=="], @@ -1684,6 +1787,8 @@ "bonjour-service": ["bonjour-service@1.3.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" } }, "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA=="], + "boolean": ["boolean@3.2.0", "", {}, "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw=="], + "bottleneck": ["bottleneck@2.19.5", "", {}, "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="], "bowser": ["bowser@2.14.1", "", {}, "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg=="], @@ -1712,10 +1817,14 @@ "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], + "bundle-require": ["bundle-require@5.1.0", "", { "dependencies": { "load-tsconfig": "^0.2.3" }, "peerDependencies": { "esbuild": ">=0.18" } }, "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA=="], + "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], "c12": ["c12@3.3.3", "", { "dependencies": { "chokidar": "^5.0.0", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^17.2.3", "exsolve": "^1.0.8", "giget": "^2.0.0", "jiti": "^2.6.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "*" }, "optionalPeers": ["magicast"] }, "sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q=="], + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], + "cacache": ["cacache@20.0.4", "", { "dependencies": { "@npmcli/fs": "^5.0.0", "fs-minipass": "^3.0.0", "glob": "^13.0.0", "lru-cache": "^11.1.0", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^7.0.2", "ssri": "^13.0.0" } }, "sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA=="], "call-bind": ["call-bind@1.0.9", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "get-intrinsic": "^1.3.0", "set-function-length": "^1.2.2" } }, "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ=="], @@ -1842,6 +1951,8 @@ "detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], + "detect-node": ["detect-node@2.1.0", "", {}, "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="], + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], @@ -1910,12 +2021,16 @@ "es-to-primitive": ["es-to-primitive@1.3.4", "", { "dependencies": { "es-abstract-get": "^1.0.0", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "is-callable": "^1.2.7", "is-date-object": "^1.1.0", "is-symbol": "^1.1.1" } }, "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw=="], + "es6-error": ["es6-error@4.1.1", "", {}, "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="], + "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], @@ -1992,6 +2107,8 @@ "finity": ["finity@0.5.4", "", {}, "sha512-3l+5/1tuw616Lgb0QBimxfdd2TqaDGpfCBpfX6EqtFmqUV3FtQnVEX4Aa62DagYEqnsTIjZcTfbq9msDbXYgyA=="], + "fix-dts-default-cjs-exports": ["fix-dts-default-cjs-exports@1.0.1", "", { "dependencies": { "magic-string": "^0.30.17", "mlly": "^1.7.4", "rollup": "^4.34.8" } }, "sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg=="], + "follow-redirects": ["follow-redirects@1.16.0", "", {}, "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw=="], "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], @@ -2012,6 +2129,8 @@ "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + "fstream": ["fstream@1.0.12", "", { "dependencies": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", "mkdirp": ">=0.5 0", "rimraf": "2" } }, "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg=="], "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], @@ -2050,6 +2169,8 @@ "glob": ["glob@13.0.5", "", { "dependencies": { "minimatch": "^10.2.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw=="], + "global-agent": ["global-agent@3.0.0", "", { "dependencies": { "boolean": "^3.0.1", "es6-error": "^4.1.1", "matcher": "^3.0.0", "roarr": "^2.15.3", "semver": "^7.3.2", "serialize-error": "^7.0.1" } }, "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q=="], + "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], "google-auth-library": ["google-auth-library@10.5.0", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.0.0", "gcp-metadata": "^8.0.0", "google-logging-utils": "^1.0.0", "gtoken": "^8.0.0", "jws": "^4.0.0" } }, "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w=="], @@ -2232,6 +2353,8 @@ "jose": ["jose@5.2.3", "", {}, "sha512-KUXdbctm1uHVL8BYhnyHkgp3zDX5KW8ZhAKVFEfUbU2P8Alpzjb+48hHvjOdQIyPshoblhzsuqOwEEAbtHVirA=="], + "joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="], + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], "js-yaml": ["js-yaml@3.15.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w=="], @@ -2256,6 +2379,8 @@ "json-stringify-nice": ["json-stringify-nice@1.1.4", "", {}, "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw=="], + "json-stringify-safe": ["json-stringify-safe@5.0.1", "", {}, "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="], + "json-with-bigint": ["json-with-bigint@3.5.12", "", {}, "sha512-uwbF/wSSuOgC7qqlq27Xp5B6a2MHVug3t0idZdTqu0JnlFvgJuH7ju+KAk/J06C7GfhoYy2gnb9wz2INqcne7w=="], "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], @@ -2288,8 +2413,14 @@ "light-my-request": ["light-my-request@6.6.0", "", { "dependencies": { "cookie": "^1.0.1", "process-warning": "^4.0.0", "set-cookie-parser": "^2.6.0" } }, "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A=="], + "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], + + "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + "listenercount": ["listenercount@1.0.1", "", {}, "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ=="], + "load-tsconfig": ["load-tsconfig@0.2.5", "", {}, "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg=="], + "locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], "lodash": ["lodash@4.18.1", "", {}, "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="], @@ -2338,10 +2469,14 @@ "lru_map": ["lru_map@0.4.1", "", {}, "sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg=="], + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + "make-fetch-happen": ["make-fetch-happen@15.0.6", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/agent": "^4.0.0", "@npmcli/redact": "^4.0.0", "cacache": "^20.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", "minipass-fetch": "^5.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^6.0.0", "ssri": "^13.0.0" } }, "sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw=="], "marked": ["marked@17.0.1", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg=="], + "matcher": ["matcher@3.0.0", "", { "dependencies": { "escape-string-regexp": "^4.0.0" } }, "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng=="], + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], "mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="], @@ -2396,6 +2531,8 @@ "mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="], + "mlly": ["mlly@1.8.2", "", { "dependencies": { "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.3" } }, "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA=="], + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], "msgpackr": ["msgpackr@2.0.6", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-plGul/tqjt9vqWFR9zyqyLZls6gb5KTLvnsRO2B9+TZ8tNiXiVI/CR8LiDWlAX4IUeVkQ9gsmzKA6voC2QOciw=="], @@ -2406,6 +2543,8 @@ "multipasta": ["multipasta@0.2.8", "", {}, "sha512-ZPWuMKyv0cSO29f7hozp+k6+crZbQijV8ipMvxNxRf2SwtYGTX1ZX89Kd20VV4H9Znonx+EQn+iy1wGQsJ+b+Q=="], + "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], + "nanoevents": ["nanoevents@7.0.1", "", {}, "sha512-o6lpKiCxLeijK4hgsqfR6CNToPyRU3keKyyI6uwuHRvpRTbZ0wXw51WRgyldVugZqoJfkGFrjrIenYH3bfEO3Q=="], "nanoid": ["nanoid@6.0.1", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-3wVS3i51pE2pi1k5FFL/95BGfVS0kSsvDVuGXHOtxox/TywUmtgq+3qiTOTbs9J7KfHaXPiN171k/A6dBnaXFw=="], @@ -2476,6 +2615,10 @@ "oniguruma-to-es": ["oniguruma-to-es@4.3.6", "", { "dependencies": { "oniguruma-parser": "^0.12.2", "regex": "^6.1.0", "regex-recursion": "^6.0.2" } }, "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA=="], + "onnxruntime-common": ["onnxruntime-common@1.23.0", "", {}, "sha512-Auz8S9D7vpF8ok7fzTobvD1XdQDftRf/S7pHmjeCr3Xdymi4z1C7zx4vnT6nnUjbpelZdGwda0BmWHCCTMKUTg=="], + + "onnxruntime-node": ["onnxruntime-node@1.23.0", "", { "dependencies": { "adm-zip": "^0.5.16", "global-agent": "^3.0.0", "onnxruntime-common": "1.23.0" }, "os": [ "linux", "win32", "darwin", ] }, "sha512-j7QVuR4ouektZjOopKtXcIGsB3C6R9kVbgS10lc2e5SxoWMUhmCwxNl4qBslpWJaPrFxvrQrQaQLQdqku8V19w=="], + "open": ["open@10.1.2", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "is-wsl": "^3.1.0" } }, "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw=="], "openai": ["openai@6.49.0", "", { "peerDependencies": { "@aws-sdk/credential-provider-node": ">=3.972.0 <4", "@smithy/hash-node": ">=4.3.0 <5", "@smithy/signature-v4": ">=5.4.0 <6", "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["@aws-sdk/credential-provider-node", "@smithy/hash-node", "@smithy/signature-v4", "ws", "zod"] }, "sha512-aYCc0C6L864eR6WSYIwQGyXriw/nIyZx0ObvhzOEVuk0zoBDpynjSbrionWI7q65B5H8jJX0DXR9snEzM6bfPg=="], @@ -2554,9 +2697,11 @@ "pino-std-serializers": ["pino-std-serializers@7.1.0", "", {}, "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw=="], + "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="], + "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="], - "pkg-types": ["pkg-types@2.3.1", "", { "dependencies": { "confbox": "^0.2.4", "exsolve": "^1.0.8", "pathe": "^2.0.3" } }, "sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg=="], + "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], "pkg-up": ["pkg-up@3.1.0", "", { "dependencies": { "find-up": "^3.0.0" } }, "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA=="], @@ -2564,6 +2709,8 @@ "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], + "postcss-load-config": ["postcss-load-config@6.0.1", "", { "dependencies": { "lilconfig": "^3.1.1" }, "peerDependencies": { "jiti": ">=1.21.0", "postcss": ">=8.0.9", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["jiti", "postcss", "tsx", "yaml"] }, "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g=="], + "postcss-selector-parser": ["postcss-selector-parser@7.1.5", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw=="], "powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="], @@ -2648,6 +2795,8 @@ "resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="], + "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], + "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], "ret": ["ret@0.5.0", "", {}, "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw=="], @@ -2660,6 +2809,10 @@ "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], + "roarr": ["roarr@2.15.4", "", { "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" } }, "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A=="], + + "rollup": ["rollup@4.64.0", "", { "dependencies": { "@types/estree": "1.0.9" }, "optionalDependencies": { "@napi-rs/lzma-linux-x64-gnu": "1.5.1", "@rollup/rollup-android-arm-eabi": "4.64.0", "@rollup/rollup-android-arm64": "4.64.0", "@rollup/rollup-darwin-arm64": "4.64.0", "@rollup/rollup-darwin-x64": "4.64.0", "@rollup/rollup-freebsd-arm64": "4.64.0", "@rollup/rollup-freebsd-x64": "4.64.0", "@rollup/rollup-linux-arm-gnueabihf": "4.64.0", "@rollup/rollup-linux-arm-musleabihf": "4.64.0", "@rollup/rollup-linux-arm64-gnu": "4.64.0", "@rollup/rollup-linux-arm64-musl": "4.64.0", "@rollup/rollup-linux-loong64-gnu": "4.64.0", "@rollup/rollup-linux-loong64-musl": "4.64.0", "@rollup/rollup-linux-ppc64-gnu": "4.64.0", "@rollup/rollup-linux-ppc64-musl": "4.64.0", "@rollup/rollup-linux-riscv64-gnu": "4.64.0", "@rollup/rollup-linux-riscv64-musl": "4.64.0", "@rollup/rollup-linux-s390x-gnu": "4.64.0", "@rollup/rollup-linux-x64-gnu": "4.64.0", "@rollup/rollup-linux-x64-musl": "4.64.0", "@rollup/rollup-openbsd-x64": "4.64.0", "@rollup/rollup-openharmony-arm64": "4.64.0", "@rollup/rollup-win32-arm64-msvc": "4.64.0", "@rollup/rollup-win32-ia32-msvc": "4.64.0", "@rollup/rollup-win32-x64-gnu": "4.64.0", "@rollup/rollup-win32-x64-msvc": "4.64.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-gjA/kFeDfffII8COoPsvLPvE16hWDTEc1+0QKQNKUkuV8iJjqsC4xXs8/FzuL0v9EV39kuxTbAgcFoTRyy2TGQ=="], + "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="], "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="], @@ -2692,8 +2845,12 @@ "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], + "semver-compare": ["semver-compare@1.0.0", "", {}, "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="], + "send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], + "serialize-error": ["serialize-error@7.0.1", "", { "dependencies": { "type-fest": "^0.13.1" } }, "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw=="], + "seroval": ["seroval@1.3.2", "", {}, "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ=="], "seroval-plugins": ["seroval-plugins@1.3.3", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w=="], @@ -2746,6 +2903,8 @@ "sonic-boom": ["sonic-boom@4.2.1", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q=="], + "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="], @@ -2810,6 +2969,8 @@ "strnum": ["strnum@2.4.2", "", { "dependencies": { "anynum": "^1.0.1" } }, "sha512-rDG3Ah4TV0k1hWvLSzkZtMmLN9+eS+h3knq4MP6A42Y3Yh5qGNnOUs1jJkoSr8FG5dsL28c7KgkIBzSEykqtuw=="], + "sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="], + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], "system-architecture": ["system-architecture@0.1.0", "", {}, "sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA=="], @@ -2822,11 +2983,15 @@ "text-decoder": ["text-decoder@1.2.7", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ=="], + "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], + + "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], + "thread-stream": ["thread-stream@4.2.0", "", { "dependencies": { "real-require": "^1.0.0" } }, "sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ=="], "thunky": ["thunky@1.1.0", "", {}, "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="], - "tinyexec": ["tinyexec@1.3.0", "", {}, "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ=="], + "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], @@ -2844,6 +3009,8 @@ "traverse": ["traverse@0.3.9", "", {}, "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ=="], + "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], + "tree-sitter-bash": ["tree-sitter-bash@0.25.0", "", { "dependencies": { "node-addon-api": "^8.2.1", "node-gyp-build": "^4.8.2" }, "peerDependencies": { "tree-sitter": "^0.25.0" }, "optionalPeers": ["tree-sitter"] }, "sha512-gZtlj9+qFS81qKxpLfD6H0UssQ3QBc/F0nKkPsiFDyfQF2YBqYvglFJUzchrPpVhZe9kLZTrJ9n2J6lmka69Vg=="], "tree-sitter-powershell": ["tree-sitter-powershell@0.25.10", "", { "dependencies": { "node-addon-api": "^7.1.0", "node-gyp-build": "^4.8.0" }, "peerDependencies": { "tree-sitter": "^0.25.0" }, "optionalPeers": ["tree-sitter"] }, "sha512-bEt8QoySpGFnU3aa8WedQyNMaN6aTwy/WUbvIVt0JSKF+BbJoSHNHu+wCbhj7xLMsfB0AuffmiJm+B8gzva8Lg=="], @@ -2854,10 +3021,14 @@ "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], + "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "tsscmp": ["tsscmp@1.0.6", "", {}, "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA=="], + "tsup": ["tsup@8.5.1", "", { "dependencies": { "bundle-require": "^5.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "consola": "^3.4.0", "debug": "^4.4.0", "esbuild": "^0.27.0", "fix-dts-default-cjs-exports": "^1.0.0", "joycon": "^3.1.1", "picocolors": "^1.1.1", "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", "rollup": "^4.34.8", "source-map": "^0.7.6", "sucrase": "^3.35.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.11", "tree-kill": "^1.2.2" }, "peerDependencies": { "@microsoft/api-extractor": "^7.36.0", "@swc/core": "^1", "postcss": "^8.4.12", "typescript": ">=4.5.0" }, "optionalPeers": ["@microsoft/api-extractor", "@swc/core", "postcss", "typescript"], "bin": { "tsup": "dist/cli-default.js", "tsup-node": "dist/cli-node.js" } }, "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing=="], + "tuf-js": ["tuf-js@4.1.0", "", { "dependencies": { "@tufjs/models": "4.1.0", "debug": "^4.4.3", "make-fetch-happen": "^15.0.1" } }, "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ=="], "tunnel": ["tunnel@0.0.6", "", {}, "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="], @@ -2880,6 +3051,8 @@ "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], + "ufo": ["ufo@1.6.4", "", {}, "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA=="], + "ulid": ["ulid@3.0.1", "", { "bin": { "ulid": "dist/cli.js" } }, "sha512-dPJyqPzx8preQhqq24bBG1YNkvigm87K8kVEHCD+ruZg24t6IFEFv00xMWfxcC4djmFtiTLdFuADn4+DOz6R7Q=="], "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], @@ -3326,6 +3499,8 @@ "c12/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], + "c12/pkg-types": ["pkg-types@2.3.1", "", { "dependencies": { "confbox": "^0.2.4", "exsolve": "^1.0.8", "pathe": "^2.0.3" } }, "sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg=="], + "compress-commons/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], "compress-commons/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], @@ -3388,6 +3563,8 @@ "minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + "mlly/acorn": ["acorn@8.19.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw=="], + "negotiator/content-type": ["content-type@2.1.0", "", {}, "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag=="], "node-gyp/undici": ["undici@6.28.0", "", {}, "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA=="], @@ -3398,6 +3575,8 @@ "nypm/citty": ["citty@0.2.2", "", {}, "sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w=="], + "nypm/tinyexec": ["tinyexec@1.3.0", "", {}, "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ=="], + "opencode-gitlab-auth/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], "opencode-poe-auth/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], @@ -3412,6 +3591,8 @@ "pdf-lib/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], + "pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], + "readdir-glob/minimatch": ["minimatch@5.1.9", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="], "redrob/@ai-sdk/cerebras": ["@ai-sdk/cerebras@2.0.60", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.54", "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.33" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Rnok3cThg6awBwaDSyiZpgRpbV7pqxGYrA89LODCo5cuEHeP2h0AM0lLHP7zIkclAdXfOm4wldKi/S2T/DGCOw=="], @@ -3420,6 +3601,8 @@ "rimraf/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], + "roarr/sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="], + "safe-array-concat/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], "safe-push-apply/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], @@ -3428,6 +3611,8 @@ "send/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], + "serialize-error/type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="], + "shiki/@shikijs/core": ["@shikijs/core@4.2.0", "", { "dependencies": { "@shikijs/primitive": "4.2.0", "@shikijs/types": "4.2.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-Hc87Ab1Ld/vEbZRCbwx344I5v+4RU8CVToUTRkqXL1+TjbuOp9U5Xa0M23V4GEWHxVn+yO5otb+HkQVm3ptWQQ=="], "shiki/@shikijs/types": ["@shikijs/types@4.2.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-VT/MKtlpOhEPZloSH3Pb9WCZEBDoQVMa9jedp5UAwmJOar1DVc9DRODAxmYPW9M93IK4ryuqRejFfmlvlVDemw=="], @@ -3440,6 +3625,8 @@ "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], + "tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], "thread-stream/real-require": ["real-require@1.0.0", "", {}, "sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g=="], @@ -3448,6 +3635,8 @@ "tree-sitter-bash/node-addon-api": ["node-addon-api@8.9.2", "", {}, "sha512-VijLXbi3UACN69I0JVXJsX4tjACjNoQDgv2gTF6sx2wWEi8tkSg2eX8p5gSIFi8z2+DL3oHmY6OyKce38SDolg=="], + "tsup/esbuild": ["esbuild@0.27.7", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.7", "@esbuild/android-arm": "0.27.7", "@esbuild/android-arm64": "0.27.7", "@esbuild/android-x64": "0.27.7", "@esbuild/darwin-arm64": "0.27.7", "@esbuild/darwin-x64": "0.27.7", "@esbuild/freebsd-arm64": "0.27.7", "@esbuild/freebsd-x64": "0.27.7", "@esbuild/linux-arm": "0.27.7", "@esbuild/linux-arm64": "0.27.7", "@esbuild/linux-ia32": "0.27.7", "@esbuild/linux-loong64": "0.27.7", "@esbuild/linux-mips64el": "0.27.7", "@esbuild/linux-ppc64": "0.27.7", "@esbuild/linux-riscv64": "0.27.7", "@esbuild/linux-s390x": "0.27.7", "@esbuild/linux-x64": "0.27.7", "@esbuild/netbsd-arm64": "0.27.7", "@esbuild/netbsd-x64": "0.27.7", "@esbuild/openbsd-arm64": "0.27.7", "@esbuild/openbsd-x64": "0.27.7", "@esbuild/openharmony-arm64": "0.27.7", "@esbuild/sunos-x64": "0.27.7", "@esbuild/win32-arm64": "0.27.7", "@esbuild/win32-ia32": "0.27.7", "@esbuild/win32-x64": "0.27.7" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w=="], + "type-is/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], "unzipper/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], @@ -3748,6 +3937,58 @@ "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "tsup/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.7", "", { "os": "aix", "cpu": "ppc64" }, "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg=="], + + "tsup/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.7", "", { "os": "android", "cpu": "arm" }, "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ=="], + + "tsup/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.7", "", { "os": "android", "cpu": "arm64" }, "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ=="], + + "tsup/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.7", "", { "os": "android", "cpu": "x64" }, "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg=="], + + "tsup/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw=="], + + "tsup/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ=="], + + "tsup/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.7", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w=="], + + "tsup/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.7", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ=="], + + "tsup/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.7", "", { "os": "linux", "cpu": "arm" }, "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA=="], + + "tsup/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A=="], + + "tsup/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.7", "", { "os": "linux", "cpu": "ia32" }, "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg=="], + + "tsup/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q=="], + + "tsup/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw=="], + + "tsup/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.7", "", { "os": "linux", "cpu": "ppc64" }, "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ=="], + + "tsup/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ=="], + + "tsup/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.7", "", { "os": "linux", "cpu": "s390x" }, "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw=="], + + "tsup/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.7", "", { "os": "linux", "cpu": "x64" }, "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA=="], + + "tsup/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w=="], + + "tsup/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.7", "", { "os": "none", "cpu": "x64" }, "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw=="], + + "tsup/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.7", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A=="], + + "tsup/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.7", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg=="], + + "tsup/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw=="], + + "tsup/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.7", "", { "os": "sunos", "cpu": "x64" }, "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA=="], + + "tsup/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA=="], + + "tsup/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.7", "", { "os": "win32", "cpu": "ia32" }, "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw=="], + + "tsup/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.7", "", { "os": "win32", "cpu": "x64" }, "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg=="], + "type-is/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], "unzipper/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], diff --git a/docs/LOCAL-ENGINE-API.md b/docs/LOCAL-ENGINE-API.md index ab9bc8fe9f..cfb8d71349 100644 --- a/docs/LOCAL-ENGINE-API.md +++ b/docs/LOCAL-ENGINE-API.md @@ -119,6 +119,51 @@ on the message text, which is localized. A client that offers sign-in on any fai reports a network timeout as "please log in" — that shipped, and it is what this code exists to prevent. +## 1b. `POST /api/insights/sessions` + +Labeled AI work sessions, sent to the Console's insights for a product that holds no key. It carries the same rule as the completions route: the product hands over labels, and the engine posts them with its own Console credential, resolved the same way. Office is the first caller, because its rule is that it never holds a provider key. + +- **Request:** `{ sessions: [...] }`, 1 to 500 sessions. A session is passed through as the product's object; the Console owns that shape and refuses any field that is not a label (`POST /v1/insights/sessions` in redrob-console). +- **Destination:** fixed at `${CONSOLE_URL}/insights/sessions`. The route takes no URL, and the key is never in a reply, so it cannot be used to read the key or send it anywhere else. +- **Reply:** the Console's `{ accepted, updated, rejected: [{ externalId, reason }] }`. +- **Errors:** + - `404 ProviderNotFoundError` when the engine has no Redrob key. + - `401` for a refused or over-budget key. + - `400` for a refused batch, carrying the Console's message. + - `503` when the Console is unreachable, or for 429 and 5xx. +- **No retries:** the product keeps a batch that got no answer for its next sync. + +## 1c. `POST /redrob/speech` + +Text to spoken mp3, on the engine's own Redrob credential, for a product that must +play audio and must not hold the key — Redrob Cowork's read-aloud is the first caller. +Same rule as the other credentialed routes: the product sends the text, the engine +calls the gateway with its own key, and the key never leaves this process. + +- **Request:** `{ text, model? }`. `text` is at most 4096 characters (counted as code + points, so the limit here matches the gateway's). `model` is a gateway speech model + id, defaulting to `elevenlabs/eleven-flash-v2.5` for playback. +- **Reply:** the raw mp3 as `audio/mpeg` — the bytes, not a JSON wrapper or a data URL. +- **Destination:** fixed at `${CONSOLE_URL}/audio/speech`. The route takes no URL. +- **Errors:** the shared control-group set — `400` invalid request (empty or over-long + text), `502` upstream (the gateway refused or returned a non-audio body), `503` the + gateway is unreachable, and a timeout error. No `engine_not_authenticated` body here: + a missing key surfaces as the upstream/service error of this group, not the OpenAI + envelope that only `/v1/chat/completions` speaks. + +## 1d. `POST /redrob/transcribe` + +The inverse: recorded speech to text, same credential model, billed to the connected +Redrob account. + +- **Request:** `{ audio, format? }`. `audio` is base64 of the raw bytes (NOT a data + URL), at most 10 MB. `format` is one of `TRANSCRIPTION_FORMATS` + (`packages/redrob/src/redrob/transcription.ts`). +- **Reply:** `{ text }` — the transcript, trimmed, and empty when nothing was said. +- **Destination:** fixed at the gateway's transcription endpoint; the route takes no URL. +- **Errors:** the same control-group set as speech — `400` invalid request (missing or + over-size audio), `502` upstream, `503` unreachable, timeout. + ## 2. Promoting `/experimental` Every `/experimental/*` route is promoted out of the experimental namespace and diff --git a/packages/client/src/generated-effect/client.ts b/packages/client/src/generated-effect/client.ts index 84a4787678..782391b402 100644 --- a/packages/client/src/generated-effect/client.ts +++ b/packages/client/src/generated-effect/client.ts @@ -290,152 +290,159 @@ const Endpoint7_1 = (raw: RawClient["server.variant"]) => (input: Endpoint7_1Inp const adaptGroup7 = (raw: RawClient["server.variant"]) => ({ paraphrase: Endpoint7_0(raw), compare: Endpoint7_1(raw) }) -type Endpoint8_0Request = Parameters[0] -type Endpoint8_0Input = { readonly location?: Endpoint8_0Request["query"]["location"] } -const Endpoint8_0 = (raw: RawClient["server.integration"]) => (input?: Endpoint8_0Input) => +type Endpoint8_0Request = Parameters[0] +type Endpoint8_0Input = { readonly sessions: Endpoint8_0Request["payload"]["sessions"] } +const Endpoint8_0 = (raw: RawClient["server.insights"]) => (input: Endpoint8_0Input) => + raw["insights.sessions"]({ payload: { sessions: input["sessions"] } }).pipe(Effect.mapError(mapClientError)) + +const adaptGroup8 = (raw: RawClient["server.insights"]) => ({ sessions: Endpoint8_0(raw) }) + +type Endpoint9_0Request = Parameters[0] +type Endpoint9_0Input = { readonly location?: Endpoint9_0Request["query"]["location"] } +const Endpoint9_0 = (raw: RawClient["server.integration"]) => (input?: Endpoint9_0Input) => raw["integration.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint8_1Request = Parameters[0] -type Endpoint8_1Input = { - readonly integrationID: Endpoint8_1Request["params"]["integrationID"] - readonly location?: Endpoint8_1Request["query"]["location"] +type Endpoint9_1Request = Parameters[0] +type Endpoint9_1Input = { + readonly integrationID: Endpoint9_1Request["params"]["integrationID"] + readonly location?: Endpoint9_1Request["query"]["location"] } -const Endpoint8_1 = (raw: RawClient["server.integration"]) => (input: Endpoint8_1Input) => +const Endpoint9_1 = (raw: RawClient["server.integration"]) => (input: Endpoint9_1Input) => raw["integration.get"]({ params: { integrationID: input["integrationID"] }, query: { location: input["location"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint8_2Request = Parameters[0] -type Endpoint8_2Input = { - readonly integrationID: Endpoint8_2Request["params"]["integrationID"] - readonly location?: Endpoint8_2Request["query"]["location"] - readonly key: Endpoint8_2Request["payload"]["key"] - readonly label?: Endpoint8_2Request["payload"]["label"] +type Endpoint9_2Request = Parameters[0] +type Endpoint9_2Input = { + readonly integrationID: Endpoint9_2Request["params"]["integrationID"] + readonly location?: Endpoint9_2Request["query"]["location"] + readonly key: Endpoint9_2Request["payload"]["key"] + readonly label?: Endpoint9_2Request["payload"]["label"] } -const Endpoint8_2 = (raw: RawClient["server.integration"]) => (input: Endpoint8_2Input) => +const Endpoint9_2 = (raw: RawClient["server.integration"]) => (input: Endpoint9_2Input) => raw["integration.connect.key"]({ params: { integrationID: input["integrationID"] }, query: { location: input["location"] }, payload: { key: input["key"], label: input["label"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint8_3Request = Parameters[0] -type Endpoint8_3Input = { - readonly integrationID: Endpoint8_3Request["params"]["integrationID"] - readonly location?: Endpoint8_3Request["query"]["location"] - readonly methodID: Endpoint8_3Request["payload"]["methodID"] - readonly inputs: Endpoint8_3Request["payload"]["inputs"] - readonly label?: Endpoint8_3Request["payload"]["label"] +type Endpoint9_3Request = Parameters[0] +type Endpoint9_3Input = { + readonly integrationID: Endpoint9_3Request["params"]["integrationID"] + readonly location?: Endpoint9_3Request["query"]["location"] + readonly methodID: Endpoint9_3Request["payload"]["methodID"] + readonly inputs: Endpoint9_3Request["payload"]["inputs"] + readonly label?: Endpoint9_3Request["payload"]["label"] } -const Endpoint8_3 = (raw: RawClient["server.integration"]) => (input: Endpoint8_3Input) => +const Endpoint9_3 = (raw: RawClient["server.integration"]) => (input: Endpoint9_3Input) => raw["integration.connect.oauth"]({ params: { integrationID: input["integrationID"] }, query: { location: input["location"] }, payload: { methodID: input["methodID"], inputs: input["inputs"], label: input["label"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint8_4Request = Parameters[0] -type Endpoint8_4Input = { - readonly attemptID: Endpoint8_4Request["params"]["attemptID"] - readonly location?: Endpoint8_4Request["query"]["location"] +type Endpoint9_4Request = Parameters[0] +type Endpoint9_4Input = { + readonly attemptID: Endpoint9_4Request["params"]["attemptID"] + readonly location?: Endpoint9_4Request["query"]["location"] } -const Endpoint8_4 = (raw: RawClient["server.integration"]) => (input: Endpoint8_4Input) => +const Endpoint9_4 = (raw: RawClient["server.integration"]) => (input: Endpoint9_4Input) => raw["integration.attempt.status"]({ params: { attemptID: input["attemptID"] }, query: { location: input["location"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint8_5Request = Parameters[0] -type Endpoint8_5Input = { - readonly attemptID: Endpoint8_5Request["params"]["attemptID"] - readonly location?: Endpoint8_5Request["query"]["location"] - readonly code?: Endpoint8_5Request["payload"]["code"] +type Endpoint9_5Request = Parameters[0] +type Endpoint9_5Input = { + readonly attemptID: Endpoint9_5Request["params"]["attemptID"] + readonly location?: Endpoint9_5Request["query"]["location"] + readonly code?: Endpoint9_5Request["payload"]["code"] } -const Endpoint8_5 = (raw: RawClient["server.integration"]) => (input: Endpoint8_5Input) => +const Endpoint9_5 = (raw: RawClient["server.integration"]) => (input: Endpoint9_5Input) => raw["integration.attempt.complete"]({ params: { attemptID: input["attemptID"] }, query: { location: input["location"] }, payload: { code: input["code"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint8_6Request = Parameters[0] -type Endpoint8_6Input = { - readonly attemptID: Endpoint8_6Request["params"]["attemptID"] - readonly location?: Endpoint8_6Request["query"]["location"] +type Endpoint9_6Request = Parameters[0] +type Endpoint9_6Input = { + readonly attemptID: Endpoint9_6Request["params"]["attemptID"] + readonly location?: Endpoint9_6Request["query"]["location"] } -const Endpoint8_6 = (raw: RawClient["server.integration"]) => (input: Endpoint8_6Input) => +const Endpoint9_6 = (raw: RawClient["server.integration"]) => (input: Endpoint9_6Input) => raw["integration.attempt.cancel"]({ params: { attemptID: input["attemptID"] }, query: { location: input["location"] }, }).pipe(Effect.mapError(mapClientError)) -const adaptGroup8 = (raw: RawClient["server.integration"]) => ({ - list: Endpoint8_0(raw), - get: Endpoint8_1(raw), - connectKey: Endpoint8_2(raw), - connectOauth: Endpoint8_3(raw), - attemptStatus: Endpoint8_4(raw), - attemptComplete: Endpoint8_5(raw), - attemptCancel: Endpoint8_6(raw), +const adaptGroup9 = (raw: RawClient["server.integration"]) => ({ + list: Endpoint9_0(raw), + get: Endpoint9_1(raw), + connectKey: Endpoint9_2(raw), + connectOauth: Endpoint9_3(raw), + attemptStatus: Endpoint9_4(raw), + attemptComplete: Endpoint9_5(raw), + attemptCancel: Endpoint9_6(raw), }) -type Endpoint9_0Request = Parameters[0] -type Endpoint9_0Input = { - readonly credentialID: Endpoint9_0Request["params"]["credentialID"] - readonly location?: Endpoint9_0Request["query"]["location"] - readonly label: Endpoint9_0Request["payload"]["label"] +type Endpoint10_0Request = Parameters[0] +type Endpoint10_0Input = { + readonly credentialID: Endpoint10_0Request["params"]["credentialID"] + readonly location?: Endpoint10_0Request["query"]["location"] + readonly label: Endpoint10_0Request["payload"]["label"] } -const Endpoint9_0 = (raw: RawClient["server.credential"]) => (input: Endpoint9_0Input) => +const Endpoint10_0 = (raw: RawClient["server.credential"]) => (input: Endpoint10_0Input) => raw["credential.update"]({ params: { credentialID: input["credentialID"] }, query: { location: input["location"] }, payload: { label: input["label"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint9_1Request = Parameters[0] -type Endpoint9_1Input = { - readonly credentialID: Endpoint9_1Request["params"]["credentialID"] - readonly location?: Endpoint9_1Request["query"]["location"] +type Endpoint10_1Request = Parameters[0] +type Endpoint10_1Input = { + readonly credentialID: Endpoint10_1Request["params"]["credentialID"] + readonly location?: Endpoint10_1Request["query"]["location"] } -const Endpoint9_1 = (raw: RawClient["server.credential"]) => (input: Endpoint9_1Input) => +const Endpoint10_1 = (raw: RawClient["server.credential"]) => (input: Endpoint10_1Input) => raw["credential.remove"]({ params: { credentialID: input["credentialID"] }, query: { location: input["location"] }, }).pipe(Effect.mapError(mapClientError)) -const adaptGroup9 = (raw: RawClient["server.credential"]) => ({ update: Endpoint9_0(raw), remove: Endpoint9_1(raw) }) +const adaptGroup10 = (raw: RawClient["server.credential"]) => ({ update: Endpoint10_0(raw), remove: Endpoint10_1(raw) }) -type Endpoint10_0Request = Parameters[0] -type Endpoint10_0Input = { readonly location?: Endpoint10_0Request["query"]["location"] } -const Endpoint10_0 = (raw: RawClient["server.permission"]) => (input?: Endpoint10_0Input) => +type Endpoint11_0Request = Parameters[0] +type Endpoint11_0Input = { readonly location?: Endpoint11_0Request["query"]["location"] } +const Endpoint11_0 = (raw: RawClient["server.permission"]) => (input?: Endpoint11_0Input) => raw["permission.request.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint10_1Request = Parameters[0] -type Endpoint10_1Input = { readonly projectID?: Endpoint10_1Request["query"]["projectID"] } -const Endpoint10_1 = (raw: RawClient["server.permission"]) => (input?: Endpoint10_1Input) => +type Endpoint11_1Request = Parameters[0] +type Endpoint11_1Input = { readonly projectID?: Endpoint11_1Request["query"]["projectID"] } +const Endpoint11_1 = (raw: RawClient["server.permission"]) => (input?: Endpoint11_1Input) => raw["permission.saved.list"]({ query: { projectID: input?.["projectID"] } }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint10_2Request = Parameters[0] -type Endpoint10_2Input = { readonly id: Endpoint10_2Request["params"]["id"] } -const Endpoint10_2 = (raw: RawClient["server.permission"]) => (input: Endpoint10_2Input) => +type Endpoint11_2Request = Parameters[0] +type Endpoint11_2Input = { readonly id: Endpoint11_2Request["params"]["id"] } +const Endpoint11_2 = (raw: RawClient["server.permission"]) => (input: Endpoint11_2Input) => raw["permission.saved.remove"]({ params: { id: input["id"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint10_3Request = Parameters[0] -type Endpoint10_3Input = { - readonly sessionID: Endpoint10_3Request["params"]["sessionID"] - readonly id?: Endpoint10_3Request["payload"]["id"] - readonly action: Endpoint10_3Request["payload"]["action"] - readonly resources: Endpoint10_3Request["payload"]["resources"] - readonly save?: Endpoint10_3Request["payload"]["save"] - readonly metadata?: Endpoint10_3Request["payload"]["metadata"] - readonly source?: Endpoint10_3Request["payload"]["source"] - readonly agent?: Endpoint10_3Request["payload"]["agent"] -} -const Endpoint10_3 = (raw: RawClient["server.permission"]) => (input: Endpoint10_3Input) => +type Endpoint11_3Request = Parameters[0] +type Endpoint11_3Input = { + readonly sessionID: Endpoint11_3Request["params"]["sessionID"] + readonly id?: Endpoint11_3Request["payload"]["id"] + readonly action: Endpoint11_3Request["payload"]["action"] + readonly resources: Endpoint11_3Request["payload"]["resources"] + readonly save?: Endpoint11_3Request["payload"]["save"] + readonly metadata?: Endpoint11_3Request["payload"]["metadata"] + readonly source?: Endpoint11_3Request["payload"]["source"] + readonly agent?: Endpoint11_3Request["payload"]["agent"] +} +const Endpoint11_3 = (raw: RawClient["server.permission"]) => (input: Endpoint11_3Input) => raw["session.permission.create"]({ params: { sessionID: input["sessionID"] }, payload: { @@ -452,87 +459,87 @@ const Endpoint10_3 = (raw: RawClient["server.permission"]) => (input: Endpoint10 Effect.map((value) => value.data), ) -type Endpoint10_4Request = Parameters[0] -type Endpoint10_4Input = { readonly sessionID: Endpoint10_4Request["params"]["sessionID"] } -const Endpoint10_4 = (raw: RawClient["server.permission"]) => (input: Endpoint10_4Input) => +type Endpoint11_4Request = Parameters[0] +type Endpoint11_4Input = { readonly sessionID: Endpoint11_4Request["params"]["sessionID"] } +const Endpoint11_4 = (raw: RawClient["server.permission"]) => (input: Endpoint11_4Input) => raw["session.permission.list"]({ params: { sessionID: input["sessionID"] } }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint10_5Request = Parameters[0] -type Endpoint10_5Input = { - readonly sessionID: Endpoint10_5Request["params"]["sessionID"] - readonly requestID: Endpoint10_5Request["params"]["requestID"] +type Endpoint11_5Request = Parameters[0] +type Endpoint11_5Input = { + readonly sessionID: Endpoint11_5Request["params"]["sessionID"] + readonly requestID: Endpoint11_5Request["params"]["requestID"] } -const Endpoint10_5 = (raw: RawClient["server.permission"]) => (input: Endpoint10_5Input) => +const Endpoint11_5 = (raw: RawClient["server.permission"]) => (input: Endpoint11_5Input) => raw["session.permission.get"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] } }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint10_6Request = Parameters[0] -type Endpoint10_6Input = { - readonly sessionID: Endpoint10_6Request["params"]["sessionID"] - readonly requestID: Endpoint10_6Request["params"]["requestID"] - readonly reply: Endpoint10_6Request["payload"]["reply"] - readonly message?: Endpoint10_6Request["payload"]["message"] +type Endpoint11_6Request = Parameters[0] +type Endpoint11_6Input = { + readonly sessionID: Endpoint11_6Request["params"]["sessionID"] + readonly requestID: Endpoint11_6Request["params"]["requestID"] + readonly reply: Endpoint11_6Request["payload"]["reply"] + readonly message?: Endpoint11_6Request["payload"]["message"] } -const Endpoint10_6 = (raw: RawClient["server.permission"]) => (input: Endpoint10_6Input) => +const Endpoint11_6 = (raw: RawClient["server.permission"]) => (input: Endpoint11_6Input) => raw["session.permission.reply"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] }, payload: { reply: input["reply"], message: input["message"] }, }).pipe(Effect.mapError(mapClientError)) -const adaptGroup10 = (raw: RawClient["server.permission"]) => ({ - listRequests: Endpoint10_0(raw), - listSaved: Endpoint10_1(raw), - removeSaved: Endpoint10_2(raw), - create: Endpoint10_3(raw), - list: Endpoint10_4(raw), - get: Endpoint10_5(raw), - reply: Endpoint10_6(raw), +const adaptGroup11 = (raw: RawClient["server.permission"]) => ({ + listRequests: Endpoint11_0(raw), + listSaved: Endpoint11_1(raw), + removeSaved: Endpoint11_2(raw), + create: Endpoint11_3(raw), + list: Endpoint11_4(raw), + get: Endpoint11_5(raw), + reply: Endpoint11_6(raw), }) -type Endpoint11_0Request = Parameters[0] -type Endpoint11_0Input = { - readonly location?: Endpoint11_0Request["query"]["location"] - readonly path?: Endpoint11_0Request["query"]["path"] +type Endpoint12_0Request = Parameters[0] +type Endpoint12_0Input = { + readonly location?: Endpoint12_0Request["query"]["location"] + readonly path?: Endpoint12_0Request["query"]["path"] } -const Endpoint11_0 = (raw: RawClient["server.fs"]) => (input?: Endpoint11_0Input) => +const Endpoint12_0 = (raw: RawClient["server.fs"]) => (input?: Endpoint12_0Input) => raw["fs.list"]({ query: { location: input?.["location"], path: input?.["path"] } }).pipe( Effect.mapError(mapClientError), ) -type Endpoint11_1Request = Parameters[0] -type Endpoint11_1Input = { - readonly location?: Endpoint11_1Request["query"]["location"] - readonly query: Endpoint11_1Request["query"]["query"] - readonly type?: Endpoint11_1Request["query"]["type"] - readonly limit?: Endpoint11_1Request["query"]["limit"] +type Endpoint12_1Request = Parameters[0] +type Endpoint12_1Input = { + readonly location?: Endpoint12_1Request["query"]["location"] + readonly query: Endpoint12_1Request["query"]["query"] + readonly type?: Endpoint12_1Request["query"]["type"] + readonly limit?: Endpoint12_1Request["query"]["limit"] } -const Endpoint11_1 = (raw: RawClient["server.fs"]) => (input: Endpoint11_1Input) => +const Endpoint12_1 = (raw: RawClient["server.fs"]) => (input: Endpoint12_1Input) => raw["fs.find"]({ query: { location: input["location"], query: input["query"], type: input["type"], limit: input["limit"] }, }).pipe(Effect.mapError(mapClientError)) -const adaptGroup11 = (raw: RawClient["server.fs"]) => ({ list: Endpoint11_0(raw), find: Endpoint11_1(raw) }) +const adaptGroup12 = (raw: RawClient["server.fs"]) => ({ list: Endpoint12_0(raw), find: Endpoint12_1(raw) }) -type Endpoint12_0Request = Parameters[0] -type Endpoint12_0Input = { readonly location?: Endpoint12_0Request["query"]["location"] } -const Endpoint12_0 = (raw: RawClient["server.command"]) => (input?: Endpoint12_0Input) => +type Endpoint13_0Request = Parameters[0] +type Endpoint13_0Input = { readonly location?: Endpoint13_0Request["query"]["location"] } +const Endpoint13_0 = (raw: RawClient["server.command"]) => (input?: Endpoint13_0Input) => raw["command.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -const adaptGroup12 = (raw: RawClient["server.command"]) => ({ list: Endpoint12_0(raw) }) +const adaptGroup13 = (raw: RawClient["server.command"]) => ({ list: Endpoint13_0(raw) }) -type Endpoint13_0Request = Parameters[0] -type Endpoint13_0Input = { readonly location?: Endpoint13_0Request["query"]["location"] } -const Endpoint13_0 = (raw: RawClient["server.skill"]) => (input?: Endpoint13_0Input) => +type Endpoint14_0Request = Parameters[0] +type Endpoint14_0Input = { readonly location?: Endpoint14_0Request["query"]["location"] } +const Endpoint14_0 = (raw: RawClient["server.skill"]) => (input?: Endpoint14_0Input) => raw["skill.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -const adaptGroup13 = (raw: RawClient["server.skill"]) => ({ list: Endpoint13_0(raw) }) +const adaptGroup14 = (raw: RawClient["server.skill"]) => ({ list: Endpoint14_0(raw) }) -const Endpoint14_0 = (raw: RawClient["server.event"]) => () => +const Endpoint15_0 = (raw: RawClient["server.event"]) => () => Stream.unwrap( raw["event.subscribe"]({}).pipe( Effect.mapError(mapClientError), @@ -540,23 +547,23 @@ const Endpoint14_0 = (raw: RawClient["server.event"]) => () => ), ) -const adaptGroup14 = (raw: RawClient["server.event"]) => ({ subscribe: Endpoint14_0(raw) }) +const adaptGroup15 = (raw: RawClient["server.event"]) => ({ subscribe: Endpoint15_0(raw) }) -type Endpoint15_0Request = Parameters[0] -type Endpoint15_0Input = { readonly location?: Endpoint15_0Request["query"]["location"] } -const Endpoint15_0 = (raw: RawClient["server.pty"]) => (input?: Endpoint15_0Input) => +type Endpoint16_0Request = Parameters[0] +type Endpoint16_0Input = { readonly location?: Endpoint16_0Request["query"]["location"] } +const Endpoint16_0 = (raw: RawClient["server.pty"]) => (input?: Endpoint16_0Input) => raw["pty.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint15_1Request = Parameters[0] -type Endpoint15_1Input = { - readonly location?: Endpoint15_1Request["query"]["location"] - readonly command?: Endpoint15_1Request["payload"]["command"] - readonly args?: Endpoint15_1Request["payload"]["args"] - readonly cwd?: Endpoint15_1Request["payload"]["cwd"] - readonly title?: Endpoint15_1Request["payload"]["title"] - readonly env?: Endpoint15_1Request["payload"]["env"] +type Endpoint16_1Request = Parameters[0] +type Endpoint16_1Input = { + readonly location?: Endpoint16_1Request["query"]["location"] + readonly command?: Endpoint16_1Request["payload"]["command"] + readonly args?: Endpoint16_1Request["payload"]["args"] + readonly cwd?: Endpoint16_1Request["payload"]["cwd"] + readonly title?: Endpoint16_1Request["payload"]["title"] + readonly env?: Endpoint16_1Request["payload"]["env"] } -const Endpoint15_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint15_1Input) => +const Endpoint16_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint16_1Input) => raw["pty.create"]({ query: { location: input?.["location"] }, payload: { @@ -568,206 +575,206 @@ const Endpoint15_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint15_1Inpu }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint15_2Request = Parameters[0] -type Endpoint15_2Input = { - readonly ptyID: Endpoint15_2Request["params"]["ptyID"] - readonly location?: Endpoint15_2Request["query"]["location"] +type Endpoint16_2Request = Parameters[0] +type Endpoint16_2Input = { + readonly ptyID: Endpoint16_2Request["params"]["ptyID"] + readonly location?: Endpoint16_2Request["query"]["location"] } -const Endpoint15_2 = (raw: RawClient["server.pty"]) => (input: Endpoint15_2Input) => +const Endpoint16_2 = (raw: RawClient["server.pty"]) => (input: Endpoint16_2Input) => raw["pty.get"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] } }).pipe( Effect.mapError(mapClientError), ) -type Endpoint15_3Request = Parameters[0] -type Endpoint15_3Input = { - readonly ptyID: Endpoint15_3Request["params"]["ptyID"] - readonly location?: Endpoint15_3Request["query"]["location"] - readonly title?: Endpoint15_3Request["payload"]["title"] - readonly size?: Endpoint15_3Request["payload"]["size"] +type Endpoint16_3Request = Parameters[0] +type Endpoint16_3Input = { + readonly ptyID: Endpoint16_3Request["params"]["ptyID"] + readonly location?: Endpoint16_3Request["query"]["location"] + readonly title?: Endpoint16_3Request["payload"]["title"] + readonly size?: Endpoint16_3Request["payload"]["size"] } -const Endpoint15_3 = (raw: RawClient["server.pty"]) => (input: Endpoint15_3Input) => +const Endpoint16_3 = (raw: RawClient["server.pty"]) => (input: Endpoint16_3Input) => raw["pty.update"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] }, payload: { title: input["title"], size: input["size"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint15_4Request = Parameters[0] -type Endpoint15_4Input = { - readonly ptyID: Endpoint15_4Request["params"]["ptyID"] - readonly location?: Endpoint15_4Request["query"]["location"] +type Endpoint16_4Request = Parameters[0] +type Endpoint16_4Input = { + readonly ptyID: Endpoint16_4Request["params"]["ptyID"] + readonly location?: Endpoint16_4Request["query"]["location"] } -const Endpoint15_4 = (raw: RawClient["server.pty"]) => (input: Endpoint15_4Input) => +const Endpoint16_4 = (raw: RawClient["server.pty"]) => (input: Endpoint16_4Input) => raw["pty.remove"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] } }).pipe( Effect.mapError(mapClientError), ) -const adaptGroup15 = (raw: RawClient["server.pty"]) => ({ - list: Endpoint15_0(raw), - create: Endpoint15_1(raw), - get: Endpoint15_2(raw), - update: Endpoint15_3(raw), - remove: Endpoint15_4(raw), +const adaptGroup16 = (raw: RawClient["server.pty"]) => ({ + list: Endpoint16_0(raw), + create: Endpoint16_1(raw), + get: Endpoint16_2(raw), + update: Endpoint16_3(raw), + remove: Endpoint16_4(raw), }) -type Endpoint16_0Request = Parameters[0] -type Endpoint16_0Input = { readonly location?: Endpoint16_0Request["query"]["location"] } -const Endpoint16_0 = (raw: RawClient["server.question"]) => (input?: Endpoint16_0Input) => +type Endpoint17_0Request = Parameters[0] +type Endpoint17_0Input = { readonly location?: Endpoint17_0Request["query"]["location"] } +const Endpoint17_0 = (raw: RawClient["server.question"]) => (input?: Endpoint17_0Input) => raw["question.request.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint16_1Request = Parameters[0] -type Endpoint16_1Input = { readonly sessionID: Endpoint16_1Request["params"]["sessionID"] } -const Endpoint16_1 = (raw: RawClient["server.question"]) => (input: Endpoint16_1Input) => +type Endpoint17_1Request = Parameters[0] +type Endpoint17_1Input = { readonly sessionID: Endpoint17_1Request["params"]["sessionID"] } +const Endpoint17_1 = (raw: RawClient["server.question"]) => (input: Endpoint17_1Input) => raw["session.question.list"]({ params: { sessionID: input["sessionID"] } }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint16_2Request = Parameters[0] -type Endpoint16_2Input = { - readonly sessionID: Endpoint16_2Request["params"]["sessionID"] - readonly requestID: Endpoint16_2Request["params"]["requestID"] - readonly answers: Endpoint16_2Request["payload"]["answers"] +type Endpoint17_2Request = Parameters[0] +type Endpoint17_2Input = { + readonly sessionID: Endpoint17_2Request["params"]["sessionID"] + readonly requestID: Endpoint17_2Request["params"]["requestID"] + readonly answers: Endpoint17_2Request["payload"]["answers"] } -const Endpoint16_2 = (raw: RawClient["server.question"]) => (input: Endpoint16_2Input) => +const Endpoint17_2 = (raw: RawClient["server.question"]) => (input: Endpoint17_2Input) => raw["session.question.reply"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] }, payload: { answers: input["answers"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint16_3Request = Parameters[0] -type Endpoint16_3Input = { - readonly sessionID: Endpoint16_3Request["params"]["sessionID"] - readonly requestID: Endpoint16_3Request["params"]["requestID"] +type Endpoint17_3Request = Parameters[0] +type Endpoint17_3Input = { + readonly sessionID: Endpoint17_3Request["params"]["sessionID"] + readonly requestID: Endpoint17_3Request["params"]["requestID"] } -const Endpoint16_3 = (raw: RawClient["server.question"]) => (input: Endpoint16_3Input) => +const Endpoint17_3 = (raw: RawClient["server.question"]) => (input: Endpoint17_3Input) => raw["session.question.reject"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] } }).pipe( Effect.mapError(mapClientError), ) -const adaptGroup16 = (raw: RawClient["server.question"]) => ({ - listRequests: Endpoint16_0(raw), - list: Endpoint16_1(raw), - reply: Endpoint16_2(raw), - reject: Endpoint16_3(raw), +const adaptGroup17 = (raw: RawClient["server.question"]) => ({ + listRequests: Endpoint17_0(raw), + list: Endpoint17_1(raw), + reply: Endpoint17_2(raw), + reject: Endpoint17_3(raw), }) -type Endpoint17_0Request = Parameters[0] -type Endpoint17_0Input = { readonly location?: Endpoint17_0Request["query"]["location"] } -const Endpoint17_0 = (raw: RawClient["server.browser"]) => (input?: Endpoint17_0Input) => +type Endpoint18_0Request = Parameters[0] +type Endpoint18_0Input = { readonly location?: Endpoint18_0Request["query"]["location"] } +const Endpoint18_0 = (raw: RawClient["server.browser"]) => (input?: Endpoint18_0Input) => raw["browser.request.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint17_1Request = Parameters[0] -type Endpoint17_1Input = { readonly sessionID: Endpoint17_1Request["params"]["sessionID"] } -const Endpoint17_1 = (raw: RawClient["server.browser"]) => (input: Endpoint17_1Input) => +type Endpoint18_1Request = Parameters[0] +type Endpoint18_1Input = { readonly sessionID: Endpoint18_1Request["params"]["sessionID"] } +const Endpoint18_1 = (raw: RawClient["server.browser"]) => (input: Endpoint18_1Input) => raw["session.browser.list"]({ params: { sessionID: input["sessionID"] } }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint17_2Request = Parameters[0] -type Endpoint17_2Input = { - readonly sessionID: Endpoint17_2Request["params"]["sessionID"] - readonly requestID: Endpoint17_2Request["params"]["requestID"] - readonly value: Endpoint17_2Request["payload"]["value"] +type Endpoint18_2Request = Parameters[0] +type Endpoint18_2Input = { + readonly sessionID: Endpoint18_2Request["params"]["sessionID"] + readonly requestID: Endpoint18_2Request["params"]["requestID"] + readonly value: Endpoint18_2Request["payload"]["value"] } -const Endpoint17_2 = (raw: RawClient["server.browser"]) => (input: Endpoint17_2Input) => +const Endpoint18_2 = (raw: RawClient["server.browser"]) => (input: Endpoint18_2Input) => raw["session.browser.reply"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] }, payload: { value: input["value"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint17_3Request = Parameters[0] -type Endpoint17_3Input = { - readonly sessionID: Endpoint17_3Request["params"]["sessionID"] - readonly requestID: Endpoint17_3Request["params"]["requestID"] - readonly reason: Endpoint17_3Request["payload"]["reason"] +type Endpoint18_3Request = Parameters[0] +type Endpoint18_3Input = { + readonly sessionID: Endpoint18_3Request["params"]["sessionID"] + readonly requestID: Endpoint18_3Request["params"]["requestID"] + readonly reason: Endpoint18_3Request["payload"]["reason"] } -const Endpoint17_3 = (raw: RawClient["server.browser"]) => (input: Endpoint17_3Input) => +const Endpoint18_3 = (raw: RawClient["server.browser"]) => (input: Endpoint18_3Input) => raw["session.browser.refuse"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] }, payload: { reason: input["reason"] }, }).pipe(Effect.mapError(mapClientError)) -const adaptGroup17 = (raw: RawClient["server.browser"]) => ({ - listRequests: Endpoint17_0(raw), - list: Endpoint17_1(raw), - reply: Endpoint17_2(raw), - refuse: Endpoint17_3(raw), +const adaptGroup18 = (raw: RawClient["server.browser"]) => ({ + listRequests: Endpoint18_0(raw), + list: Endpoint18_1(raw), + reply: Endpoint18_2(raw), + refuse: Endpoint18_3(raw), }) -type Endpoint18_0Request = Parameters[0] -type Endpoint18_0Input = { readonly location?: Endpoint18_0Request["query"]["location"] } -const Endpoint18_0 = (raw: RawClient["server.reference"]) => (input?: Endpoint18_0Input) => +type Endpoint19_0Request = Parameters[0] +type Endpoint19_0Input = { readonly location?: Endpoint19_0Request["query"]["location"] } +const Endpoint19_0 = (raw: RawClient["server.reference"]) => (input?: Endpoint19_0Input) => raw["reference.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -const adaptGroup18 = (raw: RawClient["server.reference"]) => ({ list: Endpoint18_0(raw) }) +const adaptGroup19 = (raw: RawClient["server.reference"]) => ({ list: Endpoint19_0(raw) }) -type Endpoint19_0Request = Parameters[0] -type Endpoint19_0Input = { - readonly projectID: Endpoint19_0Request["params"]["projectID"] - readonly location?: Endpoint19_0Request["query"]["location"] - readonly strategy: Endpoint19_0Request["payload"]["strategy"] - readonly directory: Endpoint19_0Request["payload"]["directory"] - readonly name?: Endpoint19_0Request["payload"]["name"] +type Endpoint20_0Request = Parameters[0] +type Endpoint20_0Input = { + readonly projectID: Endpoint20_0Request["params"]["projectID"] + readonly location?: Endpoint20_0Request["query"]["location"] + readonly strategy: Endpoint20_0Request["payload"]["strategy"] + readonly directory: Endpoint20_0Request["payload"]["directory"] + readonly name?: Endpoint20_0Request["payload"]["name"] } -const Endpoint19_0 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint19_0Input) => +const Endpoint20_0 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint20_0Input) => raw["projectCopy.create"]({ params: { projectID: input["projectID"] }, query: { location: input["location"] }, payload: { strategy: input["strategy"], directory: input["directory"], name: input["name"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint19_1Request = Parameters[0] -type Endpoint19_1Input = { - readonly projectID: Endpoint19_1Request["params"]["projectID"] - readonly location?: Endpoint19_1Request["query"]["location"] - readonly directory: Endpoint19_1Request["payload"]["directory"] - readonly force: Endpoint19_1Request["payload"]["force"] +type Endpoint20_1Request = Parameters[0] +type Endpoint20_1Input = { + readonly projectID: Endpoint20_1Request["params"]["projectID"] + readonly location?: Endpoint20_1Request["query"]["location"] + readonly directory: Endpoint20_1Request["payload"]["directory"] + readonly force: Endpoint20_1Request["payload"]["force"] } -const Endpoint19_1 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint19_1Input) => +const Endpoint20_1 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint20_1Input) => raw["projectCopy.remove"]({ params: { projectID: input["projectID"] }, query: { location: input["location"] }, payload: { directory: input["directory"], force: input["force"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint19_2Request = Parameters[0] -type Endpoint19_2Input = { - readonly projectID: Endpoint19_2Request["params"]["projectID"] - readonly location?: Endpoint19_2Request["query"]["location"] +type Endpoint20_2Request = Parameters[0] +type Endpoint20_2Input = { + readonly projectID: Endpoint20_2Request["params"]["projectID"] + readonly location?: Endpoint20_2Request["query"]["location"] } -const Endpoint19_2 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint19_2Input) => +const Endpoint20_2 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint20_2Input) => raw["projectCopy.refresh"]({ params: { projectID: input["projectID"] }, query: { location: input["location"] }, }).pipe(Effect.mapError(mapClientError)) -const adaptGroup19 = (raw: RawClient["server.projectCopy"]) => ({ - create: Endpoint19_0(raw), - remove: Endpoint19_1(raw), - refresh: Endpoint19_2(raw), +const adaptGroup20 = (raw: RawClient["server.projectCopy"]) => ({ + create: Endpoint20_0(raw), + remove: Endpoint20_1(raw), + refresh: Endpoint20_2(raw), }) -type Endpoint20_0Request = Parameters[0] -type Endpoint20_0Input = { - readonly model: Endpoint20_0Request["payload"]["model"] - readonly messages: Endpoint20_0Request["payload"]["messages"] - readonly tools?: Endpoint20_0Request["payload"]["tools"] - readonly tool_choice?: Endpoint20_0Request["payload"]["tool_choice"] - readonly stream?: Endpoint20_0Request["payload"]["stream"] - readonly max_tokens?: Endpoint20_0Request["payload"]["max_tokens"] - readonly max_completion_tokens?: Endpoint20_0Request["payload"]["max_completion_tokens"] - readonly temperature?: Endpoint20_0Request["payload"]["temperature"] - readonly top_p?: Endpoint20_0Request["payload"]["top_p"] - readonly stop?: Endpoint20_0Request["payload"]["stop"] - readonly seed?: Endpoint20_0Request["payload"]["seed"] - readonly frequency_penalty?: Endpoint20_0Request["payload"]["frequency_penalty"] - readonly presence_penalty?: Endpoint20_0Request["payload"]["presence_penalty"] - readonly reasoning_effort?: Endpoint20_0Request["payload"]["reasoning_effort"] - readonly user?: Endpoint20_0Request["payload"]["user"] -} -const Endpoint20_0 = (raw: RawClient["server.chat"]) => (input: Endpoint20_0Input) => +type Endpoint21_0Request = Parameters[0] +type Endpoint21_0Input = { + readonly model: Endpoint21_0Request["payload"]["model"] + readonly messages: Endpoint21_0Request["payload"]["messages"] + readonly tools?: Endpoint21_0Request["payload"]["tools"] + readonly tool_choice?: Endpoint21_0Request["payload"]["tool_choice"] + readonly stream?: Endpoint21_0Request["payload"]["stream"] + readonly max_tokens?: Endpoint21_0Request["payload"]["max_tokens"] + readonly max_completion_tokens?: Endpoint21_0Request["payload"]["max_completion_tokens"] + readonly temperature?: Endpoint21_0Request["payload"]["temperature"] + readonly top_p?: Endpoint21_0Request["payload"]["top_p"] + readonly stop?: Endpoint21_0Request["payload"]["stop"] + readonly seed?: Endpoint21_0Request["payload"]["seed"] + readonly frequency_penalty?: Endpoint21_0Request["payload"]["frequency_penalty"] + readonly presence_penalty?: Endpoint21_0Request["payload"]["presence_penalty"] + readonly reasoning_effort?: Endpoint21_0Request["payload"]["reasoning_effort"] + readonly user?: Endpoint21_0Request["payload"]["user"] +} +const Endpoint21_0 = (raw: RawClient["server.chat"]) => (input: Endpoint21_0Input) => raw["chat.completions"]({ payload: { model: input["model"], @@ -788,7 +795,7 @@ const Endpoint20_0 = (raw: RawClient["server.chat"]) => (input: Endpoint20_0Inpu }, }).pipe(Effect.mapError(mapClientError)) -const adaptGroup20 = (raw: RawClient["server.chat"]) => ({ completions: Endpoint20_0(raw) }) +const adaptGroup21 = (raw: RawClient["server.chat"]) => ({ completions: Endpoint21_0(raw) }) const adaptClient = (raw: RawClient) => ({ health: adaptGroup0(raw["server.health"]), @@ -799,19 +806,20 @@ const adaptClient = (raw: RawClient) => ({ models: adaptGroup5(raw["server.model"]), providers: adaptGroup6(raw["server.provider"]), "server.variant": adaptGroup7(raw["server.variant"]), - integrations: adaptGroup8(raw["server.integration"]), - credentials: adaptGroup9(raw["server.credential"]), - permissions: adaptGroup10(raw["server.permission"]), - files: adaptGroup11(raw["server.fs"]), - commands: adaptGroup12(raw["server.command"]), - skills: adaptGroup13(raw["server.skill"]), - events: adaptGroup14(raw["server.event"]), - ptys: adaptGroup15(raw["server.pty"]), - questions: adaptGroup16(raw["server.question"]), - browserRequests: adaptGroup17(raw["server.browser"]), - references: adaptGroup18(raw["server.reference"]), - projectCopies: adaptGroup19(raw["server.projectCopy"]), - "server.chat": adaptGroup20(raw["server.chat"]), + "server.insights": adaptGroup8(raw["server.insights"]), + integrations: adaptGroup9(raw["server.integration"]), + credentials: adaptGroup10(raw["server.credential"]), + permissions: adaptGroup11(raw["server.permission"]), + files: adaptGroup12(raw["server.fs"]), + commands: adaptGroup13(raw["server.command"]), + skills: adaptGroup14(raw["server.skill"]), + events: adaptGroup15(raw["server.event"]), + ptys: adaptGroup16(raw["server.pty"]), + questions: adaptGroup17(raw["server.question"]), + browserRequests: adaptGroup18(raw["server.browser"]), + references: adaptGroup19(raw["server.reference"]), + projectCopies: adaptGroup20(raw["server.projectCopy"]), + "server.chat": adaptGroup21(raw["server.chat"]), }) export const make = (options?: { readonly baseUrl?: URL | string }) => diff --git a/packages/client/src/generated/client.ts b/packages/client/src/generated/client.ts index 860f1fa632..9b138f3281 100644 --- a/packages/client/src/generated/client.ts +++ b/packages/client/src/generated/client.ts @@ -49,6 +49,8 @@ import type { ServerVariantParaphraseOutput, ServerVariantCompareInput, ServerVariantCompareOutput, + ServerInsightsSessionsInput, + ServerInsightsSessionsOutput, IntegrationsListInput, IntegrationsListOutput, IntegrationsGetInput, @@ -587,6 +589,20 @@ export function make(options: ClientOptions) { requestOptions, ), }, + "server.insights": { + sessions: (input: ServerInsightsSessionsInput, requestOptions?: RequestOptions) => + request( + { + method: "POST", + path: `/api/insights/sessions`, + body: { sessions: input["sessions"] }, + successStatus: 200, + declaredStatuses: [400, 401, 404, 503], + empty: false, + }, + requestOptions, + ), + }, integrations: { list: (input?: IntegrationsListInput, requestOptions?: RequestOptions) => request( diff --git a/packages/client/src/generated/types.ts b/packages/client/src/generated/types.ts index 09fcd1fc85..cbaaf147c2 100644 --- a/packages/client/src/generated/types.ts +++ b/packages/client/src/generated/types.ts @@ -2135,6 +2135,16 @@ export type ServerVariantCompareOutput = { readonly totalCostUsd: number } +export type ServerInsightsSessionsInput = { + readonly sessions: { readonly sessions: ReadonlyArray<{ readonly [x: string]: unknown }> }["sessions"] +} + +export type ServerInsightsSessionsOutput = { + readonly accepted: number + readonly updated: number + readonly rejected: ReadonlyArray<{ readonly externalId: string; readonly reason: string }> +} + export type IntegrationsListInput = { readonly location?: { readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined diff --git a/packages/core/src/insights.ts b/packages/core/src/insights.ts new file mode 100644 index 0000000000..3a7cd72545 --- /dev/null +++ b/packages/core/src/insights.ts @@ -0,0 +1,92 @@ +export * as Insights from "./insights" + +import { Effect, Schema } from "effect" +import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http" + +import { Insights as Wire } from "@redrob-code/schema/insights" + +import { ConsoleKey } from "./console-key" +import { CONSOLE_URL } from "./plugin/provider/redrob-constants" + +/** + * Sends an app's labeled sessions to the console's insights, with the Redrob key this engine holds. + * + * The point is custody: the app hands over labels and gets back what the console did with them, and the + * key never leaves the engine. So nothing here returns the key, logs it, or takes a destination from the + * caller -- the batch goes to `${CONSOLE_URL}/insights/sessions` and nowhere else, `CONSOLE_URL` being the + * one constant every console call in this engine uses (its developer override included). + * + * No retries: an app sends from a queue on its own schedule, and keeps a batch that got no answer for its + * next run. A second retry loop here would only hide from the app that the console was unreachable. + */ + +const REQUEST_TIMEOUT = "30 seconds" + +export class NotConnected extends Error { + readonly _tag = "InsightsNotConnected" + constructor() { + super("the Redrob provider is not connected, so there is no key to send insights with") + } +} + +export class Refused extends Error { + readonly _tag = "InsightsRefused" + constructor( + readonly status: number, + message: string, + ) { + super(message) + } +} + +/** + * The console's error body, read for its message because that is what a person can act on. NestJS answers + * a validation failure with `message` as a list of strings, so both spellings are read. + */ +const ErrorEnvelope = Schema.Struct({ + message: Schema.Union([Schema.String, Schema.Array(Schema.String)]).pipe(Schema.optional), + error: Schema.Union([Schema.String, Schema.Struct({ message: Schema.String.pipe(Schema.optional) })]).pipe( + Schema.optional, + ), +}) + +function describe(status: number, body: string): string { + const fallback = `the console refused the insights batch with ${status}` + const parsed = Schema.decodeUnknownOption(Schema.fromJsonString(ErrorEnvelope))(body) + if (parsed._tag === "None") return fallback + const { message, error } = parsed.value + if (Array.isArray(message)) return message.join("; ") || fallback + if (typeof message === "string" && message) return message + if (typeof error === "object" && error !== null && typeof error.message === "string" && error.message) { + return error.message + } + return fallback +} + +/** The call, with the HTTP client left to the caller so a test can stand in for the console. */ +export const send = Effect.fn("Insights.send")(function* (request: Wire.SessionsRequest) { + const apiKey = yield* ConsoleKey.resolve() + if (!apiKey) return yield* Effect.fail(new NotConnected()) + + const http = yield* HttpClient.HttpClient + const outgoing = yield* HttpClientRequest.post(`${CONSOLE_URL}/insights/sessions`).pipe( + HttpClientRequest.bearerToken(apiKey), + HttpClientRequest.schemaBodyJson(Wire.SessionsRequest)(request), + ) + const response = yield* http.execute(outgoing).pipe(Effect.timeout(REQUEST_TIMEOUT)) + const body = yield* response.text + + if (response.status < 200 || response.status >= 300) { + return yield* Effect.fail(new Refused(response.status, describe(response.status, body))) + } + const decoded = Schema.decodeUnknownOption(Schema.fromJsonString(Wire.SessionsResult))(body) + if (decoded._tag === "None") + return yield* Effect.fail(new Refused(response.status, "could not read the console's answer")) + return decoded.value +}) + +/* + The fetch client is provided here, as in variants.ts, so the HTTP client requirement does not leak into + the API's requirement type. One call per app sync, every few minutes, needs no shared pool. +*/ +export const sessions = (request: Wire.SessionsRequest) => Effect.provide(send(request), FetchHttpClient.layer) diff --git a/packages/core/src/plugin/host.ts b/packages/core/src/plugin/host.ts index 8a1f3437d3..677f40c087 100644 --- a/packages/core/src/plugin/host.ts +++ b/packages/core/src/plugin/host.ts @@ -211,7 +211,7 @@ export const make = Effect.fn("PluginHost.make")(function* (plugin: PluginV2.Int skill.transform((draft) => callback({ source: (source) => draft.source(Schema.decodeUnknownSync(SkillV2.Source)(source)), - list: draft.list, + list: () => mutable(draft.list()), }), ), }, diff --git a/packages/core/src/plugin/skill.ts b/packages/core/src/plugin/skill.ts index 6d23dabcf7..c305edff7f 100644 --- a/packages/core/src/plugin/skill.ts +++ b/packages/core/src/plugin/skill.ts @@ -4,7 +4,7 @@ export * as SkillPlugin from "./skill" import { define } from "./internal" import { Effect } from "effect" -import { AbsolutePath } from "../schema" +import { AbsolutePath, type DeepMutable } from "../schema" import { SkillV2 } from "../skill" import customizeRedrobContent from "./skill/customize-redrob.md" with { type: "text" } import documentToolchainContent from "./skill/document-toolchain.md" with { type: "text" } @@ -62,16 +62,7 @@ export const BuiltinSkills: ReadonlyArray = [ "Use when the task is about the page the user is looking at: reading its text, finding nodes by selector, filling a field, clicking, or navigating. Covers the six `page` calls in code mode, what a refusal means, and the round-trip cost. Do not use for fetching a URL the user is not on, which is a plain HTTP request.", location: AbsolutePath.make("/builtin/page-control.md"), autoInject: SkillV2.AutoInject.make({ - keywords: [ - "this page", - "current page", - "on screen", - "the tab", - "click the", - "fill in", - "selector", - "scrape", - ], + keywords: ["this page", "current page", "on screen", "the tab", "click the", "fill in", "selector", "scrape"], }), content: PageControlContent, }), @@ -91,7 +82,8 @@ export const Plugin = define({ effect: Effect.fn(function* (ctx) { yield* ctx.skill.transform((draft) => { for (const skill of BuiltinSkills) { - draft.source(SkillV2.EmbeddedSource.make({ type: "embedded", skill })) + // The plugin API takes the SDK's generated type, which spells arrays mutable; the host decodes it. + draft.source(SkillV2.EmbeddedSource.make({ type: "embedded", skill }) as DeepMutable) } }) }), diff --git a/packages/core/test/config/skill.test.ts b/packages/core/test/config/skill.test.ts index 3c159c9178..ad62c09820 100644 --- a/packages/core/test/config/skill.test.ts +++ b/packages/core/test/config/skill.test.ts @@ -10,6 +10,8 @@ import { SkillV2 } from "@redrob-code/core/skill" import { location } from "../fixture/location" import { testEffect } from "../lib/effect" import { host } from "../plugin/host" +import type { PluginContext } from "@redrob-code/plugin/v2/effect" +import type { SkillV2Source } from "@redrob-labs/sdk/v2/types" const it = testEffect(Layer.empty) const decode = Schema.decodeUnknownSync(Config.Info) @@ -18,8 +20,9 @@ describe("ConfigSkillPlugin.Plugin", () => { it.effect("registers configured skill directories and URLs", () => Effect.gen(function* () { const directory = AbsolutePath.make("/repo/packages/app") - const sources: SkillV2.Source[] = [] - const transform = Effect.fnUntraced(function* (update: (draft: SkillV2.Draft) => void | Effect.Effect) { + // Typed as the plugin API sees them (the SDK's generated types), not as core's schema does. + const sources: SkillV2Source[] = [] + const transform = Effect.fnUntraced(function* (update: Parameters[0]) { const result = update({ source: (source) => { sources.push(source) diff --git a/packages/core/test/insights.test.ts b/packages/core/test/insights.test.ts new file mode 100644 index 0000000000..c9df25d674 --- /dev/null +++ b/packages/core/test/insights.test.ts @@ -0,0 +1,107 @@ +import { describe, expect } from "bun:test" +import { Effect, Exit } from "effect" +import { HttpClient, HttpClientResponse } from "effect/unstable/http" +import { Credential } from "@redrob-code/core/credential" +import { AppNodeBuilder } from "@redrob-code/core/effect/app-node-builder" +import { LayerNode } from "@redrob-code/core/effect/layer-node" +import { EventV2 } from "@redrob-code/core/event" +import { Insights } from "@redrob-code/core/insights" +import { Integration } from "@redrob-code/core/integration" +import { testEffect } from "./lib/effect" + +/** + * Sending an app's labeled sessions with the key this engine holds. + * + * The console is a stand-in HttpClient that records what it was sent, so these assert the custody rule + * directly: the key goes in the Authorization header of a request to the console's fixed insights URL, + * and appears nowhere in what the caller gets back. + */ +const it = testEffect(AppNodeBuilder.build(LayerNode.group([Integration.node, Credential.node, EventV2.node]))) + +const KEY = "rrk_test_engine_held" +const SESSION = { externalId: "of_0123", startedAt: "2026-10-08T02:42:00Z", toolKey: "office", mode: 2 } + +type Seen = { url: string; authorization: string | undefined; body: unknown } + +function fakeConsole(status: number, body: unknown, seen: Seen[]) { + return HttpClient.make((request) => + Effect.gen(function* () { + const sent = request.body._tag === "Uint8Array" ? JSON.parse(new TextDecoder().decode(request.body.body)) : null + seen.push({ url: request.url, authorization: request.headers["authorization"], body: sent }) + return HttpClientResponse.fromWeb(request, Response.json(body, { status })) + }), + ) +} + +const connectRedrob = Effect.gen(function* () { + const integrations = yield* Integration.Service + const integrationID = Integration.ID.make("redrob") + yield* integrations.transform((editor) => + editor.method.update({ integrationID, method: { type: "key", label: "Redrob API key" } }), + ) + yield* integrations.connection.key({ integrationID, key: KEY, label: "Redrob" }) +}) + +describe("Insights", () => { + it.effect("posts the batch to the console's insights with the stored key, and returns only the counts", () => + Effect.gen(function* () { + yield* connectRedrob + const seen: Seen[] = [] + const result = yield* Insights.send({ sessions: [SESSION] }).pipe( + Effect.provideService(HttpClient.HttpClient, fakeConsole(200, { accepted: 1, updated: 0, rejected: [] }, seen)), + ) + expect(result).toEqual({ accepted: 1, updated: 0, rejected: [] }) + expect(seen).toEqual([ + { + url: "https://console.redrob.ai/api/backend/v1/insights/sessions", + authorization: `Bearer ${KEY}`, + body: { sessions: [SESSION] }, + }, + ]) + expect(JSON.stringify(result)).not.toContain(KEY) + }), + ) + + it.effect("passes the console's per-session rejections through", () => + Effect.gen(function* () { + yield* connectRedrob + const rejected = [{ externalId: "of_0123", reason: "taskKey is not a task of actionKey" }] + const result = yield* Insights.send({ sessions: [SESSION] }).pipe( + Effect.provideService(HttpClient.HttpClient, fakeConsole(200, { accepted: 0, updated: 0, rejected }, [])), + ) + expect(result.rejected).toEqual(rejected) + }), + ) + + it.effect("refuses without a key, and never calls the console", () => + Effect.gen(function* () { + const seen: Seen[] = [] + const exit = yield* Insights.send({ sessions: [SESSION] }).pipe( + Effect.provideService(HttpClient.HttpClient, fakeConsole(200, {}, seen)), + Effect.exit, + ) + expect(Exit.isFailure(exit) && String(exit.cause)).toContain("not connected") + expect(seen).toEqual([]) + }), + ) + + it.effect("carries the console's refusal and its message, NestJS list form included", () => + Effect.gen(function* () { + yield* connectRedrob + const exit = yield* Insights.send({ sessions: [SESSION] }).pipe( + Effect.provideService( + HttpClient.HttpClient, + fakeConsole( + 400, + { statusCode: 400, message: ["sessions.0.summary is not a field"], error: "Bad Request" }, + [], + ), + ), + Effect.flip, + ) + expect(exit).toBeInstanceOf(Insights.Refused) + if (!(exit instanceof Insights.Refused)) return + expect([exit.status, exit.message]).toEqual([400, "sessions.0.summary is not a field"]) + }), + ) +}) diff --git a/packages/core/test/plugin/skill.test.ts b/packages/core/test/plugin/skill.test.ts index c165376a26..8099ca8f1c 100644 --- a/packages/core/test/plugin/skill.test.ts +++ b/packages/core/test/plugin/skill.test.ts @@ -4,6 +4,7 @@ import { AppNodeBuilder } from "@redrob-code/core/effect/app-node-builder" import { SkillPlugin } from "@redrob-code/core/plugin/skill" import { SkillV2 } from "@redrob-code/core/skill" import { testEffect } from "../lib/effect" +import type { PluginContext } from "@redrob-code/plugin/v2/effect" import { host } from "./host" const it = testEffect(AppNodeBuilder.build(SkillV2.node)) @@ -12,7 +13,13 @@ describe("SkillPlugin.Plugin", () => { it.effect("registers the built-in customize-redrob skill", () => Effect.gen(function* () { const skill = yield* SkillV2.Service - yield* SkillPlugin.Plugin.effect(host({ skill: { ...skill, reload: skill.reload } })) + yield* SkillPlugin.Plugin.effect( + host({ + // Core's service as the plugin API: the same shape, but core spells arrays readonly and the SDK's + // generated types do not. The real host (src/plugin/host.ts) converts; this test hands it straight in. + skill: { ...skill, reload: skill.reload } as unknown as PluginContext["skill"], + }), + ) expect(yield* skill.list()).toContainEqual( expect.objectContaining({ diff --git a/packages/protocol/src/api.ts b/packages/protocol/src/api.ts index 43b1e267de..9a57f29e53 100644 --- a/packages/protocol/src/api.ts +++ b/packages/protocol/src/api.ts @@ -5,6 +5,7 @@ import { MessageGroup } from "./groups/message" import { ModelGroup } from "./groups/model" import { ProviderGroup } from "./groups/provider" import { VariantGroup } from "./groups/variant" +import { InsightsGroup } from "./groups/insights" import { makeSessionGroup } from "./groups/session" import { makePermissionGroup } from "./groups/permission" import { FileSystemGroup } from "./groups/fs" @@ -46,6 +47,7 @@ const makeApiFromGroup = < .add(ModelGroup.middleware(locationMiddleware)) .add(ProviderGroup.middleware(locationMiddleware)) .add(VariantGroup.middleware(locationMiddleware)) + .add(InsightsGroup.middleware(locationMiddleware)) .add(IntegrationGroup.middleware(locationMiddleware)) .add(CredentialGroup.middleware(locationMiddleware)) .add(makePermissionGroup(locationMiddleware, sessionLocationMiddleware)) diff --git a/packages/protocol/src/groups/insights.ts b/packages/protocol/src/groups/insights.ts new file mode 100644 index 0000000000..e1f1838c95 --- /dev/null +++ b/packages/protocol/src/groups/insights.ts @@ -0,0 +1,36 @@ +import { Insights } from "@redrob-code/schema/insights" +import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi" +import { InvalidRequestError, ProviderNotFoundError, ServiceUnavailableError, UnauthorizedError } from "../errors" + +/** + * Sending labeled AI work sessions to the Redrob console's insights. + * + * For an app that holds no credential of its own: it hands the engine the labels, the engine posts them + * with the Redrob key it holds, and the app gets back what the console did with them. The key is never + * returned and the destination is fixed, so this route cannot be used to read the key or to send it + * anywhere but the console. + * + * `ProviderNotFoundError` when the Redrob provider is not connected, as for the variants routes: the + * request was fine, there is just no key here to send it with. + */ +export const InsightsGroup = HttpApiGroup.make("server.insights") + .add( + HttpApiEndpoint.post("insights.sessions", "/api/insights/sessions", { + payload: Insights.SessionsRequest, + success: Insights.SessionsResult, + error: [InvalidRequestError, UnauthorizedError, ProviderNotFoundError, ServiceUnavailableError], + }).annotateMerge( + OpenApi.annotations({ + identifier: "v2.insights.sessions", + summary: "Send labeled sessions to the console", + description: + "Post up to 500 labeled AI work sessions to the Redrob console's insights with the Redrob key this engine holds, and get back how many were accepted, updated and rejected.", + }), + ), + ) + .annotateMerge( + OpenApi.annotations({ + title: "insights", + description: "Labeled AI work sessions for the Redrob console. Available while the Redrob provider is connected.", + }), + ) diff --git a/packages/redrob/src/redrob/transcription.ts b/packages/redrob/src/redrob/transcription.ts new file mode 100644 index 0000000000..0273e80a73 --- /dev/null +++ b/packages/redrob/src/redrob/transcription.ts @@ -0,0 +1,163 @@ +import { Effect, Schema } from "effect" +import { HttpClient, HttpClientRequest } from "effect/unstable/http" +import { Auth } from "@/auth" +import { gatewayMessage, gatewayUrl, redrobKey } from "@/tool/image_generate" + +/** + * Transcription through the Redrob gateway's `POST /v1/audio/transcriptions`, on the engine's own + * Redrob credential, for the reason speech gives: the key is the engine's and stays here. Its caller + * is the engine's `POST /redrob/transcribe` route, which is how Redrob Cowork's push-to-talk turns a + * recording into text without the app ever holding the key. + * + * Everything that can be refused is refused before anything is sent, so a bad request costs nothing. + */ + +/** Scribe handles Korean, English and the two mixed in one sentence, which is how users speak. */ +export const DEFAULT_TRANSCRIPTION_MODEL = "elevenlabs/scribe-v2" + +/** The formats the gateway accepts, which are the ones its upstream documents. */ +export const TRANSCRIPTION_FORMATS = ["wav", "mp3", "flac", "m4a", "ogg", "webm", "aac"] as const +export type TranscriptionFormat = (typeof TRANSCRIPTION_FORMATS)[number] + +/** The gateway's limit for one request, decoded, checked here so an over-size clip costs nothing. */ +export const MAX_TRANSCRIPTION_BYTES = 10 * 1024 * 1024 + +const TIMEOUT_MS = 120_000 +const BASE64 = /^[A-Za-z0-9+/]*={0,2}$/ +const LANGUAGE = /^[a-z]{2}$/ + +/** + * Why audio could not be transcribed. `invalid` and `no_key` are found before anything is sent and + * cost nothing; `upstream` and `timeout` are the gateway's. + */ +export class TranscriptionError extends Schema.TaggedErrorClass()("TranscriptionError", { + reason: Schema.Literals(["invalid", "no_key", "upstream", "timeout"]), + message: Schema.String, + status: Schema.optional(Schema.Number), +}) {} + +export type PreparedTranscription = { + audio: string + format: TranscriptionFormat + model: string + language?: string + bytes: number +} + +export type Transcript = { text: string; seconds?: number; costUsd?: number } + +/** What base64 decodes to, without decoding it: three bytes per four characters, less the padding. */ +function decodedBytes(base64: string): number { + const padding = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0 + return (base64.length / 4) * 3 - padding +} + +/** The request as it will be sent, or why it would be refused, with nothing sent either way. */ +export const prepare = Effect.fn("RedrobTranscription.prepare")(function* (input: { + audio: string + format: TranscriptionFormat + model?: string + language?: string +}) { + const audio = input.audio.replace(/\s+/g, "") + if (!audio) return yield* new TranscriptionError({ reason: "invalid", message: "Give the audio to transcribe." }) + if (audio.length % 4 !== 0 || !BASE64.test(audio)) { + return yield* new TranscriptionError({ + reason: "invalid", + message: "The audio must be base64: the raw bytes, not a data URL.", + }) + } + const bytes = decodedBytes(audio) + if (bytes > MAX_TRANSCRIPTION_BYTES) { + return yield* new TranscriptionError({ + reason: "invalid", + message: `The audio is ${bytes} bytes; transcribe at most ${MAX_TRANSCRIPTION_BYTES} per call.`, + }) + } + const language = input.language?.trim().toLowerCase() || undefined + if (language && !LANGUAGE.test(language)) { + return yield* new TranscriptionError({ + reason: "invalid", + message: `"${input.language}" is not an ISO-639-1 language such as "ko" or "en".`, + }) + } + const prepared: PreparedTranscription = { + audio, + format: input.format, + model: input.model?.trim() || DEFAULT_TRANSCRIPTION_MODEL, + ...(language ? { language } : {}), + bytes, + } + return prepared +}) + +/** The engine's Redrob key, or a `no_key` failure, which is found before anything is sent. */ +export const key = Effect.fn("RedrobTranscription.key")(function* (auth: Auth.Interface) { + const found = redrobKey(yield* auth.get("redrob").pipe(Effect.orElseSucceed(() => undefined))) + if (!found) { + return yield* new TranscriptionError({ + reason: "no_key", + message: "Connect Redrob to transcribe speech: no Redrob API key is available.", + }) + } + return found +}) + +const GatewayTranscript = Schema.Struct({ + text: Schema.String, + seconds: Schema.optional(Schema.Number), + costUsd: Schema.optional(Schema.Number), +}) +const decodeTranscript = Schema.decodeUnknownEffect(Schema.fromJsonString(GatewayTranscript)) + +/** One call to the gateway. The answer is checked for being a transcript before anyone reads it. */ +export const request = Effect.fn("RedrobTranscription.request")(function* ( + http: HttpClient.HttpClient, + key: string, + transcription: PreparedTranscription, +) { + const outgoing = yield* HttpClientRequest.post(`${gatewayUrl()}/audio/transcriptions`).pipe( + HttpClientRequest.bearerToken(key), + HttpClientRequest.bodyJson({ + model: transcription.model, + input_audio: { data: transcription.audio, format: transcription.format }, + response_format: "json", + ...(transcription.language ? { language: transcription.language } : {}), + }), + Effect.orDie, + ) + const response = yield* http.execute(outgoing).pipe( + Effect.mapError( + () => new TranscriptionError({ reason: "upstream", message: "The Redrob gateway could not be reached." }), + ), + Effect.timeoutOrElse({ + duration: TIMEOUT_MS, + orElse: () => Effect.fail(new TranscriptionError({ reason: "timeout", message: "Transcription timed out." })), + }), + ) + const body = yield* response.text.pipe( + Effect.mapError( + () => new TranscriptionError({ reason: "upstream", message: "The Redrob gateway's answer was cut off." }), + ), + ) + if (response.status < 200 || response.status >= 300) { + return yield* new TranscriptionError({ + reason: "upstream", + status: response.status, + message: `The Redrob gateway answered ${response.status}: ${gatewayMessage(body)}`, + }) + } + const parsed = yield* decodeTranscript(body).pipe( + Effect.mapError( + () => new TranscriptionError({ reason: "upstream", message: "The Redrob gateway answered without a transcript." }), + ), + ) + const transcript: Transcript = { + text: parsed.text.trim(), + ...(parsed.seconds !== undefined && Number.isFinite(parsed.seconds) ? { seconds: parsed.seconds } : {}), + ...(parsed.costUsd !== undefined && Number.isFinite(parsed.costUsd) ? { costUsd: parsed.costUsd } : {}), + } + return transcript +}) + +export * as RedrobTranscription from "./transcription" diff --git a/packages/redrob/src/server/routes/instance/httpapi/groups/control.ts b/packages/redrob/src/server/routes/instance/httpapi/groups/control.ts index 11c5315093..c3598bcfcb 100644 --- a/packages/redrob/src/server/routes/instance/httpapi/groups/control.ts +++ b/packages/redrob/src/server/routes/instance/httpapi/groups/control.ts @@ -1,9 +1,11 @@ import { Auth } from "@/auth" import { Schema } from "effect" -import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi" +import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi" +import { InvalidRequestError, ServiceUnavailableError, TimeoutError, UpstreamError } from "../errors" import { described } from "./metadata" import { ProviderV2 } from "@redrob-code/core/provider" +import { TRANSCRIPTION_FORMATS } from "@/redrob/transcription" const AuthParams = Schema.Struct({ providerID: ProviderV2.ID, @@ -28,9 +30,36 @@ export const LogInput = Schema.Struct({ }), }) +export const SpeechInput = Schema.Struct({ + text: Schema.String.annotate({ description: "The words to speak, at most 4096 characters" }), + voice: Schema.optional(Schema.String).annotate({ description: "A voice of the chosen model" }), + model: Schema.optional(Schema.String).annotate({ + description: "A speech model id served by the Redrob gateway. Defaults to elevenlabs/eleven-flash-v2.5, for playback.", + }), +}) + +export const TranscribeInput = Schema.Struct({ + audio: Schema.String.annotate({ description: "Base64-encoded audio, the raw bytes rather than a data URL, at most 10 MB" }), + format: Schema.Literals(TRANSCRIPTION_FORMATS).annotate({ description: "The audio's container format" }), + language: Schema.optional(Schema.String).annotate({ + description: 'ISO-639-1 language, e.g. "ko". Detected when omitted.', + }), + model: Schema.optional(Schema.String).annotate({ + description: "A transcription model id served by the Redrob gateway", + }), +}) + +export const TranscribeOutput = Schema.Struct({ + text: Schema.String.annotate({ description: "The transcript, trimmed; empty when nothing was said" }), + seconds: Schema.optional(Schema.Number).annotate({ description: "Seconds of audio billed" }), + costUsd: Schema.optional(Schema.Number).annotate({ description: "What the request cost, in USD" }), +}) + export const ControlPaths = { auth: "/auth/:providerID", log: "/log", + speech: "/redrob/speech", + transcribe: "/redrob/transcribe", } as const export const ControlApi = HttpApi.make("control").add( @@ -59,6 +88,33 @@ export const ControlApi = HttpApi.make("control").add( description: "Remove authentication credentials", }), ), + /* + * Speech on the engine's own Redrob credential, for a client that has to play audio and must + * not hold the key: Redrob Cowork's read-aloud. The key never leaves this process. + */ + HttpApiEndpoint.post("speech", ControlPaths.speech, { + payload: SpeechInput, + success: Schema.Uint8Array.pipe(HttpApiSchema.asUint8Array({ contentType: "audio/mpeg" })), + error: [InvalidRequestError, ServiceUnavailableError, UpstreamError, TimeoutError], + }).annotateMerge( + OpenApi.annotations({ + identifier: "redrob.speech", + summary: "Speak text", + description: "Turn text into mp3 speech through the Redrob gateway, billed to the connected Redrob account.", + }), + ), + /* Transcription on the same credential, for Redrob Cowork's push-to-talk, for the same reason. */ + HttpApiEndpoint.post("transcribe", ControlPaths.transcribe, { + payload: TranscribeInput, + success: described(TranscribeOutput, "The transcript"), + error: [InvalidRequestError, ServiceUnavailableError, UpstreamError, TimeoutError], + }).annotateMerge( + OpenApi.annotations({ + identifier: "redrob.transcribe", + summary: "Transcribe speech", + description: "Turn recorded speech into text through the Redrob gateway, billed to the connected Redrob account.", + }), + ), HttpApiEndpoint.post("log", ControlPaths.log, { query: LogQuery, payload: LogInput, diff --git a/packages/redrob/src/server/routes/instance/httpapi/handlers/control.ts b/packages/redrob/src/server/routes/instance/httpapi/handlers/control.ts index e120749f18..07a2f7079b 100644 --- a/packages/redrob/src/server/routes/instance/httpapi/handlers/control.ts +++ b/packages/redrob/src/server/routes/instance/httpapi/handlers/control.ts @@ -3,12 +3,49 @@ import { Auth } from "@/auth" import { Effect } from "effect" import { HttpApiBuilder } from "effect/unstable/httpapi" import { RootHttpApi } from "../api" -import { LogInput } from "../groups/control" +import { LogInput, SpeechInput, TranscribeInput } from "../groups/control" +import { RedrobTranscription, type TranscriptionError } from "@/redrob/transcription" +import { InvalidRequestError, ServiceUnavailableError, TimeoutError, UpstreamError } from "../errors" +import { PLAYBACK_DEFAULTS, prepareSpeech, requestSpeech, speechKey, type SpeechError } from "@/tool/speech_generate" +import { HttpClient } from "effect/unstable/http" import { ProviderV2 } from "@redrob-code/core/provider" export const controlHandlers = HttpApiBuilder.group(RootHttpApi, "control", (handlers) => Effect.gen(function* () { const auth = yield* Auth.Service + const http = yield* HttpClient.HttpClient + + /** + * Each gateway failure as the endpoints declare it; no_key is 503 because the engine, not the + * caller, lacks it. Speech and transcription fail for the same four reasons. + */ + const gatewayFailure = (operation: string) => (error: SpeechError | TranscriptionError) => + error.reason === "invalid" + ? new InvalidRequestError({ message: error.message }) + : error.reason === "no_key" + ? new ServiceUnavailableError({ message: error.message, service: "redrob" }) + : error.reason === "timeout" + ? new TimeoutError({ message: error.message, operation }) + : new UpstreamError({ + message: error.message, + service: "redrob", + ...(error.status ? { status: error.status } : {}), + }) + + const speech = Effect.fn("ControlHttpApi.speech")(function* (ctx: { payload: typeof SpeechInput.Type }) { + // This route is for audio that is played at once, so it defaults to the fast playback model. + const prepared = yield* prepareSpeech(ctx.payload, PLAYBACK_DEFAULTS) + const key = yield* speechKey(auth) + return (yield* requestSpeech(http, key, prepared)).audio + }, Effect.mapError(gatewayFailure("speech"))) + + const transcribe = Effect.fn("ControlHttpApi.transcribe")(function* (ctx: { + payload: typeof TranscribeInput.Type + }) { + const prepared = yield* RedrobTranscription.prepare(ctx.payload) + const key = yield* RedrobTranscription.key(auth) + return yield* RedrobTranscription.request(http, key, prepared) + }, Effect.mapError(gatewayFailure("transcribe"))) const authSet = Effect.fn("ControlHttpApi.authSet")(function* (ctx: { params: { providerID: ProviderV2.ID } @@ -38,6 +75,11 @@ export const controlHandlers = HttpApiBuilder.group(RootHttpApi, "control", (han return true }) - return handlers.handle("authSet", authSet).handle("authRemove", authRemove).handle("log", log) + return handlers + .handle("authSet", authSet) + .handle("authRemove", authRemove) + .handle("speech", speech) + .handle("transcribe", transcribe) + .handle("log", log) }), ) diff --git a/packages/redrob/src/server/routes/instance/httpapi/server.ts b/packages/redrob/src/server/routes/instance/httpapi/server.ts index f2fe99aaa5..43de9d3992 100644 --- a/packages/redrob/src/server/routes/instance/httpapi/server.ts +++ b/packages/redrob/src/server/routes/instance/httpapi/server.ts @@ -53,7 +53,7 @@ import { MoveSession } from "@redrob-code/core/control-plane/move-session" import { Database } from "@redrob-code/core/database/database" import { AppNodeBuilderV1 } from "@/effect/app-node-builder-v1" import { LayerNode } from "@redrob-code/core/effect/layer-node" -import { httpClient } from "@redrob-code/core/effect/app-node-platform" +import { httpClient, llmClient } from "@redrob-code/core/effect/app-node-platform" import { EventV2 } from "@redrob-code/core/event" import { ModelsDev } from "@redrob-code/core/models-dev" import { Npm } from "@redrob-code/core/npm" @@ -249,6 +249,9 @@ const app = LayerNode.group([ SessionShare.node, InstanceStore.node, httpClient, + // /v1/chat/completions calls LLM.generate / LLM.stream, which need the client; without it every + // request answered 500 "Service not found: @redrob/LLMClient". + llmClient, EventV2.node, ProjectV2.node, ProjectCopy.node, diff --git a/packages/redrob/src/tool/image_generate.ts b/packages/redrob/src/tool/image_generate.ts new file mode 100644 index 0000000000..0a90056d17 --- /dev/null +++ b/packages/redrob/src/tool/image_generate.ts @@ -0,0 +1,272 @@ +import { Effect, Schema } from "effect" +import { HttpClient, HttpClientRequest } from "effect/unstable/http" +import * as path from "path" +import * as Tool from "./tool" +import DESCRIPTION from "./image_generate.txt" +import { Auth } from "@/auth" +import { EventV2Bridge } from "@/event-v2-bridge" +import { InstanceState } from "@/effect/instance-state" +import { FileSystem } from "@redrob-code/core/filesystem" +import { Watcher } from "@redrob-code/core/filesystem/watcher" +import { FSUtil } from "@redrob-code/core/fs-util" +import { CONSOLE_URL } from "@redrob-code/core/plugin/provider/redrob-constants" +import { assertExternalDirectoryEffect } from "./external-directory" +import { sniffAttachmentMime } from "@/util/media" + +/** + * Image generation through the Redrob gateway, on the Redrob credential this engine already holds. + * + * A built-in rather than a plugin tool because the credential is the engine's: it lives in the auth + * store (or `REDROB_API_KEY`), the desktop app never reads it, and no plugin API hands it out. Calling + * the gateway from here keeps the key where it is and bills the image to the same account as the chat. + * + * The gateway relays an image model's pictures in OpenRouter's shape, `choices[0].message.images`, + * when asked with `modalities: ["image", "text"]`. The picture is written under `artifacts/` and also + * returned as an attachment, which is what puts it inline in the conversation and in front of the model. + */ + +/** A good, mid-priced default. Any image-output model the gateway serves can be named instead. */ +export const DEFAULT_IMAGE_MODEL = "google/gemini-2.5-flash-image" + +/** + * The gateway, read per call. `REDROB_CONSOLE_URL` is the same developer seam `CONSOLE_URL` honours + * (never set in a shipped build); reading it here rather than only at module load is what lets a test + * point one call at a stand-in without depending on which module loaded first. + */ +export function gatewayUrl(): string { + return (process.env["REDROB_CONSOLE_URL"] ?? CONSOLE_URL).replace(/\/+$/, "") +} + +const TIMEOUT_MS = 180_000 +/** A handful, which is what the image models take; each one is billed as image input. */ +const MAX_REFERENCES = 4 +const MAX_IMAGE_BYTES = 20 * 1024 * 1024 +const MAX_REFERENCE_BYTES = 10 * 1024 * 1024 + +const EXTENSIONS: Record = { + "image/png": "png", + "image/jpeg": "jpg", + "image/webp": "webp", + "image/gif": "gif", +} + +export const Parameters = Schema.Struct({ + prompt: Schema.String.annotate({ description: "A full visual description of the image to generate" }), + filename: Schema.optional(Schema.String).annotate({ + description: "Optional file name without an extension. Derived from the prompt when omitted.", + }), + model: Schema.optional(Schema.String).annotate({ + description: `Optional image model id served by the Redrob gateway. Defaults to ${DEFAULT_IMAGE_MODEL}.`, + }), + references: Schema.optional(Schema.Array(Schema.String)).annotate({ + description: `Optional paths of up to ${MAX_REFERENCES} images in the project to edit or to use as a reference (PNG, JPEG, WebP, or GIF). To edit an image, pass it here and describe the change in the prompt.`, + }), +}) + +const GatewayResponse = Schema.Struct({ + choices: Schema.Array( + Schema.Struct({ + message: Schema.Struct({ + content: Schema.optional(Schema.NullOr(Schema.String)), + images: Schema.optional(Schema.Array(Schema.Struct({ image_url: Schema.Struct({ url: Schema.String }) }))), + }), + }), + ), + redrob: Schema.optional(Schema.Struct({ costUsd: Schema.optional(Schema.Number) })), +}) + +const decodeResponse = Schema.decodeUnknownEffect(Schema.fromJsonString(GatewayResponse)) + +/** The Redrob key: the engine's stored credential first, then the environment, as the provider resolves it. */ +export function redrobKey(stored: Auth.Info | undefined): string | undefined { + if (stored?.type === "api" && stored.key.trim()) return stored.key.trim() + return process.env.REDROB_API_KEY?.trim() || undefined +} + +/** A file-name stem from free text: lower case, ASCII letters and digits, at most 48 characters. */ +export function slug(value: string): string { + const stem = value + .normalize("NFKD") + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-+|-+$/g, "") + .slice(0, 48) + .replace(/-+$/, "") + return stem || "image" +} + +/** A data URL's type and bytes, or undefined when it is not an inline image of a type we write. */ +export function decodeImageDataUrl(url: string): { mime: string; bytes: Uint8Array } | undefined { + const match = /^data:(image\/[a-z+.-]+);base64,([A-Za-z0-9+/=\s]+)$/i.exec(url) + if (!match) return undefined + const mime = match[1].toLowerCase() + if (!EXTENSIONS[mime]) return undefined + const bytes = Uint8Array.from(Buffer.from(match[2], "base64")) + if (bytes.byteLength === 0 || bytes.byteLength > MAX_IMAGE_BYTES) return undefined + return { mime, bytes } +} + +export const ImageGenerateTool = Tool.define( + "image_generate", + Effect.gen(function* () { + const http = yield* HttpClient.HttpClient + + const auth = yield* Auth.Service + const fs = yield* FSUtil.Service + const events = yield* EventV2Bridge.Service + + /** + * The reference images, read and checked before anything is spent: in the project (or approved + * outside it, as for any read), an image of a type the models take, and not too large to send. + */ + const readReferences = Effect.fn("ImageGenerateTool.readReferences")(function* ( + paths: readonly string[], + directory: string, + ctx: Tool.Context, + ) { + if (paths.length > MAX_REFERENCES) throw new Error(`Pass at most ${MAX_REFERENCES} reference images.`) + const references: { path: string; url: string }[] = [] + for (const given of paths) { + const filepath = path.isAbsolute(given) ? given : path.join(directory, given) + /* Asked before the file is opened, the same as any read outside the project. */ + yield* assertExternalDirectoryEffect(ctx, filepath) + const bytes = yield* fs.readFile(filepath).pipe(Effect.orElseSucceed(() => undefined)) + if (!bytes) throw new Error(`Reference image not found: ${given}`) + const mime = sniffAttachmentMime(bytes, "application/octet-stream") + if (!EXTENSIONS[mime]) throw new Error(`Not a PNG, JPEG, WebP, or GIF image: ${given}`) + if (bytes.byteLength > MAX_REFERENCE_BYTES) + throw new Error(`Reference image is over ${MAX_REFERENCE_BYTES / (1024 * 1024)} MB: ${given}`) + references.push({ path: filepath, url: `data:${mime};base64,${Buffer.from(bytes).toString("base64")}` }) + } + return references + }) + + return { + description: DESCRIPTION, + parameters: Parameters, + execute: (params: Schema.Schema.Type, ctx: Tool.Context) => + Effect.gen(function* () { + const prompt = params.prompt.trim() + if (!prompt) throw new Error("Describe the image to generate.") + const key = redrobKey(yield* auth.get("redrob").pipe(Effect.orElseSucceed(() => undefined))) + if (!key) throw new Error("Connect Redrob to generate images: no Redrob API key is available.") + const model = params.model?.trim() || DEFAULT_IMAGE_MODEL + + const instance = yield* InstanceState.context + const references = yield* readReferences(params.references ?? [], instance.directory, ctx) + const directory = path.join(instance.directory, "artifacts") + const stem = slug(params.filename?.trim() || prompt) + + /* + * The path is chosen before anything is spent, so the request is refused for free where a file + * cannot be written. Asked as `edit`, like `write`, because writing a file is what this does: + * plan mode, which denies edits, denies this too. + */ + const extension = "png" + let filepath = path.join(directory, `${stem}.${extension}`) + for (let n = 2; yield* fs.existsSafe(filepath); n += 1) { + filepath = path.join(directory, `${stem}-${n}.${extension}`) + } + yield* assertExternalDirectoryEffect(ctx, filepath) + yield* ctx.ask({ + permission: "edit", + patterns: [path.relative(instance.worktree, filepath)], + always: ["*"], + metadata: { filepath, prompt, model }, + }) + + const request = yield* HttpClientRequest.post(`${gatewayUrl()}/chat/completions`).pipe( + HttpClientRequest.bearerToken(key), + HttpClientRequest.acceptJson, + HttpClientRequest.bodyJson({ + model, + /* + * Text first, then the images, which is the order every vendor documents. A plain string + * when there are none, so a text-only request is exactly what it was. + */ + messages: [ + { + role: "user", + content: references.length + ? [ + { type: "text", text: prompt }, + ...references.map((reference) => ({ type: "image_url", image_url: { url: reference.url } })), + ] + : prompt, + }, + ], + modalities: ["image", "text"], + }), + ) + const response = yield* http.execute(request).pipe( + Effect.timeoutOrElse({ + duration: TIMEOUT_MS, + orElse: () => Effect.die(new Error("Image generation timed out")), + }), + ) + const body = yield* response.text + if (response.status < 200 || response.status >= 300) { + throw new Error(`The Redrob gateway answered ${response.status}: ${gatewayMessage(body)}`) + } + const payload = yield* decodeResponse(body) + const message = payload.choices[0]?.message + const image = (message?.images ?? []).map((item) => decodeImageDataUrl(item.image_url.url)).find(Boolean) + if (!image) { + const said = message?.content?.trim() + throw new Error(`${model} returned no image${said ? `. It said: ${said.slice(0, 500)}` : "."}`) + } + + /* A model that answered in another format keeps the chosen name with the right extension. */ + if (EXTENSIONS[image.mime] !== extension) { + const base = filepath.slice(0, -extension.length - 1) + filepath = `${base}.${EXTENSIONS[image.mime]}` + for (let n = 2; yield* fs.existsSafe(filepath); n += 1) { + filepath = `${base}-${n}.${EXTENSIONS[image.mime]}` + } + } + yield* fs.writeWithDirs(filepath, image.bytes) + yield* events.publish(FileSystem.Event.Edited, { file: filepath }) + yield* events.publish(Watcher.Event.Updated, { file: filepath, event: "add" }) + + const relative = path.relative(instance.worktree, filepath) + const costUsd = payload.redrob?.costUsd + const caption = message?.content?.trim() + return { + title: relative, + output: [`Generated ${relative} with ${model}.`, caption ? `The model said: ${caption}` : undefined] + .filter(Boolean) + .join("\n"), + metadata: { + filepath, + model, + ...(references.length ? { references: references.map((reference) => reference.path) } : {}), + ...(costUsd === undefined ? {} : { costUsd }), + }, + attachments: [ + { + type: "file" as const, + mime: image.mime, + filename: path.basename(filepath), + url: `data:${image.mime};base64,${Buffer.from(image.bytes).toString("base64")}`, + }, + ], + } + }).pipe(Effect.orDie), + } + }), +) + +/** The gateway's error message, from OpenAI's envelope or Nest's, without echoing a whole body. */ +export function gatewayMessage(body: string): string { + try { + const parsed: unknown = JSON.parse(body) + if (parsed && typeof parsed === "object") { + const error = "error" in parsed ? parsed.error : undefined + if (error && typeof error === "object" && "message" in error && typeof error.message === "string") { + return error.message + } + if ("message" in parsed && typeof parsed.message === "string") return parsed.message + } + } catch {} + return body.slice(0, 200) || "no details" +} diff --git a/packages/redrob/src/tool/image_generate.txt b/packages/redrob/src/tool/image_generate.txt new file mode 100644 index 0000000000..24691b8baa --- /dev/null +++ b/packages/redrob/src/tool/image_generate.txt @@ -0,0 +1,10 @@ +- Generates an image from a text description and saves it in the project's `artifacts/` folder +- Use this when the user asks for a picture, illustration, logo, diagram-like artwork, mockup, or any other image +- The image is shown to the user in the conversation and returned to you, so you can see what was made and refine it with another call +- Billed to the user's Redrob account per image, so make one image per request unless the user asks for variations + +Usage notes: + - Write the prompt as a full visual description: subject, setting, style, composition, colors, and any text that must appear in the image + - `filename` is optional and has no extension; a name is derived from the prompt when it is omitted, and an existing file is never overwritten + - To edit an existing image, or to keep a person, product, or style consistent, pass the image's path in `references` and describe the change in the prompt; the original is left untouched and the result is saved as a new file + - Leave `model` unset unless the user names an image model diff --git a/packages/redrob/src/tool/registry.ts b/packages/redrob/src/tool/registry.ts index e5c3bde3c2..8b1c35417b 100644 --- a/packages/redrob/src/tool/registry.ts +++ b/packages/redrob/src/tool/registry.ts @@ -26,6 +26,9 @@ import { Plugin } from "../plugin" import { Provider } from "@/provider/provider" import { WebSearchTool } from "./websearch" +import { ImageGenerateTool, redrobKey } from "./image_generate" +import { SpeechGenerateTool } from "./speech_generate" +import { Auth } from "@/auth" import { LspTool } from "./lsp" import * as Truncate from "./truncate" import { ApplyPatchTool } from "./apply_patch" @@ -58,10 +61,7 @@ import { McpCatalog } from "@/mcp/catalog" export function webSearchEnabled(providerID: ProviderV2.ID, flags = { exa: false, parallel: false }) { return ( - providerID === ProviderV2.ID.redrob || - providerID === ProviderV2.ID.make("redrob-go") || - flags.exa || - flags.parallel + providerID === ProviderV2.ID.redrob || providerID === ProviderV2.ID.make("redrob-go") || flags.exa || flags.parallel ) } @@ -108,6 +108,9 @@ const layer = Layer.effect( const plan = yield* PlanExitTool const webfetch = yield* WebFetchTool const websearch = yield* WebSearchTool + const imageGenerate = yield* ImageGenerateTool + const speechGenerate = yield* SpeechGenerateTool + const auth = yield* Auth.Service const shell = yield* ShellTool const globtool = yield* GlobTool const writetool = yield* WriteTool @@ -219,6 +222,8 @@ const layer = Layer.effect( fetch: Tool.init(webfetch), todo: Tool.init(todo), search: Tool.init(websearch), + image: Tool.init(imageGenerate), + speech: Tool.init(speechGenerate), skill: Tool.init(skilltool), patch: Tool.init(patchtool), question: Tool.init(question), @@ -242,6 +247,8 @@ const layer = Layer.effect( tool.fetch, tool.todo, tool.search, + tool.image, + tool.speech, tool.skill, tool.patch, ...(tool.execute ? [tool.execute] : []), @@ -290,7 +297,14 @@ const layer = Layer.effect( }) const tools: Interface["tools"] = Effect.fn("ToolRegistry.tools")(function* (input) { + /* + * Image and speech generation are offered only where they can run: they bill the Redrob account, so without a + * Redrob credential each would be a tool that fails on every call. Read per request because the + * credential can be connected or removed while the engine runs. + */ + const canGenerateMedia = Boolean(redrobKey(yield* auth.get("redrob").pipe(Effect.orElseSucceed(() => undefined)))) const filtered = (yield* all()).filter((tool) => { + if (tool.id === ImageGenerateTool.id || tool.id === SpeechGenerateTool.id) return canGenerateMedia if (tool.id === WebSearchTool.id) { return webSearchEnabled(input.providerID, { exa: flags.enableExa, parallel: flags.enableParallel }) } @@ -438,6 +452,7 @@ export const node = LayerNode.make({ Session.node, BackgroundJob.node, Provider.node, + Auth.node, LSP.node, Instruction.node, FSUtil.node, diff --git a/packages/redrob/src/tool/speech_generate.ts b/packages/redrob/src/tool/speech_generate.ts new file mode 100644 index 0000000000..827393d5e0 --- /dev/null +++ b/packages/redrob/src/tool/speech_generate.ts @@ -0,0 +1,219 @@ +import { Effect, Schema } from "effect" +import { HttpClient, HttpClientRequest } from "effect/unstable/http" +import * as path from "path" +import * as Tool from "./tool" +import DESCRIPTION from "./speech_generate.txt" +import { Auth } from "@/auth" +import { EventV2Bridge } from "@/event-v2-bridge" +import { InstanceState } from "@/effect/instance-state" +import { FileSystem } from "@redrob-code/core/filesystem" +import { Watcher } from "@redrob-code/core/filesystem/watcher" +import { FSUtil } from "@redrob-code/core/fs-util" +import { assertExternalDirectoryEffect } from "./external-directory" +import { gatewayMessage, gatewayUrl, redrobKey, slug } from "./image_generate" + +/** + * Speech through the Redrob gateway's `POST /v1/audio/speech`, on the engine's own Redrob credential, + * for the reason image_generate gives: the key is the engine's and stays here. + * + * Two callers share `prepareSpeech` and `requestSpeech`: the `speech_generate` tool, which saves an + * mp3, and the engine's `POST /redrob/speech` route, which hands the audio to Redrob Cowork to play + * a reply aloud without the app ever holding the key. + * + * The tool saves its audio and does NOT return it as an attachment. An attachment goes back to the + * model with the next turn, and audio input would steer `auto` to an audio-input model and bill the + * clip as input on every turn after, to tell the model nothing it does not already know: it wrote + * the words. + */ + +/** Multilingual, so a Korean script is spoken as Korean. Any speech model the gateway serves can be named. */ +export const DEFAULT_SPEECH_MODEL = "elevenlabs/eleven-multilingual-v2" +export const DEFAULT_SPEECH_VOICE = "sarah" + +/** + * For speech that is played as it arrives, a reply read aloud or a voice conversation's answer, where + * the wait before the first word matters more than the last bit of quality. Same voice, so a saved file + * and a reply read aloud sound like the same speaker. Multilingual, so Korean is spoken as Korean. + */ +export const PLAYBACK_SPEECH_MODEL = "elevenlabs/eleven-flash-v2.5" + +export type SpeechDefaults = { model: string; voice: string } +const FILE_DEFAULTS: SpeechDefaults = { model: DEFAULT_SPEECH_MODEL, voice: DEFAULT_SPEECH_VOICE } +export const PLAYBACK_DEFAULTS: SpeechDefaults = { model: PLAYBACK_SPEECH_MODEL, voice: DEFAULT_SPEECH_VOICE } + +/** The gateway's limit for one request, checked here so an over-long request costs nothing. */ +export const MAX_SPEECH_CHARACTERS = 4_096 + +const TIMEOUT_MS = 180_000 +const MAX_AUDIO_BYTES = 50 * 1024 * 1024 + +/** + * Why speech could not be made. `invalid` and `no_key` are found before anything is sent and cost + * nothing; `upstream` and `timeout` are the gateway's. + */ +export class SpeechError extends Schema.TaggedErrorClass()("SpeechError", { + reason: Schema.Literals(["invalid", "no_key", "upstream", "timeout"]), + message: Schema.String, + status: Schema.optional(Schema.Number), +}) {} + +export type PreparedSpeech = { text: string; model: string; voice?: string; characters: number } + +/** Characters as the gateway bills them: code points, so the limit here agrees with its limit there. */ +function characters(text: string): number { + return [...text].length +} + +/** The request as it will be sent, or why it would be refused, with nothing sent either way. */ +export const prepareSpeech = Effect.fn("Speech.prepare")(function* ( + input: { text: string; model?: string; voice?: string }, + defaults: SpeechDefaults = FILE_DEFAULTS, +) { + const text = input.text.trim() + if (!text) return yield* new SpeechError({ reason: "invalid", message: "Give the words to speak." }) + const length = characters(text) + if (length > MAX_SPEECH_CHARACTERS) { + return yield* new SpeechError({ + reason: "invalid", + message: `The text is ${length} characters; speak at most ${MAX_SPEECH_CHARACTERS} per call and save longer material in parts.`, + }) + } + const model = input.model?.trim() || defaults.model + /* Voices belong to a model, so the default voice only goes with the default model. */ + const voice = input.voice?.trim() || (model === defaults.model ? defaults.voice : undefined) + const prepared: PreparedSpeech = { text, model, ...(voice ? { voice } : {}), characters: length } + return prepared +}) + +/** The engine's Redrob key, or a `no_key` failure, which is found before anything is sent. */ +export const speechKey = Effect.fn("Speech.key")(function* (auth: Auth.Interface) { + const key = redrobKey(yield* auth.get("redrob").pipe(Effect.orElseSucceed(() => undefined))) + if (!key) { + return yield* new SpeechError({ + reason: "no_key", + message: "Connect Redrob to generate speech: no Redrob API key is available.", + }) + } + return key +}) + +/** One call to the gateway. The audio is checked for being audio before anyone keeps or plays it. */ +export const requestSpeech = Effect.fn("Speech.request")(function* ( + http: HttpClient.HttpClient, + key: string, + speech: PreparedSpeech, +) { + const request = yield* HttpClientRequest.post(`${gatewayUrl()}/audio/speech`).pipe( + HttpClientRequest.bearerToken(key), + HttpClientRequest.bodyJson({ + model: speech.model, + input: speech.text, + response_format: "mp3", + ...(speech.voice ? { voice: speech.voice } : {}), + }), + Effect.orDie, + ) + const response = yield* http.execute(request).pipe( + Effect.mapError(() => new SpeechError({ reason: "upstream", message: "The Redrob gateway could not be reached." })), + Effect.timeoutOrElse({ + duration: TIMEOUT_MS, + orElse: () => Effect.fail(new SpeechError({ reason: "timeout", message: "Speech generation timed out." })), + }), + ) + if (response.status < 200 || response.status >= 300) { + const body = yield* response.text.pipe(Effect.orElseSucceed(() => "")) + return yield* new SpeechError({ + reason: "upstream", + status: response.status, + message: `The Redrob gateway answered ${response.status}: ${gatewayMessage(body)}`, + }) + } + const contentType = response.headers["content-type"]?.split(";")[0]?.trim().toLowerCase() ?? "" + if (!contentType.startsWith("audio/")) { + return yield* new SpeechError({ + reason: "upstream", + message: `The Redrob gateway answered with ${contentType || "no content type"}, not audio.`, + }) + } + const buffer = yield* response.arrayBuffer.pipe( + Effect.mapError(() => new SpeechError({ reason: "upstream", message: "The Redrob gateway's audio was cut off." })), + ) + const audio = new Uint8Array(buffer) + if (audio.byteLength === 0) { + return yield* new SpeechError({ reason: "upstream", message: "The Redrob gateway returned no audio." }) + } + if (audio.byteLength > MAX_AUDIO_BYTES) { + return yield* new SpeechError({ reason: "upstream", message: `The audio is over ${MAX_AUDIO_BYTES / (1024 * 1024)} MB.` }) + } + const cost = Number(response.headers["x-redrob-cost-usd"]) + return { audio, contentType, ...(Number.isFinite(cost) ? { costUsd: cost } : {}) } +}) + +export const Parameters = Schema.Struct({ + text: Schema.String.annotate({ description: `The words to speak, at most ${MAX_SPEECH_CHARACTERS} characters` }), + voice: Schema.optional(Schema.String).annotate({ + description: `Optional voice of the chosen model. Defaults to ${DEFAULT_SPEECH_VOICE} with the default model.`, + }), + model: Schema.optional(Schema.String).annotate({ + description: `Optional speech model id served by the Redrob gateway. Defaults to ${DEFAULT_SPEECH_MODEL}.`, + }), + filename: Schema.optional(Schema.String).annotate({ + description: "Optional file name without an extension. Derived from the text when omitted.", + }), +}) + +export const SpeechGenerateTool = Tool.define( + "speech_generate", + Effect.gen(function* () { + const http = yield* HttpClient.HttpClient + const auth = yield* Auth.Service + const fs = yield* FSUtil.Service + const events = yield* EventV2Bridge.Service + + return { + description: DESCRIPTION, + parameters: Parameters, + execute: (params: Schema.Schema.Type, ctx: Tool.Context) => + Effect.gen(function* () { + const speech = yield* prepareSpeech(params) + const key = yield* speechKey(auth) + + const instance = yield* InstanceState.context + const directory = path.join(instance.directory, "artifacts") + const stem = slug(params.filename?.trim() || speech.text) + let filepath = path.join(directory, `${stem}.mp3`) + for (let n = 2; yield* fs.existsSafe(filepath); n += 1) { + filepath = path.join(directory, `${stem}-${n}.mp3`) + } + yield* assertExternalDirectoryEffect(ctx, filepath) + yield* ctx.ask({ + permission: "edit", + patterns: [path.relative(instance.worktree, filepath)], + always: ["*"], + metadata: { filepath, model: speech.model, voice: speech.voice }, + }) + + const spoken = yield* requestSpeech(http, key, speech) + yield* fs.writeWithDirs(filepath, spoken.audio) + yield* events.publish(FileSystem.Event.Edited, { file: filepath }) + yield* events.publish(Watcher.Event.Updated, { file: filepath, event: "add" }) + + const relative = path.relative(instance.worktree, filepath) + return { + title: relative, + output: `Saved ${relative}: ${speech.characters} characters spoken with ${speech.model}${speech.voice ? ` (${speech.voice})` : ""}.`, + metadata: { + filepath, + model: speech.model, + ...(speech.voice ? { voice: speech.voice } : {}), + characters: speech.characters, + ...(spoken.costUsd === undefined ? {} : { costUsd: spoken.costUsd }), + }, + } + }).pipe( + Effect.catchTag("SpeechError", (error) => Effect.die(new Error(error.message))), + Effect.orDie, + ), + } + }), +) diff --git a/packages/redrob/src/tool/speech_generate.txt b/packages/redrob/src/tool/speech_generate.txt new file mode 100644 index 0000000000..6efe5784c8 --- /dev/null +++ b/packages/redrob/src/tool/speech_generate.txt @@ -0,0 +1,10 @@ +- Turns text into spoken audio and saves it as an MP3 in the project's `artifacts/` folder +- Use this when the user asks for a voice-over, narration, a spoken summary, an audio version of a document, or anything else they want to listen to +- The audio is not played back to you; you get the file's path. The user can play it in the conversation +- Billed to the user's Redrob account per character, so speak only what the user asked for + +Usage notes: + - `text` is read aloud as written, up to 4096 characters per call; split longer material into parts and save each as its own file + - Write numbers, abbreviations and names the way they should be spoken + - Leave `model` and `voice` unset unless the user asks for a specific one; the default speaks Korean, English and many other languages + - `filename` is optional and has no extension; a name is derived from the text when it is omitted, and an existing file is never overwritten diff --git a/packages/redrob/test/server/chat-completion-session-header.test.ts b/packages/redrob/test/server/chat-completion-session-header.test.ts new file mode 100644 index 0000000000..7f5edf0063 --- /dev/null +++ b/packages/redrob/test/server/chat-completion-session-header.test.ts @@ -0,0 +1,26 @@ +import { describe, expect, test } from "bun:test" +import { sessionHeader } from "@redrob-code/server/handlers/chat-completion" + +/** + * `x-redrob-session` on /v1/chat/completions: forwarded so the console can join a labeled session to + * what its requests cost, but only to the Redrob provider and only when it is an id, never text. + */ +describe("x-redrob-session on chat completions", () => { + test("is forwarded to the Redrob provider in the console's id format", () => { + expect(sessionHeader("redrob/auto", { "x-redrob-session": "of_0123abcd" })).toEqual({ + "x-redrob-session": "of_0123abcd", + }) + expect(sessionHeader("auto", { "x-redrob-session": "cw_1:2.3-4" })).toEqual({ "x-redrob-session": "cw_1:2.3-4" }) + }) + + test("is dropped when it is not an id, and when absent", () => { + expect(sessionHeader("redrob/auto", { "x-redrob-session": "Refund 4,500,000 KRW to Kim" })).toBeUndefined() + expect(sessionHeader("redrob/auto", { "x-redrob-session": "x".repeat(129) })).toBeUndefined() + expect(sessionHeader("redrob/auto", {})).toBeUndefined() + }) + + test("never goes to another vendor", () => { + expect(sessionHeader("openai/gpt-5", { "x-redrob-session": "of_0123abcd" })).toBeUndefined() + expect(sessionHeader("ollama/llama3", { "x-redrob-session": "of_0123abcd" })).toBeUndefined() + }) +}) diff --git a/packages/redrob/test/server/httpapi-exercise/index.ts b/packages/redrob/test/server/httpapi-exercise/index.ts index 3c4a84f0ad..f5330ba806 100644 --- a/packages/redrob/test/server/httpapi-exercise/index.ts +++ b/packages/redrob/test/server/httpapi-exercise/index.ts @@ -605,6 +605,44 @@ const scenarios: Scenario[] = [ check(typeof error?.message === "string", "error should carry a message") check(typeof error?.type === "string", "error should carry a type") }), + /* + The same route answering, through the fake LLM server the session scenarios use. The 400 scenario + above never reaches a provider, which is how a 500 on every real request ("Service not found: + @redrob/LLMClient") and an empty 200 on every streamed one went unnoticed. These resolve a real + model (`test/test-model`, the project's fake provider) and assert the reply. + */ + http.protected + .post("/v1/chat/completions", "chat.completions.reply") + .withLlm() + .seeded((ctx) => ctx.llmText("pong")) + .at((ctx) => ({ + path: "/v1/chat/completions", + headers: ctx.headers(), + body: { model: "test/test-model", messages: [{ role: "user", content: "ping" }] }, + })) + .json( + 200, + (body) => { + const choices = (body as { choices?: { message?: { content?: unknown } }[] }).choices + check(choices?.[0]?.message?.content === "pong", "a completion should carry the model's answer") + }, + "status", + ), + http.protected + .post("/v1/chat/completions", "chat.completions.stream") + .withLlm() + .seeded((ctx) => ctx.llmText("pong")) + .at((ctx) => ({ + path: "/v1/chat/completions", + headers: ctx.headers(), + body: { model: "test/test-model", stream: true, messages: [{ role: "user", content: "ping" }] }, + })) + .status(200, (_ctx, result) => + Effect.sync(() => { + check(result.text.includes('"content":"pong"'), "a streamed completion should carry the answer") + check(result.text.includes("data: [DONE]"), "a streamed completion should end with [DONE]") + }), + ), http.protected .post("/experimental/session/{sessionID}/background", "experimental.session.background") .mutating() @@ -1835,6 +1873,43 @@ const scenarios: Scenario[] = [ }, })) .json(404, object, "status"), + /* + The insights route, also through its NOT-CONNECTED path and for the same reason as the variants: the + exerciser holds no console key, and a key would send a real batch to the live console on every run. + The connected path, with the key in the request to the console and nowhere in the answer, is asserted + in packages/core/test/insights.test.ts against a stand-in console. + */ + http.protected + .post("/api/insights/sessions", "insights.sessions") + .at((ctx) => ({ + path: "/api/insights/sessions", + headers: ctx.headers(), + body: { sessions: [{ externalId: "of_exercise", toolKey: "office" }] }, + })) + .json(404, object, "status"), + /* + The speech and transcribe routes, through their NOT-CONNECTED path, for the same reason as the + variants and insights above: the exerciser holds no console key, so the gateway call fails with + no_key, which both routes map to a 503 (the engine, not the caller, lacks the key). A key would + send a paid request to the live gateway on every CI run. The connected path is covered by the + tool and endpoint unit tests against a stand-in gateway. + */ + http.protected + .post("/redrob/speech", "redrob.speech") + .at((ctx) => ({ + path: "/redrob/speech", + headers: ctx.headers(), + body: { text: "exercise" }, + })) + .json(503, object, "status"), + http.protected + .post("/redrob/transcribe", "redrob.transcribe") + .at((ctx) => ({ + path: "/redrob/transcribe", + headers: ctx.headers(), + body: { audio: Buffer.from("exercise").toString("base64"), format: "wav" }, + })) + .json(503, object, "status"), http.protected .post("/global/upgrade", "global.upgrade") .global() diff --git a/packages/redrob/test/server/httpapi-speech.test.ts b/packages/redrob/test/server/httpapi-speech.test.ts new file mode 100644 index 0000000000..de7aa1fb2f --- /dev/null +++ b/packages/redrob/test/server/httpapi-speech.test.ts @@ -0,0 +1,184 @@ +import { NodeHttpServer, NodeServices } from "@effect/platform-node" +import { describe, expect } from "bun:test" +import { Config, Context, Effect, Layer } from "effect" +import { + HttpClient, + HttpClientRequest, + HttpRouter, + HttpServer, + HttpServerRequest, + HttpServerResponse, +} from "effect/unstable/http" +import * as Socket from "effect/unstable/socket/Socket" +import * as Http from "node:http" +import { ControlPaths } from "../../src/server/routes/instance/httpapi/groups/control" +import { HttpApiApp } from "../../src/server/routes/instance/httpapi/server" +import { DEFAULT_SPEECH_MODEL, DEFAULT_SPEECH_VOICE, PLAYBACK_SPEECH_MODEL } from "../../src/tool/speech_generate" +import { testEffect } from "../lib/effect" + +/** + * `POST /redrob/speech` through the production route tree, with a stand-in for the Redrob gateway + * behind it. What matters is that the app gets audio while the engine's key only ever goes to the + * gateway, and that every refusal arrives as the endpoint's declared error. + */ + +const servedRoutes: Layer.Layer = HttpRouter.serve( + HttpApiApp.routes, + { disableListenLog: true, disableLogger: true }, +) +const it = testEffect( + servedRoutes.pipe( + Layer.provide(Socket.layerWebSocketConstructorGlobal), + Layer.provideMerge(NodeHttpServer.layerTest), + Layer.provideMerge(NodeServices.layer), + ), +) + +const MP3 = new Uint8Array([0xff, 0xf3, 0x44, 0xc4, 0x01, 0x02]) + +type Seen = { authorization: string | undefined; body: unknown } +type Answer = { status: number; type: string; body: Uint8Array | string } + +/** The engine pointed at the stand-in and holding a Redrob key, restored when the test scope closes. */ +const engineEnv = (gatewayUrl: string) => + Effect.acquireRelease( + Effect.sync(() => { + const saved = { + url: process.env.REDROB_CONSOLE_URL, + auth: process.env.REDROB_AUTH_CONTENT, + key: process.env.REDROB_API_KEY, + } + process.env.REDROB_CONSOLE_URL = gatewayUrl + process.env.REDROB_AUTH_CONTENT = JSON.stringify({ redrob: { type: "api", key: "rk_engine_key" } }) + delete process.env.REDROB_API_KEY + return saved + }), + (saved) => + Effect.sync(() => { + for (const [name, value] of [ + ["REDROB_CONSOLE_URL", saved.url], + ["REDROB_AUTH_CONTENT", saved.auth], + ["REDROB_API_KEY", saved.key], + ] as const) { + if (value === undefined) delete process.env[name] + else process.env[name] = value + } + }), + ) + +/** + * Topology: the engine's routes run on the test's primary server (NodeHttpServer.layerTest), and the + * Redrob gateway stand-in is a second listener built into this test's scope with its own fresh router, + * so its `/audio/speech` cannot collide with anything the engine registers. The engine reaches the + * stand-in through `REDROB_CONSOLE_URL`, the developer seam the gateway URL already honours. + */ +const gateway = Effect.fn("SpeechTest.gateway")(function* (answer: (body: Record) => Answer) { + const seen: Seen[] = [] + const context = yield* Layer.build( + Layer.mergeAll( + Layer.fresh(HttpRouter.layer), + NodeHttpServer.layer(() => Http.createServer(), { host: "127.0.0.1", port: 0 }), + ), + ) + const server = Context.get(context, HttpServer.HttpServer) + const router = Context.get(context, HttpRouter.HttpRouter) + yield* router.add( + "POST", + "/audio/speech", + Effect.gen(function* () { + const request = yield* HttpServerRequest.HttpServerRequest + const raw = yield* request.json.pipe(Effect.orElseSucceed(() => ({}))) + const body = typeof raw === "object" && raw !== null ? Object.fromEntries(Object.entries(raw)) : {} + seen.push({ authorization: request.headers.authorization, body }) + const reply = answer(body) + return typeof reply.body === "string" + ? HttpServerResponse.text(reply.body, { status: reply.status, contentType: reply.type }) + : HttpServerResponse.uint8Array(reply.body, { status: reply.status, contentType: reply.type }) + }), + ) + yield* server.serve(router.asHttpEffect()) + if (server.address._tag !== "TcpAddress") throw new Error("expected a TCP listener") + yield* engineEnv(`http://127.0.0.1:${server.address.port}`) + return { seen } +}) + +const speak = (payload: Record) => + HttpClientRequest.post(ControlPaths.speech).pipe( + HttpClientRequest.bodyJson(payload), + Effect.flatMap(HttpClient.execute), + ) + +describe("redrob speech HttpApi", () => { + it.live("answers with the gateway's mp3, sending the engine's key only to the gateway", () => + Effect.gen(function* () { + const { seen } = yield* gateway(() => ({ status: 200, type: "audio/mpeg", body: MP3 })) + const response = yield* speak({ text: "안녕하세요" }) + + expect(response.status).toBe(200) + expect(response.headers["content-type"]).toContain("audio/mpeg") + expect(new Uint8Array(yield* response.arrayBuffer)).toEqual(MP3) + expect(seen).toEqual([ + { + authorization: "Bearer rk_engine_key", + body: { + model: PLAYBACK_SPEECH_MODEL, + input: "안녕하세요", + response_format: "mp3", + voice: DEFAULT_SPEECH_VOICE, + }, + }, + ]) + }), + ) + + it.live("plays with the fast model by default, and a chosen model keeps the voice it was given", () => + Effect.gen(function* () { + const { seen } = yield* gateway(() => ({ status: 200, type: "audio/mpeg", body: MP3 })) + expect((yield* speak({ text: "One" })).status).toBe(200) + expect((yield* speak({ text: "Two", model: DEFAULT_SPEECH_MODEL })).status).toBe(200) + expect((yield* speak({ text: "Three", model: DEFAULT_SPEECH_MODEL, voice: "george" })).status).toBe(200) + expect(seen.map((call) => call.body)).toEqual([ + { model: PLAYBACK_SPEECH_MODEL, input: "One", response_format: "mp3", voice: DEFAULT_SPEECH_VOICE }, + // Another model's voices are its own, so none is assumed for it. + { model: DEFAULT_SPEECH_MODEL, input: "Two", response_format: "mp3" }, + { model: DEFAULT_SPEECH_MODEL, input: "Three", response_format: "mp3", voice: "george" }, + ]) + }), + ) + + it.live("refuses empty or over-long text with a 400, sending nothing", () => + Effect.gen(function* () { + const { seen } = yield* gateway(() => ({ status: 200, type: "audio/mpeg", body: MP3 })) + expect((yield* speak({ text: " " })).status).toBe(400) + expect((yield* speak({ text: "가".repeat(4097) })).status).toBe(400) + expect(seen).toHaveLength(0) + }), + ) + + it.live("without a Redrob key it is a 503, sending nothing", () => + Effect.gen(function* () { + const { seen } = yield* gateway(() => ({ status: 200, type: "audio/mpeg", body: MP3 })) + process.env.REDROB_AUTH_CONTENT = JSON.stringify({}) + const response = yield* speak({ text: "Hello" }) + expect(response.status).toBe(503) + expect(JSON.stringify(yield* response.json)).toContain("Connect Redrob") + expect(seen).toHaveLength(0) + }), + ) + + it.live("a gateway refusal, or an answer that is not audio, is a 502 with the gateway's message", () => + Effect.gen(function* () { + yield* gateway((body) => + body.input === "json" + ? { status: 200, type: "application/json", body: "{}" } + : { status: 402, type: "application/json", body: JSON.stringify({ error: { message: "Out of credit." } }) }, + ) + const refused = yield* speak({ text: "Hello" }) + expect(refused.status).toBe(502) + expect(JSON.stringify(yield* refused.json)).toContain("answered 402: Out of credit.") + const json = yield* speak({ text: "json" }) + expect(json.status).toBe(502) + expect(JSON.stringify(yield* json.json)).toContain("not audio") + }), + ) +}) diff --git a/packages/redrob/test/server/httpapi-transcribe.test.ts b/packages/redrob/test/server/httpapi-transcribe.test.ts new file mode 100644 index 0000000000..2760cf91f0 --- /dev/null +++ b/packages/redrob/test/server/httpapi-transcribe.test.ts @@ -0,0 +1,200 @@ +import { NodeHttpServer, NodeServices } from "@effect/platform-node" +import { describe, expect } from "bun:test" +import { Config, Context, Effect, Layer } from "effect" +import { + HttpClient, + HttpClientRequest, + HttpRouter, + HttpServer, + HttpServerRequest, + HttpServerResponse, +} from "effect/unstable/http" +import * as Socket from "effect/unstable/socket/Socket" +import * as Http from "node:http" +import { ControlPaths } from "../../src/server/routes/instance/httpapi/groups/control" +import { HttpApiApp } from "../../src/server/routes/instance/httpapi/server" +import { DEFAULT_TRANSCRIPTION_MODEL, MAX_TRANSCRIPTION_BYTES } from "../../src/redrob/transcription" +import { testEffect } from "../lib/effect" + +/** + * `POST /redrob/transcribe` through the production route tree, with a stand-in for the Redrob + * gateway behind it. What matters is that the app gets a transcript while the engine's key only ever + * goes to the gateway, that a request the gateway would refuse is refused here before anything is + * sent, and that every refusal arrives as the endpoint's declared error. + */ + +const servedRoutes: Layer.Layer = HttpRouter.serve( + HttpApiApp.routes, + { disableListenLog: true, disableLogger: true }, +) +const it = testEffect( + servedRoutes.pipe( + Layer.provide(Socket.layerWebSocketConstructorGlobal), + Layer.provideMerge(NodeHttpServer.layerTest), + Layer.provideMerge(NodeServices.layer), + ), +) + +/** A few bytes standing in for a webm/opus recording; the gateway stand-in never decodes them. */ +const CLIP = Buffer.from([0x1a, 0x45, 0xdf, 0xa3, 0x9f, 0x42, 0x86, 0x81]).toString("base64") + +type Seen = { authorization: string | undefined; body: unknown } +type Answer = { status: number; body: string } + +/** The engine pointed at the stand-in and holding a Redrob key, restored when the test scope closes. */ +const engineEnv = (gatewayUrl: string) => + Effect.acquireRelease( + Effect.sync(() => { + const saved = { + url: process.env.REDROB_CONSOLE_URL, + auth: process.env.REDROB_AUTH_CONTENT, + key: process.env.REDROB_API_KEY, + } + process.env.REDROB_CONSOLE_URL = gatewayUrl + process.env.REDROB_AUTH_CONTENT = JSON.stringify({ redrob: { type: "api", key: "rk_engine_key" } }) + delete process.env.REDROB_API_KEY + return saved + }), + (saved) => + Effect.sync(() => { + for (const [name, value] of [ + ["REDROB_CONSOLE_URL", saved.url], + ["REDROB_AUTH_CONTENT", saved.auth], + ["REDROB_API_KEY", saved.key], + ] as const) { + if (value === undefined) delete process.env[name] + else process.env[name] = value + } + }), + ) + +/** + * Topology: the engine's routes run on the test's primary server (NodeHttpServer.layerTest), and the + * Redrob gateway stand-in is a second listener built into this test's scope with its own fresh router, + * so its `/audio/transcriptions` cannot collide with anything the engine registers. The engine reaches + * the stand-in through `REDROB_CONSOLE_URL`, the developer seam the gateway URL already honours. + */ +const gateway = Effect.fn("TranscribeTest.gateway")(function* (answer: (body: Record) => Answer) { + const seen: Seen[] = [] + const context = yield* Layer.build( + Layer.mergeAll( + Layer.fresh(HttpRouter.layer), + NodeHttpServer.layer(() => Http.createServer(), { host: "127.0.0.1", port: 0 }), + ), + ) + const server = Context.get(context, HttpServer.HttpServer) + const router = Context.get(context, HttpRouter.HttpRouter) + yield* router.add( + "POST", + "/audio/transcriptions", + Effect.gen(function* () { + const request = yield* HttpServerRequest.HttpServerRequest + const raw = yield* request.json.pipe(Effect.orElseSucceed(() => ({}))) + const body = typeof raw === "object" && raw !== null ? Object.fromEntries(Object.entries(raw)) : {} + seen.push({ authorization: request.headers.authorization, body }) + const reply = answer(body) + return HttpServerResponse.text(reply.body, { status: reply.status, contentType: "application/json" }) + }), + ) + yield* server.serve(router.asHttpEffect()) + if (server.address._tag !== "TcpAddress") throw new Error("expected a TCP listener") + yield* engineEnv(`http://127.0.0.1:${server.address.port}`) + return { seen } +}) + +const transcript = (text: string) => ({ + status: 200, + body: JSON.stringify({ text, seconds: 3.2, requestId: "req_1", costUsd: 0.0004 }), +}) + +const transcribe = (payload: Record) => + HttpClientRequest.post(ControlPaths.transcribe).pipe( + HttpClientRequest.bodyJson(payload), + Effect.flatMap(HttpClient.execute), + ) + +describe("redrob transcribe HttpApi", () => { + it.live("answers with the gateway's transcript, sending the engine's key only to the gateway", () => + Effect.gen(function* () { + const { seen } = yield* gateway(() => transcript(" 회의 요약해 줘, and send it to Minji ")) + const response = yield* transcribe({ audio: CLIP, format: "webm", language: "KO" }) + + expect(response.status).toBe(200) + expect(yield* response.json).toEqual({ + text: "회의 요약해 줘, and send it to Minji", + seconds: 3.2, + costUsd: 0.0004, + }) + expect(seen).toEqual([ + { + authorization: "Bearer rk_engine_key", + body: { + model: DEFAULT_TRANSCRIPTION_MODEL, + input_audio: { data: CLIP, format: "webm" }, + response_format: "json", + language: "ko", + }, + }, + ]) + }), + ) + + it.live("leaves the language to the gateway when none is given, and passes a chosen model through", () => + Effect.gen(function* () { + const { seen } = yield* gateway(() => transcript("Hello")) + const response = yield* transcribe({ audio: CLIP, format: "ogg", model: "openai/gpt-transcribe" }) + expect(response.status).toBe(200) + expect(seen[0]?.body).toEqual({ + model: "openai/gpt-transcribe", + input_audio: { data: CLIP, format: "ogg" }, + response_format: "json", + }) + }), + ) + + it.live("refuses audio the gateway would refuse with a 400, sending nothing", () => + Effect.gen(function* () { + const { seen } = yield* gateway(() => transcript("Hello")) + /* The smallest unpadded base64 that decodes to more than the limit. */ + const oversize = "A".repeat(Math.ceil((MAX_TRANSCRIPTION_BYTES + 1) / 3) * 4) + for (const payload of [ + { audio: " ", format: "webm" }, + { audio: `data:audio/webm;base64,${CLIP}`, format: "webm" }, + { audio: "abc", format: "webm" }, + { audio: oversize, format: "webm" }, + { audio: CLIP, format: "webm", language: "korean" }, + { audio: CLIP, format: "opus" }, + ]) { + expect((yield* transcribe(payload)).status).toBe(400) + } + expect(seen).toHaveLength(0) + }), + ) + + it.live("without a Redrob key it is a 503, sending nothing", () => + Effect.gen(function* () { + const { seen } = yield* gateway(() => transcript("Hello")) + process.env.REDROB_AUTH_CONTENT = JSON.stringify({}) + const response = yield* transcribe({ audio: CLIP, format: "webm" }) + expect(response.status).toBe(503) + expect(JSON.stringify(yield* response.json)).toContain("Connect Redrob") + expect(seen).toHaveLength(0) + }), + ) + + it.live("a gateway refusal, or an answer that is not a transcript, is a 502 with the gateway's message", () => + Effect.gen(function* () { + yield* gateway((body) => + body.model === "shapeless" + ? { status: 200, body: JSON.stringify({ transcript: "Hello" }) } + : { status: 402, body: JSON.stringify({ error: { message: "Out of credit." } }) }, + ) + const refused = yield* transcribe({ audio: CLIP, format: "webm" }) + expect(refused.status).toBe(502) + expect(JSON.stringify(yield* refused.json)).toContain("answered 402: Out of credit.") + const shapeless = yield* transcribe({ audio: CLIP, format: "webm", model: "shapeless" }) + expect(shapeless.status).toBe(502) + expect(JSON.stringify(yield* shapeless.json)).toContain("without a transcript") + }), + ) +}) diff --git a/packages/redrob/test/tool/image_generate.test.ts b/packages/redrob/test/tool/image_generate.test.ts new file mode 100644 index 0000000000..e44b1ee846 --- /dev/null +++ b/packages/redrob/test/tool/image_generate.test.ts @@ -0,0 +1,271 @@ +import { afterEach, beforeEach, describe, expect } from "bun:test" +import { LayerNode } from "@redrob-code/core/effect/layer-node" +import { httpClient } from "@redrob-code/core/effect/app-node-platform" +import { FSUtil } from "@redrob-code/core/fs-util" +import { Cause, Effect, Exit } from "effect" +import { FetchHttpClient } from "effect/unstable/http" +import fs from "fs/promises" +import path from "path" +import { Auth } from "@/auth" +import { Tool } from "@/tool/tool" +import { Truncate } from "@/tool/truncate" +import { Agent } from "../../src/agent/agent" +import { EventV2Bridge } from "../../src/event-v2-bridge" +import { SessionID, MessageID } from "../../src/session/schema" +import { DEFAULT_IMAGE_MODEL, ImageGenerateTool, decodeImageDataUrl, slug } from "../../src/tool/image_generate" +import { disposeAllInstances, TestInstance } from "../fixture/fixture" +import { testEffect } from "../lib/effect" + +/** A real one-pixel PNG, so the bytes written are an image rather than filler. */ +const PIXEL_PNG = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==" + +const it = testEffect( + LayerNode.compile( + LayerNode.group([httpClient, Auth.node, FSUtil.node, EventV2Bridge.node, Truncate.node, Agent.node]), + [[httpClient, FetchHttpClient.layer]], + ), +) + +type Seen = { authorization: string | null; body: Record } + +/** A stand-in for the Redrob gateway that records what reached it. */ +function gateway(answer: (body: Record) => Response) { + const seen: Seen[] = [] + const server = Bun.serve({ + port: 0, + async fetch(request) { + const body: Record = await request.json() + seen.push({ authorization: request.headers.get("authorization"), body }) + return answer(body) + }, + }) + return { seen, server } +} + +const imageAnswer = () => + Response.json({ + choices: [ + { + message: { + content: "A red square.", + images: [{ type: "image_url", image_url: { url: `data:image/png;base64,${PIXEL_PNG}` } }], + }, + }, + ], + redrob: { costUsd: 0.039 }, + }) + +const asks: unknown[] = [] +const ctx = { + sessionID: SessionID.make("ses_test-image"), + messageID: MessageID.make("msg_test"), + callID: "", + agent: "build", + abort: AbortSignal.any([]), + messages: [], + metadata: () => Effect.void, + ask: (request: unknown) => Effect.sync(() => void asks.push(request)), +} + +const run = Effect.fn("ImageGenerateToolTest.run")(function* (args: Tool.InferParameters) { + const info = yield* ImageGenerateTool + const tool = yield* info.init() + return yield* tool.execute(args, ctx) +}) + +const failure = (exit: Exit.Exit) => (Exit.isFailure(exit) ? Cause.pretty(exit.cause) : "") + +const saved = { + url: process.env.REDROB_CONSOLE_URL, + auth: process.env.REDROB_AUTH_CONTENT, + key: process.env.REDROB_API_KEY, +} + +beforeEach(() => { + asks.length = 0 + process.env.REDROB_AUTH_CONTENT = JSON.stringify({ redrob: { type: "api", key: "rk_test_key" } }) + delete process.env.REDROB_API_KEY +}) + +afterEach(async () => { + for (const [name, value] of [ + ["REDROB_CONSOLE_URL", saved.url], + ["REDROB_AUTH_CONTENT", saved.auth], + ["REDROB_API_KEY", saved.key], + ] as const) { + if (value === undefined) delete process.env[name] + else process.env[name] = value + } + await disposeAllInstances() +}) + +describe("tool.image_generate", () => { + it.instance("asks the gateway for an image on the engine's Redrob key, saves it, and attaches it", () => + Effect.gen(function* () { + const test = yield* TestInstance + const { seen, server } = gateway(imageAnswer) + process.env.REDROB_CONSOLE_URL = server.url.toString() + try { + const result = yield* run({ prompt: "A small red square on white" }) + + expect(seen).toHaveLength(1) + expect(seen[0].authorization).toBe("Bearer rk_test_key") + expect(seen[0].body).toMatchObject({ + model: DEFAULT_IMAGE_MODEL, + modalities: ["image", "text"], + messages: [{ role: "user", content: "A small red square on white" }], + }) + + const filepath = path.join(test.directory, "artifacts", "a-small-red-square-on-white.png") + expect(Buffer.from(yield* Effect.promise(() => fs.readFile(filepath))).toString("base64")).toBe(PIXEL_PNG) + expect(result.title.endsWith(path.join("artifacts", "a-small-red-square-on-white.png"))).toBe(true) + expect(result.output).toContain("A red square.") + expect(result.metadata).toMatchObject({ filepath, model: DEFAULT_IMAGE_MODEL, costUsd: 0.039 }) + expect(result.attachments).toEqual([ + { + type: "file", + mime: "image/png", + filename: "a-small-red-square-on-white.png", + url: `data:image/png;base64,${PIXEL_PNG}`, + }, + ]) + expect(asks).toEqual([expect.objectContaining({ permission: "edit", patterns: [result.title] })]) + } finally { + void server.stop(true) + } + }), + ) + + it.instance("never overwrites an existing file, and uses a named model and file name", () => + Effect.gen(function* () { + const test = yield* TestInstance + const existing = path.join(test.directory, "artifacts", "logo.png") + yield* Effect.promise(() => fs.mkdir(path.dirname(existing), { recursive: true })) + yield* Effect.promise(() => fs.writeFile(existing, "keep me")) + const { seen, server } = gateway(imageAnswer) + process.env.REDROB_CONSOLE_URL = server.url.toString() + try { + const result = yield* run({ prompt: "A logo", filename: "Logo", model: "openai/gpt-5-image-mini" }) + expect(seen[0].body.model).toBe("openai/gpt-5-image-mini") + expect(result.title.endsWith(path.join("artifacts", "logo-2.png"))).toBe(true) + expect(yield* Effect.promise(() => fs.readFile(existing, "utf8"))).toBe("keep me") + } finally { + void server.stop(true) + } + }), + ) + + it.instance("sends reference images after the prompt, to edit one, and leaves the original alone", () => + Effect.gen(function* () { + const test = yield* TestInstance + const original = path.join(test.directory, "artifacts", "logo.png") + yield* Effect.promise(() => fs.mkdir(path.dirname(original), { recursive: true })) + yield* Effect.promise(() => fs.writeFile(original, Buffer.from(PIXEL_PNG, "base64"))) + const { seen, server } = gateway(imageAnswer) + process.env.REDROB_CONSOLE_URL = server.url.toString() + try { + const result = yield* run({ prompt: "Make the logo blue", references: ["artifacts/logo.png"] }) + expect(seen[0].body.messages).toEqual([ + { + role: "user", + content: [ + { type: "text", text: "Make the logo blue" }, + { type: "image_url", image_url: { url: `data:image/png;base64,${PIXEL_PNG}` } }, + ], + }, + ]) + expect(result.metadata.references).toEqual([original]) + expect(result.title.endsWith(path.join("artifacts", "make-the-logo-blue.png"))).toBe(true) + expect(Buffer.from(yield* Effect.promise(() => fs.readFile(original))).toString("base64")).toBe(PIXEL_PNG) + } finally { + void server.stop(true) + } + }), + ) + + it.instance("refuses a reference that is missing, not an image, or one too many, before anything is sent", () => + Effect.gen(function* () { + const test = yield* TestInstance + yield* Effect.promise(() => fs.writeFile(path.join(test.directory, "notes.txt"), "not an image")) + const { seen, server } = gateway(imageAnswer) + process.env.REDROB_CONSOLE_URL = server.url.toString() + try { + const missing = yield* run({ prompt: "x", references: ["nope.png"] }).pipe(Effect.exit) + expect(failure(missing)).toContain("Reference image not found: nope.png") + const text = yield* run({ prompt: "x", references: ["notes.txt"] }).pipe(Effect.exit) + expect(failure(text)).toContain("Not a PNG, JPEG, WebP, or GIF image: notes.txt") + const many = yield* run({ prompt: "x", references: ["a", "b", "c", "d", "e"] }).pipe(Effect.exit) + expect(failure(many)).toContain("at most 4 reference images") + expect(seen).toHaveLength(0) + } finally { + void server.stop(true) + } + }), + ) + + it.instance("fails with what the model said when it returns no image", () => + Effect.gen(function* () { + const { server } = gateway(() => Response.json({ choices: [{ message: { content: "I cannot draw that." } }] })) + process.env.REDROB_CONSOLE_URL = server.url.toString() + try { + const exit = yield* run({ prompt: "Something" }).pipe(Effect.exit) + expect(failure(exit)).toContain("returned no image. It said: I cannot draw that.") + } finally { + void server.stop(true) + } + }), + ) + + it.instance("relays the gateway's own refusal, such as an empty balance", () => + Effect.gen(function* () { + const { server } = gateway(() => + Response.json( + { error: { message: "This workspace is out of credit.", type: "insufficient_quota" } }, + { status: 402 }, + ), + ) + process.env.REDROB_CONSOLE_URL = server.url.toString() + try { + const exit = yield* run({ prompt: "Something" }).pipe(Effect.exit) + expect(failure(exit)).toContain("answered 402: This workspace is out of credit.") + } finally { + void server.stop(true) + } + }), + ) + + it.instance("without a Redrob key it fails before anything is sent", () => + Effect.gen(function* () { + process.env.REDROB_AUTH_CONTENT = JSON.stringify({}) + const { seen, server } = gateway(imageAnswer) + process.env.REDROB_CONSOLE_URL = server.url.toString() + try { + const exit = yield* run({ prompt: "Something" }).pipe(Effect.exit) + expect(failure(exit)).toContain("Connect Redrob to generate images") + expect(seen).toHaveLength(0) + } finally { + void server.stop(true) + } + }), + ) +}) + +describe("image_generate helpers", () => { + it.effect("derives a safe file name stem", () => + Effect.sync(() => { + expect(slug("A Red Square, on white!")).toBe("a-red-square-on-white") + expect(slug("../../etc/passwd")).toBe("etc-passwd") + expect(slug("로고")).toBe("image") + expect(slug("x".repeat(100))).toHaveLength(48) + }), + ) + + it.effect("accepts only inline images of a type it writes", () => + Effect.sync(() => { + expect(decodeImageDataUrl(`data:image/png;base64,${PIXEL_PNG}`)?.mime).toBe("image/png") + expect(decodeImageDataUrl("https://example.com/a.png")).toBeUndefined() + expect(decodeImageDataUrl("data:image/svg+xml;base64,PHN2Zz4=")).toBeUndefined() + expect(decodeImageDataUrl("data:text/html;base64,PGI+")).toBeUndefined() + }), + ) +}) diff --git a/packages/redrob/test/tool/registry.test.ts b/packages/redrob/test/tool/registry.test.ts index c7c5348aa2..cc61d2704a 100644 --- a/packages/redrob/test/tool/registry.test.ts +++ b/packages/redrob/test/tool/registry.test.ts @@ -150,6 +150,39 @@ describe("tool.registry", () => { }), ) + it.instance("offers image_generate only while a Redrob credential is available", () => + Effect.gen(function* () { + const registry = yield* ToolRegistry.Service + const agents = yield* Agent.Service + const agent = yield* agents.defaultInfo() + const saved = { auth: process.env.REDROB_AUTH_CONTENT, key: process.env.REDROB_API_KEY } + const visible = () => + registry + .tools({ providerID: ProviderV2.ID.redrob, modelID: ModelV2.ID.make("test"), agent }) + .pipe(Effect.map((tools) => tools.map((tool) => tool.id).includes("image_generate"))) + try { + delete process.env.REDROB_API_KEY + process.env.REDROB_AUTH_CONTENT = JSON.stringify({}) + expect(yield* visible()).toBe(false) + + process.env.REDROB_AUTH_CONTENT = JSON.stringify({ redrob: { type: "api", key: "rk_test" } }) + expect(yield* visible()).toBe(true) + + process.env.REDROB_AUTH_CONTENT = JSON.stringify({}) + process.env.REDROB_API_KEY = "rk_env" + expect(yield* visible()).toBe(true) + } finally { + for (const [name, value] of [ + ["REDROB_AUTH_CONTENT", saved.auth], + ["REDROB_API_KEY", saved.key], + ] as const) { + if (value === undefined) delete process.env[name] + else process.env[name] = value + } + } + }), + ) + it.instance("hides task background parameter unless experimental background subagents are enabled", () => Effect.gen(function* () { const registry = yield* ToolRegistry.Service diff --git a/packages/redrob/test/tool/speech_generate.test.ts b/packages/redrob/test/tool/speech_generate.test.ts new file mode 100644 index 0000000000..23843344a9 --- /dev/null +++ b/packages/redrob/test/tool/speech_generate.test.ts @@ -0,0 +1,193 @@ +import { afterEach, beforeEach, describe, expect } from "bun:test" +import { LayerNode } from "@redrob-code/core/effect/layer-node" +import { httpClient } from "@redrob-code/core/effect/app-node-platform" +import { FSUtil } from "@redrob-code/core/fs-util" +import { Cause, Effect, Exit } from "effect" +import { FetchHttpClient } from "effect/unstable/http" +import fs from "fs/promises" +import path from "path" +import { Auth } from "@/auth" +import { Tool } from "@/tool/tool" +import { Truncate } from "@/tool/truncate" +import { Agent } from "../../src/agent/agent" +import { EventV2Bridge } from "../../src/event-v2-bridge" +import { SessionID, MessageID } from "../../src/session/schema" +import { DEFAULT_SPEECH_MODEL, DEFAULT_SPEECH_VOICE, SpeechGenerateTool } from "../../src/tool/speech_generate" +import { disposeAllInstances, TestInstance } from "../fixture/fixture" +import { testEffect } from "../lib/effect" + +/** The first bytes of an MP3 frame, which is what a real answer starts with. */ +const MP3 = new Uint8Array([0xff, 0xf3, 0x44, 0xc4, 0x00, 0x01, 0x02, 0x03]) + +const it = testEffect( + LayerNode.compile( + LayerNode.group([httpClient, Auth.node, FSUtil.node, EventV2Bridge.node, Truncate.node, Agent.node]), + [[httpClient, FetchHttpClient.layer]], + ), +) + +type Seen = { path: string; authorization: string | null; body: Record } + +/** A stand-in for the gateway's speech route, recording what reached it. */ +function gateway(answer: () => Response) { + const seen: Seen[] = [] + const server = Bun.serve({ + port: 0, + async fetch(request) { + const body: Record = await request.json() + seen.push({ path: new URL(request.url).pathname, authorization: request.headers.get("authorization"), body }) + return answer() + }, + }) + return { seen, server } +} + +const audioAnswer = () => + new Response(MP3, { headers: { "content-type": "audio/mpeg", "x-redrob-cost-usd": "0.000042" } }) + +const asks: unknown[] = [] +const ctx = { + sessionID: SessionID.make("ses_test-speech"), + messageID: MessageID.make("msg_test"), + callID: "", + agent: "build", + abort: AbortSignal.any([]), + messages: [], + metadata: () => Effect.void, + ask: (request: unknown) => Effect.sync(() => void asks.push(request)), +} + +const run = Effect.fn("SpeechGenerateToolTest.run")(function* (args: Tool.InferParameters) { + const info = yield* SpeechGenerateTool + const tool = yield* info.init() + return yield* tool.execute(args, ctx) +}) + +const failure = (exit: Exit.Exit) => (Exit.isFailure(exit) ? Cause.pretty(exit.cause) : "") + +const saved = { + url: process.env.REDROB_CONSOLE_URL, + auth: process.env.REDROB_AUTH_CONTENT, + key: process.env.REDROB_API_KEY, +} + +beforeEach(() => { + asks.length = 0 + process.env.REDROB_AUTH_CONTENT = JSON.stringify({ redrob: { type: "api", key: "rk_test_key" } }) + delete process.env.REDROB_API_KEY +}) + +afterEach(async () => { + for (const [name, value] of [ + ["REDROB_CONSOLE_URL", saved.url], + ["REDROB_AUTH_CONTENT", saved.auth], + ["REDROB_API_KEY", saved.key], + ] as const) { + if (value === undefined) delete process.env[name] + else process.env[name] = value + } + await disposeAllInstances() +}) + +describe("tool.speech_generate", () => { + it.instance("speaks the text through the gateway on the engine's key and saves an mp3, with no attachment", () => + Effect.gen(function* () { + const test = yield* TestInstance + const { seen, server } = gateway(audioAnswer) + process.env.REDROB_CONSOLE_URL = server.url.toString() + try { + const result = yield* run({ text: "안녕하세요, quarterly update." }) + + expect(seen).toHaveLength(1) + expect(seen[0].path).toBe("/audio/speech") + expect(seen[0].authorization).toBe("Bearer rk_test_key") + expect(seen[0].body).toEqual({ + model: DEFAULT_SPEECH_MODEL, + input: "안녕하세요, quarterly update.", + response_format: "mp3", + voice: DEFAULT_SPEECH_VOICE, + }) + + const filepath = path.join(test.directory, "artifacts", "quarterly-update.mp3") + expect(new Uint8Array(yield* Effect.promise(() => fs.readFile(filepath)))).toEqual(MP3) + expect(result.output).toContain("artifacts") + expect(result.output).toContain("quarterly-update.mp3") + // 24 code points: five Hangul syllables, ", ", "quarterly", " ", "update." (as the gateway bills). + expect(result.metadata).toMatchObject({ + filepath, + model: DEFAULT_SPEECH_MODEL, + characters: 24, + costUsd: 0.000042, + }) + expect(result.attachments).toBeUndefined() + expect(asks).toEqual([expect.objectContaining({ permission: "edit" })]) + } finally { + void server.stop(true) + } + }), + ) + + it.instance("a named model gets no default voice, and an existing file is never overwritten", () => + Effect.gen(function* () { + const test = yield* TestInstance + const existing = path.join(test.directory, "artifacts", "intro.mp3") + yield* Effect.promise(() => fs.mkdir(path.dirname(existing), { recursive: true })) + yield* Effect.promise(() => fs.writeFile(existing, "keep me")) + const { seen, server } = gateway(audioAnswer) + process.env.REDROB_CONSOLE_URL = server.url.toString() + try { + const result = yield* run({ text: "Hello", model: "hexgrad/kokoro-82m", filename: "intro" }) + expect(seen[0].body.voice).toBeUndefined() + expect(seen[0].body.model).toBe("hexgrad/kokoro-82m") + expect(result.title.endsWith(path.join("artifacts", "intro-2.mp3"))).toBe(true) + expect(yield* Effect.promise(() => fs.readFile(existing, "utf8"))).toBe("keep me") + } finally { + void server.stop(true) + } + }), + ) + + it.instance("text over the limit, or no key, is refused before anything is sent", () => + Effect.gen(function* () { + const { seen, server } = gateway(audioAnswer) + process.env.REDROB_CONSOLE_URL = server.url.toString() + try { + const long = yield* run({ text: "가".repeat(4097) }).pipe(Effect.exit) + expect(failure(long)).toContain("The text is 4097 characters") + process.env.REDROB_AUTH_CONTENT = JSON.stringify({}) + const keyless = yield* run({ text: "Hello" }).pipe(Effect.exit) + expect(failure(keyless)).toContain("Connect Redrob to generate speech") + expect(seen).toHaveLength(0) + } finally { + void server.stop(true) + } + }), + ) + + it.instance("a gateway refusal is relayed, and an answer that is not audio is not saved", () => + Effect.gen(function* () { + const test = yield* TestInstance + const refusal = gateway(() => + Response.json({ error: { message: "Model `x` has no voice `y`." } }, { status: 400 }), + ) + process.env.REDROB_CONSOLE_URL = refusal.server.url.toString() + try { + const exit = yield* run({ text: "Hello", model: "x", voice: "y" }).pipe(Effect.exit) + expect(failure(exit)).toContain("answered 400: Model `x` has no voice `y`.") + } finally { + void refusal.server.stop(true) + } + + const json = gateway(() => Response.json({ ok: true })) + process.env.REDROB_CONSOLE_URL = json.server.url.toString() + try { + const exit = yield* run({ text: "Hello" }).pipe(Effect.exit) + expect(failure(exit)).toContain("not audio") + const written = yield* Effect.promise(() => fs.readdir(path.join(test.directory, "artifacts")).catch(() => [])) + expect(written).toEqual([]) + } finally { + void json.server.stop(true) + } + }), + ) +}) diff --git a/packages/route-labeller/.gitignore b/packages/route-labeller/.gitignore new file mode 100644 index 0000000000..8311315c23 --- /dev/null +++ b/packages/route-labeller/.gitignore @@ -0,0 +1,2 @@ +.route-model/ +dist/ diff --git a/packages/route-labeller/NOTICE.md b/packages/route-labeller/NOTICE.md new file mode 100644 index 0000000000..48a643659b --- /dev/null +++ b/packages/route-labeller/NOTICE.md @@ -0,0 +1,7 @@ +# Route model + +The labeller runs [sentence-transformers/distiluse-base-multilingual-cased-v2](https://huggingface.co/sentence-transformers/distiluse-base-multilingual-cased-v2) +at revision `bfe45d0732ca50787611c0fe107ba278c7f3f889` (its Dense projection, `2_Dense/model.safetensors`), with the +int8 ONNX export and tokenizer of [Xenova/distiluse-base-multilingual-cased-v2](https://huggingface.co/Xenova/distiluse-base-multilingual-cased-v2) +at revision `cad454171d918d9873a2701ba245054b6c1760dd`, licensed under the Apache License 2.0 +(https://www.apache.org/licenses/LICENSE-2.0). The files are unmodified; `src/manifest.json` pins each by SHA-256. diff --git a/packages/route-labeller/README.md b/packages/route-labeller/README.md new file mode 100644 index 0000000000..4d05127b46 --- /dev/null +++ b/packages/route-labeller/README.md @@ -0,0 +1,50 @@ +# @redrob-labs/route-labeller + +Labels a request with its ModelGuide profession and task on the person's machine, for Redrob Auto to route on. + +## What it is + +Redrob Auto routes on the ModelGuide: profession x task x working language, the guide's ranked picks at their ranked effort. This package says which profession and task a request is, locally, and the app sends the result to Console as `redrob.route`. Only the two ids and the runners-up leave the machine. Redrob Cowork, Office and Design all use it, so a request labels the same way in each. + +Without its model the labeller still answers, by words alone, and says so with `labeller.mode = "lexical"`. Console routes Redrob Auto on the ModelGuide only for `"embedding"` labels; lexical ones, and requests with no label at all, route on the legacy task-type table. + +Two passes, combined: a multilingual sentence encoder (distiluse-base-multilingual-cased-v2, int8 ONNX, run with onnxruntime) compared against one prototype per cell, and the lexical pass Console itself runs on an unlabelled request. Without the model it runs the lexical pass alone. + +On the held-out set in `eval/` (132 sentences, en/ko/hi): 84.8% top-1 and 96.2% top-3 with the encoder, 59.8% / 68.2% on words alone. Console tries the runners-up in order, so top-3 is the number that bounds a wrong route. + +## Getting started + +```ts +import { loadRouteLabeller, prepareRouteModel, routeBody } from "@redrob-labs/route-labeller/node"; + +await prepareRouteModel("./route-model"); // fetched and verified once +const { labeller } = await loadRouteLabeller({ directory: "./route-model" }); +const label = await labeller.label("이 계약서의 불리한 조항을 검토해줘"); +// { profession: "lawyer", task: "review", edition: "2026-10-06", +// labeller: { id: "route-labeller/embedding", mode: "embedding", ... }, candidates: [...] } + +await fetch(`${base}/chat/completions`, { + method: "POST", + headers, + body: JSON.stringify({ model: "auto", messages, ...routeBody(label) }), +}); +``` + +In a browser or webview, use the runtime-neutral entry with `onnxruntime-web` and bytes you fetched: `SentenceEncoder.load({ manifest: MANIFEST, model, tokenizer, dense }, ort)`, then `new RouteLabeller(LEXICON, PROTOTYPES, encoder)`. + +`guideProfessions(edition, locale)` turns Console's `GET /v1/guide` into the props of the ModelGuide component in `@redrob-labs/ui`. + +## Development + +| Command | What it does | +| --- | --- | +| `pnpm model` | Fetches the model into `.route-model/`, verified against `src/manifest.json` | +| `pnpm prototypes` | Rebuilds `src/prototypes.json` after the lexicon changes | +| `pnpm eval` | Top-1 / top-3 on `eval/held-out.json`, per language, both passes | +| `pnpm typecheck`, `pnpm build` | Types; the ESM build in `dist/` | + +`src/lexicon.json` is the source of the words. Console's `guide:sync` copies it into each ModelGuide edition, so change it here, rebuild the prototypes, and re-sync Console. + +## License + +MIT. The model is sentence-transformers/distiluse-base-multilingual-cased-v2 (Apache-2.0), see `NOTICE.md`. diff --git a/packages/route-labeller/eval/held-out.json b/packages/route-labeller/eval/held-out.json new file mode 100644 index 0000000000..3c0572eced --- /dev/null +++ b/packages/route-labeller/eval/held-out.json @@ -0,0 +1,662 @@ +[ + { + "text": "Mock up a settings page for our iPad app with dark mode", + "cell": "designer/design-screens", + "language": "en" + }, + { + "text": "I need an illustration for our newsletter header, something playful", + "cell": "designer/create-graphics", + "language": "en" + }, + { + "text": "Here are notes from eight customer interviews, what patterns do you see?", + "cell": "designer/research-users", + "language": "en" + }, + { + "text": "Document the spacing, colours and states of this button component for the devs", + "cell": "designer/handoff-specs", + "language": "en" + }, + { + "text": "Is this checkout page accessible to screen reader users?", + "cell": "designer/review-usability", + "language": "en" + }, + { + "text": "Implement pagination for the /orders endpoint in our Express app", + "cell": "engineer/build-features", + "language": "en" + }, + { + "text": "My React component re-renders forever and the browser freezes, why?", + "cell": "engineer/debug-fix", + "language": "en" + }, + { + "text": "How should we shard our Postgres database as we grow to 50M users?", + "cell": "engineer/design-systems", + "language": "en" + }, + { + "text": "Add Jest tests covering the edge cases of this currency formatter", + "cell": "engineer/write-tests", + "language": "en" + }, + { + "text": "Look over this diff before I merge it and tell me what's risky", + "cell": "engineer/review-code", + "language": "en" + }, + { + "text": "Help me tell our story to seed investors in ten slides", + "cell": "founder/raise-funding", + "language": "en" + }, + { + "text": "How many months of runway do we have if we hire two more engineers?", + "cell": "founder/plan-finances", + "language": "en" + }, + { + "text": "Draft a pitch email to land our first paying customers", + "cell": "founder/sell-customers", + "language": "en" + }, + { + "text": "Who should be our first three hires after the founders?", + "cell": "founder/hire-team", + "language": "en" + }, + { + "text": "Write the quarterly update to our shareholders with revenue and burn", + "cell": "founder/update-investors", + "language": "en" + }, + { + "text": "Can employees carry unused vacation days into next year?", + "cell": "hr/answer-policy-questions", + "language": "en" + }, + { + "text": "Draft an offer letter for a marketing manager starting next month", + "cell": "hr/prepare-employment-documents", + "language": "en" + }, + { + "text": "An employee reported their manager for bullying; what are our next steps?", + "cell": "hr/handle-employee-relations", + "language": "en" + }, + { + "text": "Write review feedback for an engineer who exceeded expectations", + "cell": "hr/run-performance-reviews", + "language": "en" + }, + { + "text": "Write our policy on working from abroad for the handbook", + "cell": "hr/write-hr-policies", + "language": "en" + }, + { + "text": "Does this fintech startup fit our fund's thesis? Here's their deck", + "cell": "investor/screen-deals", + "language": "en" + }, + { + "text": "Who are the main competitors in the EV charging market?", + "cell": "investor/research-companies", + "language": "en" + }, + { + "text": "Write the IC memo recommending we lead this Series B", + "cell": "investor/write-memos", + "language": "en" + }, + { + "text": "Go through the data room and flag anything odd in the financials", + "cell": "investor/review-diligence", + "language": "en" + }, + { + "text": "Summarise portfolio performance for our LPs this quarter", + "cell": "investor/report-portfolio", + "language": "en" + }, + { + "text": "Email the client explaining the court date moved and what it means for them", + "cell": "lawyer/client", + "language": "en" + }, + { + "text": "What precedent exists on enforcing arbitration clauses in employment contracts?", + "cell": "lawyer/research", + "language": "en" + }, + { + "text": "Check this supplier agreement for one-sided indemnification", + "cell": "lawyer/review", + "language": "en" + }, + { + "text": "Prepare a memorandum analysing liability for the warehouse fire", + "cell": "lawyer/memo", + "language": "en" + }, + { + "text": "Draft a consulting agreement between a freelancer and a startup", + "cell": "lawyer/draft", + "language": "en" + }, + { + "text": "Write a blog post announcing our new feature for small shops", + "cell": "marketer/write-content", + "language": "en" + }, + { + "text": "Plan a holiday marketing campaign across social and email", + "cell": "marketer/plan-campaigns", + "language": "en" + }, + { + "text": "Write a win-back email sequence for lapsed subscribers", + "cell": "marketer/run-messaging-campaigns", + "language": "en" + }, + { + "text": "Which of last quarter's ads had the best return on spend?", + "cell": "marketer/analyze-campaigns", + "language": "en" + }, + { + "text": "Improve this product page so it ranks on Google", + "cell": "marketer/optimize-search", + "language": "en" + }, + { + "text": "Help me decide what goes into next quarter's roadmap", + "cell": "pm/plan-roadmap", + "language": "en" + }, + { + "text": "Write a product spec for in-app notifications with acceptance criteria", + "cell": "pm/write-prd", + "language": "en" + }, + { + "text": "Cluster these 200 support tickets into product themes", + "cell": "pm/synthesize-feedback", + "language": "en" + }, + { + "text": "Write a launch status update for the leadership team", + "cell": "pm/stakeholder-updates", + "language": "en" + }, + { + "text": "Did the new onboarding flow improve week-one retention?", + "cell": "pm/analyze-metrics", + "language": "en" + }, + { + "text": "Find data scientists in Seoul open to a new role and message them", + "cell": "recruiter/find-contact-candidates", + "language": "en" + }, + { + "text": "Rank these applicants for the backend role", + "cell": "recruiter/screen-resumes", + "language": "en" + }, + { + "text": "Prepare a structured interview for a sales manager", + "cell": "recruiter/prepare-interviews", + "language": "en" + }, + { + "text": "Write a job posting for a part-time bookkeeper", + "cell": "recruiter/write-job-descriptions", + "language": "en" + }, + { + "text": "Find a time next week for the final round with three interviewers", + "cell": "recruiter/schedule-interviews", + "language": "en" + }, + { + "text": "Write a follow-up to a lead who opened my email but didn't reply", + "cell": "sales/write-outreach", + "language": "en" + }, + { + "text": "Put together a proposal for a 50-seat annual contract", + "cell": "sales/create-proposals", + "language": "en" + }, + { + "text": "A customer wants to know if we integrate with Salesforce; reply to them", + "cell": "sales/answer-customers", + "language": "en" + }, + { + "text": "Tell me about Acme Corp before my discovery call", + "cell": "sales/research-prospects", + "language": "en" + }, + { + "text": "Log today's calls in HubSpot and move deals to the right stage", + "cell": "sales/update-crm", + "language": "en" + }, + { + "text": "Reply to a customer whose parcel arrived damaged", + "cell": "small-team/answer-customers", + "language": "en" + }, + { + "text": "Categorise this month's receipts and tell me my profit", + "cell": "small-team/keep-books", + "language": "en" + }, + { + "text": "Remind a client politely that their invoice is 30 days overdue", + "cell": "small-team/send-invoices", + "language": "en" + }, + { + "text": "Make an Instagram post for our café's new menu", + "cell": "small-team/create-marketing", + "language": "en" + }, + { + "text": "Price up a quote for painting a three-bedroom house", + "cell": "small-team/prepare-quotes", + "language": "en" + }, + { + "text": "아이패드 앱 설정 화면 시안을 다크 모드로 만들어줘", + "cell": "designer/design-screens", + "language": "ko" + }, + { + "text": "뉴스레터 상단에 들어갈 귀여운 일러스트가 필요해", + "cell": "designer/create-graphics", + "language": "ko" + }, + { + "text": "고객 인터뷰 여덟 건 메모야, 공통된 패턴을 찾아줘", + "cell": "designer/research-users", + "language": "ko" + }, + { + "text": "이 버튼 컴포넌트의 간격, 색상, 상태를 개발자용으로 정리해줘", + "cell": "designer/handoff-specs", + "language": "ko" + }, + { + "text": "이 결제 화면이 스크린 리더 사용자에게 접근 가능한지 봐줘", + "cell": "designer/review-usability", + "language": "ko" + }, + { + "text": "Express 앱의 주문 API에 페이지네이션을 구현해줘", + "cell": "engineer/build-features", + "language": "ko" + }, + { + "text": "리액트 컴포넌트가 무한 렌더링돼서 브라우저가 멈춰, 원인이 뭐야?", + "cell": "engineer/debug-fix", + "language": "ko" + }, + { + "text": "사용자가 5천만 명으로 늘면 Postgres를 어떻게 샤딩해야 할까?", + "cell": "engineer/design-systems", + "language": "ko" + }, + { + "text": "이 통화 포맷 함수의 경계 사례를 다루는 테스트를 추가해줘", + "cell": "engineer/write-tests", + "language": "ko" + }, + { + "text": "머지하기 전에 이 변경 사항을 검토하고 위험한 부분을 알려줘", + "cell": "engineer/review-code", + "language": "ko" + }, + { + "text": "시드 투자자에게 보여줄 열 장짜리 발표 자료를 만들어줘", + "cell": "founder/raise-funding", + "language": "ko" + }, + { + "text": "엔지니어 두 명을 더 뽑으면 런웨이가 몇 달 남아?", + "cell": "founder/plan-finances", + "language": "ko" + }, + { + "text": "첫 유료 고객을 잡기 위한 제안 메일을 써줘", + "cell": "founder/sell-customers", + "language": "ko" + }, + { + "text": "창업자 다음으로 누구를 먼저 뽑아야 할까?", + "cell": "founder/hire-team", + "language": "ko" + }, + { + "text": "주주들에게 보낼 분기 업데이트를 매출과 지출 포함해서 써줘", + "cell": "founder/update-investors", + "language": "ko" + }, + { + "text": "남은 연차를 내년으로 이월할 수 있는지 직원이 물어봤어", + "cell": "hr/answer-policy-questions", + "language": "ko" + }, + { + "text": "다음 달 입사하는 마케팅 매니저의 근로계약서를 준비해줘", + "cell": "hr/prepare-employment-documents", + "language": "ko" + }, + { + "text": "직원이 팀장을 괴롭힘으로 신고했어, 다음 절차가 뭐야?", + "cell": "hr/handle-employee-relations", + "language": "ko" + }, + { + "text": "기대 이상으로 잘한 엔지니어의 평가 코멘트를 써줘", + "cell": "hr/run-performance-reviews", + "language": "ko" + }, + { + "text": "해외 원격 근무에 관한 규정을 핸드북용으로 작성해줘", + "cell": "hr/write-hr-policies", + "language": "ko" + }, + { + "text": "이 핀테크 스타트업이 우리 펀드 투자 기준에 맞는지 봐줘", + "cell": "investor/screen-deals", + "language": "ko" + }, + { + "text": "전기차 충전 시장의 주요 경쟁사는 누구야?", + "cell": "investor/research-companies", + "language": "ko" + }, + { + "text": "이 시리즈 B를 리드하자는 투자심의 메모를 써줘", + "cell": "investor/write-memos", + "language": "ko" + }, + { + "text": "데이터룸 재무 자료에서 이상한 점을 찾아줘", + "cell": "investor/review-diligence", + "language": "ko" + }, + { + "text": "이번 분기 포트폴리오 성과를 LP에게 보고할 수 있게 정리해줘", + "cell": "investor/report-portfolio", + "language": "ko" + }, + { + "text": "의뢰인에게 재판 기일이 바뀐 사실과 그 의미를 설명하는 메일을 써줘", + "cell": "lawyer/client", + "language": "ko" + }, + { + "text": "근로계약의 중재 조항 효력에 관한 판례가 있어?", + "cell": "lawyer/research", + "language": "ko" + }, + { + "text": "이 공급 계약서에 일방적인 손해배상 조항이 있는지 확인해줘", + "cell": "lawyer/review", + "language": "ko" + }, + { + "text": "창고 화재의 책임 소재를 분석하는 의견서를 작성해줘", + "cell": "lawyer/memo", + "language": "ko" + }, + { + "text": "프리랜서와 스타트업 간 용역 계약서 초안을 써줘", + "cell": "lawyer/draft", + "language": "ko" + }, + { + "text": "소상공인용 신기능을 알리는 블로그 글을 써줘", + "cell": "marketer/write-content", + "language": "ko" + }, + { + "text": "SNS와 이메일을 아우르는 연말 마케팅 캠페인을 기획해줘", + "cell": "marketer/plan-campaigns", + "language": "ko" + }, + { + "text": "이탈한 구독자를 되찾는 이메일 시리즈를 써줘", + "cell": "marketer/run-messaging-campaigns", + "language": "ko" + }, + { + "text": "지난 분기 광고 중 광고 효율이 가장 좋았던 건 뭐야?", + "cell": "marketer/analyze-campaigns", + "language": "ko" + }, + { + "text": "이 상품 페이지가 구글 검색에서 상위에 오르게 고쳐줘", + "cell": "marketer/optimize-search", + "language": "ko" + }, + { + "text": "다음 분기 로드맵에 무엇을 넣을지 정하는 걸 도와줘", + "cell": "pm/plan-roadmap", + "language": "ko" + }, + { + "text": "인앱 알림 기능의 제품 명세를 인수 조건과 함께 작성해줘", + "cell": "pm/write-prd", + "language": "ko" + }, + { + "text": "고객 문의 200건을 제품 주제별로 묶어줘", + "cell": "pm/synthesize-feedback", + "language": "ko" + }, + { + "text": "경영진에게 보낼 출시 진행 상황 보고를 써줘", + "cell": "pm/stakeholder-updates", + "language": "ko" + }, + { + "text": "새 온보딩이 첫 주 리텐션을 높였는지 분석해줘", + "cell": "pm/analyze-metrics", + "language": "ko" + }, + { + "text": "이직 의향이 있는 서울의 데이터 사이언티스트를 찾아 연락해줘", + "cell": "recruiter/find-contact-candidates", + "language": "ko" + }, + { + "text": "백엔드 직무 지원자들의 순위를 매겨줘", + "cell": "recruiter/screen-resumes", + "language": "ko" + }, + { + "text": "영업 매니저 구조화 면접 질문을 준비해줘", + "cell": "recruiter/prepare-interviews", + "language": "ko" + }, + { + "text": "파트타임 경리 채용 공고를 써줘", + "cell": "recruiter/write-job-descriptions", + "language": "ko" + }, + { + "text": "면접관 세 명과 다음 주 최종 면접 시간을 잡아줘", + "cell": "recruiter/schedule-interviews", + "language": "ko" + }, + { + "text": "메일을 열어보고 답이 없는 리드에게 보낼 팔로업을 써줘", + "cell": "sales/write-outreach", + "language": "ko" + }, + { + "text": "50석 연간 계약용 제안서를 만들어줘", + "cell": "sales/create-proposals", + "language": "ko" + }, + { + "text": "고객이 세일즈포스 연동이 되는지 물어봤어, 답변해줘", + "cell": "sales/answer-customers", + "language": "ko" + }, + { + "text": "디스커버리 미팅 전에 Acme라는 회사를 조사해줘", + "cell": "sales/research-prospects", + "language": "ko" + }, + { + "text": "오늘 통화 내용을 CRM에 기록하고 딜 단계를 옮겨줘", + "cell": "sales/update-crm", + "language": "ko" + }, + { + "text": "택배가 파손돼서 왔다는 고객에게 답장해줘", + "cell": "small-team/answer-customers", + "language": "ko" + }, + { + "text": "이번 달 영수증을 분류하고 이익이 얼마인지 알려줘", + "cell": "small-team/keep-books", + "language": "ko" + }, + { + "text": "청구서가 30일 연체된 거래처에 정중하게 독촉해줘", + "cell": "small-team/send-invoices", + "language": "ko" + }, + { + "text": "카페 신메뉴를 알리는 인스타그램 게시물을 만들어줘", + "cell": "small-team/create-marketing", + "language": "ko" + }, + { + "text": "방 세 개짜리 집 도색 견적을 뽑아줘", + "cell": "small-team/prepare-quotes", + "language": "ko" + }, + { + "text": "हमारे न्यूज़लेटर के लिए एक मज़ेदार चित्र बनाओ", + "cell": "designer/create-graphics", + "language": "hi" + }, + { + "text": "क्या यह चेकआउट पेज स्क्रीन रीडर इस्तेमाल करने वालों के लिए सुलभ है?", + "cell": "designer/review-usability", + "language": "hi" + }, + { + "text": "मेरा रिएक्ट कंपोनेंट बार-बार रेंडर हो रहा है, गड़बड़ी कहाँ है?", + "cell": "engineer/debug-fix", + "language": "hi" + }, + { + "text": "इस करेंसी फ़ॉर्मैटर के लिए टेस्ट जोड़ो", + "cell": "engineer/write-tests", + "language": "hi" + }, + { + "text": "सीड निवेशकों के लिए दस स्लाइड का पिच डेक बनाओ", + "cell": "founder/raise-funding", + "language": "hi" + }, + { + "text": "दो और इंजीनियर रखने पर हमारे पास कितने महीने का रनवे बचेगा?", + "cell": "founder/plan-finances", + "language": "hi" + }, + { + "text": "क्या कर्मचारी बची हुई छुट्टियाँ अगले साल ले जा सकते हैं?", + "cell": "hr/answer-policy-questions", + "language": "hi" + }, + { + "text": "अगले महीने जुड़ने वाले मैनेजर के लिए ऑफ़र लेटर तैयार करो", + "cell": "hr/prepare-employment-documents", + "language": "hi" + }, + { + "text": "ईवी चार्जिंग बाज़ार में मुख्य प्रतिस्पर्धी कौन हैं?", + "cell": "investor/research-companies", + "language": "hi" + }, + { + "text": "डेटा रूम के वित्तीय दस्तावेज़ों में गड़बड़ियाँ ढूँढो", + "cell": "investor/review-diligence", + "language": "hi" + }, + { + "text": "रोज़गार अनुबंध में मध्यस्थता खंड पर कोई अदालती फ़ैसला है?", + "cell": "lawyer/research", + "language": "hi" + }, + { + "text": "फ़्रीलांसर और स्टार्टअप के बीच परामर्श अनुबंध का मसौदा लिखो", + "cell": "lawyer/draft", + "language": "hi" + }, + { + "text": "छोटी दुकानों के लिए नई सुविधा पर ब्लॉग पोस्ट लिखो", + "cell": "marketer/write-content", + "language": "hi" + }, + { + "text": "पिछली तिमाही के किस विज्ञापन का प्रदर्शन सबसे अच्छा रहा?", + "cell": "marketer/analyze-campaigns", + "language": "hi" + }, + { + "text": "इन-ऐप सूचनाओं के लिए प्रोडक्ट स्पेक लिखो", + "cell": "pm/write-prd", + "language": "hi" + }, + { + "text": "क्या नए ऑनबोर्डिंग से पहले हफ़्ते का रिटेंशन बढ़ा?", + "cell": "pm/analyze-metrics", + "language": "hi" + }, + { + "text": "बैकएंड पद के आवेदकों को क्रम में लगाओ", + "cell": "recruiter/screen-resumes", + "language": "hi" + }, + { + "text": "पार्ट-टाइम अकाउंटेंट के लिए नौकरी का विज्ञापन लिखो", + "cell": "recruiter/write-job-descriptions", + "language": "hi" + }, + { + "text": "जिस लीड ने ईमेल खोला पर जवाब नहीं दिया उसे फ़ॉलो-अप लिखो", + "cell": "sales/write-outreach", + "language": "hi" + }, + { + "text": "आज की कॉल सीआरएम में दर्ज करो और डील आगे बढ़ाओ", + "cell": "sales/update-crm", + "language": "hi" + }, + { + "text": "जिस ग्राहक का चालान 30 दिन से बकाया है उसे विनम्रता से याद दिलाओ", + "cell": "small-team/send-invoices", + "language": "hi" + }, + { + "text": "हमारे कैफ़े के नए मेन्यू के लिए इंस्टाग्राम पोस्ट बनाओ", + "cell": "small-team/create-marketing", + "language": "hi" + } +] \ No newline at end of file diff --git a/packages/route-labeller/package.json b/packages/route-labeller/package.json new file mode 100644 index 0000000000..f7ae46c2d7 --- /dev/null +++ b/packages/route-labeller/package.json @@ -0,0 +1,84 @@ +{ + "name": "@redrob-labs/route-labeller", + "version": "0.0.0", + "description": "Labels a request with its ModelGuide profession and task on the person's machine, for Redrob Auto to route on.", + "license": "MIT", + "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/redrob-labs/redrob-code.git", + "directory": "packages/route-labeller" + }, + "exports": { + ".": { + "types": "./src/index.ts", + "development": "./src/index.ts", + "default": "./dist/index.js" + }, + "./node": { + "types": "./src/node.ts", + "development": "./src/node.ts", + "default": "./dist/node.js" + }, + "./lexicon.json": "./src/lexicon.json", + "./manifest.json": "./src/manifest.json", + "./wordpiece": { + "types": "./src/wordpiece.ts", + "development": "./src/wordpiece.ts", + "default": "./dist/wordpiece.js" + } + }, + "files": [ + "dist", + "src", + "eval", + "README.md", + "NOTICE.md" + ], + "scripts": { + "build": "tsup", + "typecheck": "tsgo --noEmit", + "model": "bun scripts/prepare-model.ts", + "prototypes": "bun scripts/build-prototypes.ts", + "eval": "bun scripts/evaluate.ts", + "prepublishOnly": "bun run build" + }, + "peerDependencies": { + "onnxruntime-node": ">=1.20.0", + "onnxruntime-web": ">=1.20.0" + }, + "peerDependenciesMeta": { + "onnxruntime-node": { + "optional": true + }, + "onnxruntime-web": { + "optional": true + } + }, + "devDependencies": { + "@types/node": "catalog:", + "@typescript/native-preview": "catalog:", + "onnxruntime-node": "1.23.0", + "tsup": "^8.5.0", + "typescript": "catalog:" + }, + "publishConfig": { + "access": "public", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./node": { + "types": "./dist/node.d.ts", + "default": "./dist/node.js" + }, + "./wordpiece": { + "types": "./dist/wordpiece.d.ts", + "default": "./dist/wordpiece.js" + }, + "./lexicon.json": "./src/lexicon.json", + "./manifest.json": "./src/manifest.json" + } + } +} diff --git a/packages/route-labeller/scripts/build-prototypes.ts b/packages/route-labeller/scripts/build-prototypes.ts new file mode 100644 index 0000000000..7f1cf8ad3f --- /dev/null +++ b/packages/route-labeller/scripts/build-prototypes.ts @@ -0,0 +1,55 @@ +/* + * Builds src/prototypes.json: one vector per ModelGuide cell, the mean of the embeddings of that + * cell's example sentences (every language) and its English task terms, at unit length. + * + * pnpm --filter @redrob-labs/route-labeller model && pnpm --filter @redrob-labs/route-labeller prototypes + * + * Committed rather than computed at load, because loading would otherwise embed every example on + * every start, a few seconds of CPU nobody needs to spend twice. Rebuild after the lexicon changes; + * the labeller refuses prototypes built with a different model. + */ +import { readFile, writeFile } from "node:fs/promises"; +import { join } from "node:path"; + +import { LEXICON, MANIFEST, normalise, SentenceEncoder, type OrtRuntime } from "../src/index.ts"; + +const directory = process.env.REDROB_ROUTE_MODEL_DIR ?? join(import.meta.dir, "..", ".route-model"); +const read = (file: string) => readFile(join(directory, file)).then((buffer) => new Uint8Array(buffer)); +const ort = (await import("onnxruntime-node")) as unknown as OrtRuntime; +const encoder = await SentenceEncoder.load( + { + manifest: MANIFEST, + model: await read(MANIFEST.model.file), + tokenizer: await read(MANIFEST.tokenizer.file), + dense: await read(MANIFEST.dense.file), + }, + ort, +); + +const cells: Record = {}; +for (const [cell, entry] of Object.entries(LEXICON.tasks)) { + const sentences = [ + ...(entry.examples?.en ?? []), + ...(entry.examples?.ko ?? []), + ...(entry.examples?.hi ?? []), + (entry.en ?? []).join(", "), + ].filter((sentence) => sentence.trim()); + const sum = new Float32Array(MANIFEST.dimensions); + for (const sentence of sentences) { + const vector = await encoder.embed(sentence); + for (let k = 0; k < sum.length; k += 1) sum[k]! += vector[k]!; + } + cells[cell] = Array.from(normalise(sum), (value) => Math.round(value * 1e5) / 1e5); +} + +await writeFile( + join(import.meta.dir, "..", "src", "prototypes.json"), + `${JSON.stringify({ + model: encoder.id, + lexiconVersion: LEXICON.version, + edition: LEXICON.edition, + dimensions: MANIFEST.dimensions, + cells, + })}\n`, +); +console.log(`${Object.keys(cells).length} prototypes written for ${encoder.id}`); diff --git a/packages/route-labeller/scripts/evaluate.ts b/packages/route-labeller/scripts/evaluate.ts new file mode 100644 index 0000000000..334a5d27d1 --- /dev/null +++ b/packages/route-labeller/scripts/evaluate.ts @@ -0,0 +1,43 @@ +/* + * How often the labeller names the right cell, on held-out sentences in all three languages. + * + * pnpm --filter @redrob-labs/route-labeller eval + * + * The held-out set (eval/held-out.json) is written separately from the lexicon's examples, so the + * prototypes never saw it. Reports top-1 and top-3 (the label or one of its runners-up, which Console + * tries in order) for the full labeller and for the lexical pass alone, per language. + */ +import { readFile } from "node:fs/promises"; +import { join } from "node:path"; + +import { loadRouteLabeller } from "../src/node.ts"; +import { LEXICON, RouteLabeller } from "../src/index.ts"; + +type Case = { text: string; cell: string; language: string }; +const cases = JSON.parse(await readFile(join(import.meta.dir, "..", "eval", "held-out.json"), "utf8")) as Case[]; +const directory = process.env.REDROB_ROUTE_MODEL_DIR ?? join(import.meta.dir, "..", ".route-model"); +const { labeller, reason } = await loadRouteLabeller({ directory }); +if (reason) throw new Error(`the embedding pass did not load: ${reason}`); +const lexical = new RouteLabeller(LEXICON, null, null); + +async function score(subject: RouteLabeller) { + const byLanguage: Record = {}; + for (const item of cases) { + const label = await subject.label(item.text); + const ranked = [`${label.profession}/${label.task}`, ...label.candidates.map((c) => `${c.profession}/${c.task}`)]; + const row = (byLanguage[item.language] ??= { n: 0, top1: 0, top3: 0 }); + row.n += 1; + if (ranked[0] === item.cell) row.top1 += 1; + if (ranked.slice(0, 3).includes(item.cell)) row.top3 += 1; + } + return byLanguage; +} + +for (const [name, subject] of [["embedding + lexical", labeller], ["lexical only", lexical]] as const) { + const result = await score(subject); + const all = Object.values(result).reduce((a, r) => ({ n: a.n + r.n, top1: a.top1 + r.top1, top3: a.top3 + r.top3 }), { n: 0, top1: 0, top3: 0 }); + console.log(`\n${name}`); + for (const [language, row] of Object.entries({ ...result, all })) { + console.log(` ${language.padEnd(4)} n=${String(row.n).padStart(3)} top-1 ${(100 * row.top1 / row.n).toFixed(1)}% top-3 ${(100 * row.top3 / row.n).toFixed(1)}%`); + } +} diff --git a/packages/route-labeller/scripts/prepare-model.ts b/packages/route-labeller/scripts/prepare-model.ts new file mode 100644 index 0000000000..cbfd4ef3f6 --- /dev/null +++ b/packages/route-labeller/scripts/prepare-model.ts @@ -0,0 +1,18 @@ +/* + * Fetches the route model into a directory, verified against the pinned manifest. + * + * pnpm --filter @redrob-labs/route-labeller model [directory] + * + * Defaults to .route-model/ beside this package, which is where the prototype and evaluation + * scripts read it from. REDROB_ROUTE_MODEL_SOURCE copies from a local folder instead. + */ +import { join } from "node:path"; + +import { prepareRouteModel } from "../src/node.ts"; + +const directory = process.argv[2] ?? join(import.meta.dir, "..", ".route-model"); +await prepareRouteModel(directory, { + source: process.env.REDROB_ROUTE_MODEL_SOURCE?.trim() || null, + log: (line) => console.error(`[route-model] ${line}`), +}); +console.log(`route model ready in ${directory}`); diff --git a/packages/route-labeller/src/encoder.ts b/packages/route-labeller/src/encoder.ts new file mode 100644 index 0000000000..22a32c9806 --- /dev/null +++ b/packages/route-labeller/src/encoder.ts @@ -0,0 +1,145 @@ +/* + * A multilingual sentence encoder on onnxruntime: distiluse-base-multilingual-cased-v2. + * + * Chosen because it uses the same BERT WordPiece tokenizer the privacy detector already ships + * (wordpiece.ts, unchanged), so the labeller needs no second tokenizer implementation, and because it + * was trained so that a sentence and its translation land close together across fifty languages, + * Korean and Hindi among them. That is what lets one set of prototype sentences cover all three + * working languages the ModelGuide ranks. + * + * The pipeline is the model's own: token embeddings, mean pooling over the attention mask, then the + * Dense 768 -> 512 projection with tanh. The ONNX export covers the transformer; pooling and the + * projection are done here, from the weights the model publishes. + * + * Runtime-neutral: bytes in, no filesystem, no node:crypto. Integrity uses WebCrypto, which Node 20+, + * Electron and every webview have, so the same code runs in redrob-server, Office's main process and + * Design's webview. + */ +import type { OrtRuntime, OrtSession, RouteModelManifest } from "./types.js"; +import { vocabFromTokenizerJson, WordPiece } from "./wordpiece.js"; + +export class RouteModelIntegrityError extends Error {} + +export async function sha256Hex(bytes: Uint8Array): Promise { + const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes as unknown as ArrayBuffer); + return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join(""); +} + +type Dense = { weight: Float32Array; bias: Float32Array; inputs: number; outputs: number }; + +/** Reads the projection out of a safetensors file: an 8-byte header length, a JSON header, the data. */ +export function readDense(bytes: Uint8Array): Dense { + const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + const headerLength = Number(view.getBigUint64(0, true)); + const header = JSON.parse(new TextDecoder().decode(bytes.subarray(8, 8 + headerLength))) as Record< + string, + { dtype: string; shape: number[]; data_offsets: [number, number] } + >; + const base = 8 + headerLength; + const tensor = (name: string) => { + const entry = header[name]; + if (!entry || entry.dtype !== "F32") throw new Error(`dense weights have no F32 ${name}`); + const [from, to] = entry.data_offsets; + const copy = bytes.slice(base + from, base + to); + return { data: new Float32Array(copy.buffer, copy.byteOffset, (to - from) / 4), shape: entry.shape }; + }; + const weight = tensor("linear.weight"); + const bias = tensor("linear.bias"); + const [outputs, inputs] = weight.shape as [number, number]; + return { weight: weight.data, bias: bias.data, inputs, outputs }; +} + +export type EncoderFiles = { manifest: RouteModelManifest; model: Uint8Array; tokenizer: Uint8Array; dense: Uint8Array }; + +export class SentenceEncoder { + readonly id: string; + + private constructor( + private readonly ort: OrtRuntime, + private readonly session: OrtSession, + private readonly tokenizer: WordPiece, + private readonly dense: Dense, + readonly manifest: RouteModelManifest, + ) { + this.id = `${manifest.id}@${manifest.revision.slice(0, 8)}`; + } + + /** Verifies every file against the manifest before any of it is parsed or run. */ + static async load( + files: EncoderFiles, + ort: OrtRuntime, + options: { threads?: number } = {}, + ): Promise { + const { manifest } = files; + const checks: Array<[string, Uint8Array, string]> = [ + ["model", files.model, manifest.model.sha256], + ["tokenizer", files.tokenizer, manifest.tokenizer.sha256], + ["dense", files.dense, manifest.dense.sha256], + ]; + for (const [name, bytes, expected] of checks) { + if ((await sha256Hex(bytes)) !== expected) { + throw new RouteModelIntegrityError(`route model ${name} does not match its manifest`); + } + } + const tokenizer = new WordPiece({ + vocab: vocabFromTokenizerJson(JSON.parse(new TextDecoder().decode(files.tokenizer))), + }); + const session = await ort.InferenceSession.create(files.model, { + executionProviders: ["cpu"], + graphOptimizationLevel: "all", + intraOpNumThreads: options.threads ?? 2, + interOpNumThreads: 1, + }); + return new SentenceEncoder(ort, session, tokenizer, readDense(files.dense), manifest); + } + + /** One unit-length vector per text. Texts are encoded one at a time: requests are one sentence. */ + async embed(text: string): Promise { + const cls = this.tokenizer.id("[CLS]"); + const sep = this.tokenizer.id("[SEP]"); + const pieces = this.tokenizer.tokenize(text.normalize("NFC")).slice(0, this.manifest.maxTokens - 2); + const ids = BigInt64Array.from([cls, ...pieces.map((token) => token.id), sep].map(BigInt)); + const dims = [1, ids.length] as const; + const feeds: Record = { + input_ids: new this.ort.Tensor("int64", ids, dims), + attention_mask: new this.ort.Tensor("int64", new BigInt64Array(ids.length).fill(1n), dims), + }; + if (this.session.inputNames.includes("token_type_ids")) { + feeds.token_type_ids = new this.ort.Tensor("int64", new BigInt64Array(ids.length), dims); + } + const result = await this.session.run(feeds); + const hidden = (result.last_hidden_state ?? Object.values(result)[0])!; + const states = hidden.data as Float32Array; + const width = this.dense.inputs; + const tokens = ids.length; + + // Mean pooling: every position is attended, so the mean is over all of them. + const pooled = new Float32Array(width); + for (let t = 0; t < tokens; t += 1) { + for (let k = 0; k < width; k += 1) pooled[k]! += states[t * width + k]!; + } + for (let k = 0; k < width; k += 1) pooled[k]! /= tokens; + + const out = new Float32Array(this.dense.outputs); + for (let o = 0; o < this.dense.outputs; o += 1) { + let sum = this.dense.bias[o]!; + const row = o * width; + for (let k = 0; k < width; k += 1) sum += this.dense.weight[row + k]! * pooled[k]!; + out[o] = Math.tanh(sum); + } + return normalise(out); + } +} + +export function normalise(vector: Float32Array): Float32Array { + let norm = 0; + for (const value of vector) norm += value * value; + norm = Math.sqrt(norm) || 1; + return vector.map((value) => value / norm); +} + +export function cosine(a: ArrayLike, b: ArrayLike): number { + let dot = 0; + for (let k = 0; k < a.length; k += 1) dot += a[k]! * b[k]!; + return dot; +} diff --git a/packages/route-labeller/src/guide.ts b/packages/route-labeller/src/guide.ts new file mode 100644 index 0000000000..7b2ed9a143 --- /dev/null +++ b/packages/route-labeller/src/guide.ts @@ -0,0 +1,276 @@ + +/* + * The ModelGuide edition Redrob Auto routes on, read from Console's `GET /v1/guide`, and turned into + * the props of the ModelGuide component in @redrob-labs/ui. + * + * Shared so Cowork, Office and Design render the guide the same way, from the same edition the + * router reads, rather than each bundling a copy that is right until the next monthly edition. The + * Console web app carries the same mapping (apps/web/src/lib/guide/guide.ts) because it cannot + * depend on this package's workspace. + */ + +export type GuideKind = 'measured' | 'published' | 'derived' | 'estimate'; +type Label = { en: string; ko: string }; + +export type GuideEditionPick = { + id: string; + rank: number; + steps: Array<{ model: string; catalogueId: string; effort?: string; role?: 'image' }>; + harness: string; + kind: GuideKind; + score: { quality: number; reliability: number; speed: number; cost: number; ci: number }; + monthly: number; + monthlyKind: GuideKind; + monthlyRange: [number, number]; + efforts: Array<[string, number]>; + comingSoon: boolean; + missing: string[]; + flags: string[]; + sources: Array<{ + label: string; + value: string; + kind: GuideKind; + url?: string; + date: string; + model?: string; + }>; +}; + +export type GuideEditionResponse = { + asOf: string; + editions: string[]; + harness: string; + weights: { quality: number; reliability: number; speed: number; cost: number }; + models: Record; + professions: Array<{ + id: string; + label: Label; + tasks: Array<{ + id: string; + label: Label; + runs: number; + tools: string[]; + picks: Record; + }>; + }>; +}; + +/** + * The live edition from a Console deployment, e.g. `https://console.redrob.ai/api/backend/v1`. + * Null rather than throwing: a guide page says the guide is unavailable instead of failing. + */ +export async function fetchGuide( + baseUrl: string, + fetchImpl: typeof fetch = fetch, +): Promise { + try { + const response = await fetchImpl(`${baseUrl.replace(/\/$/, '')}/guide`); + if (!response.ok) return null; + return (await response.json()) as GuideEditionResponse; + } catch { + return null; + } +} + +/* + * The props the ModelGuide component in @redrob-labs/ui reads, restated structurally so this package + * does not depend on React or the design system. Assignable to `GuideProfession[]` as they stand. + */ +type GuideEffort = { label: string; level?: number; of?: number }; +type GuideSource = { label: string; value?: string; kind?: GuideKind; url?: string; date?: string }; +type GuideTool = { label: string; soon?: boolean; missing?: boolean }; +export type GuidePick = { + id: string; + model?: string; + steps?: Array<{ model: string; effort?: GuideEffort; role?: string }>; + harness?: string; + kind?: GuideKind; + score?: GuideEditionPick['score']; + monthly?: number; + monthlyKind?: GuideKind; + monthlyRange?: [number, number]; + effort?: GuideEffort; + efforts?: Array; + tools?: GuideTool[]; + flags?: string[]; + why?: string; + sources?: GuideSource[]; +}; +export type GuideProfession = { + id: string; + label: string; + tasks: Array<{ + id: string; + label: string; + title: string; + usage: string; + picks: GuidePick[]; + picksByLanguage: Record; + }>; +}; + +export type GuideLocale = 'en' | 'ko'; + +/** The working languages the guide ranks, for the component's language select. */ +export function guideLanguages(locale: GuideLocale): Array<{ value: string; label: string }> { + return [ + { value: 'en', label: localeText(locale, 'English', '영어') }, + { value: 'ko', label: localeText(locale, 'Korean', '한국어') }, + { value: 'hi', label: localeText(locale, 'Hindi', '힌디어') }, + ]; +} + +const EFFORTS: Record = { + none: { en: 'None', ko: '없음' }, + minimal: { en: 'Minimal', ko: '최소' }, + low: { en: 'Low', ko: '낮음' }, + medium: { en: 'Medium', ko: '중간' }, + high: { en: 'High', ko: '높음' }, + xhigh: { en: 'Extra high', ko: '매우 높음' }, + max: { en: 'Max', ko: '최대' }, + default: { en: 'Default', ko: '기본' }, +}; + +const TOOLS: Record = { + browser: { en: 'Browser', ko: '브라우저' }, + calendar: { en: 'Calendar', ko: '캘린더' }, + 'code-execution': { en: 'Code execution', ko: '코드 실행' }, + crm: { en: 'CRM', ko: 'CRM' }, + email: { en: 'Email', ko: '이메일' }, + 'file-read': { en: 'Files', ko: '파일' }, + 'graphic-design': { en: 'Graphic design', ko: '그래픽 디자인' }, + 'pdf-generation': { en: 'PDF', ko: 'PDF' }, + presentation: { en: 'Slides', ko: '슬라이드' }, + spreadsheet: { en: 'Spreadsheet', ko: '스프레드시트' }, + 'ui-ux-design': { en: 'UI/UX design', ko: 'UI/UX 디자인' }, + 'web-search': { en: 'Web search', ko: '웹 검색' }, +}; + +const FLAGS: Record = { + 'close-call': { en: 'Close call', ko: '근소한 차이' }, + 'partly-estimated': { en: 'Partly estimated', ko: '일부 추정' }, + 'outside-us': { en: 'Served outside the US', ko: '미국 외 지역에서 제공' }, + 'data-policy-unverified': { en: 'Data policy unverified', ko: '데이터 정책 미확인' }, + retiring: { en: 'Retiring', ko: '지원 종료 예정' }, +}; + +const HARNESSES: Record = { + 'redrob-desk': { en: 'Redrob Auto', ko: '레드롭 Auto' }, +}; + +function named(names: Record, id: string, locale: GuideLocale): string { + return names[id]?.[locale] ?? id; +} + +/** + * The edition as the ModelGuide component reads it, labelled in the page's language. + * + * Every step keeps its catalogue id in `id`-adjacent form so "Use this" can open the playground on the + * model the router would send, not the guide's display name. + */ +export function guideProfessions( + edition: GuideEditionResponse, + locale: GuideLocale +): GuideProfession[] { + const name = (model: string) => edition.models[model] ?? model; + return edition.professions.map(profession => ({ + id: profession.id, + label: profession.label[locale], + tasks: profession.tasks.map(task => { + const byLanguage = Object.fromEntries( + Object.entries(task.picks).map(([language, picks]) => [ + language, + picks.map((pick): GuidePick => { + const ranked = pick.steps[0]?.effort; + const of = pick.efforts.length; + const at = pick.efforts.findIndex(([label]) => label === ranked); + const effort = ranked + ? { + label: named(EFFORTS, ranked, locale), + ...(at >= 0 ? { level: at + 1, of } : {}), + } + : undefined; + const sources: GuideSource[] = pick.sources.map(source => ({ + label: + source.label === 'price' + ? `${localeText(locale, 'Price', '가격')}: ${name(source.model ?? '')}` + : source.label === 'monthly' + ? localeText(locale, 'Monthly cost', '월 비용') + : source.label === 'image' + ? localeText(locale, 'Image cost', '이미지 비용') + : source.label, + value: source.value, + kind: source.kind, + url: source.url, + date: source.date, + })); + const evidence = pick.sources.filter( + source => !['price', 'monthly', 'image'].includes(source.label) + ); + const tools: GuideTool[] = task.tools.map(tool => ({ + label: named(TOOLS, tool, locale), + missing: pick.missing.includes(tool), + })); + return { + id: `${pick.id}|${pick.steps[0]?.catalogueId ?? ''}`, + ...(pick.steps.length > 1 + ? { + steps: pick.steps.map((step, index) => ({ + model: name(step.model), + effort: index === 0 ? effort : undefined, + role: + step.role === 'image' + ? localeText(locale, 'Image', '이미지') + : localeText(locale, 'Text', '텍스트'), + })), + } + : { model: name(pick.steps[0]?.model ?? '') }), + harness: named(HARNESSES, pick.harness, locale), + kind: pick.kind, + score: pick.score, + monthly: pick.monthly, + monthlyKind: pick.monthlyKind, + monthlyRange: pick.monthlyRange, + effort, + efforts: pick.efforts.map(([label, monthly], index) => ({ + label: named(EFFORTS, label, locale), + level: index + 1, + of, + monthly, + })), + tools, + flags: pick.flags.map(flag => named(FLAGS, flag, locale)), + why: evidence + .slice(0, 2) + .map(source => `${source.label}: ${source.value}`) + .join('; '), + sources, + }; + }), + ]) + ); + return { + id: task.id, + label: task.label[locale], + title: task.label[locale], + usage: localeText( + locale, + `Priced for about ${task.runs} runs a month.`, + `월 약 ${task.runs}회 실행 기준 가격입니다.` + ), + picks: byLanguage.en ?? [], + picksByLanguage: byLanguage, + }; + }), + })); +} + +/** The catalogue id a ModelGuide pick runs first, which is what the playground is opened on. */ +export function catalogueIdOf(pickId: string): string | null { + const id = pickId.split('|')[1]; + return id ? id : null; +} + +function localeText(locale: GuideLocale, english: string, korean: string): string { + return locale === 'ko' ? korean : english; +} diff --git a/packages/route-labeller/src/index.ts b/packages/route-labeller/src/index.ts new file mode 100644 index 0000000000..e17ab17877 --- /dev/null +++ b/packages/route-labeller/src/index.ts @@ -0,0 +1,24 @@ +/* + * @redrob-labs/route-labeller: label a request with its ModelGuide profession and task, on the + * person's machine, for Redrob Auto to route on. Runtime-neutral; see node.ts for the filesystem and + * download helpers. + */ +import lexicon from "./lexicon.json" with { type: "json" }; +import manifest from "./manifest.json" with { type: "json" }; +import prototypes from "./prototypes.json" with { type: "json" }; + +import type { Lexicon, Prototypes, RouteModelManifest } from "./types.js"; + +export const LEXICON = lexicon as Lexicon; +export const MANIFEST = manifest as RouteModelManifest; +export const PROTOTYPES = prototypes as Prototypes; + +export { cosine, normalise, readDense, RouteModelIntegrityError, SentenceEncoder, sha256Hex } from "./encoder.js"; +export type { EncoderFiles } from "./encoder.js"; +export { canonicalProfession, labelLexically, scoreLexically } from "./lexical.js"; +export type { CellScore } from "./lexical.js"; +export { LABELLER_ID, LABELLER_VERSION, routeBody, RouteLabeller } from "./labeller.js"; +export type { LabelOptions } from "./labeller.js"; +export { catalogueIdOf, fetchGuide, guideLanguages, guideProfessions } from "./guide.js"; +export type { GuideEditionPick, GuideEditionResponse, GuideKind, GuideLocale, GuidePick, GuideProfession } from "./guide.js"; +export type { Lexicon, LexiconTerms, OrtRuntime, OrtSession, Prototypes, RouteLabel, RouteModelManifest } from "./types.js"; diff --git a/packages/route-labeller/src/labeller.ts b/packages/route-labeller/src/labeller.ts new file mode 100644 index 0000000000..7811e5a7d2 --- /dev/null +++ b/packages/route-labeller/src/labeller.ts @@ -0,0 +1,116 @@ +/* + * The route labeller: which ModelGuide profession and task a request is, decided on the person's + * machine and sent to Console as `redrob.route`, which Redrob Auto routes on. + * + * Two passes, combined. The embedding pass compares the request with each cell's prototype - the mean + * of its example sentences in English, Korean and Hindi - so "이 계약서 좀 봐줘" lands on contract + * review without the words matching any list. The lexical pass, the same one the Console API runs on + * unlabelled requests, adds what the words say outright. Either alone is weaker: the encoder blurs + * neighbouring tasks of one profession, the word list misses anything phrased its own way. + * + * Local by construction. The text never leaves the machine for this; only the two ids and the + * runners-up are sent, alongside a prompt that was going to Console anyway. + */ +import { cosine, type SentenceEncoder } from "./encoder.js"; +import { canonicalProfession, scoreLexically } from "./lexical.js"; +import type { Lexicon, Prototypes, RouteLabel } from "./types.js"; + +export const LABELLER_ID = "route-labeller"; +export const LABELLER_VERSION = "1.0.0"; + +/** How much one matched term is worth against cosine similarity. 0.06-0.15 is a plateau on `pnpm eval`. */ +const LEXICAL_WEIGHT = 0.1; +/** Matched terms past this add nothing: a long request should not win on length alone. */ +const LEXICAL_CAP = 4; +/** Softmax temperature for confidence. Low, because prototype similarities sit close together. */ +const TEMPERATURE = 0.03; +const CANDIDATES = 4; + +export type LabelOptions = { + /** A profession the person chose (a playbook's, or their own setting). Restricts to its tasks. */ + profession?: string | null; + /** Whether the request is code, which the caller's own classifier knows better than words. */ + coding?: boolean; +}; + +export class RouteLabeller { + constructor( + readonly lexicon: Lexicon, + private readonly prototypes: Prototypes | null, + private readonly encoder: SentenceEncoder | null, + ) { + if (prototypes && encoder && prototypes.model !== encoder.id) { + throw new Error(`prototypes were built with ${prototypes.model}, not ${encoder.id}`); + } + } + + /** Which passes are running. Without the model it is the lexical pass alone, and says so. */ + get mode(): "embedding" | "lexical" { + return this.encoder && this.prototypes ? "embedding" : "lexical"; + } + + async label(prompt: string, options: LabelOptions = {}): Promise { + const profession = canonicalProfession(this.lexicon, options.profession); + const lexical = scoreLexically(this.lexicon, prompt, { profession, coding: options.coding }); + + let vector: Float32Array | null = null; + if (this.encoder && this.prototypes && prompt.trim()) { + vector = await this.encoder.embed(prompt); + } + + const scored = lexical.map((cell) => { + const key = `${cell.profession}/${cell.task}`; + const prototype = this.prototypes?.cells[key]; + const similarity = vector && prototype ? cosine(vector, prototype) : 0; + return { ...cell, score: similarity + LEXICAL_WEIGHT * Math.min(cell.score, LEXICAL_CAP) }; + }); + // Stable sort: equal scores keep the lexicon's order, so one text always lands on one cell. + scored.sort((a, b) => b.score - a.score); + + const nothingMatched = !vector && scored.every((cell) => cell.score === 0); + if (nothingMatched || scored.length === 0) { + const own = profession ? Object.keys(this.lexicon.tasks).find((key) => key.startsWith(`${profession}/`)) : null; + const [p, t] = (own ?? this.lexicon.default).split("/") as [string, string]; + return this.result(p, t, 0, []); + } + + const top = scored.slice(0, CANDIDATES + 1); + const weights = top.map((cell) => Math.exp((cell.score - top[0]!.score) / TEMPERATURE)); + const total = weights.reduce((sum, weight) => sum + weight, 0); + const confidence = weights[0]! / total; + return this.result( + top[0]!.profession, + top[0]!.task, + confidence, + top.slice(1).map((cell, index) => ({ + profession: cell.profession, + task: cell.task, + score: round(weights[index + 1]! / total), + })), + ); + } + + private result(profession: string, task: string, confidence: number, candidates: RouteLabel["candidates"]): RouteLabel { + return { + profession, + task, + edition: this.lexicon.edition, + labeller: { + id: `${LABELLER_ID}/${this.mode}`, + version: LABELLER_VERSION, + confidence: round(confidence), + mode: this.mode, + }, + candidates, + }; + } +} + +function round(value: number): number { + return Math.round(value * 1000) / 1000; +} + +/** The label as the body field Console reads: `{ redrob: { route } }`. */ +export function routeBody(label: RouteLabel): { redrob: { route: RouteLabel } } { + return { redrob: { route: label } }; +} diff --git a/packages/route-labeller/src/lexical.ts b/packages/route-labeller/src/lexical.ts new file mode 100644 index 0000000000..c8435a30b0 --- /dev/null +++ b/packages/route-labeller/src/lexical.ts @@ -0,0 +1,88 @@ +/* + * The lexical pass: which ModelGuide cell a request's words name, from the lexicon. + * + * The same algorithm the Console API runs on a request that arrives without labels + * (redrob-console apps/api/src/inference/guide/labeller.ts), on the same lexicon, which the API's + * guide:sync copies from this package. Keeping the two in step is what makes one request label the + * same way on the person's machine and in the cloud. The embedding pass in labeller.ts sits on top + * of this; this alone is the fallback when the model is not installed. + */ +import type { Lexicon, LexiconTerms } from "./types.js"; + +/** A term in a script without spaces between words, or a phrase, is matched as a substring. */ +const NO_WORD_BOUNDARY = /[\u0900-\u097f\uac00-\ud7a3\u3040-\u30ff\u4e00-\u9fff\s/&]/; + +export function matches(text: string, term: string): boolean { + const needle = term.toLowerCase(); + if (NO_WORD_BOUNDARY.test(needle)) return text.includes(needle); + const escaped = needle.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + // A plural or a common inflection still names the thing: "clauses", "invoiced", "screening". + return new RegExp(`(^|[^\\p{L}\\p{N}])${escaped}(?:s|es|ed|d|ing)?($|[^\\p{L}\\p{N}])`, "u").test(text); +} + +function termsOf(terms: LexiconTerms | undefined): string[] { + if (!terms) return []; + return [...(terms.en ?? []), ...(terms.ko ?? []), ...(terms.hi ?? [])]; +} + +function weigh(text: string, terms: string[]): number { + let score = 0; + for (const term of terms) if (matches(text, term)) score += 1; + return score; +} + +export type CellScore = { profession: string; task: string; score: number }; + +/** A profession id as the lexicon knows it, through its aliases. Null when it names none. */ +export function canonicalProfession(lexicon: Lexicon, id: string | undefined | null): string | null { + if (!id) return null; + const key = id.trim().toLowerCase().replace(/[\s_]+/g, "-"); + if (lexicon.professions[key]) return key; + const alias = lexicon.professionAliases[key]; + return alias && lexicon.professions[alias] ? alias : null; +} + +/** + * Every cell's lexical score, in the lexicon's order. A task term counts double a profession term: + * "review this NDA" names the work, "lawyer" only names who is likely doing it. + */ +export function scoreLexically( + lexicon: Lexicon, + prompt: string, + options: { profession?: string | null; coding?: boolean } = {}, +): CellScore[] { + const text = (prompt ?? "").normalize("NFC").toLowerCase(); + const professionScores = new Map(); + const out: CellScore[] = []; + for (const cell of Object.keys(lexicon.tasks)) { + const [profession, task] = cell.split("/") as [string, string]; + if (options.profession && profession !== options.profession) continue; + if (!professionScores.has(profession)) { + professionScores.set(profession, weigh(text, termsOf(lexicon.professions[profession]))); + } + let score = 2 * weigh(text, termsOf(lexicon.tasks[cell])) + professionScores.get(profession)!; + if (options.coding && profession === "engineer") score += 1; + out.push({ profession, task, score }); + } + return out; +} + +/** The best lexical cell, or the lexicon default when nothing matched. Ties keep lexicon order. */ +export function labelLexically( + lexicon: Lexicon, + prompt: string, + options: { profession?: string | null; coding?: boolean } = {}, +): CellScore { + const scored = scoreLexically(lexicon, prompt, options).filter((cell) => cell.score > 0); + scored.sort((a, b) => b.score - a.score); + if (scored[0]) return scored[0]; + if (options.profession) { + const own = Object.keys(lexicon.tasks).find((cell) => cell.startsWith(`${options.profession}/`)); + if (own) { + const [profession, task] = own.split("/") as [string, string]; + return { profession, task, score: 0 }; + } + } + const [profession, task] = lexicon.default.split("/") as [string, string]; + return { profession, task, score: 0 }; +} diff --git a/packages/route-labeller/src/lexicon.json b/packages/route-labeller/src/lexicon.json new file mode 100644 index 0000000000..41a14d5231 --- /dev/null +++ b/packages/route-labeller/src/lexicon.json @@ -0,0 +1,632 @@ +{ + "version": 1, + "edition": "2026-10-06", + "default": "small-team/answer-customers", + "professionAliases": { + "product-manager": "pm", + "product": "pm", + "salesperson": "sales", + "sales-rep": "sales", + "small-business": "small-team", + "smb": "small-team", + "recruiting": "recruiter", + "talent": "recruiter", + "people": "hr", + "legal": "lawyer", + "attorney": "lawyer", + "developer": "engineer", + "software-engineer": "engineer", + "ux": "designer", + "vc": "investor", + "marketing": "marketer" + }, + "professions": { + "designer": { + "en": ["designer", "design", "figma", "ui", "ux", "mockup", "wireframe", "prototype"], + "ko": ["디자이너", "디자인", "피그마", "시안", "와이어프레임", "프로토타입"], + "hi": ["डिज़ाइनर", "डिज़ाइन", "मॉकअप", "प्रोटोटाइप"] + }, + "engineer": { + "en": ["code", "function", "bug", "api", "repo", "deploy", "typescript", "python", "engineer"], + "ko": ["코드", "함수", "버그", "개발", "배포", "엔지니어"], + "hi": ["कोड", "फ़ंक्शन", "बग", "डेवलपर", "इंजीनियर"] + }, + "founder": { + "en": ["startup", "founder", "investors", "runway", "fundraise", "seed", "series"], + "ko": ["스타트업", "창업", "창업자", "투자 유치", "런웨이"], + "hi": ["स्टार्टअप", "संस्थापक", "फंडिंग", "निवेश"] + }, + "hr": { + "en": ["employee", "hr", "benefits", "policy", "leave", "payroll", "handbook"], + "ko": ["직원", "인사", "복리후생", "휴가", "규정", "급여"], + "hi": ["कर्मचारी", "एचआर", "छुट्टी", "नीति", "वेतन"] + }, + "investor": { + "en": ["deal", "portfolio", "lp", "fund", "valuation", "cap table", "term sheet"], + "ko": ["딜", "포트폴리오", "펀드", "밸류에이션", "투자자"], + "hi": ["डील", "पोर्टफोलियो", "फंड", "मूल्यांकन", "निवेशक"] + }, + "lawyer": { + "en": ["contract", "clause", "legal", "law", "court", "statute", "counsel", "client matter"], + "ko": ["계약", "조항", "법률", "법원", "판례", "변호사", "의뢰인"], + "hi": ["अनुबंध", "क़ानून", "कानूनी", "अदालत", "वकील", "धारा"] + }, + "marketer": { + "en": ["marketing", "campaign", "brand", "audience", "seo", "copy", "launch"], + "ko": ["마케팅", "캠페인", "브랜드", "타깃", "카피"], + "hi": ["मार्केटिंग", "अभियान", "ब्रांड", "ऑडियंस"] + }, + "pm": { + "en": ["product", "roadmap", "prd", "feature", "spec", "users", "stakeholder"], + "ko": ["제품", "로드맵", "기능", "명세", "기획"], + "hi": ["प्रोडक्ट", "रोडमैप", "फ़ीचर", "स्पेक"] + }, + "recruiter": { + "en": ["candidate", "resume", "cv", "interview", "hiring", "recruit", "job"], + "ko": ["후보자", "이력서", "면접", "채용", "지원자"], + "hi": ["उम्मीदवार", "रिज़्यूमे", "इंटरव्यू", "भर्ती", "नौकरी"] + }, + "sales": { + "en": ["prospect", "lead", "deal", "pipeline", "quota", "crm", "account"], + "ko": ["잠재 고객", "리드", "영업", "파이프라인", "고객사"], + "hi": ["संभावित ग्राहक", "लीड", "बिक्री", "पाइपलाइन"] + }, + "small-team": { + "en": ["customer", "invoice", "shop", "store", "bookkeeping", "small business", "order"], + "ko": ["고객", "청구서", "가게", "매장", "장부", "주문"], + "hi": ["ग्राहक", "चालान", "दुकान", "हिसाब", "ऑर्डर"] + } + }, + "tasks": { + "designer/design-screens": { + "en": ["screen", "app screen", "prototype", "mockup", "wireframe", "layout", "onboarding flow"], + "ko": ["화면", "앱 화면", "프로토타입", "시안", "레이아웃"], + "hi": ["स्क्रीन", "प्रोटोटाइप", "लेआउट"], + "examples": { + "en": ["Design the onboarding screens for our mobile banking app", "Make a clickable prototype of the checkout flow"], + "ko": ["모바일 앱 온보딩 화면을 디자인해줘"], + "hi": ["हमारे ऐप के लॉगिन स्क्रीन का डिज़ाइन बनाओ"] + } + }, + "designer/create-graphics": { + "en": ["graphic", "banner", "poster", "illustration", "visual", "social post image", "logo"], + "ko": ["그래픽", "배너", "포스터", "일러스트", "비주얼", "로고"], + "hi": ["ग्राफ़िक", "बैनर", "पोस्टर", "लोगो"], + "examples": { + "en": ["Create a launch banner for our new product in brand colors", "Draw an illustration for the blog header"], + "ko": ["신제품 출시 배너 이미지를 만들어줘"], + "hi": ["नए उत्पाद के लिए एक पोस्टर बनाओ"] + } + }, + "designer/research-users": { + "en": ["user research", "interview notes", "persona", "usability test results", "feedback themes"], + "ko": ["사용자 조사", "인터뷰 노트", "페르소나", "피드백 정리"], + "hi": ["यूज़र रिसर्च", "पर्सोना", "फ़ीडबैक"], + "examples": { + "en": ["Summarise these user interview notes into themes and personas"], + "ko": ["사용자 인터뷰 내용을 주제별로 정리해줘"], + "hi": ["इन यूज़र इंटरव्यू नोट्स से मुख्य बातें निकालो"] + } + }, + "designer/handoff-specs": { + "en": ["handoff", "spec", "redline", "design tokens", "component specs", "developer handoff"], + "ko": ["핸드오프", "디자인 명세", "디자인 토큰", "컴포넌트 명세"], + "hi": ["हैंडऑफ़", "डिज़ाइन स्पेक", "टोकन"], + "examples": { + "en": ["Write the developer handoff spec for this settings page design"], + "ko": ["이 디자인을 개발자에게 넘길 명세서를 작성해줘"], + "hi": ["इस डिज़ाइन के लिए डेवलपर हैंडऑफ़ स्पेक लिखो"] + } + }, + "designer/review-usability": { + "en": ["usability", "accessibility", "wcag", "contrast", "heuristic review", "a11y"], + "ko": ["사용성", "접근성", "명도 대비", "휴리스틱"], + "hi": ["उपयोगिता", "सुलभता", "कंट्रास्ट"], + "examples": { + "en": ["Review this signup form for accessibility and usability issues"], + "ko": ["이 화면의 접근성 문제를 검토해줘"], + "hi": ["इस फ़ॉर्म की सुलभता जाँचो"] + } + }, + "engineer/build-features": { + "en": ["implement", "build", "write a function", "add endpoint", "feature", "component", "script"], + "ko": ["구현", "기능 개발", "코드 작성", "엔드포인트"], + "hi": ["फ़ीचर बनाओ", "कोड लिखो", "इम्प्लीमेंट"], + "examples": { + "en": ["Write a Python function that reverses a linked list", "Add a REST endpoint that returns the user's orders"], + "ko": ["사용자 목록을 반환하는 API를 구현해줘"], + "hi": ["एक फ़ंक्शन लिखो जो सूची को उल्टा करे"] + } + }, + "engineer/debug-fix": { + "en": ["bug", "error", "stack trace", "traceback", "exception", "crash", "fix", "not working"], + "ko": ["버그", "에러", "오류", "예외", "디버그", "고쳐"], + "hi": ["बग", "एरर", "त्रुटि", "डिबग", "ठीक करो"], + "examples": { + "en": ["This throws a TypeError: cannot read properties of undefined, fix it", "Why does my test fail with this stack trace?"], + "ko": ["이 코드에서 발생하는 에러를 고쳐줘"], + "hi": ["यह कोड क्रैश हो रहा है, बग ठीक करो"] + } + }, + "engineer/design-systems": { + "en": ["architecture", "system design", "scalability", "technical plan", "rfc", "migration plan", "database schema"], + "ko": ["아키텍처", "시스템 설계", "기술 계획", "확장성", "마이그레이션"], + "hi": ["आर्किटेक्चर", "सिस्टम डिज़ाइन", "तकनीकी योजना"], + "examples": { + "en": ["Design the architecture for a multi-tenant event pipeline", "Write an RFC for migrating our monolith to services"], + "ko": ["분산 시스템 아키텍처를 설계해줘"], + "hi": ["इस सेवा का सिस्टम डिज़ाइन बनाओ"] + } + }, + "engineer/write-tests": { + "en": ["unit test", "tests", "test coverage", "integration test", "qa", "release checklist"], + "ko": ["테스트", "단위 테스트", "통합 테스트", "릴리스 검증"], + "hi": ["टेस्ट", "यूनिट टेस्ट", "रिलीज़ जाँच"], + "examples": { + "en": ["Write unit tests for this date parsing function"], + "ko": ["이 함수에 대한 단위 테스트를 작성해줘"], + "hi": ["इस फ़ंक्शन के लिए यूनिट टेस्ट लिखो"] + } + }, + "engineer/review-code": { + "en": ["code review", "pull request", "pr", "diff", "review this code", "refactor"], + "ko": ["코드 리뷰", "풀 리퀘스트", "리팩터", "변경 사항"], + "hi": ["कोड रिव्यू", "पुल रिक्वेस्ट", "रीफ़ैक्टर"], + "examples": { + "en": ["Review this pull request diff and point out problems"], + "ko": ["이 PR을 리뷰하고 개선점을 알려줘"], + "hi": ["इस पुल रिक्वेस्ट की समीक्षा करो"] + } + }, + "founder/raise-funding": { + "en": ["pitch deck", "fundraising", "investors", "seed round", "series a", "vc pitch"], + "ko": ["피치덱", "투자 유치", "시드", "시리즈"], + "hi": ["पिच डेक", "फंडरेज़िंग", "निवेशक"], + "examples": { + "en": ["Build a 12-slide pitch deck for our seed round"], + "ko": ["시드 투자 유치용 피치덱을 만들어줘"], + "hi": ["सीड राउंड के लिए पिच डेक बनाओ"] + } + }, + "founder/plan-finances": { + "en": ["budget", "financial model", "runway", "burn rate", "forecast", "p&l"], + "ko": ["예산", "재무 모델", "런웨이", "번레이트", "손익"], + "hi": ["बजट", "वित्तीय मॉडल", "रनवे", "पूर्वानुमान"], + "examples": { + "en": ["Build an 18-month financial model with burn rate and runway"], + "ko": ["18개월 재무 모델과 런웨이를 계산해줘"], + "hi": ["अगले साल का बजट और वित्तीय मॉडल बनाओ"] + } + }, + "founder/sell-customers": { + "en": ["first customers", "sales email", "customer outreach", "cold email", "pilot"], + "ko": ["첫 고객", "영업 메일", "고객 아웃리치", "콜드 메일"], + "hi": ["पहले ग्राहक", "सेल्स ईमेल", "आउटरीच"], + "examples": { + "en": ["Write a cold email to land our first ten pilot customers"], + "ko": ["첫 고객을 위한 영업 메일을 써줘"], + "hi": ["पहले ग्राहकों के लिए ईमेल लिखो"] + } + }, + "founder/hire-team": { + "en": ["hire", "first hire", "team", "cofounder", "headcount", "org chart"], + "ko": ["채용", "첫 채용", "팀 구성", "조직도"], + "hi": ["भर्ती", "टीम बनाना", "पहली भर्ती"], + "examples": { + "en": ["Plan our first five hires and who to hire first"], + "ko": ["첫 다섯 명 채용 계획을 세워줘"], + "hi": ["हमारी पहली पाँच भर्तियों की योजना बनाओ"] + } + }, + "founder/update-investors": { + "en": ["investor update", "board meeting", "board deck", "monthly update", "kpi update"], + "ko": ["투자자 업데이트", "이사회", "월간 보고"], + "hi": ["निवेशक अपडेट", "बोर्ड मीटिंग"], + "examples": { + "en": ["Draft this month's investor update with our KPIs"], + "ko": ["이번 달 투자자 업데이트 메일을 써줘"], + "hi": ["इस महीने का निवेशक अपडेट लिखो"] + } + }, + "hr/answer-policy-questions": { + "en": ["policy question", "benefits", "pto", "parental leave", "expense policy", "employee asks"], + "ko": ["정책 문의", "복리후생", "연차", "육아휴직", "경비 규정"], + "hi": ["नीति प्रश्न", "लाभ", "छुट्टी", "मातृत्व अवकाश"], + "examples": { + "en": ["An employee asks how many days of parental leave they get"], + "ko": ["직원이 연차 이월 규정을 물어봐, 답변해줘"], + "hi": ["कर्मचारी पूछ रहा है कि छुट्टी कितनी मिलती है"] + } + }, + "hr/prepare-employment-documents": { + "en": ["offer letter", "employment contract", "onboarding documents", "termination letter"], + "ko": ["오퍼레터", "근로계약서", "입사 서류", "퇴사 서류"], + "hi": ["ऑफ़र लेटर", "रोज़गार अनुबंध", "जॉइनिंग दस्तावेज़"], + "examples": { + "en": ["Prepare an offer letter for a senior engineer starting in March"], + "ko": ["신규 입사자 오퍼레터를 작성해줘"], + "hi": ["नए कर्मचारी के लिए ऑफ़र लेटर तैयार करो"] + } + }, + "hr/handle-employee-relations": { + "en": ["complaint", "grievance", "misconduct", "investigation", "harassment report", "conflict"], + "ko": ["고충", "민원", "징계", "직장 내 괴롭힘", "갈등"], + "hi": ["शिकायत", "अनुशासन", "जाँच", "विवाद"], + "examples": { + "en": ["How should we handle a complaint between two team members?"], + "ko": ["직원 간 갈등 사안을 어떻게 처리할지 알려줘"], + "hi": ["दो कर्मचारियों के बीच शिकायत कैसे संभालें"] + } + }, + "hr/run-performance-reviews": { + "en": ["performance review", "self review", "feedback form", "calibration", "rating"], + "ko": ["성과 평가", "자기 평가", "평가 면담", "피드백"], + "hi": ["प्रदर्शन समीक्षा", "मूल्यांकन", "फ़ीडबैक"], + "examples": { + "en": ["Write performance review feedback for a mid-level designer"], + "ko": ["팀원 성과 평가 코멘트를 작성해줘"], + "hi": ["टीम सदस्य की प्रदर्शन समीक्षा लिखो"] + } + }, + "hr/write-hr-policies": { + "en": ["hr policy", "handbook", "remote work policy", "code of conduct"], + "ko": ["인사 규정", "핸드북", "재택근무 규정", "행동 강령"], + "hi": ["एचआर नीति", "हैंडबुक", "आचार संहिता"], + "examples": { + "en": ["Write a remote work policy for our employee handbook"], + "ko": ["재택근무 규정을 작성해줘"], + "hi": ["वर्क फ़्रॉम होम नीति लिखो"] + } + }, + "investor/screen-deals": { + "en": ["screen this deal", "inbound deck", "investment thesis fit", "deal flow"], + "ko": ["딜 검토", "딜 스크리닝", "투자 적합성"], + "hi": ["डील स्क्रीनिंग", "निवेश योग्य"], + "examples": { + "en": ["Screen this startup's deck against our investment thesis"], + "ko": ["이 스타트업이 우리 투자 기준에 맞는지 검토해줘"], + "hi": ["इस स्टार्टअप की डील की जाँच करो"] + } + }, + "investor/research-companies": { + "en": ["market size", "tam", "competitors", "industry research", "company research"], + "ko": ["시장 규모", "경쟁사", "산업 조사", "기업 조사"], + "hi": ["बाज़ार आकार", "प्रतिस्पर्धी", "उद्योग अनुसंधान"], + "examples": { + "en": ["Research the market size and competitors for vertical SaaS in logistics"], + "ko": ["물류 SaaS 시장 규모와 경쟁사를 조사해줘"], + "hi": ["इस उद्योग का बाज़ार आकार बताओ"] + } + }, + "investor/write-memos": { + "en": ["investment memo", "ic memo", "recommendation", "investment committee"], + "ko": ["투자 메모", "투심 보고서", "투자 심의"], + "hi": ["निवेश मेमो", "निवेश समिति"], + "examples": { + "en": ["Write the investment committee memo for this Series A"], + "ko": ["이 시리즈 A 투자 메모를 작성해줘"], + "hi": ["इस निवेश के लिए मेमो लिखो"] + } + }, + "investor/review-diligence": { + "en": ["due diligence", "data room", "financial statements", "diligence checklist"], + "ko": ["실사", "데이터룸", "재무제표"], + "hi": ["ड्यू डिलिजेंस", "डेटा रूम", "वित्तीय विवरण"], + "examples": { + "en": ["Review the data room financials and flag diligence risks"], + "ko": ["데이터룸 재무 자료를 실사 관점에서 검토해줘"], + "hi": ["डेटा रूम के दस्तावेज़ों की ड्यू डिलिजेंस करो"] + } + }, + "investor/report-portfolio": { + "en": ["lp report", "quarterly letter", "portfolio update", "fund performance", "irr"], + "ko": ["LP 보고", "분기 보고서", "포트폴리오 현황", "펀드 수익률"], + "hi": ["एलपी रिपोर्ट", "तिमाही पत्र", "पोर्टफोलियो"], + "examples": { + "en": ["Draft the quarterly LP letter on fund performance"], + "ko": ["분기 LP 보고서를 작성해줘"], + "hi": ["तिमाही एलपी रिपोर्ट लिखो"] + } + }, + "lawyer/client": { + "en": ["client update", "advise the client", "matter status", "client email", "engagement"], + "ko": ["의뢰인", "자문", "사건 진행", "고객 안내"], + "hi": ["मुवक्किल", "क्लाइंट को सलाह", "मामले की स्थिति"], + "examples": { + "en": ["Write the client an update on where their lease dispute stands"], + "ko": ["의뢰인에게 소송 진행 상황을 안내하는 메일을 써줘"], + "hi": ["मुवक्किल को मामले की प्रगति बताओ"] + } + }, + "lawyer/research": { + "en": ["case law", "precedent", "statute", "jurisdiction", "legal research", "regulation"], + "ko": ["판례", "법령", "관할", "법률 리서치", "규제"], + "hi": ["नज़ीर", "क़ानून", "क्षेत्राधिकार", "क़ानूनी शोध"], + "examples": { + "en": ["Find case law on non-compete enforceability in California"], + "ko": ["경업금지 약정 관련 판례를 찾아줘"], + "hi": ["इस विषय पर अदालत के फ़ैसले खोजो"] + } + }, + "lawyer/review": { + "en": ["review this contract", "review", "redline", "clause", "indemnity", "nda review", "one-sided", "risk in agreement"], + "ko": ["계약서 검토", "조항", "손해배상", "비밀유지계약 검토"], + "hi": ["अनुबंध समीक्षा", "धारा", "क्षतिपूर्ति"], + "examples": { + "en": ["Review this NDA and flag any one-sided clauses"], + "ko": ["이 계약서의 불리한 조항을 검토해줘"], + "hi": ["इस अनुबंध की जोखिम भरी धाराएँ बताओ"] + } + }, + "lawyer/memo": { + "en": ["legal memo", "brief", "memorandum", "argument", "motion"], + "ko": ["법률 메모", "의견서", "준비서면", "서면"], + "hi": ["क़ानूनी मेमो", "ब्रीफ़", "तर्क"], + "examples": { + "en": ["Write a legal memo on whether the arbitration clause applies"], + "ko": ["중재 조항 적용 여부에 대한 법률 의견서를 써줘"], + "hi": ["इस मुद्दे पर क़ानूनी मेमो लिखो"] + } + }, + "lawyer/draft": { + "en": ["draft a contract", "agreement", "nda", "terms of service", "msa", "lease"], + "ko": ["계약서 초안", "약관", "용역계약", "임대차 계약"], + "hi": ["अनुबंध का मसौदा", "समझौता", "शर्तें"], + "examples": { + "en": ["Draft a mutual NDA between two software companies"], + "ko": ["용역 계약서 초안을 작성해줘"], + "hi": ["एक सेवा अनुबंध का मसौदा तैयार करो"] + } + }, + "marketer/write-content": { + "en": ["blog post", "landing page copy", "tagline", "social post", "newsletter", "ad copy"], + "ko": ["블로그 글", "랜딩 페이지 카피", "슬로건", "SNS 게시물"], + "hi": ["ब्लॉग पोस्ट", "विज्ञापन कॉपी", "टैगलाइन"], + "examples": { + "en": ["Write landing page copy for our new analytics product"], + "ko": ["신제품 랜딩 페이지 카피를 써줘"], + "hi": ["हमारे उत्पाद के लिए ब्लॉग पोस्ट लिखो"] + } + }, + "marketer/plan-campaigns": { + "en": ["marketing plan", "campaign strategy", "go to market", "launch plan", "channel mix"], + "ko": ["마케팅 계획", "캠페인 전략", "출시 계획", "채널 전략"], + "hi": ["मार्केटिंग योजना", "अभियान रणनीति", "लॉन्च योजना"], + "examples": { + "en": ["Plan a go-to-market campaign for our Q4 launch"], + "ko": ["4분기 출시 마케팅 캠페인 전략을 세워줘"], + "hi": ["नए लॉन्च के लिए मार्केटिंग योजना बनाओ"] + } + }, + "marketer/run-messaging-campaigns": { + "en": ["email campaign", "drip sequence", "newsletter send", "push notification", "sms campaign"], + "ko": ["이메일 캠페인", "뉴스레터 발송", "푸시 알림", "문자 캠페인"], + "hi": ["ईमेल अभियान", "न्यूज़लेटर", "एसएमएस अभियान"], + "examples": { + "en": ["Write a three-email onboarding drip sequence"], + "ko": ["신규 가입자용 이메일 캠페인 3편을 작성해줘"], + "hi": ["नए ग्राहकों के लिए ईमेल अभियान लिखो"] + } + }, + "marketer/analyze-campaigns": { + "en": ["campaign results", "ctr", "conversion rate", "roas", "attribution", "marketing report"], + "ko": ["캠페인 성과", "클릭률", "전환율", "광고 효율"], + "hi": ["अभियान परिणाम", "कन्वर्ज़न दर", "रिपोर्ट"], + "examples": { + "en": ["Analyze last month's campaign results and report CTR and conversion"], + "ko": ["지난달 캠페인 성과를 분석해줘"], + "hi": ["पिछले अभियान के परिणामों का विश्लेषण करो"] + } + }, + "marketer/optimize-search": { + "en": ["seo", "keywords", "search ranking", "meta description", "ai answers", "geo"], + "ko": ["검색 최적화", "키워드", "검색 순위", "메타 설명"], + "hi": ["एसईओ", "कीवर्ड", "सर्च रैंकिंग"], + "examples": { + "en": ["Optimize this article for SEO and AI search answers"], + "ko": ["이 글을 검색 최적화해줘"], + "hi": ["इस लेख का एसईओ सुधारो"] + } + }, + "pm/plan-roadmap": { + "en": ["roadmap", "prioritize", "rice", "backlog", "quarterly plan", "okrs"], + "ko": ["로드맵", "우선순위", "백로그", "분기 계획"], + "hi": ["रोडमैप", "प्राथमिकता", "बैकलॉग"], + "examples": { + "en": ["Prioritize this backlog into a Q1 roadmap"], + "ko": ["다음 분기 로드맵과 기능 우선순위를 정해줘"], + "hi": ["अगली तिमाही का रोडमैप बनाओ"] + } + }, + "pm/write-prd": { + "en": ["prd", "product spec", "requirements", "user stories", "acceptance criteria"], + "ko": ["PRD", "제품 명세", "요구사항", "사용자 스토리"], + "hi": ["पीआरडी", "प्रोडक्ट स्पेक", "आवश्यकताएँ"], + "examples": { + "en": ["Write a PRD for saved searches with user stories"], + "ko": ["저장된 검색 기능의 PRD를 작성해줘"], + "hi": ["इस फ़ीचर का पीआरडी लिखो"] + } + }, + "pm/synthesize-feedback": { + "en": ["customer feedback", "feature requests", "nps comments", "support tickets themes"], + "ko": ["고객 피드백", "기능 요청", "NPS 의견"], + "hi": ["ग्राहक फ़ीडबैक", "फ़ीचर अनुरोध"], + "examples": { + "en": ["Group these feature requests and NPS comments into themes"], + "ko": ["고객 피드백을 주제별로 정리해줘"], + "hi": ["ग्राहकों के फ़ीडबैक को विषयों में बाँटो"] + } + }, + "pm/stakeholder-updates": { + "en": ["stakeholder update", "status update", "launch review deck", "exec summary"], + "ko": ["이해관계자 업데이트", "진행 보고", "발표 자료", "요약 보고"], + "hi": ["हितधारक अपडेट", "स्टेटस अपडेट", "प्रेज़ेंटेशन"], + "examples": { + "en": ["Write a weekly status update for leadership on the launch"], + "ko": ["경영진에게 보낼 주간 진행 보고를 써줘"], + "hi": ["प्रबंधन के लिए साप्ताहिक अपडेट लिखो"] + } + }, + "pm/analyze-metrics": { + "en": ["a/b test", "experiment", "retention", "funnel", "dau", "product metrics", "cohort"], + "ko": ["A/B 테스트", "실험", "리텐션", "퍼널", "지표"], + "hi": ["ए/बी टेस्ट", "प्रयोग", "रिटेंशन", "मेट्रिक्स"], + "examples": { + "en": ["Analyze this A/B test and tell me if the lift is significant"], + "ko": ["이 A/B 테스트 결과를 분석해줘"], + "hi": ["इस प्रयोग के परिणामों का विश्लेषण करो"] + } + }, + "recruiter/find-contact-candidates": { + "en": ["source candidates", "sourcing", "linkedin", "reach out to candidate", "boolean search"], + "ko": ["후보자 발굴", "소싱", "링크드인", "후보자 연락"], + "hi": ["उम्मीदवार खोजो", "सोर्सिंग", "लिंक्डइन"], + "examples": { + "en": ["Find senior backend engineers in Bangalore and write an outreach message"], + "ko": ["백엔드 개발자 후보를 찾아 연락 메시지를 써줘"], + "hi": ["बेंगलुरु में बैकएंड इंजीनियर खोजो"] + } + }, + "recruiter/screen-resumes": { + "en": ["resume", "cv", "shortlist", "screen candidates", "applicants"], + "ko": ["이력서", "서류 심사", "후보 선별", "지원자"], + "hi": ["रिज़्यूमे", "सीवी", "शॉर्टलिस्ट", "आवेदक"], + "examples": { + "en": ["Screen these resumes against the job description and shortlist five"], + "ko": ["이 이력서들을 검토해서 후보를 추려줘"], + "hi": ["इन रिज़्यूमे में से पाँच उम्मीदवार चुनो"] + } + }, + "recruiter/prepare-interviews": { + "en": ["interview questions", "scorecard", "interview feedback", "interview kit"], + "ko": ["면접 질문", "평가표", "면접 피드백"], + "hi": ["इंटरव्यू प्रश्न", "स्कोरकार्ड", "इंटरव्यू फ़ीडबैक"], + "examples": { + "en": ["Prepare interview questions and a scorecard for a product designer"], + "ko": ["프로덕트 디자이너 면접 질문을 준비해줘"], + "hi": ["इस भूमिका के लिए इंटरव्यू प्रश्न बनाओ"] + } + }, + "recruiter/write-job-descriptions": { + "en": ["job description", "job posting", "jd", "role description", "careers page"], + "ko": ["채용 공고", "직무 기술서", "JD"], + "hi": ["जॉब डिस्क्रिप्शन", "नौकरी विज्ञापन"], + "examples": { + "en": ["Write a job description for a senior data analyst"], + "ko": ["데이터 분석가 채용 공고를 작성해줘"], + "hi": ["डेटा एनालिस्ट के लिए जॉब डिस्क्रिप्शन लिखो"] + } + }, + "recruiter/schedule-interviews": { + "en": ["schedule interview", "availability", "calendar invite", "reschedule", "candidate update"], + "ko": ["면접 일정", "일정 조율", "캘린더 초대"], + "hi": ["इंटरव्यू शेड्यूल", "समय तय करो", "कैलेंडर"], + "examples": { + "en": ["Schedule second-round interviews for three candidates next week"], + "ko": ["다음 주 2차 면접 일정을 조율해줘"], + "hi": ["अगले हफ़्ते इंटरव्यू शेड्यूल करो"] + } + }, + "sales/write-outreach": { + "en": ["outreach email", "follow up", "cold email", "sequence", "prospecting email"], + "ko": ["아웃리치 메일", "팔로업", "콜드 메일"], + "hi": ["आउटरीच ईमेल", "फ़ॉलो-अप", "कोल्ड ईमेल"], + "examples": { + "en": ["Write a follow-up email to a prospect who went quiet after the demo"], + "ko": ["데모 후 연락이 없는 고객에게 팔로업 메일을 써줘"], + "hi": ["डेमो के बाद ग्राहक को फ़ॉलो-अप ईमेल लिखो"] + } + }, + "sales/create-proposals": { + "en": ["proposal", "sales deck", "pricing proposal", "rfp response", "business case"], + "ko": ["제안서", "영업 자료", "견적 제안", "RFP"], + "hi": ["प्रस्ताव", "सेल्स डेक", "आरएफ़पी"], + "examples": { + "en": ["Create a proposal and sales deck for a 200-seat enterprise deal"], + "ko": ["기업 고객용 제안서를 만들어줘"], + "hi": ["इस ग्राहक के लिए प्रस्ताव बनाओ"] + } + }, + "sales/answer-customers": { + "en": ["customer question", "pricing question", "objection", "product question", "how does it work"], + "ko": ["고객 문의", "가격 문의", "반론 대응"], + "hi": ["ग्राहक का प्रश्न", "कीमत प्रश्न", "आपत्ति"], + "examples": { + "en": ["A prospect asks whether we support SSO; answer them"], + "ko": ["고객이 SSO 지원 여부를 물어봐, 답변해줘"], + "hi": ["ग्राहक पूछ रहा है कि कीमत क्या है, जवाब दो"] + } + }, + "sales/research-prospects": { + "en": ["account research", "prospect research", "decision maker", "company background", "icp"], + "ko": ["계정 조사", "잠재 고객 조사", "의사결정자"], + "hi": ["संभावित ग्राहक शोध", "निर्णयकर्ता", "कंपनी पृष्ठभूमि"], + "examples": { + "en": ["Research this account and find the decision makers before my call"], + "ko": ["미팅 전에 이 고객사를 조사해줘"], + "hi": ["कॉल से पहले इस कंपनी के बारे में पता करो"] + } + }, + "sales/update-crm": { + "en": ["crm", "salesforce", "hubspot", "pipeline", "deal stage", "log the call"], + "ko": ["CRM", "파이프라인", "딜 단계", "영업 기록"], + "hi": ["सीआरएम", "पाइपलाइन", "डील स्टेज"], + "examples": { + "en": ["Update the CRM with notes from today's calls and move the deal stages"], + "ko": ["오늘 미팅 내용을 CRM에 정리해줘"], + "hi": ["आज की कॉल के नोट्स सीआरएम में डालो"] + } + }, + "small-team/answer-customers": { + "en": ["reply to customer", "customer message", "refund", "order status", "support email", "complaint"], + "ko": ["고객 답장", "고객 메시지", "환불", "배송 문의"], + "hi": ["ग्राहक को जवाब", "रिफ़ंड", "ऑर्डर स्थिति"], + "examples": { + "en": ["Reply to a customer asking where their order is", "Answer this email from a customer who wants a refund"], + "ko": ["배송이 늦다는 고객 문의에 답장해줘"], + "hi": ["ग्राहक के रिफ़ंड वाले ईमेल का जवाब दो"] + } + }, + "small-team/keep-books": { + "en": ["bookkeeping", "expenses", "cash flow", "reconcile", "ledger", "receipts"], + "ko": ["장부", "지출", "현금 흐름", "정산", "영수증"], + "hi": ["हिसाब-किताब", "खर्च", "नकदी प्रवाह", "रसीद"], + "examples": { + "en": ["Categorise these expenses and track this month's cash flow"], + "ko": ["이번 달 지출을 정리하고 현금 흐름을 계산해줘"], + "hi": ["इस महीने के खर्च का हिसाब बनाओ"] + } + }, + "small-team/send-invoices": { + "en": ["invoice", "payment reminder", "overdue", "chase payment", "billing"], + "ko": ["청구서", "인보이스", "미수금", "결제 독촉"], + "hi": ["चालान", "भुगतान अनुस्मारक", "बकाया"], + "examples": { + "en": ["Send an invoice and a polite reminder for the overdue payment"], + "ko": ["미수금 독촉 메일과 청구서를 보내줘"], + "hi": ["बकाया भुगतान के लिए याद दिलाने वाला संदेश लिखो"] + } + }, + "small-team/create-marketing": { + "en": ["flyer", "instagram post", "promotion", "sale poster", "menu", "local ad"], + "ko": ["전단지", "인스타그램 게시물", "할인 홍보", "포스터"], + "hi": ["पर्चा", "इंस्टाग्राम पोस्ट", "प्रचार"], + "examples": { + "en": ["Make a flyer for our weekend bakery sale"], + "ko": ["주말 할인 행사 전단지를 만들어줘"], + "hi": ["दुकान की सेल के लिए पर्चा बनाओ"] + } + }, + "small-team/prepare-quotes": { + "en": ["quote", "estimate", "price quote", "proposal for job", "bid"], + "ko": ["견적서", "견적", "단가"], + "hi": ["कोटेशन", "अनुमान", "बोली"], + "examples": { + "en": ["Prepare a quote for renovating a two-bedroom flat"], + "ko": ["인테리어 공사 견적서를 준비해줘"], + "hi": ["इस काम के लिए कोटेशन तैयार करो"] + } + } + } +} diff --git a/packages/route-labeller/src/manifest.json b/packages/route-labeller/src/manifest.json new file mode 100644 index 0000000000..870b5b3ca0 --- /dev/null +++ b/packages/route-labeller/src/manifest.json @@ -0,0 +1,22 @@ +{ + "id": "sentence-transformers/distiluse-base-multilingual-cased-v2", + "revision": "bfe45d0732ca50787611c0fe107ba278c7f3f889", + "license": "Apache-2.0", + "dimensions": 512, + "maxTokens": 128, + "model": { + "file": "model_int8.onnx", + "sha256": "d21142a1421d3cda61b7d016d1170e5d7ab682c62ce4f0609c1ce3d579676186", + "url": "https://huggingface.co/Xenova/distiluse-base-multilingual-cased-v2/resolve/cad454171d918d9873a2701ba245054b6c1760dd/onnx/model_int8.onnx" + }, + "tokenizer": { + "file": "tokenizer.json", + "sha256": "bf1b59b7b11c95f194f51708d918eea378e09d05f84c0e1656dc5180e8117088", + "url": "https://huggingface.co/Xenova/distiluse-base-multilingual-cased-v2/resolve/cad454171d918d9873a2701ba245054b6c1760dd/tokenizer.json" + }, + "dense": { + "file": "dense.safetensors", + "sha256": "0a21b1ce908e772ebf09f93c20ca09524c32706e9918d9c0169a3f0663b191ed", + "url": "https://huggingface.co/sentence-transformers/distiluse-base-multilingual-cased-v2/resolve/bfe45d0732ca50787611c0fe107ba278c7f3f889/2_Dense/model.safetensors" + } +} diff --git a/packages/route-labeller/src/node.ts b/packages/route-labeller/src/node.ts new file mode 100644 index 0000000000..80bf21b814 --- /dev/null +++ b/packages/route-labeller/src/node.ts @@ -0,0 +1,113 @@ +/* + * Node-side helpers: reading the route model from a directory, and putting it there. + * + * Separate from the runtime-neutral core (index.ts) because it touches the filesystem and the + * network. redrob-server, Office's main process and the build scripts that package the model use + * this; Design's webview uses the core with bytes it fetched itself. + * + * The weights are not in git (about 140 MB). Each file is fetched from the pinned Hugging Face + * revision the manifest names, and kept only when it hashes to the manifest's SHA-256, so a + * download is never trusted for what it claims to be. + */ +import { mkdir, readFile, rename, writeFile } from "node:fs/promises"; +import { existsSync } from "node:fs"; +import { join } from "node:path"; + +import { SentenceEncoder, sha256Hex } from "./encoder.js"; +import { RouteLabeller } from "./labeller.js"; +import { LEXICON, MANIFEST, PROTOTYPES } from "./index.js"; +import type { OrtRuntime, RouteModelManifest } from "./types.js"; + +export * from "./index.js"; + +function pinned(manifest: RouteModelManifest) { + return [manifest.model, manifest.tokenizer, manifest.dense]; +} + +/** Whether every pinned file is in `directory` and matches. */ +export async function routeModelPresent(directory: string, manifest: RouteModelManifest = MANIFEST): Promise { + for (const entry of pinned(manifest)) { + const path = join(directory, entry.file); + if (!existsSync(path)) return false; + if ((await sha256Hex(new Uint8Array(await readFile(path)))) !== entry.sha256) return false; + } + return true; +} + +/** + * Makes every pinned file present and verified in `directory`, downloading what is missing from the + * manifest's own URLs, or copying it from `source` when given. Writes the manifest beside them. + */ +export async function prepareRouteModel( + directory: string, + options: { + manifest?: RouteModelManifest; + source?: string | null; + fetchImpl?: typeof fetch; + log?: (line: string) => void; + } = {}, +): Promise { + const manifest = options.manifest ?? MANIFEST; + const log = options.log ?? (() => undefined); + await mkdir(directory, { recursive: true }); + for (const entry of pinned(manifest)) { + const target = join(directory, entry.file); + if (existsSync(target) && (await sha256Hex(new Uint8Array(await readFile(target)))) === entry.sha256) continue; + let bytes: Uint8Array; + if (options.source) { + bytes = new Uint8Array(await readFile(join(options.source, entry.file))); + } else { + if (!entry.url) throw new Error(`route model manifest has no URL for ${entry.file}`); + log(`downloading ${entry.url}`); + const response = await (options.fetchImpl ?? fetch)(entry.url); + if (!response.ok) throw new Error(`${entry.url} answered ${response.status}`); + bytes = new Uint8Array(await response.arrayBuffer()); + } + const actual = await sha256Hex(bytes); + if (actual !== entry.sha256) { + throw new Error(`${entry.file} does not match the pinned SHA-256 (expected ${entry.sha256}, got ${actual})`); + } + await writeFile(`${target}.partial`, bytes); + await rename(`${target}.partial`, target); + } + await writeFile(join(directory, "manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`); + await writeFile(join(directory, "NOTICE.md"), MODEL_NOTICE); +} + +/** Shipped beside the weights, because the Apache License asks for its notice to travel with them. */ +const MODEL_NOTICE = `# Route model + +sentence-transformers/distiluse-base-multilingual-cased-v2 (Dense projection) and the int8 ONNX export and +tokenizer of Xenova/distiluse-base-multilingual-cased-v2, licensed under the Apache License 2.0 +(https://www.apache.org/licenses/LICENSE-2.0). Unmodified; each file is pinned by SHA-256 in manifest.json. +`; + +/** + * The labeller, with the embedding pass when the model is in `directory` and the lexical pass alone + * when it is not. Never throws for a missing or tampered model: routing still works on words, and + * `labeller.mode` says which it is. + */ +export async function loadRouteLabeller(options: { + directory?: string | null; + loadRuntime?: () => Promise; + threads?: number; +}): Promise<{ labeller: RouteLabeller; reason: string | null }> { + const lexical = new RouteLabeller(LEXICON, null, null); + if (!options.directory) return { labeller: lexical, reason: "no route model is installed" }; + try { + const read = (file: string) => readFile(join(options.directory!, file)).then((buffer) => new Uint8Array(buffer)); + const [model, tokenizer, dense] = await Promise.all([ + read(MANIFEST.model.file), + read(MANIFEST.tokenizer.file), + read(MANIFEST.dense.file), + ]); + const ort = await (options.loadRuntime ?? + (async () => (await import("onnxruntime-node")) as unknown as OrtRuntime))(); + const encoder = await SentenceEncoder.load({ manifest: MANIFEST, model, tokenizer, dense }, ort, { + threads: options.threads, + }); + return { labeller: new RouteLabeller(LEXICON, PROTOTYPES, encoder), reason: null }; + } catch (error) { + return { labeller: lexical, reason: error instanceof Error ? error.message : String(error) }; + } +} diff --git a/packages/route-labeller/src/prototypes.json b/packages/route-labeller/src/prototypes.json new file mode 100644 index 0000000000..6b13ec97d4 --- /dev/null +++ b/packages/route-labeller/src/prototypes.json @@ -0,0 +1 @@ +{"model":"sentence-transformers/distiluse-base-multilingual-cased-v2@bfe45d07","lexiconVersion":1,"edition":"2026-10-06","dimensions":512,"cells":{"designer/design-screens":[-0.01323,-0.04062,-0.05351,0.03571,0.0336,-0.00392,-0.01419,0.01453,0.02271,-0.03042,-0.01744,-0.00157,0.03078,-0.01804,0.00988,-0.01422,-0.00245,0.04497,-0.0736,-0.02904,0.08512,-0.01951,-0.00401,-0.00524,0.02164,0.04457,0.04713,0.02793,0.01131,0.05084,-0.03081,-0.01761,-0.06182,0.01056,0.04326,0.00368,-0.05808,0.00518,0.04913,-0.0101,-0.07301,0.08522,-0.00467,0.00357,0.06744,-0.05553,-0.01101,0.00019,0.03378,0.00393,-0.06271,0.01613,-0.10524,0.02968,0.01961,0.03774,-0.03748,-0.01963,0.03751,0.02945,-0.07704,-0.09534,-0.06392,0.01861,0.04678,0.01294,-0.05751,-0.00796,-0.04009,-0.0317,-0.01116,0.07114,0.01918,-0.01663,-0.05396,0.00492,0.06372,0.07912,0.01753,0.01625,-0.05408,-0.04893,0.06869,0.02611,-0.03643,-0.03663,0.01453,0.01034,0.05743,0.02379,-0.00503,-0.03573,0.02976,0.02695,0.02392,-0.05804,-0.07012,-0.11321,0.04291,-0.02234,-0.00182,-0.0513,0.00169,-0.02771,0.05174,0.065,0.0331,-0.02118,0.0391,0.04984,0.07649,0.0243,-0.04332,-0.02335,-0.0644,0.04274,-0.02751,0.0947,0.08555,0.00013,0.06062,0.05624,-0.00674,0.01485,0.03177,-0.02186,-0.01429,-0.00354,-0.02771,0.06759,-0.00954,0.03098,0.00543,-0.0463,-0.01768,-0.00645,-0.00889,-0.04512,0.05892,-0.10127,-0.06401,-0.00377,0.05155,0.02923,-0.04917,-0.01986,0.02797,0.01916,0.00353,0.02698,0.04729,-0.04078,0.0016,0.0608,-0.01722,0.02928,-0.19297,-0.0011,0.0148,0.0423,-0.04224,-0.05563,-0.00283,-0.02007,-0.05346,-0.00441,0.00316,-0.05238,-0.07931,0.03903,-0.07595,-0.04015,-0.08411,-0.00142,0.09682,-0.04166,-0.02388,0.01311,-0.00637,-0.02388,0.04741,-0.03652,0.01254,0.06329,-0.04659,0.02757,0.08191,-0.02887,-0.02006,0.01543,0.02188,-0.04542,-0.03786,-0.03055,-0.03586,-0.00296,0.01558,-0.03023,-0.02983,-0.04273,0.01233,0.0554,-0.05546,-0.0398,-0.09342,0.0288,-0.03362,-0.0316,-0.03152,-0.02368,0.00114,0.00102,-0.03508,0.07284,0.03581,-0.06308,0.0177,0.02843,-0.0143,0.0525,-0.0563,-0.00494,-0.07033,-0.02496,0.00105,-0.01794,-0.03078,0.06314,-0.02375,0.021,-0.01473,-0.01474,0.10318,0.01695,-0.01895,-0.04022,0.07544,0.05283,0.01845,0.06235,0.02862,-0.0013,0.02829,0.01047,-0.01181,0.06821,0.01688,0.00973,-0.13133,-0.01024,-0.02676,-0.00344,-0.02531,0.00636,0.02486,-0.04571,0.03495,0.04122,-0.0181,0.12876,-0.00215,0.05874,-0.0006,-0.03304,-0.04188,-0.02283,-0.00534,-0.03757,-0.02841,-0.03605,-0.01972,0.01685,-0.04668,-0.03987,-0.0932,0.0184,-0.02824,0.04879,0.01459,0.01778,-0.03133,-0.00162,0.06423,0.12847,-0.05413,-0.0093,0.02709,0.02431,0.00287,0.05684,-0.0219,-0.1367,0.00424,-0.00638,0.03747,0.0185,0.00187,0.03608,0.10217,-0.0456,0.01564,-0.01864,-0.05501,0.01,-0.00639,0.139,0.03228,0.01603,0.05202,-0.01666,-0.01211,-0.01569,-0.00824,0.00219,0.02097,-0.01714,0.00396,0.03414,-0.0068,-0.05754,-0.08837,-0.00104,-0.00369,0.01774,0.09025,-0.02474,-0.03511,-0.00708,-0.03357,-0.01849,-0.01592,-0.01089,-0.02604,-0.02123,-0.08745,0.01722,0.03238,0.04493,0.04205,0.0307,0.00033,0.03709,0.01523,-0.04156,-0.00039,0.04624,-0.00341,0.00322,-0.07524,0.01772,-0.01474,0.059,-0.01878,-0.01936,0.00828,0.07338,-0.00535,-0.02453,0.02082,0.01047,0.09979,0.02502,0.04878,0.02297,-0.00221,-0.00746,0.01735,-0.02106,0.04926,0.02565,0.03237,-0.01871,-0.01034,0.09564,-0.06854,0.06299,-0.06263,0.01411,0.00701,0.01853,0.03493,-0.01261,0.04764,-0.00587,0.01238,0.01229,0.00495,-0.03706,-0.02043,0.05164,-0.05556,0.04437,-0.00396,0.01965,0.0619,-0.00767,-0.02812,0.05861,-0.0205,0.00476,0.01425,-0.04803,0.02021,0.00863,0.04273,0.07997,0.02575,-0.042,-0.02249,0.05835,-0.00396,0.05911,0.02977,-0.02017,0.05561,0.02629,0.04198,0.01715,0.00781,-0.045,-0.00379,0.06836,-0.05034,-0.03455,0.01602,-0.00491,0.08708,0.02141,-0.03714,-0.00916,-0.02067,0.09354,-0.04212,-0.04922,-0.04457,0.0771,0.01379,-0.07957,0.06223,-0.01178,0.0786,0.10488,0.01901,0.00089,-0.01984,-0.00477,-0.01344,-0.01689,0.05866,-0.09591,0.02036,0.04917,-0.00318,-0.04808,-0.02299,0.01961,-0.00137,-0.01877,0.02212,-0.08778,-0.02598,-0.01947,-0.02778,0.04718,-0.01923,0.02282,-0.06979,0.02293,0.05949,0.02855,-0.03504,-0.02979,-0.02189,-0.05058,-0.03157,-0.01934,-0.02757,-0.05564,-0.01478,-0.05869,-0.00558,-0.01637,-0.00534,-0.07392,0.01611,-0.06987,0.06081,-0.07025,0.04096,0.01303,-0.00226,-0.00755,-0.06696,-0.00253,-0.01213,-0.00964,-0.05871,-0.01087,-0.0889,-0.02402,0.04839,-0.02195,0.0207,0.03418,0.04467,0.13377,0.00018,-0.04344,-0.07263,0.0581,-0.02173,-0.00154],"designer/create-graphics":[0.03174,-0.05012,-0.02478,0.02916,-0.01626,-0.00733,-0.07626,0.05703,-0.03133,-0.02534,0.03881,-0.00569,0.07272,0.01024,0.06557,-0.08336,-0.00377,0.03974,0.02306,-0.03972,-0.05508,-0.01875,-0.01233,-0.02108,-0.00266,-0.03082,0.02183,-0.0098,0.04764,-0.07432,-0.09082,-0.01646,-0.05262,-0.00032,0.05169,0.0404,0.01221,0.05971,0.05466,0.05061,-0.02031,0.05339,0.00293,0.00526,0.00551,0.00567,-0.06666,-0.01374,0.06034,0.0789,0.02446,0.115,0.0502,-0.02172,-0.00239,-0.01515,-0.0229,0.05311,-0.0506,-0.01433,0.04957,-0.04723,-0.05712,0.00923,0.04246,-0.0697,-0.07903,0.01742,-0.02888,-0.02889,-0.02547,0.04789,0.07168,0.02332,-0.05364,0.02704,0.08164,0.04122,-0.02562,0.02314,-0.02161,-0.06547,0.05049,0.02503,-0.03267,-0.07461,-0.01182,-0.01163,0.03011,0.01398,0.07472,-0.12044,0.04897,0.04855,0.06089,-0.01992,0.00889,-0.05623,0.0284,-0.06325,0.05542,-0.06447,-0.00261,-0.01484,0.03776,0.04812,0.01891,-0.02483,0.05034,0.00646,0.0501,-0.0342,-0.00943,0.07242,-0.05467,-0.02807,0.02886,-0.02328,0.04178,-0.04232,0.02388,0.08322,-0.0325,-0.03049,0.0294,-0.00843,0.01994,-0.0222,-0.0319,0.09683,0.05514,0.03662,-0.00971,-0.06818,0.05216,-0.01798,0.02782,-0.0335,0.01862,-0.05658,-0.00602,-0.02755,0.08909,0.03472,-0.03723,-0.05945,0.05481,-0.03317,-0.04654,-0.05716,0.06418,-0.0726,0.0284,-0.00025,0.04714,0.06129,0.01838,0.03569,0.07416,0.06409,0.00805,-0.0464,0.03053,0.02408,-0.0188,0.09681,-0.00053,-0.04758,-0.01236,-0.05683,-0.07784,-0.00777,-0.0721,0.0675,-0.00988,-0.07065,-0.02525,0.04009,0.00948,-0.02255,0.00704,-0.05047,-0.04679,0.00219,0.02153,-0.08428,-0.04392,0.01609,-0.05253,0.04947,-0.07469,0.00446,-0.04342,-0.02612,-0.03651,-0.03028,0.00291,-0.01671,0.04403,-0.0405,-0.00029,-0.01495,-0.0662,-0.03935,-0.11096,0.03274,-0.05298,0.01295,0.04824,-0.02451,-0.01606,0.01362,0.00038,0.09644,0.07857,-0.01003,0.0306,-0.05678,-0.00206,0.02245,-0.05796,0.02835,-0.07638,-0.07797,0.02382,-0.05962,-0.04307,0.0323,0.05776,0.02385,0.05228,-0.05429,0.01151,-0.04179,-0.03876,0.03624,0.06012,0.00179,0.07586,0.05348,0.00733,-0.01656,0.02739,0.00456,0.09269,0.05514,0.01103,-0.01025,-0.03517,-0.01366,0.0212,0.00852,0.02572,0.02401,0.03909,-0.03468,0.05731,-0.02186,-0.01972,0.06634,0.05041,0.07704,-0.02032,0.03704,0.02201,0.01238,0.00361,0.01556,-0.01379,-0.00928,-0.03121,-0.02201,0.04114,-0.02527,0.02565,-0.07412,-0.0063,-0.04952,0.0017,-0.04257,-0.01915,0.02356,-0.03114,0.07073,0.09333,-0.00697,-0.05678,0.03046,0.05983,-0.00302,0.00495,-0.10196,-0.0016,0.02332,0.01026,-0.004,-0.01467,-0.00337,0.08843,-0.06393,0.02239,-0.02307,0.00219,0.01143,-0.03256,-0.01801,0.03333,-0.02718,0.0416,-0.06565,-0.02081,0.00091,-0.05805,-0.01694,0.04679,-0.0647,-0.04553,0.04024,-0.02627,0.02475,-0.06079,0.02633,0.04944,-0.00921,0.07699,0.01034,-0.07787,-0.00882,-0.01821,0.00244,-0.01366,0.0093,-0.0202,-0.0365,-0.04004,-0.01924,-0.05292,-0.03159,-0.01146,0.05075,-0.03445,0.02863,0.04809,-0.0097,0.06546,0.07568,0.02235,-0.0253,0.01878,-0.07758,0.00028,0.00027,-0.07408,0.00893,0.03799,-0.04866,-0.01954,-0.0376,0.04057,0.03888,-0.01923,0.00853,0.01427,-0.00128,-0.0064,0.02326,-0.00542,-0.02874,-0.00258,-0.02981,-0.015,0.01551,0.04356,0.05014,-0.04954,0.1633,-0.04719,-0.01757,0.01775,0.0647,0.08988,0.0113,0.00107,-0.00969,-0.00854,0.02232,-0.03159,0.04538,-0.00142,0.03221,0.02771,-0.05211,-0.05507,0.03385,0.02639,0.00622,-0.05891,0.10202,0.0697,-0.01973,0.05787,-0.00039,-0.08342,-0.07248,0.01528,-0.00589,-0.00744,-0.0176,-0.03842,-0.01208,-0.01401,0.02067,0.02225,0.01438,-0.04554,0.04208,0.00615,0.03597,-0.00771,-0.01599,0.04471,-0.00085,-0.0481,-0.0665,0.06343,-0.04646,0.05685,-0.03398,-0.02722,0.05737,-0.02059,-0.01008,-0.07849,0.08559,0.06273,0.08641,0.00869,0.0316,0.04851,0.04369,0.01179,0.11,0.00268,0.02245,0.05662,0.0041,0.04717,0.04436,-0.00455,-0.08377,0.00947,0.03883,-0.02176,0.00205,-0.0013,0.01691,0.01048,-0.03945,0.02396,-0.06241,0.01354,0.03662,-0.00605,-0.05086,0.01342,0.00755,-0.03854,0.04951,0.08055,-0.01515,-0.06204,-0.04722,-0.01149,-0.01368,0.00497,0.01308,-0.00014,-0.04098,-0.0188,0.03584,-0.02642,-0.0296,0.00193,-0.03543,-0.04232,-0.04375,0.05154,0.01891,0.10359,-0.05323,0.00211,-0.00478,-0.04911,-0.04625,-0.0283,-0.06497,-0.12108,-0.0077,0.03323,-0.01241,0.05345,-0.00134,0.05749,0.00741,0.04582,0.02702,-0.00551,-0.08704,0.02618,0.03392,-0.04543,0.06424],"designer/research-users":[-0.07275,0.01028,-0.09186,0.03485,0.05262,0.00046,-0.02912,-0.07878,-0.09143,-0.03232,-0.03229,-0.00517,-0.03204,-0.00409,0.04228,-0.00964,-0.0445,0.10384,-0.08217,-0.00037,-0.0785,0.00147,-0.00868,0.03038,0.03574,0.04799,-0.0992,0.00574,-0.04024,0.06672,-0.03285,0.02541,-0.05222,-0.0466,-0.02739,0.02017,0.04539,-0.02305,0.00773,-0.02932,0.12965,-0.03304,0.01915,0.02101,0.0469,-0.0927,-0.04664,0.01843,0.00045,0.05824,0.02344,0.01027,-0.07542,0.02703,-0.0389,0.00012,0.01948,-0.03374,-0.08496,-0.02703,-0.04622,-0.03919,-0.04593,0.06313,0.02616,-0.0367,0.05986,-0.04854,-0.04976,-0.01944,0.00259,-0.02772,0.00864,0.03665,-0.05682,-0.03376,0.00365,-0.05125,-0.01188,-0.00136,-0.0711,-0.05361,0.05496,-0.06626,-0.03853,-0.10799,0.01243,0.045,0.05233,0.05535,-0.0728,0.00597,0.01509,-0.02646,0.0026,-0.02609,-0.03635,0.08663,-0.01934,0.03439,-0.03857,0.03142,-0.03237,-0.01218,0.0469,-0.05602,-0.00546,-0.05988,0.03595,0.05825,-0.03193,0.04828,-0.03199,0.02497,0.01301,0.03681,0.06982,-0.13418,0.08869,-0.03014,0.04022,0.01702,-0.03768,0.02801,-0.0075,-0.00914,0.03642,-0.02234,-0.00469,-0.05292,-0.00632,0.03778,-0.02473,0.00641,0.00456,-0.05549,0.01234,0.07466,0.05044,-0.02542,-0.01901,-0.01439,-0.0335,-0.03156,-0.00271,-0.05998,0.02188,-0.00894,-0.01411,0.05931,0.02515,-0.02487,0.01329,-0.01,0.047,0.00861,0.03872,-0.03385,0.02595,-0.02318,-0.08173,0.03865,0.0676,0.03038,0.01336,0.04367,0.0523,-0.03075,0.00739,0.01794,-0.06786,0.04916,-0.09316,-0.00458,-0.03362,0.0187,-0.07538,-0.04558,-0.06236,-0.0291,-0.00564,-0.06071,0.04188,0.03903,-0.02969,-0.05485,-0.04608,-0.04849,-0.00331,0.02245,0.03127,-0.00432,-0.03235,-0.06145,-0.05601,-0.02602,0.10429,0.00473,0.05586,-0.06626,0.06714,0.00442,-0.04092,0.01895,-0.01358,0.07107,0.04402,-0.00108,0.04964,-0.04507,0.06516,-0.03157,-0.00134,-0.02205,0.00032,-0.06198,-0.03976,0.01257,0.05535,-0.01957,-0.02926,0.00834,-0.02524,0.03818,0.02838,0.00299,0.07273,-0.02999,-0.01966,0.02007,0.02733,-0.06732,-0.01621,0.01621,-0.02928,0.00895,0.01083,-0.03473,0.01499,-0.05139,-0.04306,-0.02197,0.02662,0.03942,-0.07719,0.04306,-0.07399,0.03074,-0.09205,-0.05049,0.01187,0.02501,-0.0631,0.00793,-0.00179,-0.04494,0.04963,-0.04693,0.01841,-0.00992,-0.03684,0.04164,0.00945,0.03921,0.0542,-0.01583,-0.05239,-0.06965,-0.00214,-0.01297,0.02168,-0.02128,0.03281,0.01554,-0.00219,-0.09224,-0.02192,0.0096,-0.12332,-0.02472,-0.04726,-0.06118,0.03197,-0.06266,-0.03349,0.00288,-0.05355,-0.0049,-0.02469,0.0269,0.01558,-0.05388,-0.01322,-0.03853,0.05551,-0.04899,0.02767,0.033,0.02267,-0.02492,0.0494,-0.00835,-0.01016,-0.01681,-0.02797,0.07687,0.04371,0.00634,0.06075,0.0159,0.08232,0.02052,-0.0222,-0.02901,0.00454,0.04333,-0.02429,0.0251,-0.05276,-0.04106,0.04423,-0.02221,0.0079,-0.01723,0.08943,0.01028,0.00505,0.06661,-0.06749,0.02194,0.01127,-0.01159,-0.00356,0.00946,-0.0176,-0.01121,-0.06059,-0.0614,0.10838,0.15752,-0.08791,0.01814,0.02107,0.03824,0.02268,0.01344,0.07315,0.02119,-0.06072,-0.02902,0.00652,0.00758,-0.00634,-0.01082,-0.04211,-0.05954,-0.02029,-0.00529,-0.08212,0.02893,0.06024,0.00184,-0.0086,0.01039,0.01814,-0.00208,0.00146,-0.03625,-0.03086,-0.03677,-0.11277,-0.03033,0.01329,0.0473,-0.00075,0.0272,0.02293,0.06686,0.08268,0.08412,-0.02676,-0.02888,0.02825,0.00732,-0.02165,-0.01257,0.04262,-0.03263,0.10701,0.03397,-0.00857,0.04335,-0.03126,-0.01856,-0.04312,0.01516,0.01729,-0.00865,-0.03361,-0.02515,0.00114,-0.0167,0.00955,0.04039,0.06658,0.01756,-0.0006,-0.0375,-0.04367,-0.0098,0.00343,0.04523,0.0493,0.04554,0.0726,-0.12902,-0.02658,-0.00623,-0.03189,-0.07884,0.04512,0.05076,-0.00796,-0.01317,0.02883,-0.00651,-0.03715,0.00224,-0.03761,0.05752,0.02612,0.0365,-0.00416,0.00085,-0.03286,0.03456,0.03983,0.0756,0.02616,0.00332,0.05079,0.10958,0.00375,0.05889,-0.04622,0.09245,-0.03276,0.05679,-0.08031,-0.02824,0.07467,0.03545,0.00965,-0.10404,-0.03981,0.0039,0.00743,0.00468,-0.02743,0.01117,0.02777,-0.02674,-0.04529,0.02708,-0.015,0.07504,0.02273,-0.0281,0.02345,-0.024,0.02836,0.01743,-0.01466,0.07215,-0.08897,0.01165,0.01584,-0.02609,-0.00856,-0.00368,0.00473,0.01371,0.01139,0.07397,0.01974,-0.01086,0.05609,-0.0549,0.04855,-0.00919,-0.02379,0.02702,0.02193,-0.06095,0.02734,-0.04413,-0.07838,-0.03336,0.00317,-0.0522,0.04138,0.04235,-0.04746,-0.00546,0.0141,0.03633,0.03511,-0.01956,0.02817,0.00699,0.06836,-0.00576],"designer/handoff-specs":[-0.05188,-0.03689,-0.01535,0.01732,-0.00046,-0.07793,-0.02256,0.01947,-0.012,-0.05053,0.01677,0.01204,0.01401,-0.03452,-0.07285,-0.06352,-0.0542,-0.0173,-0.05077,-0.04165,0.00804,0.00755,0.03576,-0.04506,0.00307,0.00592,0.10335,0.05459,-0.01234,0.05567,-0.02233,0.01562,-0.03747,0.04969,-0.00522,0.06301,-0.01609,-0.03571,0.08388,-0.02265,-0.04521,0.13702,-0.03192,0.0447,-0.00737,-0.04748,0.00052,-0.01334,-0.02724,0.04052,-0.0728,0.03854,-0.01619,-0.02228,-0.01829,0.03268,-0.04397,0.00576,0.10062,-0.00069,-0.04776,-0.04806,-0.05269,0.01521,0.03978,0.04733,0.03503,-0.01541,0.00645,-0.08124,-0.01368,0.09561,0.06373,0.06368,-0.0916,0.02667,0.05299,0.01225,0.04809,-0.03197,-0.01518,-0.04114,0.05661,0.02523,0.02704,0.01561,0.00864,-0.00218,0.06648,0.0017,0.06416,0.00793,0.02974,0.06655,0.02274,-0.0531,0.05522,-0.05295,0.06792,-0.01558,-0.00267,-0.03435,-0.00141,-0.02777,-0.01732,-0.04999,0.00328,-0.02433,0.02049,0.0643,0.00118,-0.0219,0.04285,0.0503,0.01007,-0.06278,-0.04095,0.02649,0.01079,-0.00458,-0.02661,0.06041,-0.00565,0.00514,-0.00037,-0.0196,-0.01713,-0.06547,0.03997,0.05924,0.02545,0.13056,0.02301,-0.03891,0.00595,-0.01336,-0.01757,-0.02779,-0.00627,-0.01191,-0.05812,-0.01115,0.03324,0.06085,-0.01152,-0.0544,-0.03406,0.01789,-0.03175,0.0325,0.0477,-0.05994,-0.02434,0.04058,0.02286,0.01311,-0.01456,0.0024,-0.0011,0.01521,-0.0699,0.07068,-0.0231,-0.04711,-0.05853,0.04508,-0.05202,-0.02999,-0.03445,-0.04162,-0.02174,-0.02861,-0.10117,-0.01537,0.00056,-0.00989,-0.02577,0.0236,0.03926,0.00129,0.03505,-0.01128,-0.00875,-0.03432,-0.01259,0.03703,0.06483,-0.07816,0.00424,0.02529,0.00288,0.0077,-0.01633,-0.0199,-0.01136,0.03678,-0.03836,-0.00155,0.0188,0.11632,0.01305,0.00117,-0.08138,-0.05389,-0.11284,0.03067,-0.035,-0.02396,0.03971,-0.02556,0.05744,0.00415,-0.02658,0.11606,0.0535,0.00204,-0.0113,-0.02816,-0.03355,0.02825,-0.02233,0.01806,-0.03816,0.02519,-0.05826,-0.12945,-0.04302,0.08305,-0.04665,0.05874,0.04133,-0.00715,0.04828,0.0147,-0.00357,-0.02797,0.01764,0.0255,-0.01167,0.02281,-0.02356,-0.05273,-0.03446,-0.03547,0.00014,0.01628,-0.00643,0.0365,-0.04476,0.03634,-0.03602,-0.06005,-0.05955,0.09913,0.0159,-0.07757,0.06095,0.02603,-0.02221,0.00983,0.00598,0.05682,0.0163,-0.02902,0.02587,-0.01634,0.00521,0.00415,0.01731,-0.01955,0.0223,-0.06691,-0.00272,0.00686,-0.06965,-0.03441,0.00363,0.00897,-0.11634,0.01691,0.05131,0.03589,-0.02285,0.07474,-0.03639,-0.0156,0.00031,0.00627,0.04019,0.03292,-0.01608,-0.04564,-0.02848,-0.03388,0.04798,-0.03404,0.05271,0.05107,0.02208,-0.06817,0.015,-0.02282,-0.0143,-0.00213,-0.05678,-0.00181,0.04777,0.00076,0.0382,-0.01236,-0.06244,0.05644,-0.09162,-0.04547,0.00328,0.0746,0.01779,0.0443,0.05896,-0.00659,0.01776,0.03252,-0.00703,0.00448,0.05651,0.02923,-0.07622,-0.02096,-0.06619,0.02743,-0.01375,-0.03,0.02389,-0.08738,-0.01685,0.01228,0.01354,-0.09419,0.04012,0.06467,-0.07034,0.04218,0.01239,0.00513,0.02653,0.02712,0.01212,-0.04425,-0.02743,-0.0003,0.0293,0.02464,0.03483,0.05337,-0.08109,-0.0278,0.01622,0.03269,0.03862,0.06344,0.05316,-0.06317,-0.01981,0.05274,-0.00641,0.03524,0.05444,-0.00916,0.06969,0.00272,0.01347,-0.01638,0.00422,0.08491,-0.06677,0.05301,-0.02516,0.08525,-0.00716,-0.07449,0.02409,-0.00764,0.07334,0.03132,-0.01618,-0.03004,0.02313,-0.01051,0.07584,-0.0197,-0.01182,-0.01635,0.02049,0.00201,-0.06804,0.02248,-0.03903,-0.02478,0.02859,-0.04878,0.04222,0.03775,-0.02931,0.06115,0.02129,0.05665,-0.03694,0.01806,-0.00268,0.00234,-0.09023,-0.00982,0.05793,0.00472,0.03513,-0.01262,0.04671,-0.02231,-0.04354,-0.04358,0.05937,0.14811,-0.07928,-0.03226,0.0473,-0.07502,0.10169,-0.08012,-0.01865,0.05521,0.05243,-0.00432,-0.06811,-0.07019,-0.0527,0.00866,-0.03107,0.0473,-0.00496,0.06771,0.05742,0.07843,-0.04339,0.06286,-0.05709,0.02692,0.02047,0.11414,0.01041,-0.00883,0.01003,0.04687,0.0184,0.02723,-0.03305,0.00302,0.06165,-0.02783,-0.00886,0.0227,0.0063,-0.10635,-0.00052,-0.01819,-0.02956,-0.02981,-0.06616,0.05037,0.09222,0.11466,0.02679,-0.00631,-0.05728,0.01303,0.02055,0.02641,-0.02765,-0.00386,0.0049,-0.05136,-0.03218,0.01155,0.05449,0.01034,0.02548,-0.02917,0.05146,-0.0443,0.02074,0.01185,0.03715,0.0082,-0.02748,-0.00616,0.02224,0.02036,-0.02646,-0.0161,-0.01417,-0.00007,0.08663,-0.0772,0.02033,-0.00337,0.02968,0.10334,0.00372,-0.01668,0.05288,-0.00103,-0.05171,0.02803],"designer/review-usability":[0.06019,-0.01954,-0.02099,0.10776,0.00891,-0.03731,-0.02945,-0.15408,-0.01897,-0.06142,-0.00033,-0.0107,0.03748,-0.0051,0.00446,-0.03206,-0.00627,0.05022,-0.08862,0.01031,-0.0117,0.00793,0.01079,-0.01959,0.03096,-0.00624,0.01769,-0.00496,0.01123,0.07466,-0.13321,0.06403,-0.01574,-0.06099,0.01572,-0.01619,0.04903,0.03818,-0.03144,-0.02538,0.00599,0.0179,-0.03864,0.00286,0.10967,-0.11574,-0.06752,0.06994,0.02371,0.07226,0.04435,0.0132,-0.03543,0.0349,-0.01326,-0.05599,0.01354,0.03089,-0.01079,0.02788,0.01947,0.02852,0.01223,0.0038,0.01795,-0.01617,-0.01119,-0.04125,-0.06224,-0.06464,-0.06182,-0.05169,0.03547,0.05258,-0.04363,-0.05267,-0.03828,-0.02256,0.01971,0.03504,-0.00684,-0.0411,0.0405,-0.01342,-0.02912,-0.02241,-0.00719,0.08827,0.04511,0.0383,-0.0124,0.01861,0.05955,0.10324,0.01451,-0.05678,-0.06321,0.00912,-0.00663,-0.02246,0.01542,-0.02444,0.00818,-0.00601,0.02319,0.02074,0.08846,-0.04886,0.0854,-0.03645,-0.00374,0.02429,-0.03918,0.03287,0.02513,0.03873,0.03535,-0.03626,0.03909,0.01719,0.08562,-0.00959,-0.00348,0.08447,-0.01465,0.00404,-0.03665,-0.00387,0.05539,-0.03081,-0.04175,0.00474,-0.0172,0.02523,0.05247,-0.06347,0.06956,0.02666,-0.01393,0.05617,0.04672,0.02432,-0.05808,-0.03797,0.0051,-0.00317,0.01108,0.02617,-0.02963,0.07517,0.05934,-0.0197,0.00688,0.01572,0.0262,-0.10107,-0.02931,-0.08834,0.05793,-0.06367,0.0476,0.12731,-0.0149,-0.05591,0.00419,0.03027,-0.01126,-0.02131,-0.0163,0.00158,-0.10022,0.01191,-0.0627,-0.02387,0.01319,0.03139,-0.01688,0.00824,0.00694,0.04286,-0.01766,-0.13775,0.02193,0.00487,-0.00394,-0.01719,0.04976,-0.05586,0.02078,0.01097,-0.05687,-0.05169,-0.00681,-0.08589,0.01768,0.01691,-0.04741,0.02109,0.0155,0.01086,0.03637,0.04123,0.01935,-0.01,0.03962,-0.01815,-0.03423,0.00305,0.01865,-0.01521,0.04803,-0.04442,-0.11935,-0.0581,0.02483,0.01417,-0.00537,0.01016,-0.03921,-0.0015,0.00407,-0.00076,-0.01957,0.00641,-0.00393,0.00975,0.01627,0.00044,-0.04749,0.07863,0.03277,-0.03567,0.09294,0.02007,-0.0093,-0.03066,0.00606,-0.01131,-0.0401,-0.0367,-0.0859,-0.0684,-0.00659,0.02084,-0.00197,0.035,0.09283,0.07835,-0.01478,-0.05426,0.08658,-0.08876,-0.04102,0.05151,-0.02244,-0.03409,-0.01077,0.01263,0.04453,-0.00647,-0.04848,0.02191,-0.09369,0.0383,0.03434,-0.04646,-0.00426,-0.05906,-0.01776,0.03266,-0.06799,-0.02357,-0.00406,0.06939,0.07425,-0.03664,0.01467,0.05474,-0.01956,-0.03518,-0.05496,-0.05116,0.03212,0.08073,-0.08327,-0.00139,-0.00901,-0.00405,0.04068,-0.0541,-0.00432,-0.04408,0.00146,0.05148,0.02966,-0.02339,0.0134,0.04348,0.02811,-0.02368,0.01313,-0.01561,-0.01203,-0.06003,-0.04139,0.02262,-0.04742,-0.01794,-0.00766,0.02157,-0.05029,0.02895,-0.01467,-0.06665,0.00041,0.03871,-0.04949,-0.03788,-0.00419,-0.01917,-0.01977,-0.00807,-0.00575,0.00812,0.0762,0.01291,-0.11408,0.03833,-0.09907,0.02973,-0.07226,-0.03625,0.00131,-0.04128,-0.06465,0.06175,-0.00122,0.02685,0.09496,0.03132,-0.05834,-0.0169,0.03325,-0.04243,0.00047,0.00268,0.0108,-0.02146,-0.01711,-0.09818,-0.01835,0.02468,-0.01206,-0.00946,-0.0808,0.00471,0.04037,-0.04971,-0.02997,0.06576,0.04344,0.05371,-0.03698,-0.03333,0.02484,-0.0222,-0.02382,-0.00086,0.02631,-0.01819,-0.02803,0.01945,0.00082,0.02395,0.00339,0.04604,-0.01433,0.02978,0.05362,0.08877,0.01456,-0.0855,0.06583,-0.01242,0.04207,0.0044,0.00167,-0.04033,-0.03928,0.03279,-0.12773,-0.00314,-0.04083,-0.0067,0.09862,0.04876,0.00851,0.0864,-0.01819,0.05802,0.03363,-0.01912,-0.00632,0.02186,0.0212,0.02845,-0.00527,-0.0018,0.02133,0.00216,-0.05817,0.09181,-0.10413,0.01363,0.13195,-0.02211,-0.04162,-0.00348,-0.01943,-0.03149,-0.01853,0.01537,-0.09578,0.0336,-0.00521,0.01752,-0.00651,-0.0018,-0.04692,0.02887,0.04481,-0.02333,-0.02824,-0.02502,-0.08548,0.03317,-0.00195,-0.02518,0.01494,0.01327,-0.00193,0.08817,0.068,0.07753,0.01452,0.07683,-0.02162,-0.00625,0.01714,-0.0057,0.03045,0.0263,-0.05558,-0.0424,-0.01749,-0.01238,0.05872,0.0257,0.00386,0.02707,-0.06577,-0.04878,0.02261,0.01273,0.01777,0.06593,-0.00091,0.00125,-0.04343,-0.01885,0.01297,-0.01617,-0.04858,-0.00571,0.01924,-0.00776,0.04671,-0.00108,0.01821,-0.01527,0.00271,0.02861,0.11616,0.01208,0.00717,0.00013,-0.04117,-0.04557,0.05165,0.04032,0.04427,-0.01297,-0.03669,0.0907,0.02613,-0.03431,0.01696,-0.02837,-0.05871,-0.05551,0.03324,-0.03788,-0.04445,-0.00849,0.0005,0.00344,-0.03535,-0.03551,0.01411,-0.06127,-0.00078,-0.03319],"engineer/build-features":[0.04806,-0.00833,-0.01662,0.01526,0.04017,-0.04058,-0.11441,-0.0815,0.01541,-0.03568,-0.04961,0.01135,-0.05975,0.01077,0.00948,-0.00077,-0.00938,0.01519,-0.01979,0.02375,-0.01674,-0.04892,0.01108,0.00355,-0.02402,-0.01368,-0.07993,0.00746,0.02237,0.069,-0.04063,0.00649,0.0084,0.01646,0.07339,0.11857,0.04492,-0.03131,0.02057,0.08417,-0.02193,0.11226,0.04084,-0.0797,-0.01942,0.02039,-0.04589,-0.09741,0.05091,0.02325,-0.06534,0.00503,-0.11536,0.04801,-0.02524,-0.00494,-0.04321,0.00302,0.00389,-0.04328,0.00331,-0.0632,-0.01103,-0.00652,0.1066,-0.0246,0.02606,-0.03948,0.02928,-0.08079,-0.06386,0.05188,-0.01966,0.10941,-0.01693,-0.00359,0.11601,-0.04773,-0.01007,0.0302,0.04874,-0.10023,0.04732,-0.06571,0.00806,0.05218,-0.00322,-0.00608,0.06986,-0.01993,-0.01496,-0.05835,0.05656,0.06659,0.02085,-0.04771,-0.00376,0.00428,0.0973,-0.03523,-0.00211,-0.0709,0.04643,-0.0268,0.01239,-0.01707,-0.02654,0.04001,0.05953,0.10928,0.05265,0.01073,0.07199,-0.04884,-0.02428,-0.02441,-0.01232,0.01809,0.09013,0.00394,-0.03897,0.04549,-0.04148,0.01776,0.08727,-0.04437,-0.01782,-0.01789,-0.04801,-0.0335,-0.02189,0.08344,-0.04957,0.01399,0.05647,-0.02236,-0.01138,-0.00998,0.03704,0.00155,-0.03128,-0.03667,0.01135,-0.01389,-0.01168,-0.0829,0.00544,-0.03303,-0.02035,0.06427,0.04615,-0.0597,0.00886,0.01007,0.05738,0.00941,0.05975,0.03717,0.04585,0.02852,-0.13387,-0.05756,-0.03841,0.06955,-0.00255,0.01118,-0.00535,-0.05965,0.00317,-0.03675,-0.08942,-0.02106,-0.09481,0.00867,0.0167,0.03164,-0.0211,-0.06073,-0.00774,0.00184,0.00691,0.01999,0.02018,0.04266,-0.05826,-0.03132,-0.05202,-0.03986,0.00018,0.04635,-0.04972,-0.01013,-0.07338,-0.08644,-0.04012,-0.02809,0.02382,-0.0444,0.02941,-0.0085,-0.02455,0.04377,-0.02036,-0.00685,-0.02987,0.09489,-0.05711,-0.05482,0.04438,-0.07383,0.06669,-0.0191,0.04423,-0.03664,-0.02231,-0.01923,-0.0093,-0.01723,0.06447,0.06436,-0.0042,0.02599,-0.09829,-0.0087,-0.06778,-0.00105,-0.04008,-0.01408,-0.02085,0.04374,0.03899,-0.01618,0.04571,0.01043,0.01406,0.02139,0.00153,0.0233,0.01861,-0.00664,0.06221,-0.02641,0.00152,-0.03407,-0.04295,-0.06528,-0.02233,0.05223,-0.06493,0.0416,0.02736,-0.00743,-0.01446,-0.04356,0.00028,0.006,0.02138,0.00819,0.04844,-0.0342,-0.04156,0.07032,0.02577,-0.01636,0.00418,-0.00649,0.01075,0.04312,0.06651,-0.0381,-0.02251,0.01967,0.00421,-0.0123,-0.00172,0.01227,-0.02232,-0.03252,-0.05906,0.01296,0.02504,0.05679,-0.02103,0.00038,0.00981,0.01759,-0.05227,0.00889,0.03353,-0.10257,0.0319,-0.05262,-0.07689,-0.06657,0.02903,-0.00811,0.02151,0.05454,0.03671,-0.0194,-0.04932,-0.02832,-0.00202,0.00992,-0.06277,0.00929,0.04597,0.05651,-0.04055,0.03048,0.04917,0.03055,-0.0506,0.03355,-0.00186,-0.03926,-0.00413,0.03358,-0.01092,-0.03478,0.01456,0.02622,0.04423,-0.02324,0.09189,0.0605,-0.03702,0.01968,0.02512,0.017,-0.07335,0.0031,0.04793,-0.05285,-0.01598,0.02934,-0.02221,-0.05229,0.02681,0.03648,-0.02966,0.01717,0.10814,-0.02135,0.00418,-0.01147,-0.00653,-0.09296,-0.0858,-0.0049,-0.05407,0.06735,0.02807,0.02505,-0.11295,-0.05358,-0.00422,0.0451,-0.03986,-0.0242,0.00964,-0.06158,-0.01676,0.01249,-0.01317,0.02311,0.00172,-0.06052,0.0378,0.00914,-0.03628,-0.03944,0.11899,0.04532,0.00881,-0.0533,0.02337,-0.01161,0.06432,-0.05201,0.01195,-0.03088,0.00793,-0.03378,0.00031,-0.03862,0.05692,0.02159,0.05431,0.07333,0.02997,0.02558,0.04204,-0.0364,-0.05745,0.05009,-0.04258,0.00818,0.01329,-0.00146,-0.00358,-0.00339,-0.11463,0.05848,-0.03859,0.05495,0.05461,-0.04191,-0.01187,0.01666,-0.04355,-0.03045,0.08454,-0.00008,0.04575,-0.00237,-0.03565,0.04182,0.04647,-0.00218,0.01236,0.02383,0.00277,-0.0319,-0.04857,-0.06492,-0.048,-0.04602,0.0425,0.05391,0.03686,-0.04792,0.00979,-0.05615,-0.00526,0.07793,-0.01131,0.05561,0.02023,0.00087,0.02657,0.05378,-0.02129,0.01658,-0.01034,-0.02722,0.0244,0.05969,-0.06669,0.02414,-0.04569,0.07919,-0.00948,-0.05505,-0.03099,0.06389,0.02576,-0.0141,-0.0265,0.02983,0.07052,-0.02112,-0.03968,-0.0741,0.01364,-0.02403,-0.01682,0.02107,0.06319,0.02204,0.06175,0.02361,-0.00826,0.00195,0.0252,-0.02464,0.00725,0.01914,0.00773,0.02131,0.05693,-0.02291,-0.02599,0.06761,-0.06291,0.03274,0.03285,-0.07312,0.00882,-0.03421,0.02469,-0.06198,0.04496,-0.05408,-0.01069,0.02738,-0.03883,-0.03653,0.09559,0.01061,0.0546,0.00317,0.00978,-0.03743,0.05886,0.01941,0.04374,-0.00038,-0.00637,-0.00509,0.02502,-0.04621],"engineer/debug-fix":[-0.01334,-0.07458,-0.0351,0.02466,-0.01833,-0.04916,0.01495,-0.02735,-0.00038,-0.05507,0.00646,0.03659,0.00396,0.01316,-0.06912,-0.04097,-0.00789,-0.01887,-0.03539,0.08148,-0.00266,-0.03166,0.03687,-0.00011,-0.00807,0.02997,-0.0512,0.09065,0.04608,0.03047,-0.02257,-0.0531,-0.02885,-0.12166,0.03015,0.01645,0.01898,0.03212,0.0391,0.04804,-0.02869,0.0593,-0.03907,-0.00811,0.02677,0.01206,-0.06599,0.00453,-0.05189,0.00186,-0.04476,0.02914,-0.18374,0.0029,0.05068,-0.00351,-0.04838,-0.0235,-0.0052,0.03535,-0.01955,0.02402,0.04236,-0.02902,0.0297,0.03402,-0.01012,0.07223,0.01136,-0.04513,0.05603,0.06307,0.05415,0.06361,0.00946,0.05197,-0.18464,-0.05132,-0.03164,0.01774,0.00459,-0.13253,0.06264,0.04291,0.06172,0.07976,-0.01003,0.06025,0.03605,-0.00316,0.0801,0.00581,0.01419,0.12934,0.00156,-0.09005,-0.07509,0.03245,0.0632,-0.00381,0.00018,-0.0159,0.09374,0.03975,0.03282,0.06762,0.03711,-0.01216,0.02329,-0.0074,-0.05944,-0.02728,0.02292,0.00904,-0.00653,-0.03821,0.01644,-0.00186,0.06282,0.0574,-0.02535,0.027,0.01572,0.03793,0.04216,0.01182,-0.0436,-0.02732,0.00907,-0.00637,-0.01382,0.04272,-0.07855,0.05509,0.03277,0.03666,-0.00636,0.00041,-0.05432,0.01976,0.08766,0.06441,0.09743,-0.0207,-0.05643,-0.02159,0.00473,0.0684,-0.01271,0.02104,0.00431,-0.03388,0.03887,-0.01076,0.03715,0.0021,0.08095,-0.0521,-0.01692,-0.03229,0.01826,0.12713,-0.05567,-0.01888,-0.03321,-0.00462,-0.00462,-0.01485,-0.01684,0.01736,-0.04686,-0.01607,-0.08197,-0.08206,0.0066,0.02977,0.00785,-0.0247,0.05506,0.00258,0.00694,-0.06139,0.06693,0.04235,0.00116,0.00176,0.04779,-0.05652,-0.00421,0.0338,0.05529,-0.02121,-0.07199,-0.05584,0.04546,0.02975,-0.05053,-0.04821,-0.01558,0.04763,0.05579,0.02096,0.03651,-0.03136,0.03134,0.05172,0.00548,-0.00344,-0.03698,-0.05602,0.09474,-0.04291,-0.04039,0.00858,0.01954,0.01684,-0.03552,0.00975,0.01382,-0.01214,0.01361,-0.01523,0.03415,0.00303,-0.04503,-0.06268,0.02859,0.01992,0.02195,-0.00533,0.04612,-0.02354,0.03139,-0.04388,-0.02335,-0.01746,0.02605,0.03533,0.02219,-0.03176,-0.03926,-0.04188,0.00325,0.02418,0.00961,-0.02477,0.03973,-0.00008,0.04645,0.09223,0.07461,0.00365,0.0475,0.04486,0.04181,-0.06349,0.02703,0.06041,0.09913,-0.05702,-0.00462,0.06985,-0.06164,-0.01227,0.016,-0.02689,-0.02952,-0.00213,-0.0749,-0.03289,-0.0541,-0.00144,-0.01346,0.04358,0.01609,0.03428,0.01632,0.04117,-0.01488,-0.03176,0.02921,0.04733,0.00591,-0.01403,-0.01995,-0.05053,0.02213,-0.00798,0.03336,0.02402,0.03421,-0.09682,-0.0622,0.01229,0.06949,0.02956,0.01115,0.04117,0.00574,-0.01036,-0.01955,-0.02153,0.03576,-0.01911,0.0381,-0.01595,0.0404,0.02943,0.03677,0.10371,0.01546,-0.00799,-0.0585,0.02105,0.05378,-0.02898,-0.04697,0.018,0.0482,-0.02792,-0.03702,-0.02155,-0.02456,-0.02034,-0.13192,0.05425,0.02614,0.00379,-0.07643,0.00108,-0.03837,-0.03526,0.0813,-0.09244,-0.01535,0.01566,-0.01446,0.03553,0.0208,0.02764,-0.02808,0.05072,0.03977,-0.02661,-0.06668,0.05994,-0.00449,-0.02239,-0.01388,-0.06482,-0.01297,0.04147,0.04701,-0.00773,-0.08619,-0.04629,0.05127,0.01956,0.08735,-0.00595,-0.01439,0.03726,-0.0054,0.02182,0.04747,-0.00537,0.05517,-0.06028,-0.02629,0.00177,-0.06553,0.05934,0.02954,0.00153,0.03357,-0.0463,-0.03715,-0.05175,0.1423,0.02849,0.00902,-0.02729,0.09973,-0.03548,0.03079,0.01861,0.01122,-0.07963,0.02679,0.05421,-0.05678,-0.00507,0.01993,-0.03387,-0.02133,0.00431,-0.07375,0.02384,0.01011,-0.03519,0.04238,-0.01786,-0.05708,0.02262,-0.0311,0.05781,-0.03524,0.00666,0.04828,-0.04648,-0.08003,-0.00031,0.00993,0.0054,-0.02593,0.07726,0.00089,0.00504,0.04519,-0.02519,0.01287,0.01561,-0.06599,-0.02317,0.03552,0.02775,0.01869,-0.07861,-0.04354,-0.03224,0.06341,0.01242,-0.02241,0.01507,-0.00861,0.04972,0.02151,0.02872,-0.00756,-0.01525,0.00775,0.11328,0.03365,0.03979,0.01369,0.05672,-0.04064,0.02779,0.00097,0.03092,0.00629,0.05982,0.03946,0.00389,-0.00611,-0.00854,0.03807,-0.04754,-0.01349,0.05603,-0.04867,0.01497,0.00614,0.04429,-0.03092,-0.02074,0.01807,-0.00121,0.02314,0.04097,0.03651,0.05347,-0.02213,-0.00063,0.01296,0.055,0.06187,-0.00811,0.05404,-0.04598,0.00357,0.00129,0.09244,-0.01399,-0.00272,-0.04687,-0.0493,-0.01413,-0.00409,0.0419,0.05107,-0.05192,0.04684,0.04904,-0.0247,-0.06252,-0.00054,0.01299,0.05005,0.00714,0.02648,-0.0977,0.04755,0.02074,-0.00098,0.01065,-0.00991,-0.0182,-0.07453,0.00207,0.02311,-0.0143],"engineer/design-systems":[0.00261,-0.05448,-0.0043,0.03224,0.01951,-0.09545,-0.05712,-0.03053,0.01431,-0.01675,-0.00663,-0.00956,-0.0085,-0.0032,0.03748,0.01484,0.0667,0.05051,-0.04618,-0.02751,0.04911,0.01582,0.00612,-0.01539,0.01374,0.02111,0.08994,0.05343,-0.00624,0.00161,-0.02561,0.0065,-0.06164,0.06348,-0.01066,-0.02453,0.00692,-0.01553,0.03679,-0.01659,0.0091,0.02778,-0.03341,-0.07722,0.02517,0.02111,-0.03615,-0.02553,-0.0088,0.02014,-0.01012,0.00559,-0.0001,0.02243,0.012,0.05316,-0.01503,0.01765,0.0653,-0.01335,0.02373,-0.02389,-0.00057,0.05792,0.01326,0.0539,-0.04166,-0.00491,0.06147,0.00587,-0.06241,-0.00715,0.04196,-0.0234,-0.06236,0.00806,0.08942,0.07632,0.09688,-0.01347,-0.04577,-0.05158,0.05396,0.03629,0.02461,0.0161,0.0365,-0.03041,0.00504,-0.03402,-0.0023,-0.00076,0.01086,0.06134,-0.00528,-0.06448,0.02665,0.01641,0.0971,0.02117,-0.02718,-0.0455,-0.04674,-0.07819,0.00025,-0.03241,0.01803,-0.07452,-0.02387,0.12059,0.03164,-0.0122,0.02731,0.02009,-0.06335,0.03209,-0.06342,0.02884,0.07321,-0.03665,-0.00909,0.04289,-0.04304,-0.00058,-0.01455,-0.05562,-0.03173,-0.05483,-0.00501,-0.02437,0.03288,0.04285,0.04565,-0.02504,-0.021,0.05112,-0.03713,-0.01763,0.07605,0.023,-0.07398,0.01811,-0.00342,0.02295,0.01632,-0.12451,0.00157,0.05415,-0.03109,-0.02101,0.01778,-0.04055,0.00599,0.05221,0.00699,0.01195,0.01944,-0.01665,-0.02331,0.06245,-0.08628,0.01135,0.01883,-0.05413,-0.03441,-0.06294,0.03454,-0.03636,0.02378,-0.01784,-0.08759,-0.05343,-0.07784,-0.02487,-0.05959,0.00374,-0.01503,0.04964,0.02525,0.00781,0.02832,-0.04613,0.05588,-0.01531,0.08489,-0.02081,0.08874,-0.02819,-0.03261,0.01894,-0.04756,-0.04985,0.01625,0.0104,0.00581,-0.00584,-0.03449,-0.02317,-0.11745,0.0595,0.05542,0.02412,-0.06008,-0.01581,-0.06015,0.05716,0.01558,-0.03636,-0.0475,-0.05009,0.04794,-0.00436,0.00408,0.06436,0.02074,0.02431,0.01158,-0.05507,0.03904,0.05042,0.02636,0.03122,-0.03573,0.0442,0.00949,0.00018,-0.06276,0.07304,-0.06652,0.00079,-0.01297,0.01292,0.04281,0.03259,-0.01725,0.0637,0.02597,-0.00067,-0.00138,0.09501,-0.06361,-0.04415,-0.092,-0.0493,0.06842,0.07471,0.01859,-0.00127,-0.10429,-0.06653,-0.03249,-0.0461,-0.09124,-0.01579,-0.04571,0.01984,0.00405,-0.02276,-0.01948,0.02949,-0.02159,0.09424,0.02394,-0.06125,-0.0058,-0.03441,-0.03128,-0.02616,0.02676,-0.0547,0.00673,-0.00453,0.00361,-0.00217,-0.04426,0.02994,-0.03527,0.0053,-0.06039,0.01993,-0.02959,0.04764,-0.01704,0.04043,0.00558,0.03814,0.00311,-0.03244,0.0449,-0.00039,0.05883,-0.10757,-0.01939,0.00428,-0.01283,-0.03699,0.00622,-0.00995,0.019,-0.03538,-0.01905,-0.02262,0.01047,-0.05302,-0.01688,-0.07145,0.09531,-0.01283,-0.0218,0.01608,-0.04225,0.02017,-0.0105,0.00523,-0.04033,0.02187,-0.01932,-0.00342,0.02695,0.01978,0.04448,-0.03605,-0.03878,0.05699,0.02626,0.02984,-0.11535,-0.08762,-0.03773,-0.00956,-0.01287,-0.04177,0.06046,-0.02221,-0.02695,-0.01944,-0.06513,-0.02611,0.04095,-0.01721,0.00022,-0.01802,0.02969,-0.00019,0.0077,-0.04384,-0.01245,-0.00705,-0.08674,0.00598,-0.04599,0.0206,0.00302,0.06817,-0.14988,-0.02488,0.05427,0.03479,-0.02927,0.01377,0.02515,0.01455,0.0485,0.02512,-0.04037,0.01128,-0.02604,-0.01134,0.08174,0.05378,0.05478,-0.04234,-0.04038,0.00701,-0.10315,0.03539,-0.04756,0.02783,-0.0267,-0.08387,-0.04903,-0.03576,0.05794,0.07517,-0.00023,0.04065,0.02481,0.01074,-0.00324,0.05841,-0.00538,0.02098,-0.02332,-0.00827,0.02842,-0.01071,0.00978,-0.02079,0.07683,0.00026,0.0204,-0.02015,-0.08547,-0.00886,0.03021,0.02679,-0.03931,0.00734,-0.03276,-0.04412,-0.0812,-0.00196,0.01076,0.02211,-0.04406,0.03544,0.06727,0.01741,0.00677,-0.01077,0.03106,0.08346,-0.0675,-0.042,-0.05174,0.02668,0.11092,-0.04223,-0.03238,-0.05008,0.06174,-0.01929,-0.06227,-0.00249,0.00026,-0.02001,0.03486,-0.04255,0.07483,-0.04534,0.09105,0.09529,0.02825,-0.00914,-0.01484,0.02093,0.00756,0.08553,0.04126,-0.05653,0.04983,0.05381,-0.01909,0.02116,-0.0295,0.03793,-0.02468,0.00033,-0.03857,-0.06927,0.02076,-0.03549,-0.04554,-0.047,0.002,0.02627,-0.09496,0.0896,0.07912,0.08344,-0.04497,-0.02527,-0.05097,-0.03973,0.0198,0.05425,-0.00806,-0.00121,0.01997,-0.06308,-0.03775,0.01442,0.04666,-0.02472,-0.02963,-0.03221,0.01969,-0.01617,0.0532,0.0623,0.05495,-0.00486,-0.09073,0.01461,0.02367,-0.00466,-0.09975,-0.0241,-0.04903,-0.00196,0.04895,-0.0849,-0.01053,-0.00022,0.02404,0.09094,0.01888,-0.07849,-0.05113,0.10053,-0.02546,0.01375],"engineer/write-tests":[0.0408,0.05415,-0.08036,0.0741,-0.00011,-0.01091,-0.07208,-0.0685,0.00782,-0.01894,-0.02844,-0.03162,-0.02106,-0.04777,0.02084,-0.01319,-0.02523,0.0268,-0.07992,0.02256,0.06364,-0.01678,0.00383,-0.04173,-0.02583,0.01871,0.00824,0.02427,0.05709,0.17389,-0.03839,0.0037,-0.07271,-0.01744,0.03607,0.00631,0.09694,0.02346,-0.01499,-0.01153,0.01006,0.02265,-0.06172,-0.07383,0.05809,-0.01002,0.01441,0.00298,0.0393,0.04832,-0.08421,0.00681,-0.01272,-0.05414,-0.00836,0.03062,-0.03402,0.02057,-0.03127,0.01718,-0.01813,-0.06193,0.02393,-0.00654,-0.03197,0.02656,0.02787,-0.01839,-0.08242,0.0105,0.00065,-0.03257,-0.00328,0.07552,-0.06197,-0.02852,0.01174,-0.06985,-0.00031,0.04475,-0.04798,-0.06822,0.0831,-0.05338,0.00612,0.02005,0.03897,0.04936,0.03929,0.02348,-0.0145,-0.00377,0.04259,0.06436,0.0077,-0.03526,0.02966,0.02393,0.01737,-0.06773,-0.01538,-0.01702,0.13566,-0.07041,-0.01374,0.01774,0.02008,-0.03732,-0.00569,0.00261,-0.03587,0.03358,-0.00011,-0.00749,0.02238,0.02484,0.00502,-0.0115,0.03654,0.08185,0.10605,0.04556,-0.01131,0.0455,-0.04458,-0.03761,-0.00875,0.08237,0.03761,-0.02216,-0.07713,-0.00266,-0.05557,-0.0138,0.03017,-0.04159,0.00527,0.05138,0.01162,-0.01897,0.03835,0.0502,0.01246,-0.02535,-0.06789,-0.02267,-0.01731,0.02641,-0.01934,-0.02304,0.01163,-0.05003,0.00188,0.03903,0.00568,-0.04024,0.04969,0.00792,0.01341,-0.05721,0.00833,0.11863,-0.06778,-0.02727,-0.01106,0.0209,-0.03009,-0.03931,0.00062,-0.00868,-0.05188,-0.02444,-0.03505,0.02715,0.02199,0.02559,-0.0365,-0.07417,0.04232,-0.00595,-0.05985,-0.0175,0.01055,-0.01079,-0.05438,-0.01495,0.03439,-0.07779,0.03422,0.04323,0.00681,-0.05228,-0.02775,-0.08289,0.03942,0.00101,-0.02971,-0.03807,-0.01179,-0.0459,-0.07927,0.02009,-0.02338,-0.00694,-0.01551,0.05255,0.03958,-0.02849,0.02737,-0.07519,0.03337,-0.01441,-0.04866,-0.07419,0.02037,-0.04288,-0.00382,-0.04481,-0.02602,0.02826,0.02378,0.04075,-0.04835,0.06526,-0.01267,0.01373,-0.02221,0.04732,-0.03538,0.04436,0.01748,-0.03878,-0.01592,0.01924,-0.05324,-0.0156,0.02341,-0.02293,-0.02129,0.03488,-0.02744,-0.08121,-0.0143,0.05486,0.00007,0.00149,0.01864,0.00526,-0.08632,-0.07257,0.03015,-0.04582,-0.06504,0.0389,0.00633,-0.00567,0.04936,0.08689,0.03229,-0.02504,-0.08321,0.05556,-0.08709,-0.02703,0.01328,-0.08829,-0.03132,0.0069,0.04674,-0.04025,-0.07153,-0.03723,-0.02571,0.04664,-0.00246,0.01942,-0.02905,-0.05322,0.00257,-0.00147,-0.05395,-0.00064,0.00851,-0.00383,-0.04572,0.03286,-0.05066,-0.03855,0.05616,0.02283,0.012,0.00064,0.01742,-0.0259,0.03065,-0.02338,0.03737,-0.00657,0.0698,-0.0472,0.04571,-0.08793,-0.01654,-0.00473,-0.00717,0.0279,0.04455,0.03758,0.0331,0.07281,0.03695,-0.07539,-0.04078,-0.0191,-0.01202,-0.00783,-0.03067,0.02178,0.02004,-0.03485,0.01206,-0.03424,0.08268,-0.00425,0.08014,0.06772,-0.04681,0.07783,-0.07586,-0.00563,-0.0524,-0.05281,0.03357,-0.05994,-0.03272,0.03105,-0.02605,-0.04289,0.0894,0.00362,-0.09222,0.03425,0.02541,-0.0548,0.05262,-0.01669,-0.0081,-0.02328,-0.04658,-0.04053,-0.01274,0.0274,-0.04566,0.1008,-0.09193,-0.03136,0.02166,0.01598,-0.01385,0.00727,0.01061,-0.06202,-0.03078,0.06833,0.03097,0.00022,-0.0385,-0.03589,0.00037,0.02284,-0.06032,0.01383,0.08612,0.02902,0.06547,-0.06005,-0.00823,-0.1075,0.03026,0.08385,-0.02984,-0.01345,0.03087,-0.01993,0.03092,0.01919,0.06045,0.05062,-0.03554,0.06851,-0.0624,0.0421,0.04612,-0.04596,0.01971,-0.0236,-0.01282,0.03989,-0.07043,0.04228,0.03024,-0.01673,-0.03527,-0.01865,-0.03665,0.07397,-0.0361,0.01287,0.02637,-0.00875,-0.05332,0.07756,0.02677,0.05936,0.04352,0.0803,-0.0305,0.05966,-0.03078,0.01914,-0.03243,0.14505,-0.06399,0.03967,0.00254,-0.02486,-0.0437,0.01784,-0.00031,-0.04687,0.06568,0.06577,-0.02512,-0.02026,-0.06077,-0.01223,0.00366,0.05291,-0.0738,-0.00045,-0.09625,0.0604,0.07006,0.01399,0.01669,0.10482,-0.0072,0.02726,-0.0511,0.01802,0.01121,0.06462,-0.00412,-0.01025,-0.06348,-0.00956,0.02898,0.02765,0.07389,0.01425,-0.0759,-0.00843,0.03332,-0.05551,-0.00073,0.03386,-0.0311,0.06518,-0.00962,-0.01655,0.04904,-0.00977,-0.03626,-0.01872,-0.00235,-0.00313,0.09864,-0.06024,0.01896,-0.07363,0.00479,0.02601,0.04156,0.02695,-0.04063,0.03682,0.02697,-0.02704,0.10019,0.01665,0.04938,-0.01898,-0.01786,-0.02849,0.03999,-0.01481,-0.08068,-0.02997,0.0507,0.00445,-0.00065,-0.02994,0.02648,0.03763,0.04347,0.06061,0.03538,0.00792,-0.04335,-0.02579,0.00714,0.00963],"engineer/review-code":[-0.03944,-0.02611,-0.03855,0.09856,0.02956,-0.04363,-0.02968,-0.03092,0.00758,-0.01932,-0.01187,-0.01913,0.0018,-0.0394,0.01661,-0.05265,-0.05469,0.04457,-0.02293,0.01064,0.03632,0.01059,0.02543,0.00635,-0.00126,-0.00623,-0.04495,0.0588,0.0086,0.04108,-0.05378,0.06161,0.00297,-0.07975,0.042,-0.0423,0.05871,-0.03221,-0.00348,0.05438,0.06952,0.02256,-0.03455,0.00577,0.06252,-0.06479,-0.08402,0.0499,-0.0444,0.02675,0.02975,0.06555,-0.05501,-0.00225,-0.00423,-0.04124,-0.02058,-0.03385,0.01325,0.00287,0.01272,0.00314,0.00892,-0.02658,0.06234,-0.00428,-0.00344,0.03241,-0.01214,0.0221,-0.05867,0.0011,0.02596,0.07205,0.01265,-0.09825,-0.04293,-0.05282,-0.02374,0.03839,-0.02383,-0.04411,0.04991,-0.01369,0.04697,0.03469,0.03683,0.0251,0.08733,0.03069,-0.00833,0.01707,0.02,0.07524,-0.00474,-0.09018,-0.04962,0.04745,0.01611,-0.03705,0.0459,-0.03976,0.05446,-0.04792,-0.02281,0.05905,0.05688,-0.05979,0.05777,0.00318,-0.01948,0.04847,-0.0261,0.00226,0.08319,0.0444,0.01938,-0.0195,0.08463,0.03376,0.09128,0.0032,0.01311,0.02792,0.06383,0.01448,-0.03834,-0.02602,0.08918,-0.04566,-0.02177,0.00462,0.00576,-0.01342,0.00067,-0.0464,0.00934,0.01042,-0.01542,0.07136,-0.01897,0.04506,-0.02222,-0.03709,-0.01392,-0.03553,0.02753,0.01895,-0.05629,0.04852,0.0306,0.09007,0.05327,-0.00478,0.07555,-0.03642,-0.01161,-0.05528,-0.03213,0.003,0.00897,0.13301,-0.00754,0.04687,0.01344,-0.00929,-0.06942,-0.05548,-0.00592,0.04373,-0.07469,0.0622,-0.08928,-0.01681,-0.0305,0.04685,-0.00807,-0.00108,-0.01222,0.03859,0.0022,-0.09189,0.02731,0.00413,0.00138,-0.05919,0.01976,-0.05021,-0.0119,0.02026,-0.02426,-0.03846,-0.04403,-0.06828,-0.01076,-0.03094,-0.0406,-0.03959,0.01551,-0.04081,0.0602,0.03472,-0.01408,-0.01828,0.02472,0.06937,0.01778,-0.04555,-0.02391,-0.06884,0.05879,-0.02623,-0.07453,0.02793,-0.02365,-0.03102,-0.03371,0.05226,0.03131,-0.09447,-0.03213,0.00842,0.02715,0.00928,-0.07333,-0.0378,-0.01167,0.00103,-0.0216,0.09085,0.03541,-0.04153,0.03658,-0.02475,-0.02928,0.00305,0.05886,-0.03894,-0.00817,-0.11676,-0.06085,-0.05258,0.00029,0.04038,0.01719,0.0719,0.07331,0.06135,-0.06222,0.00368,0.08339,-0.04466,0.02333,-0.01897,0.00151,0.00571,0.00352,0.03256,0.04349,-0.08333,0.00995,0.05482,-0.02765,0.03659,0.02767,-0.01089,-0.04604,-0.00572,0.01952,0.0003,-0.02385,0.01402,-0.0043,0.06716,0.03352,-0.01202,0.00791,-0.02501,-0.08971,-0.08287,0.03667,0.02029,0.01392,-0.05115,-0.00042,0.02374,-0.03015,-0.04792,0.04567,-0.02722,0.0275,-0.03477,-0.04537,-0.055,0.05387,-0.02654,-0.01655,0.09862,-0.00988,-0.04013,0.04655,-0.04562,-0.03375,-0.04568,-0.0575,-0.0117,-0.01901,0.01812,0.05141,0.01773,0.02952,0.03039,-0.03493,-0.02142,0.01396,0.05499,-0.04397,0.06601,-0.00483,0.00391,-0.05529,-0.0195,-0.03236,-0.00799,0.07886,-0.00302,-0.04333,-0.00852,-0.10522,-0.0634,-0.04795,-0.04119,0.01707,0.02636,-0.0671,0.0072,-0.04239,0.00755,0.07991,0.09466,-0.05272,0.00321,0.01359,0.00373,0.0157,-0.02362,0.0317,-0.03741,0.01575,-0.13043,-0.03844,0.02538,-0.04431,0.03173,-0.14514,-0.0546,0.0639,-0.06512,-0.00203,0.04377,-0.00674,0.02165,-0.0289,-0.01097,0.00151,-0.02537,0.02753,-0.02218,-0.02063,-0.00439,-0.07731,0.02998,0.0225,0.01192,0.04203,0.01148,-0.02727,0.06168,0.04671,0.10458,-0.01809,-0.10652,0.0668,-0.05624,-0.0475,0.0365,0.01245,-0.04971,0.01897,0.05254,-0.08225,0.01636,0.03612,-0.05203,0.04039,0.07267,-0.00081,-0.04039,-0.02372,-0.00809,0.0519,-0.05926,-0.07357,0.05285,0.01689,0.07044,-0.05796,0.02564,0.01262,-0.01921,-0.00836,0.07374,0.04864,0.0421,0.04879,0.00531,-0.03204,-0.02631,0.02635,0.00497,0.04137,-0.00504,-0.07341,0.07919,-0.01819,0.01764,-0.0261,0.01013,-0.04937,0.00257,0.1168,0.00343,-0.01963,-0.01698,-0.03099,0.01138,-0.03795,0.05052,0.02223,0.02603,0.05122,0.10474,0.05233,0.06919,0.01227,0.09773,-0.00013,-0.01569,0.01788,0.02532,0.00763,0.05405,0.00018,-0.09215,-0.08174,0.01904,0.01121,0.0262,0.01082,-0.01123,-0.09511,-0.0426,0.0139,0.03561,-0.00635,0.05503,-0.06555,-0.03405,-0.00654,-0.00137,-0.01027,0.0295,-0.00023,-0.05601,0.00611,0.02083,0.05818,-0.02027,0.01029,-0.03967,-0.0122,0.00013,0.05046,0.00943,-0.00706,-0.037,-0.03449,-0.00428,0.03704,-0.00622,0.03837,-0.04722,-0.03585,0.05604,0.01336,-0.05772,-0.05795,-0.04696,0.04203,-0.02124,0.09333,-0.05254,0.01694,0.01674,0.06142,0.03725,-0.00713,-0.04,-0.0286,0.00007,0.04096,-0.001],"founder/raise-funding":[0.02444,-0.08886,-0.00541,0.04898,-0.0064,-0.04093,-0.00468,0.05866,-0.02241,-0.03298,-0.02905,0.07711,-0.00583,0.01811,-0.00365,-0.02931,-0.011,0.00869,0.01713,-0.012,0.04752,-0.02513,-0.03093,0.00173,0.08242,-0.05024,0.06004,-0.00759,0.06082,-0.01636,-0.06648,0.02759,0.00742,-0.00376,-0.00963,0.01972,0.00177,-0.00763,0.08165,-0.00484,-0.04583,0.01542,0.00847,0.03632,0.04395,-0.04357,0.00976,-0.05582,-0.02883,0.0423,-0.10334,0.03292,0.03603,0.00003,0.00185,-0.00774,-0.03575,-0.02992,0.00093,-0.01542,0.04561,-0.02986,0.07139,-0.03373,0.03242,0.02645,-0.03268,0.05501,0.0096,-0.04831,-0.10166,0.07643,0.00044,-0.03864,-0.06294,0.00088,0.07511,0.06338,0.05363,0.02088,0.00416,-0.11959,0.04052,-0.01985,0.04747,0.06788,0.01973,0.06384,0.10442,-0.00532,-0.02184,-0.07206,0.02116,0.11537,0.00635,-0.06388,0.07643,-0.08744,-0.02996,-0.00749,0.07164,-0.03441,0.02949,-0.01488,-0.00017,-0.04848,-0.03632,-0.0848,0.07263,-0.00948,-0.0635,0.00701,0.02055,0.02091,0.04984,0.01118,-0.06744,0.02699,-0.00087,-0.02634,0.07361,0.0156,-0.01466,0.08101,-0.04031,-0.04798,0.05244,-0.08449,0.08312,0.05473,-0.01412,-0.05564,-0.00774,0.00596,-0.01475,0.00486,0.01509,0.04793,0.04888,-0.02165,-0.0099,-0.04384,0.03665,-0.04363,-0.08374,-0.00097,-0.04208,0.06271,-0.04946,0.00653,0.03093,-0.14655,0.00329,0.07914,0.00553,0.05913,0.00304,0.01201,-0.03891,-0.01614,0.04527,-0.10291,0.02544,0.04977,0.03798,-0.01779,-0.00611,-0.05748,-0.01632,0.01869,-0.14188,0.10572,-0.09949,0.0522,0.05234,-0.0632,-0.05558,0.00408,-0.00405,0.01968,0.01687,-0.01447,0.0294,-0.01026,-0.0582,0.07292,0.05331,-0.00365,-0.02483,0.03706,0.00137,0.02633,-0.05461,0.0011,-0.08307,-0.04605,0.01293,0.01856,0.00328,0.0298,0.05458,-0.05489,-0.01725,-0.05746,-0.00949,0.05111,-0.00378,-0.01291,0.02237,-0.04462,-0.07887,-0.04848,0.09814,-0.01321,0.01122,0.04681,-0.0022,0.00981,0.04017,-0.02035,-0.01848,0.03999,-0.01754,0.04219,-0.08528,0.02148,-0.02238,0.00226,-0.00091,0.08056,0.03138,0.04957,0.06426,0.03778,0.04069,0.04216,0.01922,0.0227,0.10498,0.0248,0.02698,-0.06527,0.00197,-0.04094,-0.02424,0.04056,0.03643,0.03788,0.01987,0.09555,0.0156,0.04023,0.01694,0.02561,0.00614,-0.03637,0.0217,0.0017,-0.03563,0.03244,-0.04391,0.01811,-0.0038,0.02977,0.01854,0.01704,0.05338,-0.08023,-0.00706,-0.05608,0.00606,-0.01996,-0.03861,-0.01822,-0.01664,0.0443,0.01516,0.06872,0.03101,0.03423,-0.04612,0.03943,-0.02873,-0.00701,0.01451,-0.04696,0.00765,0.01424,-0.02497,0.06171,0.01917,-0.01893,-0.02913,-0.02386,0.07085,-0.00804,-0.00378,-0.01146,0.03827,-0.02491,0.02963,-0.04866,-0.02569,0.0123,-0.09702,0.04012,0.13574,0.06576,0.12805,0.01129,-0.06051,-0.047,0.00071,0.04139,-0.09978,0.02643,-0.0249,-0.01793,0.04593,-0.00119,0.03489,-0.01431,-0.08359,0.00341,0.07292,0.0546,-0.04776,0.00095,0.00419,0.03739,-0.10436,-0.03167,0.06373,-0.01475,-0.04481,0.01974,-0.02499,0.05322,0.04838,0.04715,0.02643,0.04493,0.00039,-0.05886,0.0421,0.04836,-0.06279,-0.00243,0.00666,-0.0374,0.01855,-0.02722,-0.00614,-0.0303,-0.02341,-0.00585,0.06678,0.03302,-0.04154,0.00965,-0.00735,-0.0161,-0.04609,0.07092,-0.01581,-0.00081,0.03304,0.00778,0.0728,0.01774,0.0505,0.03622,0.02272,-0.02742,0.06694,-0.01714,-0.07917,-0.01515,0.02962,-0.0086,-0.02772,-0.02102,-0.01395,0.00079,0.01791,-0.01538,-0.06337,-0.07627,-0.00148,0.038,0.00911,-0.038,-0.07008,0.01104,-0.01255,-0.01837,0.0204,0.0218,-0.03762,0.05777,0.05297,-0.02276,-0.01228,-0.00887,0.03294,0.0539,0.04914,-0.03315,-0.02904,0.03783,0.01498,-0.0253,0.04386,-0.03706,-0.0507,-0.01988,0.01822,-0.02338,-0.02033,-0.04801,0.02854,0.02735,-0.0405,-0.05015,-0.00834,0.00247,-0.00626,-0.04497,0.00632,-0.01312,-0.02392,0.00213,-0.00964,-0.03338,0.03035,-0.00967,-0.00478,0.00165,0.08414,0.07056,-0.00455,0.09896,-0.02038,0.02051,-0.03386,0.01647,0.00592,0.00335,0.0233,-0.01188,-0.00266,0.02763,0.00341,-0.02823,-0.02049,-0.00045,0.00507,-0.03992,0.0218,-0.07457,-0.0204,0.03054,-0.01689,-0.01161,-0.08803,0.00186,-0.03886,0.04948,0.02416,-0.01628,-0.03991,-0.03674,-0.03058,-0.03838,0.00426,-0.07006,0.01306,-0.03457,0.03117,-0.01483,-0.02831,-0.01437,-0.04996,0.00203,0.00979,-0.03216,-0.07847,0.05446,0.08534,0.11791,0.07658,0.02625,-0.05587,0.02042,-0.03238,-0.01451,-0.05767,-0.04638,-0.03843,-0.00452,0.07678,0.03859,0.06036,-0.02992,0.04454,0.05707,-0.06666,-0.04517,-0.04495,0.0129,-0.01359,0.01961],"founder/plan-finances":[0.01583,0.00111,-0.02822,-0.03113,0.02681,0.0205,-0.03563,-0.00491,0.06551,-0.02441,0.02439,-0.02519,-0.00764,-0.02193,-0.02733,0.01975,0.02095,0.01244,0.00895,-0.05757,-0.00496,-0.02752,0.02882,-0.02757,0.02462,-0.01648,0.03557,0.01767,-0.01194,0.0225,-0.02099,0.05402,-0.06106,0.01314,0.02016,0.00199,0.05356,-0.07129,-0.024,-0.0487,-0.06335,0.03989,-0.06031,-0.00318,0.04493,-0.10336,-0.04493,-0.02699,-0.03249,0.02756,-0.10753,-0.0265,0.03591,0.01096,-0.02454,0.02565,0.04801,-0.0266,-0.05978,0.04409,-0.00161,-0.03949,0.01342,-0.00534,0.04019,0.02117,-0.02363,-0.02341,-0.05709,0.00195,0.034,0.03664,-0.01377,-0.13202,-0.0479,-0.01012,-0.01002,0.05244,0.06347,0.03911,-0.00822,-0.0489,0.03511,0.011,-0.07816,0.01071,0.03482,-0.04315,-0.01495,-0.04547,0.00575,-0.04945,0.00418,0.03874,-0.03445,-0.09248,0.00359,-0.03347,-0.02443,0.04934,0.13201,0.03308,0.05701,-0.01766,-0.05864,0.01348,-0.00066,-0.02904,0.0758,0.025,-0.02886,0.01758,-0.01272,0.0252,0.0101,0.01411,0.03493,0.00218,0.05653,0.01047,0.06655,0.02991,-0.05625,0.01423,-0.05007,-0.01398,-0.04696,-0.05826,-0.01107,0.10868,0.04051,0.06769,0.05089,0.09437,-0.12969,0.01124,0.02301,0.00578,0.03589,-0.04779,-0.07758,-0.02249,-0.01665,-0.00215,0.07517,-0.05295,-0.00865,0.01425,0.01792,0.0084,0.01254,0.09503,0.11741,-0.00196,-0.02069,0.00332,-0.02436,0.01219,-0.05601,-0.01604,-0.02203,-0.04465,0.00044,0.00279,-0.01612,0.04543,-0.06244,0.0377,0.02515,0.03486,-0.04626,-0.0034,-0.02938,-0.03573,0.03238,-0.03807,-0.02977,-0.00155,0.02736,0.03624,0.06236,-0.01673,0.02703,-0.03506,0.0214,0.00763,-0.01997,0.05523,0.04801,0.07238,-0.00987,-0.01677,0.00094,0.00157,0.00508,-0.04319,0.00045,0.05055,0.01671,0.01723,0.01069,-0.02084,0.00603,-0.05077,-0.02608,0.01361,0.00277,-0.01225,-0.01119,0.00588,0.04891,-0.04823,-0.05502,0.10913,0.03639,0.03543,0.03699,-0.03551,0.09064,0.01135,-0.00413,-0.01824,0.07442,0.0756,0.01544,0.01331,-0.10277,0.01575,-0.04412,-0.01666,0.00962,0.06393,0.02476,0.00097,0.03477,-0.00972,0.12018,-0.02282,0.038,-0.09237,0.02528,-0.00668,-0.00235,-0.00794,-0.02331,-0.02176,0.04234,-0.00645,-0.01218,-0.01661,-0.03377,0.07296,0.00569,0.03596,0.09103,-0.01993,0.02147,0.04551,0.04453,0.01409,-0.11767,0.06686,-0.03685,-0.04606,-0.01683,-0.07525,0.01852,0.00558,-0.00915,0.04071,0.00136,-0.08046,-0.04076,-0.08149,-0.07233,0.02573,0.02917,0.00253,-0.05631,0.01486,-0.04804,0.02742,-0.03301,0.02205,0.02909,0.04208,-0.02901,-0.02138,0.02442,0.00255,-0.03133,0.00632,0.11086,-0.08332,0.04897,0.00144,-0.04296,-0.03097,0.01792,-0.01234,0.03922,0.01476,0.05823,0.02721,-0.02525,0.03044,0.05573,-0.09227,0.11145,-0.05686,0.00554,-0.04554,-0.06213,-0.01357,0.04028,0.04461,-0.00034,0.03068,0.0261,0.02647,-0.03863,-0.01305,-0.04373,-0.00484,0.0382,0.00255,-0.06466,0.09766,-0.0565,-0.01098,-0.05278,-0.03006,0.01071,0.03166,-0.05489,0.05021,0.02432,0.03834,0.01046,0.00482,0.02811,-0.04759,-0.03496,-0.03878,0.05105,0.02946,-0.01171,-0.00994,0.0684,-0.04661,-0.02308,-0.05428,0.00579,-0.08701,-0.07128,-0.02995,-0.01021,-0.02241,0.08986,0.04934,-0.01901,0.06774,0.04744,0.03738,-0.00776,0.01843,0.02375,-0.03864,0.07383,-0.01719,0.08161,-0.04928,0.06124,-0.02732,0.00638,0.06021,-0.02117,0.02341,0.00473,0.01645,0.01271,0.07547,0.01812,0.06834,0.04413,-0.00536,-0.02407,-0.00458,-0.0643,0.03325,-0.05713,-0.01424,0.0286,0.0052,0.06179,0.03801,-0.06013,0.09403,0.02481,0.03128,-0.01087,-0.01547,0.05882,-0.03774,-0.08183,0.03595,-0.01037,-0.13674,-0.04325,0.01874,0.01154,-0.02527,0.00829,0.01581,-0.01732,-0.02015,0.0113,-0.08198,-0.04241,-0.05054,0.04553,0.05947,-0.02207,0.02621,0.00229,0.02595,-0.02808,-0.0197,-0.02762,-0.05792,0.06493,0.00338,-0.01584,-0.04929,-0.09669,0.02497,0.06186,0.02286,0.05494,0.06347,0.03299,0.06196,-0.04013,-0.06251,0.02915,0.10741,-0.01298,0.03936,0.03269,-0.00207,0.00555,0.06506,0.00491,-0.03011,-0.04254,0.0291,-0.0035,-0.01455,-0.00759,-0.11801,0.02695,-0.0227,0.00399,-0.01383,0.00023,0.05801,-0.00521,0.00221,0.06948,-0.01776,-0.01745,0.05115,-0.06864,0.02968,0.06126,0.09057,0.02587,-0.04298,-0.01464,0.0583,-0.0926,0.02819,-0.00557,-0.01801,0.07481,-0.01856,0.06602,0.00835,0.05801,0.04959,0.04892,0.06624,0.03654,0.06091,0.00859,-0.00161,0.00978,-0.02599,-0.0138,-0.00253,-0.0134,-0.06821,0.03973,-0.0514,0.06617,0.01422,0.03499,-0.03852,-0.00759,0.01375,-0.02352,-0.02919],"founder/sell-customers":[0.03228,-0.00983,-0.01086,-0.00908,0.00136,-0.02841,-0.04635,0.02359,0.00436,-0.05092,0.01655,-0.01979,-0.04983,0.01457,-0.06509,-0.07396,0.03364,0.04744,-0.07965,-0.0109,-0.06186,-0.02352,-0.02475,-0.00452,-0.00133,0.09701,0.0161,0.04394,0.0328,-0.02118,-0.06428,-0.00051,-0.04515,0.01026,0.04307,0.0371,0.00374,0.06271,0.07771,-0.05666,0.02938,0.01393,-0.02694,-0.06218,-0.04826,0.0139,0.02956,0.02679,0.0878,0.02859,0.08397,0.06845,-0.04493,0.00087,-0.01838,0.02992,0.00042,0.00734,-0.0348,0.03212,-0.05572,-0.01978,0.01265,0.04378,0.00627,0.00112,-0.02135,0.01809,-0.07051,-0.06358,-0.01757,-0.01505,-0.06981,-0.01215,0.00131,-0.03117,-0.00599,-0.10011,-0.00823,0.09293,-0.00437,-0.03899,0.08068,-0.07763,0.00259,-0.03341,-0.00333,-0.01517,0.01412,0.02961,0.02135,-0.06033,0.0428,0.04952,0.04084,-0.05325,-0.01818,0.038,0.02225,-0.01948,0.06026,-0.07316,0.01894,-0.04433,0.06693,-0.07926,0.03408,-0.03939,-0.0409,0.09625,0.03737,-0.00938,0.07067,0.02206,-0.00112,0.01994,-0.01409,-0.07603,0.04914,-0.07575,0.0589,0.01651,0.01925,-0.02178,-0.0401,0.02005,-0.00701,-0.06039,-0.00996,0.029,0.05317,0.04081,-0.06139,-0.04316,-0.03062,-0.00842,-0.01238,0.06695,0.04393,-0.00789,-0.05394,-0.08624,0.04823,0.11865,-0.00345,-0.10955,-0.03162,0.0444,-0.00754,-0.03187,0.00835,0.00252,0.00782,-0.04532,-0.02099,0.05303,0.02867,0.03623,0.04434,0.05495,-0.0563,-0.04116,0.00423,0.01574,-0.05136,-0.02059,0.06717,0.03332,0.00359,-0.09312,-0.07201,0.01568,-0.02827,-0.02439,-0.04535,-0.0685,-0.02992,0.06787,0.00782,-0.01569,-0.06336,-0.01277,-0.01429,0.01317,0.00603,-0.02728,-0.04977,0.0016,0.05884,-0.019,0.08273,-0.03207,-0.04523,-0.04035,-0.01569,-0.03535,0.04068,0.00898,-0.03024,-0.01242,0.03915,0.02769,-0.03859,-0.05111,-0.08502,0.08389,-0.04636,0.02823,0.00007,0.01818,0.03208,-0.03247,-0.00532,0.01506,0.0223,-0.06959,0.01563,-0.06804,0.0008,0.00324,0.01869,0.02095,0.00753,0.03927,0.02985,0.0101,0.01615,0.01936,0.04012,0.00812,0.06006,-0.04881,-0.00507,0.01849,-0.0215,0.0096,-0.08852,-0.03281,0.02005,0.01507,0.04543,0.00734,0.04126,-0.03824,0.0044,0.00349,-0.03807,-0.05058,-0.00075,-0.02501,-0.00869,0.006,0.00961,-0.01887,0.07137,-0.01168,0.0664,0.00067,-0.00984,0.01718,-0.188,-0.05477,0.03339,-0.02818,0.02619,-0.03658,0.07441,-0.05323,0.00863,-0.08142,0.00929,-0.02891,0.04079,-0.04496,0.04075,-0.00155,0.07223,0.08164,-0.06623,-0.04469,0.05224,0.04149,-0.08165,-0.044,0.01542,0.01669,-0.01934,0.00786,-0.02942,-0.01174,-0.00284,0.00438,-0.03748,-0.01863,0.05219,-0.00329,0.00614,0.01725,0.01495,-0.01262,-0.07539,-0.06469,-0.00454,-0.00449,-0.06823,-0.02916,-0.01728,0.03776,-0.00296,-0.10285,0.00989,-0.0057,-0.00998,-0.01583,0.06338,-0.00856,-0.009,0.07357,-0.01248,-0.03951,0.07818,-0.01998,0.09013,-0.02821,0.05334,0.03061,0.04768,0.03795,-0.03584,-0.04253,-0.02166,-0.0019,-0.00387,-0.01889,-0.07535,0.00122,0.08579,-0.07462,0.00929,0.08355,-0.02329,-0.0247,-0.04511,0.06611,0.01819,0.06032,-0.02555,-0.11326,0.00664,0.07652,-0.00435,-0.0093,-0.05988,0.01399,0.02523,-0.08873,0.00355,-0.01992,-0.05447,-0.03231,-0.00983,0.02953,0.14544,-0.02423,0.04958,0.05667,0.0126,-0.03555,0.00102,0.00169,-0.01034,-0.0606,0.03211,-0.02527,0.0176,-0.0382,-0.08274,0.04049,-0.00052,0.03833,-0.00668,0.0697,-0.0005,-0.05095,0.00669,0.01343,0.03706,0.03492,-0.06213,-0.03439,-0.02855,-0.01485,0.01466,0.03108,-0.12078,0.01492,-0.03694,-0.09031,-0.01301,0.01092,-0.00722,-0.00876,0.0084,0.03375,-0.00952,0.05112,-0.00807,-0.0506,-0.02998,-0.03085,-0.04404,-0.00376,0.05044,-0.02284,0.05713,-0.01765,-0.07317,-0.04317,-0.02542,-0.05157,0.04572,0.00033,-0.02452,0.01234,0.00386,0.0622,0.01124,0.00057,-0.08041,0.04297,-0.09662,0.02309,-0.00032,0.00568,-0.00162,0.02242,0.06429,0.03709,0.08384,0.06987,0.00957,0.04098,-0.01755,0.04986,-0.00679,0.05646,-0.0096,0.02924,-0.04915,-0.0067,0.00602,0.00796,0.00608,0.03809,-0.03689,-0.00105,-0.03413,0.01621,-0.01779,0.04971,0.03615,-0.02759,-0.07251,0.10948,0.07059,-0.00466,0.02539,0.01914,0.00187,-0.01943,0.03865,-0.04211,-0.08277,0.03229,0.0071,0.00535,-0.02104,-0.03443,0.03371,0.006,-0.06985,0.06797,0.03565,0.06158,-0.01046,0.04659,0.07563,-0.02469,-0.00407,-0.05614,-0.04362,0.04336,0.02586,-0.0183,0.00977,-0.04115,-0.02009,0.01456,-0.09195,0.01617,0.06692,0.02944,0.02001,-0.01222,-0.03847,-0.04285,0.08179,-0.0663,-0.03357,0.02813,0.07377,0.02442],"founder/hire-team":[0.01756,-0.10583,0.02368,0.01259,-0.00564,-0.00381,-0.06357,0.02357,0.01214,-0.06575,0.08133,0.01231,-0.02069,0.04772,-0.03026,-0.02935,-0.04674,0.06914,-0.03809,0.00622,-0.00065,-0.03869,-0.02295,-0.02089,0.02949,0.02761,0.00525,0.02956,0.00805,-0.0443,-0.03709,-0.00539,0.01235,-0.01202,-0.00798,-0.00509,0.0619,-0.04501,0.04285,-0.02533,-0.01755,-0.01019,-0.06684,-0.00053,-0.00564,-0.05252,-0.05128,-0.00761,0.09672,0.01053,-0.02979,0.04692,-0.01878,0.02452,-0.02619,-0.04065,-0.01053,-0.02479,-0.05863,0.03424,0.03157,-0.0246,0.04836,-0.01028,-0.04444,0.06764,-0.0265,-0.03892,0.00352,-0.00363,-0.02506,0.00047,0.00156,-0.03188,-0.01212,-0.05921,0.01438,0.04258,0.01413,0.11861,-0.00198,-0.09728,0.06401,0.06546,-0.0214,-0.0439,0.03061,-0.05228,-0.00315,-0.09902,-0.01323,-0.04142,0.05368,0.09587,0.02414,-0.02531,-0.04426,0.02602,-0.00021,0.04831,0.03005,-0.00039,0.02879,-0.04077,-0.01288,-0.05817,-0.02901,0.01802,-0.00289,0.04466,-0.01098,-0.02167,0.03505,0.0516,-0.03791,-0.07043,-0.03478,-0.00199,0.04907,-0.05353,0.04621,0.06105,-0.01451,-0.02657,0.01472,-0.04016,-0.01123,-0.08216,0.0545,0.04369,-0.03078,-0.03759,-0.06778,0.0711,-0.09959,-0.02727,-0.06301,0.07005,0.05496,-0.01451,-0.0357,0.03269,0.02502,0.07316,0.02562,0.01685,0.01071,-0.01021,-0.03586,-0.06759,0.03817,-0.02037,-0.02577,0.04647,-0.04833,0.11437,0.02778,0.06221,0.0687,0.01749,-0.02747,-0.09424,0.0103,-0.01332,-0.08706,-0.02922,0.01892,0.05521,0.00964,-0.04835,-0.08692,0.08867,-0.07815,0.04877,-0.01995,-0.05038,-0.0243,0.00855,-0.08251,-0.01398,-0.03081,-0.02282,0.03234,-0.01004,-0.0303,-0.00929,0.02804,0.04734,-0.03927,0.05512,-0.00991,0.03127,-0.00675,-0.07665,-0.05897,-0.01746,0.09245,-0.02168,0.00186,-0.02633,-0.01944,-0.04864,0.00502,-0.04976,0.02339,0.02303,-0.05905,-0.05091,-0.01367,0.00224,0.0508,0.01473,0.04717,0.05791,-0.00762,-0.01166,0.04762,-0.01622,-0.12349,0.01897,-0.06176,-0.01909,-0.07191,0.10432,0.02908,0.08099,0.03571,0.02076,0.01738,0.08759,0.05299,0.00237,-0.02964,-0.04383,-0.03658,-0.05044,0.00119,-0.05435,0.03355,0.01142,0.03595,-0.03179,-0.04545,0.05103,0.05646,0.03181,-0.02106,-0.01055,0.01742,-0.0042,0.00328,0.00068,0.06248,-0.04473,-0.01868,0.01115,0.04028,-0.02555,-0.01901,-0.00798,-0.01078,0.03885,-0.03361,0.0318,0.08255,0.01633,-0.03761,0.01811,0.02788,0.03068,0.05236,-0.07273,-0.00315,-0.01522,0.02224,-0.02473,0.02798,-0.02268,-0.05709,0.00266,-0.02038,0.08142,-0.00442,-0.0009,0.01411,-0.03542,0.07544,0.02329,0.03064,0.02543,0.0141,-0.05027,0.05282,0.03853,0.01639,-0.03203,-0.00944,-0.01211,0.07167,-0.02533,-0.03785,-0.09414,-0.01572,-0.01132,-0.0301,0.03735,0.0733,0.07547,-0.07586,0.05127,-0.05285,-0.06103,0.04396,0.01965,-0.04047,-0.00548,0.03764,0.02236,-0.01677,-0.01588,-0.02139,-0.03557,0.11034,-0.00423,0.03619,0.08068,-0.02559,-0.01034,-0.07607,-0.03084,-0.03553,-0.00129,0.04215,-0.02927,-0.06742,0.05395,-0.03515,-0.04964,0.0345,0.07871,-0.00708,0.02732,-0.0497,-0.00711,0.04965,0.02874,0.013,-0.02833,-0.00332,-0.02398,-0.0234,-0.01601,-0.08709,0.04376,0.02244,-0.0368,0.03544,0.01286,-0.0833,0.01536,-0.05272,0.00888,-0.00388,-0.01962,-0.01964,-0.00046,-0.00687,0.0366,-0.0113,-0.05775,0.01539,-0.05786,0.00309,-0.02079,0.03135,-0.03285,-0.04437,0.04209,0.01575,0.05802,0.0317,0.09297,0.07092,-0.02617,-0.01484,0.02911,0.05878,0.03489,-0.04303,0.00964,-0.0152,0.02156,-0.02681,-0.01862,0.01406,0.02687,0.00379,-0.0471,0.03679,0.00354,0.01996,-0.02407,-0.04298,0.06755,-0.00001,0.04138,-0.03376,0.01609,-0.10021,0.04179,-0.02688,0.03395,0.07284,-0.00945,-0.05369,0.00402,0.06564,-0.0146,0.00215,-0.03152,-0.01552,-0.01937,-0.03993,-0.00174,-0.00294,-0.04907,0.00256,-0.03095,-0.03563,-0.07596,-0.1041,-0.00459,-0.00371,-0.00271,0.10458,-0.04059,0.05698,0.03957,0.06013,0.04704,0.03631,0.07103,0.03885,0.0666,-0.01878,0.10192,-0.00565,0.0066,-0.02328,-0.0871,0.01749,0.04459,0.0202,0.02301,-0.02648,0.01491,-0.0176,-0.00216,-0.0591,-0.05368,0.14357,0.01209,0.00226,0.02359,0.04726,0.00443,0.01,0.01522,0.00533,-0.01482,0.01413,0.01104,-0.07993,0.00076,-0.02364,0.00956,-0.04696,0.01096,0.05175,-0.00291,-0.04801,0.1292,0.03562,0.14638,0.03786,-0.01366,0.10591,0.00535,0.03246,0.05049,0.0179,-0.03683,0.02598,-0.02315,0.01596,0.01661,-0.07264,-0.00065,-0.10564,-0.00496,0.0964,0.01904,0.00247,-0.02037,0.01494,0.02027,-0.01445,-0.0565,-0.02477,0.00455,-0.00588,0.0069],"founder/update-investors":[-0.00272,-0.03067,0.03862,0.04921,0.00074,-0.05915,-0.03717,-0.03502,0.02217,-0.01399,-0.06606,0.01675,0.01564,0.0155,0.01918,-0.01495,0.06566,0.02189,-0.06587,-0.02461,-0.04922,0.01965,0.03225,0.00943,0.02881,-0.1261,0.02114,-0.00438,0.02597,0.01724,0.00171,0.00756,0.00077,-0.03626,0.07831,-0.03904,-0.05899,0.00005,0.06882,0.06644,0.03157,0.02316,-0.03317,0.04066,0.04707,-0.03644,0.04124,-0.02951,0.04752,-0.0076,-0.10294,0.0862,0.02464,0.06634,0.04639,0.00015,0.03042,-0.04288,0.06811,-0.03797,0.05284,-0.04141,0.01353,0.04915,0.00117,0.01538,-0.04037,-0.00391,-0.03454,-0.03337,-0.00329,-0.00245,-0.00872,-0.01054,-0.0276,-0.02048,0.01395,0.01162,0.01095,0.01453,0.02841,-0.05054,0.05985,-0.04725,-0.02046,0.04778,-0.05848,0.01632,0.05713,0.04233,-0.03916,-0.06457,-0.01797,0.01821,-0.01048,-0.03327,0.02653,0.00087,-0.02578,-0.02257,0.08322,0.02311,0.01153,-0.0063,0.03415,-0.0604,0.01178,-0.07132,0.04677,0.07294,-0.02918,-0.0136,0.02878,0.03778,-0.03203,0.03419,-0.00622,-0.00328,0.02752,-0.04556,0.00981,-0.01418,-0.10781,-0.07135,0.0328,-0.03591,0.01598,-0.06971,0.02196,0.04806,-0.01406,-0.00344,0.03193,0.00669,-0.05074,-0.03762,0.03681,0.02635,-0.01744,-0.01731,-0.00225,0.06041,0.0312,0.00466,-0.03993,-0.03208,-0.02825,0.03503,-0.00129,0.02194,0.06251,-0.04848,-0.02881,0.01372,0.11631,0.00215,0.04121,-0.00056,-0.06427,-0.00117,0.00172,0.07295,-0.00784,0.05484,-0.0032,0.01349,-0.04818,0.02787,-0.0379,-0.04486,-0.05743,0.04764,-0.08013,0.06084,0.0258,0.03546,-0.01521,0.0116,-0.02452,0.02362,0.05886,0.04739,-0.0286,-0.0748,0.02577,0.06784,0.00305,-0.00785,-0.06206,-0.04729,-0.00848,-0.05658,-0.01493,-0.07009,-0.02637,-0.00515,-0.00117,0.01513,0.0442,0.00086,-0.00502,-0.0034,0.05787,-0.0692,-0.0329,0.04951,-0.00588,-0.01579,-0.03864,-0.03219,-0.03586,-0.06684,0.04095,0.0116,-0.01935,0.00491,0.00624,-0.00717,-0.03147,-0.04191,0.00727,0.08406,0.07846,0.02021,-0.06015,-0.00972,-0.13735,0.02686,-0.00021,0.04304,0.04556,0.01602,0.0118,-0.1355,-0.02509,-0.0484,-0.03743,-0.04693,0.07059,-0.0301,0.01635,-0.01766,-0.06186,-0.05474,-0.0038,0.01558,0.03131,-0.01296,-0.00304,0.00647,0.03658,-0.00236,-0.02701,0.0569,0.04264,-0.02594,0.03155,0.04603,0.04808,0.08208,-0.00615,0.04687,0.06128,-0.04267,0.0564,-0.07614,0.08026,0.01082,0.03233,-0.03667,0.00624,-0.06858,-0.03707,-0.01754,-0.06144,0.05344,-0.00427,0.03297,-0.04352,-0.0106,-0.00457,0.04495,0.01137,0.05428,0.04928,-0.03024,-0.01167,0.01139,0.01459,0.00651,-0.01365,-0.03329,0.14307,-0.09679,0.03586,0.0332,0.01863,-0.00948,0.01815,-0.04344,0.03241,0.04852,-0.04293,-0.00511,-0.07929,0.04679,-0.02487,-0.01537,0.07276,-0.03126,0.00764,-0.01899,-0.06712,0.00612,-0.06885,0.04756,-0.00764,0.00455,-0.02509,0.03164,-0.01553,0.02666,-0.03266,0.05981,0.05756,0.04264,-0.04077,0.02198,-0.02338,-0.04663,-0.00811,0.00209,0.02939,0.01594,-0.01702,0.00098,-0.0372,-0.02532,0.01681,0.01469,-0.001,-0.05873,0.01177,-0.08367,0.01683,-0.0622,-0.01121,-0.01353,0.07492,-0.00654,0.04254,0.00222,-0.02058,-0.04409,0.01511,-0.10563,0.03123,0.04219,0.01743,-0.05968,0.01222,0.05908,-0.00194,-0.05669,0.03396,0.00051,0.03212,0.04808,0.01102,0.07716,-0.08861,0.02099,0.0242,-0.04679,0.02407,-0.01428,-0.08048,0.04246,0.00295,-0.01916,-0.10647,0.00566,0.07201,0.06571,-0.02475,-0.01661,-0.0003,-0.02541,0.09651,-0.00154,-0.03003,0.05481,-0.06873,-0.05694,-0.00271,0.05004,0.04412,-0.03984,-0.03957,0.05082,-0.03404,-0.09847,-0.06169,0.00206,-0.06528,0.10314,-0.03717,-0.03607,0.02267,0.04339,-0.05258,0.02124,0.01166,-0.02639,-0.06186,-0.04315,0.04705,-0.07346,-0.06006,-0.03947,0.03168,0.05324,-0.03846,-0.01744,-0.07005,0.07833,-0.04553,-0.00776,0.06288,0.05427,0.04615,-0.03795,0.00988,0.03177,0.04726,0.04094,0.05417,0.0433,0.03407,0.01369,-0.06217,0.07937,-0.02927,-0.02738,0.04858,0.07976,0.05453,0.0615,-0.0405,-0.03649,-0.07331,0.06005,-0.0172,0.0044,-0.07465,0.03205,0.0062,-0.04462,0.06646,-0.04118,-0.00357,0.0425,-0.06045,-0.03092,0.02902,-0.02209,-0.0166,0.02407,0.07444,-0.05987,-0.01329,-0.05574,0.01611,0.00244,0.10151,-0.05569,0.01325,-0.04088,0.05865,0.03705,-0.04195,-0.0066,0.01958,-0.02073,0.01067,0.01998,0.00532,0.06925,0.0601,0.00166,0.10531,-0.04847,-0.00987,0.00178,-0.07158,0.01971,-0.1114,-0.06974,0.02036,-0.02284,0.01256,0.02332,0.02226,-0.01511,0.08567,0.06305,-0.01842,-0.03676,0.00653,0.07182,-0.01467,0.02579],"hr/answer-policy-questions":[0.01622,0.05437,-0.01233,-0.00934,-0.00716,-0.06551,-0.02632,0.0348,0.00221,-0.04197,-0.00837,-0.04835,0.03444,-0.00226,0.02192,0.0257,0.02005,-0.02724,-0.04773,0.06203,-0.02639,0.11914,0.01121,-0.0115,0.02598,0.03688,0.01592,0.03708,-0.02716,0.06971,-0.01059,0.0493,0.02178,-0.02349,-0.02278,0.01961,-0.01361,-0.06021,-0.02511,0.00112,0.04829,-0.02149,0.02323,0.04089,0.07266,-0.02895,-0.04035,-0.00401,-0.02803,-0.00161,-0.01753,0.0072,-0.01107,-0.02538,-0.02862,-0.01234,0.01072,-0.00674,-0.01304,0.00005,0.04271,-0.05226,-0.05337,0.05265,0.00087,-0.01967,-0.00247,0.02705,-0.04293,0.03464,0.044,-0.00058,0.07756,-0.03273,-0.03001,-0.03557,0.0262,0.02637,0.01043,0.00886,0.02807,-0.14219,0.08437,0.00432,-0.05993,-0.03675,0.06618,0.0361,0.0548,0.02381,-0.05134,0.04783,-0.00581,0.02277,-0.04043,-0.07434,0.05693,0.06451,-0.06635,0.00367,0.03,-0.03035,-0.01574,0.01637,-0.03876,0.04165,0.00753,0.00857,-0.02899,0.05961,-0.03977,0.02871,0.05771,0.00675,0.08487,-0.06404,-0.00954,-0.00632,0.05369,-0.0459,0.03806,0.0832,-0.06341,0.07001,-0.01215,-0.09332,0.05814,-0.06563,0.0287,0.02127,0.00373,-0.0221,0.0557,0.0174,-0.12909,-0.05684,0.05929,0.02484,-0.09474,0.05591,-0.05341,-0.01736,-0.00369,0.04319,-0.01382,-0.04709,0.04489,-0.01339,-0.0208,-0.00301,-0.01502,-0.09883,0.06397,-0.00221,0.00619,0.05549,0.02363,0.00134,0.01564,-0.01179,-0.06347,-0.07905,-0.00719,-0.03408,-0.02233,-0.04536,0.01534,0.00694,0.01467,-0.08061,-0.00833,0.10227,-0.06289,0.0509,-0.03717,-0.01152,-0.09026,-0.00499,-0.03835,0.02002,0.03054,-0.00127,0.00097,-0.00599,0.01559,-0.11785,0.0154,-0.04432,0.05569,0.05288,0.05965,-0.0817,-0.07079,-0.03108,-0.04023,-0.01582,0.04671,-0.03667,-0.03832,-0.07556,0.01766,-0.01341,0.07517,0.02825,-0.01423,-0.03157,0.00997,0.00607,0.00928,-0.04772,0.05075,0.00181,-0.05713,0.00872,-0.00594,-0.00705,0.03087,0.05527,0.01923,0.01825,0.03609,0.00962,0.04329,-0.00014,-0.04328,-0.0134,0.02449,0.02085,0.03874,0.02948,0.03289,0.00427,-0.09837,-0.06064,-0.05709,-0.04255,0.01913,-0.01958,0.00388,0.00228,0.03139,-0.04402,0.04345,0.01358,0.02403,0.04628,-0.0911,0.04748,-0.05398,0.00003,0.02953,0.10185,-0.01049,0.02697,0.02387,0.00689,-0.00615,0.03246,0.05364,-0.0022,-0.04787,0.06566,0.0335,0.09194,0.01485,-0.02342,-0.06948,0.01929,-0.05189,-0.0078,0.02368,0.00935,-0.02583,0.05308,-0.00374,-0.00567,-0.04232,-0.05618,-0.05949,-0.03503,-0.0175,-0.03592,0.01111,-0.04159,0.00569,-0.01847,-0.02215,-0.00706,0.02512,0.04907,0.00817,0.06702,0.15648,-0.01299,0.04038,-0.05254,-0.00936,0.07203,0.0011,0.01892,-0.03097,0.0023,0.08497,-0.05289,0.0384,0.01323,-0.02129,-0.06428,-0.00099,-0.04877,-0.02406,-0.00895,-0.00858,-0.02755,-0.05902,-0.01788,-0.03765,0.00156,-0.11416,-0.01215,-0.02949,0.01973,-0.0088,0.03435,-0.0007,-0.03936,-0.00158,0.03517,-0.05683,0.06514,-0.01741,-0.02509,0.05955,-0.04345,0.01861,-0.033,-0.07037,-0.09653,0.03262,0.14001,-0.02078,-0.02854,0.01571,0.04338,0.0009,0.03987,0.04178,0.01582,-0.01997,-0.03381,-0.00712,0.04131,0.03814,0.06551,-0.01461,-0.00531,0.02622,0.0061,-0.04361,-0.03997,0.00839,-0.0657,-0.0347,0.05183,0.01522,-0.00796,0.0441,0.03441,0.06167,-0.06697,-0.00903,-0.09388,0.04714,0.07413,0.00171,-0.07545,0.01013,-0.03758,0.03049,-0.00844,-0.00319,0.0163,0.06028,-0.04183,-0.08333,0.08775,0.0342,-0.05109,0.10949,-0.0128,-0.04149,0.05603,-0.01735,-0.07498,0.0138,0.02423,-0.01004,0.00145,0.00972,0.00912,-0.05027,-0.02285,-0.02457,0.01284,-0.02499,0.0069,0.01622,-0.04282,0.00209,-0.01974,0.00389,-0.03781,0.03365,-0.0446,0.06676,-0.05751,-0.00168,-0.01535,0.0044,-0.03262,0.04785,0.02429,-0.026,0.00226,-0.01285,0.00424,-0.03332,-0.02919,-0.07166,0.01885,0.05563,0.04181,-0.03151,-0.01259,0.02647,-0.0612,0.00079,0.13142,0.10155,-0.00667,0.05864,0.07815,0.02055,-0.05982,-0.05646,0.07714,-0.0772,0.03899,0.00887,0.06031,0.01947,0.11166,0.0284,-0.09243,-0.02452,-0.05566,0.0081,0.03371,-0.00626,-0.00188,0.0717,-0.00897,-0.00445,0.0642,-0.00886,0.04556,0.00498,-0.0115,-0.06198,-0.05898,0.07502,0.07622,-0.00874,0.0422,-0.00452,0.02348,0.01017,-0.03802,-0.08305,-0.0345,-0.02478,-0.01067,0.03276,-0.04371,0.01241,-0.02816,0.0841,-0.04759,-0.01147,0.01463,0.01267,0.01105,-0.02112,-0.00872,-0.01935,-0.03359,-0.02554,-0.04936,0.07206,0.01175,0.03798,0.03113,0.00851,0.03106,0.03357,0.0155,0.03104,-0.01316,0.00886,0.08966,0.02994,0.02218],"hr/prepare-employment-documents":[0.03502,0.008,-0.01147,0.01545,0.01509,-0.04196,-0.09163,-0.00377,-0.04459,-0.02986,-0.00547,0.01044,0.0163,-0.07177,0.00444,-0.06914,0.03492,-0.0076,-0.0122,0.00302,-0.05259,0.01997,0.01927,0.02313,0.03488,0.10093,0.02346,-0.00323,0.01274,0.0009,-0.04034,0.01309,-0.0379,-0.04487,0.04961,0.00443,-0.05084,-0.02807,0.03787,0.02706,-0.0107,0.01256,0.04631,0.03557,0.03411,0.00686,0.03207,0.00236,0.06673,0.03742,-0.03217,0.0435,0.03385,-0.00486,0.00886,-0.04578,-0.01764,-0.04752,-0.02836,-0.0144,0.04266,0.00691,-0.00383,0.00553,0.03088,0.00437,0.0005,0.08884,0.00673,-0.02496,0.00326,0.02033,0.03107,0.11068,-0.08786,-0.02406,0.04635,-0.05137,0.01403,0.02295,-0.03619,-0.09814,0.0182,-0.02645,0.01298,-0.02524,-0.06311,0.08165,0.01435,0.01745,0.0129,-0.07005,0.03427,0.03291,0.01948,-0.04571,0.02946,-0.01509,-0.05939,-0.0247,0.04199,-0.00317,0.0237,-0.04612,0.00475,0.00183,0.00805,-0.08388,-0.01119,0.05061,-0.03445,-0.0023,0.02321,0.05319,0.04037,-0.01861,0.0125,-0.04723,0.06723,-0.05439,0.03106,0.07348,0.02544,-0.03234,-0.01828,-0.04101,0.03796,-0.01936,-0.00648,0.01281,-0.00471,0.07033,-0.00917,-0.08538,-0.10125,-0.02383,0.01675,0.00774,-0.03941,0.00631,-0.00559,-0.0063,0.01645,0.09039,0.00985,-0.01509,-0.01869,-0.03836,-0.04431,-0.00293,0.03438,-0.08163,0.05028,-0.0025,0.0474,0.0746,-0.01583,0.01329,0.07494,0.03283,-0.05376,-0.10024,0.02503,0.04227,-0.04433,-0.06899,-0.02343,-0.02527,-0.02362,-0.10772,-0.08118,0.07724,-0.10492,0.03171,-0.06143,0.02469,-0.04208,0.01177,-0.01326,0.0209,0.04022,-0.06292,-0.04941,0.01016,-0.03263,-0.01754,-0.03879,0.02971,-0.00453,0.01654,-0.0039,0.02947,-0.05454,-0.06122,-0.04933,-0.02251,-0.01788,-0.00111,-0.02449,0.03012,-0.00373,-0.03554,-0.01727,-0.05693,-0.08825,0.02019,-0.02528,-0.0391,0.01263,-0.04718,0.01563,0.03814,0.0014,-0.01094,-0.00002,-0.02443,0.05331,-0.0062,-0.02251,0.04429,-0.04851,-0.02484,-0.04888,0.03654,0.01372,-0.05287,-0.07336,0.04594,0.09739,0.02659,0.01675,0.01963,-0.06653,-0.04661,-0.04153,-0.00648,0.00335,-0.02069,0.06339,0.01063,0.04853,-0.08564,-0.0255,0.0344,0.01624,0.02644,0.03965,-0.03379,-0.02947,-0.04867,-0.03025,0.01391,-0.00939,0.02543,0.0232,-0.04458,0.06189,-0.02467,0.02107,-0.0034,-0.09849,0.0354,-0.00865,-0.00141,0.00167,-0.11913,-0.09326,0.01378,0.03263,-0.04942,-0.03949,-0.07889,0.04358,-0.02937,-0.04191,-0.0579,-0.012,-0.01336,-0.09138,-0.04924,-0.04236,0.03213,0.02663,0.04586,0.0211,-0.03352,-0.02073,0.04015,0.04567,-0.04016,-0.04213,-0.02155,0.04801,-0.02547,0.02822,-0.02527,-0.02332,-0.00609,-0.03192,-0.02389,0.05065,-0.07398,0.00219,-0.01118,-0.04813,-0.05536,0.01088,0.05887,0.03234,-0.04566,0.01635,-0.00994,-0.10518,-0.03338,0.0346,-0.01565,0.00786,0.02025,-0.04117,-0.00278,-0.016,-0.01661,0.01797,0.01247,0.0923,0.03031,-0.07293,0.05177,-0.0391,-0.03206,-0.01095,-0.03671,0.02285,0.03958,-0.01831,0.01825,-0.10147,-0.08169,0.056,0.0225,-0.06091,-0.03825,0.02353,-0.06399,0.10766,0.07856,-0.04523,-0.06216,0.02851,-0.04282,-0.03387,0.02073,0.00549,0.07075,-0.04852,-0.00987,-0.01474,0.01008,-0.04071,-0.03654,0.00237,0.00913,0.02222,0.03298,0.04571,0.01862,0.06588,0.01421,-0.06321,-0.06134,-0.01358,-0.02044,0.06662,0.00148,-0.02406,-0.04145,-0.01274,0.02362,0.00886,0.06838,-0.0037,0.00631,0.00823,-0.01902,-0.01229,0.00311,0.00761,0.06064,0.07898,-0.06029,0.00054,-0.02346,-0.0054,-0.01361,-0.03864,0.00324,-0.00421,0.00068,-0.03896,-0.00295,0.0456,0.05208,-0.01825,0.0125,-0.03029,0.01039,0.01653,-0.01252,-0.03676,-0.04165,-0.04748,0.00372,0.08016,-0.05498,-0.00635,0.01139,0.01117,-0.00007,-0.01079,-0.02035,0.01764,0.09167,0.01163,-0.02155,-0.00037,-0.04722,-0.00206,-0.05248,0.00685,0.05928,0.02063,0.0168,0.02978,0.03596,0.03572,0.11971,-0.01289,0.14061,0.01973,0.0579,0.00111,0.12252,-0.01596,0.02915,0.02926,0.06404,0.01706,0.06944,-0.06265,0.00525,0.04733,0.10949,0.01619,-0.00275,-0.05783,0.00257,-0.02629,-0.06971,0.00859,0.08396,0.09259,0.02354,-0.07373,0.00108,0.09317,-0.01034,-0.0959,0.06097,-0.00125,0.01133,0.03134,-0.0049,-0.06712,0.0106,0.03813,-0.02036,-0.04384,-0.05168,0.02444,-0.04234,-0.07442,-0.02818,0.0274,-0.01435,-0.00174,0.00525,0.10961,0.0071,0.13256,0.09018,-0.04393,0.01064,0.02769,-0.03639,0.01842,0.02904,-0.11052,-0.05597,0.02027,-0.0167,0.09079,-0.02533,0.03773,-0.02901,-0.00684,0.00368,0.0285,-0.09252,0.02339,0.04312,-0.02473,0.06992],"hr/handle-employee-relations":[-0.01786,-0.02339,0.00515,-0.01377,-0.00421,-0.04846,-0.00934,-0.01209,0.0324,-0.1131,-0.01431,-0.10239,0.03585,-0.01335,-0.03196,-0.02026,-0.01673,0.02785,-0.03321,0.07432,-0.01515,0.00902,-0.00761,-0.01023,0.08302,0.03107,0.06993,0.02003,0.02532,0.01827,-0.0001,0.08547,0.04979,0.00756,-0.00273,0.00021,0.04165,-0.03699,-0.02259,-0.04939,0.01159,-0.00865,-0.01493,-0.01166,0.02608,-0.03097,-0.02323,0.12571,-0.0037,0.00056,0.04789,-0.00613,-0.02711,0.03214,0.01527,0.02157,0.03963,0.03481,0.06743,-0.00047,-0.02287,-0.04035,0.10329,0.01575,0.10565,-0.0127,0.03218,-0.00635,0.01017,-0.0249,-0.09179,-0.05709,0.08877,0.04596,-0.0534,-0.07704,-0.11289,0.03957,0.00268,-0.01318,-0.01496,-0.13755,0.09078,-0.03098,0.04225,-0.00995,-0.06938,0.09747,0.0164,0.03869,0.00296,-0.05861,0.04686,0.03437,-0.03713,-0.05395,0.03211,0.0338,-0.03594,0.05299,-0.02216,-0.04823,-0.06981,0.02208,0.00492,0.04515,-0.05567,-0.0777,-0.0101,0.01177,0.00838,0.04253,-0.00852,-0.0231,0.01627,-0.09325,-0.03221,-0.10084,0.10371,-0.03141,-0.00574,0.03664,-0.02857,0.01615,0.05648,-0.0139,0.01138,-0.03512,-0.04379,-0.04244,-0.01988,-0.07572,0.06608,-0.06371,-0.10855,-0.00397,0.03881,-0.01178,-0.07402,-0.03181,-0.10298,-0.00001,-0.02693,-0.01795,-0.04427,0.00395,0.01976,0.01768,-0.04552,0.06091,-0.02037,-0.05739,0.04849,0.056,0.01559,0.02866,0.0336,-0.06055,0.02168,-0.0802,0.00856,-0.01971,0.06687,0.01314,-0.00198,-0.02279,0.02136,-0.07464,-0.00716,0.01448,-0.00604,0.06488,-0.08687,0.02165,-0.0443,0.02566,-0.07304,0.00981,-0.04882,0.07524,0.05687,-0.04576,0.04079,0.03172,-0.01327,-0.01554,0.00347,-0.0184,0.02776,0.0362,0.08534,0.07716,-0.0292,-0.0902,-0.04769,-0.02165,0.13851,-0.02994,-0.03934,-0.02854,0.00523,-0.04254,-0.04653,0.0594,-0.00539,-0.06969,-0.05525,0.05093,0.02796,-0.08646,0.04727,0.04373,-0.02464,-0.03583,0.01388,-0.03536,0.00136,-0.00596,0.06324,-0.03367,0.02797,-0.01859,0.03754,-0.01743,0.0131,0.01246,0.07541,-0.05712,-0.01719,0.01078,0.02993,-0.0123,-0.05229,0.03808,-0.04176,0.00033,-0.05503,0.05786,0.01617,0.0207,0.00646,-0.05892,-0.04987,-0.03857,-0.05597,0.01592,-0.0589,0.00711,-0.03369,0.00374,-0.01191,-0.00303,0.02697,0.03855,-0.00395,0.11608,0.00301,0.05463,0.01665,0.01074,-0.00741,-0.00971,-0.03159,0.0431,0.01519,-0.04927,-0.05689,0.0434,0.00071,0.05571,-0.0322,0.01186,-0.04764,0.06816,0.07701,-0.01767,-0.02383,-0.02335,-0.05191,-0.03603,-0.00268,-0.0596,-0.00924,-0.06237,0.04446,-0.00421,0.0131,-0.03439,-0.00977,0.04452,0.03078,0.06348,0.01472,0.04048,0.05952,-0.12865,-0.08653,0.06052,-0.00811,0.02941,-0.00295,-0.00073,0.02973,-0.01326,-0.00099,0.0386,-0.03753,0.00708,0.04749,0.02217,0.05726,0.05917,-0.01436,-0.00037,-0.03046,0.01477,-0.00334,-0.05376,-0.0918,-0.03649,-0.06023,-0.03349,0.04088,-0.02133,-0.06314,0.06807,-0.011,-0.02739,-0.07481,0.00105,-0.01063,-0.01947,-0.03389,-0.00157,-0.02934,0.04339,0.0501,-0.00882,-0.02631,0.08268,-0.00544,0.01745,0.02967,0.0127,-0.01435,0.01123,-0.00381,-0.0758,0.01283,-0.08921,-0.02433,-0.03415,-0.03322,0.06128,-0.03932,0.00656,0.04374,-0.0781,-0.03422,-0.02464,0.03092,0.01029,-0.02406,-0.02246,0.02285,0.02259,-0.02644,0.01793,-0.00342,-0.07215,-0.07528,0.0311,-0.03782,-0.02354,-0.06353,-0.05532,-0.04423,0.00217,0.10345,0.04737,-0.00389,0.0678,0.05886,0.03141,0.0206,0.02436,0.03807,-0.06438,0.04226,-0.01271,0.01038,0.02905,-0.01349,-0.06272,0.05516,0.02131,-0.05156,-0.02409,-0.00309,0.01907,-0.02253,0.01195,-0.0461,0.0242,-0.01586,-0.03774,-0.00036,-0.00815,0.02774,-0.0442,-0.02472,0.01086,0.00517,-0.03601,0.07077,0.04536,0.02445,-0.01062,0.00533,-0.06818,0.03349,0.0191,-0.01985,0.00892,-0.00356,0.00701,-0.01595,-0.0401,-0.07747,-0.00159,0.0264,0.02468,-0.06012,0.01648,0.0035,0.05054,0.02853,0.08073,-0.00701,0.01523,0.02199,0.08241,0.04753,0.04403,-0.08951,0.07539,-0.06843,-0.01233,-0.03697,-0.07263,0.01737,0.04599,-0.00104,-0.03553,0.05373,0.01305,0.05006,0.01451,-0.00402,0.00219,0.06698,-0.00819,-0.04979,0.08773,-0.04278,0.02159,-0.00808,-0.00166,0.00789,-0.00585,0.00264,-0.01975,-0.02052,0.04091,-0.03368,0.019,-0.00776,-0.05438,0.02933,0.03593,0.10625,-0.02309,0.01249,0.01729,0.01391,-0.01139,0.10814,0.02265,0.04579,-0.0064,0.02582,-0.00848,0.03089,0.02917,0.02674,-0.03432,0.05077,0.00436,0.00319,0.02663,0.07441,-0.05285,0.02069,0.00246,0.04813,0.01083,-0.01361,-0.03054,0.00733,0.05406,0.01396,-0.04302],"hr/run-performance-reviews":[-0.03672,0.03417,-0.11495,0.0259,0.04335,-0.04495,-0.07503,-0.09748,-0.03516,-0.05943,-0.06034,-0.03723,0.01683,-0.02877,0.03725,-0.00307,-0.03363,-0.00756,-0.05441,-0.01974,0.04144,0.01584,0.04185,-0.0259,-0.04201,-0.03031,0.07545,0.03631,-0.01024,0.05773,-0.03742,0.02625,-0.01602,0.008,0.07879,0.04189,0.02974,-0.05778,0.01527,-0.03033,0.09128,0.01939,-0.04959,-0.00718,0.01152,-0.08562,-0.03864,0.04755,0.02292,0.05839,0.04446,0.03053,-0.02329,-0.03223,-0.02343,-0.03488,0.01196,-0.06397,-0.02422,-0.00938,0.00841,-0.00685,0.03972,-0.02381,0.0435,-0.04995,0.02745,-0.076,-0.06161,-0.00941,-0.03087,-0.07678,-0.03944,0.03656,-0.08299,-0.08089,0.04274,-0.00859,0.0001,-0.01413,-0.08329,-0.05439,0.04486,-0.0785,0.01773,-0.00086,0.01551,-0.0522,0.06465,0.06575,-0.02973,-0.01522,0.00796,0.06302,0.02989,-0.06098,0.02052,-0.03159,-0.00808,-0.02821,0.01394,-0.02379,0.05954,-0.01333,0.01405,0.02052,0.05042,-0.0642,0.0054,-0.00024,-0.04254,0.04007,0.00549,0.0012,0.02013,0.01083,0.12381,0.00131,0.0705,0.02055,0.07894,0.02677,-0.00963,0.05117,-0.01527,-0.01392,0.00436,-0.02169,0.04141,-0.08284,-0.02716,-0.02156,-0.00616,-0.02007,-0.00368,-0.01166,0.01496,0.08895,0.01523,0.01079,-0.08231,0.00167,-0.04769,0.02957,-0.024,-0.06524,0.00097,0.02811,-0.04277,0.01547,0.05131,0.01049,0.04405,0.0311,-0.03006,0.04488,0.02354,-0.08775,0.00525,-0.05239,0.03035,-0.03838,0.01805,0.01384,-0.03013,0.00748,0.0501,-0.01251,-0.04025,0.05918,-0.05489,0.0193,-0.04102,-0.00031,-0.01088,0.07759,-0.05353,0.00216,-0.07402,0.03372,-0.01476,-0.0616,0.02336,0.00633,-0.0304,-0.05219,-0.01174,0.01353,-0.00007,0.09071,-0.08232,-0.05048,-0.00784,-0.11899,-0.02791,-0.07994,0.02003,-0.0305,0.01584,-0.04212,-0.04759,-0.026,-0.03542,0.00136,-0.01837,0.05227,0.09332,-0.00882,0.03637,0.00785,0.04467,0.00308,0.01502,-0.01598,0.00357,-0.04149,0.01688,-0.01192,0.04003,-0.02805,-0.04293,-0.0269,-0.02772,0.02363,0.03513,-0.00414,-0.03012,-0.01945,-0.01192,0.01242,0.00015,-0.0078,0.00309,0.05095,0.00768,0.0591,0.03377,0.00666,0.01538,-0.01431,-0.08686,-0.04625,-0.00931,0.01524,0.0077,0.10925,0.03558,0.06053,-0.01199,0.02837,0.03112,-0.06911,-0.0105,0.07427,-0.00012,-0.00344,0.03583,0.11885,-0.06544,-0.03747,-0.01817,0.08204,-0.04364,0.00252,0.01459,-0.02991,-0.01956,0.02259,0.06641,0.02583,-0.03793,-0.06953,0.01201,-0.01865,0.01622,-0.00559,-0.06141,-0.00371,-0.11307,-0.01801,0.03809,0.06027,0.02232,-0.02581,-0.02227,0.03748,-0.0458,-0.00894,0.0135,0.01567,-0.0463,-0.01297,-0.00149,-0.04826,0.03164,-0.04328,-0.02647,0.03318,-0.00331,-0.03222,0.07731,0.01413,-0.01348,0.01207,-0.02547,0.02004,-0.0094,0.05173,0.03885,0.04637,0.05274,0.01139,-0.01501,-0.01823,0.04006,0.04835,0.00401,0.06377,0.00485,-0.0236,0.01651,-0.03253,0.02956,-0.01887,0.112,0.04617,-0.08694,0.03094,-0.04706,-0.0428,-0.0168,-0.04078,-0.00409,0.11953,-0.00868,0.01343,-0.03437,-0.00364,0.06192,0.07281,-0.08643,0.04978,0.00483,0.0131,0.03667,0.03048,0.02076,-0.0063,-0.04794,-0.03833,0.01376,-0.00219,-0.00127,0.08214,-0.08005,-0.05326,0.00095,-0.04044,-0.07339,0.06677,0.00531,-0.01877,-0.00633,0.0252,0.07968,-0.01127,-0.00188,0.00532,-0.02532,-0.01744,-0.09206,-0.05228,0.02952,0.00773,0.04344,0.0204,-0.03514,0.06671,0.06976,0.08127,0.04854,0.00497,0.06017,0.02015,0.00663,0.04171,0.02025,-0.0369,0.00803,0.06955,0.02703,0.03066,0.07813,-0.02794,0.00127,0.13045,0.02151,-0.01903,0.01387,0.06711,0.03071,0.02957,-0.01546,0.0272,-0.00764,0.0552,-0.04878,0.01194,0.00604,-0.02381,-0.00556,0.05248,0.01336,0.00672,0.05401,-0.03616,-0.03464,0.00695,0.04782,-0.02843,0.01148,0.05259,-0.05947,0.08783,-0.06107,-0.08704,-0.04533,0.02332,-0.01753,0.00348,0.11596,0.03035,-0.0475,-0.03681,-0.03781,0.03032,0.00641,0.02552,-0.01046,0.01776,0.03978,0.08805,0.03113,0.01637,-0.08038,0.075,-0.00543,0.00699,0.01863,0.00587,0.05453,0.01877,-0.0459,-0.04492,-0.03534,0.03294,0.01053,0.04734,0.03306,0.01414,-0.04386,-0.0926,-0.00098,-0.07231,-0.0256,0.04164,-0.00948,0.01479,0.02743,0.05258,0.00182,-0.03707,-0.01537,-0.03897,-0.02583,-0.05733,0.08126,-0.03818,0.08819,-0.00662,0.01641,-0.00343,0.00371,0.0034,-0.00853,0.04568,0.05785,-0.02231,0.05837,0.04634,0.01466,-0.02424,-0.01932,0.02238,0.03253,-0.04056,-0.09443,0.0168,0.03628,-0.0541,0.09376,0.00714,-0.01826,0.06297,0.10705,0.08299,0.01361,-0.04728,0.05829,-0.01373,0.09509,-0.06804],"hr/write-hr-policies":[-0.00739,0.04153,0.02459,0.03422,0.03542,-0.07133,-0.03075,0.04094,-0.03928,-0.01824,0.00731,-0.05017,-0.04011,-0.0468,-0.01198,-0.03933,0.02775,0.02436,-0.01184,0.05654,0.00504,0.01005,0.09287,0.00768,0.07381,0.03961,0.01418,0.04564,0.01206,0.03124,-0.0338,-0.02176,0.01647,-0.01132,0.00596,0.08292,-0.0071,-0.02821,0.02655,-0.08329,0.01813,0.00618,-0.00973,-0.00502,-0.02134,-0.01515,0.02078,0.00038,0.06784,0.07297,-0.0338,0.0971,0.03861,-0.05658,0.01941,-0.00921,0.00663,0.00324,0.04025,0.0096,0.01188,0.00723,-0.06592,-0.0094,0.08505,0.00181,-0.01567,0.05241,-0.02999,-0.02236,-0.09512,0.04858,0.01974,0.00129,-0.05757,0.00002,0.05957,0.06705,-0.0307,-0.00287,-0.0126,-0.13908,0.02054,0.07298,0.05446,0.01593,0.01429,0.0173,0.0325,0.04007,-0.02244,-0.04236,0.01672,0.03064,0.01488,0.01482,0.04526,0.02957,-0.06102,0.03106,0.03038,-0.07205,0.0505,-0.05265,-0.01858,0.0177,-0.07428,-0.06153,-0.01707,0.03347,-0.07022,0.04098,0.00152,-0.02417,0.01362,0.00736,-0.01454,0.0685,0.09691,-0.00443,-0.0161,0.07217,-0.03697,0.06593,0.00425,-0.05044,0.06357,-0.03139,-0.01183,0.00882,-0.07857,-0.03486,0.03806,0.01535,-0.09836,-0.0323,-0.04188,0.00353,-0.11901,0.02077,-0.05949,-0.02307,0.00953,0.05807,-0.02047,-0.07262,-0.03197,0.00721,0.00976,0.03038,-0.01393,-0.08685,-0.00563,0.0101,-0.0125,0.06859,0.01558,-0.04983,0.03939,-0.0405,-0.02773,-0.06923,-0.01021,0.02725,-0.07373,-0.03363,0.00996,-0.07416,0.03309,-0.01207,-0.12968,0.11616,-0.11354,0.02577,-0.06845,0.03743,-0.05775,0.02087,-0.01982,0.01092,-0.06837,-0.0442,0.08855,0.00196,-0.02676,-0.01875,-0.09628,0.01406,0.04436,0.03222,-0.00432,-0.09974,-0.00449,-0.00831,-0.06108,-0.0375,-0.05623,-0.06671,0.03285,0.01388,-0.02402,-0.04765,0.00244,-0.03728,-0.05273,-0.01849,0.01693,0.0058,0.01648,-0.01043,0.07329,-0.03322,-0.04515,0.06134,-0.01939,-0.00306,0.06103,0.00027,0.01859,0.00302,-0.07101,0.03558,-0.03767,0.03187,0.00807,-0.01403,0.05093,0.04684,0.06065,0.052,-0.03741,0.01152,-0.07102,0.0471,-0.02201,0.00783,-0.02312,0.04435,-0.0047,0.05135,0.01934,-0.0442,0.04294,-0.02699,0.02014,-0.04361,0.03625,0.06544,-0.03595,-0.04749,0.0167,-0.03323,0.0143,0.01887,0.00112,-0.03102,0.04411,0.04495,0.03719,-0.01341,-0.0692,0.04513,0.0127,0.01073,0.01517,-0.03746,-0.09484,0.01089,0.04167,-0.00494,-0.0087,-0.06435,-0.02019,-0.01385,0.02567,-0.01566,0.037,0.02608,-0.00058,-0.02872,0.02436,0.03593,0.01963,0.04789,0.06352,0.04851,-0.02944,0.04162,0.01697,-0.09833,-0.05532,0.00905,0.00172,0.02876,0.01595,-0.07562,-0.05379,0.06363,0.0322,-0.03874,-0.0439,-0.00356,0.02181,0.05854,-0.01803,-0.04204,0.01441,0.02114,-0.00558,0.03385,0.00362,0.02666,-0.07206,-0.01637,0.00534,0.02306,-0.01308,-0.01688,-0.05756,-0.0374,0.00288,-0.06937,0.00126,0.00849,0.06806,0.03561,0.00497,-0.00959,-0.04844,-0.04364,0.00606,-0.01037,-0.00561,-0.0002,0.00557,-0.03245,-0.01355,-0.07243,0.03771,-0.00648,-0.10407,-0.06488,0.01787,-0.09366,0.04885,0.10364,0.01961,0.00591,-0.00726,-0.00192,0.0059,0.01609,0.0034,0.07604,-0.06481,0.06098,0.00512,-0.024,-0.03448,0.03866,0.07141,-0.027,0.00321,0.06394,0.00398,0.05762,0.05833,-0.0179,-0.03264,0.00255,0.04225,-0.04328,-0.01027,0.09182,0.01091,-0.09571,0.04937,-0.02122,0.05078,-0.02444,0.00187,-0.02744,0.07924,-0.03768,0.04292,0.06659,0.01816,-0.00799,0.05789,0.03049,0.02946,0.05063,-0.00683,-0.01099,-0.04699,-0.05353,-0.0859,0.01816,-0.05726,0.00147,-0.00167,0.04634,-0.04122,0.06901,-0.05199,0.08344,-0.04947,-0.01681,-0.00986,-0.04953,0.00011,-0.01509,0.00836,-0.01964,0.02053,-0.01074,-0.03189,0.04972,-0.04841,0.00293,-0.00086,0.00599,0.01207,0.02889,-0.02335,0.05409,0.01469,0.0344,-0.05082,0.05851,-0.02604,-0.06694,-0.00983,-0.02031,0.03456,0.04378,-0.04604,0.01445,0.09472,0.01719,0.05126,0.08719,-0.02995,-0.01,-0.04525,0.0855,0.00697,0.06371,-0.03426,-0.06254,0.03966,0.15939,-0.03106,-0.08499,-0.06471,-0.00952,0.02032,-0.04514,-0.00154,0.08538,0.09576,-0.02173,-0.02967,-0.047,0.02015,0.01287,-0.01022,0.03402,0.00133,0.01714,-0.01332,0.04623,-0.00132,0.07017,-0.00681,-0.01666,-0.00067,-0.03673,0.03357,-0.01047,0.00611,0.02492,0.05402,-0.04134,0.06993,0.03473,0.07339,0.00988,0.00431,0.09028,0.0461,-0.04721,0.01017,-0.01168,0.02469,0.01053,-0.03367,-0.03907,0.03895,-0.04833,0.06578,-0.04371,0.04718,-0.0319,0.00855,0.03543,0.01794,-0.03803,0.02097,0.04294,-0.04919,-0.05202],"investor/screen-deals":[0.00661,-0.06656,0.01948,0.11799,-0.02634,-0.049,0.00924,-0.01221,0.01065,-0.02666,-0.05884,0.04733,-0.0154,-0.02569,-0.0105,-0.04046,0.02568,0.03932,-0.03207,-0.01956,0.01783,0.0212,0.03472,-0.0371,0.06283,-0.10786,0.02638,-0.01752,0.0003,0.02396,-0.05155,0.01539,0.04713,-0.05552,-0.01092,-0.03724,-0.0154,0.00005,-0.00828,-0.01081,0.0393,0.04048,-0.02749,0.06532,0.07233,-0.01726,0.03944,0.05637,0.04639,0.05599,-0.1177,0.08414,0.03283,-0.00084,0.04998,-0.03068,0.01,-0.05151,-0.00611,-0.02124,0.0252,0.08933,0.05148,0.01077,0.0454,-0.05358,-0.02824,0.00524,0.0169,-0.02884,0.00304,0.01562,0.03002,-0.01742,-0.02943,-0.01083,0.02624,0.03516,0.01619,0.01235,-0.028,-0.0389,0.06099,-0.01385,0.0306,0.02071,0.00174,0.05258,0.06951,0.04831,-0.03364,-0.00815,0.02921,0.07085,0.00105,-0.0513,-0.02066,-0.02257,-0.03407,-0.0216,0.11681,0.0303,0.06534,-0.05636,0.01032,-0.03766,-0.02,-0.05999,0.08535,-0.05543,-0.01881,0.02086,-0.03336,-0.00959,-0.0468,0.05727,-0.04428,-0.01517,0.00776,0.00858,0.07143,0.03585,-0.0373,0.01092,-0.04616,-0.06369,-0.01043,-0.07422,0.04709,-0.00078,-0.04084,-0.04672,-0.03947,0.02959,-0.00187,-0.00146,0.05375,0.01781,0.01226,0.00515,0.05592,0.0523,-0.01072,0.0169,0.02854,0.02654,0.00904,0.06948,-0.03109,-0.00357,0.04406,-0.10617,-0.0137,0.0699,0.09374,-0.03356,-0.01086,-0.03021,-0.01486,-0.05037,0.04166,0.18387,-0.02202,0.01916,-0.01898,-0.01986,-0.00819,-0.03651,-0.05238,0.0118,-0.09251,0.08968,-0.11792,0.0156,0.07869,-0.0218,-0.06975,0.0012,-0.00599,0.00703,0.00139,-0.02863,0.0191,-0.03757,0.01171,0.05099,0.10734,-0.06607,-0.04781,-0.04196,0.01089,-0.03166,-0.02055,-0.05676,-0.06074,-0.02605,-0.02359,0.04198,0.03212,-0.01734,0.00255,-0.03889,-0.04409,-0.06161,0.01758,0.02077,-0.00832,-0.02225,-0.00821,-0.05852,-0.02373,-0.04204,-0.02462,-0.07106,-0.02064,-0.02075,-0.02358,0.06154,-0.01134,-0.01912,-0.00884,0.01515,0.04601,0.02198,-0.03778,-0.01066,-0.00518,0.01925,-0.01299,0.10476,0.04114,0.05107,0.0633,0.01817,0.00126,0.03156,0.01631,0.00461,0.00174,0.00844,0.0077,-0.03005,-0.03548,0.00958,-0.04537,0.0604,0.10376,0.01032,-0.02813,0.01364,0.09079,-0.005,-0.02555,0.04538,0.00631,-0.01594,0.04278,0.00929,0.01981,0.04341,-0.03687,0.05607,0.06203,-0.02858,0.05861,-0.05657,0.00306,-0.07268,0.02919,-0.04237,-0.03761,-0.04583,-0.04528,0.02502,0.00434,0.05841,-0.00873,0.09609,0.01465,-0.02676,-0.04143,0.0201,0.00256,0.03573,-0.07836,-0.02269,0.00752,-0.00635,0.04071,-0.00694,-0.03602,0.01613,-0.03136,-0.05074,0.06036,0.02563,0.0184,0.02299,0.05706,-0.02911,-0.00082,-0.00349,-0.0614,-0.01011,-0.05325,0.03119,-0.01486,0.07186,0.0846,-0.00217,-0.01559,-0.01239,-0.01426,-0.06369,-0.01123,0.07903,-0.01227,0.00134,-0.00786,-0.03453,-0.03435,0.01234,0.00327,0.02535,0.07807,0.00274,-0.0134,0.05946,-0.11964,-0.05512,-0.06314,-0.03883,0.02905,-0.07678,0.00715,0.00055,-0.0304,-0.01284,0.08466,0.05051,-0.04228,0.03231,0.01935,-0.11019,0.05819,0.00391,-0.01465,-0.06329,0.08227,-0.0284,-0.01096,0.01823,-0.03236,-0.02463,-0.00084,-0.00781,0.07543,0.01577,-0.00921,0.02467,-0.0099,0.06395,-0.0923,-0.03387,-0.02767,0.03469,0.00234,0.00856,0.00211,0.0369,0.02564,0.00658,0.02359,0.01833,0.00994,-0.00605,-0.02126,0.08556,0.01821,0.10109,-0.00615,-0.01974,0.11563,0.01382,0.00637,-0.02108,0.02542,-0.06338,-0.02679,0.01163,-0.06784,0.00521,-0.0413,0.03755,0.07851,0.01435,-0.0025,0.03154,-0.02941,0.04168,0.04321,-0.08561,0.01793,0.03107,0.05208,0.10204,-0.04782,-0.03497,-0.06861,0.03025,-0.03177,0.12317,0.04565,-0.02251,0.01754,-0.03003,-0.02336,-0.07992,-0.01366,-0.10595,0.01262,0.0556,-0.08635,-0.02694,0.01931,0.04569,0.01295,0.0118,-0.0114,0.01813,0.01361,0.02885,0.00532,0.01834,0.0435,0.01545,0.0347,-0.00659,0.06627,0.06965,-0.04077,0.11988,0.03245,0.08502,0.0237,0.07955,0.02336,0.01835,-0.01655,-0.09676,0.05901,0.03747,-0.02687,0.00552,-0.01862,-0.03667,-0.05101,-0.0306,0.04358,-0.01971,-0.0299,-0.02294,-0.053,0.02939,-0.05378,0.03914,-0.0371,-0.0139,-0.01403,-0.00436,-0.0133,0.00025,-0.04034,-0.09622,-0.01908,-0.0067,-0.00493,-0.04192,-0.00963,0.01257,-0.03402,0.06329,0.08143,-0.00234,0.00105,0.00422,-0.06498,0.02822,0.05319,0.0606,0.05199,-0.00446,-0.041,0.01289,-0.01185,-0.00514,-0.05928,-0.04445,-0.02026,-0.05763,0.01558,0.02466,0.01024,-0.03077,0.02997,0.04331,-0.05745,-0.01013,0.03183,-0.00843,-0.01106,0.01517],"investor/research-companies":[0.07487,-0.05438,-0.01224,0.02507,0.0491,-0.00092,0.04801,-0.111,0.01373,-0.02348,-0.02492,-0.02418,-0.06993,-0.01749,0.0297,-0.00077,0.07536,0.02421,0.02659,0.00776,0.03763,0.01394,0.02302,-0.02419,0.05313,-0.03794,0.02088,-0.02557,0.02878,0.00634,-0.03918,0.03218,-0.0208,0.00592,0.02243,0.02277,0.01219,0.0231,-0.01947,-0.00066,0.03147,-0.03327,-0.00133,0.01929,0.05275,-0.05952,-0.00432,-0.00539,0.01573,0.04177,0.05136,-0.03627,0.05638,-0.03729,-0.01578,-0.00671,-0.01653,-0.07463,-0.00151,0.01629,0.07159,-0.06483,-0.01416,0.01566,0.03225,-0.10431,0.05571,0.03621,-0.03389,0.00236,-0.02626,0.00657,0.09728,0.06421,-0.01738,-0.05291,0.0293,0.02716,-0.00532,0.01162,-0.01641,-0.04703,0.05581,-0.04415,0.03061,-0.0784,0.00475,0.04955,0.00889,0.06185,-0.06541,-0.00162,0.00673,0.01317,-0.02843,-0.07137,0.08099,-0.02105,-0.01268,-0.05685,0.20081,0.04267,0.05802,-0.07263,0.04149,-0.01574,0.00592,-0.04995,0.00206,-0.02108,0.04863,0.01281,-0.0149,0.04482,0.05823,-0.06213,-0.08866,0.01738,0.01344,-0.0416,0.09522,-0.0053,-0.06205,0.02077,-0.03256,0.00579,-0.00132,-0.06985,-0.00004,0.04178,-0.0257,-0.062,-0.06327,0.07363,0.02766,0.05081,0.01911,0.05437,0.03942,0.01464,-0.02553,0.01696,0.0036,0.08963,0.03361,-0.01634,0.0125,0.04632,-0.02923,-0.00322,-0.01709,0.01678,-0.0064,0.05595,0.0065,-0.01491,-0.01822,0.01087,0.01124,-0.04522,0.01399,-0.003,0.03918,0.00923,0.00276,0.04444,-0.01885,-0.02934,-0.05045,0.01178,-0.0331,0.03228,-0.04832,-0.00772,0.06863,-0.01881,-0.02013,0.06688,0.03037,0.02051,-0.04035,-0.05879,0.07302,0.01676,-0.01679,0.03053,0.05399,-0.03466,-0.02935,-0.0108,0.06319,0.07908,0.00032,0.00857,-0.04069,-0.0036,0.07901,-0.01518,0.06029,-0.07205,0.05325,-0.03449,0.0332,-0.01088,0.09801,-0.0002,0.00271,-0.01975,0.08248,-0.06902,-0.00993,-0.0034,-0.00382,0.06259,0.05495,0.04187,-0.00518,-0.00445,-0.0382,-0.03128,-0.01724,0.0205,0.06983,0.01755,-0.01456,-0.04123,0.07766,-0.01074,0.01181,0.0295,-0.02245,0.02634,-0.01638,0.06228,-0.02744,0.03242,0.00568,-0.01701,0.00536,-0.06076,-0.04254,-0.03541,-0.11014,0.03777,-0.05595,0.00233,0.02875,-0.04155,-0.0306,-0.01669,0.01604,0.05807,-0.07808,0.01672,-0.062,-0.00895,0.00753,-0.03157,0.02834,0.09482,0.06708,0.02018,0.00979,0.06517,0.01393,-0.07297,-0.00153,-0.00764,0.08649,-0.02739,0.00933,-0.03201,0.03502,-0.0487,0.10213,-0.0042,0.02879,0.09668,-0.04156,-0.08109,-0.08169,0.02292,0.05135,-0.03961,-0.05027,0.02231,-0.02899,-0.04278,0.04684,0.0271,-0.0271,-0.03265,-0.00096,-0.01066,0.01268,-0.05789,-0.03897,-0.0046,0.04744,-0.00677,-0.00318,-0.02441,0.03557,-0.04173,-0.07399,0.01659,-0.00511,-0.02612,0.03753,0.02863,-0.08159,0.03798,-0.05237,-0.05215,0.04463,-0.04704,0.00537,-0.07006,0.05246,0.01074,0.02586,-0.02458,0.04442,0.03864,0.06287,0.00867,0.02668,0.04963,-0.03655,-0.07825,-0.01624,-0.02887,-0.03712,0.00386,-0.06643,0.00223,-0.07299,0.00669,0.09024,0.09718,-0.05233,0.00127,0.05535,0.00636,-0.04236,0.02198,0.0126,-0.00889,0.02552,-0.08718,-0.00879,-0.0126,0.04943,-0.02181,-0.03253,0.00098,0.0235,-0.06294,0.13376,-0.03961,0.03393,0.01552,0.00361,0.02764,-0.03337,-0.0446,-0.05006,0.01129,-0.05944,-0.05587,0.01735,0.05348,-0.02314,-0.02426,0.03048,-0.00277,-0.05389,-0.04041,0.00897,-0.00723,-0.04769,0.08117,0.06099,0.06587,0.03172,0.00414,-0.02805,0.06155,-0.06057,0.01284,-0.03416,-0.03362,-0.00648,-0.0027,0.03821,0.04452,-0.10649,-0.04813,0.0524,0.01895,0.00088,-0.02004,-0.0079,0.02677,0.05447,-0.0325,0.00475,-0.10159,-0.02147,0.00102,0.00125,0.04547,-0.01544,0.00067,-0.04539,-0.06782,-0.04438,-0.08095,-0.03581,0.03418,0.05115,0.06534,-0.05644,-0.01376,-0.03865,0.04736,-0.02791,-0.03194,-0.06313,0.01444,-0.01595,-0.01716,-0.0069,-0.027,0.0299,-0.05689,0.04624,-0.04804,-0.02862,0.02787,0.03805,0.08257,-0.01364,0.0881,-0.05144,0.0324,0.03965,0.08628,0.04175,0.00843,0.0434,0.03789,-0.02873,0.00104,-0.01469,-0.07551,0.07964,0.0928,0.02312,-0.01886,-0.03183,-0.04652,-0.00401,-0.05514,0.01943,0.04006,-0.0725,0.06555,-0.02578,-0.03528,-0.05566,0.01268,-0.03236,-0.04283,-0.02222,0.05461,0.10547,-0.04495,0.02405,0.05388,-0.00898,-0.01221,0.04987,-0.04943,-0.01178,-0.03096,0.04265,0.02976,0.11406,0.00145,-0.02077,0.05233,-0.05382,-0.00007,0.04521,0.03054,0.0884,0.0126,0.01412,-0.01346,0.03867,-0.00841,0.00776,0.06093,-0.01618,0.03708,0.01202,-0.01428,-0.00916,0.00662,-0.02113,0.00875],"investor/write-memos":[0.00024,-0.08044,-0.00357,0.07656,0.0328,-0.05601,-0.00776,-0.00757,0.00604,-0.02242,-0.10207,0.02868,0.00544,-0.00738,-0.01908,-0.01044,0.02463,-0.03362,-0.02649,0.02436,-0.0321,0.01633,0.06157,0.00281,0.04273,-0.10976,0.01681,-0.04834,-0.03117,0.01472,-0.03776,-0.0265,0.00816,-0.03817,-0.01308,0.01608,0.0033,0.03673,0.05602,-0.06062,0.07989,0.0217,-0.02908,0.00944,0.05842,-0.05238,0.05803,-0.00055,0.04979,0.02331,-0.11132,0.0781,0.06515,0.06004,0.00094,-0.00399,0.03534,-0.0165,-0.03229,-0.09377,0.05742,0.06827,0.0211,0.00457,0.03525,0.05338,-0.03884,0.05029,-0.01897,-0.00492,-0.0396,0.07165,-0.04659,0.01344,-0.04081,-0.01499,0.06165,-0.02485,0.07017,-0.00263,-0.03308,-0.05218,0.0253,-0.03802,0.02281,0.01824,-0.05066,0.05174,0.04564,0.07884,-0.03369,-0.02927,0.03833,0.08855,-0.02725,-0.03043,0.01879,-0.06887,-0.03348,-0.01095,0.09206,0.05451,0.06235,0.01919,-0.01009,-0.04923,0.04831,-0.05295,0.09547,-0.02983,-0.01647,-0.01461,0.01432,0.02678,-0.00065,0.06275,-0.00124,0.01845,0.03986,-0.03786,0.07349,0.04447,-0.01339,0.03452,-0.02003,-0.03826,0.03772,-0.07399,0.02976,-0.02515,0.00323,-0.09034,0.06332,-0.0103,0.00345,-0.01766,-0.02939,0.03391,0.0329,-0.03206,0.0369,0.02875,-0.04686,0.03649,0.01137,0.02748,-0.01522,0.02759,0.0357,0.02536,0.04634,-0.05279,-0.07465,0.03127,0.09994,-0.01597,0.03293,-0.0598,-0.04303,-0.02677,0.04391,0.07035,0.03618,0.03892,-0.00127,0.02899,-0.00335,-0.01333,-0.09479,0.00997,-0.1028,0.05601,-0.09179,0.07341,0.02032,0.02736,-0.06363,-0.02924,-0.02445,0.0251,-0.01206,0.00873,-0.00293,-0.08441,-0.03309,0.07834,-0.01661,-0.05776,-0.06712,-0.02562,-0.06503,-0.06665,0.00333,-0.04258,-0.06068,-0.05214,0.00499,0.01829,0.06057,0.02683,-0.04622,-0.02718,-0.03321,-0.02727,-0.04636,0.0554,-0.02519,-0.0143,0.00083,0.00197,-0.03131,-0.07723,0.05931,-0.04015,0.02157,-0.01815,-0.01711,-0.00859,-0.01932,-0.02577,0.0045,0.01851,0.07821,0.01745,-0.00876,-0.05796,-0.03402,0.05347,0.01536,0.05115,0.04751,0.0233,0.02972,0.04612,0.00736,0.00391,0.05222,-0.0029,0.02537,0.03203,-0.00017,-0.04472,-0.06425,-0.02585,-0.00678,0.04082,0.01935,-0.02253,-0.00684,-0.01418,0.05858,0.05821,-0.06269,0.0043,-0.01984,0.00767,0.02934,0.00589,0.00711,0.03583,0.01305,0.0405,0.06987,-0.05043,-0.01532,-0.03704,0.02478,-0.00418,0.02986,-0.0834,-0.00372,-0.07123,-0.02171,-0.01979,-0.03524,0.06841,0.02734,0.06136,-0.04312,0.03955,0.00505,0.0466,-0.06132,0.00396,-0.01014,-0.03305,-0.05978,0.01587,-0.01859,-0.01062,-0.01874,0.04091,-0.00892,-0.02815,0.04757,-0.0152,0.03929,-0.0118,0.10257,-0.05366,-0.01567,-0.00394,-0.02724,-0.00913,-0.08454,0.01228,0.00695,-0.00421,0.06329,0.00431,-0.0021,-0.05987,-0.06104,-0.03153,-0.06389,0.1045,0.00628,0.01389,0.01927,0.02759,-0.03353,0.03474,-0.02068,0.01553,0.08412,0.06908,-0.07437,0.04378,-0.0273,-0.00974,-0.04134,-0.00467,0.04788,-0.03594,-0.00559,-0.03359,0.01746,-0.02656,0.05166,0.02648,-0.12463,-0.02628,-0.02352,-0.0563,0.06826,0.02959,-0.06698,0.00308,0.10607,-0.01072,0.0178,0.02447,-0.01835,0.00583,-0.04979,-0.01553,0.02981,0.03374,-0.02428,0.01437,0.02098,0.05483,-0.02513,0.03661,-0.01923,0.02373,0.09197,-0.02995,0.02563,0.07094,-0.00985,0.0116,0.02051,0.05808,0.02038,-0.03362,-0.05801,0.07365,-0.01043,-0.0111,-0.04753,0.05761,0.03112,0.04258,0.00833,-0.02587,0.03478,-0.01761,0.03044,0.04014,-0.05684,0.00074,-0.10333,-0.0338,-0.07228,-0.03851,0.01505,-0.00371,-0.04939,0.02866,0.02645,-0.09521,-0.05713,-0.02026,0.02514,0.10148,-0.06013,-0.03993,-0.0055,-0.03018,-0.06597,0.00357,0.04893,-0.03475,-0.05857,-0.04396,-0.00891,-0.05907,-0.05912,-0.07151,0.01712,0.01276,-0.09413,-0.02542,-0.07017,0.05519,-0.03548,-0.00977,0.01216,0.00231,0.04042,0.01124,0.01489,-0.00515,0.10356,0.00941,0.01881,0.02731,0.02087,0.04677,-0.04059,0.09373,-0.00227,-0.00281,0.01139,0.05912,0.01387,0.0747,-0.05177,-0.02027,0.02219,-0.03147,-0.02811,-0.05607,-0.01115,-0.06278,-0.03987,-0.04808,0.00711,0.03799,0.01424,-0.02273,-0.11377,-0.02735,-0.01291,-0.00963,0.00303,-0.01723,0.05254,-0.01921,-0.01565,-0.04434,-0.05203,-0.06663,0.07314,-0.06817,-0.00207,-0.06735,-0.01201,0.0515,-0.01205,0.01013,0.02749,0.03143,0.01959,-0.0494,-0.04258,0.01819,0.04173,0.05362,0.07823,0.03758,-0.01019,-0.05129,-0.01785,0.04428,-0.08318,-0.04156,0.01403,-0.06212,0.0386,0.0075,0.06551,-0.0091,0.0868,0.04567,0.00026,-0.02579,0.10883,0.00742,0.02414,0.04095],"investor/review-diligence":[0.01277,-0.027,0.00812,0.06093,0.01716,0.0456,0.04131,-0.06009,0.05368,-0.00847,0.02717,-0.01401,0.02972,-0.03006,0.00963,-0.01863,0.02509,0.09989,-0.09361,0.02783,-0.02482,0.01538,-0.00316,-0.0274,0.05128,-0.04645,-0.04039,-0.03352,-0.00156,0.06243,-0.07084,0.04491,-0.03931,0.04154,-0.01326,-0.03936,0.03262,-0.01077,-0.07952,0.06665,-0.0029,0.05878,-0.09162,-0.01609,-0.04133,-0.04194,-0.01802,-0.0292,0.05939,0.02404,-0.07026,0.08401,0.00545,-0.02346,-0.0723,-0.01104,0.04284,-0.01905,0.02641,0.03439,-0.03856,-0.02261,0.03113,0.00113,-0.04283,0.03884,0.09397,0.00044,-0.05293,0.00799,-0.04074,0.01882,0.04679,-0.01951,-0.07037,0.01678,-0.01558,-0.07606,-0.01557,-0.00832,-0.02731,-0.00907,0.03951,0.05558,-0.03489,-0.03564,-0.02417,-0.0129,0.04753,-0.00558,-0.07325,0.00158,-0.01668,0.03793,-0.03977,-0.01462,-0.0001,0.003,-0.04348,0.02029,0.04077,0.04521,0.04326,-0.01806,-0.02212,-0.02248,0.02054,-0.06777,0.0557,0.0575,0.01655,0.06416,-0.05331,0.08599,0.02247,-0.01119,0.03587,0.0514,0.04591,0.03207,0.11664,0.01587,-0.07003,0.01647,0.04044,-0.0074,0.06175,-0.0413,0.01822,0.044,-0.04743,-0.02531,0.01555,0.07628,-0.03003,0.00942,0.03308,0.00568,0.00897,0.04227,-0.02189,-0.00776,-0.03247,-0.05172,0.02467,0.04718,-0.03947,0.0123,0.06161,-0.02848,-0.01509,-0.03351,0.06565,0.0202,0.01873,-0.04432,0.05571,0.00942,-0.02262,0.00886,0.06543,-0.04066,0.0679,-0.03561,0.00517,0.00999,-0.10549,-0.00694,-0.03915,0.06736,-0.08568,0.00966,-0.08242,-0.07677,0.00845,0.00413,0.0052,0.01328,-0.02038,-0.00563,0.07247,-0.0029,-0.00894,-0.03842,0.0019,0.04692,-0.0208,-0.01245,0.00842,0.0159,-0.03674,-0.03314,-0.0335,-0.10092,0.0038,0.0202,0.03656,0.08551,0.049,0.00066,-0.00937,0.05351,0.02935,-0.01472,0.02299,-0.05122,-0.00504,-0.06676,-0.04823,0.02406,-0.00251,-0.04834,0.04172,0.00462,-0.02874,-0.00566,0.03985,-0.07116,0.07231,-0.00695,-0.06599,0.03841,0.03101,0.06471,-0.04761,-0.05952,-0.03305,0.02908,-0.08218,0.02918,0.036,-0.01281,0.00775,0.05026,-0.00903,0.02035,0.04182,-0.03027,-0.02447,-0.00832,-0.03815,-0.08689,0.00624,-0.02154,-0.0445,-0.01086,0.05402,-0.00421,-0.06658,-0.04766,-0.05885,0.03216,-0.10463,0.04914,0.00005,-0.03791,-0.06934,0.06347,0.05409,-0.05081,-0.05359,0.05027,-0.04481,-0.06126,0.01432,-0.07763,0.00443,0.02661,0.09747,0.02638,-0.06175,-0.02519,-0.04008,-0.04507,-0.00774,-0.02865,0.06025,-0.0508,-0.06924,0.01018,0.02957,-0.06958,0.09643,-0.05188,0.01684,0.04237,0.00834,-0.00671,0.09051,-0.05413,0.01228,-0.04535,0.02461,-0.06433,-0.01605,-0.02528,-0.06173,-0.00001,-0.04092,0.00931,0.06228,-0.02813,-0.0035,0.00276,-0.04502,-0.01998,-0.02999,0.04605,0.00435,0.03391,0.01941,-0.00703,-0.08574,-0.01721,0.02555,0.02599,-0.01169,0.01547,-0.04647,0.08125,-0.0362,0.01105,0.06291,-0.02586,0.05447,-0.00386,-0.01027,0.05582,-0.01167,-0.06531,0.03066,-0.03523,-0.06939,0.02823,-0.02786,0.03885,0.05333,0.04709,0.00295,0.04989,-0.06754,-0.07457,-0.01649,-0.01107,-0.0085,0.02383,0.01098,-0.04181,-0.05179,-0.03008,-0.00927,-0.00563,0.02445,-0.03601,-0.0775,-0.02978,0.02718,-0.00557,0.0083,0.03014,-0.05602,0.0399,0.09157,0.02586,-0.00175,0.02891,0.00264,0.05062,0.03449,-0.03196,-0.01453,-0.02518,0.05874,-0.07495,0.05711,0.04423,-0.00714,-0.03819,0.05874,0.03886,-0.01673,0.09834,0.08131,0.06785,-0.00192,0.03718,0.02225,-0.04968,-0.01839,-0.00381,0.05423,-0.00751,0.02792,-0.07274,0.08921,0.03157,0.06092,0.04763,-0.0631,0.08475,0.02572,-0.05427,0.02702,-0.02795,-0.05745,0.08485,-0.06244,-0.03258,-0.02986,0.01513,-0.00063,0.05164,-0.02206,0.00404,0.02981,-0.11048,-0.00094,0.04567,-0.02335,-0.01086,0.01493,0.00022,-0.06107,0.0941,-0.01194,0.0269,-0.06625,0.01583,-0.03495,-0.05193,0.04329,0.05109,0.00212,0.01375,-0.04611,0.06668,0.08687,0.02679,-0.01141,0.05342,-0.0163,0.08861,0.05056,0.02364,0.01358,0.02172,-0.01682,0.05661,-0.06035,0.01189,-0.02341,0.04198,-0.04588,-0.07549,0.01666,0.01555,0.04656,-0.0489,0.00387,-0.12926,-0.03183,0.00218,-0.03037,0.02234,0.02693,0.04969,0.02315,0.01856,0.04682,-0.03738,0.01539,0.07363,0.04203,0.05247,-0.00227,-0.03509,0.03791,0.00624,0.08049,0.01369,-0.03465,0.02118,-0.0347,-0.06539,-0.01573,0.05049,0.02916,0.02492,0.04884,0.11279,0.06641,-0.03798,-0.05513,-0.02232,0.00974,-0.00172,-0.01525,0.00284,0.02797,0.0034,0.00672,-0.06883,0.0336,-0.02351,0.04257,-0.01002,-0.00381,0.00491,-0.09117,0.06478,-0.03551,-0.00309],"investor/report-portfolio":[-0.01513,0.05428,0.01762,0.03839,0.10122,-0.01981,-0.10838,0.00911,0.02992,-0.04249,-0.05267,-0.01746,0.0514,0.00336,0.02106,-0.03399,0.00148,0.01582,-0.04096,0.08404,0.0195,0.02755,0.02252,-0.01146,0.0054,-0.08579,0.04884,0.01017,0.09068,0.06381,0.01402,-0.00352,-0.05193,0.02524,0.08102,0.02966,-0.02161,-0.02311,0.0593,-0.0004,0.00466,-0.00256,-0.05759,-0.10079,0.01489,-0.07989,0.00215,-0.02462,-0.02099,0.04615,-0.08255,0.06179,0.03304,0.01984,-0.01024,-0.00677,0.01183,-0.06216,-0.00389,-0.02489,0.03493,-0.03389,-0.02189,0.00879,0.01495,-0.00236,-0.04257,0.00952,0.0009,-0.03146,-0.03218,0.02977,0.00016,0.08274,-0.06141,-0.04142,-0.07601,-0.01658,0.05464,-0.05766,-0.06229,-0.0525,0.00883,-0.01808,0.01086,0.03132,0.01967,0.03531,0.0498,-0.00772,-0.02658,-0.00213,-0.0107,0.05362,-0.01306,0.00256,0.06916,0.00822,-0.04515,-0.02798,0.03852,-0.03004,0.07047,-0.05254,0.00919,-0.01414,0.06049,-0.07273,0.0306,-0.05695,-0.01391,0.05213,0.01271,0.0195,-0.01078,-0.00046,0.0084,0.038,0.08543,-0.05211,0.00501,-0.01096,-0.03822,-0.04184,0.02042,0.04727,0.03928,-0.05526,-0.01898,-0.04563,-0.09704,-0.07012,-0.03417,0.00903,-0.04367,0.02498,0.0169,-0.02113,0.0021,0.01136,0.00455,-0.03249,0.00897,-0.00656,-0.04841,-0.00741,-0.0143,-0.04512,0.00362,0.02063,-0.03382,-0.05271,-0.01495,0.03306,0.02646,0.05771,0.01816,-0.02322,0.01418,-0.00731,-0.01949,-0.06121,0.03658,-0.04124,-0.00944,0.063,-0.00411,-0.02614,-0.01297,0.0028,-0.11162,0.06906,-0.08621,-0.01484,-0.06858,0.10016,-0.02868,-0.05052,-0.07898,0.08859,0.00347,0.02407,0.00729,-0.03645,-0.05355,0.01412,-0.02203,-0.01008,0.04575,0.01834,-0.02992,0.01024,-0.03583,-0.108,-0.01264,-0.03239,-0.01768,0.04993,0.03481,0.00811,-0.00763,0.02716,-0.08868,-0.05216,-0.12916,-0.01058,0.0003,-0.0809,0.00628,0.01102,0.01737,0.00921,0.0705,0.04239,-0.06042,0.02272,-0.00284,-0.0302,0.03649,0.0066,-0.04053,0.03393,0.01875,-0.02488,0.02185,-0.07513,-0.08844,0.00821,-0.01129,0.01404,-0.0208,0.02397,-0.03038,-0.0326,-0.00357,0.02798,-0.0555,-0.009,0.03998,0.03828,-0.01314,0.00456,-0.04735,-0.00201,0.00179,0.01099,0.05401,0.06397,-0.01277,-0.04925,-0.0285,0.04217,0.05379,-0.02088,0.05959,-0.01175,-0.03061,-0.00029,-0.05865,0.06814,-0.06812,-0.00913,0.03432,-0.03159,-0.01792,-0.09385,-0.00385,-0.01097,0.06731,-0.02741,-0.09768,-0.06285,-0.03229,-0.03398,-0.06572,-0.01998,0.05135,-0.01719,-0.01297,-0.04134,-0.04053,-0.01912,0.02553,-0.00764,0.03058,-0.00415,-0.03293,0.00542,-0.03329,-0.00294,-0.01502,0.0074,0.01292,-0.05532,0.04809,0.02774,-0.04531,0.06072,-0.01635,-0.01505,-0.02901,-0.01714,-0.02016,0.02339,-0.11202,-0.02563,-0.00111,0.07767,-0.02395,-0.03812,0.05658,0.07517,0.00483,-0.01893,0.00955,-0.01122,0.01616,0.02629,-0.06162,0.00127,-0.07914,-0.07661,0.04183,0.09195,0.11452,0.02045,-0.11715,0.09648,0.00382,-0.03641,-0.01001,-0.00455,0.07275,0.0471,0.03778,-0.02295,0.01043,-0.00434,0.10684,0.05036,-0.06256,0.08197,0.02905,-0.01678,0.01581,0.03337,-0.09118,0.04728,0.02755,-0.02485,0.03419,-0.02825,-0.08471,0.00835,-0.03261,0.03694,-0.02907,-0.02455,0.003,0.04631,-0.00431,-0.00435,0.06724,0.0708,0.03945,-0.01168,0.04014,0.02268,0.05592,-0.04643,-0.00967,0.02183,0.03395,0.00966,0.00304,-0.03228,-0.08356,0.03944,0.05923,0.02561,-0.01178,0.01385,0.03855,0.01987,0.04662,0.00947,0.01582,0.02427,0.00918,0.08201,0.0079,0.02183,-0.01234,-0.06278,-0.01059,0.05256,0.03201,-0.07207,-0.00489,-0.01604,0.07967,-0.03462,-0.06027,0.01898,-0.01827,0.08427,-0.0489,-0.05055,0.00693,-0.01998,0.01621,0.01801,0.02404,-0.03012,-0.06535,-0.09276,0.04529,0.03964,-0.05466,-0.0479,0.002,0.06001,-0.00879,0.03552,-0.03113,-0.00363,0.03172,0.00259,-0.01456,0.08046,-0.00784,0.03557,0.05825,-0.0378,-0.00523,0.05425,-0.02901,0.0424,-0.02074,-0.00721,0.01345,0.09917,-0.03692,-0.0038,-0.03589,0.02674,0.04038,0.06226,-0.04462,0.0529,-0.01245,0.03317,-0.02098,-0.01046,-0.11133,-0.00074,0.02988,-0.02,-0.04903,0.02033,0.05291,-0.03976,-0.0509,0.02013,0.00196,-0.00657,0.04795,0.06342,0.08469,-0.04352,-0.02779,0.03316,0.06234,0.03224,-0.04772,-0.01126,0.00773,-0.01197,0.09572,0.09569,-0.01694,-0.02441,-0.00462,0.01443,0.02076,0.0064,-0.00879,0.05163,0.04729,0.04854,0.07106,0.00815,-0.05558,-0.00677,0.04586,-0.06391,-0.11391,-0.02235,0.00873,-0.08235,0.043,-0.0451,0.04142,0.00018,0.01745,0.09284,0.08431,-0.05269,0.0349,0.04022,-0.01168,-0.03118],"lawyer/client":[-0.02135,-0.05367,-0.00638,0.00542,0.00003,-0.05319,-0.03553,-0.00269,0.0216,-0.06885,-0.07718,-0.05071,-0.04201,0.01262,-0.03849,-0.06885,0.02134,0.01597,-0.10252,0.0683,-0.06238,0.02108,-0.01708,0.024,-0.00314,0.02618,0.04557,0.02513,0.00875,0.00588,-0.07589,0.06353,0.0235,0.02851,0.08843,-0.00498,0.05843,-0.03692,0.05277,0.05754,-0.0015,0.05983,0.00745,-0.02342,0.00518,-0.02971,0.00268,0.02608,0.02987,0.01406,0.01386,0.02396,0.00706,0.03507,-0.01252,0.05752,0.00659,0.02583,0.01852,0.01497,-0.01243,-0.0214,0.02132,0.06762,0.06977,-0.03293,-0.04853,-0.05116,-0.01528,-0.05746,-0.09952,0.01374,0.03031,0.04799,-0.01354,0.01291,-0.06617,0.01271,0.04402,-0.05331,-0.00587,-0.12427,0.08293,-0.02133,0.03027,0.03372,-0.04085,0.08121,0.06988,0.0252,-0.0101,-0.07234,0.04773,0.05842,-0.00012,-0.09804,-0.00208,0.03895,-0.04727,0.03485,0.03738,-0.05461,-0.04588,-0.00785,0.07125,-0.06545,0.03439,-0.08459,0.01454,0.06404,0.01631,0.00922,0.06069,0.01478,0.07335,-0.03449,-0.04184,-0.07381,0.00668,-0.07268,0.0033,0.02921,-0.03182,-0.08987,0.06527,0.00255,0.01819,-0.03388,-0.04387,-0.0415,0.00094,0.06139,0.06383,-0.01326,-0.10703,0.03014,0.08101,-0.0392,-0.05881,-0.02906,-0.08733,-0.08561,0.01166,0.0141,-0.05061,-0.08691,-0.00302,0.06951,0.01878,-0.022,0.03146,-0.08405,-0.03715,-0.0345,0.03232,0.01426,0.06876,0.04108,0.01014,-0.01476,-0.04798,0.00006,0.0469,-0.01432,0.02238,-0.01639,0.00559,0.00444,0.03996,-0.08232,-0.06839,0.1004,-0.08999,0.0181,-0.0934,0.04905,-0.0749,0.04378,-0.01683,0.03343,0.02148,-0.05323,-0.02252,0.00929,-0.02512,-0.00117,-0.0628,-0.04677,0.02038,0.01983,0.06125,0.04475,-0.04861,0.00542,-0.02744,-0.02814,-0.00455,-0.01184,-0.05623,-0.01524,-0.00712,-0.0125,-0.07032,-0.02619,-0.04692,0.07235,-0.08044,0.06295,-0.01129,-0.07514,0.05518,0.04764,0.01746,0.00766,-0.02162,-0.0423,0.02876,-0.01714,-0.01762,-0.0123,0.03997,0.00416,0.05072,-0.03287,-0.03496,-0.00709,-0.12548,-0.01983,0.08188,0.03146,0.10297,-0.01171,0.0483,-0.05272,-0.01952,0.01769,-0.00858,0.01097,0.0092,0.00111,0.04696,0.01608,-0.01251,-0.07089,-0.00469,-0.02296,-0.01031,0.03878,0.02138,-0.03485,-0.02182,0.05075,0.03228,0.01758,0.06939,-0.01609,0.03639,0.0291,0.00501,0.01888,-0.0845,-0.03207,0.02639,0.02441,0.01907,-0.02689,0.04377,-0.04216,0.01755,-0.08081,0.00428,-0.02294,-0.02376,-0.00844,0.00217,-0.04531,-0.02039,0.04886,-0.05897,-0.00554,-0.01579,0.03221,-0.00287,-0.0408,0.06488,0.00892,-0.04802,0.02226,-0.01566,-0.02393,-0.01084,-0.05945,0.02032,-0.05801,0.04138,-0.07034,-0.03816,0.01598,0.02753,-0.0443,-0.01064,-0.03178,0.00762,-0.02938,-0.05092,0.02425,-0.00891,0.06587,0.05778,-0.03738,-0.00609,0.03559,-0.0353,-0.04175,0.02922,-0.0095,-0.04704,0.03282,-0.09717,-0.07618,-0.04651,-0.06348,0.00555,-0.00608,0.01275,0.04008,-0.00366,-0.0411,-0.00808,-0.07939,0.00496,-0.03483,0.02692,0.06975,-0.07131,-0.0023,0.03778,-0.01049,-0.02427,0.07418,-0.06319,-0.02941,-0.00608,0.05137,0.02434,-0.01542,0.03263,-0.0687,-0.03388,-0.05157,0.00522,-0.0245,0.07762,-0.00057,-0.00024,-0.06189,0.03752,-0.07362,0.04058,-0.05471,0.02788,-0.00384,0.05432,-0.06152,0.0482,0.06053,0.00321,0.01018,0.00118,0.00076,-0.0801,0.0271,0.03366,0.01086,-0.05096,0.00608,-0.0581,0.05706,0.06928,0.01381,-0.03829,-0.01031,0.03529,-0.01485,-0.01126,0.06596,-0.00296,-0.04521,0.03386,-0.00561,-0.01589,0.05752,0.02983,-0.07603,-0.08035,0.08921,-0.03462,-0.10083,0.03617,0.03101,-0.0388,-0.02287,-0.04356,-0.00243,-0.03829,0.05734,0.00985,-0.01053,0.01266,-0.03272,-0.00937,0.03367,0.05819,0.00132,0.03056,-0.00843,0.01967,-0.06198,-0.02968,-0.06209,0.06289,0.00607,-0.00935,0.01212,-0.03706,0.06421,-0.01543,0.02189,-0.09771,0.07714,0.02846,0.00597,-0.02047,-0.01513,0.02614,0.09164,0.05235,-0.01191,0.02056,0.0658,0.00469,0.06644,0.00197,0.00716,-0.02092,0.03002,-0.02844,0.07696,-0.08557,0.05325,-0.00603,0.0378,0.01922,-0.02518,-0.0017,0.10486,0.03127,-0.01285,0.05047,0.06,0.0296,-0.02079,-0.06156,0.07408,0.02693,0.02313,-0.01417,-0.04498,0.00846,0.04014,0.04376,-0.02049,-0.02231,0.10725,0.01257,-0.01991,-0.04621,-0.00698,0.05853,-0.02197,-0.01015,-0.04832,0.02493,-0.03201,-0.02304,0.01764,0.01585,0.00628,0.05762,-0.02447,0.04559,0.01084,-0.00539,0.05075,0.02779,-0.06988,-0.04241,-0.02716,0.00439,-0.006,0.09065,-0.00472,0.0134,-0.01107,-0.00993,0.04402,0.02208,-0.02648,-0.00556,0.08682,-0.01005,0.01173],"lawyer/research":[0.03909,-0.06423,0.04181,0.03643,0.05868,0.03632,0.02038,-0.01183,0.05019,-0.03376,0.01837,-0.03726,-0.04555,0.01252,-0.01569,-0.0565,0.01829,0.03932,0.03555,0.20979,0.03182,0.08105,-0.00289,-0.01383,0.09935,0.02553,-0.00572,0.04554,0.03106,0.02958,-0.0764,-0.01665,-0.06533,-0.02653,0.03489,-0.05881,0.13148,-0.08024,0.01958,-0.00065,0.01763,-0.00097,-0.04568,0.01254,0.09158,-0.02998,0.0658,-0.03881,0.04696,0.0727,0.04974,-0.02372,0.07598,0.02747,0.00052,-0.0047,0.03874,0.01987,0.0322,-0.00167,0.02979,0.03982,-0.00461,0.01348,0.01232,-0.01723,0.04184,0.02508,-0.05379,-0.02165,-0.06575,0.00021,-0.01033,0.01603,-0.025,0.03299,-0.04967,0.06868,-0.04294,0.0207,0.01245,-0.11636,0.04271,0.09187,0.08339,0.03928,-0.06057,0.05416,0.03595,0.01209,0.00055,0.00922,0.03886,0.05751,-0.00699,-0.04312,0.02057,-0.00742,-0.08805,-0.01938,0.01759,-0.10745,0.05844,-0.02496,0.03469,-0.02462,0.07972,-0.07008,0.03715,-0.03423,0.01779,0.01714,-0.01741,0.01384,0.05822,0.04582,-0.05815,-0.0036,0.09913,0.05436,0.04162,0.02755,-0.09894,0.05534,0.00938,-0.02936,-0.01299,0.00585,0.02519,0.02369,0.02613,-0.04998,-0.00317,0.03997,-0.13047,0.00877,-0.00553,-0.02459,-0.14979,0.01647,-0.04981,0.00816,-0.02278,-0.0705,0.03516,0.06201,0.0008,-0.03051,-0.01018,-0.02745,-0.00339,-0.06588,-0.15519,-0.00331,-0.00036,-0.01172,0.05676,0.06689,0.01397,-0.04388,-0.02075,-0.03888,-0.04718,0.03273,0.00841,0.01794,-0.02809,-0.03649,0.01645,-0.00773,-0.07001,0.13036,-0.08625,-0.02336,0.01268,-0.00175,-0.04545,0.0514,-0.01746,0.03448,0.0588,-0.06996,0.03931,0.00007,-0.00631,-0.02204,-0.03791,0.01538,0.02147,0.00936,0.02922,0.05268,-0.01778,-0.00297,-0.03664,0.05706,-0.00985,0.02464,-0.05975,-0.03846,0.02919,0.00672,0.00373,0.01059,0.08717,-0.05168,0.00998,0.02494,0.07164,-0.07279,0.02966,0.02487,-0.02728,0.01041,0.01733,-0.02297,0.06869,-0.01729,-0.03395,0.00337,-0.03792,-0.03117,0.00312,0.01938,0.00148,0.00615,0.0274,-0.01694,-0.03251,0.01503,-0.02224,0.00836,0.03014,0.00672,0.00576,-0.01151,0.0516,0.10679,-0.03451,0.03859,0.03625,-0.04353,-0.09114,-0.02777,-0.05783,0.02134,0.04782,0.006,-0.02728,-0.09437,0.01224,0.04783,0.00237,0.03991,0.01305,-0.02724,0.00964,0.06874,0.03818,-0.00849,-0.10593,0.00134,0.00633,0.08339,0.0477,-0.00401,-0.01755,0.0073,0.04881,0.00027,-0.01675,0.0267,-0.02189,-0.02091,0.05822,-0.03052,-0.00325,0.02863,0.01504,-0.0193,-0.00032,0.02041,0.04102,-0.00982,-0.06003,0.01859,-0.01819,-0.01433,-0.0187,-0.01005,0.03573,0.03577,0.00823,0.03707,0.01994,-0.10942,-0.06146,0.04033,0.05702,0.03342,-0.05056,0.02364,-0.03945,-0.03985,-0.04752,0.02236,-0.03783,0.01177,-0.02325,-0.01053,-0.05401,0.10742,-0.00399,-0.04947,-0.0053,-0.01981,-0.04856,0.02413,-0.08288,-0.00869,-0.02895,0.00894,0.026,0.02106,0.02033,0.08231,-0.01006,0.00018,-0.02431,-0.04864,-0.04753,-0.05589,-0.03633,0.00453,-0.02689,0.01429,-0.01066,0.02407,0.0373,-0.02388,-0.04118,0.05847,0.01622,-0.03824,0.00216,-0.02794,0.03031,0.01964,0.03377,-0.06483,0.03074,0.00172,0.04572,-0.06564,-0.07976,-0.00501,0.01231,-0.03845,0.00448,-0.02018,0.02641,-0.01078,-0.01161,-0.00645,0.05689,0.05313,-0.02442,0.02205,-0.00032,0.0126,0.03117,-0.03266,-0.03987,-0.02016,0.05577,-0.05068,0.04755,-0.00243,0.03528,-0.01059,-0.03888,-0.03971,0.0398,-0.04571,0.01404,-0.00944,0.00267,-0.0121,-0.00465,-0.02672,-0.05609,0.03047,-0.01741,-0.05292,0.03166,0.00361,-0.03456,0.02424,0.0195,0.01501,-0.01801,-0.01877,0.01325,-0.01165,-0.0307,0.00565,-0.00383,0.00137,-0.13044,0.0081,0.0083,0.08582,0.02248,-0.01125,0.0568,-0.01984,-0.05965,-0.00006,-0.06362,0.01934,0.02619,0.01271,-0.0382,0.03432,0.01513,0.09399,-0.03997,0.0312,-0.07787,-0.03845,0.04408,0.03167,-0.01728,-0.03027,-0.04524,0.06185,0.10051,0.02456,0.06116,0.0443,0.02775,0.05034,-0.00407,0.08113,-0.04056,0.1136,-0.01299,0.055,-0.05961,-0.03911,-0.03645,0.00636,-0.02944,-0.03172,-0.0148,0.0161,0.08666,0.07787,-0.00378,0.01645,0.02838,0.00236,0.00404,0.05491,-0.01685,0.0312,-0.06074,-0.05341,-0.00701,0.06925,-0.04488,0.06468,-0.07258,0.06082,0.01492,-0.06715,-0.01412,-0.04777,-0.01394,-0.01654,0.00131,0.01617,0.04261,-0.05579,-0.00861,-0.00965,-0.07705,0.00961,0.07115,-0.00487,0.00577,0.012,-0.02254,-0.01733,0.01378,-0.01543,-0.02848,-0.02985,0.03236,-0.00837,-0.01167,-0.06797,0.01693,0.03093,-0.02655,0.02427,-0.04272,-0.015,-0.01791,0.08246,-0.02423,0.00909],"lawyer/review":[-0.05381,-0.10055,-0.03407,0.06382,0.04389,-0.04017,-0.04014,-0.00735,-0.04367,-0.00601,-0.02674,-0.04311,0.02371,-0.06862,0.00407,-0.0669,0.04443,0.04357,0.01541,0.12172,-0.01044,0.07885,0.0124,-0.04174,-0.00423,-0.00362,0.01571,0.0574,-0.02082,0.02719,-0.02209,0.05646,0.07064,-0.00149,-0.06335,-0.03958,0.03295,-0.0416,-0.04807,0.0331,-0.00008,0.04817,0.02041,-0.01482,0.0367,-0.00153,0.02747,0.03076,0.03096,0.01914,-0.02595,0.0585,-0.0126,-0.05245,0.04575,0.01412,-0.00575,-0.04919,0.00838,0.03434,0.07181,0.02863,-0.0024,0.03371,-0.02164,-0.00917,0.0216,-0.01885,-0.03022,0.02057,-0.00058,0.01233,0.06816,0.0165,-0.03832,-0.08464,0.01519,0.03257,0.01504,0.01761,-0.04748,-0.05118,0.05545,0.02161,0.09049,0.05208,-0.01388,0.01836,0.05859,0.0507,0.03369,0.02049,0.03548,0.04928,-0.01496,-0.07889,0.04081,0.01627,-0.06309,0.03083,0.10439,-0.02081,0.05275,-0.02694,0.00367,-0.05159,0.04382,-0.03847,0.03267,-0.01019,0.01242,0.08091,0.00349,-0.02206,0.06938,0.0457,-0.01058,-0.03367,0.1029,-0.00665,0.06816,0.0208,-0.04066,0.01139,-0.04971,-0.04036,-0.0278,-0.02848,0.05956,-0.07302,-0.0241,-0.00057,-0.04443,-0.05059,-0.04011,-0.02655,0.00755,-0.00776,-0.0875,0.03028,-0.03248,0.03048,-0.0382,0.02948,-0.01452,-0.01755,0.00442,-0.04328,0.00578,-0.04215,0.00711,-0.0206,0.00012,0.0019,0.0555,-0.04957,-0.01106,-0.03434,-0.05887,0.01743,0.04979,0.11791,0.00912,0.02325,-0.01658,-0.07407,-0.06342,-0.03438,0.00872,0.0594,-0.06699,0.04201,-0.04501,-0.0206,0.03017,0.05546,-0.03514,0.01215,-0.06097,0.09604,-0.02931,-0.0743,-0.02848,-0.07072,-0.00667,-0.03016,0.02767,-0.07218,0.02146,0.05395,-0.03201,0.01671,0.00231,-0.05227,-0.02522,-0.00172,-0.02207,0.00787,-0.00047,0.01017,-0.03734,0.02117,-0.03342,-0.00621,0.07835,-0.05813,0.00594,-0.00975,0.01056,-0.09853,0.07954,-0.01513,-0.03392,-0.01063,-0.0148,0.01649,-0.02724,-0.0086,0.02489,0.00502,-0.05519,0.02609,0.05711,-0.05924,-0.00291,0.00826,-0.03286,0.08875,-0.00925,0.09434,0.02705,-0.02574,-0.00729,0.01258,-0.06606,0.00119,0.07352,0.03051,0.00277,-0.02013,-0.02994,-0.02935,-0.08214,-0.04957,-0.05794,-0.0365,0.00868,-0.00877,-0.09541,-0.02236,0.02788,-0.05521,-0.00241,0.00398,0.05294,0.01587,-0.00052,0.08356,0.01267,-0.08207,-0.08445,-0.02569,0.027,0.025,0.03566,0.00283,-0.03479,0.04194,0.05081,0.04512,-0.06164,-0.02609,-0.0302,0.0118,0.07332,0.02131,0.00509,-0.0025,-0.05714,0.00725,0.00537,-0.02763,0.03305,0.03243,-0.00322,0.03335,0.04488,-0.05229,0.07813,-0.01036,-0.03542,-0.00142,-0.06693,-0.0292,0.04896,-0.0011,-0.01625,-0.01143,-0.02311,0.00908,0.11544,-0.04593,-0.04909,-0.06649,-0.05525,-0.02147,-0.04933,0.07063,0.04277,0.02732,0.00898,0.06182,-0.04384,-0.02868,0.02999,0.00853,-0.08036,-0.00951,-0.06572,-0.00919,-0.08534,-0.00241,0.01725,0.05238,0.06032,0.02889,-0.0406,0.02554,-0.08791,-0.03497,0.0097,-0.04623,-0.07087,0.03319,-0.0221,0.08217,-0.03227,-0.00778,0.05116,0.08905,-0.09006,0.0267,-0.00599,-0.06748,0.0421,-0.03064,-0.01753,-0.01338,0.06144,-0.0714,-0.06693,-0.00999,0.03158,-0.02221,-0.0958,-0.01668,0.01367,0.00408,-0.00383,0.03281,-0.07183,-0.0511,-0.03844,-0.04228,0.00632,0.02853,0.01954,0.01224,0.00194,-0.06119,0.00041,0.04542,0.08328,-0.06151,-0.0072,0.03943,0.0053,0.11335,0.06885,0.0951,-0.02527,-0.04176,0.09498,-0.05573,-0.02218,-0.00233,-0.02947,-0.06422,-0.0096,0.0297,-0.05228,0.00074,0.03625,-0.05008,0.02146,0.00204,-0.02098,-0.0159,-0.049,0.02144,0.0422,-0.05676,-0.03933,0.04057,0.04913,0.04886,-0.04786,-0.03259,-0.06933,-0.01327,-0.09548,0.06877,0.01182,-0.01795,0.05264,-0.05293,0.02062,-0.00793,-0.03853,-0.06688,-0.02853,0.05196,-0.04948,-0.00778,0.07967,0.01044,-0.00174,0.03498,-0.0632,0.02984,0.05011,0.05274,0.02638,0.0122,0.02049,-0.00277,-0.03532,0.04008,-0.01316,0.08588,0.02209,0.09579,-0.00065,0.06915,-0.02217,0.03554,0.00403,0.0647,-0.01352,-0.01066,0.03223,0.00719,0.01987,-0.07185,-0.02457,0.02554,-0.03599,0.03045,0.0184,0.09026,-0.04948,-0.0535,-0.00322,0.0049,0.03394,0.0515,-0.06812,0.08891,-0.00883,0.0813,0.01971,0.02427,-0.06946,-0.08941,0.03694,0.04319,-0.04042,-0.03983,0.02399,-0.01343,-0.00237,0.02264,0.05349,-0.01101,-0.00032,0.03265,-0.00911,-0.03757,0.05261,0.03233,0.02632,0.0411,-0.01688,-0.0112,0.02604,-0.08294,-0.04844,-0.00542,-0.01598,-0.0165,0.06868,-0.03192,-0.00122,0.03879,-0.01879,0.01322,0.02547,0.0004,0.02253,-0.05177,-0.07333,-0.00644],"lawyer/memo":[0.06211,-0.03409,-0.03925,0.03557,0.03412,-0.01118,-0.03776,-0.00265,-0.03499,0.00221,-0.05062,-0.08461,-0.00061,0.01611,-0.08576,-0.06962,0.00291,0.00221,0.01823,0.20368,-0.04006,0.04677,0.06332,-0.02072,0.08079,-0.00464,0.04089,0.01671,-0.04158,0.06501,-0.09132,0.03368,0.01191,0.04257,0.00486,0.05109,0.02703,-0.06293,0.04268,-0.01471,0.01297,0.03792,-0.01666,-0.01496,0.03755,0.00125,0.06592,0.0268,0.0818,0.02226,-0.02299,-0.0022,0.06618,0.02985,0.0674,-0.00916,0.01813,-0.03767,0.01964,0.00639,-0.00249,0.03793,0.00378,0.03612,0.02933,0.03976,0.00129,-0.01504,-0.03322,0.00253,-0.05165,0.00802,-0.00792,0.04295,-0.07733,0.01607,0.00583,0.02331,-0.03614,-0.01123,0.02998,-0.08656,0.02316,0.05068,0.12085,-0.00286,-0.00859,0.08385,0.06535,-0.01443,-0.0191,-0.00662,0.00978,0.01418,-0.00197,-0.04618,-0.01604,-0.00957,-0.11594,0.00223,-0.01265,-0.06952,0.05237,-0.0086,0.0383,-0.0171,0.05753,-0.01679,0.07987,-0.02031,0.07367,0.05002,-0.03498,-0.00197,0.04922,0.03167,-0.03737,-0.00395,0.10272,0.00447,-0.00816,0.02714,0.00327,0.03128,0.01673,0.00978,0.0406,0.01545,0.05834,-0.00124,-0.01091,-0.0483,-0.00193,0.01282,-0.08811,0.02181,-0.05144,-0.07224,-0.17905,0.01572,-0.04823,-0.03183,-0.01869,0.01686,0.0141,0.02156,-0.0161,-0.03783,0.02015,0.01091,0.0298,-0.10603,-0.12114,0.00269,0.02166,0.01667,0.03334,-0.03723,-0.03294,-0.02195,-0.02453,-0.02377,0.02192,0.01132,-0.00676,-0.01885,-0.05752,-0.06092,0.00875,0.01853,-0.03914,0.10151,-0.07669,-0.00485,-0.02586,0.05751,-0.07755,-0.01696,-0.0665,0.06057,-0.04545,-0.0593,0.03948,-0.01092,0.01344,-0.01745,-0.08115,-0.01254,0.07272,0.01984,-0.00218,0.02434,-0.0103,-0.01951,-0.03253,0.00821,-0.05322,-0.01507,-0.03686,0.01666,0.05136,0.02147,-0.00628,0.01968,0.02095,-0.00151,0.01887,-0.00823,0.07426,-0.04467,0.07599,-0.02802,-0.0458,-0.01695,-0.00222,-0.06214,-0.00314,-0.03301,0.00834,0.05313,-0.0652,0.00381,0.03404,-0.02151,0.01395,-0.0314,0.00554,0.00272,0.03585,0.01755,-0.00239,0.02709,0.0405,0.00129,-0.02884,0.01831,0.08018,0.10146,-0.0336,0.03123,0.02338,-0.04583,-0.01584,-0.03806,-0.02239,0.03363,0.05624,0.03858,-0.04325,-0.06782,-0.00963,0.02475,-0.0335,-0.01957,-0.00133,0.00332,0.08711,0.00952,0.01651,0.01704,-0.14637,0.02107,0.06257,0.07376,0.02545,-0.10013,0.02625,0.00776,0.0699,-0.02745,-0.0192,0.00815,0.00506,-0.03016,0.01543,-0.02441,-0.03591,-0.00499,-0.0392,0.05609,0.04825,0.02853,0.01732,-0.0066,0.02075,0.0094,-0.03348,0.00741,-0.04835,-0.01859,-0.00498,0.05745,0.01964,0.01352,0.04793,-0.04501,-0.05668,0.00612,0.05782,-0.00051,-0.05404,-0.0259,-0.04762,-0.0265,-0.0211,0.02733,-0.03185,0.03983,-0.03188,0.03248,0.0248,0.12448,-0.00946,-0.0653,-0.01904,-0.02461,-0.05694,0.00428,-0.08375,0.01673,-0.02647,-0.00142,-0.00038,0.03277,0.07917,0.05521,-0.01701,0.00579,0.00795,-0.04004,-0.01089,-0.01922,0.01072,0.01416,-0.00893,-0.0477,-0.00037,-0.00545,0.00516,0.02518,-0.09008,-0.00244,0.0294,-0.01777,0.04649,-0.05185,0.01387,0.00396,0.02207,-0.06354,0.06606,0.00419,0.07482,-0.05551,-0.10355,-0.03584,0.01626,0.01608,-0.00894,0.02374,0.04387,0.02527,0.02621,0.00524,0.03272,0.06205,0.0125,0.0148,0.0004,-0.0014,0.00564,-0.02872,-0.02913,0.02804,0.00765,-0.02645,0.01771,0.02353,0.09189,0.02275,-0.06879,-0.08121,0.02738,-0.05086,0.03112,-0.00807,-0.00931,0.01367,0.05624,-0.01553,-0.03459,0.06227,-0.03067,-0.06807,-0.03802,-0.01936,-0.02746,-0.02158,0.01933,-0.02516,0.00999,0.0026,-0.02411,-0.04758,-0.02535,0.04611,-0.05467,-0.03052,-0.08769,-0.01212,0.0053,0.02499,0.02983,0.0142,0.09264,-0.05152,-0.02044,-0.01211,-0.05087,-0.0064,-0.00697,0.06762,-0.08557,-0.05071,0.01587,0.04328,-0.04508,0.05978,-0.00993,-0.00712,0.04341,0.01368,-0.02047,-0.01395,0.02807,0.09792,-0.04583,-0.00879,0.00384,0.02924,0.06253,0.06437,-0.03894,-0.0014,-0.06484,0.07044,-0.01198,0.07489,-0.09663,-0.00205,-0.04047,-0.00684,-0.01984,-0.11394,-0.04588,0.0279,-0.00396,0.00256,-0.00695,0.06966,0.06288,-0.08172,0.0365,0.02615,0.01468,0.02311,-0.01757,-0.03811,0.02541,0.09641,-0.03515,0.02909,-0.10033,0.09604,-0.04437,-0.10297,-0.04416,-0.01854,0.03206,-0.01417,0.01108,-0.0176,0.00345,-0.0356,-0.00692,-0.0461,-0.02123,-0.02828,0.11304,-0.00724,0.01538,0.01236,0.05562,0.00224,-0.00047,-0.00194,-0.07453,-0.03145,0.03458,-0.03488,0.03465,-0.04094,0.01816,0.07511,-0.0261,0.00402,0.02183,-0.03245,0.01155,0.04952,0.00545,-0.01012],"lawyer/draft":[-0.02658,-0.09933,-0.01579,0.03596,0.06595,-0.04323,-0.11002,0.00372,-0.02194,-0.04509,-0.0396,-0.01907,-0.00667,0.00053,0.01128,0.01101,0.06027,0.01687,0.00454,0.03399,-0.062,0.0463,-0.01947,-0.00214,-0.03397,-0.00949,0.06895,0.02038,0.05255,0.01131,-0.03081,0.01635,0.00145,0.01408,-0.09402,-0.02358,-0.01108,-0.10334,0.0345,-0.0078,-0.01823,0.05067,0.0222,-0.04212,-0.03008,0.01775,0.04116,-0.05051,0.09056,0.01453,-0.04213,-0.01065,-0.01326,0.00053,0.04307,0.03406,0.012,-0.01268,0.08263,-0.01164,0.10451,0.0502,-0.02407,0.02421,-0.00663,-0.02493,-0.06854,-0.00973,0.03456,-0.01636,-0.00912,0.03661,0.04352,0.03788,-0.03802,-0.03977,-0.00094,0.05176,0.05269,-0.03179,-0.04762,-0.0599,0.01282,-0.01787,0.03686,0.04302,-0.04571,0.07249,0.01048,0.0193,0.0759,-0.01303,0.01828,0.02736,-0.00813,-0.02951,0.02901,0.02358,-0.02386,-0.01924,0.11087,-0.0357,0.01628,-0.01491,-0.00953,-0.06318,-0.01798,-0.03716,0.0387,0.04337,0.03033,0.04923,0.04714,0.01571,0.01074,-0.00014,-0.0472,-0.03899,0.10324,-0.0529,0.03983,0.02232,-0.02841,-0.07368,-0.00606,-0.09845,-0.01047,-0.01796,-0.02151,-0.02511,0.02548,0.08161,-0.01789,-0.05508,-0.07579,0.01481,0.00943,-0.01222,-0.03204,-0.00509,-0.06817,0.04208,0.01066,0.13606,0.01708,-0.01392,-0.02564,0.0073,0.02811,-0.03432,0.05024,-0.07129,0.00643,0.07192,-0.00069,0.02004,-0.00808,-0.04865,-0.01822,0.04522,-0.02963,-0.05716,0.05401,-0.02205,-0.01932,-0.06009,0.01748,-0.01811,-0.01147,-0.02089,-0.11247,0.05562,-0.10084,0.01768,-0.02302,0.02623,-0.06529,0.05419,-0.021,0.10486,-0.0096,-0.03618,0.02329,-0.0401,-0.0177,-0.02709,0.00655,-0.04114,0.02296,0.03507,0.01201,0.0556,-0.00176,-0.00338,-0.00775,0.03539,-0.01493,-0.01494,-0.07657,0.03937,0.00279,-0.02087,-0.07266,-0.01012,-0.07453,-0.07803,0.00995,-0.0149,-0.0171,-0.09864,0.06155,0.03852,-0.01802,0.01198,0.02081,0.008,0.01711,-0.06979,-0.04354,0.04778,-0.03593,0.04816,0.01389,0.0023,0.05195,0.01482,-0.06016,0.08392,-0.03988,0.08491,0.03545,-0.00314,0.05648,0.01589,-0.0451,0.02075,0.02237,0.04218,0.03016,0.03316,-0.02096,-0.06525,-0.06195,-0.05086,-0.02233,0.02302,0.06919,0.00546,-0.10329,-0.01858,-0.0585,0.03004,-0.05144,-0.003,-0.05566,0.04797,0.05714,-0.00303,-0.01608,0.00732,-0.08493,-0.01863,0.07834,0.00633,0.02176,-0.02362,-0.08517,0.05781,0.05011,0.03646,-0.02725,-0.00655,-0.00671,-0.05444,0.03251,0.02481,-0.01921,-0.01204,-0.0594,0.06235,0.04908,0.00018,0.00596,0.04968,0.01972,0.0061,0.03543,-0.02519,0.08983,0.01182,0.01279,-0.0897,-0.00225,0.04086,0.00906,-0.01591,-0.04223,0.00668,-0.02925,-0.01002,0.06313,-0.02868,-0.05413,-0.06446,-0.02866,-0.01308,0.02269,0.10434,-0.00868,-0.01005,-0.02367,0.05099,-0.02707,-0.01258,0.02335,0.01472,-0.03263,-0.05488,-0.10841,-0.05534,-0.03669,0.01677,-0.0274,0.07021,0.10337,0.04236,-0.0353,0.01172,-0.03065,-0.01851,0.00815,-0.02487,-0.06511,0.00083,-0.00692,0.03073,-0.07743,-0.03668,0.04826,0.05168,-0.05333,0.00787,0.00569,-0.07581,0.05347,-0.0232,-0.066,-0.01532,0.01299,-0.02178,0.02417,0.0088,-0.01385,0.03655,-0.06444,-0.02991,-0.01861,0.03228,-0.01167,0.03557,-0.00674,-0.00804,-0.03559,-0.00158,0.02191,0.02119,-0.01506,0.00031,-0.00445,-0.02572,0.01228,0.06025,0.02674,-0.06952,-0.07986,0.03361,-0.01425,0.0759,0.05184,0.00039,-0.04913,-0.04571,0.10992,-0.01603,0.00337,0.01703,-0.07656,0.01684,0.02117,-0.03303,0.06087,-0.01062,0.01142,-0.03709,-0.01061,-0.07464,-0.00648,-0.01475,0.00463,-0.00516,0.04685,-0.07226,0.01814,0.05157,0.01373,0.01947,-0.01186,-0.00534,-0.08303,-0.03711,-0.06622,0.02005,0.04984,-0.00626,0.02791,0.05152,0.08807,-0.01047,-0.02724,-0.03836,-0.00072,0.072,-0.05202,-0.02532,0.02294,0.00429,0.03913,0.00111,-0.04224,-0.02387,0.03679,-0.01694,-0.02221,-0.03119,-0.00351,0.02394,-0.02415,0.03799,-0.01979,0.05837,0.07846,0.0816,-0.02408,0.02815,-0.05266,0.05103,0.00027,0.02284,0.05022,-0.04001,0.06793,0.07336,0.01344,-0.03165,-0.01549,-0.00296,-0.00626,0.04606,0.0361,0.0637,0.0559,-0.02908,-0.05107,-0.01535,0.05955,0.03481,-0.12995,0.05219,0.0208,0.11898,0.01408,0.02146,-0.09261,-0.03215,0.05472,0.0735,-0.05616,-0.04458,-0.02447,-0.03356,-0.04916,0.02923,0.03523,-0.01751,0.02564,-0.00401,0.05813,0.03349,0.11816,0.01933,0.02213,0.05341,-0.00756,0.00199,0.06067,-0.02508,-0.08048,-0.00854,-0.03218,-0.03217,0.03074,-0.03859,0.05283,0.03878,0.00744,0.05404,0.05101,-0.03873,0.04391,0.03283,-0.06924,0.01974],"marketer/write-content":[0.01069,-0.0063,-0.04356,-0.02418,0.01029,-0.01521,-0.03858,0.00191,-0.06579,-0.01015,0.02996,-0.06028,0.00285,-0.04361,0.03904,-0.04474,-0.02797,0.01545,-0.01203,-0.04192,0.00286,-0.01691,0.0029,-0.0046,0.04187,0.00603,0.04838,0.00652,-0.03026,-0.01357,-0.06005,-0.02202,-0.03686,0.03052,0.05758,0.03992,0.03714,-0.00574,0.08377,0.06399,-0.03105,0.05524,0.02836,0.0389,-0.03176,-0.00109,-0.0423,0.04716,0.03418,0.04397,-0.09453,0.10337,0.02391,-0.03192,-0.01434,-0.01959,-0.0176,0.03738,0.03966,0.00648,0.07432,-0.03272,-0.06612,-0.04344,0.05925,-0.00327,0.0633,0.03187,-0.01545,0.00245,-0.01877,-0.01953,0.03609,0.07462,-0.06792,0.01219,0.04064,0.02181,-0.01744,-0.00847,0.00684,-0.04396,0.03011,-0.05879,-0.01353,-0.03998,0.02095,0.00249,0.06553,-0.04449,0.09636,-0.07113,0.0446,0.05987,0.0139,0.00138,0.04872,-0.00572,-0.01023,-0.0652,0.02811,-0.05232,0.04041,-0.04256,0.08261,0.02854,0.04226,-0.02595,0.02692,-0.02617,0.02013,-0.05999,0.00518,0.0496,-0.05388,0.03323,0.05036,0.07943,0.02108,0.00874,0.02835,0.03495,0.03333,-0.05454,0.02983,-0.00252,0.04127,-0.023,-0.03494,0.07025,-0.00749,0.03232,-0.00938,-0.06213,0.02986,-0.02355,0.01684,-0.0418,0.06819,-0.02688,0.04364,-0.0325,0.06296,0.03254,-0.03707,-0.05087,0.0203,0.02516,0.02286,0.06858,0.03062,-0.04823,0.03707,-0.01265,0.0612,0.05789,0.06985,-0.00919,0.06852,-0.00061,0.0611,-0.05227,-0.02196,0.03733,-0.02127,0.09079,-0.00028,-0.06314,-0.02384,0.0071,-0.06592,0.04425,-0.07193,0.0485,-0.02161,-0.03584,-0.02232,-0.00692,0.04541,-0.03281,0.00764,-0.00825,-0.0403,-0.06626,-0.03827,-0.06144,-0.04779,0.03119,-0.01982,0.00209,-0.04085,0.02755,-0.04411,-0.05838,-0.04889,-0.08939,-0.00103,-0.06049,0.04197,-0.00839,0.00163,-0.00003,-0.02363,-0.03066,-0.05794,0.01265,0.00941,0.06216,0.07449,0.03412,-0.02253,-0.02761,0.0738,0.02037,0.10059,0.01711,0.02061,-0.02471,0.01805,-0.00266,-0.08151,-0.01873,-0.03767,-0.04183,-0.05489,-0.10745,-0.10226,0.06131,0.02618,0.01527,0.02212,0.0024,-0.01097,-0.01538,-0.02215,0.032,0.13466,-0.00091,0.04245,0.0062,0.01969,0.00267,0.01292,-0.01137,0.03971,-0.01012,0.04042,0.05549,-0.05122,0.01988,0.07553,-0.03672,-0.01114,0.01581,0.03358,0.00583,0.08487,-0.05789,-0.03482,0.01525,0.00594,0.03805,0.01821,0.04461,-0.02873,-0.01794,0.0133,0.08106,-0.0089,0.00881,-0.06844,0.01206,0.0276,0.00273,0.01,-0.05189,0.00853,-0.06417,-0.04182,-0.05852,0.05338,0.00854,0.05638,0.01446,0.00471,0.00926,-0.03134,0.03011,-0.01874,-0.05917,0.04492,-0.05164,-0.03088,0.0026,0.03956,0.04231,0.00847,0.05344,0.05777,-0.04368,-0.03632,-0.02277,-0.05038,0.05046,-0.04456,-0.02014,0.04693,0.00887,0.00458,-0.01383,0.00066,0.02057,-0.11519,-0.0782,0.07895,-0.04987,-0.04591,0.09342,-0.02011,0.03252,0.0096,-0.03035,0.05028,-0.01131,0.07117,0.05754,-0.07737,0.01393,-0.02763,0.03082,-0.06886,-0.01448,0.04575,0.04531,0.00154,-0.09402,-0.08568,-0.06935,-0.0051,0.06808,-0.11825,0.0421,0.05304,-0.00141,0.07756,-0.01152,-0.00617,-0.0876,0.0538,-0.04229,-0.04195,-0.00313,-0.11377,0.00512,-0.04282,0.00428,-0.06,-0.05747,0.03503,0.05456,0.03215,0.02769,0.03361,0.0483,-0.00728,-0.00218,0.04743,-0.03914,0.01311,0.00445,-0.03901,-0.01795,0.05203,0.03552,0.0215,-0.02914,-0.04742,0.05866,0.04438,0.05955,0.0566,-0.00696,0.0418,-0.02115,0.03125,0.01177,0.01681,0.06066,0.01946,-0.04032,0.01794,-0.0541,-0.07858,0.05657,-0.04067,-0.02998,-0.0284,0.04692,0.01696,0.01871,0.0215,0.0461,-0.06747,-0.01771,-0.031,0.04399,-0.05274,-0.02679,-0.00845,-0.00315,-0.00479,0.01609,0.01181,0.01447,-0.01507,0.00496,0.03565,0.00879,-0.0338,-0.01484,0.07337,0.04676,0.06064,-0.06631,0.0196,-0.01168,0.0375,0.04268,-0.00961,0.05925,-0.00705,-0.05198,-0.04604,0.05522,0.04177,0.05484,0.04125,0.01479,0.00906,0.0165,0.04057,0.08242,0.03022,0.01206,0.03577,0.06438,0.05537,0.09954,0.04218,-0.07067,-0.02488,0.00152,-0.01072,0.02054,-0.09804,0.0352,-0.01322,-0.01802,0.0163,0.02802,-0.02584,-0.00625,0.01086,0.01191,-0.00539,0.0366,-0.01427,0.10106,0.07594,-0.00924,-0.06219,-0.09722,0.00568,0.09519,-0.00584,-0.01163,0.01968,-0.07878,0.03448,0.04194,-0.03282,-0.05258,-0.00839,-0.01254,0.00642,-0.04106,0.01315,0.0083,0.04031,0.01262,0.00364,0.00965,-0.03374,-0.06748,-0.02078,-0.01192,-0.1885,-0.03112,0.06179,-0.01447,0.08372,-0.03838,0.00524,0.01621,0.00686,0.02387,0.01033,-0.04796,0.00652,0.04181,-0.02685,0.05487],"marketer/plan-campaigns":[-0.00291,-0.06301,-0.00083,0.01969,0.03456,-0.00746,-0.01526,0.06688,-0.04265,-0.00936,0.02531,0.05713,-0.07656,0.02574,0.04755,-0.00453,0.10844,-0.01725,0.02473,-0.05181,0.0059,-0.03498,0.02316,0.01559,-0.0031,0.01469,0.05203,-0.00967,0.01421,-0.02926,-0.06706,0.02469,0.00367,0.00314,-0.03087,-0.0168,0.00423,0.07843,0.01049,-0.00234,0.02371,-0.05163,-0.01738,0.03505,-0.03111,-0.00997,-0.086,-0.03049,0.04162,0.01923,-0.0443,-0.00578,0.07173,-0.05189,0.05698,-0.00561,0.00406,-0.02561,-0.00524,-0.01003,0.05029,-0.05133,0.00604,0.08941,0.04486,-0.05916,-0.02445,0.01601,-0.01751,-0.00822,-0.04814,-0.03014,0.08733,0.0018,-0.01124,-0.07423,0.04255,0.08315,0.07969,0.02603,0.05783,-0.05659,0.0289,-0.01942,0.01892,0.01936,-0.01874,-0.01725,0.02079,0.05198,-0.06915,-0.06979,0.01522,-0.01979,0.00447,-0.05995,0.07687,0.01174,-0.00436,0.01515,0.08805,-0.01107,0.04918,-0.03026,0.00079,-0.01494,0.01504,-0.06438,0.04374,0.01716,-0.0053,0.00742,-0.00375,0.00499,0.02572,-0.02664,-0.10422,0.02548,0.02337,-0.01662,0.12948,0.00143,-0.03265,-0.02803,-0.01267,-0.01493,-0.00668,-0.04431,-0.03565,0.0782,0.05926,0.00632,-0.08599,0.06264,-0.00177,0.00055,-0.05752,-0.01432,0.12594,-0.0005,-0.02672,0.00882,0.04011,0.06164,-0.01368,-0.03956,-0.00061,0.01019,0.02359,-0.00425,-0.00603,-0.0532,-0.02525,0.03299,-0.06317,0.05787,0.03171,0.06773,0.00427,0.03737,-0.04936,-0.04661,0.06574,-0.02375,-0.03674,0.0652,0.01084,-0.01662,0.00212,-0.09052,-0.07707,0.01334,-0.06503,0.01097,0.02318,-0.05173,0.01615,0.07106,-0.04667,-0.04598,-0.09267,-0.01488,0.01536,0.00576,0.00603,0.01752,-0.01252,0.01313,0.04187,0.03825,0.0397,0.07363,-0.05484,0.03724,-0.02124,-0.02511,0.01305,0.00575,0.073,-0.01732,0.02682,-0.00898,-0.01736,-0.03761,0.00157,0.04509,0.01547,-0.03026,0.0415,-0.05488,0.0106,0.05095,0.01566,0.05557,0.08101,-0.0217,0.05287,0.02427,-0.00272,-0.00119,-0.04769,-0.04561,0.02248,-0.03834,0.04519,-0.0087,0.01015,0.03938,-0.04146,-0.00445,0.01481,0.02997,0.04142,-0.07944,-0.05509,0.02032,0.04192,-0.06131,0.06834,0.00991,-0.00791,-0.05022,-0.00624,0.04319,0.10044,0.00766,0.04764,-0.06872,-0.04882,0.02092,-0.00457,0.0544,-0.01109,-0.0014,-0.05831,-0.02485,-0.00041,-0.02985,-0.00436,0.11131,0.03379,-0.00755,0.00519,0.02703,0.05699,-0.0409,0.03122,0.05436,0.05344,-0.06316,-0.00779,-0.04005,0.03353,0.00914,0.09342,-0.01722,-0.00738,-0.03955,-0.03845,0.01991,-0.04765,0.0807,0.00774,0.03539,0.0312,0.01591,-0.02341,0.00506,0.14967,0.04945,0.03911,-0.08978,0.06611,0.03668,0.01811,-0.00227,-0.01175,0.05876,0.07474,-0.02546,0.059,-0.0938,-0.10327,0.01305,-0.04158,0.04478,0.00411,-0.00846,-0.04953,0.00494,-0.06133,0.00742,-0.00374,0.01829,-0.00671,0.0248,-0.00741,0.02874,-0.03152,-0.04828,0.0333,-0.04978,-0.02456,0.01366,0.07601,0.02371,-0.01503,0.06411,-0.06288,-0.08502,-0.04061,-0.00688,0.01984,-0.03696,-0.07562,0,-0.04252,0.01078,0.08342,0.01955,0.01562,-0.00221,-0.0215,-0.00436,0.02161,0.04219,0.04521,0.02387,0.05629,-0.04007,0.02156,-0.01691,-0.02594,0.02206,-0.02528,0.00839,0.03312,0.00387,0.04734,0.01165,0.03584,0.03334,0.06254,-0.06864,-0.06045,0.02131,0.01838,-0.07663,-0.00619,-0.01792,0.00155,0.03479,-0.03524,0.02301,0.02249,-0.04362,-0.04912,0.01164,0.02335,-0.02945,-0.01283,0.06548,0.02399,0.05554,0.03756,0.02222,0.03949,0.11544,-0.07789,0.06157,-0.06384,-0.0143,-0.02065,0.01303,0.11198,0.02312,-0.00354,-0.02809,0.01317,-0.03244,0.02289,-0.03929,-0.08476,-0.03136,0.04167,-0.01154,-0.00121,-0.07633,-0.0209,-0.02908,-0.03306,0.03114,0.00005,-0.03299,-0.03594,-0.04405,0.01105,0.04354,0.02421,0.04202,0.04628,0.07904,-0.07458,-0.0103,0.0088,-0.02333,0.02255,0.04945,0.00468,0.03536,-0.09787,-0.02764,-0.05631,0.05347,0.12479,0.00466,0.03297,0.05408,0.05662,0.07694,0.06253,0.08411,0.03475,0.03107,-0.00785,0.00504,0.05515,0.0005,-0.03609,-0.0677,0.01245,0.07014,-0.00199,0.00052,-0.0101,-0.04631,0.0105,0.02024,0.0103,0.00307,0.09321,0.00154,-0.07168,-0.07064,-0.0033,0.05821,-0.02697,0.01385,0.00991,0.00507,-0.06648,-0.036,-0.04132,-0.0077,-0.0089,0.02575,0.07739,0.02685,0.04911,0.05617,-0.05008,0.00053,0.05236,0.02569,0.02256,-0.04587,0.02096,0.02512,0.1163,0.0221,0.02357,0.0113,0.0212,0.00713,-0.01152,-0.06577,-0.02801,-0.02516,-0.0462,-0.02091,0.03679,0.07829,0.00231,0.02888,0.04436,0.0896,-0.03403,-0.08083,0.04112,0.02073,-0.09724,0.0037],"marketer/run-messaging-campaigns":[-0.00518,-0.02231,-0.03257,-0.00492,0.04077,-0.02105,0.02272,0.02603,0.0094,-0.03161,-0.01783,0.01067,0.03852,0.00308,-0.01613,-0.05361,0.01629,-0.01597,-0.00167,-0.0181,-0.03756,-0.01222,0.03354,0.01397,-0.00562,0.04074,0.01115,-0.02713,0.05133,-0.02048,-0.05893,-0.07199,-0.00639,-0.0008,-0.00504,0.07224,-0.01804,0.0882,0.0245,-0.00633,-0.00864,0.00817,0.00071,-0.01441,0.00194,0.04394,0.03,-0.0146,0.11261,0.04748,0.01108,0.04664,0.02547,0.00047,-0.00559,-0.03296,-0.01611,-0.0119,-0.02549,-0.00919,-0.01764,-0.05541,0.00133,0.01856,0.0643,-0.01184,0.00642,0.01026,-0.07455,-0.00297,-0.04669,0.0067,-0.00013,0.08196,-0.06617,-0.05491,0.03154,-0.01314,0.01328,-0.0301,0.06571,-0.0453,0.03622,-0.10377,0.02212,-0.03909,-0.03366,-0.01942,0.02519,0.03708,0.03041,-0.08501,0.04363,0.01643,-0.00473,-0.08559,0.04808,-0.01311,0.00594,0.00624,0.02036,-0.09493,-0.00163,-0.02037,0.08181,-0.0346,0.06454,-0.06504,0.0195,0.07187,0.03387,0.00978,0.05155,0.05079,0.04895,0.01893,-0.0004,-0.05927,0.05945,-0.04927,0.03444,0.02943,-0.01018,-0.02448,-0.01858,0.05919,0.02418,-0.06647,-0.05017,0.06612,0.0762,-0.00923,-0.05762,-0.09357,0.04521,0.01797,-0.06776,-0.02689,0.0586,0.01146,-0.025,-0.03635,0.06841,-0.01417,-0.02698,-0.1045,-0.04072,0.04273,-0.00455,0.01221,-0.00912,-0.00835,0.00844,-0.0304,0.02247,-0.0066,0.01713,0.01438,0.04039,0.08243,-0.10947,-0.06135,-0.02058,0.01265,-0.04666,-0.02104,-0.00097,-0.0327,0.03374,-0.12174,-0.07066,-0.00574,-0.10106,0.02186,-0.06215,0.01736,-0.01869,0.0042,-0.05094,-0.01951,-0.04854,-0.02688,-0.0445,0.02808,-0.00711,0.00911,-0.05965,0.00807,0.04245,0.04645,0.02355,0.00128,-0.06252,-0.01988,-0.02916,-0.09134,0.0539,0.0396,0.0069,0.03818,-0.04423,0.02692,-0.03203,-0.02766,-0.14784,0.05882,-0.01309,-0.03082,0.02091,-0.02906,0.03476,0.00548,0.04221,0.03887,0.04008,-0.07476,0.04588,-0.06783,-0.00875,0.07099,0.01956,0.00004,0.07517,-0.04809,0.02277,-0.0137,-0.01823,0.0216,0.09318,0.02877,0.0251,0.0031,-0.01903,-0.00243,-0.05727,-0.01982,0.0544,-0.04523,0.05919,0.022,0.01477,-0.0411,0.02199,-0.0194,0.04144,0.00956,-0.02233,-0.0698,0.00699,-0.00513,-0.08428,-0.00603,0.02342,-0.0079,0.06086,0.0282,0.03258,-0.02909,-0.02136,0.04254,-0.13011,0.00795,-0.00781,0.00297,0.01263,-0.01729,-0.00346,-0.01527,0.01353,-0.09216,-0.04102,0.00077,0.06924,-0.02884,-0.03817,-0.04824,0.02878,0.00832,-0.04769,0.02819,0.05193,0.05179,-0.01002,0.00945,0.10483,0.03459,-0.01814,-0.0109,-0.01721,-0.02349,0.06805,-0.0666,0.0416,-0.00057,0.04758,0.00087,0.01104,0.03633,0.0223,0.00571,0.02622,-0.04403,0.0213,0.04238,-0.04773,0.0139,0.02714,0.05172,0.01244,-0.03167,0.04884,0.03933,-0.12399,0.02801,0.10541,-0.00856,0.00613,0.05164,-0.02253,-0.01159,0.03947,0.00816,0.04321,-0.01266,0.07854,0.06474,0.02082,0.03286,-0.02384,-0.01548,-0.10054,-0.0035,0.0114,-0.00908,-0.02187,-0.04245,-0.00263,-0.0365,0.05415,0.01172,-0.0164,-0.02218,-0.06334,-0.01864,0.03491,0.06947,-0.02982,-0.02206,0.03736,-0.06759,0.04819,0.00111,-0.02206,0.07074,-0.04425,-0.03226,-0.03091,-0.01174,0.00639,0.02235,0.01069,0.01415,0.18269,-0.03663,0.03202,0.04155,0.05128,-0.04644,0.0079,0.03876,-0.04791,0.00624,-0.0215,-0.00942,0.01024,-0.03552,-0.02964,0.03831,0.06771,0.06575,-0.02638,0.04729,-0.01463,-0.02157,0.00874,0.02516,-0.02802,0.04253,-0.1134,-0.0389,0.00153,-0.01121,0.03455,-0.05283,-0.08651,0.0165,-0.00502,-0.05278,-0.0083,-0.00952,0.06231,0.06837,-0.05945,-0.03098,0.0154,0.03156,0.0005,0.00171,-0.03128,0.03419,-0.02918,0.00002,0.05714,-0.0352,0.0635,-0.04324,-0.02205,0.01231,-0.03551,0.0385,0.06173,0.06226,-0.04049,-0.03931,-0.02222,0.06022,0.06217,0.02607,0.00043,0.08934,-0.03589,-0.00232,-0.00494,0.01275,0.0771,0.06794,0.08412,0.05227,0.08621,0.03224,-0.04499,0.08196,0.02903,0.03951,0.0464,0.01777,0.04832,-0.00099,-0.02405,0.01139,0.0266,-0.00305,-0.00967,0.03043,-0.06208,0.058,0.00086,-0.07627,0.02887,0.0997,0.00526,0.03434,-0.05971,0.01739,0.06366,0.0318,-0.06305,0.06811,0.0055,0.01575,-0.00244,0.0096,0.00032,0.02305,0.03872,0.00031,-0.03401,-0.03947,0.07407,0.08095,-0.07635,-0.00378,-0.01695,0.04986,0.03581,-0.00433,0.00933,0.01938,0.10481,0.00341,-0.05515,0.03998,-0.01427,-0.0331,0.029,-0.11062,-0.06909,-0.01455,0.004,-0.00854,0.06848,-0.01539,0.0456,0.00967,-0.04482,-0.00541,0.02825,-0.05458,0.02274,0.08425,0.03674,0.03789],"marketer/analyze-campaigns":[-0.07111,-0.02635,-0.04851,0.02686,0.02638,-0.01343,0.03928,-0.06097,-0.01815,-0.01822,-0.03495,-0.01416,-0.0043,-0.01273,0.08011,-0.0062,0.0746,0.01557,0.01389,-0.01406,-0.04952,0.02002,-0.05102,-0.03101,-0.01116,-0.04091,0.02631,0.03781,-0.03144,-0.00081,-0.02957,0.02308,-0.01805,-0.01468,0.00856,0.03431,-0.02183,-0.00693,0.07236,0.03864,0.02398,-0.01885,-0.03532,-0.00751,-0.04116,-0.01604,-0.06161,-0.02365,0.05993,0.05822,-0.02433,0.00174,0.02279,0.02702,-0.0225,-0.0059,0.05043,-0.02125,0.01577,-0.01694,-0.00215,-0.08013,0.04158,0.06284,-0.0507,-0.05386,-0.02006,-0.02799,-0.1941,-0.02244,0.01721,-0.03371,0.07402,0.0082,-0.07317,-0.09329,-0.03601,0.04564,-0.01797,-0.02354,0.03668,-0.00471,0.0356,-0.04769,0.02806,-0.01976,0.00462,-0.06182,0.03167,0.11844,-0.03156,-0.03684,-0.02595,-0.01265,-0.02975,-0.02865,-0.00501,-0.00803,-0.00779,-0.04458,0.01536,0.02275,0.06055,-0.07144,-0.01932,-0.00285,0.01736,-0.07919,0.07406,0.03196,-0.01838,-0.01305,-0.01439,-0.04551,0.02077,0.01183,0.03624,-0.02963,0.02345,-0.04881,0.01327,-0.00467,-0.00721,0.00844,-0.01139,0.00466,0.05729,-0.06734,-0.03494,0.07062,0.02781,-0.0872,-0.06409,0.02414,-0.01788,-0.0012,0.0136,0.02051,0.03567,-0.00421,-0.06111,0.05711,-0.04215,0.01857,-0.03895,-0.02734,-0.00589,0.02846,0.00925,-0.06548,-0.01886,0.00656,0.09789,-0.06972,0.03798,-0.01181,0.07784,0.05701,0.00572,0.00415,0.01398,0.0274,0.01567,-0.03028,0.00965,0.06297,-0.06024,-0.0141,0.01823,0.02668,-0.04428,-0.0104,-0.06822,-0.08242,0.06279,-0.00126,-0.04249,0.03386,-0.01096,-0.00381,-0.00377,-0.04925,0.00443,-0.02694,0.05638,0.00281,0.00303,-0.01241,0.0138,0.09133,0.02609,-0.00071,-0.02094,-0.04887,-0.03548,-0.01854,0.04515,-0.01396,0.07387,-0.09197,-0.05834,-0.02028,-0.05187,-0.03051,-0.03357,0.00054,0.03666,-0.00214,0.05918,0.00619,-0.01086,0.04931,0.08436,0.02058,-0.04646,-0.07648,0.01358,-0.03794,-0.01251,-0.04155,-0.05808,-0.03956,0.09311,0.02858,0.01341,-0.00109,-0.0198,-0.05402,-0.05331,0.05813,0.00867,0.02969,-0.01492,-0.11517,-0.03794,-0.06376,0.00667,-0.02582,0.04056,-0.02466,-0.04307,-0.05072,-0.00426,0.0414,0.04303,-0.00698,0.0393,-0.02796,-0.03307,-0.06481,-0.06372,0.04967,0.0325,0.00768,-0.00545,-0.03174,-0.03293,-0.00688,-0.00524,0.08233,0.00884,0.02485,-0.04818,-0.04132,0.01265,-0.07335,0.03332,-0.05342,0.0267,-0.03396,-0.05899,-0.01031,-0.00047,-0.01124,0.01001,0.00077,-0.03831,-0.02851,-0.03635,-0.03142,-0.00167,0.01242,0.03993,0.07963,0.05126,0.04913,-0.00397,-0.044,-0.04093,0.02699,-0.01635,-0.08449,0.09451,-0.02314,0.03984,0.00359,-0.02553,0.09068,-0.06559,-0.01995,0.08226,0.05618,-0.05591,0.04082,-0.01862,-0.00238,-0.00709,0.01367,0.07257,0.02781,0.04027,0.13997,-0.01177,-0.00705,0.07106,-0.02066,-0.0384,0.03019,-0.03026,0.01049,0.02198,-0.03814,0.0383,0.04196,0.07305,0.02258,-0.0208,0.02212,-0.00489,-0.04658,-0.04077,-0.00872,-0.05243,0.00777,-0.00954,0.02724,-0.05069,-0.0358,0.06857,0.01995,-0.06426,0.11139,-0.06438,-0.05635,0.02127,0.01289,0.00754,0.04282,-0.02214,-0.00385,0.01253,0.01584,-0.04609,-0.00834,-0.03298,-0.0223,0.00789,-0.01081,0.04669,0.0276,0.00012,-0.0024,0.05942,-0.01655,0.02095,0.08389,-0.04629,-0.02642,-0.00384,0.02789,-0.05958,0.0546,0.02212,-0.03156,0.12769,-0.05983,-0.04545,-0.01962,0.07136,0.00809,-0.06978,-0.02392,0.09052,0.0354,0.00543,0.06535,-0.0299,0.01609,-0.037,0.0395,0.03955,0.04486,0.01664,-0.04705,0.06358,0.04855,-0.02493,-0.04554,0.02768,0.0074,0.03488,-0.05959,-0.02868,-0.04544,-0.02845,0.02027,-0.02517,-0.03453,0.0044,-0.00464,-0.03227,0.09636,0.05229,-0.01108,-0.04593,-0.05275,-0.0497,0.02781,-0.09282,0.0247,0.11573,0.08569,-0.05685,0.03685,0.01928,0.05447,0.01306,0.0261,0.05186,0.02961,0.07242,0.02854,-0.05185,0.02488,0.05014,0.01023,0.08467,0.00432,-0.00358,0.01232,-0.04027,0.06274,0.02006,0.01168,-0.03659,0.00407,0.05183,0.04859,0.0244,0.02823,-0.02344,0.01594,0.00098,-0.0284,-0.0339,-0.04043,0.06121,0.00616,-0.01881,0.01314,0.04236,-0.01059,-0.00745,-0.04633,-0.01555,0.01849,-0.02926,0.00353,0.03884,-0.04979,-0.0472,0.03754,0.07951,-0.02695,-0.01952,0.04317,0.05176,0.03201,0.09545,0.07188,-0.01534,0.05783,0.01,-0.05126,0.00531,0.0264,0.05814,0.03168,0.1713,0.0291,-0.00376,-0.00533,-0.0159,0.00787,-0.0001,-0.1141,-0.09853,-0.01655,0.07482,0.00182,0.02567,0.01082,0.02354,0.01905,0.08433,0.01811,0.00827,-0.05662,-0.05908,-0.01182,0.06436,-0.03518],"marketer/optimize-search":[-0.02728,0.06199,0.04479,0.0606,0.04818,-0.03918,0.01832,-0.08819,0.0051,-0.04378,-0.03062,-0.00896,0.00557,-0.00241,-0.00343,-0.03833,-0.0051,-0.05098,-0.03046,-0.01776,-0.04154,0.00751,-0.02803,-0.02211,0.03685,-0.01636,-0.06027,0.00994,0.01262,0.01417,-0.07073,0.02591,-0.03509,-0.06966,0.0239,0.04891,0.03468,-0.05788,-0.00788,0.02789,0.0764,-0.02503,-0.06546,-0.03018,0.09153,-0.01819,0.02315,-0.00391,-0.04528,0.05379,0.02695,0.03268,0.00595,-0.00495,0.01887,-0.12871,-0.01689,-0.08502,0.0241,0.01828,0.02467,0.05483,-0.09068,0.02405,-0.00032,-0.02847,0.00505,0.00734,0.05305,0.05304,-0.0825,0.05814,-0.00506,0.06858,-0.08071,-0.04988,-0.01793,-0.04692,-0.06381,0.02913,0.04474,-0.077,0.00463,-0.0097,0.01729,0.0294,-0.0167,0.06451,0.03981,0.02233,0.07096,0.0285,0.06599,0.00737,0.00896,0.00196,0.04076,0.05048,0.038,0.00274,0.00319,0.02623,0.07536,0.0896,0.09492,0.04327,0.01033,-0.08252,0.01361,0.05223,-0.03168,0.042,0.0324,0.02228,0.08425,0.04128,0.00954,0.04019,0.07238,0.07746,-0.00211,0.03325,-0.04154,0.02133,0.05865,-0.03426,-0.05809,-0.05209,-0.00229,-0.00625,0.05133,-0.00266,-0.06343,0.03152,0.06402,-0.09289,0.03878,0.06209,0.01723,0.04029,-0.00687,0.01997,-0.05386,-0.03384,0.00532,-0.06418,0.02177,-0.00357,0.01594,0.02284,0.09946,0.01781,0.01219,-0.00127,0.05759,-0.00492,0.04321,-0.04724,0.06706,-0.0429,0.02722,0.06073,-0.05496,0.03838,0.07274,0.03947,0.04108,-0.03732,-0.07033,0.02415,-0.08517,0.08717,-0.03652,0.00467,-0.00201,0.03447,-0.02196,0.07384,0.04546,0.0315,0.0121,-0.05387,0.04023,-0.01941,-0.03934,0.03234,0.03739,0.0122,-0.01854,0.00767,-0.06917,-0.01979,-0.009,-0.03834,-0.05749,0.02422,0.01029,0.00472,0.05312,0.00303,0.02976,-0.0218,0.01969,-0.01948,0.02792,0.03258,-0.00032,0.0062,0.00518,-0.03377,0.0406,-0.00288,-0.00327,0.0023,-0.00863,0.07049,-0.02804,0.02766,-0.03147,-0.06443,-0.04462,0.02146,-0.02137,0.00076,0.02035,-0.05108,-0.03632,-0.04573,0.01588,0.08447,0.03154,-0.04115,0.06679,0.01274,0.0356,0.01229,0.04905,-0.00249,0.05912,0.00701,0.01906,-0.03779,-0.06564,-0.00018,0.0067,0.03842,0.06973,-0.00841,0.01042,-0.04652,0.02964,-0.02871,0.00988,0.06776,0.07547,-0.01997,-0.021,-0.00575,-0.01907,0.00507,0.06271,0.08323,0.00068,0.04035,0.06105,0.06427,-0.0485,0.07387,0.0229,0.02718,-0.04137,0.05757,0.03336,0.01342,0.00985,-0.02127,-0.03236,0.0227,-0.03664,-0.04331,0.01324,0.00297,0.00302,0.01253,-0.00295,0.00456,0.00923,-0.00754,-0.02301,-0.0449,-0.00242,-0.08795,-0.06492,0.02919,-0.00487,-0.04822,0.02179,0.03635,-0.012,-0.00989,-0.04059,-0.00306,-0.01223,0.01676,-0.08176,-0.03372,-0.02178,-0.02912,-0.02127,0.03952,0.00156,-0.04523,-0.05565,-0.08231,-0.03928,0.00212,-0.04475,0.02438,0.00997,0.0531,-0.01625,-0.05519,0.01164,0.00499,0.12583,0.0865,-0.01579,0.00767,-0.07523,0.01755,-0.04728,0.01314,-0.00444,-0.06277,0.03876,-0.00611,-0.03936,-0.09002,0.07627,0.06203,-0.11567,0.00555,0.03852,0.01529,-0.02613,-0.10393,0.01683,0.04006,-0.01297,-0.05777,0.01825,-0.01731,-0.03668,-0.06557,-0.1329,-0.06727,-0.07126,-0.05337,-0.05036,0.02882,-0.01506,-0.00935,-0.07895,0.02461,-0.02735,0.01092,0.00145,-0.00331,-0.0106,-0.01619,-0.0771,0.00574,0.00461,-0.01043,0.06681,-0.02421,-0.00459,-0.00448,0.03249,0.06467,-0.06463,-0.02422,0.03907,-0.03585,0.00857,-0.02281,0.08079,-0.02495,-0.01855,0.00741,-0.07446,-0.0116,-0.0339,0.02257,-0.08206,0.08526,0.00327,-0.00178,0.05559,0.09313,0.0579,-0.05275,-0.05074,0.04494,-0.0424,0.0233,-0.00624,0.00567,-0.04855,-0.00153,0.01925,0.04108,0.04172,0.01793,-0.06706,-0.0212,-0.03004,-0.07129,0.06863,-0.01415,0.03215,0.04033,0.04038,0.04279,-0.0839,0.01954,-0.02454,-0.01912,-0.02383,0.02145,0.00755,-0.01171,0.03556,-0.03424,-0.01361,0.06044,0.0474,0.03734,0.03724,0.04859,0.02033,0.07945,0.00154,0.03323,-0.02276,0.09582,0.05459,0.08179,0.04609,0.05013,0.0563,0.00588,0.0028,-0.0134,-0.1192,0.01633,0.06581,0.02838,0.05106,-0.00349,0.00382,-0.00942,-0.05714,0.0694,0.00396,0.08915,-0.02399,-0.0024,-0.02173,0.00526,-0.04384,0.05081,-0.06483,0.00051,-0.01443,-0.04718,0.01287,-0.06868,0.00985,0.09413,-0.0259,0.03279,0.08899,0.00999,-0.03734,-0.00849,-0.05868,-0.03965,0.0466,0.0041,0.04078,-0.03923,0.01336,-0.04908,0.02304,-0.02459,-0.07816,-0.02259,0.02698,-0.07367,0.06968,0.00098,-0.01651,0.00963,0.01787,0.06093,0.02251,-0.02028,-0.02402,0.01672,0.05782,0.00913],"pm/plan-roadmap":[-0.06707,-0.0567,-0.00306,0.03823,-0.00101,0.00962,-0.02761,0.0106,-0.07405,-0.06587,-0.05865,0.04694,-0.04936,0.01331,-0.02898,-0.03173,-0.00988,0.0614,-0.01609,0.00934,-0.00565,-0.10838,-0.02695,0.00449,0.0196,0.05846,-0.02798,0.04888,-0.02898,0.04683,-0.00812,0.08547,-0.02627,-0.04008,0.00883,0.03522,-0.00591,0.03182,-0.01608,0.1111,0.01912,0.01677,-0.08544,-0.00862,0.00794,-0.03683,-0.09488,-0.07971,-0.01089,0.0603,0.01699,0.03677,-0.06633,-0.03878,0.01682,-0.01713,-0.01662,0.03021,-0.01255,-0.02344,0.02037,-0.00397,-0.00051,0.05388,-0.07453,0.01618,0.01708,-0.00885,-0.03233,-0.03052,-0.00562,0.02603,-0.03191,-0.01791,0.12666,-0.0626,0.03928,0.04156,0.02231,0.08243,0.02088,-0.06261,0.00906,-0.03116,0.01572,0.05392,0.02774,0.02462,0.02108,-0.06995,0.08468,-0.04609,-0.00825,0.04502,0.00165,-0.06742,0.00159,0.02728,-0.00497,-0.02023,0.00032,0.01225,0.0867,0.0413,-0.03067,0.0346,0.0159,-0.0345,0.05577,-0.00011,-0.02072,-0.03541,0.00362,0.02329,0.07332,-0.02643,-0.04523,-0.07357,0.04265,0.05149,-0.01935,0.03423,-0.04226,0.06572,-0.04429,-0.0074,-0.04374,-0.10134,0.04635,0.01557,-0.02423,0.02543,-0.00491,0.02094,-0.04984,0.0213,0.00848,-0.05065,0.12327,-0.01586,-0.02717,-0.00218,0.0373,0.03471,-0.02867,0.01769,0.00962,0.00787,-0.02654,0.02208,-0.06028,-0.00795,-0.03591,-0.01189,0.04853,0.05609,0.01838,0.05491,-0.09214,-0.03656,0.00262,0.02957,-0.01722,0.02996,-0.00939,0.01528,-0.03105,0.01348,-0.01287,0.01976,-0.12139,-0.01037,-0.03601,-0.0085,-0.00688,-0.08953,-0.05178,0.00956,-0.0063,0.01953,-0.08743,-0.01552,0.02469,0.00069,0.02949,-0.02875,0.00398,-0.02046,0.03856,0.03588,0.01987,-0.02255,-0.0692,-0.04355,-0.03051,-0.00279,0.00043,-0.05804,0.04349,-0.00972,0.01405,-0.00681,0.04278,-0.06179,0.00545,0.04244,-0.00639,-0.07446,0.02313,-0.01203,0.03084,-0.05806,-0.03774,-0.00776,0.03183,-0.01146,0.05547,-0.01284,0.0882,0.04482,0.02939,0.00385,-0.08799,-0.01357,0.00428,0.02185,0.00925,-0.00154,0.03336,0.07267,0.05289,0.03542,-0.00018,-0.12248,0.01828,0.00343,-0.01231,-0.03945,0.00504,-0.05204,0.05007,-0.03939,-0.07932,0.0184,-0.00283,0.02876,0.04856,-0.08256,0.02105,0.09134,0.03044,0.0269,0.00757,-0.03586,0.00957,0.03294,-0.04164,-0.01576,0.06915,-0.05239,-0.01943,0.01107,-0.00764,-0.01456,0.00835,0.01299,0.04555,0.01514,0.03032,0.06801,-0.01771,-0.05859,-0.03274,0.08068,-0.07549,0.00967,-0.01953,-0.01812,-0.00843,-0.04812,-0.02923,0.03438,-0.02805,-0.06952,-0.01152,-0.01113,0.01488,-0.01065,-0.00145,-0.00636,0.03518,-0.07939,-0.04052,-0.03723,0.05289,0.01891,-0.05294,0.07895,-0.01439,-0.04133,-0.00705,-0.07958,-0.0583,-0.00944,-0.00731,0.02402,0.0938,-0.03139,-0.01108,0.01707,-0.00738,0.00382,-0.0034,0.02607,-0.05545,-0.01144,0.07724,-0.0247,0.04999,0.0403,0.01731,-0.08842,0.02105,0.03023,0.09295,0.02375,-0.02474,0.01479,-0.00896,-0.0569,-0.09424,-0.0584,0.02373,0.01314,-0.02139,0.04146,0.0038,-0.08684,0.05372,-0.01712,-0.0579,0.04606,0.00546,0.03112,0.05496,0.08887,-0.06866,0.00232,-0.01192,-0.00114,0.01202,-0.00939,-0.02138,0.01555,-0.10817,-0.02096,0.05443,0.015,-0.04662,-0.01258,0.02527,0.02968,-0.02844,-0.01774,-0.01794,-0.0636,-0.0201,-0.11488,0.02549,0.02137,0.00259,-0.08319,0.02929,-0.02068,-0.03396,-0.02853,-0.04779,0.01318,0.05621,0.09265,0.01991,-0.00922,0.04669,-0.04885,-0.00182,-0.02099,0.00526,0.17127,-0.05339,0.09469,-0.12591,0.03755,-0.00344,-0.01585,0.0484,-0.00274,-0.04002,0.06199,-0.03904,-0.02652,0.01709,-0.04721,-0.06687,0.00719,-0.02874,0.07358,-0.03635,-0.02322,-0.04961,0.02693,-0.05862,0.06578,0.02352,-0.00912,-0.02947,-0.05086,0.01297,-0.05198,-0.04671,0.0467,0.06734,0.03651,-0.00937,-0.03535,0.01717,-0.02702,0.0526,-0.0065,-0.00484,0.02614,-0.10825,-0.07398,0.00875,-0.01322,0.02169,-0.00454,0.06155,-0.07298,0.02118,0.01715,0.08965,0.098,-0.00355,0.0987,-0.0083,0.06103,-0.00984,0.00968,-0.04312,-0.0106,0.03417,-0.00348,-0.02924,-0.0083,-0.02582,0.02917,0.06337,0.00339,-0.06451,-0.02132,0.08758,-0.02003,0.04151,0.03908,-0.00016,0.03945,0.02635,-0.00392,0.05248,0.01797,-0.05565,0.07579,-0.0342,-0.00611,0.02049,0.00568,-0.02579,-0.02551,0.04333,0.00774,-0.04448,0.09058,0.02847,0.08266,0.01339,0.00747,0.01222,0.00978,-0.01246,0.02001,-0.00534,0.00008,0.02779,0.01847,0.0027,-0.02011,-0.08237,-0.02572,-0.04852,-0.02424,0.09598,-0.00114,-0.00403,0.02817,0.08615,0.01966,-0.04399,0.01923,-0.0302,0.04841,0.00312,-0.02197],"pm/write-prd":[0.05451,0.03864,0.00047,0.03808,0.03644,-0.02777,-0.06379,-0.02635,0.06213,-0.07116,-0.04874,0.01156,-0.03983,-0.04432,-0.00042,-0.0233,-0.03802,0.08567,-0.01035,0.07747,-0.00654,0.05429,0.0233,-0.0913,0.05081,0.00712,-0.05833,-0.00314,0.06545,0.05889,-0.03185,-0.01476,-0.08008,-0.00111,-0.01823,-0.00474,0.05903,-0.07089,0.02112,0.00439,0.00702,-0.00574,-0.0532,-0.02923,-0.04921,-0.05858,-0.00781,-0.01218,-0.05249,0.0506,-0.05464,0.08707,-0.05071,0.07186,-0.05024,0.00415,-0.00208,-0.02141,0.00452,-0.01605,0.01008,0.00578,-0.07123,-0.01732,0.01473,-0.04466,0.03491,0.02474,-0.0618,-0.00845,-0.06295,0.00705,0.04373,0.10122,-0.07167,0.03235,0.02353,-0.00787,0.01795,-0.00442,-0.01438,-0.06395,0.01084,-0.05294,0.05124,-0.02053,-0.00403,0.05533,0.06013,0.00098,-0.02642,-0.02059,0.01343,0.03919,-0.03274,0.00301,0.01015,0.11565,-0.02903,0.03975,0.02589,-0.13475,0.06395,-0.03772,0.02495,-0.02071,0.04706,-0.10998,-0.00428,0.05217,0.04642,-0.01246,0.00046,0.017,0.01997,0.04547,0.00653,0.03816,0.04437,-0.00938,0.02345,0.03444,0.03,0.01452,-0.0063,0.01775,0.02105,-0.0368,-0.01729,-0.01897,-0.01297,-0.03925,-0.04364,0.02445,0.04451,-0.04609,-0.02549,0.07966,0.01619,0.0342,-0.03522,-0.05875,0.01526,0.00485,-0.00112,-0.04915,0.01128,-0.01017,0.01054,0.04494,-0.00269,-0.043,-0.02721,0.03767,0.01946,-0.00922,0.07399,-0.01752,0.11222,0.00555,-0.086,0.01224,0.00665,-0.03122,-0.03762,0.00908,0.03596,-0.03794,-0.08079,-0.02903,-0.12909,0.03597,-0.11537,-0.01391,-0.0477,-0.00337,-0.0187,-0.02224,-0.0215,0.0771,-0.00764,-0.04818,-0.01556,-0.0085,-0.01452,-0.07111,-0.0269,-0.03881,-0.01875,-0.02734,-0.07472,0.00552,-0.01449,-0.0659,-0.05467,-0.02241,-0.02408,0.05449,0.00726,-0.03242,0.05138,-0.02356,-0.01286,-0.06003,-0.05276,0.02979,0.01583,-0.03492,-0.00467,0.01958,0.02306,0.05099,0.00484,0.04188,0.00528,-0.00226,0.01379,0.01989,-0.02085,0.02923,-0.04589,0.0219,0.01261,-0.016,-0.00739,-0.06535,-0.0122,0.01078,0.0438,0.06701,0.03956,-0.02671,-0.02916,0.02914,0.00537,0.0065,0.05778,-0.01704,0.03026,-0.00109,0.01382,-0.05881,-0.03608,0.00079,-0.05169,-0.08685,0.03146,0.04781,-0.04776,-0.02848,0.08076,0.00386,0.00154,0.04562,0.04484,-0.02611,-0.00184,0.02108,-0.00691,-0.02449,0.02063,0.03477,0.0156,0.03424,0.04435,0.01993,-0.02421,-0.07948,0.04459,-0.06662,-0.02015,-0.01606,-0.02197,-0.02466,0.01953,-0.02157,0.02281,0.00874,-0.0682,-0.00124,-0.01507,0.02936,-0.06313,0.02586,-0.0278,0.01253,-0.04283,0.03779,-0.04619,-0.07903,-0.00869,-0.0624,-0.04546,-0.0695,0.05119,-0.02996,0.01892,0.1312,0.02697,-0.04684,-0.00884,0.00083,-0.03475,-0.00105,-0.13177,0.02485,0.03335,0.04354,-0.00028,-0.00328,0.0215,0.04205,-0.0726,0.00048,0.02415,0.00984,0.02079,0.0322,-0.0028,-0.07208,-0.01109,-0.02588,0.02551,-0.00099,0.09447,-0.00457,-0.05616,0.03622,-0.01162,0.01077,-0.02034,-0.03147,0.00484,-0.00736,-0.00669,-0.01733,-0.05821,-0.03465,0.06983,0.0299,-0.12785,0.06231,0.06365,-0.05288,0.02626,0.02031,0.01468,-0.00147,-0.07558,-0.03541,0.05395,0.04098,-0.03267,-0.00649,-0.06844,-0.00912,-0.00393,-0.02613,-0.00042,0.06528,0.03739,-0.01016,-0.00405,0.0826,0.04617,-0.01044,0.03736,-0.02609,0.01813,-0.06217,-0.00232,0.02349,-0.02931,-0.06176,0.04221,-0.02423,-0.053,0.02155,0.01162,-0.03501,-0.01254,-0.04366,0.06986,0.03077,-0.01583,-0.05137,0.0495,-0.01885,0.01622,-0.01315,0.01935,0.01332,-0.03633,-0.01531,-0.03819,0.00633,-0.0488,0.03424,-0.00376,0.0247,0.03366,-0.00538,-0.00679,0.05423,-0.04902,0.05488,-0.03016,-0.01648,-0.01656,-0.02322,-0.04626,-0.05412,0.06974,-0.0392,0.06411,-0.10117,-0.01579,-0.02242,-0.01645,0.00364,0.02234,0.10312,-0.02381,0.023,-0.05267,-0.0196,0.01153,-0.03141,-0.04858,0.02828,-0.03828,-0.05993,0.01039,-0.0052,-0.08453,0.04772,-0.01139,0.10603,-0.02008,0.06335,-0.03647,0.08085,-0.04857,0.0344,-0.103,0.02903,0.0217,0.14366,-0.05411,0.01391,-0.0095,-0.02352,-0.00592,0.01985,-0.07801,-0.06272,0.02619,-0.04523,-0.03061,0.03378,0.00567,-0.03001,-0.04329,-0.03573,0.02102,0.02834,-0.02875,0.09256,0.04366,-0.02894,0.00631,0.08387,-0.08569,0.05245,-0.0353,-0.00503,0.05536,-0.00239,0.02857,0.08516,0.00663,-0.08178,-0.0036,0.01549,-0.06172,0.03878,0.00191,0.0395,-0.01346,0.04308,0.07431,0.0316,-0.02913,-0.09239,0.04852,-0.02726,-0.12331,-0.07191,0.05449,-0.03287,0.12856,-0.02902,0.02605,-0.04047,0.01043,0.00496,0.01819,-0.03471,0.04758,0.04584,-0.03014,0.02874],"pm/synthesize-feedback":[-0.07312,-0.03402,-0.09224,0.04186,0.02825,0.00102,-0.10786,-0.00832,-0.01745,-0.01958,-0.05991,0.02572,-0.03405,0.0261,0.03565,-0.01997,-0.02731,0.04917,-0.07237,-0.02664,-0.04646,0.03187,-0.03812,0.04103,0.03112,0.03522,-0.03197,0.0275,0.00975,-0.00407,-0.05298,-0.01458,0.00415,-0.01111,0.03312,-0.00579,0.03089,0.0014,0.03593,-0.009,0.06355,0.01088,0.00479,-0.01867,0.06902,-0.02892,-0.01676,0.02189,0.02068,0.04908,0.02276,-0.01489,-0.0687,0.02535,-0.07636,0.04344,0.01601,0.03794,-0.03992,0.00925,-0.04313,-0.03199,0.04854,0.02699,0.07171,-0.04678,0.0406,-0.0413,-0.02109,-0.02797,-0.03959,-0.02288,0.05601,-0.01762,-0.05993,-0.05908,0.0114,-0.1096,0.02801,-0.02519,-0.08266,-0.0303,0.04535,-0.00768,-0.04117,-0.02275,0.00148,0.07901,0.05781,0.02518,-0.02638,0.00245,0.03464,0.0087,0.01628,-0.04753,0.01414,0.06722,-0.00954,-0.02246,0.05861,-0.02187,-0.0492,-0.00481,0.01589,-0.09455,0.01517,-0.04348,-0.01191,0.08497,0.00825,0.02765,-0.07243,-0.0047,0.04055,0.03496,0.0138,-0.05515,0.09397,-0.03929,0.07139,-0.01178,-0.01953,0.0289,0.00456,0.01668,-0.0374,-0.0656,-0.04339,-0.06054,0.04756,0.062,0.01933,-0.03748,-0.00883,0.01454,0.04831,0.08444,-0.00955,0.00027,-0.0783,-0.07551,-0.03273,-0.01866,0.02891,-0.1062,0.01023,0.03189,-0.02296,0.05899,0.05748,-0.01312,0.02591,0.01277,0.03624,0.00358,-0.02072,-0.04561,-0.01838,-0.01868,-0.12005,0.00764,0.04966,0.0096,-0.00058,0.05994,0.00644,-0.04626,0.00343,0.01412,-0.10969,0.00651,-0.07361,-0.02978,-0.02143,-0.02436,-0.03773,0.02659,-0.07063,0.00709,-0.00883,0.00178,0.08559,0.06523,0.00716,-0.11851,-0.0623,-0.02128,-0.01695,-0.0317,0.04397,-0.04005,-0.01487,-0.02523,-0.02716,-0.0135,0.12036,-0.0295,-0.01081,-0.09622,0.07227,0.01402,-0.0816,0.01336,0.07429,0.09908,0.0563,0.00609,-0.00972,-0.03068,0.06276,-0.02465,0.01561,0.02839,-0.02499,-0.01277,-0.00472,-0.00531,0.08234,-0.0974,0.01131,-0.03149,-0.00266,-0.04568,-0.03826,-0.02236,0.03834,-0.03809,0.03055,0.00934,-0.00015,-0.08766,0.0558,0.07456,-0.03343,0.01252,0.00776,0.01763,-0.01907,-0.05152,-0.03505,0.01669,0.03764,-0.0175,-0.03205,0.06918,-0.02686,0.06185,-0.05142,0.00269,0.03759,-0.03662,-0.02708,0.00524,0.02242,-0.02207,-0.01645,0.07587,0.00306,0.01619,-0.05213,0.01097,0.02604,0.0081,0.04145,0.0045,0.02489,-0.03498,0.0056,-0.04158,0.00658,-0.02097,0.04157,0.00059,0.09396,-0.05197,-0.01752,0.00788,-0.14025,0.04876,-0.03557,0.06182,-0.02905,-0.06191,-0.02672,0.0523,-0.06444,-0.05008,0.02595,-0.01125,0.03371,-0.04144,-0.05426,-0.04418,0.06623,-0.06288,-0.00583,0.11805,-0.01328,0.01298,0.00682,-0.0138,-0.05596,0.01284,-0.02945,0.01499,0.02039,-0.00135,0.07386,-0.01788,0.05012,0.02242,-0.02655,-0.0036,-0.0068,0.02514,-0.0321,0.0822,-0.04262,-0.02771,-0.02243,-0.0487,0.02095,-0.07603,0.07698,0.02287,-0.02186,0.06582,-0.03204,-0.07259,-0.01388,-0.02403,-0.06351,0.06173,-0.08646,-0.01558,0.02755,-0.05441,0.02015,0.13657,-0.03006,-0.05919,0.00886,0.09144,0.01413,-0.00488,0.03243,0.0231,-0.0323,-0.04129,-0.00872,-0.00962,-0.0397,0.00818,-0.05026,-0.05554,-0.00251,-0.07134,-0.10258,0.03267,-0.00214,-0.01908,-0.04218,-0.04762,0.02717,0.01195,-0.00065,-0.01101,-0.01793,-0.00503,-0.11834,-0.04358,0.00779,-0.0168,0.01677,0.03423,-0.01361,0.05416,0.08672,0.10748,0.02732,-0.03129,0.05581,-0.01387,0.02974,-0.00388,0.04211,-0.03324,0.05913,-0.0009,-0.01566,0.07112,-0.05978,-0.05209,-0.03387,0.00857,0.01483,-0.1125,0.03033,-0.01622,-0.01872,-0.00743,0.01654,0.01359,0.01885,0.04666,-0.02271,-0.02966,0.00747,-0.01521,0.03063,0.00375,-0.00848,0.01304,0.12483,-0.08647,-0.04077,-0.06088,-0.02368,-0.06613,0.05311,0.04071,0.00297,0.02126,0.00096,-0.00445,-0.05867,-0.00586,-0.0751,0.03754,0.02673,0.0278,-0.0423,-0.00422,-0.01775,0.04906,0.01538,0.03022,0.01318,0.03228,0.06529,0.08929,0.00148,0.03877,-0.04125,0.03271,-0.00922,0.05355,-0.07302,-0.03824,-0.01646,0.01343,-0.02892,-0.0802,-0.02946,0.00943,0.02391,-0.00099,0.0017,0.03198,-0.03625,-0.04249,-0.01388,-0.01818,0.0343,0.08326,0.01398,-0.049,0.03782,-0.00779,0.01858,0.00386,-0.02856,0.0028,-0.04216,0.0022,0.01174,0.00659,0.00079,-0.03825,0.05574,-0.03988,0.03385,-0.02215,-0.00191,0.04582,0.0184,-0.03827,0.00955,-0.04234,0.03528,0.02679,-0.04155,0.02405,0.02529,-0.03685,-0.06438,-0.01266,-0.02133,-0.07083,0.0404,-0.02363,-0.00783,0.02466,0.01804,0.02346,0.02555,-0.03762,0.03534,0.06275,0.08634,-0.05163],"pm/stakeholder-updates":[-0.02897,0.02531,-0.04387,0.01655,0.05292,-0.09185,0.00114,-0.00487,0.04509,-0.02764,-0.07452,-0.06273,0.02507,-0.01611,-0.01179,-0.04006,0.06563,-0.02824,-0.10417,-0.02321,0.02672,-0.00965,0.02107,0.00362,-0.01976,-0.04348,0.06317,0.03249,0.03036,0.02792,-0.0375,0.03325,-0.06091,0.00551,0.09234,0.02329,-0.0203,-0.06206,0.03359,0.08946,0.02365,0.01873,-0.07155,0.01818,-0.02344,-0.03413,0.00049,0.01935,0.01927,0.01391,-0.01022,0.08737,0.00425,-0.02248,0.00512,-0.01162,-0.02087,-0.02846,0.00862,-0.01013,0.05551,-0.07121,-0.01358,0.08154,0.03054,-0.02999,-0.05193,-0.06169,-0.01458,-0.02501,-0.06433,0.0214,0.04157,0.06416,-0.02366,-0.03773,-0.03231,0.03877,0.03785,-0.03166,0.00896,-0.09707,0.04288,-0.094,-0.016,0.05766,-0.02903,0.05757,0.0438,-0.04927,0.00477,-0.06061,0.03259,0.00452,0.02732,-0.01277,0.10283,0.03055,-0.02094,0.03798,0.01444,-0.01621,-0.01018,-0.02045,0.04487,-0.01917,0.00925,-0.02883,-0.02515,0.06685,0.01708,0.03151,0.07472,-0.02324,0.04332,-0.01606,-0.02543,-0.05915,0.06377,-0.03084,0.05073,0.02921,-0.09696,-0.03231,0.03991,-0.09471,0.08539,-0.03251,0.00319,-0.04603,-0.10644,0.02202,0.01902,0.01761,-0.07538,-0.03037,0.0358,0.00533,-0.05944,0.0163,-0.06519,0.04787,0.00209,0.02411,-0.06588,-0.00946,-0.01829,0.03194,-0.03031,0.03141,0.01265,-0.06604,0.00332,0.02063,0.07546,0.00453,0.05149,-0.00294,0.05026,0.0149,-0.02801,-0.04619,0.03944,0.02195,-0.02861,0.02658,-0.00277,-0.01705,0.02898,-0.07637,-0.05469,0.05412,-0.07071,0.02418,-0.05763,0.0843,-0.04802,0.01294,-0.02828,0.06462,0.00074,-0.02173,0.011,-0.05083,-0.02218,-0.00984,-0.03416,-0.0284,0.06986,0.04185,0.02678,-0.05289,-0.03246,-0.02255,-0.04687,-0.06297,-0.03589,-0.04224,0.01872,-0.00835,-0.00738,0.02056,0.02173,-0.06952,-0.05231,0.05421,-0.03632,-0.03056,0.03159,-0.02172,0.01603,0.03053,0.00069,0.05233,-0.01751,-0.02701,0.02722,0.06389,-0.09397,-0.00598,-0.02498,-0.01967,0.05309,-0.04954,-0.01774,-0.02667,-0.13353,0.01469,0.06177,0.00626,0.02353,0.00881,0.00333,-0.14268,0.01117,-0.04046,-0.04819,-0.03241,0.06588,0.00547,-0.03039,-0.02179,-0.00321,-0.01908,0.0149,-0.00153,0.02873,0.06038,-0.00887,0.00232,0.05633,-0.0082,-0.00174,0.05277,0.06476,-0.03803,0.08286,0.02467,0.03046,-0.0023,-0.01794,0.02827,0.0203,-0.03225,0.03406,-0.03608,0.04275,-0.00632,0.00726,-0.02326,-0.00108,-0.01619,-0.00097,-0.02453,-0.06223,-0.04603,0.05804,-0.0228,-0.06343,-0.01663,-0.01521,0.04687,0.02591,0.10255,0.08381,-0.00612,-0.03112,0.0236,-0.03675,-0.02701,-0.01119,-0.05523,0.11311,-0.03975,0.0478,-0.02607,-0.00648,-0.00789,-0.00671,-0.05844,-0.01122,-0.05307,-0.0297,-0.00832,-0.03615,0.07272,0.00431,0.05962,0.02983,-0.02635,-0.01277,0.01848,-0.04555,-0.02417,-0.04233,0.02295,-0.04047,0.04208,-0.09722,-0.0542,-0.05258,-0.071,0.06517,0.08743,0.08712,0.00925,-0.03491,0.00934,-0.01829,-0.05649,0.02629,-0.06126,0.05688,0.03902,-0.04771,0.01101,-0.01951,-0.01279,0.0682,0.04155,-0.06681,-0.00791,0.04616,-0.00499,0.01222,-0.04016,-0.02022,0.00862,-0.01921,-0.00692,0.07469,-0.01425,0.01493,0.09852,-0.01525,-0.01347,0.00051,-0.01274,-0.06643,-0.05241,0.03878,-0.03002,0.04466,0.0054,0.02401,-0.03561,-0.02101,0.00924,-0.02594,-0.0375,-0.05479,0.00156,0.0471,0.0134,0.00543,-0.0114,-0.08695,0.06016,0.04976,0.05767,0.01642,0.02942,0.03934,-0.06841,0.03096,0.03977,0.0064,0.07998,0.06362,0.00914,0.00428,0.03062,0.00962,-0.02978,-0.00033,0.01731,-0.0088,-0.06805,-0.013,0.0601,0.01309,-0.03312,-0.06962,0.01128,-0.0781,0.06792,-0.01294,0.00569,0.02191,-0.02792,-0.04975,0.02767,0.04071,0.00891,-0.0239,-0.03584,0.01768,-0.0155,-0.03953,0.00657,0.01836,0.00806,-0.08924,-0.00576,-0.07428,0.05108,-0.02328,0.01014,-0.0107,0.12284,0.00875,0.00094,0.01293,0.0005,-0.00358,0.05462,0.03383,0.05934,0.05053,0.03625,0.07082,0.07335,0.02033,-0.02546,0.02934,0.07165,0.05791,0.04529,-0.00398,0.04016,-0.06508,0.07047,0.03213,-0.0591,-0.08631,0.04006,0.05761,-0.01513,0.04421,-0.01617,0.00522,-0.03401,-0.01241,-0.06873,0.03206,-0.00147,-0.08187,0.0038,0.05361,-0.01017,-0.01103,-0.0381,0.0289,0.04355,-0.05051,-0.05365,-0.04264,0.02483,0.09606,-0.04136,-0.02132,0.00569,-0.01037,-0.02253,0.01396,0.01203,0.01222,0.03435,0.03957,0.04424,0.01558,-0.01752,0.01638,-0.01285,0.01347,-0.06445,-0.12804,-0.03466,0.02727,-0.04171,0.09001,-0.01069,0.02162,-0.02826,0.00699,0.07798,0.02514,-0.08171,0.06314,0.12341,-0.03337,-0.03581],"pm/analyze-metrics":[-0.01899,0.01932,-0.05438,0.02719,0.00197,0.05134,-0.01439,-0.0563,-0.02388,-0.04868,-0.03358,-0.05258,0.03072,-0.03301,0.03605,-0.01545,0.04209,0.01341,0.00055,-0.05468,0.03368,0.02,-0.04343,-0.04158,0.01011,0.02414,0.02248,0.04822,-0.01371,0.01813,-0.10036,0.04823,0.01362,-0.00463,0.03493,0.00281,0.11609,-0.03918,0.01022,-0.0527,0.05381,0.00613,-0.0752,-0.01249,0.01753,-0.0879,0.00099,0.03273,-0.00462,0.09091,-0.04757,0.01031,-0.01997,0.05051,-0.05744,-0.024,0.00928,0.005,-0.03386,0.02164,-0.01776,-0.05226,0.02155,0.04017,-0.05376,-0.02684,0.00586,-0.03159,-0.12343,0.0459,0.01633,-0.04349,-0.00247,0.02017,0.00895,-0.08171,0.00902,-0.04561,0.01982,-0.00253,-0.06211,-0.02457,0.02815,0.017,0.03365,-0.0468,0.03681,0.03892,0.03355,0.14456,0.0043,-0.00698,-0.02201,0.05782,-0.00733,0.00874,0.03592,0.04011,0.01455,-0.03769,-0.02506,0.06706,0.07555,-0.05019,-0.03612,0.01193,0.08154,-0.06104,0.03105,-0.06526,-0.0418,0.02554,-0.04392,0.03828,0.01836,0.05641,0.01545,-0.05259,-0.05179,0.01801,0.09029,-0.02864,0.01498,-0.00381,-0.06948,-0.07232,0.02864,-0.00561,0.05594,-0.03571,-0.03831,-0.03157,0.00056,0.0079,0.05092,-0.02562,0.0513,0.07347,0.01319,-0.06658,0.03815,0.08759,-0.00667,0.00443,-0.04277,-0.02741,0.1036,0.06491,-0.0526,-0.04458,0.04101,0.0471,0.03451,-0.0124,-0.00451,-0.05172,0.05353,0.02458,-0.07333,-0.03902,0.00905,0.1298,-0.06542,-0.02731,0.04344,-0.00902,-0.06317,-0.02623,-0.03326,0.07451,-0.02645,-0.01461,-0.03252,0.01355,-0.02567,0.02303,-0.04823,0.00588,0.05609,0.021,0.03361,-0.08353,0.00588,0.0095,0.02205,-0.02658,0.03067,-0.08255,-0.02296,0.05287,0.03844,-0.0497,-0.01133,-0.08584,-0.0079,0.02488,-0.01225,0.05209,0.00383,-0.03464,-0.09402,0.0056,-0.08255,0.02041,-0.03343,0.02025,0.02584,-0.03105,0.02346,0.037,-0.05724,-0.01141,0.01552,-0.08304,-0.0539,-0.01903,-0.00982,-0.03638,-0.02846,-0.02234,-0.0208,-0.01309,-0.01899,0.04126,-0.0012,0.0631,-0.00301,-0.00855,-0.01354,0.05162,0.04271,-0.00908,-0.02256,0.00332,-0.00607,0.02177,0.04579,-0.0064,-0.01552,-0.02199,-0.0406,-0.07579,0.00497,0.04748,0.0056,0.00675,0.04597,0.00825,-0.04434,-0.09252,-0.00007,0.01418,-0.02964,0.03488,0.06016,-0.01899,0.03868,0.01824,-0.02564,0.02341,0.0316,-0.04808,-0.08996,-0.01587,-0.06208,-0.05194,-0.03802,-0.02675,0.03299,-0.04315,-0.04192,-0.018,-0.05604,0.01776,0.05379,-0.00226,-0.01376,0.02576,-0.00021,0.00233,-0.01432,-0.02483,0.03938,-0.02184,-0.07597,0.03173,0.05251,-0.04414,-0.0214,0.01842,-0.02558,-0.01898,0.0091,-0.02883,0.04369,-0.0137,-0.01082,0.08768,0.0324,-0.04885,0.02683,0.00957,-0.02084,0.03039,0.01189,-0.00609,0.02655,0.03513,0.0657,0.12259,-0.03293,-0.03431,0.04106,-0.07267,0.04481,-0.059,-0.0309,-0.01849,0.05068,0.00598,0.0235,-0.0563,0.06076,-0.02045,0.05502,0.02835,-0.03501,0.1018,-0.01026,-0.00839,-0.09834,-0.02061,0.04591,-0.06346,-0.00804,-0.02273,-0.00765,-0.01065,0.04912,-0.00472,-0.08017,0.08986,0.01124,-0.049,0.05685,0.02329,0.02103,-0.01396,-0.0115,-0.06948,-0.02709,0.02566,-0.0214,0.02374,0.00122,-0.03833,-0.00057,-0.07997,0.03328,0.04173,0.02855,-0.01307,-0.02265,0.07789,0.03611,0.02784,-0.00082,-0.01602,0.00181,0.05159,-0.07604,-0.00761,0.05399,0.01628,0.11559,-0.06941,-0.01804,-0.11936,0.03454,0.01386,-0.05702,-0.06144,0.0612,-0.02036,-0.00754,-0.00044,-0.03512,-0.01307,-0.01563,0.02903,-0.06209,-0.00936,-0.01946,0.00476,0.0952,0.04719,-0.06999,0.01974,-0.00228,0.04282,0.04,-0.04127,-0.03677,-0.03721,-0.05911,-0.01516,-0.05627,-0.00164,0.0401,-0.01817,-0.06343,0.11613,0.04507,0.07787,-0.04124,0.05409,-0.01748,0.02217,-0.12482,-0.00227,-0.00572,0.03651,-0.05473,0.02304,0.01335,-0.02343,-0.02627,0.02096,-0.00458,-0.07602,0.07366,0.04186,-0.03592,0.03129,0.00824,-0.08643,0.03045,-0.04387,0.01163,0.05034,-0.00246,0.05276,0.06684,0.00316,-0.00299,0.07274,-0.06659,0.07425,-0.03387,0.03519,0.04114,-0.05186,-0.03103,0.00409,-0.06254,-0.0125,0.01039,0.06306,0.03483,-0.0008,-0.06764,-0.01913,0.07068,-0.03308,-0.01888,0.04666,-0.02579,0.00571,0.01446,-0.05665,-0.00423,-0.03915,0.00243,-0.02534,0.00043,0.0441,0.12641,0.03205,0.04378,-0.04557,-0.02019,0.04318,0.06422,0.05998,-0.005,0.04472,-0.02956,0.02215,0.0418,-0.00214,0.05917,0.02185,-0.05092,-0.02587,-0.00277,-0.04134,-0.04055,-0.00877,0.11896,-0.00044,-0.01427,-0.00887,0.01151,-0.01162,0.04662,0.01912,0.0208,-0.02472,-0.0649,-0.00374,0.05576,0.00953],"recruiter/find-contact-candidates":[-0.02045,0.00224,-0.00073,-0.01079,0.07603,-0.00374,0.01794,-0.02049,0.05885,-0.05126,-0.0516,0.05175,-0.02962,-0.01969,0.00544,-0.06354,-0.00128,0.04315,0.0166,0.03102,-0.02647,-0.01054,0.03775,0.01766,0.08804,0.01418,-0.05798,0.01927,-0.01548,-0.05747,-0.03562,-0.00931,-0.01345,-0.01832,-0.04522,-0.02188,0.05253,-0.02362,0.04593,0.04181,-0.03936,0.0736,-0.03502,-0.01995,0.0716,-0.06455,0.03898,-0.02036,-0.03947,0.03055,0.05348,0.02622,0.01038,0.09008,-0.02144,-0.07158,-0.02893,-0.04902,0.02079,-0.04646,0.04488,-0.00877,-0.03849,-0.01289,0.06722,-0.06724,0.08638,0.04607,-0.05089,-0.03767,-0.07751,0.04252,-0.0426,0.04467,0.01781,0.06626,-0.01612,0.02302,-0.00913,0.03708,0.01326,-0.08475,0.07436,-0.05149,0.01516,-0.06202,0.02368,0.0254,-0.00638,0.0399,0.0515,0.00883,-0.01246,-0.05175,-0.03065,-0.07389,0.02206,0.02177,0.01101,-0.01012,0.01788,0.04106,-0.02942,-0.07258,0.11093,-0.0313,0.00177,-0.06542,-0.07127,0.03159,-0.03661,0.03485,-0.03112,-0.01308,0.01809,-0.04369,-0.00061,-0.05018,0.0807,0.0557,-0.00028,0.08878,-0.0372,0.00085,0.04228,-0.04307,-0.00397,-0.12968,-0.01473,0.0125,-0.0118,0.10402,-0.01499,-0.01933,-0.07158,0.01392,0.03752,0.10424,0.10213,0.04765,-0.04124,0.05416,-0.02282,-0.02437,0.00667,-0.05214,0.02293,-0.06045,-0.00033,0.00972,0.02918,0.03239,0.02883,-0.00145,0.02012,0.01996,0.00087,0.06263,0.03063,0.02738,-0.12639,-0.07263,-0.03658,0.02572,0.02425,0.00845,0.00143,-0.05067,0.00982,0.0195,-0.06257,0.06309,-0.08153,-0.05968,-0.01901,0.05178,-0.04262,0.03651,-0.06849,-0.03968,0.04255,-0.06238,0.02137,0.00477,-0.0313,-0.03292,0.07547,0.03344,0.05757,-0.03081,0.04005,0.05922,-0.04137,-0.02115,-0.0838,0.01594,0.02705,0.04998,-0.03051,0.04469,-0.01804,-0.00489,0.00728,-0.05741,-0.02962,0.03161,-0.03762,-0.01717,0.05622,-0.01336,0.05914,0.03455,0.02359,0.04066,-0.06463,-0.02365,0.0084,0.01393,-0.04721,0.00599,-0.01227,-0.04748,0.00176,0.08914,-0.00706,-0.09244,-0.00941,-0.01425,-0.01846,0.0356,-0.00548,0.0751,-0.01231,-0.00997,-0.04365,0.03789,-0.03254,0.018,0.04201,-0.05081,0.01904,-0.06747,-0.07108,0.05694,-0.05118,0.06854,0.00876,0.02655,-0.04494,-0.06982,0.01506,-0.00822,-0.00814,-0.00819,-0.0854,0.01357,0.01186,-0.01122,-0.03491,-0.00304,0.02882,0.08091,-0.036,0.03643,0.04036,-0.05482,-0.11002,-0.02586,-0.00422,-0.03204,-0.00011,0.03054,-0.01945,-0.0345,-0.01765,-0.0739,-0.03034,-0.01175,-0.09632,-0.03329,0.07577,0.02836,0.00111,-0.04115,-0.05168,0.01909,0.02754,0.05475,0.0144,0.01509,-0.00995,-0.06653,-0.02557,0.05984,-0.01698,-0.06997,-0.00722,-0.01559,-0.03433,-0.02153,0.03224,-0.03328,0.00759,0.00012,-0.08783,0.07052,-0.03595,0.00227,0.01426,-0.03016,-0.09948,0.0879,-0.0719,-0.03647,0.05256,0.01907,-0.0005,0.03102,-0.026,-0.02224,-0.00335,0.01163,-0.01095,-0.02677,0.05444,0.07027,0.01372,-0.00039,-0.04881,-0.02225,-0.0165,-0.08983,0.00385,0.0261,0.04474,-0.03258,-0.02421,-0.02498,0.06611,-0.03392,-0.04315,0.07576,0.07353,-0.05148,0.03842,-0.0083,-0.02932,-0.0215,-0.02377,-0.03643,0.01207,0.06069,0.03826,-0.02234,-0.07286,0.00957,-0.07921,-0.03491,0.00362,-0.00595,-0.00504,-0.04959,0.05428,-0.00116,-0.04143,0.02143,0.03364,0.03826,0.00562,0.00215,-0.00673,0.00461,0.01003,-0.02796,-0.02414,-0.08604,-0.02884,0.06644,0.01334,-0.02101,-0.03311,-0.04046,0.08442,0.05134,0.01668,-0.01724,0.02738,-0.05266,0.06077,-0.01901,-0.02947,-0.00176,-0.01498,0.02279,0.00493,0.01767,-0.00275,0.03046,0.02161,0.01242,0.04863,-0.05259,0.04901,0.03897,0.08339,0.03155,0.04289,-0.00902,0.00038,-0.0174,-0.04002,0.06237,0.02808,-0.03462,-0.01743,0.01413,-0.06212,0.01931,-0.01467,0.05571,0.02023,0.03802,-0.00117,-0.0176,-0.05248,0.03807,0.10966,-0.10365,-0.06608,-0.01464,-0.00879,0.02473,0.09673,-0.00332,-0.04414,0.07827,-0.03638,0.08491,0.03566,0.05147,0.0449,0.05271,-0.01728,0.06848,-0.02455,0.01434,0.04095,0.06303,-0.02926,-0.00268,-0.00684,0.03036,0.00639,0.05602,0.00972,-0.01257,0.0642,0.03263,0.0294,-0.00899,0.0393,0.00489,-0.06579,0.05289,0.02854,-0.03415,-0.08803,-0.05374,0.00032,0.01468,0.0448,0.05213,-0.09727,0.00972,0.00663,-0.00959,0.07546,-0.0179,0.03058,0.04239,0.01172,-0.03246,-0.06379,-0.10551,0.06288,0.00021,0.07776,-0.00419,0.03554,0.04184,-0.03499,0.00496,-0.00181,-0.05348,0.03185,0.00773,-0.00642,-0.05684,0.00018,-0.03038,0.1217,-0.05502,0.01682,0.01412,0.0058,0.01493,0.0028,-0.04917,0.001,0.01749,-0.03616,0.00004],"recruiter/screen-resumes":[0.01982,-0.04,-0.02058,0.05121,-0.01822,-0.03743,-0.02479,-0.05082,0.02086,-0.04774,0.0142,0.03618,-0.05256,0.03127,-0.03405,-0.05892,-0.04829,0.03554,-0.05433,-0.00621,-0.04265,-0.03891,0.00766,-0.0193,0.05291,0.01739,-0.06487,0.03985,-0.03873,-0.01646,-0.04871,-0.03326,-0.06397,-0.09149,-0.03965,0.02807,0.04652,-0.03704,0.02221,0.02736,-0.03161,0.02246,-0.04453,0.0359,0.03663,-0.05881,-0.02634,-0.02521,0.07695,0.06874,-0.01945,-0.02969,-0.02938,0.05274,-0.10802,-0.08797,-0.06336,-0.06028,-0.05189,-0.05549,0.01493,-0.07042,0.00894,-0.05003,0.04266,0.02283,0.02788,0.00756,-0.00031,-0.02297,-0.04199,-0.01202,0.00007,0.03924,-0.03021,0.00869,0.01019,-0.0074,0.01418,0.04219,-0.00374,-0.06906,0.05519,0.02666,0.01947,-0.02418,0.01519,-0.00174,0.05186,0.04084,0.00821,0.01292,-0.00243,0.05424,-0.04099,-0.05166,-0.01111,0.00802,-0.03357,-0.02683,-0.00831,-0.00901,0.02285,-0.02692,0.03242,0.02229,-0.02297,0.06481,0.00609,0.07239,0.01005,0.03226,-0.01738,-0.01365,0.03773,0.02907,0.01915,0.02285,0.05418,-0.02062,-0.01433,0.07393,-0.00049,0.04021,0.05302,0.02271,0.00622,-0.08683,0.02604,0.04587,-0.03922,-0.0184,-0.09873,0.01239,-0.02368,-0.02511,-0.03474,0.04068,0.03597,0.02354,0.00811,0.06235,-0.05005,0.01144,0.07417,-0.03808,0.01165,0.00318,-0.04673,-0.01071,0.02596,0.0417,-0.03724,0.05834,0.00481,0.01597,0.00311,0.06246,0.13073,-0.00051,-0.07213,0.02672,0.00882,0.03162,0.029,-0.01679,-0.08195,-0.01675,0.01869,0.00858,-0.06584,0.0753,-0.12507,0.04189,0.03419,0.00675,-0.0142,-0.02904,-0.10469,-0.00878,0.00111,-0.03289,0.04608,0.02628,-0.05034,-0.00099,0.07187,-0.02255,-0.00331,0.06574,-0.01128,-0.03755,-0.05648,-0.06493,-0.05703,-0.06763,0.14781,0.06182,0.03641,-0.05041,-0.04161,0.02748,0.01423,-0.02478,-0.00913,0.02052,-0.05439,-0.04041,0.04672,0.00311,0.00692,-0.01107,0.00594,0.0752,-0.0609,-0.06487,0.00856,0.08666,-0.09035,-0.02861,-0.04778,-0.05339,-0.01764,0.0784,-0.03155,0.00146,0.06739,0.03641,0.02261,0.0907,0.05214,-0.00315,-0.00984,-0.0008,-0.03899,-0.04003,-0.00583,-0.02597,0.04522,-0.04866,0.01429,-0.05064,-0.0301,0.05685,-0.02907,-0.03072,-0.00864,0.01815,-0.05204,-0.08133,-0.01898,0.03945,0.04139,0.00702,-0.02113,-0.06322,-0.02442,0.01715,-0.00992,-0.02203,-0.05635,0.0735,-0.0129,0.00603,0.08656,0.01317,-0.12882,0.00958,0.05115,0.02484,0.01455,-0.10861,-0.01774,0.01168,-0.01804,-0.00716,0.00267,-0.03156,-0.09239,-0.04572,0.00775,0.0474,0.01599,0.03059,-0.06684,0.01729,0.08431,0.00501,0.04358,-0.03389,-0.00428,-0.02967,0.03529,-0.02838,0.00641,-0.05187,0.01164,0.02551,0.06775,-0.04656,0.04307,-0.02966,0.01888,0.01302,-0.07763,0.0562,0.03098,0.02794,-0.03595,0.02131,-0.03298,-0.00267,0.00445,-0.02877,0.03903,0.02926,0.02253,0.05481,-0.03546,0.00457,-0.10545,-0.02284,0.09273,-0.06182,0.08702,0.08061,-0.04879,0.01883,-0.05132,-0.00086,-0.05161,-0.05381,-0.00706,-0.00127,0.01493,-0.04119,-0.0999,-0.08137,0.09016,0.08989,-0.08037,0.02124,0.02673,-0.05292,0.01811,0.00463,-0.00888,-0.0343,-0.01423,-0.05403,-0.03447,0.02181,-0.02726,-0.0116,-0.03285,0.00095,0.01141,-0.04534,-0.02307,0.04472,-0.03448,-0.03578,-0.01654,-0.00932,-0.0211,0.02979,-0.00526,0.03551,-0.02184,-0.03273,0.00046,-0.00769,0.03877,0.02414,0.07623,-0.03168,0.04322,0.07647,0.05509,0.07059,-0.01516,-0.02935,0.10437,0.00949,0.0193,-0.02539,0.09053,0.00579,-0.03894,0.00163,0.01222,0.03186,-0.01768,-0.09184,0.01828,0.00663,-0.00143,0.00066,-0.01792,-0.03458,0.06277,-0.02728,-0.01415,0.07645,0.01291,0.04543,0.02017,-0.01372,0.03945,0.03501,0.04439,0.13347,0.04488,0.00783,0.01915,-0.03203,0.00616,0.04421,-0.00504,0.01017,-0.00172,0.00659,-0.06869,-0.06862,-0.03841,-0.00488,-0.01913,0.02481,0.03412,0.00319,0.03112,-0.02418,0.02868,0.04651,0.03716,0.0322,0.03508,-0.01782,0.02787,0.01904,0.01047,0.04061,-0.00178,0.04554,0.02086,0.0706,-0.00623,0.01826,-0.04831,0.00287,0.02605,0.03272,0.0098,-0.09474,-0.03896,-0.03202,0.00238,-0.02756,0.00157,-0.01998,0.04731,0.01256,-0.03764,-0.08332,0.04673,0.04642,-0.04335,0.01862,-0.04687,0.00865,-0.03901,0.0908,-0.0322,-0.00233,-0.09923,-0.01646,-0.08248,0.02746,-0.02691,-0.00668,0.02338,0.01807,0.01138,0.08499,-0.02466,-0.06264,0.08329,-0.02785,0.09052,0.04347,0.04658,-0.04222,-0.00073,-0.05824,0.03123,0.04886,-0.03181,-0.01651,-0.00474,-0.02872,0.14955,-0.00839,-0.00805,-0.00464,0.00907,0.02645,-0.02299,-0.0219,-0.00938,-0.00848,-0.05107,-0.02027],"recruiter/prepare-interviews":[-0.05547,-0.0668,-0.04823,0.05191,0.0164,0.01394,-0.03516,-0.01394,-0.09987,-0.0147,-0.00759,0.09765,-0.01852,-0.0258,0.04692,0.03689,-0.00136,0.07485,-0.03859,-0.09824,-0.076,-0.0034,-0.0108,-0.01108,0.03205,0.05923,0.0051,-0.00318,-0.00331,0.09705,-0.02881,0.0337,0.01383,-0.01962,-0.03399,0.01676,0.02806,-0.00018,0.03617,-0.04473,0.10893,-0.00723,-0.00758,0.02191,0.06196,-0.01507,-0.12097,-0.03123,-0.02583,0.04268,0.03169,0.01999,-0.01129,-0.0343,-0.04678,0.02557,0.00259,-0.03191,-0.02988,-0.03887,-0.01272,-0.07924,-0.03338,0.04014,0.01794,-0.00204,0.01695,-0.0095,-0.02554,0.00351,-0.01031,0.05903,0.06007,0.05601,-0.0554,-0.06635,0.01073,0.00444,0.04121,0.07363,-0.04187,-0.05129,0.0405,-0.04543,-0.03826,-0.08289,0.05221,0.01661,0.05227,0.08083,-0.02773,0.00168,0.01749,0.03801,0.00035,-0.01124,-0.04019,0.00117,0.02176,-0.01262,0.0172,-0.05908,-0.01495,0.0061,-0.012,0.00202,-0.00402,-0.0666,0.02448,0.04177,-0.07566,0.00635,-0.06171,0.01298,0.05516,-0.04662,0.01853,-0.02105,0.03105,-0.01687,0.06468,0.06371,-0.08153,0.06659,-0.00875,-0.04976,0.03253,-0.02185,0.04608,-0.00803,-0.00978,0.06731,-0.01083,0.01222,-0.01885,-0.03771,0.03291,0.02855,0.06279,-0.02866,-0.00214,-0.00798,-0.01321,0.00067,0.01315,-0.04852,0.02145,0.02252,-0.03934,0.03053,-0.01167,0.00024,0.08057,0.07214,0.01305,0.00602,0.04823,-0.04026,-0.00739,-0.00003,-0.07263,-0.04682,-0.02555,0.00578,-0.01927,0.03094,0.02108,0.00218,-0.04611,-0.02475,-0.0301,0.03402,-0.09985,-0.02156,0.00672,-0.04646,-0.03568,0.04572,-0.03578,-0.04845,0.11152,0.00392,0.05281,0.08524,-0.06655,-0.10586,0.07567,-0.0184,-0.00233,-0.00542,0.03909,0.01712,-0.0593,-0.03213,-0.04904,-0.01286,0.02881,0.0134,0.01557,-0.08382,0.0836,0.00785,-0.05462,0.00652,-0.0923,0.05979,0.03088,0.02935,0.05642,-0.12159,-0.00168,-0.03863,0.01111,0.02359,0.05413,-0.02326,-0.04291,0.02025,-0.03329,-0.0183,-0.03914,-0.02448,-0.0213,0.04625,0.02968,-0.02325,-0.01568,0.03889,-0.00446,0.02637,0.0111,-0.04932,-0.01224,0.02718,0.01038,0.00321,-0.0137,-0.04623,0.01749,-0.04836,-0.04642,-0.06908,0.0499,0.06251,-0.02449,0.0896,0.01629,0.05884,-0.05092,-0.05124,0.00226,0.07944,-0.05637,-0.02111,-0.01965,-0.04015,0.03685,-0.03913,0.02976,-0.02401,-0.05938,0.051,0.059,0.0502,0.02771,0.00511,-0.09168,-0.06314,-0.03994,-0.00212,0.05362,0.01151,0.02908,-0.00618,-0.01764,-0.06256,-0.03903,-0.03596,-0.11979,-0.0049,-0.02476,-0.05987,0.04808,-0.07781,-0.00952,0.01369,-0.06615,0.00652,0.02856,0.05975,0.00647,-0.06539,0.04352,-0.0135,0.02045,-0.06645,0.00632,0.02953,0.01389,-0.03355,0.10242,0.01118,-0.05317,-0.00438,0.00409,0.03863,0.01574,-0.02288,0.05106,-0.05783,-0.01187,0.01647,-0.01944,-0.01725,0.01173,0.00268,0.00032,0.05646,-0.00923,0.06467,0.02137,0.00474,-0.05038,0.03871,0.06156,0.03224,-0.01354,0.02894,-0.02633,0.01451,0.01031,-0.04005,-0.03913,-0.00802,-0.04313,-0.01144,-0.0846,-0.09919,0.08332,0.07823,-0.07721,-0.03725,0.04293,-0.02679,0.0617,0.06303,0.06873,0.06438,-0.07236,-0.05922,-0.02131,-0.01297,-0.01563,0.02187,-0.07895,-0.0309,0.01632,-0.03458,-0.05393,0.03411,0.05584,-0.00819,-0.05748,0.06972,0.02468,0.01162,-0.04147,-0.00366,-0.02392,-0.05565,-0.08276,-0.03172,0.03184,0.03387,-0.00816,0.05313,0.04201,0.00691,0.01075,0.07303,-0.00588,0.00393,0.01922,0.04766,-0.08158,-0.00407,0.01896,0.01549,0.09661,0.01134,0.02219,0.05895,-0.02111,0.01407,0.01713,0.03595,0.06822,0.04537,0.02438,-0.03708,0.02654,0.00655,0.00221,0.04779,0.03377,0.01037,-0.04109,-0.00014,-0.04737,0.01337,-0.03116,0.01751,0.04188,0.02508,0.05245,-0.08958,-0.01096,-0.04185,-0.00649,-0.06621,0.07171,0.05635,-0.07653,0.01031,0.06733,-0.03856,0.0176,0.00904,-0.03925,0.01251,0.05782,0.04158,-0.07391,-0.04339,-0.01831,0.05624,-0.02426,0.08159,0.0388,0.00309,0.09543,0.09905,-0.02108,0.03909,-0.05651,0.07582,-0.03609,0.01652,-0.01374,0.00474,0.05931,0.05445,0.00805,-0.0746,-0.00661,0.00431,0.03143,0.02516,-0.02848,-0.00183,0.0341,-0.02225,-0.01329,0.05129,-0.01453,0.0491,-0.0403,-0.04251,-0.08421,-0.03718,0.03788,-0.01305,-0.01527,0.02357,-0.03871,-0.01906,0.00678,-0.07702,-0.06528,-0.07538,0.02293,0.06748,0.06191,0.05142,0.02677,-0.07534,0.04904,-0.02531,0.02801,-0.01355,-0.00482,0.05003,-0.02115,-0.05479,0.02032,0.03159,-0.0947,-0.06105,0.01957,0.00081,0.05472,0.01683,0.02597,0.01161,0.06581,0.03262,0.02267,-0.03683,0.01873,0.03859,0.00254,-0.00718],"recruiter/write-job-descriptions":[0.01849,-0.00506,-0.06216,0.04475,0.01791,0.00261,0.01211,-0.09701,-0.01603,-0.0126,-0.01505,-0.01274,-0.0041,-0.0297,-0.0555,-0.03673,0.0285,0.01694,-0.05439,-0.01101,-0.07582,0.00519,0.0129,-0.03566,0.04812,-0.02585,-0.0262,-0.00479,-0.07093,0.0411,-0.08295,-0.00955,-0.03516,0.01246,-0.04311,0.02568,-0.00575,-0.00619,0.00275,-0.00716,-0.03565,0.06002,-0.04249,-0.01676,0.02533,-0.01396,0.01052,-0.01487,0.04057,0.0203,-0.03553,0.03247,-0.03618,0.03577,-0.0652,-0.02775,0.00607,-0.02364,0.05691,0.03726,-0.0121,-0.0408,0.02665,0.05191,-0.00619,-0.0114,0.03166,-0.00455,-0.05119,-0.02531,-0.05097,-0.0306,0.02789,0.07509,-0.08622,0.04014,0.05323,-0.04638,0.00095,-0.01241,-0.00453,-0.07412,0.06533,0.00413,-0.01268,-0.01672,0.0173,0.02861,0.04538,0.01614,-0.03667,-0.03114,0.01655,0.04268,0.00317,-0.02797,-0.01554,0.08046,0.01813,0.02848,-0.00975,0.03001,0.06923,0.00533,0.03465,-0.00542,0.03577,-0.07373,0.0094,0.03035,-0.07697,0.02359,0.0148,0.00054,0.01546,0.02082,0.06827,0.05914,0.05761,-0.03867,0.03449,0.03177,-0.00657,0.02742,0.04009,-0.03648,0.06288,-0.03634,-0.05284,0.02318,0.04313,-0.00274,-0.03648,-0.00878,-0.02606,-0.0484,-0.01785,0.05199,0.05626,-0.02672,-0.05227,-0.0203,0.03766,0.02294,-0.0479,-0.03269,0.0053,0.00986,0.00216,-0.03765,-0.0498,-0.06572,0.01002,0.02256,-0.01903,0.03339,0.06783,-0.00453,0.08265,-0.03522,0.02266,-0.04517,0.05488,0.00175,-0.00727,0.05114,-0.04546,-0.0423,-0.05054,0.01576,-0.07865,-0.00117,-0.08604,0.04459,0.01407,0.04265,-0.04282,-0.03163,0.04847,0.03202,0.04272,-0.04652,0.04867,0.03681,0.02368,-0.00835,0.01215,-0.01482,-0.00083,0.04016,0.00778,0.00416,-0.04369,-0.04398,0.00071,-0.02033,-0.0181,0.04586,0.05276,-0.08585,-0.03828,0.01171,0.05612,0.0062,-0.03302,-0.0096,0.01939,-0.01941,-0.01737,0.01014,0.04033,-0.00325,0.08541,-0.01195,-0.0435,0.03153,0.05209,-0.04722,-0.01595,-0.02854,-0.03176,0.05407,0.01276,0.11443,-0.05225,-0.09023,-0.04385,-0.00589,0.02082,0.08386,0.00295,0.00934,-0.08004,0.05811,-0.00201,-0.02035,0.07011,-0.01579,0.03273,0.033,-0.03149,-0.08611,-0.02992,0.03197,-0.02557,-0.02054,0.08176,-0.01557,0.0011,-0.06627,-0.02188,-0.03241,-0.06444,0.05615,-0.01355,-0.05016,-0.01927,0.01751,0.02768,-0.02803,-0.00504,0.007,-0.02954,-0.04313,0.03408,-0.07597,-0.05385,-0.06675,0.06716,-0.04374,-0.04488,-0.01694,-0.01945,-0.04236,-0.0411,-0.04859,-0.0343,-0.0064,-0.10959,-0.01723,0.02591,0.00003,0.06477,0.08596,0.03674,0.01862,-0.0105,0.01373,-0.02056,-0.0157,-0.04132,-0.0637,0.02945,-0.04906,0.00817,-0.06323,-0.00033,0.02957,0.04192,-0.03241,0.07506,0.03539,-0.04059,0.04582,-0.0217,-0.00215,0.01488,0.03724,0.01406,0.09824,0.06026,-0.02283,-0.06845,-0.03053,0.0571,0.05504,0.00806,0.01829,0.00731,-0.02254,0.04298,-0.03937,0.1091,-0.03327,0.05629,0.04874,-0.01094,0.0263,-0.03191,0.00184,-0.03752,-0.00473,-0.02823,0.00618,0.02127,0.03011,-0.06606,-0.15257,0.04229,0.09172,-0.11755,0.02777,0.01311,-0.03273,0.03251,0.00305,0.02798,-0.08708,-0.11578,0.02308,0.06454,0.00898,-0.01452,0.08086,-0.04178,-0.08402,-0.00781,0.00641,0.00092,-0.00537,0.02814,-0.00653,0.01244,0.06347,0.09462,0.01394,0.06853,0.01736,-0.03544,-0.07396,-0.03123,-0.08246,0.00956,-0.0594,0.01643,-0.05055,0.00066,0.00426,0.0623,-0.01821,-0.06811,0.01861,0.05602,0.03866,0.03449,-0.02978,0.03945,0.00758,0.0298,0.0162,0.07261,0.05197,0.02178,-0.00702,-0.0156,0.00467,-0.04592,0.09284,-0.03667,-0.01335,0.0103,0.01349,-0.02565,0.02084,-0.11551,0.02459,0.02152,-0.01033,-0.00228,-0.03014,-0.02065,0.04249,0.01234,-0.00656,0.05823,-0.07999,0.04109,0.00401,-0.07461,-0.02617,-0.01305,0.1087,-0.04174,0.02676,-0.03821,-0.01236,-0.05018,-0.03507,-0.01561,-0.00508,0.03237,0.01842,-0.03786,0.01966,0.00258,0.05719,0.09261,0.03393,0.03855,0.01947,0.05662,0.07066,0.01386,-0.00455,-0.05002,0.06458,0.00767,0.08219,-0.00914,0.05632,-0.0582,0.07898,0.01724,0.01118,-0.03552,-0.00775,0.01146,-0.06449,-0.02123,-0.00668,0.03154,0.02306,-0.04173,0.02204,0.01492,-0.0277,0.00272,0.04014,0.04022,-0.05576,-0.01313,0.04114,0.02677,0.02619,0.01553,-0.06439,0.07108,0.0107,0.07069,-0.05058,-0.06856,0.0328,0.01475,-0.00916,0.00188,-0.01912,0.14402,-0.00432,0.04923,0.10815,0.06676,-0.02787,-0.05132,-0.03965,0.03938,0.04704,-0.10054,-0.05709,0.03594,-0.02682,0.07566,0.01411,0.03999,0.04602,0.07914,0.04817,0.03001,-0.03076,-0.11671,0.07666,-0.05007,0.03223],"recruiter/schedule-interviews":[-0.05775,-0.01772,0.03103,-0.01457,0.05665,-0.02088,0.0291,-0.00659,-0.03272,-0.01003,-0.0353,0.04457,-0.02411,0.06029,0.03554,-0.00767,0.04102,0.00807,-0.08949,-0.09202,-0.02675,-0.04644,-0.05491,0.02951,0.00802,0.06352,-0.02965,0.01279,-0.03227,0.0178,-0.02642,0.05748,-0.02991,-0.04425,-0.02001,0.00628,0.00395,-0.04953,0.06338,0.06488,0.05878,-0.02997,-0.02307,0.0336,-0.01181,-0.05659,-0.07901,-0.00593,0.01701,0.04393,0.03561,-0.04232,-0.04217,0.02715,-0.01241,-0.06157,-0.03729,-0.08489,0.04275,-0.05155,0.03815,-0.10278,-0.04622,0.061,-0.0438,-0.03091,-0.00142,0.01151,-0.0571,0.04523,-0.00895,-0.0341,0.05931,0.03405,0.00858,-0.05929,-0.00535,0.02856,0.03835,0.07626,-0.01726,-0.0611,0.01005,-0.06254,-0.04772,-0.01912,-0.06715,0.04221,0.01477,0.01792,-0.03098,-0.00576,-0.00145,0.03041,-0.01501,-0.01825,0.03595,0.03598,-0.04012,0.01087,-0.04816,-0.0018,0.02305,0.02643,-0.00708,-0.05238,-0.02035,-0.01519,-0.03999,0.09183,-0.00631,0.00312,0.0142,-0.04085,0.03316,-0.05324,-0.01773,-0.10562,0.06474,-0.02807,0.08174,0.06905,-0.09017,-0.01663,-0.04227,-0.0496,0.02989,-0.02265,-0.00588,0.03093,-0.06732,-0.0063,-0.08016,0.05661,-0.05249,-0.04256,0.00803,0.01462,0.01439,-0.01183,0.00169,0.07004,0.00987,-0.00013,0.02245,-0.00811,-0.00948,-0.00822,0.00019,0.02303,0.00437,-0.04923,0.02758,0.05606,0.08917,0.02438,0.04681,0.04188,0.02276,-0.02402,-0.08704,0.00826,0.03588,0.05458,0.02643,-0.00196,-0.03074,0.02359,0.02709,-0.00196,-0.04977,0.06632,-0.07241,0.01861,0.00132,0.00426,-0.04587,-0.02665,-0.11558,-0.01079,0.05073,0.02497,0.00916,0.06028,-0.05245,-0.06726,-0.00452,-0.02032,0.00641,0.06486,0.02886,-0.02492,-0.07451,-0.02107,-0.04095,-0.00636,0.04902,0.00174,-0.02008,-0.06925,0.0608,0.00532,0.06017,-0.06318,0.02928,0.03768,-0.01102,-0.00367,0.11058,-0.03651,0.02723,-0.03438,0.01378,0.08599,-0.01283,-0.04444,-0.01062,0.04117,0.0148,0.00937,-0.0172,-0.06165,-0.0282,0.0513,0.02238,0.0601,0.0029,0.04907,0.00823,-0.01201,0.04139,0.00255,0.01337,-0.17589,0.00999,-0.06561,-0.01899,-0.06268,0.07447,-0.00544,0.01729,-0.0649,0.04918,0.04899,-0.07181,0.01558,-0.00537,0.04894,-0.07646,-0.04448,-0.01579,0.07095,-0.00584,0.00881,0.01484,0.08283,0.04548,-0.0388,0.07334,0.02213,-0.00586,0.08073,0.06733,-0.03069,0.05809,-0.01124,-0.05575,0.00047,0.01474,0.02552,0.02362,-0.00703,0.03978,0.03024,-0.0374,-0.03625,-0.00854,-0.02196,-0.06885,-0.03014,-0.01757,-0.00629,0.07316,0.07043,0.05021,-0.02701,-0.00139,0.00938,0.03047,0.00416,0.01421,-0.00268,0.17418,-0.00466,0.0106,0.00473,-0.01398,-0.00911,0.03872,-0.00036,0.00071,-0.06166,-0.02695,-0.01141,-0.00731,0.12156,0.06341,-0.00818,-0.01181,-0.03646,-0.01136,-0.02244,0.01827,0.07172,-0.01031,-0.05657,0.03615,-0.00275,-0.07848,-0.0549,0.00257,-0.03717,0.00356,0.08237,0.0809,0.02277,0.01594,0.07387,-0.03223,0.01789,0.00381,-0.05934,-0.00537,0.04339,-0.04634,-0.02516,-0.06833,-0.05238,0.11362,0.08782,-0.01856,-0.02894,0.02047,-0.02371,0.04965,0.00272,-0.0441,0.07068,-0.0518,-0.03174,0.05458,0.0135,-0.04252,0.04869,-0.0261,-0.006,0.00886,0.01847,-0.04504,-0.04154,0.02532,-0.03176,-0.01293,-0.01778,0.03236,-0.02842,-0.01289,0.01995,-0.04208,0.02172,-0.05418,-0.05878,0.03232,-0.0002,0.0076,0.00795,0.00689,0.01442,0.03646,0.06946,-0.0209,0.05357,0.03975,-0.02109,-0.03269,-0.00019,0.04378,0.07996,0.03743,0.04213,0.02116,0.10903,-0.04631,-0.05441,0.03258,-0.00534,0.06086,-0.01719,-0.04778,-0.00663,0.01825,-0.00683,-0.00206,0.02525,0.00472,0.00842,0.03925,0.03804,-0.06488,0.03142,-0.00616,0.02963,-0.00682,0.00927,-0.01231,-0.09105,0.03128,-0.05644,-0.01063,0.0042,0.04826,-0.02494,-0.01284,-0.05583,-0.04238,0.02373,-0.00519,-0.01978,-0.00406,0.08796,0.03193,0.0339,-0.00885,0.01399,0.04872,0.04334,0.06946,0.10055,0.0641,-0.05479,0.09282,0.06044,0.01093,0.05562,0.0035,0.06119,-0.01228,-0.02234,0.0097,0.01863,-0.03444,0.01734,0.00999,-0.12003,-0.04761,-0.03917,0.00562,0.02609,-0.00863,0.00316,0.01949,-0.0206,-0.0171,-0.04647,0.0331,0.05873,-0.04308,-0.07112,0.01345,-0.0132,0.03931,0.0424,-0.00332,0.02085,-0.04325,-0.01472,0.02697,0.02268,0.00285,-0.03869,-0.0217,0.04629,0.02902,0.09788,0.07647,-0.0758,0.05428,0.00031,0.01682,-0.00195,0.00246,0.03891,0.03961,-0.01687,-0.01028,0.02198,-0.12563,-0.01299,0.03494,0.01595,0.03982,0.00438,0.04177,-0.03772,0.00582,0.04154,-0.0137,-0.05393,0.04903,0.12073,-0.00712,-0.00168],"sales/write-outreach":[-0.0484,-0.02983,-0.02417,-0.03536,0.04089,-0.04794,0.03,-0.02358,-0.05519,-0.07543,-0.05376,-0.01096,0.02288,0.04117,-0.03235,-0.06677,0.04092,-0.00925,-0.09441,-0.06996,-0.05123,-0.07438,-0.03028,-0.00403,-0.00013,0.08227,0.04986,0.04806,-0.02156,0.03542,-0.05096,-0.03559,-0.02002,0.00923,0.05891,0.02598,-0.04675,0.01602,0.01796,0.07866,0.00482,0.02613,0.00791,-0.0248,-0.02504,-0.00617,0.05573,0.03024,0.05101,0.0693,0.03208,0.00358,-0.03641,-0.03197,-0.02128,0.00891,-0.00856,0.00503,-0.00027,0.0042,-0.03165,-0.00375,-0.0183,0.0159,0.01564,-0.01756,0.01075,0.02818,-0.04947,-0.06802,-0.01575,0.03,-0.05247,0.06854,-0.0218,-0.03357,-0.00919,-0.0234,0.0563,0.00703,-0.01541,-0.06319,0.03196,-0.04794,0.02429,0.03213,-0.00424,0.01019,0.04588,0.07883,-0.01753,-0.07013,-0.04164,0.048,0.01025,-0.11646,0.03505,0.07508,-0.00485,0.0233,0.0223,-0.07774,0.04398,-0.02913,0.09469,-0.04506,0.05205,-0.08339,0.01065,0.11597,0.07082,-0.00464,0.02726,0.04333,0.04447,0.03189,-0.00048,-0.0394,0.0435,-0.05803,-0.01366,0.03519,-0.00873,-0.01831,-0.0688,0.06542,-0.01207,-0.07372,-0.03549,-0.02811,0.02784,0.06957,-0.05178,-0.06781,-0.01349,0.02067,0.00925,0.02193,0.05564,0.0013,-0.03483,-0.04491,0.05458,0.10668,-0.04946,-0.12184,-0.05902,0.05688,0.00312,-0.00093,-0.00344,0.03091,-0.01063,-0.0368,-0.0026,0.04186,0.05826,0.00507,-0.01041,-0.01095,-0.06226,-0.03539,-0.02367,0.02681,0.0018,-0.03623,-0.01281,-0.0208,0.05393,-0.09481,-0.08887,0.03841,-0.03991,0.00545,-0.05717,-0.05985,-0.03407,-0.04941,-0.01577,0.01453,-0.03725,-0.05753,-0.0502,0.05492,-0.04338,-0.0299,-0.03917,-0.00147,0.07064,0.03563,0.1004,-0.04049,-0.07449,-0.03255,-0.00522,-0.03771,0.00963,0.04342,-0.01861,0.01291,0.02095,0.03513,-0.00827,-0.07825,-0.13156,0.04452,-0.05882,0.02605,0.04667,-0.04423,0.04439,-0.02888,-0.01348,0.04536,-0.00801,-0.03225,0.00716,-0.06091,0.01379,0.07366,0.03332,-0.03006,0.07795,0.0022,-0.04001,0.02155,-0.0391,-0.00326,0.07971,-0.02916,0.08366,0.02385,-0.02523,-0.02878,0.03252,-0.00874,-0.04632,-0.06576,-0.02462,-0.04015,0.02542,-0.00844,0.0364,-0.0132,-0.03358,0.04463,-0.00325,-0.03325,-0.09212,0.03402,-0.04864,0.05422,0.00096,0.0109,0.04078,0.01552,0.01047,0.01268,0.01753,0.05561,-0.16431,-0.03233,0.00501,-0.04166,-0.0046,-0.02002,-0.0056,-0.0334,0.06414,-0.07703,0.0167,-0.00551,0.05053,-0.00269,-0.0225,-0.02674,0.00782,0.08364,-0.07994,-0.08607,0.03158,0.00559,-0.04663,-0.02013,0.03632,0.02082,-0.02162,0.02473,0.0162,0.0122,0.01844,-0.04885,0.02888,-0.05764,0.04347,0.02039,-0.03775,-0.00014,0.00173,-0.03552,-0.03677,-0.0338,0.02302,0.0185,-0.05891,-0.00664,-0.02424,0.02743,-0.03095,-0.0734,0.03145,-0.01501,-0.01694,-0.01411,0.05421,-0.02193,-0.02209,0.05922,-0.03674,-0.07867,0.04522,0.0138,-0.0026,-0.02094,-0.01088,0.02006,-0.00901,-0.02473,-0.03459,-0.01067,-0.05581,-0.04012,0.03708,0.07625,-0.01089,-0.02273,0.08983,-0.01936,0.01668,0.0418,-0.03937,-0.04776,-0.03723,0.03648,0.08054,0.07914,-0.10306,-0.13018,-0.02823,0.00112,-0.00929,-0.00192,-0.00588,-0.00798,-0.03679,-0.06586,0.00097,-0.04419,-0.01603,0.04758,0.03328,0.03765,0.16154,0.01611,0.03736,0.0463,0.03499,0.02444,0.0317,0.0463,-0.00742,-0.06571,0.03553,0.01611,-0.01926,-0.0356,-0.05859,0.02431,0.05771,0.0601,-0.00376,0.00167,0.0129,-0.05704,-0.003,-0.00205,-0.04289,-0.01396,-0.06146,-0.02421,-0.05586,0.05947,0.02016,-0.02335,-0.10677,0.03697,-0.0255,-0.03042,-0.05635,-0.01838,0.01301,0.0071,-0.01228,0.02047,-0.00051,-0.02885,-0.01798,0.01353,-0.01432,-0.03909,-0.00207,0.03523,0.03004,-0.06097,0.07537,-0.0068,-0.03814,-0.0579,-0.06801,-0.01529,0.06328,-0.02089,-0.03152,-0.02003,-0.09128,0.07558,0.00879,-0.00876,-0.07452,0.04126,-0.03807,-0.01174,0.01781,-0.0358,0.02153,0.04116,0.04489,0.03064,0.0459,0.0071,-0.03902,0.0591,-0.04443,0.04145,-0.05171,-0.00815,0.0083,0.01876,-0.07663,0.043,0.00529,0.00354,-0.03411,0.03165,0.02783,0.04126,0.00516,-0.01774,0.02946,0.07634,-0.01589,-0.0209,-0.05544,0.06652,0.04644,0.02279,0.00719,-0.0734,-0.0267,0.01478,0.0809,-0.01479,0.00465,0.02019,0.03887,-0.02368,-0.04711,0.02954,0.01524,0.06395,-0.09146,-0.06558,-0.03836,-0.01552,-0.0067,-0.03029,0.04093,0.0178,0.02386,-0.03711,-0.03904,0.0476,0.00613,-0.01151,0.02253,-0.08665,-0.05889,0.01792,0.0076,-0.01317,0.10111,-0.012,0.01371,0.02183,-0.0183,-0.00563,0.00762,-0.02842,-0.01137,0.07866,0.04643,-0.00196],"sales/create-proposals":[0.00228,-0.09215,-0.01286,0.06108,-0.00913,-0.06061,-0.06987,0.07113,-0.02202,-0.05698,0.00017,0.05542,-0.12657,-0.06469,0.01443,-0.03487,0.0297,-0.0008,-0.02267,-0.04977,-0.0141,0.02395,-0.02699,0.00926,0.02221,0.00785,0.01375,0.05554,0.01481,-0.00778,-0.06556,0.03423,-0.0221,-0.03123,0.01089,-0.04671,0.00589,-0.01915,0.03722,-0.05519,0.00208,0.06465,0.00848,-0.03936,0.01464,-0.02235,0.01655,0.02809,0.1083,0.01135,-0.09029,0.07701,-0.03009,0.06002,0.01264,0.02188,0.03277,-0.03456,0.03145,-0.016,0.01166,-0.00184,-0.01043,0.00589,0.02321,-0.07052,-0.00403,0.00099,-0.03546,-0.06966,-0.099,0.02649,0.06049,-0.03087,-0.00941,-0.08573,0.08288,-0.02649,0.06963,0.04657,-0.02282,-0.00543,0.01433,0.00174,0.02008,0.00414,-0.05617,-0.01679,0.06319,0.04391,0.01043,-0.06103,0.05138,0.03736,-0.00966,-0.02806,0.03589,-0.01317,-0.03829,-0.00528,0.14581,-0.00668,-0.06234,-0.02298,-0.01809,-0.06496,-0.01776,-0.08445,0.03723,0.10248,-0.05639,-0.00182,-0.06469,-0.03607,0.05049,-0.01573,-0.01043,-0.01083,0.01562,-0.10594,0.0772,0.01275,-0.00877,-0.05278,-0.0238,0.00347,-0.00613,-0.07213,-0.03262,-0.00717,0.08582,0.10767,-0.04437,-0.00358,-0.03337,0.01159,0.0372,0.02401,-0.03514,-0.01535,-0.09858,-0.04645,-0.02393,0.09943,0.08432,-0.10428,-0.01257,0.07407,-0.02765,-0.04533,-0.01112,0.00726,0.03521,0.05665,0.05691,-0.01586,0.02538,0.00898,-0.03891,0.03124,-0.06239,0.00747,0.03018,0.01643,-0.00326,-0.03464,0.01836,0.02213,0.04018,-0.03323,-0.07121,0.02874,-0.08315,-0.0437,-0.03764,-0.02449,-0.03648,0.08385,-0.02069,0.00528,-0.01715,-0.03922,0.02125,0.0605,-0.08723,0.00744,0.00957,-0.01506,0.00602,0.00894,0.03301,0.01014,-0.03292,0.05464,-0.03523,0.05274,0.0064,0.04143,-0.04304,-0.02838,0.07064,0.02475,-0.13375,-0.01604,0.04211,0.07266,0.04675,0.01695,0.02888,-0.10042,-0.01772,0.0163,0.01228,0.02637,0.08085,-0.00633,0.03586,-0.02829,0.00086,-0.03672,0.00872,-0.05346,0.00696,0.01279,-0.01332,0.02788,-0.0122,0.0304,0.00558,0.03739,0.06704,-0.02557,0.06245,0.05335,-0.02721,0.04359,0.00609,-0.03062,0.02368,-0.01954,0.0015,-0.02701,0.04642,-0.06127,0.06049,0.03379,0.06329,-0.06909,-0.07363,-0.04513,0.05426,0.02985,-0.03725,0.00222,0.00788,-0.00892,0.00298,-0.04775,-0.00628,0.10029,-0.0607,0.0009,0.02871,-0.00332,0.05116,-0.03427,0.01088,-0.05253,0.04696,-0.13099,0.02751,-0.01735,-0.00075,-0.02126,0.05535,0.0129,0.00916,-0.00855,-0.08846,0.04025,-0.00633,0.05218,-0.01072,0.02062,0.00688,0.02365,-0.00829,-0.03831,0.08947,-0.0289,-0.09097,-0.07608,-0.07703,0.01392,0.05529,-0.02186,0.03113,-0.00572,0.04675,-0.00768,0.02544,-0.11278,-0.08479,0.00915,-0.02604,0.02014,-0.04376,0.03323,-0.00961,-0.07692,-0.01467,-0.00024,0.0424,-0.01147,0.02829,0.00526,-0.03148,0.01886,-0.03094,-0.02412,-0.12873,-0.00186,-0.01694,0.00861,0.10797,0.02459,-0.03912,0.04479,-0.02334,-0.05972,-0.02176,-0.05199,-0.0617,-0.01558,-0.03396,-0.02179,-0.00756,-0.04327,0.03354,0.09512,-0.01256,-0.00239,0.00521,-0.03305,0.03122,0.01132,-0.04587,-0.00475,0.03839,-0.0303,-0.00729,-0.03385,0.01156,0.01223,-0.02246,-0.02177,0.03493,0.03935,-0.00945,0.00785,-0.01913,-0.02013,-0.05457,-0.024,0.02627,0.05261,0.0202,0.0037,-0.0382,-0.01563,0.00788,-0.034,0.02807,0.01912,-0.04149,-0.02871,-0.03779,0.07181,-0.0159,0.09435,-0.00502,-0.03234,0.06527,-0.01979,-0.0591,0.02276,-0.0099,-0.06796,-0.00065,0.01582,0.00156,0.00983,-0.01675,-0.02253,-0.01282,0.0616,-0.01135,-0.05406,0.022,0.01041,-0.02469,-0.03823,-0.032,0.02011,-0.01607,0.02997,0.00794,-0.05938,0.00161,0.0084,-0.05696,0.04978,0.04699,-0.02068,0.036,-0.0168,0.0231,-0.08474,0.01234,-0.03484,0.02206,0.07031,-0.03424,0.00661,0.04238,0.01879,-0.00286,-0.02977,-0.05305,0.01279,0.00513,0.01955,-0.07589,-0.00337,0.0936,0.07805,-0.00385,0.00908,0.07578,0.10409,0.07014,0.07556,-0.01411,-0.00819,-0.0324,-0.00519,-0.03264,0.01949,0.04462,0.00407,0.05648,0.04181,-0.01816,-0.05498,-0.0266,0.00805,-0.00339,0.01345,-0.01045,0.04306,0.03976,-0.01481,-0.06494,-0.01122,0.05715,0.02053,-0.04366,-0.04927,0.01835,0.00046,0.03008,-0.00318,-0.05443,-0.01978,0.00324,-0.01186,0.01208,-0.01096,-0.00152,-0.05688,-0.02839,0.00802,0.09573,-0.03705,-0.06058,-0.08053,0.07138,-0.00462,0.08311,-0.07011,0.03276,0.02795,-0.01572,-0.00323,0.0762,-0.0092,-0.04233,-0.02887,-0.0436,-0.0001,0.02598,-0.02164,0.05871,-0.06265,-0.03435,0.04291,0.03208,-0.06696,0.03304,0.02532,-0.02834,0.05139],"sales/answer-customers":[-0.00351,0.00024,-0.02296,-0.00013,-0.02481,-0.0257,-0.01851,-0.0239,-0.02292,-0.04616,-0.03884,0.05066,-0.05941,0.02608,0.00094,0.05642,0.02947,-0.01466,-0.05216,-0.01145,-0.06013,0.03008,-0.08284,-0.00048,0.03771,0.04184,0.00216,0.0298,-0.00016,0.00996,-0.03115,0.05255,0.07695,-0.00527,0.01267,0.01289,0.00926,0.04026,0.00218,-0.02852,0.07521,-0.00492,0.04207,-0.0345,0.05617,0.02876,-0.07248,0.00791,0.0339,-0.01228,-0.0471,-0.0791,-0.02321,-0.01324,-0.02848,0.04619,0.06692,0.00679,0.0122,0.05819,-0.00039,-0.00942,0.02456,0.00884,0.01329,-0.06363,-0.00358,0.00966,0.00332,-0.042,-0.04975,-0.02343,0.04536,-0.01044,-0.01748,-0.08738,0.05691,-0.02343,0.02149,0.001,-0.0523,-0.06552,0.07354,-0.03506,-0.05785,-0.06109,0.08252,0.04416,0.10146,0.10917,-0.00713,0.06304,-0.03463,0.0653,-0.05052,-0.04238,0.01795,0.01523,-0.03844,-0.0727,0.11348,-0.00879,-0.02989,0.05797,-0.01793,0.01054,0.02,-0.03435,0.00436,0.04642,-0.00685,0.01603,-0.06234,-0.01615,0.00244,-0.0371,-0.01628,-0.04596,0.06406,-0.05949,0.05249,0.01155,-0.06497,0.03703,-0.02246,-0.00705,-0.0201,-0.08596,0.00141,-0.0086,0.01712,0.05914,-0.03527,0.01094,-0.03629,0.00402,0.06522,0.07236,-0.07296,0.05152,-0.00733,-0.08078,0.04687,0.0204,0.03789,-0.05174,0.03438,0.0887,-0.03227,0.03799,0.00528,-0.02861,0.05135,0.01207,0.0052,0.05025,-0.03261,-0.00583,0.03601,-0.06429,-0.11989,-0.02537,0.01813,-0.04495,0.00569,0.04513,0.04427,0.02024,-0.00037,-0.05765,0.01966,0.01749,-0.06681,-0.0142,-0.05829,-0.03664,-0.04131,0.06433,-0.03465,0.00215,0.01627,0.00939,0.05861,0.02324,-0.05261,-0.09233,-0.0174,-0.00076,-0.00053,-0.02518,0.08531,-0.00551,-0.0768,-0.02671,-0.02379,0.00637,0.01424,0.01249,-0.05855,-0.09602,0.11549,0.03235,-0.01387,0.08156,0.00637,0.06606,0.04832,0.00409,0.01907,-0.08146,0.00195,0.01389,-0.02606,-0.01242,0.0092,0.0618,-0.008,0.03603,0.01755,-0.07176,-0.03369,-0.05697,0.0938,-0.04785,0.02023,0.01992,-0.00057,-0.01592,-0.00939,0.0438,0.04627,0.0015,0.04289,0.06334,0.01991,0.07884,-0.05901,-0.00321,0.039,-0.02012,-0.00292,-0.04403,0.04379,-0.00748,0.04857,0.0224,-0.01125,0.03775,0.03303,-0.01504,0.05335,0.0505,-0.03814,0.00966,0.05624,-0.00146,0.01871,0.01614,-0.00288,0.06172,-0.05571,0.01039,0.07236,0.06702,-0.00153,-0.01426,-0.00434,0.00442,-0.04311,-0.02778,0.02356,0.03317,0.02843,0.01003,0.05798,-0.02746,-0.02206,0.02559,-0.11528,0.01104,-0.01525,-0.0284,0.01718,-0.10089,-0.02579,-0.01562,0.01749,-0.03264,0.05838,0.00252,0.00169,-0.09594,-0.02276,-0.02731,0.0305,-0.04218,-0.03965,0.07416,-0.00556,0.02376,-0.02978,-0.01029,0.00816,0.02616,0.02481,-0.01355,0.02306,-0.05795,0.02046,-0.08395,0.0404,-0.00473,-0.00393,-0.08465,-0.00947,-0.06705,-0.04718,0.03476,-0.07688,-0.00211,-0.02672,0.03607,-0.05698,-0.02005,0.01406,0.0291,-0.05509,0.0496,0.00805,-0.00306,0.00071,-0.01418,-0.039,0.00994,-0.03614,0.04371,0.00137,-0.05188,0.00069,0.09832,-0.07996,-0.06578,-0.01432,0.03289,0.03931,0.05581,0.06775,0.04612,-0.02057,-0.07798,-0.03039,0.01071,-0.00104,-0.05577,-0.01473,-0.06528,-0.0032,-0.11201,-0.00358,-0.02234,-0.00497,-0.02957,-0.08893,-0.02777,-0.00854,0.02676,-0.03912,0.03875,-0.00502,-0.06918,-0.05239,-0.07942,0.04623,0.08033,-0.00357,0.00139,-0.01292,0.04248,0.04672,0.04461,-0.00631,-0.02951,0.09514,-0.02026,-0.09456,-0.01886,0.02233,-0.11186,0.03369,0.05228,-0.01515,0.00802,-0.00187,-0.02475,-0.02727,0.08152,-0.00138,-0.08731,0.06652,0.04589,0.01818,-0.04406,0.02185,0.01246,0.01939,0.01821,-0.04153,-0.01964,0.05507,-0.00567,0.0194,-0.00599,0.00736,-0.04745,0.03547,-0.07924,-0.06253,-0.11767,-0.00626,-0.01255,0.04506,-0.00821,0.00696,-0.01506,-0.02813,0.02976,0.01078,-0.02728,-0.07088,-0.01677,0.00269,0.08609,-0.05457,-0.08567,-0.00732,0.04284,0.00825,0.04276,0.05063,-0.01476,-0.00548,0.06187,-0.02554,0.00783,-0.11014,0.02845,-0.03503,0.07178,0.00249,-0.007,0.0295,0.01197,0.00615,-0.04349,0.00724,-0.0073,0.03681,0.07891,0.03908,0.00403,0.0171,-0.02277,-0.05981,0.09116,0.02986,0.02114,0.04308,-0.0361,-0.03206,-0.05542,0.0896,-0.0028,-0.00446,-0.00111,0.00495,0.04269,0.0298,-0.0533,-0.09102,-0.02571,0.05422,0.06789,0.02068,0.00079,0.0238,-0.04757,0.00208,0.00467,0.03626,-0.04679,0.06876,0.04657,-0.03767,0.04155,0.05271,0.00699,0.012,-0.07069,0.07596,-0.03354,0.06793,0.04583,0.00999,0.01161,0.03555,-0.00601,0.03689,-0.03538,0.00688,0.05794,0.05317,0.03422],"sales/research-prospects":[-0.04009,-0.04487,0.03502,0.03918,0.03368,-0.00082,-0.01408,-0.0014,0.04844,-0.03907,-0.02807,0.02161,-0.11372,0.00475,0.00659,-0.06442,0.01078,0.07486,-0.03769,0.05153,-0.01655,0.0301,-0.05358,-0.01315,0.10076,0.0365,-0.06019,0.07658,0.04509,0.01632,-0.04694,0.03378,-0.01524,-0.04337,-0.05009,-0.04186,0.05966,-0.08887,0.00671,0.05079,0.02506,-0.03324,0.00747,0.04381,0.05342,-0.01114,0.02229,0.02597,-0.02022,0.07564,0.02834,0.01745,-0.01609,0.0365,-0.03338,-0.00584,0.01635,0.03207,0.01034,-0.00369,0.02908,0.04488,-0.0481,0.03319,-0.03142,-0.05122,0.01661,0.00289,-0.07686,-0.04264,-0.00987,-0.04195,-0.01145,0.00107,-0.00016,-0.00411,-0.03207,0.04172,0.02699,0.02971,-0.02346,-0.03975,0.0683,-0.03663,-0.025,0.00312,-0.0437,0.07349,0.06534,0.04437,-0.00915,0.02676,0.00296,0.03338,-0.00924,-0.04878,-0.01048,0.06276,-0.09752,-0.05982,0.06854,0.0586,0.00962,-0.02637,0.04422,-0.00262,0.0071,-0.03741,-0.02716,0.03762,-0.05465,-0.019,-0.01079,0.01412,-0.03416,-0.02881,-0.05551,-0.08561,0.01166,-0.05138,0.08801,0.0255,-0.12462,-0.00781,0.00227,-0.02168,-0.07819,-0.06229,0.04763,-0.02505,-0.03032,-0.00447,0.02312,0.03807,-0.07619,-0.00391,0.05345,0.02363,0.06201,0.03387,0.03512,0.00778,-0.03565,0.0915,0.05751,-0.03965,-0.02168,-0.01629,-0.00119,-0.08362,0.02536,0.00944,0.0177,-0.01302,0.02033,0.04618,-0.01585,0.08798,-0.01483,-0.03974,-0.0148,0.08157,0.04673,-0.03164,-0.02222,0.00371,-0.05185,-0.01037,-0.07585,-0.01622,-0.08343,0.0997,-0.07163,-0.0464,-0.00866,-0.05143,-0.04488,0.04707,-0.03369,-0.01604,0.04716,-0.10424,-0.02447,0.07221,-0.05897,-0.00804,0.01368,-0.07452,-0.02998,0.03999,0.01071,0.01602,0.00647,-0.04589,-0.05077,0.08635,-0.01817,0.05071,-0.00991,-0.0378,-0.0135,-0.00212,-0.03404,-0.06035,0.03207,0.01324,-0.03089,0.0079,0.0419,-0.02992,-0.00181,0.03891,0.0283,0.07532,0.04715,-0.0188,0.01704,0.01736,-0.01774,-0.04683,-0.02445,0.00587,-0.01598,0.06137,-0.03436,-0.00588,0.03664,-0.02716,0.03574,0.04558,0.07516,-0.01855,0.01826,-0.03752,-0.00068,-0.0584,-0.02974,-0.04198,-0.00067,-0.03712,0.03432,-0.04962,-0.03926,0.00408,-0.04289,0.04066,0.0566,-0.01442,-0.05202,-0.05506,0.07896,0.03488,0.05,-0.00264,0.00918,-0.01942,-0.04097,0.04912,0.05246,-0.00941,-0.06229,0.02092,-0.02056,0.00614,0.01635,-0.00817,-0.04789,-0.01597,0.0807,-0.01446,0.00639,-0.00717,-0.00686,0.01507,0.04574,-0.04266,0.07795,0.03365,-0.10629,-0.04054,-0.02396,-0.02113,-0.03461,-0.03992,-0.06526,0.01599,0.0076,-0.01052,0.06105,-0.05113,-0.01229,-0.05942,0.04029,0.01521,0.03943,-0.04706,0.00151,-0.00213,-0.00036,-0.06802,-0.04238,-0.00287,-0.02999,-0.07353,-0.08272,0.10351,-0.02659,-0.00188,0.02784,0.03131,-0.07457,0.05151,0.01748,-0.05375,0.03472,0.0202,-0.02568,0.02449,-0.02618,-0.04453,-0.0273,0.01807,0.04708,-0.00913,0.05041,0.04606,-0.0507,0.04587,-0.03874,-0.02881,0.00077,-0.08455,-0.04174,0.01818,0.04005,0.02078,-0.01101,0.00185,0.0753,-0.01724,-0.09872,0.08309,-0.00739,-0.01323,0.05108,0.0887,0.06304,-0.0252,0.02771,0.02083,-0.02343,-0.02917,-0.00368,0.02305,-0.0478,-0.00648,0.04342,-0.06597,0.00409,0.0128,0.013,0.00719,0.02582,-0.03302,-0.05314,-0.05471,0.03081,0.02067,-0.07262,0.04342,0.0059,-0.01741,0.05555,-0.01128,0.04026,-0.08258,-0.03647,0.07241,0.00532,0.08927,0.01954,-0.07625,0.09619,0.03908,-0.02788,0.05681,-0.04895,-0.00608,0.00319,0.00024,-0.0694,0.04706,0.03164,-0.03253,0.01666,0.00612,-0.01604,-0.04007,0.03797,0.06629,-0.01078,-0.05075,0.01605,0.0076,0.03809,-0.00137,-0.01763,0.03775,-0.07684,0.02186,-0.03022,0.1078,0.07915,-0.02816,0.03853,-0.01868,-0.0442,-0.08336,-0.07984,-0.06746,0.03977,0.01433,-0.05525,0.04533,0.00771,0.05295,-0.05176,-0.07089,-0.09922,-0.05556,-0.02828,-0.01454,-0.00125,-0.00793,-0.08007,-0.01217,0.07699,-0.00254,0.03675,0.05847,0.02536,0.05321,-0.03243,0.09747,-0.06642,0.08065,-0.02015,-0.01604,-0.00965,-0.00692,0.00687,-0.01489,0.00867,0.07817,0.01952,0.00003,0.07056,0.06013,0.01053,0.03493,-0.00316,-0.07604,-0.06237,0.08573,-0.03882,-0.04416,-0.00013,-0.02493,-0.02982,-0.01061,0.01752,0.03719,-0.07341,-0.02822,0.04905,-0.01227,0.03629,-0.09619,0.0246,-0.00471,0.00377,0.05247,0.05247,-0.05175,0.00568,-0.05815,0.07257,-0.01342,0.00405,0.01338,0.02777,0.02268,-0.02562,-0.01747,0.03112,0.00024,-0.02975,-0.03511,-0.00393,0.01378,0.09965,-0.08298,0.06854,-0.05,0.02129,0.01593,-0.03245,-0.00498,-0.00806,0.02836,-0.00587,-0.03467],"sales/update-crm":[-0.03083,-0.04071,-0.02309,0.05748,0.07568,0.0029,-0.0535,-0.07119,-0.00803,-0.01364,-0.07137,-0.01283,0.02375,-0.03484,-0.00323,0.00181,0.01876,0.06101,-0.04981,0.0518,-0.00228,0.00548,0.03442,0.01923,0.01492,-0.02412,0.00024,-0.05118,0.01559,-0.0112,-0.02395,-0.00845,0.01304,-0.02213,-0.02252,-0.06036,-0.01629,0.06342,-0.00015,0.06398,0.02268,0.04562,0.00894,-0.04437,-0.01478,0.08799,0.07787,-0.00713,-0.01551,0.01646,-0.01921,0.04962,-0.05181,-0.02955,-0.04451,0.02573,-0.0444,-0.01721,-0.04663,-0.00001,0.04834,0.03861,-0.04016,0.03244,0.00123,0.02819,-0.00087,0.00657,-0.0435,-0.02378,-0.07115,0.0715,0.06239,0.04617,-0.02902,-0.00894,0.01792,0.05127,0.04187,-0.0248,-0.06024,-0.07009,0.04791,-0.05839,0.00482,0.07846,0.0194,0.00236,0.08102,-0.00515,-0.03835,0.00231,-0.02527,0.07964,0.00765,-0.07427,-0.02096,0.0242,-0.07221,-0.03566,0.07359,-0.07025,-0.07437,-0.06022,0.10421,-0.03216,0.02168,-0.0652,0.09766,0.08308,-0.03944,0.01641,0.00846,-0.05019,0.00787,-0.03733,-0.05633,-0.07682,0.10685,-0.03854,-0.00177,0.01686,-0.02171,-0.04878,-0.01827,0.01402,0.09176,-0.02031,0.03042,-0.07716,-0.0465,-0.02512,-0.02615,0.00337,-0.09686,0.01714,-0.00607,0.01269,-0.01507,0.01535,-0.00519,-0.02377,0.02149,0.07324,-0.03965,-0.00839,-0.04009,-0.03684,0.0218,0.01515,-0.05457,-0.00399,-0.01364,0.00762,0.08821,0.02398,-0.07079,0.03066,-0.00677,-0.06562,-0.02408,0.09454,0.09465,0.02854,-0.02087,-0.09844,-0.0194,-0.03744,-0.08589,0.00634,-0.08541,0.01693,-0.09661,-0.04373,-0.03872,0.04905,-0.01244,-0.02497,-0.10187,-0.06224,-0.01997,0.00369,-0.03363,0.03542,-0.05889,-0.00767,-0.00368,-0.04923,0.00173,0.05368,-0.00737,0.01258,-0.0599,-0.01299,-0.05973,0.01597,0.01142,-0.04217,0.01873,0.075,0.03281,-0.00724,0.05006,-0.09126,0.02902,0.04676,-0.00454,0.00406,0.03372,-0.01452,-0.00302,0.02456,-0.01571,0.00669,-0.02994,0.0513,0.02729,-0.00434,0.00272,0.02099,-0.0124,0.0037,0.07441,-0.03164,0.04585,0.07776,-0.12325,0.05219,0.03819,0.04819,-0.02083,0.07273,-0.03468,-0.15412,-0.02665,0.0294,0.02265,0.02363,0.03575,-0.01154,0.00444,-0.03161,-0.02372,0.01514,-0.0127,-0.02802,0.00864,0.01237,-0.05021,-0.02111,0.05605,0.05016,0.00951,-0.00923,0.00926,0.00197,0.01606,-0.03861,0.12871,0.00338,-0.06685,0.01784,0.02511,0.02067,0.03104,-0.01069,0.01681,-0.03389,0.07895,-0.04271,-0.04035,0.04933,0.03867,0.01331,-0.04523,0.02783,0.04124,-0.02709,-0.06097,-0.05158,0.06829,0.01816,0.01809,-0.02379,0.01558,0.01229,0.01586,-0.00756,0.02073,0.02342,-0.00476,-0.05318,0.12132,-0.01928,0.05737,0.01201,0.02799,0.00613,-0.05718,-0.00169,-0.02105,-0.04986,-0.02942,0.01974,-0.07901,0.03696,-0.00593,-0.00429,0.06253,0.07065,0.00463,0.03592,0.01208,-0.04477,0.00597,-0.02515,-0.01228,0.07488,-0.05327,-0.04587,-0.01673,0.00182,0.00886,0.06502,0.04756,0.05103,-0.09152,0.03829,-0.01861,-0.08259,0.07901,-0.06131,-0.08091,-0.0057,-0.01029,-0.00998,-0.0256,-0.04061,0.03857,0.04064,-0.07051,-0.0024,0.03451,-0.03403,0.03886,0.02393,-0.0597,-0.01736,-0.03096,0.02751,0.04609,0.02627,0.02009,0.06716,-0.03196,-0.00453,0.00972,-0.04986,0.03688,-0.01973,0.05575,-0.00941,0.07196,-0.05577,-0.04332,0.0249,0.00704,0.03256,-0.02896,-0.05045,-0.04066,0.09818,-0.02634,0.01537,-0.00331,-0.04543,-0.04144,0.02359,0.0611,0.02604,-0.0058,-0.0799,0.0822,0.06694,0.04285,-0.00053,-0.00349,0.05868,0.05694,0.03704,0.06333,0.06299,-0.02997,-0.06656,0.02365,0.01682,0.00616,-0.06974,-0.03924,0.02773,0.01378,-0.0234,-0.04157,0.01201,0.0301,0.06935,-0.05935,-0.06122,-0.01322,0.007,0.00483,-0.04269,0.0438,-0.01981,-0.01844,0.05011,-0.07086,-0.006,-0.05792,-0.01882,0.01562,0.03422,-0.00479,-0.02143,0.00141,0.04757,0.00455,-0.01245,-0.04199,0.04977,0.01481,-0.02768,0.05993,0.0204,0.01906,0.0299,0.00671,-0.03736,0.00271,-0.02251,0.09747,0.05714,-0.03023,0.03607,-0.0301,-0.00473,0.03473,0.03507,0.01519,0.01512,-0.07846,-0.02012,0.00532,-0.01658,-0.13292,0.0085,0.0493,0.00749,0.06468,0.00687,-0.01673,0.00083,0.01762,-0.03502,0.04398,0.0352,-0.05909,0.00853,-0.04337,-0.01918,0.03225,0.00119,-0.0178,0.03728,-0.02267,0.05232,-0.00424,-0.06815,0.05975,0.03,0.01958,-0.07321,-0.03414,-0.04411,-0.07027,0.01613,0.03522,0.04184,0.05279,0.00556,0.08586,-0.01367,0.01671,-0.02017,-0.01075,-0.01036,-0.08756,-0.03804,-0.00115,-0.02969,0.09914,-0.02847,0.02199,-0.00268,0.05473,-0.00713,0.02709,-0.05602,0.07209,0.00469,-0.03003,-0.0364],"small-team/answer-customers":[-0.02022,-0.0438,-0.00182,0.00119,0.0185,-0.03182,-0.06123,0.00568,-0.03412,-0.069,-0.07237,0.04286,-0.05389,0.02581,-0.01496,-0.02046,0.07302,-0.04277,-0.08094,-0.05423,-0.07216,0.01819,-0.03471,-0.00078,0.01523,0.07141,-0.01251,0.12096,0.02184,-0.01886,-0.07512,0.02983,0.03134,-0.01693,0.04354,0.02929,0.01322,0.03252,0.0254,0.02852,0.03471,-0.00983,0.00155,-0.08493,0.07462,0.03053,-0.03623,0.0213,-0.00093,0.03802,0.05367,-0.01548,-0.00731,0.00011,-0.00217,0.03367,0.03055,-0.00416,-0.00222,-0.0059,-0.0485,0.01304,-0.03613,0.03076,0.02992,-0.04981,0.01362,-0.01159,-0.04973,-0.02209,-0.03297,0.00159,0.00737,-0.00184,-0.00265,-0.09559,-0.01825,-0.09225,0.02026,-0.0036,-0.02189,-0.06003,0.05285,-0.02745,-0.01536,-0.01219,0.01613,0.01851,0.08148,0.09146,0.02561,0.02463,0.02933,0.04591,-0.00707,-0.04985,0.01578,0.02372,-0.01187,-0.05843,0.08934,-0.07814,-0.04426,0.003,0.06478,-0.04612,0.02546,-0.07326,-0.00434,0.08744,0.00543,0.00992,0.04062,-0.01123,0.01215,-0.03278,-0.00273,-0.01607,0.04154,-0.08546,0.03611,0.03805,-0.01088,0.00522,0.0205,0.02763,0.00952,-0.07158,-0.04753,-0.0748,0.05335,0.10003,-0.03187,-0.00664,-0.04978,-0.0006,0.03192,0.08885,0.02251,0.03347,-0.00191,-0.11792,0.06584,-0.0149,0.01593,-0.14455,-0.02864,0.02824,0.00907,-0.00355,0.02655,0.01946,0.03019,-0.04167,0.03899,0.00996,-0.00714,0.01253,-0.00059,-0.04124,-0.13362,-0.00592,-0.06186,-0.02355,0.03461,-0.01842,0.06184,-0.01113,0.02534,-0.06894,-0.03995,0.06006,-0.07317,-0.03089,-0.0737,-0.01068,-0.03323,0.02152,-0.04002,-0.01711,0.01628,0.01129,-0.03055,0.0328,-0.00748,-0.12773,-0.07165,-0.03352,-0.01906,-0.02271,0.09343,-0.06325,-0.043,0.00112,-0.02162,-0.02324,0.02022,0.03444,-0.06198,-0.09504,0.04566,0.04949,-0.0604,0.00813,-0.07821,0.09194,0.01047,0.04383,0.01968,-0.0798,0.00209,-0.045,-0.04883,-0.00083,0.02675,0.005,0.00458,-0.01683,0.05667,-0.04033,0.01535,-0.05061,0.03959,-0.03734,-0.06248,0.0257,-0.01623,-0.00139,0.03636,0.02216,0.06566,-0.07583,0.05542,0.03722,-0.01564,0.0295,-0.07043,-0.00089,0.02147,-0.00066,0.04659,-0.02259,0.0292,-0.05618,0.01112,0.04789,-0.02122,0.03395,0.00032,-0.00195,-0.03519,0.08631,-0.02248,-0.00135,0.06853,-0.03545,-0.05036,0.0543,0.02713,0.0354,-0.1016,0.03069,0.07927,0.03097,0.00034,-0.02393,0.03851,0.01693,0.02308,-0.06401,0.02317,0.02597,0.02759,0.0148,0.03489,-0.03023,-0.0237,0.00887,-0.13063,-0.0129,0.00553,0.00955,-0.00261,-0.03906,0.01301,0.00518,-0.01549,-0.01076,0.01994,0.00221,0.02468,-0.02712,-0.02473,-0.06859,0.02689,-0.02793,0.00516,0.05662,0.00928,-0.01526,-0.0708,-0.025,0.03717,0.01719,-0.01839,-0.03855,-0.04644,-0.03537,0.05577,-0.09167,-0.02662,-0.06309,-0.044,-0.02968,0.00369,-0.02757,0.01054,0.06914,-0.03679,-0.01465,-0.01026,-0.01222,-0.03586,-0.00602,0.04277,-0.02551,0.00606,0.0302,-0.02078,-0.01845,-0.04684,-0.02179,0.00622,0.03162,0.00345,-0.04093,0.04022,-0.0214,0.00514,0.0939,-0.06109,-0.11798,-0.00289,0.03513,0.02503,0.10107,-0.02933,-0.03718,-0.02094,-0.03271,-0.03795,0.00669,0.012,0.01649,-0.02869,-0.06135,-0.00907,-0.07531,-0.03127,-0.0618,-0.06592,-0.01167,0.07394,-0.00241,0.03766,0.08863,-0.0143,0.04321,0.0072,-0.00338,-0.0768,-0.07582,0.04327,0.05275,0.02149,-0.0115,-0.03146,0.02913,0.07762,0.06442,-0.01495,0.01955,0.0082,-0.05232,-0.03445,-0.00984,0.00166,-0.07518,0.01964,-0.00317,-0.01386,0.00653,0.01991,-0.03018,-0.0727,0.0784,-0.03474,-0.08032,0.02785,0.0405,0.00349,0.00141,-0.01908,0.01865,0.01603,0.00566,0.00549,0.01172,0.06107,0.01889,0.00558,-0.00879,0.01341,-0.04673,0.097,-0.03591,-0.03997,-0.10249,0.01583,0.01563,0.047,0.0076,0.02722,0.00599,-0.058,0.03295,0.00966,-0.00929,-0.08966,0.03394,-0.00584,0.02002,-0.01708,-0.09163,-0.01836,0.1142,0.01252,0.04621,0.09339,0.0335,0.00605,0.06401,-0.05671,0.0461,-0.06222,0.01399,-0.07559,0.03226,-0.06416,0.04319,0.05866,-0.01696,-0.01922,-0.04139,-0.02332,0.03549,0.00532,-0.01774,0.05364,0.00219,0.02341,-0.02412,-0.06057,0.03281,0.05344,0.03464,0.03045,-0.06147,-0.03987,0.01839,0.05277,-0.00046,-0.02856,0.00794,-0.00215,0.01987,-0.06968,-0.06006,-0.03841,0.01658,-0.00468,0.01156,0.06894,0.05203,-0.02967,-0.02381,0.02016,0.02404,0.00575,-0.05162,-0.03503,0.04231,-0.01163,0.00545,0.02266,-0.026,0.01838,-0.00313,0.05139,0.00034,0.10514,0.003,0.03153,0.0056,-0.01741,0.02272,0.06875,-0.00829,0.01593,0.12914,0.07793,-0.01373],"small-team/keep-books":[0.01885,-0.02989,0.0345,0.01676,-0.00902,-0.03223,-0.00424,-0.02577,0.01285,-0.00369,-0.02752,-0.01147,0.06622,0.06215,0.02243,-0.0029,0.01617,0.02606,-0.08056,-0.028,0.02441,0.06008,0.05866,-0.07164,0.02366,-0.04008,0.01594,0.07404,0.01123,0.00492,-0.0752,0.05639,-0.00124,-0.0285,0.03536,-0.05054,0.00883,-0.01805,-0.05286,0.01701,-0.05367,0.02252,-0.02973,0.05732,0.07321,-0.05282,-0.01251,-0.03626,0.01938,0.00194,-0.22231,0.012,0.00544,-0.00027,-0.01965,-0.05667,0.01181,-0.04043,0.01685,0.02039,0.02295,-0.06305,-0.05459,0.0376,0.00259,0.03809,0.04898,-0.00172,-0.03165,0.00159,0.03019,-0.02759,0.00026,-0.15517,-0.05005,-0.07325,0.02679,-0.01412,-0.03471,-0.02922,0.00286,-0.05179,0.05959,-0.01735,-0.04294,0.00017,-0.03574,-0.00119,0.05828,-0.01192,0.05189,0.01098,0.02848,0.04655,-0.03346,-0.03025,-0.00825,0.02992,-0.03883,-0.04178,0.16341,0.03992,0.02258,-0.03903,-0.08114,0.04535,-0.07402,-0.02531,0.04612,0.06073,0.00643,0.02439,0.01952,0.04757,0.03559,0.01604,0.00864,0.08873,0.04532,-0.0101,-0.00858,0.01565,-0.07656,-0.02422,0.00886,0.0432,-0.0359,-0.08556,0.03794,0.00317,0.00861,-0.00559,0.03953,0.05203,-0.11912,-0.01185,-0.05399,-0.04711,-0.01537,0.03555,-0.04467,-0.04252,-0.0309,-0.05773,-0.04188,-0.04887,-0.00499,0.02049,-0.0013,-0.06583,-0.00107,0.03303,0.04753,-0.0057,0.05526,-0.01378,-0.05171,0.03059,-0.00134,0.00096,-0.0322,0.0733,0.00053,-0.01744,0.00177,0.04775,-0.12633,0.02015,-0.04353,0.0562,-0.07035,0.02457,-0.05351,-0.0208,0.04499,0.00048,-0.01699,-0.04157,-0.01405,-0.02042,0.05027,0.01157,-0.02893,-0.07002,-0.02468,-0.00243,0.033,-0.02119,-0.00742,0.02729,-0.03316,-0.079,-0.0393,-0.06222,-0.0261,0.01023,0.02281,0.01056,-0.00014,-0.02463,0.02,-0.01383,0.04881,-0.03684,-0.02367,-0.00445,-0.01326,-0.03674,-0.04362,-0.01701,0.04055,0.01469,0.00108,0.01153,-0.04856,0.02497,0.0009,-0.01895,0.0874,-0.02777,-0.03076,0.00908,0.08384,-0.02099,-0.07542,0.05316,-0.0042,0.02953,-0.02808,0.09798,0.00839,0.02327,0.03589,-0.06066,-0.05165,-0.05129,0.08135,-0.0115,0.05047,-0.07474,0.0227,-0.04126,-0.02251,-0.04805,-0.00432,-0.01595,0.04325,0.00688,-0.01393,0.00042,0.00152,-0.02184,0.00577,0.03342,0.02484,-0.06347,0.00183,0.09511,0.04625,0.01348,-0.14283,0.00875,-0.03979,-0.00619,-0.00745,-0.05236,0.04415,-0.02797,0.01339,0.04836,-0.0402,-0.03591,-0.0642,0.02425,-0.01037,-0.03365,-0.01019,-0.04518,-0.02794,0.02847,0.05558,-0.00784,0.02131,0.01237,0.01852,0.00708,-0.0147,-0.00276,0.04108,-0.01026,-0.02127,0.03007,0.05446,-0.11435,0.02209,-0.00587,0.00866,0.06026,-0.00641,-0.03608,0.02448,0.02483,-0.00625,-0.02704,-0.00292,0.04538,0.02326,-0.08542,0.05437,-0.03675,0.01272,-0.03425,-0.04317,-0.02026,-0.07647,0.00994,-0.00893,-0.04254,-0.04087,0.08054,-0.01838,0.03092,0.03696,0.0585,0.06358,-0.01585,-0.04355,-0.00981,-0.02669,-0.02277,0.00767,0.01191,0.0084,-0.06703,-0.03719,0.12268,-0.03668,-0.0115,0.00253,0.0146,0.01787,-0.0185,-0.03118,-0.01737,-0.00015,0.05544,-0.01391,0.00198,0.00326,-0.05743,-0.01493,-0.00941,0.01763,0.003,-0.05123,0.00124,0.04165,-0.05593,0.03888,-0.03677,0.01052,0.09965,0.11264,-0.00917,0.06005,0.03461,-0.00243,0.01092,0.05062,0.03076,-0.02981,-0.04729,0.02794,-0.05431,0.0538,-0.04054,-0.07545,-0.04377,0.00528,0.01892,-0.01358,0.02195,0.11259,0.01905,-0.00487,0.02718,0.02349,-0.01851,-0.00628,0.04071,-0.04573,0.01788,-0.00667,-0.04906,0.02735,0.04509,0.01129,0.09798,-0.02647,0.0696,-0.01077,-0.07775,-0.05495,0.01164,-0.06397,0.10678,0.01349,-0.02666,-0.05796,0.04415,-0.04574,0.03369,0.04198,0.03571,0.01521,-0.08654,0.09286,-0.00243,-0.09552,-0.04328,0.04281,0.07634,-0.05268,-0.01645,-0.01567,0.05152,-0.04076,0.00541,-0.02983,-0.05969,0.05025,0.08524,-0.026,0.02381,-0.07027,-0.01664,0.08151,0.06811,-0.04869,-0.01657,-0.0441,0.05882,0.01072,-0.01844,0.03157,0.07633,-0.03006,0.03995,-0.0173,-0.01565,-0.04903,0.05551,-0.03076,-0.0013,-0.04073,0.01104,0.02582,0.01812,-0.00798,-0.07626,0.03464,0.00005,0.00454,-0.07343,-0.01184,0.05348,-0.01383,0.01537,0.02954,0.00584,-0.03654,-0.00193,-0.02257,-0.00883,0.04545,0.02619,-0.07298,-0.0047,-0.02964,0.0369,-0.09015,0.01165,0.03956,-0.05373,0.07925,-0.00129,-0.00743,0.03365,0.03646,0.04391,0.05808,-0.03264,0.00107,0.04663,-0.0378,-0.01688,-0.03297,-0.05288,-0.0077,0.00917,-0.02537,-0.06115,0.02522,0.00536,0.04681,-0.00833,0.04275,-0.00857,0.00838,0.07542,0.07728,-0.05032],"small-team/send-invoices":[-0.05742,-0.06121,-0.01955,0.01714,0.04463,-0.02782,-0.04676,-0.01918,0.01554,-0.02631,-0.12979,-0.02183,0.03376,0.01267,-0.02035,-0.07831,-0.02617,0.02599,-0.11121,0.04267,0.03358,-0.01753,0.04079,-0.00682,0.00792,0.11683,0.01591,0.08416,-0.01957,0.0073,-0.08609,0.01636,-0.02087,-0.00773,0.00666,-0.01473,-0.03005,-0.01149,-0.00622,0.03051,-0.02247,0.05385,0.0013,0.00403,0.11806,0.01336,0.0475,0.01227,0.05031,0.03519,-0.09946,0.02562,0.01395,0.00115,-0.0209,-0.04441,-0.03344,0.00547,0.01091,0.00996,0.00866,-0.01514,-0.03766,0.01451,0.0146,0.07288,0.02455,0.02595,-0.02374,0.01619,-0.0315,0.01402,-0.0137,-0.06151,-0.04316,-0.04894,-0.02251,-0.04408,0.02402,-0.03321,-0.03419,-0.09533,0.04729,-0.05648,0.03045,-0.01761,-0.02415,0.00884,0.03235,-0.0107,0.00554,-0.02114,0.01645,0.00333,-0.02846,-0.07693,-0.00815,0.01473,-0.09051,-0.01306,0.13327,-0.06676,0.04571,-0.05392,0.05308,0.0416,-0.01863,-0.05879,0.05795,0.02858,0.03744,0.03274,0.00099,0.04986,0.02599,-0.05446,0.00408,-0.00035,0.0973,-0.0627,0.00609,0.02611,-0.00433,-0.01154,0.06732,0.02366,0.04629,-0.03943,0.00269,-0.06136,-0.04264,0.02042,0.06334,0.01121,-0.10062,-0.00975,-0.00863,-0.02082,-0.01428,0.07277,-0.03201,-0.07684,0.05139,0.02113,-0.06424,-0.0942,-0.05085,-0.01682,0.03744,0.00826,-0.05279,0.08425,-0.03224,-0.02177,0.0246,0.01224,0.02397,-0.03926,0.03933,0.00737,-0.05933,-0.09009,0.03363,-0.00785,-0.00999,0.01176,-0.10528,-0.06466,-0.00541,-0.0253,-0.10619,0.09868,-0.08567,0.00425,-0.08637,0.03219,-0.02827,-0.06967,-0.0329,0.04211,0.01399,-0.00907,-0.01439,-0.03717,-0.02558,-0.01746,-0.05189,0.00432,0.05193,0.02481,0.01222,-0.03803,-0.04931,-0.08992,-0.0455,-0.02881,0.00253,0.02005,0.00916,0.01689,-0.00986,-0.01589,0.02165,-0.04736,-0.10521,0.02211,-0.01716,-0.0158,0.02933,0.00019,0.01402,0.00612,-0.01162,0.05757,-0.05443,0.02143,0.00963,-0.07257,0.05053,0.04088,0.03381,-0.02849,0.04898,-0.07286,-0.04024,-0.00112,0.02323,0.01886,0.05274,0.06727,0.08164,0.0228,-0.00392,-0.00543,-0.02447,-0.09723,0.05006,0.03133,0.00018,-0.08526,0.01022,-0.07855,0.0068,-0.04694,0.02042,-0.0049,0.0514,0.0276,-0.03339,-0.00091,-0.04089,0.03149,-0.05588,-0.02863,-0.00475,-0.03655,0.0721,-0.01615,0.01407,-0.04241,-0.15997,0.036,-0.03012,0.03362,-0.04276,-0.06604,0.00273,-0.00041,0.01369,0.03905,-0.02543,0.01599,0.02464,-0.03201,0.00631,-0.01902,0.03075,-0.00598,-0.06909,0.05067,0.07689,0.02706,-0.03468,-0.08918,0.02763,-0.01868,-0.00886,0.02621,0.0335,0.03995,-0.02309,-0.01632,-0.03342,-0.06294,0.03185,-0.01325,-0.04188,-0.03664,0.02495,-0.06802,-0.00942,-0.014,0.0295,-0.02938,-0.01401,0.03948,0.00414,0.0054,0.03473,-0.02751,0.03773,0.00437,-0.05203,-0.0337,-0.00582,0.00623,-0.00637,0.01825,-0.10285,0.01055,-0.01962,0.00529,0.0425,0.02212,0.04961,0.00395,-0.00708,0.0014,-0.03841,-0.00227,-0.03119,-0.02459,-0.00042,0.04628,0.00939,0.07022,0.0214,0.00924,0.01791,0.01256,-0.0747,0.02617,0.04193,0.04655,0.06312,0.04509,-0.05143,-0.05346,-0.01077,-0.06377,0.00472,-0.01276,0.00537,0.02381,-0.07806,0.09274,0.00835,-0.03483,-0.00203,-0.02719,-0.02636,0.01841,0.22153,-0.02173,0.01741,0.01296,0.02871,0.01824,0.04231,0.00918,-0.05615,-0.04298,0.02365,-0.00992,-0.06531,-0.05711,-0.05753,0.04213,0.10025,0.06177,-0.02363,-0.01849,0.01158,-0.09099,0.02134,-0.00474,0.00602,-0.07094,-0.02197,-0.00147,-0.05782,-0.01448,0.04441,-0.0402,-0.0362,0.01302,-0.01492,0.03098,-0.00171,-0.05065,0.04347,-0.00667,-0.04937,-0.01075,0.00744,0.06336,0.00361,0.04622,-0.02533,-0.02747,-0.02211,0.03775,0.10567,-0.01471,0.04015,-0.05134,0.08222,-0.00975,-0.06867,-0.01247,0.02477,0.00433,-0.07837,-0.04853,-0.03632,0.06041,0.00752,0.00204,-0.05717,0.04294,0.02479,0.07344,-0.01392,-0.03065,-0.02432,0.08376,0.04012,0.05491,-0.00324,0.00454,-0.05257,0.08201,-0.01272,0.02314,-0.03775,0.04116,-0.02401,0.05579,-0.02728,0.02167,0.00777,-0.03765,-0.01108,-0.02183,-0.01391,0.05569,-0.02852,0.00924,0.01606,0.03592,0.05754,-0.04472,-0.00723,0.02926,0.0077,0.01138,-0.04172,-0.04388,-0.03129,0.01859,-0.00223,0.00278,-0.09484,0.02517,-0.00196,0.00212,-0.06412,-0.02341,0.00759,0.04697,-0.09877,-0.02967,-0.04627,-0.05399,-0.02819,0.00491,0.01709,0.03128,0.01372,-0.00302,-0.04336,0.0173,0.02348,-0.00945,0.01531,-0.05584,-0.05121,-0.01907,0.03496,-0.00829,0.07561,-0.04367,0.05174,-0.0334,-0.00045,-0.02622,0.0091,-0.02971,0.01604,0.07638,0.05467,-0.01741],"small-team/create-marketing":[-0.0056,-0.04382,-0.04177,0.04673,-0.0004,-0.02933,-0.01969,0.05285,0.03715,-0.0257,-0.0549,0.02979,-0.00307,0.00569,0.01959,-0.04791,0.08277,-0.02691,-0.0153,-0.07138,-0.00215,-0.03149,-0.05052,-0.01351,0.05984,0.05179,0.04615,-0.01715,0.05229,-0.0151,-0.05783,0.01516,-0.07653,-0.01918,0.05103,0.01949,0.00044,0.019,-0.04204,0.03321,-0.09626,0.00014,0.04145,0.04968,0.00001,0.00121,-0.02022,0.00872,0.00463,0.08195,0.02107,0.05764,0.01053,-0.04609,-0.03503,-0.01993,-0.07614,-0.02948,-0.02521,-0.00561,0.08881,-0.10682,0.0173,0.02685,0.01657,0.03789,-0.07644,-0.01212,-0.04504,-0.01604,-0.06172,0.07664,0.05199,-0.02105,0.0133,-0.04461,0.06157,0.04192,0.03354,0.03335,-0.0217,-0.11411,0.00923,-0.06277,-0.01982,0.00462,-0.05634,0.00772,0.0629,-0.03396,0.0602,-0.11131,0.04895,0.02015,0.03619,-0.01937,0.08692,-0.0038,-0.06158,0.0058,0.13145,-0.02715,0.04044,-0.02339,0.04519,0.05311,0.02245,-0.07263,0.01849,0.05101,0.02985,-0.0105,-0.0224,0.01472,0.05072,-0.01367,-0.0072,0.00295,0.0501,-0.08409,0.08177,0.01735,0.02521,0.0179,-0.0362,-0.02714,0.07213,-0.02716,0.01254,0.00135,0.04524,0.01974,-0.05758,0.03052,-0.07992,-0.02904,0.00172,-0.00466,0.01163,-0.00383,-0.02126,-0.03968,0.05429,-0.00194,-0.03476,-0.04399,-0.06094,-0.02866,0.00459,-0.00738,-0.00787,-0.09001,0.07425,-0.00379,0.04522,0.02244,0.00183,0.06783,0.0194,0.01492,-0.03014,-0.06383,0.00131,0.04498,-0.01937,0.02736,-0.00498,-0.0595,0.03025,-0.03617,-0.07634,0.10484,-0.08926,0.01508,-0.0338,-0.06704,-0.03084,0.07084,-0.0416,-0.01761,0.03679,0.03081,0.02093,-0.03996,0.02484,-0.00202,-0.07614,-0.03221,0.02071,0.09903,0.07496,-0.00638,-0.05099,-0.00166,-0.05451,-0.01949,0.01828,-0.00742,0.01929,-0.00763,0.03509,-0.06728,-0.09691,-0.06201,0.00137,0.02333,-0.07756,0.00717,0.09905,0.01093,-0.01629,-0.01483,0.06998,0.12898,0.04842,-0.00533,0.06962,-0.03584,-0.05391,0.01717,0.02293,-0.03186,-0.02417,-0.07583,-0.06227,-0.00915,-0.01979,0.06714,0.01372,0.04808,0.04561,0.0108,0.02612,-0.03227,-0.07534,-0.05493,-0.02472,-0.0164,0.06304,0.06127,0.07222,-0.04542,0.08132,0.01031,0.06553,0.0445,0.03373,0.02857,-0.02109,0.05263,0.03923,0.022,-0.01558,0.03331,0.02368,0.00592,0.09483,-0.07645,0.00946,0.02881,0.02312,0.04052,0.00099,-0.04615,0.02356,-0.00903,0.03959,-0.03404,0.03048,-0.04271,0.00234,0.00607,0.02434,-0.00205,0.01622,0.02123,0.06827,-0.01958,0.01978,0.04578,0.0409,0.03057,-0.01902,0.1253,0.04547,-0.00701,-0.01832,-0.01425,0.05635,0.02414,-0.05763,-0.0121,0.0476,0.03883,0.07466,-0.00893,-0.00925,-0.00169,0.03036,-0.02388,-0.04801,-0.08069,-0.00073,0.00807,-0.0245,0.07606,0.03698,0.00067,0.00115,-0.02776,-0.05465,-0.04836,-0.03888,0.06089,0.00281,-0.02269,-0.04015,0.02554,-0.04583,-0.00335,-0.0171,-0.0487,0.02953,0.04508,0.09778,-0.04896,-0.0231,0.03537,-0.01903,-0.02573,-0.05886,-0.08397,0.04679,-0.04447,-0.01741,0.02054,0.01019,-0.00487,0.05021,0.05865,-0.03746,0.07248,0.01083,-0.06152,0.01623,0.03464,-0.05167,0.00795,0.00968,-0.0203,-0.01501,0.03207,-0.02158,0.06591,-0.02114,0.00119,0.05822,-0.01472,0.01007,-0.00844,0.01909,-0.04534,0.00081,0.01629,0.08047,-0.00142,-0.03001,-0.03109,-0.01395,-0.01423,0.00471,0.05345,-0.02877,-0.00455,0.09618,-0.02017,0.01022,-0.06895,-0.00848,0.0063,0.01397,0.00055,0.00564,-0.03793,0.0713,0.01582,-0.01071,0.03281,-0.00273,0.03593,-0.00582,-0.00612,-0.00142,0.02892,-0.02588,0.02342,0.00292,-0.03052,-0.00156,0.01156,0.02752,-0.00308,-0.03222,-0.00074,-0.06178,0.08901,0.07357,-0.01931,-0.00314,-0.03887,0.03604,-0.04814,0.01532,-0.0537,-0.04029,0.01911,-0.01376,0.03126,0.02071,0.02856,0.01355,0.00076,-0.08711,-0.04132,-0.00078,0.0442,-0.0885,-0.03218,-0.04005,0.05368,-0.01557,0.08603,-0.02358,0.03738,0.02494,0.07286,0.0069,0.00404,0.03752,-0.00185,0.07243,0.0951,-0.03152,-0.03066,-0.00041,-0.01144,-0.01642,0.02968,0.03033,-0.01522,-0.1012,0.0397,0.02387,-0.05752,-0.07303,-0.02602,0.03464,0.01892,0.00708,-0.13468,0.01821,-0.02412,0.0131,-0.03724,0.01149,0.05593,-0.06309,0.04671,0.03079,0.01309,-0.02344,-0.0386,-0.02282,-0.04352,-0.0383,0.04581,-0.03559,-0.0033,0.0568,-0.04337,-0.08283,-0.03315,0.02404,-0.06679,-0.01919,-0.02183,0.06555,0.00214,0.06026,0.00393,0.03377,0.02918,0.00502,-0.061,-0.0363,0.045,-0.12704,-0.02698,0.02847,-0.02063,0.01452,-0.01206,0.05582,-0.1,0.06561,0.04867,0.03507,-0.04909,-0.00758,-0.00545,-0.0166,0.00631],"small-team/prepare-quotes":[-0.02101,-0.08281,-0.05352,0.07744,0.02012,-0.06075,-0.05674,0.04929,-0.05232,-0.0605,-0.01709,0.05986,-0.11063,-0.06301,0.02443,-0.00651,-0.01852,-0.01742,-0.03507,-0.03346,0.00623,0.03121,-0.0339,-0.01471,0.02197,0.02907,0.01226,0.02978,0.02612,0.02486,-0.08228,0.06295,0.01091,0.01499,0.01979,-0.01051,0.00804,-0.00973,0.032,0.01737,-0.01197,0.03791,-0.02446,0.03526,-0.03942,-0.05619,-0.0249,-0.01734,0.02973,0.06403,-0.0355,0.02276,0.0332,-0.01686,-0.01024,-0.00813,-0.02694,0.01666,0.04967,0.00902,0.02157,0.0291,0.02992,-0.00775,0.07364,0.04646,-0.00389,0.0455,-0.06187,-0.04538,-0.08043,0.0602,0.04982,0.03871,-0.08007,-0.06231,0.04652,-0.00819,0.05124,0.04051,-0.04255,-0.05755,0.03668,-0.0474,0.03117,0.04178,0.01353,0.03367,0.06532,0.00428,-0.01599,-0.06923,0.05478,0.06289,0.02837,-0.01711,0.02,-0.03956,-0.01039,-0.07145,0.03466,-0.00132,0.04079,-0.05421,-0.03014,0.01122,-0.02862,-0.11551,-0.02055,0.08147,-0.0668,0.02226,0.01504,0.00614,0.06627,-0.04703,-0.01428,0.00067,0.02593,-0.01947,0.07549,0.04993,-0.04316,-0.02013,0.02539,-0.01,-0.01133,-0.03507,0.0042,-0.04626,-0.02622,0.07254,-0.01979,-0.03923,-0.09391,-0.02557,0.05058,-0.05917,-0.00383,-0.00406,-0.04285,0.00668,0.0081,0.02808,0.05853,0.01435,-0.00174,0.04277,-0.02847,-0.05364,0.02746,-0.13988,0.04229,0.07391,0.00345,0.0084,0.04089,0.0343,-0.01762,0.04997,-0.03633,-0.00053,0.02842,0.02489,0.01588,-0.05226,0.00018,-0.05291,-0.00515,-0.00811,-0.07905,0.10634,-0.11726,0.01598,-0.00417,-0.0388,-0.02053,0.07867,0.01485,0.03021,0.1143,-0.076,-0.00715,0.08754,-0.05227,-0.04419,-0.02481,-0.01206,0.00522,0.06233,-0.02609,0.01623,-0.05102,0.0169,-0.04622,0.0516,-0.01966,0.01326,-0.02761,-0.01862,-0.02579,-0.01378,-0.05062,-0.04653,-0.0307,0.0441,-0.0176,-0.01463,-0.03258,-0.04613,0.00559,-0.02243,-0.0076,0.00257,0.00902,0.01241,0.03015,-0.05456,-0.0177,-0.01342,-0.0491,0.00907,-0.08732,0.03278,-0.0049,-0.01451,-0.03221,0.02628,0.0164,0.07442,0.06815,0.00611,0.05127,-0.03802,0.00482,-0.02863,0.01115,-0.00498,0.03414,0.05507,0.00625,-0.10914,0.01109,-0.02318,0.01736,0.02282,0.08519,0.00083,-0.069,0.00822,-0.01607,0.02516,-0.06877,-0.0043,0.03413,-0.00411,0.05187,-0.01523,0.05215,-0.01597,-0.05221,0.11665,-0.01129,-0.00987,-0.01149,-0.03463,-0.08238,-0.02237,0.03112,0.01578,-0.05983,-0.03277,0.03259,-0.02176,0.00492,-0.05049,-0.00743,0.00439,-0.04364,0.00409,-0.01855,0.06783,0.06192,-0.00222,-0.02002,-0.02871,-0.00526,0.00083,0.05016,0.01135,-0.06807,-0.05173,-0.02575,-0.04884,0.02146,-0.04894,-0.04828,-0.05731,0.01984,-0.04668,0.03355,-0.12089,-0.05436,0.01052,0.01123,0.00443,0.00772,0.07919,0.0811,0.0194,-0.02592,-0.04531,-0.08526,-0.01188,-0.0546,-0.01378,0.01102,0.00811,-0.05961,-0.01976,-0.12394,-0.0111,-0.03012,0.02424,0.1188,0.01124,-0.09205,0.01047,-0.02067,-0.04655,-0.04276,-0.0518,0.01121,-0.03902,-0.03273,0.06393,-0.05984,-0.04751,0.06078,0.05033,-0.03423,-0.02502,0.02179,-0.0553,0.0606,0.03419,-0.02168,-0.04521,0.05764,-0.03441,-0.00316,-0.01122,-0.04491,0.05371,-0.0708,0.03624,0.00718,0.00156,-0.04367,0.00698,-0.05065,0.02674,-0.12192,0.02184,0.03097,-0.013,-0.04039,0.00329,-0.03921,-0.03559,-0.0124,-0.03029,-0.01125,-0.01356,-0.02182,0.00977,0.00521,0.01759,0.01048,0.02881,0.03354,-0.05494,0.05876,-0.01283,-0.03526,-0.02638,-0.04974,0.05004,0.01445,-0.01449,0.02662,0.00861,-0.02817,-0.03443,0.00479,0.03532,0.03847,0.04487,-0.02325,0.01851,0.04363,-0.05062,-0.01594,0.0513,-0.02058,0.07326,0.01288,0.0171,-0.04714,-0.03949,-0.01682,0.01376,0.08845,-0.03208,-0.02805,0.01841,0.02033,-0.00022,0.02677,0.01768,0.0371,0.01648,-0.05317,0.02854,0.0475,-0.04329,-0.02604,-0.00678,0.03373,0.02555,0.04679,0.02251,-0.03253,-0.03965,0.03306,0.0577,0.03649,0.03009,0.02005,0.09242,0.02997,0.12135,0.01279,-0.00189,-0.0382,0.08356,0.00352,0.00358,0.04185,-0.01031,0.05326,0.08481,-0.00419,-0.02545,-0.00347,-0.02679,0.04429,0.0164,0.04475,0.02822,0.03116,-0.00686,-0.06417,0.01865,0.06643,0.06946,-0.00167,-0.00138,-0.01055,0.02539,0.05466,0.01099,-0.11934,0.04188,0.03418,-0.03164,-0.0253,0.0039,-0.02705,-0.01104,-0.05545,0.0561,0.04629,0.00112,0.03681,-0.00658,0.02595,0.09871,0.09496,0.05696,0.03392,-0.00847,-0.01671,-0.01808,0.06874,0.04382,-0.10486,-0.08964,-0.00554,-0.01351,0.04617,-0.03342,0.06194,-0.11738,0.0129,0.03508,-0.03294,-0.07884,0.00643,0.02245,-0.07199,-0.05127]}} diff --git a/packages/route-labeller/src/types.ts b/packages/route-labeller/src/types.ts new file mode 100644 index 0000000000..e74fb9451c --- /dev/null +++ b/packages/route-labeller/src/types.ts @@ -0,0 +1,71 @@ +/** Terms per working language, matched case-insensitively. */ +export type LexiconTerms = Partial>; + +/** + * The words the labeller reads a request with, per ModelGuide cell. Shipped with this package as + * lexicon.json and copied by the Console API's guide:sync into each edition, so both label alike. + */ +export type Lexicon = { + version: number; + /** The ModelGuide edition the lexicon was written against. */ + edition: string; + /** The `profession/task` a request with nothing recognisable in it is labelled as. */ + default: string; + /** Profession ids a person or app may use that mean one of the guide's, e.g. `salesperson`. */ + professionAliases: Record; + professions: Record; + /** Keyed `profession/task`. `examples` are what the embedding pass compares a request against. */ + tasks: Record; +}; + +/** What the labeller says a request is, in the shape Console's `redrob.route` takes. */ +export type RouteLabel = { + profession: string; + task: string; + edition: string; + /** + * `mode` is whether the embedding model ran (`embedding`) or the labeller read words alone because + * the model is not installed or not downloaded yet (`lexical`). Console routes Redrob Auto on the + * ModelGuide only for `embedding`; a `lexical` label routes on the legacy table, and is recorded. + */ + labeller: { id: string; version: string; confidence: number; mode: "embedding" | "lexical" }; + /** The runners-up, best first. Console tries them before its own nearest-cell rules. */ + candidates: Array<{ profession: string; task: string; score: number }>; +}; + +/** The manifest of the embedding model the labeller runs. Every file is pinned by SHA-256. */ +export type RouteModelManifest = { + id: string; + revision: string; + license: string; + dimensions: number; + /** Tokens per request read, the newest first. Longer text is cut, not windowed. */ + maxTokens: number; + model: { file: string; sha256: string; url?: string }; + tokenizer: { file: string; sha256: string; url?: string }; + /** The sentence-transformers Dense projection after mean pooling, as safetensors. */ + dense: { file: string; sha256: string; url?: string }; +}; + +/** The part of onnxruntime's API the labeller uses; onnxruntime-node and -web both provide it. */ +export type OrtRuntime = { + InferenceSession: { + create(model: Uint8Array, options?: Record): Promise; + }; + Tensor: new (type: "int64", data: BigInt64Array, dims: readonly number[]) => unknown; +}; + +export type OrtSession = { + run(feeds: Record): Promise>; + inputNames: readonly string[]; +}; + +/** Per-cell prototype vectors: the mean of each cell's example and label embeddings, unit length. */ +export type Prototypes = { + /** Which model and lexicon produced them; a mismatch means they must be rebuilt. */ + model: string; + lexiconVersion: number; + edition: string; + dimensions: number; + cells: Record; +}; diff --git a/packages/route-labeller/src/wordpiece.ts b/packages/route-labeller/src/wordpiece.ts new file mode 100644 index 0000000000..fe5e19b575 --- /dev/null +++ b/packages/route-labeller/src/wordpiece.ts @@ -0,0 +1,169 @@ +/* + * BERT WordPiece tokenizer with character offsets, shared by the privacy detector and the route + * labeller (both run BERT-family encoders on the person's machine). + * + * Matches Hugging Face `tokenizers` for the configuration every candidate model uses + * (BertNormalizer clean_text + handle_chinese_chars, no lowercasing, no accent stripping; + * BertPreTokenizer; WordPiece with `##`, 100 characters per word at most). wordpiece.test.ts pins + * it against ids and offsets produced by the Python library, so a drift shows up as a failing test, + * not as quietly worse detection. + * + * Offsets are UTF-16 indexes into the input string, the way JavaScript slices it. + */ + +export type WordPieceToken = { + id: number; + /** Start and end in the input, UTF-16 units. */ + start: number; + end: number; + /** True for a `##` piece that continues the previous one inside the same word. */ + continuation: boolean; + piece: string; +}; + +export type WordPieceConfig = { + vocab: ReadonlyMap; + unkToken?: string; + prefix?: string; + maxCharsPerWord?: number; +}; + +const isWhitespace = (cp: number) => + cp === 0x20 || cp === 0x09 || cp === 0x0a || cp === 0x0d || /\s/u.test(String.fromCodePoint(cp)); + +/** What BertNormalizer's clean_text drops: NUL, U+FFFD and control characters other than whitespace. */ +function isDropped(cp: number): boolean { + if (cp === 0 || cp === 0xfffd) return true; + if (cp === 0x09 || cp === 0x0a || cp === 0x0d) return false; + return /\p{Cc}|\p{Cf}/u.test(String.fromCodePoint(cp)); +} + +/** CJK ideographs, which BERT splits one per word. Hangul is not in these ranges. */ +function isChinese(cp: number): boolean { + return ( + (cp >= 0x4e00 && cp <= 0x9fff) || + (cp >= 0x3400 && cp <= 0x4dbf) || + (cp >= 0x20000 && cp <= 0x2a6df) || + (cp >= 0x2a700 && cp <= 0x2b73f) || + (cp >= 0x2b740 && cp <= 0x2b81f) || + (cp >= 0x2b820 && cp <= 0x2ceaf) || + (cp >= 0xf900 && cp <= 0xfaff) || + (cp >= 0x2f800 && cp <= 0x2fa1f) + ); +} + +function isPunctuation(cp: number): boolean { + if ((cp >= 33 && cp <= 47) || (cp >= 58 && cp <= 64) || (cp >= 91 && cp <= 96) || (cp >= 123 && cp <= 126)) return true; + return /\p{P}/u.test(String.fromCodePoint(cp)); +} + +/** Words with their offsets, after normalisation and pre-tokenisation. */ +export function preTokenize(text: string): Array<{ word: string; start: number; end: number }> { + const words: Array<{ word: string; start: number; end: number }> = []; + let word = ""; + let start = 0; + let end = 0; + const flush = () => { + if (word) words.push({ word, start, end }); + word = ""; + }; + let index = 0; + while (index < text.length) { + const cp = text.codePointAt(index)!; + const width = cp > 0xffff ? 2 : 1; + if (isDropped(cp)) { + // Dropped characters vanish without splitting the word around them, as in the reference. + } else if (isWhitespace(cp)) { + flush(); + } else if (isChinese(cp) || isPunctuation(cp)) { + flush(); + words.push({ word: String.fromCodePoint(cp), start: index, end: index + width }); + } else { + if (!word) start = index; + word += String.fromCodePoint(cp); + end = index + width; + } + index += width; + } + flush(); + return words; +} + +export class WordPiece { + private readonly vocab: ReadonlyMap; + private readonly unkId: number; + private readonly prefix: string; + private readonly maxChars: number; + + constructor(config: WordPieceConfig) { + this.vocab = config.vocab; + const unk = config.unkToken ?? "[UNK]"; + const unkId = this.vocab.get(unk); + if (unkId === undefined) throw new Error(`vocabulary has no ${unk}`); + this.unkId = unkId; + this.prefix = config.prefix ?? "##"; + this.maxChars = config.maxCharsPerWord ?? 100; + } + + id(token: string): number { + const id = this.vocab.get(token); + if (id === undefined) throw new Error(`vocabulary has no ${token}`); + return id; + } + + tokenize(text: string): WordPieceToken[] { + const out: WordPieceToken[] = []; + for (const { word, start, end } of preTokenize(text)) { + // Offsets inside a word follow its characters; dropped characters only occur between words + // in practice, so a word's text is contiguous in the input when its span length matches. + const contiguous = end - start === word.length; + const chars = Array.from(word); + if (chars.length > this.maxChars) { + out.push({ id: this.unkId, start, end, continuation: false, piece: "[UNK]" }); + continue; + } + const pieces: WordPieceToken[] = []; + let charIndex = 0; + let unitOffset = 0; + let failed = false; + while (charIndex < chars.length) { + let endChar = chars.length; + let found: { id: number; piece: string } | null = null; + while (endChar > charIndex) { + const sub = chars.slice(charIndex, endChar).join(""); + const piece = charIndex > 0 ? `${this.prefix}${sub}` : sub; + const id = this.vocab.get(piece); + if (id !== undefined) { + found = { id, piece }; + break; + } + endChar -= 1; + } + if (!found) { + failed = true; + break; + } + const units = chars.slice(charIndex, endChar).join("").length; + pieces.push({ + id: found.id, + start: contiguous ? start + unitOffset : start, + end: contiguous ? start + unitOffset + units : end, + continuation: charIndex > 0, + piece: found.piece, + }); + unitOffset += units; + charIndex = endChar; + } + if (failed) out.push({ id: this.unkId, start, end, continuation: false, piece: "[UNK]" }); + else out.push(...pieces); + } + return out; + } +} + +/** The vocabulary from a Hugging Face tokenizer.json, which every candidate ships. */ +export function vocabFromTokenizerJson(json: unknown): Map { + const model = (json as { model?: { type?: string; vocab?: Record } }).model; + if (model?.type !== "WordPiece" || !model.vocab) throw new Error("tokenizer.json is not a WordPiece tokenizer"); + return new Map(Object.entries(model.vocab)); +} diff --git a/packages/route-labeller/tsconfig.json b/packages/route-labeller/tsconfig.json new file mode 100644 index 0000000000..8230c72743 --- /dev/null +++ b/packages/route-labeller/tsconfig.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "@tsconfig/bun/tsconfig.json", + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["ES2022", "DOM"], + "rootDir": ".", + "outDir": "dist", + "declaration": true, + "strict": true, + "noUncheckedIndexedAccess": true, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "noEmit": true, + "allowImportingTsExtensions": true + }, + "include": ["src/**/*", "scripts/**/*", "test/**/*"] +} diff --git a/packages/route-labeller/tsup.config.ts b/packages/route-labeller/tsup.config.ts new file mode 100644 index 0000000000..a2eafcfff6 --- /dev/null +++ b/packages/route-labeller/tsup.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { index: "src/index.ts", node: "src/node.ts", wordpiece: "src/wordpiece.ts" }, + format: ["esm"], + dts: true, + clean: true, + target: "es2022", + platform: "neutral", + sourcemap: false, + splitting: true, + treeshake: true, + external: ["onnxruntime-node", "onnxruntime-web", "node:fs", "node:fs/promises", "node:path"], + loader: { ".json": "json" }, +}); diff --git a/packages/schema/src/insights.ts b/packages/schema/src/insights.ts new file mode 100644 index 0000000000..010a2c20aa --- /dev/null +++ b/packages/schema/src/insights.ts @@ -0,0 +1,44 @@ +export * as Insights from "./insights" + +import { Schema } from "effect" +import { NonNegativeInt } from "./schema" + +/** + * Labeled AI work sessions, sent to the Redrob console's insights on an app's behalf. + * + * WHY THROUGH THE ENGINE. An app that keeps no credential of its own -- Office's rule is that it never + * holds a provider key -- still has to send its labels with the person's Redrob key. The engine holds + * that key, so the engine makes the call and the key never leaves it. The route takes no URL: the batch + * goes to the console's fixed insights endpoint and nowhere else. + * + * A session is passed through as the app's object rather than re-declared here. The console owns the + * shape (`POST /v1/insights/sessions` in redrob-console) and refuses any field that is not a label, so a + * copy of that contract here would only drift from the one that decides. What this side bounds is the + * batch: 1 to 500 sessions, the console's own limit. + */ + +/** The most sessions the console takes in one request. */ +export const MAX_SESSIONS = 500 + +export const SessionsRequest = Schema.Struct({ + sessions: Schema.Array(Schema.Record(Schema.String, Schema.Unknown)).check( + Schema.isMinLength(1), + Schema.isMaxLength(MAX_SESSIONS), + ), +}).annotate({ identifier: "Insights.SessionsRequest" }) +export interface SessionsRequest extends Schema.Schema.Type {} + +/** One session the console refused, with why. A refusal is permanent: sending it again is refused again. */ +export const Rejection = Schema.Struct({ + externalId: Schema.String, + reason: Schema.String, +}).annotate({ identifier: "Insights.Rejection" }) +export interface Rejection extends Schema.Schema.Type {} + +/** What the console did with the batch, session by session. */ +export const SessionsResult = Schema.Struct({ + accepted: NonNegativeInt, + updated: NonNegativeInt, + rejected: Schema.Array(Rejection), +}).annotate({ identifier: "Insights.SessionsResult" }) +export interface SessionsResult extends Schema.Schema.Type {} diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index ce3837420c..d2d0cf6ebd 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -15,6 +15,8 @@ import type { AuthRemoveResponses, AuthSetErrors, AuthSetResponses, + BrowserRequestRefusal, + BrowserRequestReply, ChatCompletionRequest, CommandListErrors, CommandListResponses, @@ -264,8 +266,16 @@ import type { TuiShowToastResponses, TuiSubmitPromptErrors, TuiSubmitPromptResponses, + V1BrowserRequestListErrors, + V1BrowserRequestListResponses, V1ChatCompletionsErrors, V1ChatCompletionsResponses, + V1SessionBrowserListErrors, + V1SessionBrowserListResponses, + V1SessionBrowserRefuseErrors, + V1SessionBrowserRefuseResponses, + V1SessionBrowserReplyErrors, + V1SessionBrowserReplyResponses, V2AgentListErrors, V2AgentListResponses, V2CommandListErrors, @@ -7140,6 +7150,155 @@ export class V2 extends HeyApiClient { } } +export class Request3 extends HeyApiClient { + /** + * List pending browser requests + * + * Retrieve browser actions awaiting a client for a location. A client that reconnects uses this to recover requests published while it was away. + */ + public list( + parameters?: { + location?: { + directory?: string + workspace?: string + } + }, + options?: Options, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "location" }] }]) + return (options?.client ?? this.client).get< + V1BrowserRequestListResponses, + V1BrowserRequestListErrors, + ThrowOnError + >({ + url: "/api/browser/request", + ...options, + ...params, + }) + } +} + +export class Browser extends HeyApiClient { + private _request?: Request3 + get request(): Request3 { + return (this._request ??= new Request3({ client: this.client })) + } +} + +export class Browser2 extends HeyApiClient { + /** + * List session browser requests + * + * Retrieve browser actions awaiting a client, owned by a session. + */ + public list( + parameters: { + sessionID: string + }, + options?: Options, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "path", key: "sessionID" }] }]) + return (options?.client ?? this.client).get< + V1SessionBrowserListResponses, + V1SessionBrowserListErrors, + ThrowOnError + >({ + url: "/api/session/{sessionID}/browser", + ...options, + ...params, + }) + } + + /** + * Answer a pending browser request + * + * Settle a browser action with the value it produced. The value is typed per action, so answering with the wrong shape is reported to the engine's caller rather than read as a fact about the page. + */ + public reply( + parameters: { + sessionID: string + requestID: string + browserRequestReply: BrowserRequestReply + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "path", key: "requestID" }, + { key: "browserRequestReply", map: "body" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post< + V1SessionBrowserReplyResponses, + V1SessionBrowserReplyErrors, + ThrowOnError + >({ + url: "/api/session/{sessionID}/browser/{requestID}/reply", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Refuse a pending browser request + * + * Report that the action could not be performed, with the reason. Refusing is faster and more honest than letting the request expire on the engine's deadline. + */ + public refuse( + parameters: { + sessionID: string + requestID: string + browserRequestRefusal: BrowserRequestRefusal + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "path", key: "requestID" }, + { key: "browserRequestRefusal", map: "body" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post< + V1SessionBrowserRefuseResponses, + V1SessionBrowserRefuseErrors, + ThrowOnError + >({ + url: "/api/session/{sessionID}/browser/{requestID}/refuse", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } +} + +export class Session4 extends HeyApiClient { + private _browser?: Browser2 + get browser(): Browser2 { + return (this._browser ??= new Browser2({ client: this.client })) + } +} + export class Chat extends HeyApiClient { /** * Create a chat completion @@ -7167,6 +7326,16 @@ export class Chat extends HeyApiClient { } export class V1 extends HeyApiClient { + private _browser?: Browser + get browser(): Browser { + return (this._browser ??= new Browser({ client: this.client })) + } + + private _session?: Session4 + get session(): Session4 { + return (this._session ??= new Session4({ client: this.client })) + } + private _chat?: Chat get chat(): Chat { return (this._chat ??= new Chat({ client: this.client })) diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 11e8c0238a..681e83cfae 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -67,6 +67,9 @@ export type Event = | EventQuestionV2Asked | EventQuestionV2Replied | EventQuestionV2Rejected + | EventBrowserRequestAsked + | EventBrowserRequestAnswered + | EventBrowserRequestRefused | EventTodoUpdated | EventLspUpdated | EventPermissionAsked @@ -1401,6 +1404,32 @@ export type GlobalEvent = { requestID: string } } + | { + id: string + type: "browser.request.asked" + properties: { + id: string + sessionID: string + command: BrowserRequestCommand + } + } + | { + id: string + type: "browser.request.answered" + properties: { + sessionID: string + requestID: string + } + } + | { + id: string + type: "browser.request.refused" + properties: { + sessionID: string + requestID: string + reason: string + } + } | { id: string type: "todo.updated" @@ -2967,6 +2996,9 @@ export type V2Event = | QuestionV2Asked | QuestionV2Replied | QuestionV2Rejected + | BrowserRequestAsked + | BrowserRequestAnswered + | BrowserRequestRefused | TodoUpdated | LspUpdated | PermissionAsked @@ -3001,6 +3033,12 @@ export type ForbiddenError = { message: string } +export type BrowserRequestNotFoundError = { + _tag: "BrowserRequestNotFoundError" + requestID: string + message: string +} + export type ProjectCopyError = { name: "ProjectCopyError" data: { @@ -3296,6 +3334,33 @@ export type QuestionV2Tool = { export type QuestionV2Answer = Array +export type BrowserRequestCommand = + | { + action: "page.url" + } + | { + action: "page.text" + } + | { + action: "page.query" + selector: string + limit?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + } + | { + action: "page.click" + selector: string + } + | { + action: "page.type" + selector: string + text: string + submit?: boolean + } + | { + action: "page.navigate" + url: string + } + export type ProjectVcs = "git" export type ProjectIcon = { @@ -3978,6 +4043,11 @@ export type ConfigV2ExperimentalPolicy = { resource: string } +export type SkillV2AutoInject = { + keywords?: Array + url?: Array +} + export type ProjectDirectories = Array<{ directory: string strategy?: string @@ -5196,6 +5266,8 @@ export type SkillV2Info = { name: string description?: string slash?: boolean + icon?: string + autoInject?: SkillV2AutoInject location: string content: string } @@ -5837,6 +5909,89 @@ export type QuestionV2Rejected = { } } +export type BrowserRequestCommand1 = + | { + action: "page.url" + } + | { + action: "page.text" + } + | { + action: "page.query" + selector: string + limit?: number | "NaN" | "Infinity" | "-Infinity" + } + | { + action: "page.click" + selector: string + } + | { + action: "page.type" + selector: string + text: string + submit?: boolean + } + | { + action: "page.navigate" + url: string + } + +export type BrowserRequestAsked = { + id: string + metadata?: { + [key: string]: unknown + } + type: "browser.request.asked" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + id: string + sessionID: string + command: BrowserRequestCommand1 + } +} + +export type BrowserRequestAnswered = { + id: string + metadata?: { + [key: string]: unknown + } + type: "browser.request.answered" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + requestID: string + } +} + +export type BrowserRequestRefused = { + id: string + metadata?: { + [key: string]: unknown + } + type: "browser.request.refused" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + requestID: string + reason: string + } +} + export type TodoUpdated = { id: string metadata?: { @@ -6301,6 +6456,44 @@ export type QuestionV2Reply = { answers: Array } +export type BrowserRequestRequest = { + id: string + sessionID: string + command: BrowserRequestCommand +} + +export type BrowserRequestNode = { + selector: string + text: string + attributes: { + [key: string]: string + } +} + +export type BrowserRequestValue = + | { + type: "string" + value: string + } + | { + type: "nodes" + value: Array + } + | { + type: "void" + } + +export type BrowserRequestReply = { + value: BrowserRequestValue +} + +export type BrowserRequestRefusal = { + /** + * Why the action could not be performed, in one sentence. + */ + reason: string +} + export type ReferenceLocalSource = { type: "local" path: string @@ -7018,6 +7211,62 @@ export type EventQuestionV2Rejected = { } } +export type BrowserRequestCommand2 = + | { + action: "page.url" + } + | { + action: "page.text" + } + | { + action: "page.query" + selector: string + limit?: number | "NaN" | "Infinity" | "-Infinity" + } + | { + action: "page.click" + selector: string + } + | { + action: "page.type" + selector: string + text: string + submit?: boolean + } + | { + action: "page.navigate" + url: string + } + +export type EventBrowserRequestAsked = { + id: string + type: "browser.request.asked" + properties: { + id: string + sessionID: string + command: BrowserRequestCommand2 + } +} + +export type EventBrowserRequestAnswered = { + id: string + type: "browser.request.answered" + properties: { + sessionID: string + requestID: string + } +} + +export type EventBrowserRequestRefused = { + id: string + type: "browser.request.refused" + properties: { + sessionID: string + requestID: string + reason: string + } +} + export type EventTodoUpdated = { id: string type: "todo.updated" @@ -8546,6 +8795,7 @@ export type AppSkillsResponses = { description?: string location: string content: string + autoInject?: SkillV2AutoInject }> } @@ -13698,6 +13948,152 @@ export type V2SessionQuestionRejectResponses = { export type V2SessionQuestionRejectResponse = V2SessionQuestionRejectResponses[keyof V2SessionQuestionRejectResponses] +export type V1BrowserRequestListData = { + body?: never + path?: never + query?: { + location?: { + directory?: string + workspace?: string + } + } + url: "/api/browser/request" +} + +export type V1BrowserRequestListErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestError + /** + * UnauthorizedError + */ + 401: UnauthorizedError +} + +export type V1BrowserRequestListError = V1BrowserRequestListErrors[keyof V1BrowserRequestListErrors] + +export type V1BrowserRequestListResponses = { + /** + * Success + */ + 200: { + location: LocationInfo + data: Array + } +} + +export type V1BrowserRequestListResponse = V1BrowserRequestListResponses[keyof V1BrowserRequestListResponses] + +export type V1SessionBrowserListData = { + body?: never + path: { + sessionID: string + } + query?: never + url: "/api/session/{sessionID}/browser" +} + +export type V1SessionBrowserListErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestError + /** + * UnauthorizedError + */ + 401: UnauthorizedError + /** + * SessionNotFoundError + */ + 404: SessionNotFoundError +} + +export type V1SessionBrowserListError = V1SessionBrowserListErrors[keyof V1SessionBrowserListErrors] + +export type V1SessionBrowserListResponses = { + /** + * Success + */ + 200: { + data: Array + } +} + +export type V1SessionBrowserListResponse = V1SessionBrowserListResponses[keyof V1SessionBrowserListResponses] + +export type V1SessionBrowserReplyData = { + body: BrowserRequestReply + path: { + sessionID: string + requestID: string + } + query?: never + url: "/api/session/{sessionID}/browser/{requestID}/reply" +} + +export type V1SessionBrowserReplyErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestError + /** + * UnauthorizedError + */ + 401: UnauthorizedError + /** + * SessionNotFoundError | BrowserRequestNotFoundError + */ + 404: BrowserRequestNotFoundError | SessionNotFoundError +} + +export type V1SessionBrowserReplyError = V1SessionBrowserReplyErrors[keyof V1SessionBrowserReplyErrors] + +export type V1SessionBrowserReplyResponses = { + /** + * + */ + 204: void +} + +export type V1SessionBrowserReplyResponse = V1SessionBrowserReplyResponses[keyof V1SessionBrowserReplyResponses] + +export type V1SessionBrowserRefuseData = { + body: BrowserRequestRefusal + path: { + sessionID: string + requestID: string + } + query?: never + url: "/api/session/{sessionID}/browser/{requestID}/refuse" +} + +export type V1SessionBrowserRefuseErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestError + /** + * UnauthorizedError + */ + 401: UnauthorizedError + /** + * SessionNotFoundError | BrowserRequestNotFoundError + */ + 404: BrowserRequestNotFoundError | SessionNotFoundError +} + +export type V1SessionBrowserRefuseError = V1SessionBrowserRefuseErrors[keyof V1SessionBrowserRefuseErrors] + +export type V1SessionBrowserRefuseResponses = { + /** + * + */ + 204: void +} + +export type V1SessionBrowserRefuseResponse = V1SessionBrowserRefuseResponses[keyof V1SessionBrowserRefuseResponses] + export type V2ReferenceListData = { body?: never path?: never diff --git a/packages/server/src/handlers.ts b/packages/server/src/handlers.ts index 5a1dc10f79..da45dd87d3 100644 --- a/packages/server/src/handlers.ts +++ b/packages/server/src/handlers.ts @@ -3,6 +3,7 @@ import { MessageHandler } from "./handlers/message" import { ModelHandler } from "./handlers/model" import { ProviderHandler } from "./handlers/provider" import { VariantHandler } from "./handlers/variant" +import { InsightsHandler } from "./handlers/insights" import { SessionHandler } from "./handlers/session" import { PermissionHandler } from "./handlers/permission" import { FileSystemHandler } from "./handlers/fs" @@ -30,6 +31,7 @@ export const handlers = Layer.mergeAll( ModelHandler, ProviderHandler, VariantHandler, + InsightsHandler, IntegrationHandler, CredentialHandler, PermissionHandler, diff --git a/packages/server/src/handlers/chat-completion.ts b/packages/server/src/handlers/chat-completion.ts index da056c4da0..7f130320ac 100644 --- a/packages/server/src/handlers/chat-completion.ts +++ b/packages/server/src/handlers/chat-completion.ts @@ -15,7 +15,7 @@ import { Integration } from "@redrob-code/core/integration" import { ModelV2 } from "@redrob-code/core/model" import { ProviderV2 } from "@redrob-code/core/provider" import { fromCatalogModel } from "@redrob-code/core/session/runner/model" -import { LLM, LLMError } from "@redrob-code/llm" +import { LLM, LLMClient, LLMError } from "@redrob-code/llm" import type { LLMEvent, LLMResponse } from "@redrob-code/llm" import type { Credential } from "@redrob-code/schema/credential" import { ChatCompletionRequest } from "@redrob-code/protocol/groups/chat-completion" @@ -164,7 +164,25 @@ const resolveModel = Effect.fn("chat.resolveModel")(function* (model: string) { return yield* fromCatalogModel(info, credential) }) -const buildRequest = Effect.fn("chat.buildRequest")(function* (payload: ChatCompletionRequest) { +/** + * The session a request belongs to, as the Redrob console knows it: `x-redrob-session`, which a product + * sets so the console can join a labeled session (POST /api/insights/sessions) to what its requests cost. + * Forwarded to the Redrob provider only, and only in the console's own id format (1-128 of letters, + * digits, `.`, `_`, `:`, `-`), so it carries an id and never text, and no other vendor receives it. + */ +const SESSION_HEADER = "x-redrob-session" +const SESSION_ID = /^[A-Za-z0-9._:-]{1,128}$/ + +export function sessionHeader(model: string, headers: Readonly>) { + const value = headers[SESSION_HEADER] + const redrob = !model.includes("/") || model.startsWith("redrob/") + return redrob && value !== undefined && SESSION_ID.test(value) ? { [SESSION_HEADER]: value } : undefined +} + +const buildRequest = Effect.fn("chat.buildRequest")(function* ( + payload: ChatCompletionRequest, + session?: Record, +) { const model = yield* resolveModel(payload.model) const messages = toLLMMessages(payload) const tools = toLLMTools(payload) @@ -176,6 +194,7 @@ const buildRequest = Effect.fn("chat.buildRequest")(function* (payload: ChatComp // tell the provider "you may call nothing", which is a different thing. ...(tools ? { tools: tools.definitions, ...(tools.choice ? { toolChoice: tools.choice } : {}) } : {}), ...(generation ? { generation } : {}), + ...(session ? { http: { headers: session } } : {}), }) }) @@ -288,8 +307,9 @@ export const ChatCompletionHandler = HttpApiBuilder.group(Api, "server.chat", (h // to answer with either JSON or an event stream. The declared schema is // still the contract, so it is applied here rather than trusting the body. const payload = yield* HttpServerRequest.schemaBodyJson(ChatCompletionRequest) + const incoming = yield* HttpServerRequest.HttpServerRequest const id = completionID() - const request = yield* buildRequest(payload) + const request = yield* buildRequest(payload, sessionHeader(payload.model, incoming.headers)) if (payload.stream !== true) { const response = yield* LLM.generate(request) @@ -299,7 +319,11 @@ export const ChatCompletionHandler = HttpApiBuilder.group(Api, "server.chat", (h // Streaming: the error envelope can only be sent before the first byte, // so a failure after headers travels as an SSE error frame (see // eventFrames) rather than as a status code. - const frames = toChunks(id, payload.model, LLM.stream(request)).pipe( + // The client is taken HERE, inside the handler. `LLM.stream` reads it from the context when the + // stream starts, and the response body runs after this handler returns, where it is gone: every + // streamed reply was an empty 200. + const client = yield* LLMClient.Service + const frames = toChunks(id, payload.model, client.stream(request)).pipe( Stream.pipeThroughChannel(Sse.encode()), Stream.encodeText, ) diff --git a/packages/server/src/handlers/insights.ts b/packages/server/src/handlers/insights.ts new file mode 100644 index 0000000000..13bd724fc1 --- /dev/null +++ b/packages/server/src/handlers/insights.ts @@ -0,0 +1,61 @@ +import { Insights } from "@redrob-code/core/insights" +import { Effect } from "effect" +import { HttpApiBuilder } from "effect/unstable/httpapi" + +import { Api } from "../api" +import { + InvalidRequestError, + ProviderNotFoundError, + ServiceUnavailableError, + UnauthorizedError, +} from "@redrob-code/protocol/errors" + +/** + * The insights route, and where the console's refusals become this API's errors, by the same rules as + * the variants routes (handlers/variant.ts): an over-budget or rejected key is unauthorized, a refused + * batch is an invalid request, and anything that means "try again later" is service-unavailable. The + * console's message is carried through, because it is what says which field it refused. + */ + +const notConnected = () => + new ProviderNotFoundError({ + providerID: "redrob", + message: "The Redrob provider is not connected, so there is no key to send insights with.", + }) + +function refusal(error: Insights.Refused) { + const status = error.status + if (status === 401 || status === 402 || status === 403) return new UnauthorizedError({ message: error.message }) + if (status === 429) return new ServiceUnavailableError({ message: error.message }) + if (status >= 400 && status < 500) return new InvalidRequestError({ message: error.message }) + return new ServiceUnavailableError({ message: error.message }) +} + +type RouteError = InvalidRequestError | UnauthorizedError | ProviderNotFoundError | ServiceUnavailableError + +const handle = (effect: Effect.Effect): Effect.Effect => + effect.pipe( + Effect.catch((error): Effect.Effect => { + if (error instanceof Insights.Refused) return Effect.fail(refusal(error)) + if (error instanceof Insights.NotConnected) return Effect.fail(notConnected()) + return Effect.fail( + new ServiceUnavailableError({ + message: + error instanceof Error + ? `could not reach the Redrob console: ${error.message}` + : "could not reach the Redrob console", + }), + ) + }), + ) + +export const InsightsHandler = HttpApiBuilder.group(Api, "server.insights", (handlers) => + Effect.gen(function* () { + return handlers.handle( + "insights.sessions", + Effect.fn(function* (ctx) { + return yield* handle(Insights.sessions(ctx.payload)) + }), + ) + }), +) diff --git a/packages/server/src/routes.ts b/packages/server/src/routes.ts index 111d7e1cdf..1d3db8210a 100644 --- a/packages/server/src/routes.ts +++ b/packages/server/src/routes.ts @@ -1,6 +1,6 @@ import { Database } from "@redrob-code/core/database/database" import { LayerNode } from "@redrob-code/core/effect/layer-node" -import { httpClient } from "@redrob-code/core/effect/app-node-platform" +import { httpClient, llmClient } from "@redrob-code/core/effect/app-node-platform" import { AppNodeBuilder } from "@redrob-code/core/effect/app-node-builder" import { EventV2 } from "@redrob-code/core/event" import { Credential } from "@redrob-code/core/credential" @@ -27,6 +27,7 @@ const applicationServices = LayerNode.group([ Database.node, EventV2.node, httpClient, + llmClient, ToolOutputStore.cleanupNode, SessionV2.node, PermissionSaved.node, @@ -51,6 +52,13 @@ export function createEmbeddedRoutes() { function makeRoutes(auth: Layer.Layer) { const serviceLayer = AppNodeBuilder.build(applicationServices, [[SessionExecution.node, SessionExecutionLocal.node]]) + // The chat-completion handler takes the LLM client inside the request (its streaming reply reads it after + // the handler returns), so LLMClient is a per-request requirement of the API rather than a construction + // dependency -- Layer.provide(serviceLayer) does not discharge it. It is a global service, identical for + // every request, so provide it once here. This keeps the embedded routes self-contained (no residual + // request requirement leaking to callers, cf. PermissionSaved which genuinely varies per request). + const llmClientLayer = AppNodeBuilder.build(LayerNode.group([llmClient])) + return HttpApiBuilder.layer(Api, { openapiPath: "/openapi.json" }).pipe( Layer.provide(handlers), Layer.provide(sessionLocationLayer), @@ -59,7 +67,7 @@ function makeRoutes(auth: Layer.Layer outbox.add(session)); + +recorder.observe({ kind: "user-turn", sessionID, messageID, at: Date.now(), attachedSource: false }); +await recorder.observeFirstMessage(sessionID, messageID, text, (value) => classifier.label(value)); +await recorder.sweep(Date.now()); +await syncOutbox(outbox, { readKey, fetch, baseUrl: "https://console.redrob.ai/api/backend/v1" }); +``` + +### Download on first use + +Apps that do not bundle the model (Office) fetch it when it is first needed, in the background: + +```ts +import { WorkModelFetcher, WorkClassifierSource } from "@redrob-labs/work-labeller/node"; + +const fetcher = new WorkModelFetcher(join(app.getPath("userData"), "models", "insights")); +// After a chat finishes, never at start-up or while one streams: +const directory = await fetcher.request(); // null until ready; retries a failure after 1 min, 5 min, 30 min, 2 h +fetcher.onChange((state) => showInSettings(state)); // absent | downloading | ready | failed +``` + +The files come from the release `MANIFEST` names. Each is streamed to disk and hashed as it streams. A broken download resumes with a byte range, and a file is kept only when its SHA-256 matches. The download needs 600 MB free, and removes the folders of older revisions once the new one is ready. + +In a webview, use `createWorkClassifier({ model, tokenizer }, ort)` from the runtime-neutral entry, with `onnxruntime-web` and bytes your app read. The files must hash to `MANIFEST`. + +## Development + +| Command | What it does | +| --- | --- | +| `pnpm test` | Tokenizer parity with Hugging Face `tokenizers`, the heads, the labels, and the model data checks in `model/` | +| `pnpm typecheck`, `pnpm build` | Types; the ESM build in `dist/` | + +### Retraining the head + +`model/` holds what builds `src/work-head.json`. None of it is published, since `files` lists only `dist` and `src`: + +- `model/eval/work-samples.ts`: the evaluation set, which is scored and never trained on. +- `model/prototypes.ts`, `model/train/`: the prototype phrases, the training set, and the tuning slice that picks the confidence floor. +- `model/scripts/`: `export.ts` dumps all of the above as JSON; `evaluate.py` and `train.py` measure the candidates and write the head. + +```sh +uv pip install -r model/scripts/requirements.txt +bun model/scripts/export.ts > .model-runs/eval-data.json +python model/scripts/train.py .model-runs/eval-data.json # writes .model-runs/head.json +``` + +Copy `.model-runs/head.json` to `src/work-head.json` only when it passes the bar in `model-evaluation.md`, and record the round there. + +## License + +MIT. The model is intfloat/multilingual-e5-base (MIT); see `NOTICE.md`. diff --git a/packages/work-labeller/bench/webview/README.md b/packages/work-labeller/bench/webview/README.md new file mode 100644 index 0000000000..ee5d8ed29a --- /dev/null +++ b/packages/work-labeller/bench/webview/README.md @@ -0,0 +1,13 @@ +# Work classifier in a webview: measurement (Design, PR 4 of office-and-design.md) + +Runs the package's runtime-neutral classifier on `onnxruntime-web` (WASM) in a browser engine, against the 296 evaluation samples, and reports agreement with the Python/onnxruntime-node reference, latency, load time and heap. + +```sh +npm i onnxruntime-web@1.23.0 zod@4 +bun build spike.ts --target=browser --outfile www/spike.js +echo '' > www/index.html +# www/ref.json: [{ text, action, family, confidence }] for the 296 evaluation samples, from the Python reference +PLAYWRIGHT_FROM=/path/to/package.json BROWSER=chromium CHROME=/usr/local/bin/chrome node run.mjs +``` + +The page is served cross-origin isolated (COOP/COEP), which WASM threads need. Results are in `docs/features/ai-work-insights/office-and-design.md`. diff --git a/packages/work-labeller/bench/webview/run.mjs b/packages/work-labeller/bench/webview/run.mjs new file mode 100644 index 0000000000..e7fa71e836 --- /dev/null +++ b/packages/work-labeller/bench/webview/run.mjs @@ -0,0 +1,57 @@ +// Serves the spike (cross-origin isolated, so wasm threads are allowed) and drives it in a browser engine. +// Before running: `npm i onnxruntime-web@1.23.0 zod@4` here, `bun build spike.ts --target=browser --outfile +// www/spike.js`, write www/index.html loading /spike.js, and www/ref.json (the Python reference labels, +// [{ text, action, family, confidence }], from the 296 evaluation samples). See README.md. +import { createReadStream, statSync } from "node:fs" +import { createServer } from "node:http" +import { createRequire } from "node:module" +import { extname, join } from "node:path" + +// PLAYWRIGHT_FROM: a package.json whose node_modules has playwright-core. BROWSER: chromium or webkit. +// CHROME: a Chrome binary for chromium (optional). MODEL_DIR: a folder holding the pinned model files. +const require = createRequire(process.env.PLAYWRIGHT_FROM ?? import.meta.url) +const engines = require("playwright-core") +const kind = process.env.BROWSER ?? "chromium" +const here = new URL(".", import.meta.url).pathname + +const roots = { + "/ort/": join(here, "node_modules/onnxruntime-web/dist/"), + "/model/": process.env.MODEL_DIR ?? join(here, "../../../../apps/desktop/resources/insights-model/"), + "/": join(here, "www/"), +} +const types = { ".html": "text/html", ".js": "text/javascript", ".mjs": "text/javascript", ".wasm": "application/wasm", ".json": "application/json" } +const server = createServer((req, res) => { + const url = new URL(req.url, "http://x") + const prefix = Object.keys(roots).find((p) => url.pathname.startsWith(p)) + const file = join(roots[prefix], url.pathname.slice(prefix.length) || "index.html") + try { + statSync(file) + } catch { + res.writeHead(404).end() + return + } + res.writeHead(200, { + "content-type": types[extname(file)] ?? "application/octet-stream", + "cross-origin-opener-policy": "same-origin", + "cross-origin-embedder-policy": "require-corp", + }) + createReadStream(file).pipe(res) +}) +await new Promise((resolve) => server.listen(18931, "127.0.0.1", resolve)) + +const browser = await engines[kind].launch( + kind === "chromium" ? { ...(process.env.CHROME ? { executablePath: process.env.CHROME } : {}), args: ["--no-sandbox", "--enable-precise-memory-info"] } : {}, +) +for (const threads of [1, 2, 4]) { + const page = await browser.newPage() + page.on("pageerror", (e) => console.log("pageerror", e.message)) + await page.goto("http://127.0.0.1:18931/") + await page.waitForFunction(() => typeof window.runSpike === "function") + const result = await page.evaluate((t) => window.runSpike(t), threads) + delete result.labels + delete result.userAgent + console.log(JSON.stringify(result)) + await page.close() +} +await browser.close() +server.close() diff --git a/packages/work-labeller/bench/webview/spike.ts b/packages/work-labeller/bench/webview/spike.ts new file mode 100644 index 0000000000..83977ceeb4 --- /dev/null +++ b/packages/work-labeller/bench/webview/spike.ts @@ -0,0 +1,51 @@ +// The work classifier in a browser: @redrob-labs/work-labeller's runtime-neutral entry + onnxruntime-web. +import * as ort from "onnxruntime-web/wasm" +import { createWorkClassifier } from "../../src/index" + +type Ref = { text: string; action: string | null; family: string | null; confidence: number } + +declare global { + interface Window { + runSpike: (threads: number) => Promise + } +} + +window.runSpike = async (threads: number) => { + ort.env.wasm.wasmPaths = "/ort/" + ort.env.wasm.numThreads = threads + const bytes = async (path: string) => new Uint8Array(await (await fetch(path)).arrayBuffer()) + const t0 = performance.now() + const [model, tokenizer] = await Promise.all([bytes("/model/model_int8.onnx"), bytes("/model/tokenizer.json")]) + const fetched = performance.now() + const classifier = await createWorkClassifier({ model, tokenizer }, ort, { threads }) + const loaded = performance.now() + const ref: Ref[] = await (await fetch("/ref.json")).json() + const labels: { action: string | null; family: string | null }[] = [] + let agree = 0 + let maxDiff = 0 + const times: number[] = [] + for (const r of ref) { + const s = performance.now() + const got = await classifier.label(r.text) + labels.push({ action: got.action, family: got.family }) + times.push(performance.now() - s) + if (got.action === r.action && got.family === r.family) agree += 1 + maxDiff = Math.max(maxDiff, Math.abs(got.confidence - r.confidence)) + } + times.sort((a, b) => a - b) + const memory = (performance as unknown as { memory?: { usedJSHeapSize: number } }).memory + return { + userAgent: navigator.userAgent, + threads, + crossOriginIsolated: self.crossOriginIsolated, + fetchMs: Math.round(fetched - t0), + loadMs: Math.round(loaded - fetched), + samples: ref.length, + agree, + maxConfidenceDiff: maxDiff, + medianMs: +times[times.length >> 1]!.toFixed(1), + p95Ms: +times[Math.floor(times.length * 0.95)]!.toFixed(1), + labels, + jsHeapMB: memory ? Math.round(memory.usedJSHeapSize / 1e6) : null, + } +} diff --git a/packages/work-labeller/model/eval/review.md b/packages/work-labeller/model/eval/review.md new file mode 100644 index 0000000000..cba55c34f2 --- /dev/null +++ b/packages/work-labeller/model/eval/review.md @@ -0,0 +1,27 @@ +# Reviewing the work classifier evaluation set + +`work-samples.ts` holds 296 first instructions, the kind of message a person opens a Cowork chat with: + +- 128 plain English and 128 plain Korean samples, 8 per kind of work in each language; +- 40 hard cases: things that aren't work, mixed Korean and English, messages too short or vague to place, work that sits between two kinds, and messages with privacy labels like `[PERSON_1]` already in them. + +Each sample says what a correct classifier answers. Candidate models are scored against these answers, so a wrong answer here penalises a model for being right. All of the text is made up. + +## What to check in each Korean sample + +1. **Natural:** it reads like something a Korean colleague would type at work. A sample that reads like a translation is the main thing to catch, because people will write the real ones naturally. +2. **Register:** the plain samples are split on purpose. Each kind of work has a polite, detailed version (합니다 or 해요 style, with a brief) and a terse version (반말, "~해줘"). Both registers should look like real usage. +3. **Kind of work and task:** the first two fields of each row, under the action it's listed under. `null` as the task means the message fits that kind of work but none of its tasks. +4. **`brief`, the second field:** `1` when the message says what done looks like, such as who it's for, the format, the length, or the test that proves it. Saying only what to work on is `0`. +5. **`learn`, the third field:** `1` when the person asks for an explanation, or a review of their own work, rather than for the work itself. + +Korean doesn't need to match the English sample beside it. They're separate samples, and a Korean sample that uses a more natural local example (원화 amounts, 세금계산서, 반기 평가) is better. + +## How to give feedback + +Comment on the pull request against the line, or edit the line directly. + +- To flag a sample without rewriting it, comment "unnatural", "wrong label" or "ambiguous". +- An ambiguous sample can stay if the label is the one most people would choose. Otherwise move it to the hard cases. + +`pnpm --filter redrob-server test src/insights` checks that every label exists in the console's vocabulary, that every task appears in both languages, and that each kind of work keeps 8 samples per language. Edits that keep that test passing are safe to make. diff --git a/packages/work-labeller/model/eval/work-samples.test.ts b/packages/work-labeller/model/eval/work-samples.test.ts new file mode 100644 index 0000000000..7e530012d0 --- /dev/null +++ b/packages/work-labeller/model/eval/work-samples.test.ts @@ -0,0 +1,51 @@ +import { describe, expect, test } from "bun:test"; + +import { WORK_ACTIONS, WORK_TASKS } from "../../src/index.js"; +import { WORK_SAMPLES } from "./work-samples.js"; + +describe("work classifier evaluation set", () => { + test("every label is one the console accepts", () => { + for (const sample of WORK_SAMPLES) { + if (sample.action === null) { + expect(sample.task).toBeNull(); + continue; + } + expect(WORK_ACTIONS).toContain(sample.action); + if (sample.task !== null) expect(WORK_TASKS[sample.action]).toContain(sample.task); + } + }); + + test("ids are unique and no text appears twice", () => { + expect(new Set(WORK_SAMPLES.map((s) => s.id)).size).toBe(WORK_SAMPLES.length); + expect(new Set(WORK_SAMPLES.map((s) => s.text)).size).toBe(WORK_SAMPLES.length); + }); + + test("every kind of work has 8 plain samples in each language", () => { + for (const action of WORK_ACTIONS) { + for (const lang of ["en", "ko"]) { + const plain = WORK_SAMPLES.filter((s) => s.source === "plain" && s.action === action && s.lang === lang); + expect(plain.length).toBe(8); + } + } + }); + + test("every task appears in both languages", () => { + for (const [action, tasks] of Object.entries(WORK_TASKS)) { + for (const task of tasks) { + for (const lang of ["en", "ko"]) { + const found = WORK_SAMPLES.some((s) => s.action === action && s.task === task && s.lang === lang); + expect(`${action}.${task} ${lang} ${found}`).toBe(`${action}.${task} ${lang} true`); + } + } + } + }); + + test("briefs, learning asks and not-about-work cases are all represented", () => { + const count = (keep: (s: (typeof WORK_SAMPLES)[number]) => boolean) => WORK_SAMPLES.filter(keep).length; + expect(count((s) => s.brief)).toBeGreaterThanOrEqual(100); + expect(count((s) => !s.brief)).toBeGreaterThanOrEqual(100); + expect(count((s) => s.learn)).toBeGreaterThanOrEqual(30); + expect(count((s) => s.action === null)).toBeGreaterThanOrEqual(20); + expect(count((s) => s.lang === "mixed")).toBeGreaterThanOrEqual(5); + }); +}); diff --git a/packages/work-labeller/model/eval/work-samples.ts b/packages/work-labeller/model/eval/work-samples.ts new file mode 100644 index 0000000000..18bf7524e0 --- /dev/null +++ b/packages/work-labeller/model/eval/work-samples.ts @@ -0,0 +1,456 @@ +/* + * The work classifier evaluation set: first instructions a person might give Redrob Cowork, in English + * and Korean, each tagged by hand with what a correct classifier should answer. + * + * Every sample is written here, so no candidate model can have trained on it. Names, companies and + * figures are invented. + * + * The labels are the ones Crew and the Redrob Console use (console `insights/reference.ts`): + * - action: one of the 16 kinds of work, or null when the instruction is not about work or is too + * vague to place. A classifier that answers "not labeled" there is right. + * - task: the task under that action (the console's `action.task-slug` without the action), or + * null when the work fits the action but none of its tasks. + * - brief: the instruction says what done looks like: who it is for, the form, the length or the + * test that proves it. Saying only what to work on is not a brief. + * - learn: the person asks for an explanation, or a review of their own work, rather than for the + * work itself (mode 1, Learn). + * + * Sample tuple: [task, brief, learn, text]. `review.md` beside this file says how to review it. + */ + +export type WorkSample = { + id: string; + lang: "en" | "ko" | "mixed"; + /** Hard cases are reported apart: a set of only easy ones flatters every model. */ + source: "plain" | "hard"; + text: string; + action: string | null; + task: string | null; + brief: boolean; + learn: boolean; +}; + +type Row = readonly [task: string | null, brief: 0 | 1, learn: 0 | 1, text: string]; +type ActionRows = { en: readonly Row[]; ko: readonly Row[] }; + +const PLAIN: Record = { + reply: { + en: [ + ["refund-request", 1, 0, "Customer says they were charged twice for the annual plan and wants one charge back. Draft a reply under 120 words, apologetic but not grovelling, that confirms the refund goes out in 5-7 business days."], + ["refund-request", 0, 0, "Help me answer this refund request, ticket pasted below."], + ["bug-report-reply", 1, 0, "A user reports the export button does nothing in Safari. Write a reply that thanks them, says engineering reproduced it, gives the workaround (use Chrome or the CSV link in Settings) and promises an update by Friday. Keep it to two short paragraphs."], + ["bug-report-reply", 0, 0, "Reply to this bug report from a customer about the login loop"], + ["how-to-answer", 1, 0, "Customer asks how to add a teammate as a viewer. Answer in numbered steps, max 5, and link to the Members help page at the end."], + ["how-to-answer", 0, 0, "can you answer this question about setting up SSO for them"], + ["escalation-response", 1, 0, "This enterprise customer is angry that the outage broke their payroll run. Draft a response from me as head of support: own the problem, give the timeline from the incident report attached, offer a call today, no discounts promised. Under 200 words."], + ["escalation-response", 0, 1, "Here's the reply I wrote to an escalated ticket. Is the tone okay or does it sound defensive?"], + ], + ko: [ + ["refund-request", 1, 0, "고객이 연간 요금제가 두 번 결제됐다고 환불을 요청했어요. 사과하면서도 과하지 않게, 영업일 기준 5~7일 안에 환불된다고 안내하는 답장을 150자 이내로 써 주세요."], + ["refund-request", 0, 0, "이 환불 문의 답변 좀 도와줘"], + ["bug-report-reply", 1, 0, "사파리에서 내보내기 버튼이 안 눌린다는 버그 신고가 들어왔어요. 재현했다는 것, 임시 해결책(크롬 사용 또는 설정의 CSV 링크), 금요일까지 업데이트 드린다는 내용으로 두 문단짜리 답장을 써 주세요."], + ["bug-report-reply", 0, 0, "로그인이 계속 반복된다는 고객 버그 신고에 답장 써줘"], + ["how-to-answer", 1, 0, "팀원을 뷰어 권한으로 추가하는 방법을 묻는 고객 문의예요. 5단계 이내 번호 목록으로 답하고 마지막에 멤버 도움말 링크를 넣어 주세요."], + ["how-to-answer", 0, 0, "SSO 설정 방법 물어본 고객한테 답변해줘"], + ["escalation-response", 1, 0, "장애 때문에 급여 처리가 멈췄다고 화가 난 엔터프라이즈 고객입니다. 고객지원 총괄인 제 이름으로, 책임을 인정하고 첨부한 장애 보고서의 타임라인을 설명하고 오늘 통화를 제안하는 답장을 써 주세요. 할인 약속은 하지 말고 300자 이내로."], + ["escalation-response", 0, 1, "에스컬레이션된 티켓에 이렇게 답장을 썼는데, 너무 방어적으로 들리나요?"], + ], + }, + summ: { + en: [ + ["ticket-thread-summary", 1, 0, "Summarize this 40-message ticket thread for the engineer picking it up: what the customer reported, what we already tried, and what is still open. Bullet points, no more than 8."], + ["ticket-thread-summary", 0, 0, "Summarize this ticket thread"], + ["call-notes", 1, 0, "Turn this call transcript into notes for the account team: decisions, action items with owners, and risks. Use three headed sections and keep it to one screen."], + ["call-notes", 0, 0, "write up notes from the call with Northwind this morning, transcript attached"], + ["weekly-account-digest", 1, 0, "From the activity export attached, write the weekly digest for our top 10 accounts: one line each on usage change, open tickets and renewal date, sorted by renewal."], + ["weekly-account-digest", 0, 0, "Can you do the weekly account digest again?"], + [null, 0, 0, "tl;dr this thread for me"], + ["call-notes", 0, 1, "These are my notes from the customer call. Did I miss anything important from the transcript?"], + ], + ko: [ + ["ticket-thread-summary", 1, 0, "이 티켓을 이어받을 개발자를 위해 40개 메시지 스레드를 요약해 주세요. 고객이 보고한 내용, 이미 시도한 것, 아직 남은 문제를 8개 이내 글머리표로."], + ["ticket-thread-summary", 0, 0, "이 티켓 스레드 요약해줘"], + ["call-notes", 1, 0, "통화 녹취록을 영업팀용 회의록으로 정리해 주세요. 결정 사항, 담당자가 있는 액션 아이템, 리스크 세 부분으로 나누고 한 화면 분량으로."], + ["call-notes", 0, 0, "오늘 오전 노스윈드랑 한 통화 내용 정리해줘. 녹취록 첨부했어"], + ["weekly-account-digest", 1, 0, "첨부한 활동 내역으로 상위 10개 고객사 주간 다이제스트를 만들어 주세요. 고객사마다 사용량 변화, 열린 티켓, 갱신일을 한 줄씩, 갱신일 순으로."], + ["weekly-account-digest", 0, 0, "이번 주 고객사 다이제스트도 부탁해"], + [null, 0, 0, "이 스레드 세 줄 요약"], + ["call-notes", 0, 1, "고객 통화 메모를 이렇게 정리했는데 녹취록에서 빠뜨린 중요한 내용이 있을까요?"], + ], + }, + email: { + en: [ + ["renewal-note", 1, 0, "Write a renewal reminder to Harborline's ops lead: their contract ends Nov 30, usage grew 40% this year, and we can hold this year's price if they sign by Nov 15. Friendly, under 150 words, one clear ask."], + ["renewal-note", 0, 0, "draft the renewal email for Stonebridge"], + ["cold-first-touch", 1, 0, "Cold email to a VP of Finance at a 300-person logistics company. Hook on month-end close taking too long, one line of proof (a customer cut close from 9 days to 4), ask for 20 minutes. Max 90 words, no buzzwords."], + ["cold-first-touch", 0, 0, "Write a cold outreach email to this prospect"], + ["demo-follow-up", 1, 0, "Follow-up after today's demo with Meridian. Recap the three things they cared about (approvals, audit log, SSO), attach the security pack, and propose two times next week for a technical call. Under 180 words."], + ["demo-follow-up", 0, 0, "send a follow up to the people from the demo yesterday"], + [null, 0, 0, "Email the customer that their account manager is changing"], + ["cold-first-touch", 0, 1, "Why do my cold emails get so few replies? Here are three I sent last week."], + ], + ko: [ + ["renewal-note", 1, 0, "하버라인 운영 책임자에게 보낼 갱신 안내 메일을 써 주세요. 계약은 11월 30일 종료, 올해 사용량 40% 증가, 11월 15일까지 서명하면 올해 가격 유지. 친근하게, 300자 이내, 요청은 하나만."], + ["renewal-note", 0, 0, "스톤브리지 갱신 메일 초안 써줘"], + ["cold-first-touch", 1, 0, "300명 규모 물류회사 재무 담당 임원에게 보낼 첫 콜드메일입니다. 월말 결산이 오래 걸린다는 점으로 시작하고, 고객사 사례 한 줄(결산 9일→4일), 20분 미팅 요청. 200자 이내, 유행어 없이."], + ["cold-first-touch", 0, 0, "이 잠재 고객한테 보낼 첫 영업 메일 써줘"], + ["demo-follow-up", 1, 0, "오늘 메리디안 데모 후속 메일이에요. 관심 보였던 세 가지(승인, 감사 로그, SSO)를 정리하고 보안 자료를 첨부하고, 다음 주 기술 미팅 시간 두 개를 제안해 주세요. 400자 이내."], + ["demo-follow-up", 0, 0, "어제 데모 참석자들한테 후속 메일 보내줘"], + [null, 0, 0, "고객한테 담당 매니저가 바뀐다고 메일 써줘"], + ["cold-first-touch", 0, 1, "제 콜드메일 답장률이 왜 이렇게 낮을까요? 지난주에 보낸 세 통이에요."], + ], + }, + research: { + en: [ + ["account-brief", 1, 0, "Before my call with Ironwood Robotics on Thursday, put together a one-page brief: what they sell, headcount, recent funding or news from the last 6 months, and who we know there from the CRM export attached. Cite a source for each fact."], + ["account-brief", 0, 0, "Research Silverleaf for me before the meeting"], + ["competitor-scan", 1, 0, "Compare the three main competitors in the attached list on pricing, SSO support and audit logs. A table with one row per competitor, and a source link per cell."], + ["competitor-scan", 0, 0, "what are our competitors doing with AI features"], + [null, 1, 0, "Find the market size for B2B invoice automation in Korea and Japan, with sources from 2025 or later, as a short table."], + ["account-brief", 0, 0, "who is Oakridge Partners and what do they do"], + ["competitor-scan", 0, 0, "Look into how competitors price their enterprise tier"], + ["account-brief", 0, 1, "I wrote this account brief on Crescent. Is anything in it out of date?"], + ], + ko: [ + ["account-brief", 1, 0, "목요일 아이언우드 로보틱스 미팅 전에 한 장짜리 브리프를 만들어 주세요. 주요 제품, 직원 수, 최근 6개월 투자나 뉴스, 첨부한 CRM 내보내기에서 우리와 아는 사람. 사실마다 출처를 달아 주세요."], + ["account-brief", 0, 0, "미팅 전에 실버리프 좀 조사해줘"], + ["competitor-scan", 1, 0, "첨부 목록의 주요 경쟁사 세 곳을 가격, SSO 지원, 감사 로그 기준으로 비교해 주세요. 경쟁사마다 한 행, 칸마다 출처 링크가 있는 표로."], + ["competitor-scan", 0, 0, "경쟁사들 AI 기능 뭐 하고 있는지 알아봐줘"], + [null, 1, 0, "한국과 일본의 B2B 송장 자동화 시장 규모를 2025년 이후 자료로 찾아서 짧은 표로 정리해 주세요."], + ["account-brief", 0, 0, "오크리지 파트너스가 뭐 하는 회사야?"], + ["competitor-scan", 0, 0, "경쟁사들이 엔터프라이즈 요금제를 어떻게 책정하는지 조사해줘"], + ["account-brief", 0, 1, "크레센트 고객사 브리프를 써 봤는데 오래된 정보가 있는지 봐 주세요."], + ], + }, + analyze: { + en: [ + ["pipeline-review", 1, 0, "From the pipeline sheet attached, list deals over $50k that haven't moved stage in 30 days, with owner and next step, sorted by amount. Then one sentence on the total at risk."], + ["pipeline-review", 0, 0, "look at our pipeline and tell me what's stuck"], + ["churn-analysis", 1, 0, "Using the attached customer export, compare churned vs retained accounts in the last 12 months on seats, tickets per seat and days since last login. Show the method first, then a table and the two biggest differences."], + ["churn-analysis", 0, 0, "Why are customers churning? Data attached."], + ["forecast-check", 1, 0, "Check the Q4 forecast in this sheet against the last three quarters' close rates by stage. Flag any rep whose forecast is more than 20% above what their history supports."], + ["forecast-check", 0, 0, "does this forecast look right to you"], + [null, 0, 0, "Make a pivot table of this CSV by region"], + ["churn-analysis", 0, 1, "Here is my churn analysis. Is grouping by plan the right way to do it, or am I missing something?"], + ], + ko: [ + ["pipeline-review", 1, 0, "첨부한 파이프라인 시트에서 30일 넘게 단계 변화가 없는 5천만 원 이상 딜을 담당자, 다음 단계와 함께 금액순으로 정리해 주세요. 마지막에 위험 금액 합계를 한 문장으로."], + ["pipeline-review", 0, 0, "파이프라인 보고 막혀 있는 거 알려줘"], + ["churn-analysis", 1, 0, "첨부한 고객 데이터로 최근 12개월 이탈 고객과 유지 고객을 좌석 수, 좌석당 티켓 수, 마지막 로그인 이후 일수로 비교해 주세요. 분석 방법을 먼저 설명하고 표와 가장 큰 차이 두 가지를 보여 주세요."], + ["churn-analysis", 0, 0, "고객들이 왜 이탈하는지 분석해줘. 데이터 첨부함"], + ["forecast-check", 1, 0, "이 시트의 4분기 전망을 지난 세 분기의 단계별 성사율과 비교해서, 과거 실적보다 20% 넘게 높게 잡은 담당자를 표시해 주세요."], + ["forecast-check", 0, 0, "이 전망치 맞는 것 같아?"], + [null, 0, 0, "이 CSV 지역별로 피벗 테이블 만들어줘"], + ["churn-analysis", 0, 1, "이탈 분석을 요금제별로 묶어서 했는데 이 방법이 맞나요? 놓친 게 있을까요?"], + ], + }, + code: { + en: [ + ["new-endpoint", 1, 0, "Add GET /v1/teams/:id/members to the API: admin or the team lead only, paginated with limit/offset like /v1/logs, returns id, email and role. Add an integration test that a member of another team gets 403."], + ["new-endpoint", 0, 0, "add an endpoint for listing team members"], + ["ui-component", 1, 0, "Build a DateRangePicker component for the usage page: presets for 7, 30 and 90 days plus custom, keyboard accessible, uses the kit's Popover. Done when the usage page uses it and the narrow-viewport test passes."], + ["ui-component", 0, 0, "Make a dropdown component for picking the team"], + ["data-migration", 1, 0, "Write a migration that adds a nullable team_id to memberships and backfills it from the old groups table, in batches of 1,000, safe to run while the current code is deployed. Include a rollback note."], + ["data-migration", 0, 0, "we need to move the old settings JSON into real columns"], + [null, 0, 0, "refactor this file, it's a mess"], + ["new-endpoint", 0, 1, "Can you explain how this controller decides which permission to check? I'm new to the codebase."], + ], + ko: [ + ["new-endpoint", 1, 0, "API에 GET /v1/teams/:id/members를 추가해 주세요. 관리자나 팀장만 접근, /v1/logs처럼 limit/offset 페이지네이션, id·이메일·역할 반환. 다른 팀 멤버는 403을 받는 통합 테스트도 추가해 주세요."], + ["new-endpoint", 0, 0, "팀 멤버 목록 엔드포인트 추가해줘"], + ["ui-component", 1, 0, "사용량 페이지용 DateRangePicker 컴포넌트를 만들어 주세요. 7일·30일·90일 프리셋과 직접 선택, 키보드 접근 가능, 키트의 Popover 사용. 사용량 페이지에 적용되고 좁은 화면 테스트가 통과하면 완료입니다."], + ["ui-component", 0, 0, "팀 고르는 드롭다운 컴포넌트 만들어줘"], + ["data-migration", 1, 0, "memberships에 nullable team_id를 추가하고 예전 groups 테이블에서 1,000건씩 백필하는 마이그레이션을 작성해 주세요. 현재 배포된 코드와 함께 돌아도 안전해야 하고, 롤백 방법도 적어 주세요."], + ["data-migration", 0, 0, "예전 설정 JSON을 진짜 컬럼으로 옮겨야 해"], + [null, 0, 0, "이 파일 리팩터링 좀 해줘. 엉망이야"], + ["new-endpoint", 0, 1, "이 컨트롤러가 어떤 권한을 검사할지 어떻게 정하는지 설명해 줄래요? 코드베이스가 처음이라서요."], + ], + }, + fix: { + en: [ + ["failing-test", 1, 0, "billing.test.mjs fails on 'auto top-up stops after a decline' since yesterday's merge. Find the cause and fix the code, not the test. Done when yarn test passes locally."], + ["failing-test", 0, 0, "CI is red, can you fix it"], + ["production-incident", 1, 0, "Prod is returning 502 on /v1/chat/completions for about 8% of requests since 14:10 KST. Logs attached. Find the likely cause, propose the smallest safe fix, and write the two-line status update for customers."], + ["production-incident", 0, 0, "the site is down, help"], + [null, 1, 0, "The date picker shows yesterday for users in New York. Fix it so dates use the browser's time zone, and add a test with America/New_York."], + ["failing-test", 0, 0, "this test is flaky, make it stop failing"], + [null, 0, 0, "there's a bug where the avatar doesn't load"], + ["production-incident", 0, 1, "Why would memory keep climbing on the worker after deploy? Not asking you to fix it yet, just help me understand."], + ], + ko: [ + ["failing-test", 1, 0, "어제 머지 이후로 billing.test.mjs의 '결제 거절 후 자동 충전 중단' 테스트가 실패합니다. 원인을 찾아서 테스트가 아니라 코드를 고쳐 주세요. 로컬에서 yarn test가 통과하면 완료입니다."], + ["failing-test", 0, 0, "CI 빨간불이야. 고쳐줘"], + ["production-incident", 1, 0, "14시 10분부터 운영 환경 /v1/chat/completions 요청의 약 8%가 502를 반환합니다. 로그 첨부합니다. 가능성 높은 원인을 찾고, 가장 작고 안전한 수정안과 고객 공지용 두 줄 상태 업데이트를 써 주세요."], + ["production-incident", 0, 0, "사이트 다운됐어 도와줘"], + [null, 1, 0, "뉴욕 사용자에게 날짜 선택기가 어제 날짜로 보여요. 브라우저 시간대를 쓰도록 고치고 America/New_York 테스트를 추가해 주세요."], + ["failing-test", 0, 0, "이 테스트 가끔 실패하는데 안 실패하게 해줘"], + [null, 0, 0, "프로필 사진이 안 뜨는 버그가 있어"], + ["production-incident", 0, 1, "배포 후에 워커 메모리가 계속 올라가는 이유가 뭘까요? 아직 고치지 말고 이해만 돕고 싶어요."], + ], + }, + review: { + en: [ + ["pull-request-review", 1, 0, "Review PR #193 for security: can a device report sessions for another user or another app? List each finding with file and line, most serious first. Ignore style."], + ["pull-request-review", 0, 0, "review this PR"], + ["pull-request-review", 1, 0, "Look at this diff and tell me whether the migration is safe to run while the old code is still deployed. Yes or no first, then why."], + ["pull-request-review", 0, 0, "can you look over my changes before I push"], + ["pull-request-review", 0, 1, "I'm about to approve this PR from a teammate. What should I look for in a change to the payment flow?"], + [null, 0, 0, "is this code any good"], + ["pull-request-review", 1, 0, "Review the attached patch only for performance: any N+1 queries or unbounded loops? Bullet list, file:line each."], + ["pull-request-review", 0, 1, "Here's a PR I wrote. Be honest, what would a senior engineer push back on?"], + ], + ko: [ + ["pull-request-review", 1, 0, "PR #193을 보안 관점으로 리뷰해 주세요. 기기가 다른 사용자나 다른 앱의 세션을 보고할 수 있나요? 발견 사항마다 파일과 줄 번호를, 심각한 것부터. 스타일은 무시해 주세요."], + ["pull-request-review", 0, 0, "이 PR 리뷰해줘"], + ["pull-request-review", 1, 0, "이 diff를 보고 예전 코드가 배포된 상태에서 마이그레이션을 돌려도 안전한지 알려 주세요. 먼저 예/아니오, 그다음 이유."], + ["pull-request-review", 0, 0, "푸시하기 전에 내 변경사항 좀 봐줄래"], + ["pull-request-review", 0, 1, "동료 PR을 승인하려고 하는데, 결제 흐름을 바꾸는 변경에서는 뭘 봐야 하나요?"], + [null, 0, 0, "이 코드 괜찮아?"], + ["pull-request-review", 1, 0, "첨부한 패치를 성능 관점으로만 리뷰해 주세요. N+1 쿼리나 끝없는 반복이 있나요? 파일:줄 형식의 목록으로."], + ["pull-request-review", 0, 1, "제가 쓴 PR인데 솔직하게, 시니어 엔지니어라면 어디를 지적할까요?"], + ], + }, + test: { + en: [ + ["unit-tests", 1, 0, "Write unit tests for suppress() covering: no small counts, one small count that hides the next smallest, all zeros, and a minimum of 5. Use node:test, one assertion per case."], + ["unit-tests", 0, 0, "add tests for this function"], + ["end-to-end-tests", 1, 0, "Write a Playwright test for sign-in through device code: start authorize, approve as admin in the browser, poll until the key arrives. Must run headless in CI under 30 seconds."], + ["end-to-end-tests", 0, 0, "we need an e2e test for checkout"], + ["unit-tests", 1, 0, "Our date helpers have no tests. Cover week start in Asia/Seoul and America/New_York across a DST change, with expected values written out."], + [null, 0, 0, "increase our test coverage"], + ["end-to-end-tests", 0, 0, "test the whole invite flow end to end"], + ["unit-tests", 0, 1, "What's the difference between mocking the database and using the embedded Postgres for these tests? Which should I use?"], + ], + ko: [ + ["unit-tests", 1, 0, "suppress()의 단위 테스트를 작성해 주세요. 작은 값이 없을 때, 작은 값 하나가 다음으로 작은 값을 가릴 때, 모두 0일 때, 최소값 5일 때. node:test로, 케이스마다 assertion 하나씩."], + ["unit-tests", 0, 0, "이 함수 테스트 추가해줘"], + ["end-to-end-tests", 1, 0, "기기 코드 로그인 Playwright 테스트를 작성해 주세요. authorize 시작, 관리자가 브라우저에서 승인, 키가 올 때까지 폴링. CI에서 헤드리스로 30초 안에 돌아야 합니다."], + ["end-to-end-tests", 0, 0, "결제 E2E 테스트가 필요해"], + ["unit-tests", 1, 0, "날짜 헬퍼에 테스트가 하나도 없어요. 서머타임 전환을 포함해서 Asia/Seoul과 America/New_York의 주 시작일을 예상값을 직접 적어서 검증해 주세요."], + [null, 0, 0, "테스트 커버리지 좀 올려줘"], + ["end-to-end-tests", 0, 0, "초대 흐름 전체를 처음부터 끝까지 테스트해줘"], + ["unit-tests", 0, 1, "이 테스트에서 DB를 목으로 만드는 것과 내장 Postgres를 쓰는 것의 차이가 뭐예요? 뭘 써야 하나요?"], + ], + }, + spec: { + en: [ + ["product-spec", 1, 0, "Write a one-page spec for letting team leads see their team's insights: problem, who it's for, what they can and can't see, the minimum-group rule, and open questions. Use those five headings."], + ["product-spec", 0, 0, "write a PRD for the new sharing feature"], + ["project-plan", 1, 0, "Plan the migration from Crew's ingest to the console's: milestones with owners and dates for the next 6 weeks, dependencies, and the risks with a mitigation each. As a table."], + ["project-plan", 0, 0, "help me plan the Q1 roadmap"], + ["product-spec", 0, 0, "We want customers to be able to export insights. Spec it."], + [null, 0, 0, "write down what we decided in the meeting"], + ["project-plan", 1, 0, "Break the classifier evaluation into tasks of a day or less, in order, with what 'done' means for each."], + ["product-spec", 0, 1, "Read my draft spec. Is the scope too big for one quarter?"], + ], + ko: [ + ["product-spec", 1, 0, "팀장이 자기 팀 인사이트를 보는 기능의 한 장짜리 기획서를 써 주세요. 문제, 대상, 볼 수 있는 것과 없는 것, 최소 그룹 규칙, 남은 질문. 이 다섯 제목으로."], + ["product-spec", 0, 0, "새 공유 기능 PRD 써줘"], + ["project-plan", 1, 0, "Crew 수집에서 콘솔 수집으로 옮기는 계획을 세워 주세요. 앞으로 6주의 마일스톤과 담당자, 날짜, 의존 관계, 리스크마다 대응 방안. 표로."], + ["project-plan", 0, 0, "1분기 로드맵 계획 좀 도와줘"], + ["product-spec", 0, 0, "고객이 인사이트를 내보낼 수 있게 하고 싶어. 기획해줘"], + [null, 0, 0, "회의에서 결정한 거 정리해줘"], + ["project-plan", 1, 0, "분류기 평가 작업을 하루 이내 단위 작업으로 순서대로 나누고, 각각 '완료'의 기준을 적어 주세요."], + ["product-spec", 0, 1, "제 기획서 초안을 읽어 봐 주세요. 한 분기에 하기엔 범위가 너무 큰가요?"], + ], + }, + design: { + en: [ + ["ui-mockup", 1, 0, "Mock up the Insights overview page for an admin: hero sentence, four tiles, teams table, and a 'worth a look' panel. Use the design system tokens, desktop at 1440 wide, light theme."], + ["ui-mockup", 0, 0, "design a settings screen for teams"], + ["marketing-visual", 1, 0, "Make three directions for the launch banner, 1200x630, Redrob blue, headline 'See how your team works with AI', no stock photos of people."], + ["marketing-visual", 0, 0, "need a graphic for the blog post"], + ["ui-mockup", 1, 0, "Redesign the empty state for Explore when fewer than 3 people match: say why nothing is shown and offer to remove a filter. Mobile and desktop."], + [null, 0, 0, "make it look better"], + ["marketing-visual", 0, 0, "an illustration for the onboarding email"], + ["ui-mockup", 0, 1, "Does this dashboard layout have too much on it? Screenshot attached."], + ], + ko: [ + ["ui-mockup", 1, 0, "관리자용 인사이트 개요 페이지 시안을 만들어 주세요. 핵심 문장, 타일 네 개, 팀 표, '살펴볼 것' 패널. 디자인 시스템 토큰 사용, 데스크톱 1440 너비, 라이트 테마."], + ["ui-mockup", 0, 0, "팀 설정 화면 디자인해줘"], + ["marketing-visual", 1, 0, "출시 배너 시안 세 가지를 1200x630으로 만들어 주세요. 레드롭 블루, 헤드라인은 'AI와 일하는 팀의 모습을 보세요', 인물 스톡 사진은 쓰지 말고요."], + ["marketing-visual", 0, 0, "블로그 글에 넣을 그래픽이 필요해"], + ["ui-mockup", 1, 0, "조건에 맞는 사람이 3명 미만일 때 탐색 화면의 빈 상태를 다시 디자인해 주세요. 왜 아무것도 안 보이는지 말하고 필터 제거를 제안하도록. 모바일과 데스크톱 둘 다."], + [null, 0, 0, "좀 더 예쁘게 만들어줘"], + ["marketing-visual", 0, 0, "온보딩 메일에 넣을 일러스트"], + ["ui-mockup", 0, 1, "이 대시보드 레이아웃 너무 복잡한가요? 스크린샷 첨부했어요."], + ], + }, + copy: { + en: [ + ["blog-post", 1, 0, "Write a 900-word blog post for engineering managers on measuring AI adoption without surveillance. Open with a concrete example, three sections, end with what to do this week. Plain words."], + ["blog-post", 0, 0, "write a blog post about our new feature"], + ["landing-page-copy", 1, 0, "Landing page copy for Insights: headline under 8 words, subhead under 20, three benefit blocks of 25 words each, and one CTA. Audience is a head of operations."], + ["landing-page-copy", 0, 0, "rewrite the pricing page copy"], + ["social-post", 1, 0, "LinkedIn post announcing the Korean launch, under 600 characters, one emoji at most, ends with the signup link."], + ["social-post", 0, 0, "tweet about the release"], + [null, 0, 0, "write some marketing copy"], + ["landing-page-copy", 0, 1, "Which of these two headlines is clearer, and why?"], + ], + ko: [ + ["blog-post", 1, 0, "엔지니어링 매니저를 위한 블로그 글을 써 주세요. 감시 없이 AI 도입을 측정하는 방법, 3,000자 내외, 구체적인 사례로 시작해서 세 부분으로 나누고 이번 주에 할 일로 마무리. 쉬운 말로."], + ["blog-post", 0, 0, "새 기능 소개 블로그 글 써줘"], + ["landing-page-copy", 1, 0, "인사이트 랜딩 페이지 문구를 써 주세요. 헤드라인 15자 이내, 서브헤드 40자 이내, 혜택 블록 세 개(각 60자), CTA 하나. 대상은 운영 총괄입니다."], + ["landing-page-copy", 0, 0, "요금제 페이지 문구 다시 써줘"], + ["social-post", 1, 0, "한국 출시를 알리는 링크드인 게시글, 600자 이내, 이모지는 최대 하나, 마지막에 가입 링크."], + ["social-post", 0, 0, "출시 소식 SNS에 올릴 글"], + [null, 0, 0, "마케팅 문구 좀 써줘"], + ["landing-page-copy", 0, 1, "이 두 헤드라인 중에 어느 쪽이 더 명확한지, 이유도 알려 주세요."], + ], + }, + translate: { + en: [ + ["korean-and-english-reply", 1, 0, "Translate my reply below into Korean for a customer in Busan. Polite 합니다 style, keep product names in English, don't add anything."], + ["korean-and-english-reply", 0, 0, "translate this ticket from Korean"], + ["help-article", 1, 0, "Translate the attached help article on SSO into Korean. Keep the headings, code blocks and links unchanged, and use the terms in our glossary file."], + ["help-article", 0, 0, "Can you put the getting started guide into Korean?"], + [null, 0, 0, "translate this"], + ["korean-and-english-reply", 1, 0, "This customer wrote in Korean. Translate their message to English for me, then translate my answer back, matching their level of formality."], + ["help-article", 0, 0, "localize the FAQ page for Japan"], + ["korean-and-english-reply", 0, 1, "Is my Korean in this reply natural, or does it sound like a translation?"], + ], + ko: [ + ["korean-and-english-reply", 1, 0, "아래 제 답장을 미국 고객에게 보낼 영어로 번역해 주세요. 정중하지만 딱딱하지 않게, 제품명은 그대로, 내용은 더하지 말고요."], + ["korean-and-english-reply", 0, 0, "이 영어 티켓 번역해줘"], + ["help-article", 1, 0, "첨부한 SSO 도움말 문서를 영어로 번역해 주세요. 제목, 코드 블록, 링크는 그대로 두고 용어집 파일의 용어를 써 주세요."], + ["help-article", 0, 0, "시작 가이드 영어로 옮겨줄 수 있어?"], + [null, 0, 0, "이거 번역해줘"], + ["korean-and-english-reply", 1, 0, "고객이 영어로 문의했어요. 먼저 한국어로 옮겨 주시고, 제 답변을 고객과 같은 격식 수준의 영어로 다시 번역해 주세요."], + ["help-article", 0, 0, "FAQ 페이지 일본어로 현지화해줘"], + ["korean-and-english-reply", 0, 1, "이 답장 영어 표현이 자연스러운가요, 아니면 번역투인가요?"], + ], + }, + policy: { + en: [ + ["contract-review", 1, 0, "Review the attached MSA from the customer's side. Flag anything on liability caps, data processing, auto-renewal and termination that differs from our standard terms (also attached). Table: clause, theirs, ours, risk."], + ["contract-review", 0, 0, "can you check this contract"], + ["policy-draft", 1, 0, "Draft an internal policy on using AI tools with customer data: what's allowed, what needs approval, what's never allowed, and who to ask. One page, plain language, for all staff."], + ["policy-draft", 0, 0, "write a remote work policy"], + ["contract-review", 1, 0, "Does this NDA allow us to share the customer's name in a case study? Quote the clause and answer yes, no or unclear."], + [null, 0, 0, "what are the legal risks here"], + ["policy-draft", 0, 0, "update our data retention policy"], + ["contract-review", 0, 1, "Explain what an indemnification clause actually does, using this contract as the example."], + ], + ko: [ + ["contract-review", 1, 0, "첨부한 고객사 기본계약서를 검토해 주세요. 책임 한도, 개인정보 처리, 자동 갱신, 해지 조항 중 우리 표준 약관(첨부)과 다른 부분을 표시해 주세요. 표: 조항, 상대방 안, 우리 안, 리스크."], + ["contract-review", 0, 0, "이 계약서 좀 봐줄래?"], + ["policy-draft", 1, 0, "고객 데이터를 다룰 때 AI 도구 사용에 관한 사내 정책 초안을 써 주세요. 허용되는 것, 승인이 필요한 것, 절대 안 되는 것, 문의처. 전 직원 대상, 한 장, 쉬운 말로."], + ["policy-draft", 0, 0, "재택근무 정책 써줘"], + ["contract-review", 1, 0, "이 비밀유지계약서상 고객사 이름을 사례 연구에 써도 되나요? 해당 조항을 인용하고 가능, 불가, 불분명 중 하나로 답해 주세요."], + [null, 0, 0, "여기 법적 리스크가 뭐야"], + ["policy-draft", 0, 0, "데이터 보관 정책 업데이트해줘"], + ["contract-review", 0, 1, "면책 조항이 실제로 무슨 역할을 하는지 이 계약서를 예로 설명해 주세요."], + ], + }, + hr: { + en: [ + ["job-description", 1, 0, "Job description for a senior backend engineer in Seoul: 5+ years, NestJS and Postgres, hybrid 3 days. Sections: the role, what you'll do (5 bullets), what you bring (5 bullets), salary band 90-120M KRW. No 'rockstar'."], + ["job-description", 0, 0, "write a JD for a designer"], + ["review-summary", 1, 0, "Summarize these five peer reviews of one engineer into strengths, growth areas and one suggested goal for next half. Neutral tone, no direct quotes, under 250 words."], + ["review-summary", 0, 0, "summarize the feedback for my report's review"], + ["onboarding-plan", 1, 0, "30-60-90 day onboarding plan for a new customer success manager: a goal, three activities and how we'll know it worked, for each period. As a table."], + ["onboarding-plan", 0, 0, "make an onboarding plan for the new hire starting Monday"], + [null, 0, 0, "help me write an offer letter"], + ["review-summary", 0, 1, "I wrote this self-review. Does it undersell what I did?"], + ], + ko: [ + ["job-description", 1, 0, "서울 근무 시니어 백엔드 엔지니어 채용 공고를 써 주세요. 경력 5년 이상, NestJS와 Postgres, 주 3일 출근. 구성: 직무 소개, 하는 일(5개), 자격 요건(5개), 연봉 9천만~1억 2천만 원. 과장된 표현 없이."], + ["job-description", 0, 0, "디자이너 채용 공고 써줘"], + ["review-summary", 1, 0, "엔지니어 한 명에 대한 동료 평가 다섯 개를 강점, 성장 영역, 다음 반기 목표 하나로 요약해 주세요. 중립적인 어조로, 직접 인용 없이, 600자 이내."], + ["review-summary", 0, 0, "팀원 평가 피드백 요약해줘"], + ["onboarding-plan", 1, 0, "신규 고객성공 매니저의 30-60-90일 온보딩 계획을 표로 만들어 주세요. 기간마다 목표 하나, 활동 세 가지, 잘 됐는지 아는 방법."], + ["onboarding-plan", 0, 0, "월요일에 오는 신입 온보딩 계획 짜줘"], + [null, 0, 0, "처우 제안서 쓰는 것 좀 도와줘"], + ["review-summary", 0, 1, "제가 쓴 자기 평가인데, 한 일을 너무 낮춰 쓴 것 같나요?"], + ], + }, + finance: { + en: [ + ["month-end-reconciliation", 1, 0, "Reconcile the September bank export against the ledger export, both attached. List unmatched lines on each side with amount and date, and the net difference. Match within 2 days and exact amount."], + ["month-end-reconciliation", 0, 0, "help me close the books for this month"], + ["invoice-check", 1, 0, "Check these 12 vendor invoices against the POs: flag any where quantity, unit price or tax differs, and show the difference in KRW. One row per invoice."], + ["invoice-check", 0, 0, "is this invoice correct?"], + ["month-end-reconciliation", 0, 0, "the credit card statement doesn't match our expenses sheet"], + [null, 0, 0, "make a budget for next year"], + ["invoice-check", 1, 0, "Does the Stonebridge invoice charge for 120 seats when the contract says 100? Answer yes or no, then the line that shows it."], + ["month-end-reconciliation", 0, 1, "Walk me through how accruals should work at month end. I keep getting this wrong."], + ], + ko: [ + ["month-end-reconciliation", 1, 0, "첨부한 9월 은행 거래 내역과 원장 내역을 대사해 주세요. 양쪽의 불일치 항목을 금액, 날짜와 함께 나열하고 순차이를 알려 주세요. 날짜는 2일 이내, 금액은 정확히 일치해야 매칭입니다."], + ["month-end-reconciliation", 0, 0, "이번 달 결산 좀 도와줘"], + ["invoice-check", 1, 0, "거래처 송장 12건을 발주서와 대조해서 수량, 단가, 세금이 다른 건을 표시하고 차액을 원화로 보여 주세요. 송장마다 한 행."], + ["invoice-check", 0, 0, "이 세금계산서 맞아?"], + ["month-end-reconciliation", 0, 0, "법인카드 명세서랑 경비 시트가 안 맞아"], + [null, 0, 0, "내년 예산 짜줘"], + ["invoice-check", 1, 0, "계약서에는 100석인데 스톤브리지 송장에 120석이 청구됐나요? 예/아니오로 답하고 해당 줄을 보여 주세요."], + ["month-end-reconciliation", 0, 1, "월말 미지급 비용 처리를 어떻게 해야 하는지 차근차근 설명해 주세요. 자꾸 틀려요."], + ], + }, +}; + +/** + * Cases a classifier is most likely to get wrong. A null action is a correct "not labeled": the + * instruction is personal, too vague, or genuinely between kinds of work. + */ +const HARD: ReadonlyArray = [ + ["en", null, null, 0, 0, "what's a good restaurant near Gangnam station for a team dinner of 8"], + ["ko", null, null, 0, 0, "주말에 부산 여행 일정 짜줘"], + ["en", null, null, 0, 0, "hi"], + ["ko", null, null, 0, 0, "안녕"], + ["en", null, null, 0, 0, "continue"], + ["ko", null, null, 0, 0, "계속해"], + ["en", null, null, 0, 1, "What is the capital of Australia?"], + ["ko", null, null, 0, 1, "양자컴퓨터가 뭐야?"], + ["en", null, null, 0, 0, "help me write a birthday message for my mom"], + ["ko", null, null, 0, 0, "아이 숙제 수학 문제 같이 풀어줘"], + ["en", null, null, 0, 0, "recommend a sci-fi novel for my flight tomorrow"], + ["ko", null, null, 0, 0, "저녁 메뉴 추천해줘. 냉장고에 두부랑 김치 있어"], + ["en", null, null, 0, 1, "explain how mortgages work in Korea, I'm thinking of buying an apartment"], + ["ko", null, null, 0, 1, "블랙홀은 왜 빛도 못 빠져나와?"], + ["en", null, null, 0, 0, "thanks, that's perfect"], + ["ko", null, null, 0, 0, "고마워 완벽해"], + ["en", null, null, 0, 0, "write a short poem about autumn in Seoul"], + ["ko", null, null, 0, 0, "친구 결혼식 축사 써줘"], + ["en", null, null, 0, 0, "do the thing we talked about"], + ["ko", null, null, 0, 0, "아까 그거 다시 해줘"], + ["mixed", "reply", "refund-request", 1, 0, "이 고객 refund request에 답장 써줘. 5 business days 안에 처리된다고, 150자 이내로."], + ["mixed", "fix", "failing-test", 0, 0, "billing test 깨졌어, fix 해줘"], + ["mixed", "email", "demo-follow-up", 0, 0, "어제 demo 들은 Meridian 쪽에 follow-up email 보내줘"], + ["mixed", "code", "new-endpoint", 1, 0, "GET /v1/teams endpoint 추가해줘. admin만 접근 가능하고 integration test 포함해서."], + ["mixed", "analyze", "churn-analysis", 0, 0, "churn data 보고 왜 떠났는지 analysis 해줘"], + ["en", "translate", "korean-and-english-reply", 0, 0, "reply to this Korean customer in Korean, they asked about the refund"], + ["ko", "translate", "help-article", 0, 0, "도움말 문서 영어판 만들어줘"], + ["en", "summ", "call-notes", 0, 0, "Summarize the call and draft the follow-up email"], + ["ko", "research", "competitor-scan", 0, 0, "경쟁사 가격 조사해서 우리 가격 바꿀지 기획안까지 써줘"], + ["en", "review", "pull-request-review", 0, 0, "check if this PR fixes the bug in the ticket"], + ["ko", "fix", null, 0, 0, "PR 리뷰에서 지적받은 거 고쳐줘"], + ["en", "test", "unit-tests", 0, 0, "the function has no tests and a bug, add tests that show the bug first"], + ["en", "policy", "contract-review", 0, 0, "red-line this"], + ["ko", "finance", "invoice-check", 0, 0, "이 청구서 이상한 데 없나 봐줘"], + ["en", "hr", "job-description", 0, 0, "we're hiring a PM, need the posting by tomorrow"], + ["ko", "copy", "social-post", 1, 0, "인스타 캡션 세 개, 각 100자 이내, 해시태그 두 개씩"], + ["en", "design", "ui-mockup", 0, 0, "wireframe"], + ["ko", "spec", "project-plan", 0, 0, "다음 스프린트 뭐 할지 정리"], + ["en", "reply", "how-to-answer", 0, 0, "[PERSON_1] from [ORG_1] is asking how to reset 2FA, answer them"], + ["ko", "email", "renewal-note", 0, 0, "[ORG_1] 담당자 [PERSON_1]님께 계약 갱신 안내 메일 보내줘"], +]; + +const LANGS: ReadonlyArray<"en" | "ko"> = ["en", "ko"]; + +const toSample = (id: string, lang: WorkSample["lang"], source: WorkSample["source"], action: string | null, row: Row): WorkSample => ({ + id, + lang, + source, + action, + task: row[0], + brief: row[1] === 1, + learn: row[2] === 1, + text: row[3], +}); + +export const WORK_SAMPLES: WorkSample[] = [ + ...Object.entries(PLAIN).flatMap(([action, rows]) => + LANGS.flatMap((lang) => rows[lang].map((row, i) => toSample(`${action}-${lang}-${i + 1}`, lang, "plain", action, row))), + ), + ...HARD.map(([lang, action, ...row], i) => toSample(`hard-${i + 1}`, lang, "hard", action, row)), +]; diff --git a/packages/work-labeller/model/prototypes.test.ts b/packages/work-labeller/model/prototypes.test.ts new file mode 100644 index 0000000000..fd9233c8ea --- /dev/null +++ b/packages/work-labeller/model/prototypes.test.ts @@ -0,0 +1,25 @@ +import { describe, expect, test } from "bun:test"; + +import { WORK_SAMPLES } from "./eval/work-samples.js"; +import { WORK_ACTIONS } from "../src/index.js"; +import { WORK_PROTOTYPES } from "./prototypes.js"; + +const normal = (text: string) => text.toLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim(); + +describe("work classifier prototypes", () => { + test("none is, or contains, a phrase of the evaluation set", () => { + const samples = WORK_SAMPLES.map((s) => normal(s.text)); + for (const prototype of WORK_PROTOTYPES) { + const p = normal(prototype.text); + expect(samples.filter((s) => s === p || (p.length > 12 && s.includes(p)))).toEqual([]); + } + }); + + test("every kind of work has at least three phrases in each language", () => { + for (const action of WORK_ACTIONS) { + const of = WORK_PROTOTYPES.filter((p) => p.action === action); + expect(of.filter((p) => /[가-힣]/.test(p.text)).length).toBeGreaterThanOrEqual(3); + expect(of.filter((p) => !/[가-힣]/.test(p.text)).length).toBeGreaterThanOrEqual(3); + } + }); +}); diff --git a/packages/work-labeller/model/prototypes.ts b/packages/work-labeller/model/prototypes.ts new file mode 100644 index 0000000000..7dfe394842 --- /dev/null +++ b/packages/work-labeller/model/prototypes.ts @@ -0,0 +1,169 @@ +/* + * The phrases the work classifier compares a first message with: a few per kind of work, in English + * and Korean, plus phrases for asking to learn and for things that are not work. + * + * These are part of the classifier, not of its evaluation. They are written apart from the + * evaluation set (eval/work-samples.ts) and never copied from it, so a score on that set measures how + * the classifier does on messages it has not seen. `prototypes.test.ts` fails if any phrase + * here also appears there. + */ + +export type Prototype = { action: string | null; learn: boolean; text: string }; + +const work = (action: string, phrases: readonly string[]): Prototype[] => + phrases.map((text) => ({ action, learn: false, text })); + +export const WORK_PROTOTYPES: Prototype[] = [ + ...work("reply", [ + "answer a customer's support ticket", + "write a reply to the customer who reported a problem", + "respond to this help desk request", + "고객 문의 티켓에 답변 작성", + "문제를 신고한 고객에게 보낼 답장", + "고객센터 문의에 회신", + ]), + ...work("summ", [ + "summarize this conversation for me", + "give me the key points of the meeting transcript", + "condense the thread into a short recap", + "이 대화 내용 요약", + "회의 녹취록 핵심 정리", + "스레드를 짧게 정리해줘", + ]), + ...work("email", [ + "write an email to a client", + "draft an outreach email to a prospect", + "compose a follow-up message to the customer", + "고객사에 보낼 이메일 작성", + "잠재 고객에게 보낼 영업 메일", + "고객에게 후속 메일 쓰기", + ]), + ...work("research", [ + "look up information about this company", + "investigate the market and competitors", + "find sources and background on an account", + "이 회사에 대한 정보 조사", + "시장과 경쟁사 리서치", + "고객사 배경 자료 찾기", + ]), + ...work("analyze", [ + "analyze the data in this spreadsheet", + "find trends in these numbers", + "compare figures across the sheet and report what changed", + "이 스프레드시트 데이터 분석", + "숫자에서 추세 찾기", + "시트 수치 비교해서 변화 보고", + ]), + ...work("code", [ + "implement a new feature in the codebase", + "add an API endpoint", + "build a component for the app", + "코드베이스에 새 기능 구현", + "API 엔드포인트 추가", + "앱에 들어갈 컴포넌트 개발", + ]), + ...work("fix", [ + "fix this bug", + "debug why the service is failing", + "the build is broken, find the cause and repair it", + "이 버그 수정", + "서비스가 실패하는 원인 디버깅", + "빌드 깨진 거 원인 찾아서 고치기", + ]), + ...work("review", [ + "review this pull request", + "look over the code changes and point out problems", + "do a code review of the diff", + "이 풀 리퀘스트 리뷰", + "코드 변경사항 검토하고 문제 지적", + "diff 코드 리뷰", + ]), + ...work("test", [ + "write tests for this module", + "add test cases that cover the edge cases", + "create an automated test for the flow", + "이 모듈 테스트 작성", + "엣지 케이스 테스트 추가", + "흐름 자동화 테스트 만들기", + ]), + ...work("spec", [ + "write a product requirements document", + "plan the project with milestones", + "draft a spec for the feature", + "제품 요구사항 문서 작성", + "마일스톤으로 프로젝트 계획", + "기능 기획서 초안", + ]), + ...work("design", [ + "design a screen layout", + "create a mockup of the page", + "make a visual for the campaign", + "화면 레이아웃 디자인", + "페이지 시안 만들기", + "캠페인 비주얼 제작", + ]), + ...work("copy", [ + "write marketing copy", + "draft a blog article for our audience", + "write a social media post announcing the launch", + "마케팅 문구 작성", + "블로그 글 초안", + "출시 알리는 SNS 게시물", + ]), + ...work("translate", [ + "translate this text into another language", + "localize the document for Korean readers", + "translate the customer's message to English", + "이 글을 다른 언어로 번역", + "문서를 영어 독자용으로 현지화", + "고객 메시지 한국어로 번역", + ]), + ...work("policy", [ + "review the terms of this contract", + "check the agreement for legal risks", + "draft a company policy", + "계약서 조항 검토", + "계약의 법적 리스크 확인", + "회사 정책 초안 작성", + ]), + ...work("hr", [ + "write a job posting", + "summarize performance feedback for an employee", + "create an onboarding plan for a new hire", + "채용 공고 작성", + "직원 성과 피드백 요약", + "신입 사원 온보딩 계획", + ]), + ...work("finance", [ + "reconcile the accounts", + "check invoices against purchase orders", + "match bank transactions to the ledger", + "계정 대사 작업", + "송장과 발주서 대조", + "은행 거래와 장부 맞추기", + ]), + /* Asking to learn: an explanation, or a review of one's own work, rather than the work. */ + ...[ + "explain how this works", + "help me understand the concept", + "what am I doing wrong here, give me feedback", + "is my draft good enough", + "이게 어떻게 동작하는지 설명해줘", + "개념을 이해하게 도와줘", + "내가 뭘 잘못하고 있는지 피드백 해줘", + "내 초안 괜찮은지 봐줘", + ].map((text) => ({ action: null, learn: true, text })), + /* Not about work: personal asks and messages with nothing to classify. */ + ...[ + "plan my vacation", + "suggest something to cook tonight", + "tell me a joke", + "ok thanks", + "go on", + "휴가 계획 세워줘", + "오늘 저녁 뭐 먹지", + "농담 하나 해줘", + "응 고마워", + "계속", + ].map((text) => ({ action: null, learn: false, text })), +]; diff --git a/packages/work-labeller/model/scripts/evaluate.py b/packages/work-labeller/model/scripts/evaluate.py new file mode 100644 index 0000000000..2fd13dc257 --- /dev/null +++ b/packages/work-labeller/model/scripts/evaluate.py @@ -0,0 +1,266 @@ +""" +Measures candidate models for the on-device work classifier against the evaluation set. + +Reproduce: + uv pip install -r packages/work-labeller/model/scripts/requirements.txt + cd packages/work-labeller && bun model/scripts/export.ts > .model-runs/eval-data.json + python model/scripts/evaluate.py .model-runs/eval-data.json + +Each candidate embeds the prototype phrases (model/prototypes.ts) and each sample +(model/eval/work-samples.ts), and answers with the kind of work of the nearest prototypes, +or nothing when the best match is not clearly better than "not work". The threshold is chosen on the +prototypes alone, never on the samples, so the score is not tuned to the set it is reported on. +""" + +import json +import statistics +import sys +import time +from pathlib import Path + +import numpy as np +import onnxruntime as ort +from huggingface_hub import hf_hub_download +from tokenizers import Tokenizer + +CANDIDATES = [ + # id, repo, revision, onnx file, query prefix, pooling + ("e5-small", "Xenova/multilingual-e5-small", "761b726d", "onnx/model_int8.onnx", "query: ", "mean"), + ("minilm-l12", "Xenova/paraphrase-multilingual-MiniLM-L12-v2", "2c4055b1", "onnx/model_int8.onnx", "", "mean"), + ("e5-base", "Xenova/multilingual-e5-base", "1ec92430", "onnx/model_int8.onnx", "query: ", "mean"), +] + +# The bar, written down before the first run. +BAR = { + "precision": 0.85, # of the kinds of work it names, the share it names correctly + "coverage": 0.70, # of messages that are work, the share it names a kind for + "abstain": 0.70, # of messages that are not work or too vague, the share it leaves unlabeled + "ko_gap": 0.10, # Korean precision no more than this below English + # Raised from 120 MB on 2026-10-08, by product decision, to ship the kind of work on e5-base (278 MB). + "size_mb": 300, + "ms": 50, # median per message, 2 threads +} + +TOP_K = 3 + + +def load(repo, revision, onnx_file): + full = None + from huggingface_hub import HfApi + + for ref in HfApi().list_repo_commits(repo): + if ref.commit_id.startswith(revision): + full = ref.commit_id + break + model = hf_hub_download(repo, onnx_file, revision=full) + tok = hf_hub_download(repo, "tokenizer.json", revision=full) + options = ort.SessionOptions() + options.intra_op_num_threads = 2 + options.inter_op_num_threads = 1 + # Basic optimisations only: they are exact, so onnxruntime-node in redrob-server reproduces these + # embeddings bit for bit. The extended fusions ("all") change int8 numerics by version. + options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_BASIC + started = time.perf_counter() + session = ort.InferenceSession(model, options, providers=["CPUExecutionProvider"]) + load_ms = (time.perf_counter() - started) * 1000 + tokenizer = Tokenizer.from_file(tok) + tokenizer.enable_truncation(256) + return session, tokenizer, Path(model).stat().st_size / 1e6, load_ms, full + + +def embed(session, tokenizer, texts, prefix): + names = {i.name for i in session.get_inputs()} + out = [] + times = [] + for text in texts: + enc = tokenizer.encode(prefix + text) + ids = np.array([enc.ids], dtype=np.int64) + mask = np.array([enc.attention_mask], dtype=np.int64) + feeds = {"input_ids": ids, "attention_mask": mask} + if "token_type_ids" in names: + feeds["token_type_ids"] = np.zeros_like(ids) + started = time.perf_counter() + hidden = session.run(None, feeds)[0][0] + times.append((time.perf_counter() - started) * 1000) + m = mask[0][:, None].astype(np.float32) + vec = (hidden * m).sum(0) / m.sum() + out.append(vec / np.linalg.norm(vec)) + return np.stack(out), times + + +def scores_by_label(sims, labels): + """Mean of the top-k similarities per label (an action key, or None for not work).""" + by = {} + for label in set(labels): + idx = [i for i, l in enumerate(labels) if l == label] + top = np.sort(sims[:, idx], axis=1)[:, -min(TOP_K, len(idx)) :] + by[label] = top.mean(axis=1) + return by + + +def classify(by, margin): + """The best action when it beats "not work" by at least the margin, else None.""" + actions = [k for k in by if k is not None] + n = len(next(iter(by.values()))) + answers = [] + for i in range(n): + best = max(actions, key=lambda a: by[a][i]) + answers.append(best if by[best][i] - by[None][i] >= margin else None) + return answers + + +def choose_margin(proto_vecs, proto_labels): + """Leave-one-out on the prototypes: the margin that best separates work from not work there.""" + sims = proto_vecs @ proto_vecs.T + np.fill_diagonal(sims, -1.0) + by = scores_by_label(sims, proto_labels) + best, best_score = 0.0, -1 + for margin in np.arange(-0.05, 0.15, 0.005): + answers = classify(by, margin) + right = sum(1 for a, l in zip(answers, proto_labels) if a == l) + if right > best_score: + best, best_score = float(margin), right + return best + + +SCALE = 20.0 # cosine-softmax temperature: unit vectors carry too little range for 17 classes + + +def train_head(vecs, labels, epochs=400, lr=0.5, l2=1e-3): + """Softmax regression on the prototypes only. Classes: every action, plus None for not work.""" + vecs = vecs * SCALE + classes = sorted({l for l in labels if l is not None}) + [None] + y = np.array([classes.index(l) for l in labels]) + w = np.zeros((vecs.shape[1], len(classes))) + b = np.zeros(len(classes)) + onehot = np.eye(len(classes))[y] + for _ in range(epochs): + logits = vecs @ w + b + logits -= logits.max(axis=1, keepdims=True) + p = np.exp(logits) + p /= p.sum(axis=1, keepdims=True) + grad = p - onehot + w -= lr * (vecs.T @ grad / len(y) + l2 * w) + b -= lr * grad.mean(axis=0) + return classes, w, b + + +def head_answers(classes, w, b, vecs, min_p): + logits = (vecs * SCALE) @ w + b + logits -= logits.max(axis=1, keepdims=True) + p = np.exp(logits) + p /= p.sum(axis=1, keepdims=True) + out = [] + for row in p: + k = int(row.argmax()) + out.append(classes[k] if classes[k] is not None and row[k] >= min_p else None) + return out + + +def choose_floor(vecs, labels): + """ + The confidence floor, from the prototypes alone: train without each one in turn, record what the + head said about it and how sure it was, and keep the lowest floor whose held-out precision on + named kinds of work is at least the bar. Never looks at the evaluation set. + """ + held = [] + for i in range(len(labels)): + keep = [j for j in range(len(labels)) if j != i] + classes, w, b = train_head(vecs[keep], [labels[j] for j in keep]) + logits = (vecs[i : i + 1] * SCALE) @ w + b + logits -= logits.max() + p = np.exp(logits[0]) + p /= p.sum() + k = int(p.argmax()) + held.append((classes[k], float(p[k]), labels[i])) + for floor in np.arange(0.05, 0.95, 0.01): + named = [(a, l) for a, conf, l in held if a is not None and conf >= floor] + if named and sum(a == l for a, l in named) / len(named) >= BAR["precision"]: + return float(floor) + return 0.95 + + +METHOD = "nearest" + + +def evaluate(candidate, data): + cid, repo, revision, onnx_file, prefix, _ = candidate + session, tokenizer, size_mb, load_ms, full = load(repo, revision, onnx_file) + protos = data["prototypes"] + proto_labels = [None if p["learn"] or p["action"] is None else p["action"] for p in protos] + proto_vecs, _ = embed(session, tokenizer, [p["text"] for p in protos], prefix) + margin = choose_margin(proto_vecs, proto_labels) + samples = data["samples"] + vecs, times = embed(session, tokenizer, [s["text"] for s in samples], prefix) + if METHOD == "head": + margin = choose_floor(proto_vecs, proto_labels) + classes, w, b = train_head(proto_vecs, proto_labels) + answers = head_answers(classes, w, b, vecs, margin) + else: + by = scores_by_label(vecs @ proto_vecs.T, proto_labels) + answers = classify(by, margin) + + def rates(keep): + rows = [(a, s) for a, s in zip(answers, samples) if keep(s)] + work = [(a, s) for a, s in rows if s["action"] is not None] + named = [(a, s) for a, s in work if a is not None] + named_all = [(a, s) for a, s in rows if a is not None] + none = [(a, s) for a, s in rows if s["action"] is None] + return { + "n": len(rows), + "precision": sum(a == s["action"] for a, s in named_all) / len(named_all) if named_all else None, + "coverage": len(named) / len(work) if work else None, + "accuracy": sum(a == s["action"] for a, s in work) / len(work) if work else None, + "abstain": sum(a is None for a, _ in none) / len(none) if none else None, + } + + report = { + "id": f"{cid}/{METHOD}", + "repo": repo, + "revision": full, + "file": onnx_file, + "size_mb": round(size_mb, 1), + "load_ms": round(load_ms), + "ms_median": round(statistics.median(times), 1), + "margin": round(margin, 3), + "all": rates(lambda s: True), + "en": rates(lambda s: s["lang"] == "en"), + "ko": rates(lambda s: s["lang"] == "ko"), + "plain": rates(lambda s: s["source"] == "plain"), + "hard": rates(lambda s: s["source"] == "hard"), + "confusions": {}, + } + for a, s in zip(answers, samples): + if s["action"] and a and a != s["action"]: + key = f'{s["action"]}->{a}' + report["confusions"][key] = report["confusions"].get(key, 0) + 1 + a = report["all"] + fails = [] + if (a["precision"] or 0) < BAR["precision"]: + fails.append("precision") + if (a["coverage"] or 0) < BAR["coverage"]: + fails.append("coverage") + if (a["abstain"] or 0) < BAR["abstain"]: + fails.append("abstain") + if (report["en"]["precision"] or 0) - (report["ko"]["precision"] or 0) > BAR["ko_gap"]: + fails.append("korean") + if size_mb > BAR["size_mb"]: + fails.append("size") + if report["ms_median"] > BAR["ms"]: + fails.append("latency") + report["bar"] = "pass" if not fails else "fail: " + ", ".join(fails) + return report + + +def main(): + global METHOD + data = json.loads(Path(sys.argv[1]).read_text()) + reports = [] + for method in ("nearest", "head"): + METHOD = method + reports += [evaluate(c, data) for c in CANDIDATES] + print(json.dumps({"bar": BAR, "samples": len(data["samples"]), "prototypes": len(data["prototypes"]), "reports": reports}, ensure_ascii=False, indent=1)) + + +if __name__ == "__main__": + main() diff --git a/packages/work-labeller/model/scripts/export.ts b/packages/work-labeller/model/scripts/export.ts new file mode 100644 index 0000000000..3523a54202 --- /dev/null +++ b/packages/work-labeller/model/scripts/export.ts @@ -0,0 +1,8 @@ +// Prints the evaluation set, the prototypes and the training set as JSON, for evaluate.py and train.py. +import { WORK_SAMPLES } from "../eval/work-samples.ts"; +import { WORK_PROTOTYPES } from "../prototypes.ts"; +import { TRAINING_EXAMPLES } from "../train/index.ts"; +import { TUNING_EXAMPLES } from "../train/tuning.ts"; + +// Bun.write, not console.log: piped, console.log split a multibyte character at a buffer boundary. +await Bun.write(Bun.stdout, `${JSON.stringify({ samples: WORK_SAMPLES, prototypes: WORK_PROTOTYPES, training: TRAINING_EXAMPLES, tuning: TUNING_EXAMPLES })}\n`); diff --git a/packages/work-labeller/model/scripts/requirements.txt b/packages/work-labeller/model/scripts/requirements.txt new file mode 100644 index 0000000000..8e73086f79 --- /dev/null +++ b/packages/work-labeller/model/scripts/requirements.txt @@ -0,0 +1,4 @@ +onnxruntime==1.30.0 +tokenizers==0.23.2 +huggingface_hub +numpy diff --git a/packages/work-labeller/model/scripts/train.py b/packages/work-labeller/model/scripts/train.py new file mode 100644 index 0000000000..197b3f401f --- /dev/null +++ b/packages/work-labeller/model/scripts/train.py @@ -0,0 +1,184 @@ +""" +Trains the work classifier's head and measures it on the evaluation set. + +Reproduce: + uv pip install -r packages/work-labeller/model/scripts/requirements.txt + cd packages/work-labeller + bun model/scripts/export.ts > .model-runs/eval-data.json + python model/scripts/train.py .model-runs/eval-data.json + +The head is softmax regression on a frozen encoder's sentence embeddings, at two levels: the work +family (write, sheet, code, design, or not work) and the kind of work. Training uses the training set +and the prototypes. The confidence floors come from the tuning slice (model/train/tuning.ts), +written like the evaluation set but apart from it: the lowest floor at which the tuning slice reaches +TUNING_PRECISION with TUNING_COVERAGE, chosen before the evaluation set is scored. The evaluation set +is embedded once, at the end, and only scored. Writes the head of the candidate that +passes the most levels (the smaller on a tie) to .model-runs/head.json. +""" + +import json +import sys +from pathlib import Path + +import numpy as np + +sys.path.insert(0, str(Path(__file__).parent)) +import evaluate as ev # noqa: E402 + +FAMILY = { + "reply": "write", "summ": "write", "email": "write", "research": "write", "spec": "write", + "copy": "write", "translate": "write", "policy": "write", "hr": "write", + "analyze": "sheet", "finance": "sheet", + "code": "code", "fix": "code", "review": "code", "test": "code", + "design": "design", +} +SCALE = 20.0 +# Five points above the bar: the tuning slice is small (128 work messages), so a floor that only just +# reaches 85% on it would land under 85% about half the time on new data. +TUNING_PRECISION = 0.90 +TUNING_COVERAGE = 0.70 + + +def fit(x, labels, epochs=600, lr=0.5, l2=1e-3): + classes = sorted({l for l in labels if l is not None}) + [None] + y = np.array([classes.index(l) for l in labels]) + onehot = np.eye(len(classes))[y] + xs = x * SCALE + w = np.zeros((x.shape[1], len(classes))) + b = np.zeros(len(classes)) + for _ in range(epochs): + logits = xs @ w + b + logits -= logits.max(axis=1, keepdims=True) + p = np.exp(logits) + p /= p.sum(axis=1, keepdims=True) + grad = p - onehot + w -= lr * (xs.T @ grad / len(y) + l2 * w) + b -= lr * grad.mean(axis=0) + return classes, w, b + + +def predict(model, x): + classes, w, b = model + logits = (x * SCALE) @ w + b + logits -= logits.max(axis=1, keepdims=True) + p = np.exp(logits) + p /= p.sum(axis=1, keepdims=True) + k = p.argmax(axis=1) + return [classes[i] for i in k], p[np.arange(len(k)), k] + + +def floor_for(model, x, labels): + """The lowest floor at which the tuning slice reaches the tuning precision and coverage.""" + names, conf = predict(model, x) + work = sum(1 for l in labels if l is not None) + for floor in np.arange(0.05, 0.96, 0.01): + named = [(n, l) for n, c, l in zip(names, conf, labels) if n is not None and c >= floor] + if not named: + break + precision = sum(n == l for n, l in named) / len(named) + coverage = sum(1 for n, l in named if l is not None) / work + if coverage < TUNING_COVERAGE: + break + if precision >= TUNING_PRECISION: + return float(floor) + return 0.96 + + +def answer(model, floor, x): + names, conf = predict(model, x) + return [n if n is not None and c >= floor else None for n, c in zip(names, conf)] + + +def score(answers, truths, samples): + def rates(keep): + rows = [(a, t, s) for a, t, s in zip(answers, truths, samples) if keep(s)] + named = [(a, t) for a, t, _ in rows if a is not None] + work = [(a, t) for a, t, _ in rows if t is not None] + none = [a for a, t, _ in rows if t is None] + return { + "precision": sum(a == t for a, t in named) / len(named) if named else None, + "coverage": sum(a is not None for a, _ in work) / len(work) if work else None, + "abstain": sum(a is None for a in none) / len(none) if none else None, + } + + return { + "all": rates(lambda s: True), + "en": rates(lambda s: s["lang"] == "en"), + "ko": rates(lambda s: s["lang"] == "ko"), + "hard": rates(lambda s: s["source"] == "hard"), + } + + +def bar(result, size_mb, ms): + a = result["all"] + fails = [] + if (a["precision"] or 0) < ev.BAR["precision"]: + fails.append("precision") + if (a["coverage"] or 0) < ev.BAR["coverage"]: + fails.append("coverage") + if (a["abstain"] or 0) < ev.BAR["abstain"]: + fails.append("abstain") + if (result["en"]["precision"] or 0) - (result["ko"]["precision"] or 0) > ev.BAR["ko_gap"]: + fails.append("korean") + if size_mb > ev.BAR["size_mb"]: + fails.append("size") + if ms > ev.BAR["ms"]: + fails.append("latency") + return "pass" if not fails else "fail: " + ", ".join(fails) + + +def main(): + data = json.loads(Path(sys.argv[1]).read_text()) + train = [{"text": p["text"], "action": None if p["learn"] else p["action"]} for p in data["prototypes"]] + [ + {"text": t["text"], "action": None if t["learn"] else t["action"]} for t in data["training"] + ] + samples = data["samples"] + tuning = data["tuning"] + reports = [] + best = None + for cid, repo, revision, onnx_file, prefix, _ in ev.CANDIDATES: + session, tokenizer, size_mb, _, full = ev.load(repo, revision, onnx_file) + x, _ = ev.embed(session, tokenizer, [t["text"] for t in train], prefix) + actions = [t["action"] for t in train] + families = [FAMILY[a] if a else None for a in actions] + action_model, family_model = fit(x, actions), fit(x, families) + tx, _ = ev.embed(session, tokenizer, [t["text"] for t in tuning], prefix) + tuning_actions = [t["action"] for t in tuning] + action_floor = floor_for(action_model, tx, tuning_actions) + family_floor = floor_for(family_model, tx, [FAMILY[a] if a else None for a in tuning_actions]) + sx, times = ev.embed(session, tokenizer, [s["text"] for s in samples], prefix) + ms = float(np.median(times)) + result = {} + for level, model, floor, truth in ( + ("action", action_model, action_floor, [s["action"] for s in samples]), + ("family", family_model, family_floor, [FAMILY[s["action"]] if s["action"] else None for s in samples]), + ): + r = score(answer(model, floor, sx), truth, samples) + r["floor"] = round(floor, 2) + r["bar"] = bar(r, size_mb, ms) + result[level] = r + report = {"id": cid, "repo": repo, "revision": full, "file": onnx_file, "size_mb": round(size_mb, 1), "ms": round(ms, 1), **result} + reports.append(report) + # The candidate that passes more levels wins; on a tie, the earlier (smaller) one. + passed = (result["action"]["bar"] == "pass") + (result["family"]["bar"] == "pass") + if passed and (best is None or passed > best[0]): + best = (passed, report, action_model, action_floor, family_model, family_floor, prefix) + print(json.dumps({"bar": ev.BAR, "training": len(train), "tuning": len(tuning), "samples": len(samples), "reports": reports}, indent=1)) + if best: + _, report, am, af, fm, ff, prefix = best + + def dump(model, floor): + classes, w, b = model + return {"classes": classes, "scale": SCALE, "floor": round(floor, 2), "w": np.round(w, 5).tolist(), "b": np.round(b, 5).tolist()} + + head = { + "encoder": {k: report[k] for k in ("repo", "revision", "file")}, + "prefix": prefix, + "action": dump(am, af) if report["action"]["bar"] == "pass" else None, + "family": dump(fm, ff), + } + Path(sys.argv[1]).with_name("head.json").write_text(json.dumps(head)) + + +if __name__ == "__main__": + main() diff --git a/packages/work-labeller/model/train/contrast.ts b/packages/work-labeller/model/train/contrast.ts new file mode 100644 index 0000000000..3032553c84 --- /dev/null +++ b/packages/work-labeller/model/train/contrast.ts @@ -0,0 +1,217 @@ +/* + * Contrastive training examples: kinds of work that share words with a neighbour. "Review" a contract + * (policy) or a pull request (review); a test that fails (fix) or tests to write (test); a summary of + * what happened (summ) or copy for an audience (copy). Each example leans on the word the neighbour + * also uses, so the head learns what tells them apart. The pairs come from the tuning slice + * (tuning.ts), never from the evaluation set. + */ +import type { TrainingRows } from "./types.js"; + +export const CONTRAST: TrainingRows = { + fix: { + en: [ + "The integration test for refunds keeps failing on CI, find out what broke in the code", + "test_invoice_totals fails since yesterday's merge, track down the bug and fix it", + "Our e2e suite is red because login redirects to a blank page. Fix the redirect.", + "A unit test caught a rounding error in tax calculation, patch the calculation", + "flaky test turned out to be a real race condition in the cache, fix the race", + "The tests pass locally but the build fails in production, figure out why and fix it", + "Error rate on the payments API spiked after the release. Find the cause and roll forward a fix.", + "Customers get logged out every 5 minutes, debug the session expiry", + ], + ko: [ + "CI에서 환불 통합 테스트가 계속 실패해, 코드에서 뭐가 깨졌는지 찾아줘", + "어제 머지 이후로 test_invoice_totals가 실패해요. 버그 찾아서 고쳐 주세요.", + "로그인하면 빈 페이지로 리다이렉트돼서 E2E가 다 빨간불이야, 리다이렉트 고쳐줘", + "단위 테스트에서 세금 계산 반올림 오류가 잡혔어요. 계산 로직을 수정해 주세요.", + "불안정한 테스트인 줄 알았는데 캐시 경쟁 조건이었어, 그거 고쳐줘", + "로컬에선 테스트가 통과하는데 운영 빌드가 실패해요. 원인 찾아서 고쳐 주세요.", + "배포 이후 결제 API 에러율이 튀었어요. 원인을 찾아서 수정해 주세요.", + "고객들이 5분마다 로그아웃돼, 세션 만료 디버깅해줘", + ], + }, + test: { + en: [ + "Nothing tests the refund flow yet. Write integration tests for full and partial refunds.", + "Add a regression test so the tax rounding bug we fixed can't come back", + "write Playwright tests for the checkout page, happy path and declined card", + "Increase coverage on the auth module to 80%, test the token refresh edge cases", + "Write property-based tests for the date parser", + "add unit tests for every branch in the permissions helper", + ], + ko: [ + "환불 흐름은 아직 테스트가 없어요. 전액 환불과 부분 환불 통합 테스트를 작성해 주세요.", + "우리가 고친 세금 반올림 버그가 다시 안 생기게 회귀 테스트 추가해줘", + "결제 페이지 Playwright 테스트 써줘, 정상 결제랑 카드 거절 케이스로", + "인증 모듈 커버리지를 80%까지 올려 주세요. 토큰 갱신 경계 케이스를 테스트해 주세요.", + "날짜 파서에 속성 기반 테스트 작성해줘", + "권한 헬퍼의 모든 분기에 단위 테스트 추가해줘", + ], + }, + policy: { + en: [ + "Review the vendor agreement and mark any clause that lets them use our data for training", + "Look over this SaaS contract and tell me what the termination terms really say", + "check the indemnity section of this partnership agreement against our playbook", + "Go through the DPA they sent and list where it deviates from GDPR standard clauses", + "review this lease for anything that puts the cost of repairs on us", + "Redline the liability cap in this order form", + "Draft our data retention policy: what we keep, for how long, and who can delete it", + "write a travel and expense policy for a 40-person company", + ], + ko: [ + "공급업체 계약서 검토해서 우리 데이터를 학습에 쓸 수 있게 한 조항 표시해줘", + "이 SaaS 계약서 해지 조항이 실제로 무슨 뜻인지 검토해 주세요", + "제휴 계약서 면책 조항을 우리 기준이랑 비교해서 봐줘", + "상대방이 보낸 데이터처리약정서를 검토해서 GDPR 표준 조항과 다른 곳을 정리해 주세요.", + "이 임대차 계약서에 수리비를 우리가 부담하게 하는 내용 있는지 검토해줘", + "이 주문서의 책임 한도 조항에 수정 의견 달아줘", + "데이터 보관 정책 초안을 써 주세요. 무엇을, 얼마나, 누가 삭제할 수 있는지요.", + "40명 규모 회사 출장비 경비 규정 써줘", + ], + }, + review: { + en: [ + "Review the pull request that adds the webhook retry logic, and flag anything that could loop forever", + "look over this PR's database queries for N+1 problems", + "Give feedback on my teammate's refactor of the auth middleware before we merge", + "review the diff in this merge request and approve it or list what blocks it", + "Check this pull request for missing error handling", + "code review please, mostly worried about the concurrency in worker.go", + ], + ko: [ + "웹훅 재시도 로직을 추가한 풀리퀘스트를 리뷰하고 무한 반복될 수 있는 부분을 짚어 주세요", + "이 PR 데이터베이스 쿼리에 N+1 문제 있는지 봐줘", + "머지 전에 동료가 인증 미들웨어 리팩터링한 거 코드 리뷰해 주세요", + "이 머지 리퀘스트 diff 리뷰하고 승인할지 막는 이유가 뭔지 알려줘", + "이 풀리퀘스트에 빠진 에러 처리 있는지 확인해줘", + "코드 리뷰 부탁해, worker.go 동시성 부분이 제일 걱정돼", + ], + }, + summ: { + en: [ + "Summarise this Slack thread about the outage so someone who missed it can catch up", + "condense the meeting transcript into decisions and action items", + "Give me the gist of the last two weeks of emails with Orbit Labs", + "Recap the customer interview recordings: what they liked, what confused them", + "boil this 30-page report down to half a page", + "write a summary of the incident channel for the postmortem doc", + ], + ko: [ + "장애 관련 슬랙 스레드를 못 본 사람도 따라올 수 있게 요약해 주세요", + "회의 녹취록을 결정 사항이랑 할 일로 정리해줘", + "오르빗랩스랑 최근 2주 주고받은 메일 핵심만 알려줘", + "고객 인터뷰 녹음 내용을 좋았던 점, 헷갈려한 점으로 정리해 주세요", + "이 30페이지 보고서를 반 페이지로 줄여줘", + "회고 문서에 넣을 수 있게 장애 채널 내용 요약해줘", + ], + }, + copy: { + en: [ + "Write the announcement post for our new pricing, upbeat but honest about the increase", + "punchy headline and subhead for the integrations page", + "Write a newsletter intro for customers about the spring release", + "write ad copy for a search campaign aimed at finance teams, three variants", + "Product Hunt launch description, 260 characters", + "Draft the copy for our careers page hero section", + ], + ko: [ + "새 요금제 공지 글을 써 주세요. 밝지만 인상 사실은 솔직하게요.", + "연동 페이지 헤드라인이랑 서브카피 임팩트 있게 뽑아줘", + "봄 업데이트 소식 전하는 고객 뉴스레터 도입부 써줘", + "재무팀 대상 검색 광고 문구 세 가지 버전으로 써줘", + "프로덕트헌트 출시 소개 문구 260자로 써줘", + "채용 페이지 상단 카피 초안 써 주세요", + ], + }, + research: { + en: [ + "Find out what payroll tools mid-size Korean companies use most, with sources", + "research how other SaaS companies handle usage-based pricing for AI features", + "Dig up recent funding news and leadership changes at Corvid Analytics", + "what are the main regulations on storing health data in Korea? find sources", + "Gather public reviews of our competitor's onboarding and list the common complaints", + "look into who the key buyers are for logistics software in Southeast Asia", + ], + ko: [ + "국내 중견기업이 가장 많이 쓰는 급여 관리 도구가 뭔지 출처와 함께 찾아줘", + "다른 SaaS 회사들이 AI 기능 사용량 기반 요금을 어떻게 받는지 조사해 주세요", + "코르비드애널리틱스 최근 투자 소식이랑 경영진 변동 찾아줘", + "국내에서 건강 데이터 저장 관련 주요 규제가 뭔지 출처랑 같이 알아봐줘", + "경쟁사 온보딩에 대한 공개 리뷰를 모아서 자주 나오는 불만을 정리해 주세요", + "동남아 물류 소프트웨어 주요 구매자가 누군지 알아봐줘", + ], + }, + spec: { + en: [ + "Write the scope doc for audit logs: user stories, what's in v1, what's out, rollout plan", + "plan the migration to the new billing provider: phases, owners, risks, dates", + "Draft a technical design for moving file storage to S3, with alternatives considered", + "Write acceptance criteria for the bulk edit feature", + "put together a launch plan for the Korean market with milestones", + "one-pager proposing a self-serve trial, problem, solution, metrics", + ], + ko: [ + "감사 로그 기능 범위 문서 써줘. 사용자 스토리, v1 포함/제외, 출시 계획까지", + "새 결제 대행사로 이전하는 계획을 단계, 담당자, 리스크, 일정으로 짜 주세요", + "파일 저장소를 S3로 옮기는 기술 설계 문서 초안을 검토한 대안과 함께 써 주세요", + "일괄 수정 기능 인수 조건 작성해줘", + "한국 시장 출시 계획을 마일스톤과 함께 정리해줘", + "셀프 체험판 도입을 제안하는 한 장짜리 문서, 문제·해결책·지표로 써줘", + ], + }, + design: { + en: [ + "Sketch the empty state for the inbox when there are no messages yet", + "design the pricing table layout with three tiers and a toggle for annual billing", + "Create a social card image for the launch, 1200x630, with our logo and the headline", + "Mock up a mobile version of the invoice detail screen", + "redesign the signup form so it fits on one screen", + "make a few visual concepts for the conference booth backdrop", + ], + ko: [ + "메시지가 아직 없을 때 받은편지함 빈 화면 시안 그려줘", + "연간 결제 토글이 있는 3단계 요금표 레이아웃 디자인해줘", + "출시용 소셜 카드 이미지를 1200x630으로 로고와 헤드라인 넣어서 만들어 주세요", + "청구서 상세 화면 모바일 버전 목업 만들어줘", + "가입 폼이 한 화면에 들어가게 다시 디자인해줘", + "컨퍼런스 부스 배경 비주얼 콘셉트 몇 가지 잡아줘", + ], + }, + hr: { + en: [ + "Write a job posting for a part-time bookkeeper, remote, 20 hours a week", + "summarize the 360 feedback for my direct report into strengths and growth areas", + "Create a first-week onboarding checklist for new engineers", + "draft interview questions for a customer success role, with what a good answer looks like", + "Write the promotion case for Mina based on her last two quarters", + "outline a performance improvement plan for a sales rep missing quota", + ], + ko: [ + "주 20시간 원격 근무 파트타임 경리 채용공고 써줘", + "팀원 다면평가 내용을 강점이랑 성장 포인트로 정리해 주세요", + "신입 엔지니어 첫 주 온보딩 체크리스트 만들어줘", + "고객성공 직무 면접 질문이랑 좋은 답변 기준 같이 써줘", + "지난 두 분기 성과를 바탕으로 미나 승진 추천서 써 주세요", + "목표 미달인 영업 담당자 성과 개선 계획 초안 잡아줘", + ], + }, + email: { + en: [ + "Email the Acme buyer to say the renewal quote is attached and ask if they need anything for procurement", + "write a thank-you email after the onsite at Pinecrest, recap the next steps", + "Send a check-in email to a customer who went quiet after the trial", + "outreach email to a VP of finance we met at the conference", + "Write the email introducing our new account manager to the customer", + "follow up with the prospect who asked for the security questionnaire", + ], + ko: [ + "아크미 구매 담당자한테 갱신 견적서 첨부했다고, 구매 절차에 필요한 거 있는지 묻는 메일 써줘", + "파인크레스트 방문 미팅 후 감사 메일을 다음 단계 정리와 함께 써 주세요", + "체험판 이후 연락이 끊긴 고객에게 안부 메일 보내줘", + "컨퍼런스에서 만난 재무 담당 부사장한테 보낼 아웃리치 메일 써줘", + "새 어카운트 매니저를 고객에게 소개하는 메일 써 주세요", + "보안 설문지 요청했던 잠재고객한테 팔로업 메일 써줘", + ], + }, +}; diff --git a/packages/work-labeller/model/train/index.ts b/packages/work-labeller/model/train/index.ts new file mode 100644 index 0000000000..3c74d725cd --- /dev/null +++ b/packages/work-labeller/model/train/index.ts @@ -0,0 +1,146 @@ +/* + * The work classifier's training set: about 30 first messages per kind of work in each language, + * plus asking-to-learn and not-about-work examples, all hand-written for training. + * + * Kept apart from the evaluation set (eval/work-samples.ts): `train.test.ts` fails if any example + * here is, or contains, an evaluation message. The classifier learns from these and the prototypes + * only; the evaluation set is used for the final score and nothing else. + */ +import type { TrainingRows } from "./types.js"; +import { CONTRAST } from "./contrast.js"; +import { SHEET_CODE_DESIGN } from "./sheet-code-design.js"; +import { WRITE_A } from "./write-a.js"; +import { WRITE_B } from "./write-b.js"; + +export type TrainingExample = { action: string | null; learn: boolean; lang: "en" | "ko"; text: string }; + +const ROWS: TrainingRows = { ...WRITE_A, ...WRITE_B, ...SHEET_CODE_DESIGN }; + +/** Asking for an explanation, or a review of one's own work, rather than for the work itself. */ +const LEARN: { en: readonly string[]; ko: readonly string[] } = { + en: [ + "How does OAuth actually work? Explain it simply.", + "What's the difference between a left join and an inner join?", + "Can you explain what deferred revenue means?", + "I wrote this reply to a customer, is the tone right?", + "Why would someone use a message queue here?", + "Teach me how to read a cash flow statement", + "What does this error message mean?", + "Is my approach to this function reasonable, or am I overcomplicating it?", + "Explain what a p-value tells me in an A/B test", + "What makes a good job description?", + "Help me understand how our pricing tiers differ", + "How should I think about prioritizing features?", + "Give me feedback on my presentation outline", + "What is a race condition, with an example?", + "Explain the difference between gross and net revenue retention", + "Am I reading this contract clause correctly?", + "How do I get better at writing cold emails?", + "What's the point of an indemnity clause?", + "Can you walk me through how Kubernetes scheduling works?", + "Here is my draft blog post, what would make it stronger?", + "Explain how accrual accounting differs from cash accounting", + "What should I look for when reviewing a pull request?", + "What are the pros and cons of microservices?", + "Is this a good way to structure a spreadsheet model?", + "Explain like I'm new: what does a product manager do day to day?", + ], + ko: [ + "OAuth가 실제로 어떻게 동작하는지 쉽게 설명해줘", + "레프트 조인이랑 이너 조인 차이가 뭐야?", + "선수수익이 무슨 뜻인지 설명해 주실래요?", + "고객한테 이렇게 답장 썼는데 톤 괜찮아?", + "여기서 메시지 큐를 왜 쓰는 거야?", + "현금흐름표 보는 법 알려 주세요", + "이 에러 메시지가 무슨 뜻이야?", + "이 함수 접근 방식 괜찮아? 너무 복잡하게 하는 건가?", + "A/B 테스트에서 p값이 뭘 말해 주는지 설명해줘", + "좋은 채용 공고의 조건이 뭘까요?", + "우리 요금제 등급이 어떻게 다른지 이해하게 도와줘", + "기능 우선순위는 어떻게 생각해야 해?", + "발표 개요 피드백 좀 주세요", + "경쟁 조건이 뭔지 예시랑 같이 설명해줘", + "총 매출 유지율과 순 매출 유지율 차이 설명해 주세요", + "이 계약 조항 제가 제대로 이해한 건가요?", + "콜드메일 잘 쓰려면 어떻게 해야 해?", + "면책 조항은 왜 있는 거예요?", + "쿠버네티스 스케줄링이 어떻게 돌아가는지 차근차근 알려줘", + "블로그 초안인데 어떻게 하면 더 좋아질까요?", + "발생주의 회계랑 현금주의 회계 차이 설명해줘", + "PR 리뷰할 때 뭘 봐야 하나요?", + "마이크로서비스 장단점이 뭐야?", + "스프레드시트 모델 이렇게 짜는 게 맞아?", + "신입 눈높이로 PM이 하루에 뭐 하는지 설명해 주세요", + ], +}; + +/** Not about work: personal asks, small talk, and messages with nothing to classify. */ +const NONE: { en: readonly string[]; ko: readonly string[] } = { + en: [ + "what should I get my sister for her birthday", + "recommend a good movie for tonight", + "how long should I boil an egg", + "write a funny poem about my cat", + "plan a weekend trip to Jeju", + "what's a healthy breakfast", + "translate 'good morning' into French for my kid's homework", + "help me write a wedding toast for my friend", + "yes", + "no that's fine", + "thank you!", + "keep going", + "do it again", + "hmm", + "can you try once more", + "what time is it in London", + "suggest names for my new puppy", + "what's the weather like in Busan this weekend", + "tell me something interesting", + "write a bedtime story about a dragon", + "how do I get a stain out of a shirt", + "best way to learn guitar as an adult", + "make a grocery list for a week of dinners", + "who won the football match last night", + "never mind", + ], + ko: [ + "여동생 생일 선물 뭐가 좋을까", + "오늘 밤에 볼 영화 추천해줘", + "계란 몇 분 삶아야 해", + "우리 고양이에 대한 웃긴 시 써줘", + "제주도 주말 여행 계획 짜줘", + "건강한 아침 메뉴 뭐가 있어", + "아이 숙제로 '좋은 아침'을 프랑스어로 뭐라고 해", + "친구 결혼식 건배사 쓰는 거 도와줘", + "응", + "아니 괜찮아", + "감사합니다!", + "계속 해줘", + "다시 한번 해줘", + "음", + "한 번만 더 해볼래?", + "런던은 지금 몇 시야", + "새로 데려온 강아지 이름 추천해줘", + "이번 주말 부산 날씨 어때", + "재밌는 얘기 해줘", + "용이 나오는 잠자리 동화 써줘", + "셔츠 얼룩 지우는 법", + "어른이 기타 배우기 좋은 방법", + "일주일 저녁 장보기 목록 만들어줘", + "어젯밤 축구 경기 누가 이겼어", + "됐어 신경 쓰지 마", + ], +}; + +const LANGS: readonly ("en" | "ko")[] = ["en", "ko"]; + +export const TRAINING_EXAMPLES: TrainingExample[] = [ + ...Object.entries(ROWS).flatMap(([action, rows]) => + LANGS.flatMap((lang) => rows[lang].map((text) => ({ action, learn: false, lang, text }))), + ), + ...LANGS.flatMap((lang) => LEARN[lang].map((text) => ({ action: null, learn: true, lang, text }))), + ...LANGS.flatMap((lang) => NONE[lang].map((text) => ({ action: null, learn: false, lang, text }))), + ...Object.entries(CONTRAST).flatMap(([action, rows]) => + LANGS.flatMap((lang) => rows[lang].map((text) => ({ action, learn: false, lang, text }))), + ), +]; diff --git a/packages/work-labeller/model/train/sheet-code-design.ts b/packages/work-labeller/model/train/sheet-code-design.ts new file mode 100644 index 0000000000..77620afbc4 --- /dev/null +++ b/packages/work-labeller/model/train/sheet-code-design.ts @@ -0,0 +1,470 @@ +/* + * Training examples for the work classifier: data analysis, finance, building, fixing, reviewing + * and testing code, and design. Written for training only; see train/index.ts. + */ +import type { TrainingRows } from "./types.js"; + +export const SHEET_CODE_DESIGN: TrainingRows = { + analyze: { + en: [ + "Which regions grew fastest last quarter? Data attached.", + "Analyze this CSV of signups and tell me where users drop off", + "Build a cohort retention table from the attached export", + "What's driving the increase in support tickets? Here's the data.", + "Look at the sales numbers and find our best performing product line", + "Calculate win rates by sales rep from this spreadsheet", + "Find outliers in this expense data", + "Compare conversion rates between the two landing page variants", + "Analyze the NPS responses by customer segment", + "Create a chart of monthly active users from this sheet", + "Is there a correlation between seat count and churn in this data?", + "Segment our customers by usage and revenue", + "Analyze average deal size over time from the CRM export", + "Which features are used most? Event data attached.", + "Build a pivot of revenue by plan and month", + "analyze this survey data and give me the main findings", + "Check the funnel numbers, where's the biggest drop?", + "Forecast next quarter's signups from the last two years of data", + "Calculate customer acquisition cost by channel", + "Analyze the A/B test results and tell me if it's significant", + "What's our median response time per support agent? Sheet attached.", + "Look at inventory levels and flag items running low", + "Analyze the website traffic sources for the last 90 days", + "Find which customers are at risk based on declining usage", + "Build a summary table of headcount by department over time", + "Analyze time-to-close for deals by industry", + "Calculate the lifetime value by plan tier", + "Find the busiest hours for support tickets", + "Analyze the price sensitivity from these quote results", + "Clean up this dataset and compute the weekly averages", + ], + ko: [ + "지난 분기에 어느 지역이 가장 빨리 성장했어? 데이터 첨부했어", + "가입자 CSV 분석해서 어디서 이탈하는지 알려줘", + "첨부 데이터로 코호트 리텐션 표 만들어 주세요", + "고객 문의가 늘어난 원인이 뭔지 데이터 보고 분석해줘", + "매출 수치 보고 제일 잘 나가는 제품군 찾아 주세요", + "이 스프레드시트로 영업 담당자별 수주율 계산해줘", + "경비 데이터에서 이상치 찾아줘", + "랜딩 페이지 두 가지 버전의 전환율 비교해 주세요", + "고객 세그먼트별 NPS 응답 분석", + "이 시트로 월간 활성 사용자 차트 만들어줘", + "좌석 수랑 이탈 사이에 상관관계 있는지 봐 주세요", + "사용량이랑 매출로 고객 세그먼트 나눠줘", + "CRM 내보내기로 평균 계약 규모 추이 분석해 주세요", + "어떤 기능이 제일 많이 쓰이는지 이벤트 데이터 보고 알려줘", + "요금제별 월별 매출 피벗 만들어줘", + "이 설문 데이터 분석해서 주요 결과 알려 주세요", + "퍼널 수치 봐줘. 제일 많이 빠지는 데가 어디야", + "지난 2년 데이터로 다음 분기 가입자 수 예측해 주세요", + "채널별 고객 획득 비용 계산해줘", + "A/B 테스트 결과 분석해서 유의미한지 알려 주세요", + "상담원별 응답 시간 중앙값 계산해줘. 시트 첨부", + "재고 수준 보고 부족한 품목 표시해 주세요", + "최근 90일 웹사이트 유입 경로 분석해줘", + "사용량이 줄어드는 위험 고객 찾아 주세요", + "부서별 인원 추이 요약 표 만들어줘", + "업종별 계약 성사까지 걸리는 기간 분석해 주세요", + "요금제 등급별 고객 생애 가치 계산", + "고객 문의가 제일 몰리는 시간대 찾아줘", + "견적 결과로 가격 민감도 분석해 주세요", + "이 데이터셋 정리하고 주간 평균 계산해줘", + ], + }, + finance: { + en: [ + "Reconcile the Stripe payouts with our bank deposits for October", + "Match these vendor invoices to the purchase orders and flag mismatches", + "Close the books for September: list unreconciled items", + "Check whether the credit card statement matches the expense reports", + "Find duplicate payments in the accounts payable ledger", + "Reconcile intercompany balances between the US and Korea entities", + "Verify the VAT amounts on these invoices", + "Tie out the payroll journal to the bank transfers", + "Check this invoice from the agency against our contract rates", + "Prepare the month-end accrual entries from this list", + "Reconcile the deferred revenue schedule with billing", + "Match the customer payments to open invoices", + "Find which expenses are missing receipts", + "Reconcile the petty cash log", + "Check the vendor statement against our AP balance", + "reconcile accounts receivable aging with the GL", + "Validate the totals on this batch of supplier invoices", + "Compare the budget to actuals for marketing and explain the variance", + "Reconcile the fixed asset register with depreciation", + "Check whether we've been double-billed by the cloud provider", + "Match corporate card transactions to employees", + "Prepare the bank reconciliation for the operating account", + "Check the sales tax collected against what we filed", + "Reconcile refunds issued against the payment processor report", + "Verify the exchange rates used on the foreign currency invoices", + "Find unapplied cash in the receivables", + "Reconcile the subscription revenue in the CRM with the accounting system", + "Check that every PO over $10k has an approval", + "Review this month's journal entries for errors", + "Reconcile the expense report totals with the reimbursement payments", + ], + ko: [ + "10월 스트라이프 정산금이랑 은행 입금 내역 대사해줘", + "공급업체 송장을 발주서와 맞춰 보고 안 맞는 거 표시해 주세요", + "9월 결산해야 해. 대사 안 된 항목 정리해줘", + "법인카드 명세서가 경비 보고서랑 맞는지 확인해 주세요", + "매입채무 원장에서 중복 지급 찾아줘", + "미국 법인과 한국 법인 간 내부 거래 잔액 대사", + "이 세금계산서들 부가세 금액 검증해 주세요", + "급여 분개를 은행 이체 내역과 맞춰줘", + "대행사 청구서를 계약 단가와 대조해 주세요", + "이 목록으로 월말 미지급 비용 분개 만들어줘", + "선수수익 스케줄을 청구 내역과 대사해 주세요", + "고객 입금을 미수 송장에 매칭해줘", + "영수증이 빠진 경비 찾아 주세요", + "소액 현금 장부 대사해줘", + "거래처 잔액 확인서를 우리 매입채무 잔액과 대조", + "매출채권 연령 분석을 총계정원장과 대사해줘", + "공급업체 송장 묶음 합계 검증해 주세요", + "마케팅 예산 대비 실적 비교하고 차이 설명해줘", + "고정자산 대장을 감가상각 내역과 대사해 주세요", + "클라우드 업체가 이중 청구했는지 확인해줘", + "법인카드 거래를 직원별로 매칭해 주세요", + "운영 계좌 은행 잔액 조정표 만들어줘", + "징수한 부가세가 신고한 금액과 맞는지 확인해 주세요", + "환불 처리 내역을 결제대행사 리포트와 대사해줘", + "외화 송장에 적용된 환율 검증해 주세요", + "매출채권에서 미적용 입금 찾아줘", + "CRM 구독 매출을 회계 시스템과 대사해 주세요", + "천만 원 넘는 발주서마다 승인 있는지 확인해줘", + "이번 달 분개 오류 있는지 검토해 주세요", + "경비 보고서 합계를 지급한 금액과 대사해줘", + ], + }, + code: { + en: [ + "Add pagination to the /v1/orders endpoint", + "Implement CSV export for the reports page", + "Build a settings screen where users can change their notification preferences", + "Create a React hook that debounces search input", + "Add a webhook that fires when a subscription is cancelled", + "Write a migration that adds an archived flag to projects", + "Implement dark mode support in the web app", + "Add rate limiting middleware to the API", + "Create a CLI command that seeds the local database", + "Build an endpoint that returns usage per day for a workspace", + "Integrate Stripe checkout into the upgrade flow", + "Add a background job that sends weekly digest emails", + "Implement role-based access control for the admin pages", + "Refactor the auth module so the token logic lives in one place", + "Add file upload with drag and drop to the composer", + "Create a Terraform module for the staging environment", + "Build a Slack bot that posts deploy notifications", + "add a search bar to the members table that filters by email", + "Implement soft delete for comments", + "Write a script that backfills the new column for existing rows", + "Add OpenTelemetry tracing to the payment service", + "Build the onboarding wizard component with three steps", + "Add caching to the product catalogue endpoint", + "Implement the forgot password flow end to end", + "Port this Python script to TypeScript", + "Add support for Korean in the date formatting helper", + "Create a GitHub Action that runs the linter on pull requests", + "Implement infinite scroll on the activity feed", + "Build an export to Google Sheets integration", + "Add an API for creating teams, with validation", + ], + ko: [ + "/v1/orders 엔드포인트에 페이지네이션 추가해줘", + "리포트 페이지에 CSV 내보내기 구현해 주세요", + "사용자가 알림 설정을 바꿀 수 있는 설정 화면 만들어줘", + "검색 입력에 디바운스 거는 React 훅 만들어 주세요", + "구독이 해지되면 호출되는 웹훅 추가해줘", + "프로젝트에 보관 여부 플래그 추가하는 마이그레이션 작성", + "웹앱에 다크 모드 지원 구현해 주세요", + "API에 요청 제한 미들웨어 추가해줘", + "로컬 DB에 시드 데이터 넣는 CLI 명령어 만들어 주세요", + "워크스페이스별 일일 사용량을 돌려주는 엔드포인트 개발해줘", + "업그레이드 흐름에 스트라이프 결제 연동해 주세요", + "주간 요약 메일 보내는 백그라운드 작업 추가해줘", + "관리자 페이지에 역할 기반 권한 제어 구현", + "토큰 로직이 한 군데 있도록 인증 모듈 리팩터링해 주세요", + "작성창에 드래그 앤 드롭 파일 업로드 추가해줘", + "스테이징 환경용 테라폼 모듈 만들어 주세요", + "배포 알림 올리는 슬랙 봇 만들어줘", + "멤버 표에 이메일로 거르는 검색창 추가해줘", + "댓글 소프트 삭제 구현해 주세요", + "기존 행에 새 컬럼 값 채우는 백필 스크립트 작성해줘", + "결제 서비스에 OpenTelemetry 트레이싱 추가", + "3단계짜리 온보딩 마법사 컴포넌트 만들어 주세요", + "상품 목록 엔드포인트에 캐시 넣어줘", + "비밀번호 찾기 기능 처음부터 끝까지 구현해 주세요", + "이 파이썬 스크립트 타입스크립트로 옮겨줘", + "날짜 포맷 헬퍼에 한국어 지원 추가해 주세요", + "PR마다 린터 돌리는 깃허브 액션 만들어줘", + "활동 피드에 무한 스크롤 구현해 주세요", + "구글 시트로 내보내는 연동 기능 개발", + "팀 생성 API 추가해줘. 입력 검증 포함해서", + ], + }, + fix: { + en: [ + "The login page throws a 500 when the email has a plus sign, fix it", + "Users report the export button does nothing in Firefox. Find and fix the bug.", + "Fix the memory leak in the websocket handler", + "Why does the build fail on CI but pass locally? Fix it.", + "The date picker shows the wrong month in January, fix it", + "Fix the race condition when two people edit the same document", + "The cron job runs twice every night, figure out why and fix it", + "Prod is down, the API returns 502 for every request. Help me find the cause.", + "Fix the N+1 query that's slowing down the dashboard", + "The dark mode toggle resets after refresh, fix it", + "This TypeError keeps showing up in Sentry, here's the stack trace", + "Fix the broken image uploads on iOS Safari", + "The total on the invoice is off by one cent, find the rounding bug", + "Search returns no results for Korean queries, fix it", + "fix the flaky timeout in the checkout service", + "Our deploy is stuck rolling back, help me debug", + "The app crashes when the user has no profile picture", + "Fix the CORS error the frontend gets when calling the API", + "Emails aren't being sent since this morning's release, find out why", + "The pagination skips a record between pages, fix it", + "Fix the off-by-one error in the retry logic", + "Database CPU is at 100% since the last migration, help me find the cause", + "The modal can't be closed with the Escape key, fix it", + "Webhooks are being delivered out of order, debug it", + "Fix the segfault in the image processing worker", + "Login works on staging but not production, figure out what's different", + "The chart renders blank when there's only one data point", + "Fix the hydration mismatch warning on the pricing page", + "Users in New York see yesterday's date in the report, fix the timezone bug", + "Our health check keeps failing after deploy, investigate", + ], + ko: [ + "이메일에 + 들어가면 로그인 페이지가 500 에러나. 고쳐줘", + "파이어폭스에서 내보내기 버튼이 안 먹는대요. 버그 찾아서 고쳐 주세요", + "웹소켓 핸들러 메모리 누수 수정해줘", + "CI에서는 빌드 실패하고 로컬에서는 되는데 왜 그래? 고쳐줘", + "1월에 날짜 선택기가 엉뚱한 달을 보여 줘요. 수정해 주세요", + "두 사람이 같은 문서 편집할 때 경쟁 조건 문제 고쳐줘", + "크론 작업이 매일 밤 두 번씩 돌아. 원인 찾아서 고쳐줘", + "운영 서버 다운됐어. API가 전부 502 반환해. 원인 찾는 거 도와줘", + "대시보드 느리게 만드는 N+1 쿼리 고쳐 주세요", + "새로고침하면 다크 모드 설정이 풀려. 수정해줘", + "센트리에 이 TypeError가 계속 떠. 스택 트레이스 첨부할게", + "iOS 사파리에서 이미지 업로드 깨지는 거 고쳐 주세요", + "청구서 합계가 1원씩 틀려. 반올림 버그 찾아줘", + "한국어로 검색하면 결과가 안 나와. 고쳐줘", + "결제 서비스 간헐적 타임아웃 고쳐줘", + "배포 롤백이 멈춰 있어. 디버깅 도와줘", + "프로필 사진 없는 사용자면 앱이 죽어요", + "프론트에서 API 호출할 때 나는 CORS 에러 수정해 주세요", + "오늘 아침 배포 이후로 메일이 안 나가. 원인 알아봐줘", + "페이지 넘길 때 레코드 하나가 빠져. 페이지네이션 고쳐줘", + "재시도 로직의 off-by-one 오류 수정해 주세요", + "지난 마이그레이션 이후로 DB CPU가 100%야. 원인 찾아줘", + "ESC 키로 모달이 안 닫혀요. 고쳐 주세요", + "웹훅이 순서가 뒤바뀌어서 전달돼. 디버깅해줘", + "이미지 처리 워커 세그폴트 수정", + "스테이징에서는 로그인 되는데 운영에서는 안 돼. 뭐가 다른지 찾아줘", + "데이터가 하나뿐이면 차트가 빈 화면으로 나와요", + "가격 페이지 하이드레이션 불일치 경고 고쳐줘", + "뉴욕 사용자한테 리포트 날짜가 어제로 보여. 시간대 버그 수정해 주세요", + "배포 후에 헬스 체크가 계속 실패해. 확인해줘", + ], + }, + review: { + en: [ + "Review my PR and tell me what to change before I ask for approval", + "Look at this diff and check for security issues", + "Code review this function for readability", + "Is this migration safe? Review it.", + "Review the error handling in this service", + "Go through this pull request and leave comments like a senior reviewer would", + "Check this change for performance problems", + "Review the new API design in this PR", + "Is there anything wrong with this SQL query?", + "review the tests in this PR, are they meaningful?", + "Review this Dockerfile for best practices", + "Look over the changes to the auth middleware", + "Can you review the React component I just wrote?", + "Check this PR for breaking changes to the public API", + "Review the concurrency handling in this code", + "Review the Terraform plan before I apply it", + "Check whether this change handles null inputs", + "Review my implementation of the caching layer", + "Is the naming in this module consistent? Review it.", + "Review the accessibility of this new form component", + "Look at the diff for the payment refactor and spot regressions", + "Review this regex, will it catch all the cases?", + "Review the dependency upgrades in this PR", + "Review this GraphQL schema change", + "Look over the logging changes and tell me if we leak PII", + "Review the config changes for the production rollout", + "review this shell script before I run it on the server", + "Check this PR follows our style guide", + "Review the database indexes added in this change", + "Review my teammate's PR on the billing module", + ], + ko: [ + "승인 요청하기 전에 내 PR 리뷰하고 고칠 점 알려줘", + "이 diff 보안 문제 있는지 검토해 주세요", + "이 함수 가독성 관점으로 코드 리뷰해줘", + "이 마이그레이션 안전해? 리뷰해 줘", + "이 서비스의 에러 처리 리뷰해 주세요", + "시니어 리뷰어처럼 이 PR 보고 코멘트 남겨줘", + "이 변경에 성능 문제 있는지 봐 주세요", + "이 PR의 새 API 설계 리뷰", + "이 SQL 쿼리 잘못된 거 있어?", + "이 PR 테스트 의미 있는지 리뷰해줘", + "이 Dockerfile 모범 사례 기준으로 리뷰해 주세요", + "인증 미들웨어 변경사항 검토해줘", + "방금 짠 React 컴포넌트 리뷰해 줄래?", + "이 PR에 공개 API 호환성 깨지는 변경 있는지 봐 주세요", + "이 코드 동시성 처리 리뷰해줘", + "적용하기 전에 테라폼 플랜 리뷰해 주세요", + "이 변경이 null 입력 처리하는지 확인해줘", + "캐시 레이어 구현한 거 리뷰해 주세요", + "이 모듈 네이밍 일관성 있는지 리뷰", + "새 폼 컴포넌트 접근성 리뷰해줘", + "결제 리팩터링 diff 보고 회귀 문제 찾아 주세요", + "이 정규식 모든 경우 다 잡는지 검토해줘", + "이 PR 의존성 업그레이드 리뷰해 주세요", + "GraphQL 스키마 변경 리뷰해줘", + "로깅 변경사항 보고 개인정보 새는 거 없는지 봐 주세요", + "운영 배포용 설정 변경 리뷰", + "서버에서 돌리기 전에 이 셸 스크립트 검토해줘", + "이 PR 우리 스타일 가이드 지키는지 확인해 주세요", + "이 변경에서 추가한 DB 인덱스 리뷰해줘", + "동료가 올린 결제 모듈 PR 리뷰해 주세요", + ], + }, + test: { + en: [ + "Write unit tests for the invoice calculator", + "Add tests for the edge cases in the date parser", + "Write an integration test for the signup API", + "Create Playwright tests for the login flow", + "Our coverage on the billing module is 30%, add tests", + "Write a test that reproduces the bug before we fix it", + "Add snapshot tests for the email templates", + "Write property-based tests for the sorting function", + "Write tests that cover the permission checks for each role", + "Set up a load test for the search endpoint", + "Write Jest tests for this React component", + "Add regression tests for the timezone handling", + "Write a contract test between the web app and the API", + "Create test fixtures for the order processing tests", + "write tests for the retry logic using a fake clock", + "Add end-to-end tests for the checkout with a test card", + "Write pytest tests for the data pipeline transforms", + "Mock the payment provider and test the failure paths", + "Write tests for the CSV importer with malformed files", + "Add a test that fails if the migration drops a column", + "Write tests for the webhook signature verification", + "Create a test plan for the release", + "Write tests for the rate limiter, including the boundary", + "Add Cypress tests for the admin dashboard", + "Write unit tests for the currency formatting helper with Korean won", + "Write tests that check the API returns 403 for other workspaces", + "Add tests for concurrency in the inventory reservation", + "Write tests for the search ranking with sample documents", + "Add a smoke test that runs after every deploy", + "Write tests for the password strength validator", + ], + ko: [ + "청구 금액 계산기 단위 테스트 작성해줘", + "날짜 파서 예외 케이스 테스트 추가해 주세요", + "가입 API 통합 테스트 작성", + "로그인 흐름 Playwright 테스트 만들어줘", + "결제 모듈 커버리지가 30%야. 테스트 추가해 주세요", + "고치기 전에 버그 재현하는 테스트부터 써줘", + "메일 템플릿 스냅샷 테스트 추가", + "정렬 함수 속성 기반 테스트 작성해 주세요", + "역할별 권한 검사를 다 커버하는 테스트 써줘", + "검색 엔드포인트 부하 테스트 세팅해 주세요", + "이 React 컴포넌트 Jest 테스트 작성해줘", + "시간대 처리 회귀 테스트 추가해 주세요", + "웹앱과 API 사이 계약 테스트 작성", + "주문 처리 테스트용 픽스처 만들어줘", + "가짜 시계로 재시도 로직 테스트 써줘", + "테스트 카드로 결제 E2E 테스트 추가해 주세요", + "데이터 파이프라인 변환 pytest 테스트 작성", + "결제 대행사 목 만들어서 실패 경로 테스트해줘", + "잘못된 형식 파일로 CSV 가져오기 테스트 작성해 주세요", + "마이그레이션이 컬럼을 지우면 실패하는 테스트 추가", + "웹훅 서명 검증 테스트 써줘", + "이번 릴리스 테스트 계획 만들어 주세요", + "경계값 포함해서 요청 제한기 테스트 작성해줘", + "관리자 대시보드 Cypress 테스트 추가해 주세요", + "원화 통화 포맷 헬퍼 단위 테스트 써줘", + "다른 워크스페이스 접근 시 API가 403 주는지 테스트 작성해 주세요", + "재고 예약 동시성 테스트 추가해줘", + "샘플 문서로 검색 랭킹 테스트 작성", + "배포할 때마다 도는 스모크 테스트 추가해 주세요", + "비밀번호 강도 검사기 테스트 써줘", + ], + }, + design: { + en: [ + "Design a dashboard layout for the analytics page", + "Mock up a mobile onboarding flow, three screens", + "Create an illustration for the empty inbox state", + "Design an icon set for the file types we support", + "Make a poster for the hackathon", + "Design the settings page in our design system", + "Create a wireframe for the new checkout", + "Design a banner for the conference booth", + "Redesign the pricing table to make the recommended plan stand out", + "Make a social media graphic for the product launch", + "Design a logo concept for the internal tool", + "Create a style guide page for our brand colors and fonts", + "Design the email template header", + "Mock up a data table with filters and bulk actions", + "design a slide template for the sales deck", + "Create three visual directions for the rebrand", + "Design the error page with a friendly illustration", + "Make an infographic from these survey results", + "Design an app icon in a few variations", + "Design a modal for confirming account deletion", + "Create a hero image for the blog post", + "Design a dark mode version of the sidebar", + "Design a dashboard widget showing usage trends", + "Mock up the Korean version of the landing page", + "Design an onboarding checklist component", + "Create a thumbnail for the YouTube tutorial", + "Design packaging for the swag kit", + "Make a flowchart diagram of the signup process for the docs", + "Design the notification center dropdown", + "Create a visual for the annual report cover", + ], + ko: [ + "분석 페이지 대시보드 레이아웃 디자인해줘", + "모바일 온보딩 화면 세 개 시안 만들어 주세요", + "받은편지함 빈 화면 일러스트 그려줘", + "지원하는 파일 형식별 아이콘 세트 디자인", + "해커톤 포스터 만들어 주세요", + "디자인 시스템에 맞춰 설정 페이지 디자인해줘", + "새 결제 화면 와이어프레임 그려 주세요", + "컨퍼런스 부스 배너 디자인", + "추천 요금제가 눈에 띄게 가격표 다시 디자인해줘", + "제품 출시용 SNS 그래픽 만들어 주세요", + "사내 도구 로고 시안 디자인해줘", + "브랜드 색상과 폰트 스타일 가이드 페이지 만들어 주세요", + "메일 템플릿 헤더 디자인", + "필터랑 일괄 작업 있는 데이터 표 시안 만들어줘", + "영업 자료 슬라이드 템플릿 디자인해 주세요", + "리브랜딩 비주얼 방향 세 가지 만들어줘", + "친근한 일러스트 들어간 에러 페이지 디자인", + "설문 결과로 인포그래픽 만들어 주세요", + "앱 아이콘 몇 가지 버전으로 디자인해줘", + "계정 삭제 확인 모달 디자인해 주세요", + "블로그 글 대표 이미지 만들어줘", + "사이드바 다크 모드 버전 디자인", + "사용량 추이 보여 주는 대시보드 위젯 디자인해 주세요", + "랜딩 페이지 한국어 버전 시안 만들어줘", + "온보딩 체크리스트 컴포넌트 디자인", + "유튜브 튜토리얼 썸네일 만들어 주세요", + "굿즈 키트 패키지 디자인해줘", + "문서에 넣을 가입 절차 흐름도 그려 주세요", + "알림 센터 드롭다운 디자인해줘", + "연간 보고서 표지 비주얼 만들어 주세요", + ], + }, +}; diff --git a/packages/work-labeller/model/train/train.test.ts b/packages/work-labeller/model/train/train.test.ts new file mode 100644 index 0000000000..0a6ae24467 --- /dev/null +++ b/packages/work-labeller/model/train/train.test.ts @@ -0,0 +1,50 @@ +import { describe, expect, test } from "bun:test"; + +import { WORK_SAMPLES } from "../eval/work-samples.js"; +import { WORK_ACTIONS } from "../../src/index.js"; +import { TRAINING_EXAMPLES } from "./index.js"; +import { TUNING_EXAMPLES } from "./tuning.js"; + +const normal = (text: string) => text.toLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim(); + +describe("work classifier training set", () => { + test("shares nothing with the evaluation set, and the tuning slice shares nothing with either", () => { + const evaluation = WORK_SAMPLES.map((s) => normal(s.text)); + const training = TRAINING_EXAMPLES.map((e) => normal(e.text)); + const leaks = [...TRAINING_EXAMPLES, ...TUNING_EXAMPLES].filter((example) => { + const t = normal(example.text); + // Containment only for phrases long enough to be a message of their own: "translate this" is in the + // evaluation set, and a longer request that starts with those words is not a copy of it. + return evaluation.some((e) => e === t || (t.length >= 20 && e.includes(t)) || (e.length >= 20 && t.includes(e))); + }); + expect(leaks.map((l) => l.text)).toEqual([]); + expect(TUNING_EXAMPLES.filter((e) => training.includes(normal(e.text))).map((e) => e.text)).toEqual([]); + }); + + test("no example appears twice", () => { + const texts = TRAINING_EXAMPLES.map((e) => normal(e.text)); + expect(texts.filter((t, i) => texts.indexOf(t) !== i)).toEqual([]); + }); + + test("covers every kind of work, at least 30 in each language", () => { + for (const action of WORK_ACTIONS) { + for (const lang of ["en", "ko"]) { + expect(TRAINING_EXAMPLES.filter((e) => e.action === action && e.lang === lang).length).toBeGreaterThanOrEqual(30); + } + } + }); + + test("Korean examples are Korean, English ones are not", () => { + for (const e of [...TRAINING_EXAMPLES, ...TUNING_EXAMPLES]) { + if (e.lang === "ko") expect(`${/[가-힣]/.test(e.text)} ${e.text}`).toBe(`true ${e.text}`); + else expect(`${/[가-힣]/.test(e.text)} ${e.text}`).toBe(`false ${e.text}`); + } + }); + + test("has learning and not-work examples in both languages", () => { + for (const lang of ["en", "ko"]) { + expect(TRAINING_EXAMPLES.filter((e) => e.learn && e.lang === lang).length).toBe(25); + expect(TRAINING_EXAMPLES.filter((e) => e.action === null && !e.learn && e.lang === lang).length).toBe(25); + } + }); +}); diff --git a/packages/work-labeller/model/train/tuning.ts b/packages/work-labeller/model/train/tuning.ts new file mode 100644 index 0000000000..5e7e7bc7d5 --- /dev/null +++ b/packages/work-labeller/model/train/tuning.ts @@ -0,0 +1,269 @@ +/* + * The tuning slice: first messages written the way the evaluation set is (a detailed, briefed request + * and a terse one for each task, in both registers), but kept apart from both it and the training set. + * + * The classifier never trains on these. They choose what the training set cannot: the confidence + * floor, which is only meaningful on messages that look like real use, and which pairs of kinds of + * work are still confused. The evaluation set stays untouched until the final score. + */ +import type { TrainingExample } from "./index.js"; + +type Rows = { en: readonly string[]; ko: readonly string[] }; + +const BY_ACTION: Record = { + reply: { + en: [ + "Ticket below: customer was billed after cancelling. Write a reply that confirms the refund of $49, says it lands in 3-5 days, and apologises once. Under 100 words.", + "help me reply to this customer, they can't find the export button", + "An admin says the new permissions update locked half their team out. Draft my response as support lead: acknowledge, explain the rollback we did at 2pm, and offer a call. No more than three paragraphs.", + "write back to the user who reported the calendar sync bug", + ], + ko: [ + "해지했는데 결제가 됐다는 고객 티켓이에요. 49달러 환불을 확인하고 3~5일 안에 들어간다고 안내하는 답장을 써 주세요. 사과는 한 번만, 200자 이내로요.", + "내보내기 버튼을 못 찾겠다는 고객 문의에 답변 좀 써줘", + "권한 업데이트 이후 팀원 절반이 접속을 못 한다고 관리자가 항의했어요. 고객지원 리드로서 상황을 인정하고, 오후 2시에 롤백한 내용을 설명하고, 통화를 제안하는 답장을 세 문단 이내로 써 주세요.", + "캘린더 동기화 버그 신고한 사용자한테 답장해줘", + ], + }, + summ: { + en: [ + "Here's a 40-message support thread with Lumen Foods. Summarise it for the account manager: the problem, what we tried, what's still open, and who owes the next step. Five bullets max.", + "summarize my notes from the call with the Harbor team", + "Turn this week's activity on our top 10 accounts into a digest for the sales channel: one line per account, flag anything at risk in bold.", + "tl;dr this ticket history please", + ], + ko: [ + "루멘푸드와 주고받은 40개짜리 지원 스레드예요. 담당 영업에게 전달할 수 있게 문제, 시도한 조치, 남은 이슈, 다음 담당자를 다섯 줄 이내로 요약해 주세요.", + "하버팀이랑 한 통화 메모 정리해줘", + "이번 주 상위 10개 고객사 동향을 영업 채널에 올릴 다이제스트로 만들어 주세요. 고객사별 한 줄씩, 위험 신호는 굵게 표시해 주세요.", + "이 티켓 히스토리 요약 좀", + ], + }, + email: { + en: [ + "Write a renewal email to Northwind's CFO. Their contract ends March 31; mention the 8% price increase, the usage growth that justifies it, and offer a 15-minute call. Keep it under 150 words.", + "draft a follow-up email after yesterday's demo with Kestrel", + "Write a first cold email to the head of operations at a mid-size logistics company. One sentence on the pain, one on what we do, one ask. No buzzwords.", + "email the prospect from the webinar and ask for a meeting", + ], + ko: [ + "노스윈드 CFO에게 보낼 갱신 메일을 써 주세요. 계약이 3월 31일에 끝나고, 8% 인상과 그 근거가 되는 사용량 증가를 언급하고, 15분 통화를 제안해 주세요. 300자 이내로요.", + "어제 케스트럴 데모 끝나고 보낼 팔로업 메일 써줘", + "중견 물류회사 운영 총괄에게 보낼 첫 콜드메일을 써 주세요. 문제 한 문장, 우리가 하는 일 한 문장, 요청 한 문장. 유행어는 빼고요.", + "웨비나 참석한 잠재고객한테 미팅 요청 메일 보내줘", + ], + }, + research: { + en: [ + "Before Thursday's meeting with Brightline Health, put together an account brief: what they do, recent news, who the decision makers are, and two angles for our pitch. One page.", + "look up what our three main competitors charge for their team plans", + "Scan how Asana, Monday and ClickUp position AI features on their pricing pages and summarise the differences in a table.", + "find out who runs procurement at Delmar Group", + ], + ko: [ + "목요일 브라이트라인헬스 미팅 전에 어카운트 브리프를 만들어 주세요. 사업 내용, 최근 뉴스, 의사결정권자, 제안 포인트 두 가지를 한 페이지로요.", + "주요 경쟁사 세 곳 팀 요금제 가격 좀 찾아줘", + "아사나, 먼데이, 클릭업이 요금제 페이지에서 AI 기능을 어떻게 내세우는지 조사해서 차이를 표로 정리해 주세요.", + "델마그룹 구매 담당자가 누군지 알아봐줘", + ], + }, + analyze: { + en: [ + "Attached is the Q3 pipeline export. Tell me which deals over $50k have slipped more than once, and what share of the quarter's forecast they make up. Show the numbers.", + "why did churn jump in August? data's in the sheet", + "Check this forecast against the last four quarters' actual close rates and tell me if the commit number is realistic, with the math.", + "break down signups by channel for the last 6 months", + ], + ko: [ + "첨부한 3분기 파이프라인 데이터에서 5만 달러 이상 딜 중 두 번 이상 밀린 건이 뭔지, 그게 분기 예측의 몇 퍼센트인지 숫자와 함께 알려 주세요.", + "8월에 이탈률이 왜 뛰었는지 봐줘, 데이터는 시트에 있어", + "이 예측치를 지난 4분기 실제 성사율과 비교해서 커밋 숫자가 현실적인지 계산 과정과 함께 판단해 주세요.", + "최근 6개월 가입자를 채널별로 나눠서 분석해줘", + ], + }, + code: { + en: [ + "Add a GET /api/projects/:id/members endpoint that returns members with their role, paginated 50 at a time. Follow the pattern in routes/teams.ts and include the OpenAPI annotation.", + "build a date range picker component for the reports page", + "Write the migration that moves user preferences from the JSON column into their own table, with a backfill and a down migration.", + "implement CSV import for contacts", + ], + ko: [ + "프로젝트 멤버를 역할과 함께 50명씩 페이지로 돌려주는 GET /api/projects/:id/members 엔드포인트를 추가해 주세요. routes/teams.ts 패턴을 따르고 OpenAPI 주석도 넣어 주세요.", + "리포트 페이지에 쓸 날짜 범위 선택 컴포넌트 만들어줘", + "사용자 설정을 JSON 컬럼에서 별도 테이블로 옮기는 마이그레이션을 백필과 롤백까지 포함해서 작성해 주세요.", + "연락처 CSV 가져오기 기능 구현해줘", + ], + }, + fix: { + en: [ + "The checkout test in cart.spec.ts started failing after the currency change. Find the cause and fix the code, not the test, unless the test is wrong. Explain which it was.", + "prod is throwing 500s on /login since the deploy, fix it", + "Users in Seoul see yesterday's date on the dashboard. Track down the timezone bug and patch it.", + "this function returns undefined sometimes, figure out why", + ], + ko: [ + "통화 변경 이후 cart.spec.ts의 결제 테스트가 깨졌어요. 원인을 찾아서 코드를 고쳐 주세요. 테스트가 잘못된 거면 그렇다고 말해 주시고요.", + "배포 이후 운영에서 /login이 500 에러 나, 고쳐줘", + "서울 사용자 대시보드에 어제 날짜가 보여요. 시간대 버그 찾아서 수정해 주세요.", + "이 함수가 가끔 undefined를 반환하는데 왜 그런지 찾아줘", + ], + }, + review: { + en: [ + "Review PR #212 before I merge it. Focus on the locking in the job queue and anything that could double-charge a customer. Comment inline, and say whether it's safe to ship.", + "take a look at my teammate's pull request and leave comments", + "Go through this diff for security problems: SQL built from strings, missing auth checks, secrets in logs. List each with the line.", + "can you review the changes in this branch", + ], + ko: [ + "머지 전에 PR #212를 리뷰해 주세요. 작업 큐의 락 처리와 고객 이중 결제 가능성을 중심으로 인라인 코멘트를 남기고 배포해도 되는지 판단해 주세요.", + "동료 풀리퀘스트 보고 코멘트 남겨줘", + "이 diff에서 문자열로 만든 SQL, 빠진 권한 체크, 로그에 남는 비밀값 같은 보안 문제를 줄 번호와 함께 찾아 주세요.", + "이 브랜치 변경사항 리뷰해줘", + ], + }, + test: { + en: [ + "Write unit tests for the discount calculator in pricing/discount.ts: cover stacking, the 100% cap, expired codes and rounding to cents. Use the existing vitest setup.", + "add tests for the signup form", + "Write an end-to-end test that signs up, creates a project, invites a teammate and checks the invite email arrives, using Playwright.", + "we have zero test coverage on utils/date.ts, add some", + ], + ko: [ + "pricing/discount.ts 할인 계산기에 대한 단위 테스트를 작성해 주세요. 중복 할인, 100% 상한, 만료된 코드, 센트 단위 반올림을 다루고 기존 vitest 설정을 써 주세요.", + "회원가입 폼 테스트 추가해줘", + "가입하고, 프로젝트 만들고, 팀원 초대하고, 초대 메일이 오는지까지 확인하는 E2E 테스트를 Playwright로 작성해 주세요.", + "utils/date.ts 테스트 커버리지가 0이야, 테스트 좀 써줘", + ], + }, + spec: { + en: [ + "Write a product spec for shared dashboards: the problem, who it's for, scope and non-goals, the permissions model, and how we'll measure success. Two pages at most.", + "draft a project plan for the billing migration", + "Turn these meeting notes into a one-page PRD for the mobile offline mode, with open questions at the end.", + "write requirements for the new onboarding flow", + ], + ko: [ + "공유 대시보드 기능의 제품 기획서를 써 주세요. 문제, 대상 사용자, 범위와 제외 범위, 권한 모델, 성공 지표까지 두 페이지 이내로요.", + "결제 시스템 이전 프로젝트 계획 짜줘", + "이 회의록을 모바일 오프라인 모드에 대한 한 페이지짜리 PRD로 정리하고 마지막에 미결 사항을 적어 주세요.", + "새 온보딩 플로우 요구사항 정리해줘", + ], + }, + design: { + en: [ + "Mock up the settings page for team billing: plan card, seat count with +/- controls, invoice list. Use our existing component styles and show the empty state too.", + "design a banner for the spring sale", + "Lay out three options for the new onboarding screen on mobile, 390px wide, and note which one you'd pick and why.", + "make a wireframe for the admin dashboard", + ], + ko: [ + "팀 결제 설정 페이지 목업을 만들어 주세요. 요금제 카드, +/- 버튼이 있는 좌석 수, 청구서 목록이 들어가고 기존 컴포넌트 스타일을 쓰고 빈 상태 화면도 보여 주세요.", + "봄 세일 배너 디자인해줘", + "390px 너비 모바일 온보딩 화면 시안을 세 가지 잡아 주시고, 어떤 걸 고를지와 이유도 적어 주세요.", + "관리자 대시보드 와이어프레임 그려줘", + ], + }, + copy: { + en: [ + "Write a 900-word blog post announcing our Korean-language support, aimed at ops managers. Warm, concrete, one customer quote placeholder, and a call to action to book a demo.", + "write landing page copy for the new API product", + "Three LinkedIn posts for the product launch next week: one story, one stat, one question. Under 80 words each.", + "need a tagline for the pricing page hero", + ], + ko: [ + "한국어 지원 출시를 알리는 운영 매니저 대상 블로그 글을 2,000자 정도로 써 주세요. 따뜻하고 구체적으로, 고객 인용 자리 하나, 데모 예약 유도 문구로 마무리해 주세요.", + "새 API 상품 랜딩페이지 문구 써줘", + "다음 주 출시용 링크드인 게시물 세 개를 써 주세요. 하나는 사례, 하나는 수치, 하나는 질문으로, 각각 150자 이내로요.", + "요금제 페이지 상단 카피 한 줄 뽑아줘", + ], + }, + translate: { + en: [ + "Translate this help article on setting up SSO into Korean. Keep product names and menu labels in English, use the formal polite register, and keep the headings.", + "put this customer reply into English", + "Translate my answer to the Korean customer below; it should sound natural to them, not word-for-word.", + "translate the release notes to Korean", + ], + ko: [ + "SSO 설정 도움말 문서를 영어로 번역해 주세요. 제목 구조는 그대로 두고, 제품명과 메뉴 이름은 원문 그대로, 자연스러운 미국식 영어로요.", + "이 고객 답장 영어로 옮겨줘", + "아래 영어권 고객에게 보낼 제 답변을 번역해 주세요. 직역 말고 자연스럽게요.", + "릴리스 노트 한국어로 번역해줘", + ], + }, + policy: { + en: [ + "Review this MSA from Ridgeway before legal sees it. Flag anything on liability caps, auto-renewal and data processing that differs from our standard terms, with the clause numbers.", + "draft a remote work policy", + "Write our acceptable use policy for AI tools: what employees may paste in, what needs approval, and what's banned. Plain language, one page.", + "check this NDA for anything unusual", + ], + ko: [ + "법무팀에 넘기기 전에 리지웨이 기본계약서를 검토해 주세요. 책임 한도, 자동 갱신, 데이터 처리 조항 중 우리 표준과 다른 부분을 조항 번호와 함께 표시해 주세요.", + "재택근무 규정 초안 써줘", + "AI 도구 사용 정책을 써 주세요. 직원이 입력해도 되는 것, 승인이 필요한 것, 금지된 것을 쉬운 말로 한 페이지에 정리해 주세요.", + "이 NDA에 이상한 조항 있는지 봐줘", + ], + }, + hr: { + en: [ + "Write a job description for a senior backend engineer: Go and Postgres, on-call one week in six, hybrid in Seoul. Include the salary band placeholder and skip the clichés.", + "summarize these peer reviews for Dana's mid-year check-in", + "Put together a 30-60-90 day onboarding plan for a new customer success manager, with who they should meet in week one.", + "write a JD for a product designer", + ], + ko: [ + "시니어 백엔드 엔지니어 채용공고를 써 주세요. Go와 Postgres, 6주에 1주 온콜, 서울 하이브리드 근무이고 연봉 범위 자리 표시와 진부한 표현은 빼 주세요.", + "다나 상반기 면담용으로 동료 평가 내용 정리해줘", + "신규 고객성공 매니저를 위한 30-60-90일 온보딩 계획을 짜 주시고 첫 주에 만나야 할 사람도 적어 주세요.", + "프로덕트 디자이너 채용공고 써줘", + ], + }, + finance: { + en: [ + "Reconcile September's card transactions against the ledger export. List every mismatch over $10 with the date and amount, and total what's unexplained.", + "check these vendor invoices against the POs", + "Match the Stripe payouts to bank deposits for last month and tell me which payouts are missing or short.", + "find duplicate invoices in this list", + ], + ko: [ + "9월 법인카드 거래 내역을 장부 내보내기와 대사해 주세요. 1만 원 넘는 불일치 건을 날짜와 금액과 함께 나열하고 설명 안 되는 금액 합계도 알려 주세요.", + "이 거래처 세금계산서들 발주서랑 맞는지 확인해줘", + "지난달 스트라이프 정산액을 통장 입금 내역과 맞춰 보고 빠지거나 모자란 정산 건을 알려 주세요.", + "이 목록에서 중복 청구서 찾아줘", + ], + }, +}; + +/** Not about work, too vague to place, or asking to learn: a correct classifier names no kind. */ +const NONE: Rows = { + en: [ + "what's a good place for lunch near Gangnam station", + "hey", + "can you help me with something", + "write me a poem about my cat", + "do the thing from earlier", + "What's the difference between a PR review and a code audit?", + "Explain what an accrual is like I'm new to accounting", + "I drafted this email to a customer, does it sound too pushy?", + ], + ko: [ + "강남역 근처 점심 맛집 추천해줘", + "하이 반가워", + "뭐 좀 도와줄 수 있어?", + "우리 고양이에 대한 시 써줘", + "아까 그거 해줘", + "PR 리뷰랑 코드 감사는 뭐가 달라요?", + "회계 처음인 사람한테 설명하듯이 발생주의가 뭔지 알려줘", + "고객한테 보낼 메일 초안인데 너무 밀어붙이는 느낌인가요?", + ], +}; + +export const TUNING_EXAMPLES: TrainingExample[] = [ + ...Object.entries(BY_ACTION).flatMap(([action, rows]) => + (["en", "ko"] as const).flatMap((lang) => rows[lang].map((text) => ({ action, learn: false, lang, text }))), + ), + ...(["en", "ko"] as const).flatMap((lang) => NONE[lang].map((text) => ({ action: null, learn: false, lang, text }))), +]; diff --git a/packages/work-labeller/model/train/types.ts b/packages/work-labeller/model/train/types.ts new file mode 100644 index 0000000000..9087de9b6b --- /dev/null +++ b/packages/work-labeller/model/train/types.ts @@ -0,0 +1,2 @@ +/** Training examples per kind of work, per language. Action keys are the console's (vocabulary.ts). */ +export type TrainingRows = Record; diff --git a/packages/work-labeller/model/train/write-a.ts b/packages/work-labeller/model/train/write-a.ts new file mode 100644 index 0000000000..75db293b1c --- /dev/null +++ b/packages/work-labeller/model/train/write-a.ts @@ -0,0 +1,338 @@ +/* + * Training examples for the work classifier: support replies, summaries, customer email, research + * and translation. Written for training only, apart from the evaluation set; see train/index.ts. + */ +import type { TrainingRows } from "./types.js"; + +export const WRITE_A: TrainingRows = { + reply: { + en: [ + "Customer can't log in after resetting their password, write them a reply", + "Help me respond to a ticket asking why their invoice is higher this month", + "Reply to this user who says the mobile app crashes on startup. Be empathetic and ask for their device model.", + "Draft a response to a customer asking if we support SAML", + "A customer wants to cancel. Write a reply that confirms the cancellation date and mentions they can export their data first.", + "Write back to the ticket below, they're asking how to change the billing email", + "answer this support question about rate limits", + "Customer is frustrated that support took three days to respond. Write an apology and the answer to their original question.", + "Need a reply to a ticket where the user accidentally deleted a project", + "Write a short, friendly answer explaining that the feature they want is on the roadmap but has no date", + "respond to the customer, tell them the outage is resolved and we'll credit their account", + "Reply to this enterprise admin asking how to add 50 users at once", + "Customer reports duplicate notifications. Draft a reply asking for screenshots and the time it happened.", + "Can you write the support reply for ticket #4821? They want a refund for an unused month.", + "help me answer a customer who thinks they were overcharged", + "Draft a response saying we can't share their data with a third party, and explain why", + "Write a reply to a user asking how to export their reports to PDF, step by step", + "Customer says the integration with Slack stopped working. Reply with the fix: reconnect from Settings.", + "Respond to a complaint about slow page loads, without promising a timeline", + "Write the reply to this escalated ticket from our biggest account", + "Draft an answer to a question about our data retention period", + "A customer asked whether they can downgrade mid-cycle. Answer them.", + "reply to this ticket in a calm tone, the customer is very angry", + "Write a response that walks the user through resetting two-factor authentication", + "Help me close out this ticket with a polite final reply", + "Customer wants to know when their trial ends, reply with the date and how to upgrade", + "Write a support reply explaining the error message they're seeing and what to try", + "Respond to the user asking for an invoice with our tax ID on it", + "Reply to a customer who sent a bug report with no details, asking for the steps to reproduce", + "Draft the reply for a ticket about a failed payment, include the link to update the card", + ], + ko: [ + "비밀번호 재설정 후에 로그인이 안 된다는 고객 문의에 답장 써줘", + "이번 달 청구서 금액이 왜 올랐냐는 문의에 답변 좀 도와줘", + "앱이 시작하자마자 꺼진다는 사용자한테 답장 써 주세요. 공감하는 톤으로, 기기 모델도 물어봐 주세요.", + "SAML 지원하냐는 고객 질문에 답변 초안", + "해지하겠다는 고객에게 해지 날짜를 확인해 주고, 그 전에 데이터를 내보낼 수 있다고 안내하는 답장을 써 주세요.", + "아래 티켓에 답장해줘. 결제 이메일 바꾸는 방법 묻는 거야", + "요청 한도 관련 고객 문의에 답변해줘", + "답변이 3일이나 늦었다고 화난 고객입니다. 사과와 함께 원래 질문에 대한 답을 써 주세요.", + "프로젝트를 실수로 삭제했다는 고객 티켓 답장이 필요해", + "원하는 기능이 로드맵에는 있지만 일정은 없다고 짧고 친절하게 답해 주세요", + "장애 해결됐고 크레딧 넣어 드린다고 고객한테 답장해줘", + "사용자 50명을 한 번에 추가하는 방법을 묻는 엔터프라이즈 관리자에게 답변해 주세요", + "알림이 두 번씩 온다는 고객 신고예요. 스크린샷이랑 발생 시간 요청하는 답장 써 주세요.", + "4821번 티켓 답장 써 줄래? 안 쓴 한 달 환불해 달래", + "요금이 더 나갔다고 생각하는 고객한테 답변 좀", + "고객 데이터를 제3자에게 공유할 수 없다는 내용과 이유를 설명하는 답장 초안", + "리포트를 PDF로 내보내는 방법을 단계별로 안내하는 답변을 써 주세요", + "슬랙 연동이 끊겼다는 고객에게 설정에서 다시 연결하면 된다고 답해줘", + "페이지가 느리다는 불만에 일정은 약속하지 말고 답변해 주세요", + "제일 큰 고객사에서 에스컬레이션된 티켓 답장 써줘", + "데이터 보관 기간 묻는 문의에 답변 작성", + "결제 주기 중간에 요금제를 낮출 수 있는지 묻는 고객에게 답해 주세요", + "이 티켓 차분한 톤으로 답장해줘. 고객이 엄청 화났어", + "2단계 인증 재설정 방법을 차례대로 안내하는 답장을 써 주세요", + "이 티켓 마무리하는 정중한 마지막 답장 부탁해", + "체험 기간 언제 끝나는지 묻는 고객에게 날짜랑 업그레이드 방법 알려 주는 답장", + "고객이 보고 있는 오류 메시지가 뭔지 설명하고 해볼 방법을 안내하는 답변을 써 주세요", + "사업자등록번호가 들어간 청구서를 요청한 고객에게 답장해줘", + "재현 방법 없이 버그만 신고한 고객에게 재현 단계를 물어보는 답장", + "결제 실패 티켓 답장 써줘. 카드 정보 바꾸는 링크도 넣고", + ], + }, + summ: { + en: [ + "Summarize this Slack thread so I can catch up", + "What were the decisions in this meeting? Transcript below.", + "Give me a one-paragraph summary of the attached customer call", + "Boil this 30-reply email chain down to what's still unresolved", + "summarize the notes from today's standup", + "Write a short recap of the incident channel for people who missed it", + "Turn this interview transcript into five key takeaways", + "Summarize the support tickets from this week into themes", + "Can you condense this long document into a page?", + "Recap the board meeting notes in bullet points", + "Summarize what the customer said on the call about pricing", + "Give me the TL;DR of this RFC", + "Pull the action items out of these meeting notes, with owners", + "Summarize this week's activity across our top accounts", + "Make a brief summary of the feedback survey responses", + "Summarize this thread for my manager in three sentences", + "What did we agree on in the call with the vendor? Here's the recording transcript.", + "Condense the attached report into an executive summary", + "summarize these customer reviews", + "Write a digest of the product team's updates this sprint", + "Summarize the Q&A from the all-hands", + "I missed the planning meeting, summarize it for me from the notes", + "Give me a quick summary of the ticket history before I take it over", + "Summarize the key risks raised in this discussion", + "Turn this voice memo transcript into tidy notes", + "Summarize the comments on this pull request discussion", + "Recap of yesterday's client workshop, please", + "Summarize the main complaints in these app store reviews", + "Shorten this status update to fit in one Slack message", + "Summarize the user research sessions into findings", + ], + ko: [ + "이 슬랙 스레드 따라잡게 요약해줘", + "이 회의에서 뭘 결정했는지 알려줘. 녹취록 아래에 있어", + "첨부한 고객 통화를 한 문단으로 요약해 주세요", + "답장 30개짜리 메일 스레드에서 아직 안 풀린 것만 정리해줘", + "오늘 스탠드업 메모 요약", + "장애 채널 내용을 못 본 사람들을 위해 짧게 정리해 주세요", + "인터뷰 녹취록을 핵심 다섯 가지로 정리해 주세요", + "이번 주 고객 문의 티켓들을 주제별로 요약해줘", + "이 긴 문서 한 장으로 줄여 줄 수 있어?", + "이사회 회의록을 글머리표로 정리해 주세요", + "통화에서 고객이 가격에 대해 한 말만 요약해줘", + "이 RFC 세 줄 요약", + "회의 메모에서 담당자랑 같이 할 일만 뽑아줘", + "주요 고객사들의 이번 주 활동을 요약해 주세요", + "피드백 설문 응답 간단히 요약해줘", + "이 스레드를 팀장님께 세 문장으로 요약해 드려야 해", + "벤더랑 통화에서 뭐 합의했는지 정리해줘. 녹음 녹취록이야", + "첨부한 보고서를 경영진용 요약으로 만들어 주세요", + "고객 리뷰들 요약해줘", + "이번 스프린트 제품팀 업데이트를 다이제스트로 정리해 주세요", + "전사 미팅 Q&A 정리해줘", + "기획 회의 못 들어갔는데 메모 보고 요약해 줘", + "티켓 넘겨받기 전에 지금까지 이력 빠르게 요약해줘", + "이 논의에서 나온 주요 리스크만 정리해 주세요", + "음성 메모 녹취를 깔끔한 메모로 정리해줘", + "이 PR 토론에 달린 의견들 요약", + "어제 고객사 워크숍 내용 정리 부탁해요", + "앱스토어 리뷰에서 주요 불만 사항만 요약해 주세요", + "이 진행 상황 업데이트를 슬랙 메시지 하나 분량으로 줄여줘", + "사용자 리서치 세션들을 발견점 위주로 정리해 주세요", + ], + }, + email: { + en: [ + "Write an email to a customer letting them know their contract renews next month", + "Draft a first outreach email to the head of IT at a hospital group", + "Email the prospect we met at the conference and suggest a call next week", + "Write a follow-up to the client who went quiet after our proposal", + "Draft an email introducing our new account manager to the customer", + "Write a thank-you email after the demo with a link to the recording", + "Email the customer that their pilot ends Friday and ask whether they want to continue", + "draft an upsell email for customers on the basic plan", + "Write an email inviting our top customers to the user conference", + "Compose an email to a lead asking who else should join the evaluation", + "Write a polite chaser to a customer whose invoice is 30 days overdue", + "Draft a customer email announcing the price change in March", + "Write an email to a prospect who asked for a case study, attach the healthcare one", + "email the customer the summary of what we agreed in today's meeting", + "Draft a win-back email for customers who churned last quarter", + "Write a short email asking a happy customer for a referral", + "Draft an email to set up a quarterly business review with the client", + "Write to the customer's procurement team with the documents they asked for", + "Cold email for CFOs at mid-size retailers, under 100 words", + "Write an email confirming the onboarding schedule with the customer", + "Draft an email apologizing to the customer for the missed deadline", + "Email the prospect a recap of the pricing options we discussed", + "Write an email to a customer champion who just changed jobs", + "Follow-up email after the trade show to everyone who visited our booth", + "Write an email letting the customer know the feature they asked for has shipped", + "Draft an email to re-engage a prospect who hasn't replied in two months", + "Write a renewal email offering a discount for a two-year commitment", + "Email the customer to schedule the security review call", + "Draft a note to a customer explaining the changes to our support hours", + "Write an introduction email from me to a potential partner", + ], + ko: [ + "다음 달에 계약이 갱신된다고 고객에게 알리는 메일 써줘", + "병원 그룹 IT 책임자에게 보낼 첫 영업 메일 초안", + "컨퍼런스에서 만난 잠재 고객에게 다음 주 통화를 제안하는 메일을 써 주세요", + "제안서 보낸 뒤로 연락이 없는 고객에게 후속 메일 써줘", + "새 담당 매니저를 고객에게 소개하는 메일 초안", + "데모 후에 녹화 링크와 함께 보낼 감사 메일을 써 주세요", + "파일럿이 금요일에 끝나는데 계속 쓸지 묻는 메일 고객한테 보내줘", + "기본 요금제 고객 대상 업셀 메일 초안 써줘", + "주요 고객사를 사용자 컨퍼런스에 초대하는 메일을 작성해 주세요", + "도입 검토에 누가 더 참여해야 할지 묻는 메일을 리드에게 써줘", + "청구서가 30일 연체된 고객에게 정중하게 독촉하는 메일", + "3월 가격 변경을 안내하는 고객 메일 초안을 써 주세요", + "사례 자료 요청한 잠재 고객에게 의료 사례 첨부해서 메일 써줘", + "오늘 회의에서 합의한 내용 정리해서 고객한테 메일 보내줘", + "지난 분기에 이탈한 고객을 다시 데려올 메일 초안", + "만족한 고객에게 소개를 부탁하는 짧은 메일을 써 주세요", + "고객사와 분기 비즈니스 리뷰 일정 잡는 메일 써줘", + "고객사 구매팀이 요청한 서류를 보내는 메일을 작성해 주세요", + "중견 유통사 재무 책임자 대상 콜드메일, 200자 이내로", + "온보딩 일정을 고객과 확정하는 메일 써줘", + "마감을 못 지킨 것에 대해 고객에게 사과하는 메일 초안을 써 주세요", + "얘기 나눈 가격 옵션 정리해서 잠재 고객에게 메일로 보내줘", + "이직한 고객사 담당자에게 보낼 메일 써줘", + "전시회 부스 방문자 전원에게 보낼 후속 메일", + "요청하신 기능이 출시됐다고 고객에게 알리는 메일을 써 주세요", + "두 달째 답이 없는 잠재 고객 다시 연락하는 메일 초안", + "2년 약정 시 할인해 준다는 갱신 메일 써줘", + "보안 검토 통화 일정을 잡자는 메일을 고객에게 보내 주세요", + "고객지원 운영 시간 변경을 설명하는 안내 메일 초안", + "잠재 파트너사에 저를 소개하는 메일을 써 주세요", + ], + }, + research: { + en: [ + "Find out everything public about this prospect before my meeting", + "Research the top three vendors in our space and how they price", + "Who are the decision makers at this company? Use LinkedIn and their website.", + "Look into the regulations for selling software to banks in Singapore", + "What's the latest news about our biggest customer?", + "Research how competitors handle onboarding for enterprise customers", + "Find market sizing data for HR software in Southeast Asia, with sources", + "Dig into this startup's funding history and investors", + "Give me background on this account: industry, size, tech stack", + "research which companies recently adopted our competitor's product", + "Find three examples of companies that publish their pricing for this kind of tool", + "What are analysts saying about the AI coding assistant market this year?", + "Look up the hiring trends at this company to see if they're growing", + "Research industry benchmarks for SaaS churn in the mid-market", + "Find out what tools this prospect currently uses for project management", + "Put together a brief on the customer's recent acquisitions", + "research the Japanese market for our product, regulations and competitors", + "Find case studies from competitors in the logistics sector", + "What are the main trends in customer support software? Cite sources.", + "Look into this company's annual report and pull out their strategic priorities", + "Research average contract values for tools like ours", + "Find the conferences our target customers go to", + "Investigate why a competitor raised their prices", + "Who does this company partner with? Find their integrations and resellers.", + "Research the procurement process at public universities in Korea", + "Compare the feature sets of the leading alternatives", + "Find reviews of our competitor on G2 and summarize the complaints", + "Research this person before my call: role, background, recent posts", + "Look up the market share of the top cloud providers in Korea", + "Find out if this prospect has had any security incidents in the news", + ], + ko: [ + "미팅 전에 이 잠재 고객사에 대해 공개된 정보 전부 찾아줘", + "우리 분야 상위 벤더 세 곳과 가격 정책을 조사해 주세요", + "이 회사 의사결정권자가 누군지 링크드인이랑 홈페이지로 알아봐줘", + "싱가포르 은행에 소프트웨어 팔 때 필요한 규제 조사", + "가장 큰 고객사 최근 뉴스 뭐 있어?", + "경쟁사들이 엔터프라이즈 온보딩을 어떻게 하는지 조사해 주세요", + "동남아 HR 소프트웨어 시장 규모 자료를 출처와 함께 찾아줘", + "이 스타트업 투자 이력이랑 투자사 알아봐줘", + "이 고객사 배경 정리해 주세요. 업종, 규모, 기술 스택", + "최근에 경쟁사 제품 도입한 회사들 조사해줘", + "이런 종류 도구 중에 가격을 공개하는 회사 사례 세 개 찾아줘", + "올해 AI 코딩 도구 시장에 대해 애널리스트들이 뭐라고 하는지 알려 주세요", + "이 회사 채용 동향 보고 성장 중인지 알아봐줘", + "중견기업 SaaS 이탈률 업계 벤치마크 조사", + "이 잠재 고객이 지금 프로젝트 관리에 무슨 도구를 쓰는지 알아봐 주세요", + "고객사가 최근 인수한 회사들에 대한 브리프 만들어줘", + "우리 제품 일본 시장 조사해줘. 규제랑 경쟁사", + "물류 업계 경쟁사 고객 사례 찾아 주세요", + "고객지원 소프트웨어 주요 트렌드가 뭐야? 출처도 달아줘", + "이 회사 연차보고서에서 전략 우선순위를 뽑아 주세요", + "우리 같은 도구의 평균 계약 금액 조사해줘", + "타깃 고객들이 가는 컨퍼런스 찾아줘", + "경쟁사가 왜 가격을 올렸는지 알아봐 주세요", + "이 회사 파트너사가 어디야? 연동이랑 리셀러 찾아줘", + "국내 국립대 구매 절차 조사해 주세요", + "주요 대안 제품들 기능 비교 조사", + "G2에서 경쟁사 리뷰 찾아서 불만 사항 정리해줘", + "통화 전에 이 사람 조사 좀. 직책, 경력, 최근 게시물", + "국내 클라우드 사업자 시장 점유율 찾아 주세요", + "이 잠재 고객사가 보안 사고로 뉴스에 난 적 있는지 알아봐줘", + ], + }, + translate: { + en: [ + "Translate this email from the Japanese customer into English", + "Put this release note into Korean", + "Translate my reply into Korean, keep it formal", + "Can you translate the attached contract summary into English?", + "translate this to Spanish", + "Translate the onboarding guide into Japanese, keep the screenshots' labels in English", + "The customer wrote in Vietnamese, what does it say?", + "Translate these 20 UI strings into Korean", + "Make a Korean version of the FAQ page", + "Translate the support macro into Korean and Japanese", + "Translate this Korean feedback into English for the product team", + "Please translate the help center article on billing into Korean", + "What's this Chinese message from the partner saying?", + "Translate our privacy notice into Korean", + "Localize the welcome email for our Korean users", + "Translate the meeting notes from Korean to English", + "translate the attached slide text into English", + "Translate this complaint into English and keep the tone", + "Turn this English job post into natural Korean", + "Translate the product description for the Japanese store listing", + "Translate my answer back into the customer's language, which is German", + "Translate this survey into Korean", + "Translate the error messages file into Korean", + "Rewrite this machine-translated paragraph into natural English", + "Translate the terms of service changes into Korean", + "Give me an English translation of this Korean tax notice", + "Translate the chat transcript from Korean to English", + "Translate these push notification texts into Korean, keep them short", + "Translate the customer's PDF letter into English", + "Localize the pricing page copy for Japan", + ], + ko: [ + "일본 고객이 보낸 메일 영어로 번역해줘", + "이 릴리스 노트 한국어로 옮겨 주세요", + "내 답장 격식 있게 영어로 번역해줘", + "첨부한 계약 요약본을 영어로 번역해 주실 수 있나요?", + "이거 스페인어로 번역", + "온보딩 가이드를 일본어로 번역해 주세요. 스크린샷 라벨은 영어로 두고요", + "고객이 베트남어로 썼는데 뭐라는 거야?", + "UI 문구 20개 한국어로 번역해줘", + "FAQ 페이지 영어판 만들어 주세요", + "고객지원 매크로를 영어와 일본어로 번역해줘", + "이 한국어 피드백을 제품팀용으로 영어로 번역해 주세요", + "결제 관련 도움말 문서 영어로 번역 부탁드려요", + "파트너사에서 온 중국어 메시지 무슨 내용이야?", + "개인정보 처리방침 영어로 번역해 주세요", + "한국 사용자용 환영 메일 현지화해줘", + "회의록 한국어에서 영어로 번역", + "첨부 슬라이드 텍스트 영어로 번역해줘", + "이 불만 메일 영어로 번역해 주세요. 어조는 그대로", + "영어 채용 공고를 자연스러운 한국어로 바꿔줘", + "일본 스토어 등록용 제품 설명 번역해 주세요", + "내 답변을 고객 언어인 독일어로 번역해줘", + "이 설문 영어로 번역해 주세요", + "오류 메시지 파일 한국어로 번역", + "기계 번역된 문단을 자연스러운 한국어로 다시 써줘", + "이용약관 변경 내용 영어로 번역해 주세요", + "이 국세청 안내문 영어로 번역해줘", + "채팅 기록 한국어에서 영어로 번역해 주세요", + "푸시 알림 문구들 짧게 영어로 번역해줘", + "고객이 보낸 PDF 서신 영어로 번역 부탁해요", + "가격 페이지 문구를 일본 시장에 맞게 현지화해 주세요", + ], + }, +}; diff --git a/packages/work-labeller/model/train/write-b.ts b/packages/work-labeller/model/train/write-b.ts new file mode 100644 index 0000000000..0ffe535a43 --- /dev/null +++ b/packages/work-labeller/model/train/write-b.ts @@ -0,0 +1,272 @@ +/* + * Training examples for the work classifier: plans and specs, marketing copy, contracts and + * policies, and people documents. Written for training only; see train/index.ts. + */ +import type { TrainingRows } from "./types.js"; + +export const WRITE_B: TrainingRows = { + spec: { + en: [ + "Write a PRD for bulk user import", + "Draft a project plan for migrating our billing system, with phases", + "Turn these notes into a one-pager describing the feature and its goals", + "Write the requirements for the new reporting dashboard", + "Create a roadmap for the next two quarters from this list of ideas", + "Write a design doc for adding SSO, including open questions", + "Plan the launch: workstreams, owners, and dates", + "Draft acceptance criteria for these user stories", + "Write a spec for the mobile offline mode", + "Break this initiative into milestones and estimate each", + "Outline the scope for v1 of the partner portal, what's in and out", + "Write an RFC proposing we move from REST to GraphQL", + "Make a project plan for the office move with a timeline", + "Draft the problem statement and success metrics for this feature", + "Write a technical proposal for rate limiting per workspace", + "plan next sprint from the backlog below", + "Write user stories for the checkout redesign", + "Turn this brainstorm into a prioritized feature list with rationale", + "Draft a rollout plan with a beta, a staged release and a rollback step", + "Write a spec for the notification preferences page", + "Create a work breakdown for the data warehouse project", + "Draft a decision memo comparing three options for search", + "Plan the Q3 OKRs for the platform team", + "Write the functional spec for exporting audit logs", + "Outline a migration plan from the old CRM, with risks", + "Draft a product brief for the AI assistant feature", + "Write requirements for the admin role permissions", + "Create a timeline for the hiring plan next half", + "Write a spec covering the edge cases for subscription upgrades", + "Plan the deprecation of the v1 API, with communication steps", + ], + ko: [ + "사용자 일괄 가져오기 PRD 써줘", + "결제 시스템 이전 프로젝트 계획을 단계별로 세워 주세요", + "이 메모를 기능과 목표를 설명하는 한 장짜리 문서로 만들어줘", + "새 리포트 대시보드 요구사항 작성", + "아이디어 목록으로 다음 두 분기 로드맵 만들어 주세요", + "SSO 추가 설계 문서 써줘. 미결 질문도 포함해서", + "출시 계획 세워줘. 업무 갈래, 담당자, 날짜", + "이 유저 스토리들에 인수 조건 써 주세요", + "모바일 오프라인 모드 기획서 작성", + "이 과제를 마일스톤으로 나누고 각각 공수 추정해줘", + "파트너 포털 v1 범위 정리해 주세요. 포함과 제외", + "REST에서 GraphQL로 옮기자는 RFC 써줘", + "사무실 이전 일정이 들어간 프로젝트 계획 만들어줘", + "이 기능의 문제 정의와 성공 지표 초안을 써 주세요", + "워크스페이스별 요청 제한 기술 제안서 작성", + "아래 백로그로 다음 스프린트 계획 짜줘", + "결제 화면 개편 유저 스토리 써 주세요", + "브레인스토밍 결과를 근거와 함께 우선순위 매긴 기능 목록으로 정리해줘", + "베타, 단계별 배포, 롤백까지 들어간 출시 계획 초안", + "알림 설정 페이지 기획서 써줘", + "데이터 웨어하우스 프로젝트 작업 분해 구조 만들어 주세요", + "검색 방식 세 가지를 비교하는 의사결정 문서 초안", + "플랫폼팀 3분기 OKR 계획 세워줘", + "감사 로그 내보내기 기능 명세서 작성해 주세요", + "기존 CRM에서 옮기는 마이그레이션 계획을 리스크와 함께 정리해줘", + "AI 어시스턴트 기능 제품 브리프 초안", + "관리자 역할 권한 요구사항 써 주세요", + "하반기 채용 계획 타임라인 만들어줘", + "구독 업그레이드 예외 상황까지 다루는 기획서 작성", + "v1 API 종료 계획을 공지 단계까지 포함해서 세워 주세요", + ], + }, + copy: { + en: [ + "Write a blog post announcing our Series B", + "Draft three headline options for the new landing page", + "Write a LinkedIn post about our new Korean office", + "Write product page copy for the analytics feature", + "Come up with a tagline for the spring campaign", + "Write a newsletter intro for this month's product updates", + "Draft ad copy for Google search, three variants under 90 characters", + "Write a case study page from this customer interview", + "Write the hero section text for our homepage", + "Write tweets announcing the launch, a thread of five", + "Draft an email newsletter promoting the webinar", + "Write copy for the pricing page explaining each plan", + "Write an Instagram caption for the team offsite photo", + "Draft a press release about the partnership", + "Write microcopy for the empty state in the dashboard", + "write a blog post about best practices for remote onboarding", + "Rewrite our About page to sound less corporate", + "Write copy for the app store listing", + "Draft a launch announcement for our community forum", + "Write the text for a promotional banner, short and punchy", + "Write a thought leadership article for our CEO about AI at work", + "Draft copy for the feature comparison page", + "Write a product launch video script, 60 seconds", + "Write the subject line and preview text for the campaign email", + "Write a customer story blog post from these notes", + "Draft social posts for the conference we're sponsoring", + "Write copy for the signup page that improves conversion", + "Write a short brand story for the investor deck", + "Write the description for our YouTube channel", + "Draft taglines in a playful tone for the summer sale", + ], + ko: [ + "시리즈 B 투자 유치 알리는 블로그 글 써줘", + "새 랜딩 페이지 헤드라인 세 가지 안 만들어 주세요", + "한국 사무소 오픈 소식 링크드인 게시글 써줘", + "분석 기능 제품 페이지 문구 작성해 주세요", + "봄 캠페인 태그라인 뽑아줘", + "이번 달 제품 업데이트 뉴스레터 도입부 써 주세요", + "구글 검색 광고 문구 세 가지, 45자 이내로", + "이 고객 인터뷰로 고객 사례 페이지 써줘", + "홈페이지 메인 영역 문구 작성", + "출시 알리는 트윗 다섯 개짜리 스레드 써줘", + "웨비나 홍보 뉴스레터 메일 초안 써 주세요", + "요금제별로 설명하는 가격 페이지 문구 작성해줘", + "팀 워크숍 사진에 붙일 인스타 캡션", + "파트너십 보도자료 초안 써 주세요", + "대시보드 빈 화면에 들어갈 안내 문구 써줘", + "원격 온보딩 모범 사례 블로그 글 써줘", + "회사 소개 페이지를 덜 딱딱하게 다시 써 주세요", + "앱스토어 등록 문구 작성", + "커뮤니티 포럼에 올릴 출시 공지 초안", + "프로모션 배너 문구, 짧고 강렬하게", + "대표님 명의로 일하는 방식과 AI에 대한 기고문 써 주세요", + "기능 비교 페이지 문구 초안", + "60초짜리 제품 출시 영상 대본 써줘", + "캠페인 메일 제목이랑 미리보기 문구 써 주세요", + "이 메모로 고객 이야기 블로그 글 써줘", + "후원하는 컨퍼런스 홍보용 SNS 게시물 초안", + "가입 전환율 높일 가입 페이지 문구 써 주세요", + "투자 제안서에 넣을 짧은 브랜드 스토리 작성", + "유튜브 채널 소개글 써줘", + "여름 세일 태그라인을 발랄한 톤으로 만들어 주세요", + ], + }, + policy: { + en: [ + "Review this vendor agreement and flag anything unusual", + "Check the indemnity clause in this contract against our standard terms", + "Draft a data processing agreement for a new customer", + "Does this NDA restrict us from hiring their employees? Point to the clause.", + "Write an acceptable use policy for company laptops", + "Review the customer's redlines on our MSA", + "Draft an internal policy on expense approvals", + "What are the termination rights in this agreement?", + "Write a security policy for handling customer data", + "Compare this SaaS agreement with our template and list the differences", + "Draft a code of conduct for our community", + "Review the liability cap in this contract", + "Write a travel policy for employees", + "Check this lease agreement for renewal terms and notice periods", + "draft a privacy policy for our mobile app", + "Is there anything risky in this partnership agreement?", + "Write the open source usage policy for engineering", + "Review the SLA terms the customer is asking for", + "Draft a policy on using generative AI tools at work", + "Summarize the obligations we take on in this contract and flag the risky ones", + "Write a password and access policy", + "Review the reseller agreement payment terms", + "Draft a whistleblower policy", + "Check if this contract has an auto-renewal clause", + "Write a records retention policy", + "Review this employment contract template for problems", + "Draft a remote work equipment policy", + "Check the governing law and jurisdiction in this agreement", + "Write the incident response policy for the security team", + "Review the change of control clause in the investment agreement", + ], + ko: [ + "이 공급 계약서 검토하고 이상한 부분 표시해줘", + "이 계약의 면책 조항을 우리 표준 약관과 비교해 주세요", + "신규 고객용 개인정보 처리 위탁 계약서 초안", + "이 비밀유지계약 때문에 그쪽 직원을 채용 못 하는지 해당 조항 짚어줘", + "회사 노트북 사용 정책 써 주세요", + "고객이 우리 기본계약서에 수정 표시한 부분 검토해줘", + "경비 승인 사내 규정 초안 작성", + "이 계약에서 해지 권한이 어떻게 돼 있어?", + "고객 데이터 취급 보안 정책 써 주세요", + "이 SaaS 계약을 우리 템플릿과 비교해서 차이점 정리해줘", + "커뮤니티 행동 강령 초안", + "이 계약서 책임 한도 검토해 주세요", + "직원 출장 규정 작성해줘", + "임대차 계약서 갱신 조건이랑 통지 기간 확인해 주세요", + "모바일 앱 개인정보 처리방침 초안", + "이 제휴 계약에 위험한 부분 있어?", + "개발팀 오픈소스 사용 정책 써 주세요", + "고객이 요구하는 SLA 조건 검토해줘", + "업무 중 생성형 AI 도구 사용 정책 초안 작성", + "이 계약에서 우리가 지는 의무를 정리하고 위험한 건 표시해 주세요", + "비밀번호 및 접근 권한 정책 써줘", + "리셀러 계약서 대금 지급 조건 검토", + "공익 신고 정책 초안 써 주세요", + "이 계약서에 자동 갱신 조항 있는지 확인해줘", + "기록 보존 정책 작성", + "근로계약서 템플릿 문제 있는지 검토해 주세요", + "재택근무 장비 지원 규정 초안", + "이 계약의 준거법이랑 관할 법원 확인해줘", + "보안팀 사고 대응 정책 써 주세요", + "투자 계약서의 경영권 변동 조항 검토해줘", + ], + }, + hr: { + en: [ + "Write a job description for a product designer", + "Draft interview questions for a senior data engineer", + "Summarize the 360 feedback for this manager", + "Write an onboarding checklist for new sales reps", + "Draft a performance improvement plan for an underperforming engineer", + "Write the offer letter for our new head of marketing", + "Create a 90-day plan for a new engineering manager", + "Write a job post for a part-time customer support agent", + "Summarize the exit interview notes into themes", + "Draft a promotion case for this engineer based on their achievements", + "Write a career ladder for the design team", + "Draft the rejection email for candidates who didn't make the final round", + "Write a welcome message for a new hire's first day", + "Summarize this quarter's employee engagement survey", + "Write competencies for a team lead role", + "Draft goals for my direct report for next half", + "Write a reference check questionnaire", + "Create an interview scorecard for the account executive role", + "Write a job description for a Korean-speaking customer success manager", + "Draft feedback for my report on their presentation skills", + "Write the internship program description", + "Summarize the candidates' interview feedback into a hiring decision memo", + "Write an announcement that a team member is leaving", + "Draft the parental leave section of the handbook", + "write a JD for a backend intern", + "Write a self-review based on these accomplishments", + "Create onboarding training plan for the support team", + "Draft a note to the team announcing two new hires", + "Write a role description for a staff engineer", + "Summarize the peer reviews into strengths and areas to grow", + ], + ko: [ + "UX 리서처 뽑는 공고문 작성해줘", + "시니어 데이터 엔지니어 면접 질문 초안", + "이 매니저의 다면 평가 결과 요약해 주세요", + "신규 영업 사원 온보딩 체크리스트 작성", + "성과가 낮은 엔지니어의 성과 개선 계획 초안", + "새 마케팅 총괄님께 보낼 처우 안내서 써 주세요", + "새 엔지니어링 매니저의 90일 계획 만들어줘", + "파트타임 고객지원 상담원 채용 공고 작성", + "퇴사 면담 메모를 주제별로 요약해 주세요", + "이 엔지니어 성과를 바탕으로 승진 추천서 초안", + "디자인팀 커리어 레벨 체계 써줘", + "최종 면접에서 떨어진 지원자들에게 보낼 불합격 메일 초안", + "신입 첫 출근날 환영 메시지 써 주세요", + "이번 분기 직원 몰입도 설문 결과 요약", + "팀장 역할 역량 정의 작성해줘", + "팀원 하반기 목표 초안 잡아 주세요", + "평판 조회 질문지 만들어줘", + "영업 담당자 직무 면접 평가표 만들어 주세요", + "한국어 가능한 고객 성공 매니저 직무 기술서", + "팀원에게 발표 역량에 대한 피드백 초안 써줘", + "인턴십 프로그램 소개글 작성", + "지원자 면접 피드백을 채용 결정 메모로 정리해 주세요", + "팀원 퇴사 소식 공지 써줘", + "취업 규칙에 들어갈 육아휴직 조항 초안", + "백엔드 인턴 JD 써줘", + "이 성과들로 자기 평가서 써 주세요", + "고객지원팀 온보딩 교육 계획 만들어줘", + "신규 입사자 두 명 소개하는 팀 공지 초안", + "스태프 엔지니어 직무 설명 작성해 주세요", + "동료 평가를 강점과 성장할 점으로 요약해줘", + ], + }, +}; diff --git a/packages/work-labeller/package.json b/packages/work-labeller/package.json new file mode 100644 index 0000000000..8547bd7446 --- /dev/null +++ b/packages/work-labeller/package.json @@ -0,0 +1,73 @@ +{ + "name": "@redrob-labs/work-labeller", + "version": "0.0.0", + "description": "Labels an AI work session on the person's machine (kind of work, family, mode and outcome) for the Redrob Console's insights. Only labels leave the machine.", + "license": "MIT", + "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/redrob-labs/redrob-code.git", + "directory": "packages/work-labeller" + }, + "exports": { + ".": { + "types": "./src/index.ts", + "development": "./src/index.ts", + "default": "./dist/index.js" + }, + "./node": { + "types": "./src/node.ts", + "development": "./src/node.ts", + "default": "./dist/node.js" + }, + "./manifest.json": "./src/manifest.json" + }, + "files": [ + "dist", + "src", + "README.md", + "NOTICE.md" + ], + "scripts": { + "build": "tsup", + "typecheck": "tsgo --noEmit", + "test": "bun --conditions=development test test model", + "prepublishOnly": "bun run build" + }, + "dependencies": { + "zod": "catalog:" + }, + "peerDependencies": { + "onnxruntime-node": ">=1.20.0", + "onnxruntime-web": ">=1.20.0" + }, + "peerDependenciesMeta": { + "onnxruntime-node": { + "optional": true + }, + "onnxruntime-web": { + "optional": true + } + }, + "devDependencies": { + "@types/node": "catalog:", + "@typescript/native-preview": "catalog:", + "onnxruntime-node": "1.23.0", + "tsup": "^8.5.0", + "typescript": "catalog:" + }, + "publishConfig": { + "access": "public", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./node": { + "types": "./dist/node.d.ts", + "default": "./dist/node.js" + }, + "./manifest.json": "./src/manifest.json" + } + } +} diff --git a/packages/work-labeller/src/classifier.ts b/packages/work-labeller/src/classifier.ts new file mode 100644 index 0000000000..4b570014b1 --- /dev/null +++ b/packages/work-labeller/src/classifier.ts @@ -0,0 +1,159 @@ +/* + * The work classifier: which kind of work a session was (a support reply, a bug fix, ...) and its + * family (writing, a sheet, code, design), read from its first message on the person's machine. + * Only the labels leave it. + * + * A frozen multilingual-e5-base encoder (int8 ONNX, about 278 MB) turns the message into a sentence + * embedding; two softmax heads (work-head.json, trained by model/scripts/train.py) name the kind of + * work and the family, or say it is not + * work. Measured in redrob-cowork docs/features/ai-work-insights/model-evaluation.md. When the kind + * of work is named, the family is its family; when it is under its floor, the family head may still + * name the family alone. + * + * Runtime-neutral: bytes in, an onnxruntime (node or web) passed in, integrity checked with WebCrypto + * against MANIFEST before anything is parsed or run. `./node` adds reading and downloading the files. + */ +import { z } from "zod"; + +import manifest from "./manifest.json" with { type: "json" }; +import { unigramFromTokenizerJson, type Unigram } from "./unigram.js"; +import { ACTION_FAMILY, WORK_ACTIONS } from "./vocabulary.js"; +import trainedHead from "./work-head.json" with { type: "json" }; + +export const WORK_FAMILIES = ["write", "sheet", "code", "design"] as const; +export type WorkFamily = (typeof WORK_FAMILIES)[number]; +export type WorkLabel = { action: string | null; family: WorkFamily | null; confidence: number }; + +/** What the encoder reads at most, as in training (truncation 256). */ +const MAX_TOKENS = 256; + +const level = >(name: T) => + z.object({ + classes: z.array(name.nullable()), + scale: z.number(), + floor: z.number(), + w: z.array(z.array(z.number())), + b: z.array(z.number()), + }); +const Head = z.object({ + prefix: z.string(), + action: level(z.string().refine((key) => WORK_ACTIONS.includes(key), "not a kind of work")).nullable(), + family: level(z.enum(WORK_FAMILIES)), +}); +export type WorkHead = z.infer; + +export const WORK_HEAD: WorkHead = Head.parse(trainedHead); + +const ModelFile = z.object({ file: z.string(), sha256: z.string().regex(/^[0-9a-f]{64}$/), url: z.string().url() }); +const Manifest = z.object({ id: z.string(), revision: z.string(), license: z.string(), model: ModelFile, tokenizer: ModelFile }); +export type WorkModelManifest = z.infer; + +/** The encoder this version of the package trusts: what a download or a folder must hash to. */ +export const MANIFEST: WorkModelManifest = Manifest.parse(manifest); + +/** The most likely class of one head, and its probability. */ +function top(level: { classes: readonly C[]; scale: number; w: number[][]; b: number[] }, embedding: Float32Array) { + const logits = level.b.map((bias, k) => { + let sum = bias; + for (let i = 0; i < embedding.length; i += 1) sum += embedding[i]! * level.scale * level.w[i]![k]!; + return sum; + }); + const peak = Math.max(...logits); + const exps = logits.map((logit) => Math.exp(logit - peak)); + const total = exps.reduce((sum, value) => sum + value, 0); + const best = exps.indexOf(Math.max(...exps)); + return { name: level.classes[best]!, confidence: exps[best]! / total }; +} + +/** + * The labels for an L2-normalised sentence embedding. The kind of work when its head is sure enough, + * with its family; else the family alone when that head is; else nothing (not work, or unsure). + */ +export function labelEmbedding(head: WorkHead, embedding: Float32Array): WorkLabel { + if (head.action) { + const action = top(head.action, embedding); + if (action.name && action.confidence >= head.action.floor) { + return { action: action.name, family: ACTION_FAMILY[action.name] ?? null, confidence: action.confidence }; + } + } + const family = top(head.family, embedding); + return { action: null, family: family.name && family.confidence >= head.family.floor ? family.name : null, confidence: family.confidence }; +} + +/** Mean of the token vectors (every token is attended), then L2 normalisation. */ +export function meanPool(hidden: Float32Array, tokens: number, width: number): Float32Array { + const out = new Float32Array(width); + for (let t = 0; t < tokens; t += 1) for (let i = 0; i < width; i += 1) out[i]! += hidden[t * width + i]! / tokens; + const norm = Math.hypot(...out); + for (let i = 0; i < width; i += 1) out[i]! /= norm; + return out; +} + +/** The part of onnxruntime's API the classifier uses; onnxruntime-node and onnxruntime-web both provide it. */ +export type OrtRuntime = { + InferenceSession: { create(model: Uint8Array, options?: Record): Promise }; + Tensor: new (type: "int64", data: BigInt64Array, dims: readonly number[]) => unknown; +}; +export type OrtSession = { + run(feeds: Record): Promise>; + inputNames: readonly string[]; +}; + +export interface WorkClassifier { + readonly id: string; + label(text: string): Promise; +} + +export class WorkModelIntegrityError extends Error {} + +export async function sha256OfBytes(bytes: Uint8Array): Promise { + const digest = await globalThis.crypto.subtle.digest("SHA-256", new Uint8Array(bytes)); + return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join(""); +} + +class OnnxWorkClassifier implements WorkClassifier { + constructor( + readonly id: string, + private readonly ort: OrtRuntime, + private readonly session: OrtSession, + private readonly tokenizer: Unigram, + private readonly head: WorkHead, + ) {} + + async label(text: string): Promise { + if (!text.trim()) return { action: null, family: null, confidence: 0 }; + const ids = BigInt64Array.from(this.tokenizer.encode(this.head.prefix + text, MAX_TOKENS).map(BigInt)); + const dims = [1, ids.length] as const; + const feeds: Record = { + input_ids: new this.ort.Tensor("int64", ids, dims), + attention_mask: new this.ort.Tensor("int64", new BigInt64Array(ids.length).fill(1n), dims), + }; + if (this.session.inputNames.includes("token_type_ids")) feeds.token_type_ids = new this.ort.Tensor("int64", new BigInt64Array(ids.length), dims); + const output = (await this.session.run(feeds)).last_hidden_state; + if (!output || !(output.data instanceof Float32Array)) throw new Error("the work model returned no last_hidden_state"); + return labelEmbedding(this.head, meanPool(output.data, ids.length, output.dims[2]!)); + } +} + +/** + * A classifier from the model and tokenizer bytes. Both are checked against `manifest` (the + * package's own by default) before either is parsed or run, so swapped files are refused. + */ +export async function createWorkClassifier( + files: { model: Uint8Array; tokenizer: Uint8Array }, + ort: OrtRuntime, + options: { manifest?: WorkModelManifest; head?: WorkHead; threads?: number } = {}, +): Promise { + const pinned = options.manifest ?? MANIFEST; + if ((await sha256OfBytes(files.model)) !== pinned.model.sha256) throw new WorkModelIntegrityError("work model file does not match its manifest"); + if ((await sha256OfBytes(files.tokenizer)) !== pinned.tokenizer.sha256) throw new WorkModelIntegrityError("work model tokenizer does not match its manifest"); + const tokenizer = unigramFromTokenizerJson(JSON.parse(new TextDecoder().decode(files.tokenizer))); + const session = await ort.InferenceSession.create(files.model, { + executionProviders: ["cpu"], + // Basic only: exact, so the embeddings are the ones the head was trained on (train.py does the same). + graphOptimizationLevel: "basic", + intraOpNumThreads: options.threads ?? 1, + interOpNumThreads: 1, + }); + return new OnnxWorkClassifier(`${pinned.id}@${pinned.revision.slice(0, 8)}`, ort, session, tokenizer, options.head ?? WORK_HEAD); +} diff --git a/packages/work-labeller/src/download.ts b/packages/work-labeller/src/download.ts new file mode 100644 index 0000000000..f61a876a69 --- /dev/null +++ b/packages/work-labeller/src/download.ts @@ -0,0 +1,205 @@ +/* + * Download on first use: puts the files MANIFEST pins into a cache folder, verified, without ever + * holding the model in memory. For apps that do not bundle the model (Office); Cowork bundles it. + * + * Each file is streamed to `.partial` and hashed as it is written. A partial left by an earlier + * attempt is resumed with a byte range, and its bytes are hashed again first, so a resumed file is + * verified end to end like a fresh one. A file is renamed into place only when its SHA-256 matches; + * a mismatch deletes the partial, so a bad range cannot be resumed forever. Nothing here trusts the + * network: the release URL is just where the bytes come from. + */ +import { createHash } from "node:crypto"; +import { createReadStream, createWriteStream, existsSync, statfsSync } from "node:fs"; +import { mkdir, readdir, rename, rm, stat } from "node:fs/promises"; +import { join } from "node:path"; + +import { MANIFEST, type WorkModelManifest } from "./classifier.js"; + +/** Free space required before a download starts: the files, plus room for the OS and the app. */ +export const MIN_FREE_BYTES = 600 * 1024 * 1024; + +export type DownloadProgress = { file: string; received: number; total: number | null }; + +export type EnsureOptions = { + manifest?: WorkModelManifest; + fetch?: (input: string, init?: RequestInit) => Promise; + onProgress?: (progress: DownloadProgress) => void; + /** Bytes free on the cache's volume; defaults to statfs. */ + freeBytes?: (directory: string) => number; + signal?: AbortSignal; +}; + +export class WorkModelDownloadError extends Error {} + +/** The folder a revision's files live in, under the app's cache root. */ +export function modelDirectory(cacheRoot: string, manifest: WorkModelManifest = MANIFEST): string { + return join(cacheRoot, manifest.revision); +} + +async function hashFile(path: string): Promise { + const hash = createHash("sha256"); + for await (const chunk of createReadStream(path)) hash.update(chunk); + return hash.digest("hex"); +} + +/** Whether every pinned file is in `directory` and hashes to the manifest. */ +export async function modelPresent(directory: string, manifest: WorkModelManifest = MANIFEST): Promise { + for (const entry of [manifest.model, manifest.tokenizer]) { + const path = join(directory, entry.file); + if (!existsSync(path) || (await hashFile(path)) !== entry.sha256) return false; + } + return true; +} + +const defaultFreeBytes = (directory: string): number => { + const stats = statfsSync(directory); + return stats.bavail * stats.bsize; +}; + +async function downloadOne(directory: string, entry: WorkModelManifest["model"], options: EnsureOptions): Promise { + const target = join(directory, entry.file); + if (existsSync(target) && (await hashFile(target)) === entry.sha256) return; + const partial = `${target}.partial`; + const offset = existsSync(partial) ? (await stat(partial)).size : 0; + const response = await (options.fetch ?? fetch)(entry.url, { + redirect: "follow", + headers: offset ? { Range: `bytes=${offset}-` } : {}, + ...(options.signal ? { signal: options.signal } : {}), + }); + if (!response.ok || !response.body) throw new WorkModelDownloadError(`${entry.url} answered ${response.status}`); + // 206 continues the partial; anything else is the whole file, so it starts again. + const resumed = offset > 0 && response.status === 206; + const hash = createHash("sha256"); + if (resumed) for await (const chunk of createReadStream(partial)) hash.update(chunk); + await stream(response, partial, hash, resumed ? offset : 0, entry, options); + const digest = hash.digest("hex"); + if (digest !== entry.sha256) { + await rm(partial, { force: true }); + throw new WorkModelDownloadError(`${entry.file} does not match the pinned SHA-256 (expected ${entry.sha256}, got ${digest})`); + } + await rename(partial, target); +} + +async function stream( + response: Response, + partial: string, + hash: ReturnType, + offset: number, + entry: WorkModelManifest["model"], + options: EnsureOptions, +): Promise { + const length = Number(response.headers.get("content-length")); + const total = Number.isFinite(length) && length > 0 ? offset + length : null; + const out = createWriteStream(partial, { flags: offset ? "a" : "w" }); + let received = offset; + try { + const body = response.body; + if (!body) throw new WorkModelDownloadError(`${entry.url} sent no body`); + const reader = body.getReader(); + for (let read = await reader.read(); !read.done; read = await reader.read()) { + const chunk = read.value; + hash.update(chunk); + received += chunk.length; + if (!out.write(chunk)) await new Promise((resolve) => out.once("drain", () => resolve())); + options.onProgress?.({ file: entry.file, received, total }); + } + } finally { + await new Promise((resolve, reject) => out.end((error?: Error | null) => (error ? reject(error) : resolve()))); + } +} + +/** + * Makes the pinned model present and verified under `cacheRoot`, downloading what is missing, and + * removes the folders of other revisions. Returns the folder to load it from. Throws on too little + * space, a refused or broken download, or bytes that do not match; the caller retries later. + */ +export async function ensureWorkModel(cacheRoot: string, options: EnsureOptions = {}): Promise { + const manifest = options.manifest ?? MANIFEST; + const directory = modelDirectory(cacheRoot, manifest); + await mkdir(directory, { recursive: true }); + if (await modelPresent(directory, manifest)) return directory; + const free = (options.freeBytes ?? defaultFreeBytes)(directory); + if (free < MIN_FREE_BYTES) { + throw new WorkModelDownloadError(`only ${Math.floor(free / 1024 / 1024)} MB free; the work model needs ${MIN_FREE_BYTES / 1024 / 1024} MB`); + } + for (const entry of [manifest.tokenizer, manifest.model]) await downloadOne(directory, entry, options); + for (const name of await readdir(cacheRoot)) { + if (name !== manifest.revision) await rm(join(cacheRoot, name), { recursive: true, force: true }); + } + return directory; +} + +export type WorkModelState = + | { state: "absent" } + | { state: "downloading"; received: number; total: number | null } + | { state: "ready"; directory: string } + | { state: "failed"; reason: string; retryAt: number }; + +const RETRY_MS = [60_000, 5 * 60_000, 30 * 60_000, 2 * 60 * 60_000]; + +/** + * Fetches the model in the background, once, when the app asks: after a chat has finished, never at + * start-up or while one streams. A failure is retried on the next request after a growing wait + * (1 min, 5 min, 30 min, then every 2 h), and never surfaces as an error in a chat. `state()` is + * what Settings shows. + */ +export class WorkModelFetcher { + private current: WorkModelState = { state: "absent" }; + private running: Promise | null = null; + private failures = 0; + private readonly listeners = new Set<(state: WorkModelState) => void>(); + + constructor( + private readonly cacheRoot: string, + private readonly options: EnsureOptions & { now?: () => number } = {}, + ) {} + + state(): WorkModelState { + return this.current; + } + + onChange(listener: (state: WorkModelState) => void): () => void { + this.listeners.add(listener); + return () => this.listeners.delete(listener); + } + + private set(state: WorkModelState): void { + this.current = state; + for (const listener of this.listeners) listener(state); + } + + /** The folder when the model is ready; otherwise starts or continues fetching it and returns null. */ + request(): Promise { + if (this.current.state === "ready") return Promise.resolve(this.current.directory); + const now = (this.options.now ?? Date.now)(); + if (this.current.state === "failed" && now < this.current.retryAt) return Promise.resolve(null); + this.running ??= this.run().finally(() => { + this.running = null; + }); + return this.running; + } + + private async run(): Promise { + this.set({ state: "downloading", received: 0, total: null }); + const totals = new Map(); + try { + const directory = await ensureWorkModel(this.cacheRoot, { + ...this.options, + onProgress: (progress) => { + totals.set(progress.file, progress.received); + const received = [...totals.values()].reduce((sum, value) => sum + value, 0); + this.set({ state: "downloading", received, total: progress.total }); + this.options.onProgress?.(progress); + }, + }); + this.failures = 0; + this.set({ state: "ready", directory }); + return directory; + } catch (error) { + const wait = RETRY_MS[Math.min(this.failures, RETRY_MS.length - 1)]!; + this.failures += 1; + this.set({ state: "failed", reason: error instanceof Error ? error.message : String(error), retryAt: (this.options.now ?? Date.now)() + wait }); + return null; + } + } +} diff --git a/packages/work-labeller/src/facts.ts b/packages/work-labeller/src/facts.ts new file mode 100644 index 0000000000..ae5f6007bc --- /dev/null +++ b/packages/work-labeller/src/facts.ts @@ -0,0 +1,77 @@ +/* + * What a session recorder keeps from an app's agent events: counts, flags and times, never text. + * + * Each app reduces its own events to these facts (Cowork: engine bus events, in its OpenCode plugin; + * Office: AgentLoop callbacks; Design: its chat and editor events). Where something written decides a + * flag, such as a command that runs tests, the app computes the flag and only the boolean is a fact. + */ + +export type Fact = + | { kind: "session"; sessionID: string; parentID: string | null; at: number } + | { kind: "user-turn"; sessionID: string; messageID: string; at: number; attachedSource: boolean } + | { kind: "assistant-done"; sessionID: string; messageID: string; at: number } + | { kind: "tool"; sessionID: string; callID: string; at: number; status: "running" | "completed" | "error"; effect: ToolEffect } + | { kind: "permission"; sessionID: string; at: number; asked: boolean; reply: "once" | "always" | "reject" | null } + | { kind: "busy"; sessionID: string; at: number; busy: boolean } + | { kind: "aborted"; sessionID: string; at: number } + | { kind: "idle"; sessionID: string; at: number }; + +/** What a tool call did, as far as the labels care. */ +export type ToolEffect = "artifact" | "checks" | "delegates" | "sends" | "reads" | "other"; + +const isRecord = (value: unknown): value is Record => + typeof value === "object" && value !== null && !Array.isArray(value); +const str = (value: unknown): string | null => (typeof value === "string" && value ? value : null); +const num = (value: unknown): number | null => (typeof value === "number" && Number.isFinite(value) ? value : null); +const field = (value: unknown, key: string): unknown => (isRecord(value) ? value[key] : undefined); + +const EFFECTS: readonly ToolEffect[] = ["artifact", "checks", "delegates", "sends", "reads", "other"]; + +/** + * A fact as a recorder receives it from another process, checked field by field. Anything else in the object is + * dropped, so the shape is the only thing that can be stored, whatever a caller sends. + */ +export function parseFact(value: unknown): Fact | null { + const kind = str(field(value, "kind")); + const sessionID = str(field(value, "sessionID")); + const at = num(field(value, "at")); + if (!kind || !sessionID || at === null) return null; + switch (kind) { + case "session": { + const parentID = field(value, "parentID"); + return { kind, sessionID, at, parentID: typeof parentID === "string" && parentID ? parentID : null }; + } + case "user-turn": { + const messageID = str(field(value, "messageID")); + return messageID ? { kind, sessionID, at, messageID, attachedSource: field(value, "attachedSource") === true } : null; + } + case "assistant-done": { + const messageID = str(field(value, "messageID")); + return messageID ? { kind, sessionID, at, messageID } : null; + } + case "tool": { + const callID = str(field(value, "callID")); + const status = field(value, "status"); + const effect = EFFECTS.find((e) => e === field(value, "effect")); + if (!callID || !effect || (status !== "running" && status !== "completed" && status !== "error")) return null; + return { kind, sessionID, at, callID, status, effect }; + } + case "permission": { + const reply = field(value, "reply"); + return { + kind, + sessionID, + at, + asked: field(value, "asked") === true, + reply: reply === "once" || reply === "always" || reply === "reject" ? reply : null, + }; + } + case "busy": + return { kind, sessionID, at, busy: field(value, "busy") === true }; + case "aborted": + case "idle": + return { kind, sessionID, at }; + default: + return null; + } +} diff --git a/packages/work-labeller/src/index.ts b/packages/work-labeller/src/index.ts new file mode 100644 index 0000000000..c5975b04ed --- /dev/null +++ b/packages/work-labeller/src/index.ts @@ -0,0 +1,28 @@ +/* + * @redrob-labs/work-labeller: labels an AI work session on the person's machine for the Redrob + * Console's insights, the same way in Redrob Cowork, Office and Design. Only labels leave the machine. + * + * Runtime-neutral: no filesystem and no node:crypto. `./node` adds reading the model from a folder. + */ +export { + createWorkClassifier, + labelEmbedding, + MANIFEST, + meanPool, + sha256OfBytes, + WORK_FAMILIES, + WORK_HEAD, + WorkModelIntegrityError, +} from "./classifier.js"; +export type { OrtRuntime, OrtSession, WorkClassifier, WorkFamily, WorkHead, WorkLabel, WorkModelManifest } from "./classifier.js"; +export { parseFact } from "./facts.js"; +export type { Fact, ToolEffect } from "./facts.js"; +export { externalIdOf, labelSession, modeOf } from "./labeler.js"; +export type { LabeledSession, LabelingApp, SessionTally } from "./labeler.js"; +export { SessionRecorder } from "./recorder.js"; +export { sha256Hex } from "./sha256.js"; +export { syncOutbox } from "./sync.js"; +export type { SessionOutbox, SyncDeps, SyncOutcome } from "./sync.js"; +export { Unigram, unigramFromTokenizerJson } from "./unigram.js"; +export type { UnigramOptions, UnigramPiece } from "./unigram.js"; +export { ACTION_FAMILY, taskKey, WORK_ACTIONS, WORK_TASKS } from "./vocabulary.js"; diff --git a/packages/work-labeller/src/labeler.ts b/packages/work-labeller/src/labeler.ts new file mode 100644 index 0000000000..6c47c49fe3 --- /dev/null +++ b/packages/work-labeller/src/labeler.ts @@ -0,0 +1,169 @@ +/* + * Structural labels for one finished session: mode, outcome, craft flags that can be seen without + * reading anything, and the agent figures. Pure, so every rule is a test away. + * + * The kind of work and its family come from the work classifier, which reads the first message on + * this machine (classifier.ts); only the labels are kept. When it is unsure of the kind of work it + * may still name the family alone. What it cannot tell yet is left out: the task within a kind of + * work, whether the first message said what done looks like, and whether a session without a file + * was a draft or an answer. So a session that only wrote + * text in the chat is labeled as an answer (Look up or Learn), which undercounts drafts; it never + * overcounts them. + */ +import type { WorkFamily } from "./classifier.js"; +import { sha256Hex } from "./sha256.js"; + +/** + * Which app is labeling, as the console knows it. A change of rules or model is a new + * `labelerVersion`, so the console can show the boundary. + */ +export type LabelingApp = { + /** A labeling tool of console `insights/reference.ts`: cowork, office, design. */ + toolKey: string; + /** Starts every external id, so two apps never share one: `cw_`, `of_`, `dz_`. */ + idPrefix: string; + labelerId: string; + labelerVersion: string; +}; + +/** What the recorder accumulated for a session and every subagent session under it. */ +export type SessionTally = { + rootSessionID: string; + startedAt: number; + lastActivityAt: number; + userTurns: number; + /** The first message attached a file or pointed at one. */ + firstAttachedSource: boolean; + assistantMessages: number; + toolCalls: number; + artifacts: number; + checks: number; + sends: number; + delegations: number; + /** Most delegated subagents running at the same moment. */ + peakConcurrentAgents: number; + /** Minutes subagents spent running, all added up. */ + subagentMinutes: number; + /** Minutes the root agent spent running. */ + busyMinutes: number; + /** Minutes between an answer and the person's next message, each gap capped. */ + attentionMinutes: number; + permissionsAsked: number; + permissionsAlways: number; + aborted: number; + /** A message from the person within two messages after an abort: the run was redirected. */ + redirected: number; + /** Sends to the model that carried something sensitive, from the privacy gate. */ + sensitiveSends: number; + /** Of those, sends where something sensitive went out unmasked at the chat's level. */ + unmaskedSends: number; + /** The work classifier's kind of work for the first message; absent when it named none or did not run. */ + action?: string | null; + /** Its family: the kind of work's, or the classifier's alone when it was unsure of the kind. */ + family?: WorkFamily | null; +}; + +export type LabeledSession = { + externalId: string; + startedAt: string; + toolKey: string; + mode: number; + producedOutput: boolean; + brief: boolean; + context: boolean; + checked: boolean; + steerApplicable: boolean; + steered: boolean; + outward: boolean; + sensitiveTouched: boolean; + sensitiveOk: boolean; + turns: number; + familyKey?: WorkFamily; + actionKey?: string; + agent?: { + actions: number; + instructions: number; + agentMinutes: number; + attentionMinutes: number; + autoApproved: boolean; + interrupted: boolean; + agentsAtOnce: number; + humanEquivHours: number; + }; + labelerId: string; + labelerVersion: string; +}; + +/** + * The id the console knows a session by, and the value of x-redrob-session on its requests. A hash, + * so the engine's own session id never leaves the machine; the same for the recorder and the plugin. + */ +export function externalIdOf(app: Pick, rootSessionID: string): string { + return `${app.idPrefix}${sha256Hex(rootSessionID).slice(0, 32)}`; +} + +/** Tool calls per message from the person above which the agent did the work, not the person. */ +const DELEGATED_STEPS_PER_TURN = 6; + +/** + * The mode, by Crew's definitions: + * 5 Orchestrate: two or more agents at once. + * 4 Delegate: one agent did the whole task, either a delegated subagent or the agent taking many + * steps on its own for each message, ending in something produced. + * 3 Iterate: something produced over three or more messages. + * 2 Draft: something produced in one or two messages. + * 1 Learn: nothing produced, but a back and forth. + * 0 Look up: one question, nothing produced. + */ +export function modeOf(t: SessionTally): number { + const produced = t.artifacts > 0 || t.sends > 0; + if (t.peakConcurrentAgents >= 2) return 5; + const autonomous = produced && t.userTurns > 0 && t.toolCalls / t.userTurns >= DELEGATED_STEPS_PER_TURN; + if ((t.delegations > 0 && produced) || autonomous) return 4; + if (produced) return t.userTurns >= 3 ? 3 : 2; + return t.userTurns >= 2 ? 1 : 0; +} + +const round2 = (value: number) => Math.round(value * 100) / 100; + +export function labelSession(app: LabelingApp, t: SessionTally): LabeledSession { + const mode = modeOf(t); + const producedOutput = t.artifacts > 0 || t.sends > 0; + const agent = mode >= 4; + return { + externalId: externalIdOf(app, t.rootSessionID), + startedAt: new Date(t.startedAt).toISOString().replace(/\.\d+Z$/, "Z"), + toolKey: app.toolKey, + mode, + producedOutput, + // Needs the classifier, which reads the first message on this machine. + brief: false, + context: t.firstAttachedSource, + checked: t.checks > 0, + steerApplicable: t.aborted > 0 || (mode >= 3 && t.userTurns >= 3), + steered: t.redirected > 0, + outward: t.sends > 0, + sensitiveTouched: t.sensitiveSends > 0, + sensitiveOk: t.sensitiveSends > 0 && t.unmaskedSends === 0, + turns: t.userTurns, + ...(t.family ? { familyKey: t.family } : {}), + ...(t.action ? { actionKey: t.action } : {}), + ...(agent + ? { + agent: { + actions: t.toolCalls, + instructions: Math.max(1, t.userTurns), + agentMinutes: round2(Math.min(100_000, t.subagentMinutes + t.busyMinutes)), + attentionMinutes: round2(Math.min(100_000, t.attentionMinutes)), + autoApproved: t.permissionsAsked === 0 || t.permissionsAlways > 0, + interrupted: t.aborted > 0, + agentsAtOnce: Math.min(64, Math.max(1, t.peakConcurrentAgents)), + // Crew's "work done by agents" needs the kind of work's baseline; the console estimates it. + humanEquivHours: 0, + }, + } + : {}), + labelerId: app.labelerId, + labelerVersion: app.labelerVersion, + }; +} diff --git a/packages/work-labeller/src/manifest.json b/packages/work-labeller/src/manifest.json new file mode 100644 index 0000000000..2e486fb474 --- /dev/null +++ b/packages/work-labeller/src/manifest.json @@ -0,0 +1,15 @@ +{ + "id": "Xenova/multilingual-e5-base", + "revision": "1ec9243030a27d1a115d5c340572074c125b58b2", + "license": "MIT", + "model": { + "file": "model_int8.onnx", + "sha256": "9ddfd8b45086dabc59a7e1bb00463225dace8954962418b240840f2153bc87da", + "url": "https://github.com/redrob-labs/redrob-cowork/releases/download/insights-model-e5-base-2026.10/model_int8.onnx" + }, + "tokenizer": { + "file": "tokenizer.json", + "sha256": "62c24cdc13d4c9952d63718d6c9fa4c287974249e16b7ade6d5a85e7bbb75626", + "url": "https://github.com/redrob-labs/redrob-cowork/releases/download/insights-model-e5-base-2026.10/tokenizer.json" + } +} diff --git a/packages/work-labeller/src/node.ts b/packages/work-labeller/src/node.ts new file mode 100644 index 0000000000..29daec24b9 --- /dev/null +++ b/packages/work-labeller/src/node.ts @@ -0,0 +1,116 @@ +/* + * The work classifier in Node and Electron: the model read from a folder, and the one classifier per + * process, loaded on first use. The folder is only where to look; the files must hash to MANIFEST. + */ +import { existsSync } from "node:fs"; +import { readFile } from "node:fs/promises"; +import { join } from "node:path"; + +import { + createWorkClassifier, + MANIFEST, + WorkModelIntegrityError, + type OrtRuntime, + type WorkClassifier, + type WorkHead, + type WorkLabel, + type WorkModelManifest, +} from "./classifier.js"; + +export * from "./index.js"; +export { ensureWorkModel, MIN_FREE_BYTES, modelDirectory, modelPresent, WorkModelDownloadError, WorkModelFetcher } from "./download.js"; +export type { DownloadProgress, EnsureOptions, WorkModelState } from "./download.js"; + +export async function loadWorkClassifier( + directory: string, + ort: OrtRuntime, + options: { manifest?: WorkModelManifest; head?: WorkHead; threads?: number } = {}, +): Promise { + const pinned = options.manifest ?? MANIFEST; + const [model, tokenizer] = await Promise.all([ + readFile(join(directory, pinned.model.file)), + readFile(join(directory, pinned.tokenizer.file)), + ]); + return createWorkClassifier({ model: new Uint8Array(model), tokenizer: new Uint8Array(tokenizer) }, ort, options); +} + +export type WorkClassifierStatus = + | { state: "ready"; model: string } + | { state: "not-loaded" } + | { state: "absent"; reason: string } + | { state: "failed"; reason: string }; + +/** + * The one work classifier per process, loaded on first use. Without a model, or in a runtime that + * cannot load it, sessions are labeled without a kind of work and `status()` says why; never throws. + */ +export class WorkClassifierSource { + private loading: Promise | null = null; + private current: WorkClassifierStatus; + + constructor( + private readonly options: { + directory: string | null; + manifest?: WorkModelManifest; + loadRuntime?: () => Promise; + load?: typeof loadWorkClassifier; + }, + ) { + const { directory } = options; + const model = (options.manifest ?? MANIFEST).model.file; + if (!directory) this.current = { state: "absent", reason: "no work model is installed" }; + else if (!existsSync(join(directory, model))) this.current = { state: "absent", reason: "the work model folder has no model" }; + else this.current = { state: "not-loaded" }; + } + + status(): WorkClassifierStatus { + return this.current; + } + + get(): Promise { + if (this.current.state === "absent" || this.current.state === "failed") return Promise.resolve(null); + this.loading ??= this.load(); + return this.loading; + } + + /** The labels for a message, or null when there is no model or it fails. */ + async label(text: string): Promise { + const classifier = await this.get(); + if (!classifier) return null; + try { + return await classifier.label(text); + } catch (error) { + this.current = { state: "failed", reason: `the work model failed: ${error instanceof Error ? error.message : String(error)}` }; + return null; + } + } + + private async load(): Promise { + const { directory, manifest } = this.options; + if (!directory) return null; + try { + const ort = await (this.options.loadRuntime ?? loadOnnxRuntimeNode)(); + const classifier = await (this.options.load ?? loadWorkClassifier)(directory, ort, manifest ? { manifest } : {}); + this.current = { state: "ready", model: classifier.id }; + return classifier; + } catch (error) { + const reason = + error instanceof WorkModelIntegrityError + ? `the work model failed its integrity check: ${error.message}` + : `the work model could not be loaded: ${error instanceof Error ? error.message : String(error)}`; + this.current = { state: "failed", reason }; + return null; + } + } +} + +async function loadOnnxRuntimeNode(): Promise { + const ort: { default?: unknown } & Record = await import("onnxruntime-node"); + const runtime = ort.default ?? ort; + if (!isOrtRuntime(runtime)) throw new Error("onnxruntime-node has no InferenceSession"); + return runtime; +} + +function isOrtRuntime(value: unknown): value is OrtRuntime { + return typeof value === "object" && value !== null && "InferenceSession" in value && "Tensor" in value; +} diff --git a/packages/work-labeller/src/recorder.ts b/packages/work-labeller/src/recorder.ts new file mode 100644 index 0000000000..6bb7136b90 --- /dev/null +++ b/packages/work-labeller/src/recorder.ts @@ -0,0 +1,242 @@ +/* + * Folds engine facts into one tally per session, and hands each finished session to the outbox. + * + * A subagent runs in a session of its own, created with the session that started it as its parent. + * Its facts are folded into that root session, which is the one the person sees and the one the + * console counts: a run that started three subagents is one orchestrated session, not four. + * + * A session is finished when it has been quiet for `closeAfterMs` and nothing in it is running. The + * tallies are held in memory only: after a restart a session in progress starts a new tally, which + * loses part of that one session and nothing else. + */ +import type { WorkLabel } from "./classifier.js"; +import type { Fact } from "./facts.js"; +import { labelSession, type LabeledSession, type LabelingApp, type SessionTally } from "./labeler.js"; + +const MINUTE = 60_000; +/** A gap longer than this between an answer and the next message is the person away, not reading. */ +const ATTENTION_CAP_MS = 10 * MINUTE; +const MAX_SESSIONS = 500; + +type Live = { + tally: SessionTally; + userMessages: Set; + firstUserMessage: string | null; + /** The first message went to the work classifier. */ + workRead: boolean; + toolCalls: Set; + delegations: Set; + lastAnswerAt: number | null; + /** Sessions in this tree running now, with when each started. */ + busySince: Map; + /** An abort waiting for the person's next message. */ + pendingRedirect: boolean; +}; + +export class SessionRecorder { + private readonly roots = new Map(); + private readonly live = new Map(); + + constructor( + private readonly app: LabelingApp, + private readonly onFinished: (session: LabeledSession) => void | Promise, + private readonly closeAfterMs = 15 * MINUTE, + ) {} + + private rootOf(sessionID: string): string { + let current = sessionID; + for (let depth = 0; depth < 16; depth += 1) { + const parent = this.roots.get(current); + if (!parent || parent === current) return current; + current = parent; + } + return current; + } + + private entry(root: string, at: number): Live { + let found = this.live.get(root); + if (!found) { + found = { + tally: { + rootSessionID: root, + startedAt: at, + lastActivityAt: at, + userTurns: 0, + firstAttachedSource: false, + assistantMessages: 0, + toolCalls: 0, + artifacts: 0, + checks: 0, + sends: 0, + delegations: 0, + peakConcurrentAgents: 0, + subagentMinutes: 0, + busyMinutes: 0, + attentionMinutes: 0, + permissionsAsked: 0, + permissionsAlways: 0, + aborted: 0, + redirected: 0, + sensitiveSends: 0, + unmaskedSends: 0, + }, + userMessages: new Set(), + firstUserMessage: null, + workRead: false, + toolCalls: new Set(), + delegations: new Set(), + lastAnswerAt: null, + busySince: new Map(), + pendingRedirect: false, + }; + this.live.set(root, found); + while (this.live.size > MAX_SESSIONS) { + const oldest = this.live.keys().next(); + if (oldest.done) break; + this.live.delete(oldest.value); + } + } + return found; + } + + observe(fact: Fact): void { + if (fact.kind === "session") { + if (fact.parentID) this.roots.set(fact.sessionID, fact.parentID); + return; + } + const root = this.rootOf(fact.sessionID); + const isRoot = root === fact.sessionID; + const live = this.entry(root, fact.at); + const t = live.tally; + t.lastActivityAt = Math.max(t.lastActivityAt, fact.at); + + switch (fact.kind) { + case "user-turn": { + // Messages inside a subagent are the agent instructing itself, not the person. + if (!isRoot) return; + if (!live.userMessages.has(fact.messageID)) { + live.userMessages.add(fact.messageID); + live.firstUserMessage ??= fact.messageID; + t.userTurns += 1; + if (t.userTurns === 1) t.startedAt = Math.min(t.startedAt, fact.at); + if (live.lastAnswerAt !== null) { + t.attentionMinutes += Math.min(ATTENTION_CAP_MS, Math.max(0, fact.at - live.lastAnswerAt)) / MINUTE; + } + if (live.pendingRedirect) { + t.redirected += 1; + live.pendingRedirect = false; + } + } + if (fact.attachedSource && fact.messageID === live.firstUserMessage) t.firstAttachedSource = true; + return; + } + case "assistant-done": + if (isRoot) { + t.assistantMessages += 1; + live.lastAnswerAt = fact.at; + } + return; + case "tool": { + if (fact.status === "running") { + if (fact.effect === "delegates" && !live.delegations.has(fact.callID)) { + live.delegations.add(fact.callID); + t.delegations += 1; + } + return; + } + if (live.toolCalls.has(fact.callID)) return; + live.toolCalls.add(fact.callID); + t.toolCalls += 1; + if (fact.status !== "completed") return; + if (fact.effect === "artifact") t.artifacts += 1; + if (fact.effect === "checks") t.checks += 1; + if (fact.effect === "sends") t.sends += 1; + if (fact.effect === "delegates" && !live.delegations.has(fact.callID)) { + live.delegations.add(fact.callID); + t.delegations += 1; + } + return; + } + case "permission": + if (fact.asked) t.permissionsAsked += 1; + if (fact.reply === "always") t.permissionsAlways += 1; + return; + case "busy": { + const since = live.busySince.get(fact.sessionID); + if (fact.busy) { + if (since === undefined) live.busySince.set(fact.sessionID, fact.at); + const agents = [...live.busySince.keys()].filter((id) => id !== root).length; + t.peakConcurrentAgents = Math.max(t.peakConcurrentAgents, agents); + return; + } + if (since === undefined) return; + live.busySince.delete(fact.sessionID); + const minutes = Math.max(0, fact.at - since) / MINUTE; + if (isRoot) t.busyMinutes += minutes; + else t.subagentMinutes += minutes; + return; + } + case "aborted": + if (isRoot) { + t.aborted += 1; + live.pendingRedirect = true; + } + return; + case "idle": + if (live.busySince.has(fact.sessionID)) { + this.observe({ kind: "busy", sessionID: fact.sessionID, at: fact.at, busy: false }); + } + return; + } + } + + /** + * From the privacy gate, not the engine: the plugin has no way to report this, so a fact sent to + * the facts route can never claim a session was handled safely. + */ + observeSensitivity(sessionID: string, at: number, unmasked: boolean): void { + const root = this.rootOf(sessionID); + const live = this.entry(root, at); + live.tally.sensitiveSends += 1; + if (unmasked) live.tally.unmaskedSends += 1; + } + + /** + * The first message's text, from the plugin, for the work classifier. Only a root session's first + * message is read, once; the text is passed to `label` and not kept, and only the labels are. + * Returns whether it was read. + */ + async observeFirstMessage( + sessionID: string, + messageID: string, + text: string, + label: (text: string) => Promise, + ): Promise { + const live = this.live.get(sessionID); + if (!live || this.rootOf(sessionID) !== sessionID || live.firstUserMessage !== messageID || live.workRead) return false; + live.workRead = true; + const result = await label(text); + live.tally.action = result?.action ?? null; + live.tally.family = result?.family ?? null; + return true; + } + + /** Labels and hands over every session quiet for long enough. Returns how many were finished. */ + async sweep(now: number): Promise { + let finished = 0; + for (const [root, live] of [...this.live]) { + if (live.busySince.size > 0 || now - live.tally.lastActivityAt < this.closeAfterMs) continue; + this.live.delete(root); + // A session the person never wrote in (a subagent whose parent was missed, a restore) is nobody's work. + if (live.tally.userTurns === 0) continue; + await this.onFinished(labelSession(this.app, live.tally)); + finished += 1; + } + return finished; + } + + /** For tests and the status endpoint: sessions being tallied now. */ + liveCount(): number { + return this.live.size; + } +} diff --git a/packages/work-labeller/src/sha256.ts b/packages/work-labeller/src/sha256.ts new file mode 100644 index 0000000000..1ad55ed2fb --- /dev/null +++ b/packages/work-labeller/src/sha256.ts @@ -0,0 +1,49 @@ +/* + * SHA-256 of a short string, synchronously and without node:crypto, so a session's external id can + * be computed the same way in Node, Electron and a webview. Model files are checked with WebCrypto + * or node:crypto instead: this is for ids, not for hundreds of megabytes. + */ + +const K = new Uint32Array([ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, + 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, + 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +]); + +const rotr = (x: number, n: number) => (x >>> n) | (x << (32 - n)); + +export function sha256Hex(text: string): string { + const data = new TextEncoder().encode(text); + const length = Math.ceil((data.length + 9) / 64) * 64; + const bytes = new Uint8Array(length); + bytes.set(data); + bytes[data.length] = 0x80; + const view = new DataView(bytes.buffer); + view.setUint32(length - 8, Math.floor((data.length * 8) / 2 ** 32)); + view.setUint32(length - 4, (data.length * 8) >>> 0); + const h = new Uint32Array([0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]); + const w = new Uint32Array(64); + for (let block = 0; block < length; block += 64) { + for (let i = 0; i < 16; i += 1) w[i] = view.getUint32(block + i * 4); + for (let i = 16; i < 64; i += 1) { + const a = w[i - 15]!; + const b = w[i - 2]!; + const s0 = rotr(a, 7) ^ rotr(a, 18) ^ (a >>> 3); + const s1 = rotr(b, 17) ^ rotr(b, 19) ^ (b >>> 10); + w[i] = (w[i - 16]! + s0 + w[i - 7]! + s1) >>> 0; + } + let [a, b, c, d, e, f, g, k] = [h[0]!, h[1]!, h[2]!, h[3]!, h[4]!, h[5]!, h[6]!, h[7]!]; + for (let i = 0; i < 64; i += 1) { + const t1 = (k + (rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25)) + ((e & f) ^ (~e & g)) + K[i]! + w[i]!) >>> 0; + const t2 = ((rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22)) + ((a & b) ^ (a & c) ^ (b & c))) >>> 0; + [k, g, f, e, d, c, b, a] = [g, f, e, (d + t1) >>> 0, c, b, a, (t1 + t2) >>> 0]; + } + const next = [a, b, c, d, e, f, g, k]; + for (let i = 0; i < 8; i += 1) h[i] = (h[i]! + next[i]!) >>> 0; + } + return Array.from(h, (word) => word.toString(16).padStart(8, "0")).join(""); +} diff --git a/packages/work-labeller/src/sync.ts b/packages/work-labeller/src/sync.ts new file mode 100644 index 0000000000..8004dff458 --- /dev/null +++ b/packages/work-labeller/src/sync.ts @@ -0,0 +1,65 @@ +/* + * Sends finished sessions to the Redrob Console, `POST /insights/sessions`, with the person's + * Redrob Key, in batches of 500. The person and workspace are the key's, so the console counts each + * session as that person's work and nobody else's. + * + * Sessions the console accepted, updated or rejected leave the outbox: a rejection is permanent (an + * old labeler, a label the console no longer accepts) and would only be refused again. Anything that + * got no answer stays for the next run. Each app keeps its own outbox; this needs only list and remove. + */ +import type { LabeledSession } from "./labeler.js"; + +const BATCH = 500; + +export interface SessionOutbox { + list(): Promise>; + remove(externalIds: readonly string[]): Promise; +} + +export type SyncDeps = { + /** The Redrob Key, read when it is needed. Null when there is none. */ + readKey: () => Promise; + fetch: (input: string, init: RequestInit) => Promise; + /** The console's API base, e.g. https://console.redrob.ai/api/backend/v1. */ + baseUrl: string; +}; + +export type SyncOutcome = + | { status: "nothing" | "no-key" } + | { status: "sent"; accepted: number; updated: number; rejected: number } + | { status: "refused"; code: number } + | { status: "unreachable" }; + +type IngestAnswer = { accepted?: unknown; updated?: unknown; rejected?: unknown }; + +const count = (value: unknown): number => (typeof value === "number" && Number.isFinite(value) ? value : 0); + +export async function syncOutbox(outbox: SessionOutbox, deps: SyncDeps): Promise { + const entries = await outbox.list(); + if (!entries.length) return { status: "nothing" }; + const key = await deps.readKey(); + if (!key) return { status: "no-key" }; + const base = deps.baseUrl.replace(/\/+$/, ""); + const totals = { accepted: 0, updated: 0, rejected: 0 }; + for (let start = 0; start < entries.length; start += BATCH) { + const batch = entries.slice(start, start + BATCH).map((entry) => entry.session); + let response: Response; + try { + response = await deps.fetch(`${base}/insights/sessions`, { + method: "POST", + headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" }, + body: JSON.stringify({ sessions: batch }), + signal: AbortSignal.timeout(20_000), + }); + } catch { + return totals.accepted + totals.updated + totals.rejected ? { status: "sent", ...totals } : { status: "unreachable" }; + } + if (!response.ok) return { status: "refused", code: response.status }; + const answer: IngestAnswer = await response.json().catch(() => ({})); + totals.accepted += count(answer.accepted); + totals.updated += count(answer.updated); + totals.rejected += Array.isArray(answer.rejected) ? answer.rejected.length : 0; + await outbox.remove(batch.map((session) => session.externalId)); + } + return { status: "sent", ...totals }; +} diff --git a/packages/work-labeller/src/unigram.ts b/packages/work-labeller/src/unigram.ts new file mode 100644 index 0000000000..424d690ad7 --- /dev/null +++ b/packages/work-labeller/src/unigram.ts @@ -0,0 +1,214 @@ +/* + * The XLM-R SentencePiece tokenizer the work classifier's encoder (multilingual-e5-base) reads, as + * Hugging Face `tokenizers` runs it from tokenizer.json: split out special tokens, the Precompiled + * normalizer (SentencePiece's nmt_nfkc charsmap), then either a whitespace split (e5-base) or runs of + * spaces collapsed (e5-small), Metaspace, Unigram Viterbi, then ` A `. Ids match `tokenizers` exactly (test/fixtures/unigram-parity.json), because + * the head was trained on what that library produced. + */ + +import { z } from "zod"; + +const SPACE = "\u2581"; +/** `tokenizers`' Unigram: an unknown character costs this much below the vocab's lowest score. */ +const UNK_PENALTY = 10; +/** Rust's `char::is_whitespace`, which `tokenizers`' WhitespaceSplit uses; JavaScript's `\s` differs. */ +const WHITESPACE = "[\\t\\n\\v\\f\\r \\u0085\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000]"; + +export type UnigramPiece = { id: number; score: number }; + +export type UnigramOptions = { + pieces: ReadonlyMap; + unkId: number; + /** The lowest score in the whole vocab (a fixture may hold a subset of it). */ + minScore: number; + /** SentencePiece's precompiled_charsmap, or null to skip normalisation. */ + charsmap: Uint8Array | null; + /** Special tokens matched in the raw text, as `tokenizers`' added vocabulary does. */ + specials: ReadonlyMap; + /** Specials that take the whitespace before them (`lstrip`). */ + lstrip?: ReadonlySet; + /** Pre-tokenizer: split on whitespace, then Metaspace each word (e5-base), or Metaspace alone after + * collapsing runs of spaces (e5-small). */ + whitespaceSplit: boolean; + bosId: number; + eosId: number; +}; + +/** SentencePiece's double-array trie over UTF-8 bytes, read as spm_precompiled reads it. */ +class Charsmap { + private readonly units: Uint32Array; + private readonly normalized: Uint8Array; + private readonly decoder = new TextDecoder(); + private readonly encoder = new TextEncoder(); + private readonly graphemes = new Intl.Segmenter(undefined, { granularity: "grapheme" }); + + constructor(bytes: Uint8Array) { + const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + const trieBytes = view.getUint32(0, true); + this.units = new Uint32Array(trieBytes / 4); + for (let i = 0; i < this.units.length; i += 1) this.units[i] = view.getUint32(4 + i * 4, true); + this.normalized = bytes.subarray(4 + trieBytes); + } + + /** The replacement for the shortest charsmap entry `chunk` starts with, as spm_precompiled does. */ + transform(chunk: string): string | null { + const key = this.encoder.encode(chunk); + const units = this.units; + const offset = (unit: number) => (unit >>> 10) << ((unit & (1 << 9)) >>> 6); + let node = offset(units[0]!); + for (const byte of key) { + if (byte === 0) break; + node ^= byte; + const unit = units[node]!; + if ((unit & 0x800000ff) >>> 0 !== byte) return null; + node ^= offset(unit); + if ((unit >>> 8) & 1) { + const start = units[node]! & 0x7fffffff; + let end = start; + while (end < this.normalized.length && this.normalized[end] !== 0) end += 1; + return this.decoder.decode(this.normalized.subarray(start, end)); + } + } + return null; + } + + normalize(text: string): string { + let out = ""; + for (const { segment } of this.graphemes.segment(text)) { + if (this.encoder.encode(segment).length < 6) { + const whole = this.transform(segment); + if (whole !== null) { + out += whole; + continue; + } + } + for (const char of segment) out += this.transform(char) ?? char; + } + return out; + } +} + +export class Unigram { + private readonly charsmap: Charsmap | null; + private readonly longest: number; + private readonly specials: RegExp | null; + + constructor(private readonly options: UnigramOptions) { + this.charsmap = options.charsmap ? new Charsmap(options.charsmap) : null; + let longest = 1; + for (const piece of options.pieces.keys()) longest = Math.max(longest, [...piece].length); + this.longest = longest; + const names = [...options.specials.keys()].sort((a, b) => b.length - a.length); + const pattern = (name: string) => + `${options.lstrip?.has(name) ? `${WHITESPACE}*` : ""}${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`; + this.specials = names.length ? new RegExp(names.map(pattern).join("|"), "g") : null; + } + + /** Token ids with `` and ``, at most `maxLength` of them in all. */ + encode(text: string, maxLength = 512): number[] { + const ids: number[] = []; + let last = 0; + for (const match of this.specials ? text.matchAll(this.specials) : []) { + ids.push(...this.segment(text.slice(last, match.index)), this.options.specials.get(match[0].replace(this.leading, ""))!); + last = match.index + match[0].length; + } + ids.push(...this.segment(text.slice(last))); + return [this.options.bosId, ...ids.slice(0, Math.max(0, maxLength - 2)), this.options.eosId]; + } + + private readonly leading = new RegExp(`^${WHITESPACE}+`); + + private segment(text: string): number[] { + if (!text) return []; + const plain = this.charsmap ? this.charsmap.normalize(text) : text; + if (this.options.whitespaceSplit) { + const ids: number[] = []; + for (const word of plain.split(new RegExp(`${WHITESPACE}+`))) { + if (!word) continue; + const marked = word.startsWith(SPACE) ? word : SPACE + word; + for (const piece of marked.split(new RegExp(`(?=${SPACE})`))) ids.push(...this.viterbi(piece)); + } + return ids; + } + const normalized = plain.replace(/ {2,}/g, " ").replaceAll(" ", SPACE); + if (!normalized) return []; + const marked = normalized.startsWith(SPACE) ? normalized : SPACE + normalized; + const ids: number[] = []; + for (const word of marked.split(new RegExp(`(?=${SPACE})`))) ids.push(...this.viterbi(word)); + return ids; + } + + /** Best-scoring split of one word, ties to the shorter piece first found; unknown runs fused. */ + private viterbi(word: string): number[] { + const chars = [...word]; + const { pieces, unkId, minScore } = this.options; + const best: Array<{ score: number; from: number; id: number } | null> = new Array(chars.length + 1).fill(null); + best[0] = { score: 0, from: -1, id: -1 }; + for (let start = 0; start < chars.length; start += 1) { + const here = best[start]!.score; + let single = false; + let piece = ""; + for (let end = start + 1; end <= Math.min(chars.length, start + this.longest); end += 1) { + piece += chars[end - 1]; + const found = pieces.get(piece); + if (!found) continue; + const score = here + found.score; + const target = best[end]; + if (!target || score > target.score) best[end] = { score, from: start, id: found.id }; + if (end === start + 1) single = true; + } + if (!single) { + const score = here + minScore - UNK_PENALTY; + const target = best[start + 1]; + if (!target || score > target.score) best[start + 1] = { score, from: start, id: unkId }; + } + } + const ids: number[] = []; + for (let at = chars.length; at > 0; at = best[at]!.from) { + const id = best[at]!.id; + if (!(id === unkId && ids[ids.length - 1] === unkId)) ids.push(id); + } + return ids.reverse(); + } +} + +/** Reads the parts of a `tokenizers` tokenizer.json this class needs; refuses any other kind. */ +export function unigramFromTokenizerJson(json: unknown): Unigram { + const parsed = TokenizerJson.parse(json); + const pieces = new Map(); + let minScore = Infinity; + parsed.model.vocab.forEach(([piece, score], id) => { + pieces.set(piece, { id, score }); + minScore = Math.min(minScore, score); + }); + const steps = "normalizers" in parsed.normalizer ? parsed.normalizer.normalizers : [parsed.normalizer]; + const charsmap = steps.find((step) => step.type === "Precompiled")?.precompiled_charsmap; + const special = parsed.added_tokens.filter((token) => token.special); + const specials = new Map(special.map((token) => [token.content, token.id])); + const lstrip = new Set(special.filter((token) => token.lstrip).map((token) => token.content)); + const pre = parsed.pre_tokenizer; + const whitespaceSplit = pre.type === "Sequence" && pre.pretokenizers[0]?.type === "WhitespaceSplit"; + return new Unigram({ + pieces, + unkId: parsed.model.unk_id, + minScore, + charsmap: charsmap ? Uint8Array.from(atob(charsmap), (char) => char.charCodeAt(0)) : null, + specials, + lstrip, + whitespaceSplit, + bosId: specials.get("")!, + eosId: specials.get("")!, + }); +} + +const Step = z.object({ type: z.string(), precompiled_charsmap: z.string().optional() }); +const Metaspace = z.object({ type: z.literal("Metaspace"), replacement: z.literal(SPACE) }); +const TokenizerJson = z.object({ + added_tokens: z.array(z.object({ id: z.number(), content: z.string(), special: z.boolean(), lstrip: z.boolean().optional() })), + normalizer: z.union([z.object({ type: z.literal("Sequence"), normalizers: z.array(Step) }), Step]), + pre_tokenizer: z.union([ + Metaspace, + z.object({ type: z.literal("Sequence"), pretokenizers: z.tuple([z.object({ type: z.literal("WhitespaceSplit") }), Metaspace]) }), + ]), + model: z.object({ type: z.literal("Unigram"), unk_id: z.number(), vocab: z.array(z.tuple([z.string(), z.number()])) }), +}); diff --git a/packages/work-labeller/src/vocabulary.ts b/packages/work-labeller/src/vocabulary.ts new file mode 100644 index 0000000000..0f68aab281 --- /dev/null +++ b/packages/work-labeller/src/vocabulary.ts @@ -0,0 +1,41 @@ +/* + * The kinds of work and tasks a session can be labeled with, as the Redrob Console and Crew name + * them (console `apps/api/src/insights/reference.ts`). Keys only: names and copy live in the console, + * which is what shows them. A label outside this list is refused by the console, so the labeler and + * the evaluation set both check against it. + */ + +export const WORK_TASKS: Readonly> = { + reply: ["refund-request", "bug-report-reply", "how-to-answer", "escalation-response"], + summ: ["ticket-thread-summary", "call-notes", "weekly-account-digest"], + email: ["renewal-note", "cold-first-touch", "demo-follow-up"], + research: ["account-brief", "competitor-scan"], + analyze: ["pipeline-review", "churn-analysis", "forecast-check"], + code: ["new-endpoint", "ui-component", "data-migration"], + fix: ["failing-test", "production-incident"], + review: ["pull-request-review"], + test: ["unit-tests", "end-to-end-tests"], + spec: ["product-spec", "project-plan"], + design: ["ui-mockup", "marketing-visual"], + copy: ["blog-post", "landing-page-copy", "social-post"], + translate: ["korean-and-english-reply", "help-article"], + policy: ["contract-review", "policy-draft"], + hr: ["job-description", "review-summary", "onboarding-plan"], + finance: ["month-end-reconciliation", "invoice-check"], +}; + +export const WORK_ACTIONS = Object.keys(WORK_TASKS); + +/** The family each kind of work belongs to, as console `reference.ts` ACTIONS gives it. */ +export const ACTION_FAMILY: Readonly> = { + reply: "write", summ: "write", email: "write", research: "write", spec: "write", copy: "write", + translate: "write", policy: "write", hr: "write", + analyze: "sheet", finance: "sheet", + code: "code", fix: "code", review: "code", test: "code", + design: "design", +}; + +/** The console's task key: `reply.refund-request`. */ +export function taskKey(action: string, task: string): string { + return `${action}.${task}`; +} diff --git a/packages/work-labeller/src/work-head.json b/packages/work-labeller/src/work-head.json new file mode 100644 index 0000000000..d2a6820f31 --- /dev/null +++ b/packages/work-labeller/src/work-head.json @@ -0,0 +1 @@ +{"encoder": {"repo": "Xenova/multilingual-e5-base", "revision": "1ec9243030a27d1a115d5c340572074c125b58b2", "file": "onnx/model_int8.onnx"}, "prefix": "query: ", "action": {"classes": ["analyze", "code", "copy", "design", "email", "finance", "fix", "hr", "policy", "reply", "research", "review", "spec", "summ", "test", "translate", null], "scale": 20.0, "floor": 0.39, "w": [[0.06635, -0.04484, 0.0693, -0.04321, -0.08268, 0.2076, -0.08879, -0.09234, -0.14538, -0.12074, 0.16799, -0.08433, 0.15735, 0.10185, -0.08391, -0.0287, 0.04448], [0.04549, -0.01767, -0.03702, 0.11717, -0.18999, 0.05329, -0.03949, -0.1253, 0.02473, -0.13207, 0.15135, 0.2286, 0.00449, -0.03039, -0.1962, -0.00891, 0.15193], [-0.08945, -0.06557, -0.05695, -0.09326, -0.00324, -0.0333, 0.12146, -0.05576, -0.12109, 0.0134, 0.02188, 0.02621, 0.0346, 0.14206, -0.00601, 0.09775, 0.06727], [0.0485, 0.15251, -0.10439, 0.06575, 0.02837, -0.15635, -0.00516, 0.09643, 0.02762, -0.18838, -0.23609, -0.06825, 0.15936, -0.02286, 0.13185, 0.01953, 0.05158], [0.00936, -0.07676, 0.00401, -0.00879, -0.02665, 0.01417, -0.11295, 0.02379, 0.09644, -0.01781, 0.11683, -0.12123, -0.19509, 0.18935, 0.04319, 0.05961, 0.00253], [-0.34154, 0.1254, 0.04256, 0.06924, 0.04399, 0.24051, -0.30858, 0.26767, 0.02837, 0.09127, -0.02712, -0.15775, 0.01713, 0.19066, -0.01466, -0.18043, -0.08672], [0.01467, 0.03054, 0.07724, -0.0433, 0.02153, -0.00481, -0.07675, -0.06505, -0.09119, 0.04575, 0.07216, 0.09368, -0.06379, 0.01909, -0.12293, 0.0451, 0.04808], [0.1478, -0.06756, -0.02581, -0.0915, -0.09521, 0.05664, 0.06222, -0.11534, 0.00455, -0.03611, -0.15628, 0.00238, 0.06992, 0.12096, 0.0828, -0.0374, 0.07796], [0.05649, 0.00703, 0.02181, -0.07382, -0.01138, -0.27272, 0.36512, -0.03046, -0.07378, -0.06958, 0.10194, -0.03739, -0.09574, 0.07201, 0.01956, 0.0788, -0.05788], [0.04714, 0.25566, 0.02984, 0.03177, -0.10488, -0.00102, -0.26047, -0.18625, -0.01147, -0.23723, -0.05079, 0.15727, 0.02152, -0.1071, 0.11344, 0.22515, 0.07742], [0.23193, -0.09378, 0.06736, -0.07699, 0.12535, 0.09502, -0.07467, -0.04347, 0.0962, -0.04069, 0.01522, -0.08069, -0.09346, 0.04232, -0.22042, 0.11029, -0.05953], [0.03989, -0.0479, -0.11584, -0.28259, -0.01037, -0.05809, -0.02714, 0.10288, 0.26489, 0.01453, 0.0324, 0.02351, 0.15695, -0.08216, -0.07181, -0.0176, 0.07846], [-0.09827, 0.08616, -0.12056, 0.0328, -0.15401, 0.09021, 0.04543, 0.09425, -0.03753, -0.07942, 0.08166, 0.04402, -0.09289, 0.02097, -0.14812, -0.07501, 0.31032], [0.21511, 0.02152, -0.11179, -0.04836, -0.13614, 0.10624, -0.13084, 0.05355, -0.00477, -0.07095, 0.08067, 0.02322, -0.12221, 0.02241, 0.10011, -0.1504, 0.15262], [-0.02752, -0.04745, 0.01442, 0.10267, 0.00199, -0.08435, -0.01437, 0.0783, -0.0893, 0.08791, 0.04778, 0.00033, -0.03571, 0.06704, -0.12143, -0.04498, 0.06468], [-0.19657, 0.10287, -0.04546, -0.04411, 0.06152, -0.00908, -0.1139, 0.12911, 0.09948, 0.08596, -0.12649, 0.05571, 0.0256, -0.08665, -0.08074, 0.19798, -0.05521], [-0.04308, -0.00434, -0.11998, -0.13563, -0.03891, 0.29181, -0.03922, 0.05559, -0.00059, 0.01791, 0.0767, -0.04102, 0.03694, -0.29051, 0.06633, 0.01068, 0.15732], [0.14095, 0.1402, -0.00873, 0.17324, 0.0079, -0.12152, -0.0617, 0.19172, 0.08729, -0.20549, -0.14813, -0.15676, -0.03106, -0.16475, 0.10684, 0.06106, -0.01106], [0.01959, -0.15863, -0.10282, 0.05849, -0.09674, 0.07736, -0.09222, -0.19633, -1e-05, 0.12229, 0.24129, -0.21071, -0.11455, 0.13739, -0.00157, 0.21423, 0.10295], [-0.09515, -0.12291, -0.09228, 0.04979, -0.04574, 0.06249, -0.04811, -0.03135, 0.09392, 0.09578, 0.07031, -0.03578, 0.09025, 0.00036, 0.09215, 0.06206, -0.14579], [0.00318, -0.00659, 0.17789, 0.05899, 0.11509, -0.13021, -0.00031, -0.14096, 0.07197, -0.13477, 0.23498, -0.11707, -0.12426, 0.08342, 0.00996, -0.06357, -0.03773], [0.07127, -0.05994, 0.13468, -0.07192, -0.07499, -0.0385, 0.05174, -0.00447, -0.05811, 0.00802, 0.01847, -0.01684, 0.04613, -0.0137, -0.02604, 0.0053, 0.0289], [0.23722, 0.08209, -0.08558, -0.12835, 0.25783, 0.17822, -0.13508, -0.26444, -0.05114, -0.11289, 0.14931, -0.04312, 0.11201, -0.14237, 0.01406, -0.03607, -0.0317], [0.09393, -0.00169, 0.01112, -0.11795, 0.00326, 0.08794, -0.09336, 0.17412, -0.01985, -0.17759, 0.03099, 0.01859, -0.05322, -0.01713, 0.00332, -0.07663, 0.13415], [0.00423, 0.00132, 0.01755, 0.01364, 0.09737, -0.10816, -0.02407, -0.0343, 0.05975, -0.11331, -0.24716, 0.13299, 0.06492, 0.1314, -0.00454, -0.01571, 0.02409], [-0.08565, 0.09522, 0.02709, 0.09402, 0.05366, 0.01731, -0.0019, 0.07832, 0.01795, 0.03268, 0.03948, -0.01515, -0.10163, -0.26458, 0.08865, -0.04291, -0.03255], [0.00388, 0.00417, -0.09141, 0.17475, -0.18385, 0.00964, 0.04595, 0.19972, -0.19605, -0.0395, -0.19559, 0.00766, 0.06672, -0.00699, 0.24019, -0.02639, -0.01289], [-0.15848, -0.11247, 0.12341, 0.126, 0.01092, -0.00627, 0.13726, 0.07732, 0.08191, -0.14206, -0.04184, 0.01797, -0.05722, 0.0219, 0.0571, -0.23908, 0.10363], [-0.15606, -0.07349, 0.20233, 0.00274, 0.01967, -0.01114, -0.02592, 0.1112, -0.14389, 0.13695, -0.0861, -0.05961, -0.00816, -0.00532, -0.03626, 0.01744, 0.11561], [-0.05104, -0.0717, 0.25125, 0.01757, 0.24117, 0.04547, -0.20501, -0.01712, 0.03027, -0.08956, -0.03482, -0.06916, 0.26307, -0.04681, -0.03533, -0.00347, -0.22477], [-0.04194, 0.11313, 0.00323, 0.0507, 0.12021, -0.15546, 0.0123, 0.02437, -0.04714, -0.11945, -0.10062, -0.02009, -0.00252, 0.12905, 0.07774, -0.05613, 0.01262], [-0.06283, -0.12939, -0.1516, 0.01593, 0.00906, -0.04978, -0.02827, 0.22822, 0.0702, 0.14388, -0.04584, 0.18578, 0.13641, -0.05675, -0.13132, -0.26931, 0.13561], [0.00539, 0.25609, -0.05704, -0.02995, -0.02597, 0.19513, -0.12382, 0.18781, -0.21492, -0.03014, -0.02528, -0.17016, 0.08948, -0.05871, -0.01398, -0.01166, 0.02774], [0.01019, 0.04759, -0.14806, -0.06687, -0.06837, 0.13788, 0.00238, -0.23173, 0.10132, 0.18541, 0.07951, -0.01997, 0.07051, -0.1924, 0.23212, 0.02625, -0.16575], [0.08397, 0.08407, 0.05533, -0.00861, -0.0908, 0.11898, 0.00265, -0.13129, -0.07075, -0.08043, -0.10851, 0.18301, -0.05167, -0.02541, 0.11186, -0.02404, -0.04835], [0.18999, -0.07018, 0.09466, 0.23461, -0.03285, -0.15713, -0.10713, 0.09682, 0.03621, 0.03087, 0.15936, -0.26078, -0.0217, -0.1283, 0.095, -0.1621, 0.00265], [-0.00869, -0.14095, 0.17479, 0.265, -0.05422, -0.19999, 0.00509, 0.11262, -0.05574, -0.08632, 0.00963, -0.00949, -0.04451, 0.05759, -0.01844, 0.06868, -0.07506], [-0.07188, -0.0089, -0.12823, -0.06081, 0.137, 0.00661, -0.17301, -0.0138, 0.09602, -0.1158, 0.12201, 0.03389, 0.06615, -0.07683, 0.07228, -0.00653, 0.12184], [-0.2609, 0.10236, 0.03543, -0.18057, 0.02355, -0.04531, 0.02394, -0.1284, 0.06151, 0.05625, -0.0492, 0.00916, -0.16383, 0.06356, 0.08832, 0.15607, 0.20805], [-0.01028, -0.12774, 0.04136, -0.07772, 0.07477, 0.08115, -0.21739, 0.06847, 0.13265, 0.01915, 0.07507, 0.02859, 0.0254, -0.08886, -0.13946, 0.10053, 0.01432], [0.05437, 0.06429, -0.19242, -0.05089, -0.08375, -0.14349, 0.1434, 0.19163, 0.01283, 0.09267, 0.06169, 0.232, -0.00583, -0.17166, 0.09551, -0.04089, -0.25946], [0.03294, -0.0058, 0.07821, 0.19488, -0.11493, 0.00331, 0.0348, -0.3866, -0.03189, 0.26828, 0.06007, 0.20266, -0.2248, 0.04968, 0.01494, -0.07499, -0.10078], [0.07592, 0.04369, -0.11489, 0.1454, 0.02035, -0.09918, 0.01813, -0.12971, 0.07483, 0.07224, 0.03902, 0.12677, -0.05822, -0.10887, 0.00078, -0.27174, 0.16547], [-0.26104, -0.04998, 0.0374, 0.15418, 0.09914, 0.1671, -0.04035, -0.04844, 0.03193, 0.03556, 0.0704, 0.16306, 0.00019, -0.08407, -0.03609, 0.07206, -0.31105], [0.03863, 0.15704, -0.0682, 0.12481, 0.15833, -0.01994, 0.07302, -0.20886, -0.0093, 0.13356, -0.19252, -0.18807, 0.02048, 0.05625, -0.05329, 0.18071, -0.20265], [0.03046, 0.08057, 0.04635, -0.00638, 0.08049, -0.09707, 0.01834, -0.09867, -0.02488, 0.12257, 0.04511, -0.02209, 0.00306, 0.02801, -0.07576, -0.12327, -0.00684], [-0.22034, 0.132, 0.06028, 0.07573, -0.01957, -0.06996, 0.04675, 0.0524, -0.00054, -0.01556, -0.003, 0.05113, 0.0282, -0.0646, 0.04976, -0.08067, -0.02201], [-0.22966, -0.01908, 0.00848, -0.09793, -0.05397, 0.14046, 0.03972, 0.0859, 0.09078, 0.05931, -0.06053, 0.14708, 0.10433, 0.11106, -0.05256, -0.10609, -0.16732], [0.03193, -0.04195, 0.07962, -0.06361, -0.05833, -0.14447, 0.10096, 0.12496, 0.09869, -0.27408, -0.10876, 0.05151, 0.17015, 0.08055, 0.08293, -0.09997, -0.03013], [0.0012, 0.04476, 0.11456, -0.00253, -0.01993, -0.02155, -0.10548, 0.03562, 0.01395, 0.03158, 0.06842, -0.09259, 0.0057, -0.08839, 0.10445, -0.06765, -0.02211], [0.05234, -0.0391, 0.01586, -0.1208, -0.06927, 0.08113, 0.08559, -0.0649, -0.05361, 0.08835, 0.03661, 0.02582, -0.01257, 0.04345, 0.009, 0.09514, -0.17304], [0.10493, -0.05458, -0.03709, -0.15188, 0.11447, 0.03737, -0.03616, 0.01007, -0.11382, 0.11025, 0.00783, 0.02492, 0.0032, -0.04263, -0.08265, 0.02249, 0.08328], [0.1911, -0.08956, -0.11357, 0.00662, -0.09206, 0.0591, -0.08523, 0.04359, 0.17301, -0.12629, 0.11903, -0.0702, -0.08536, -0.03423, 0.11243, 0.02551, -0.0339], [-0.10013, 0.15842, -0.03072, -0.04333, 0.02002, -0.02505, 0.08494, -0.01699, 0.02248, 0.10435, -0.04753, 0.02544, -0.04654, -0.17769, -0.09364, 0.08013, 0.08583], [-0.14976, 0.08017, 0.05063, 0.02193, 0.09782, -0.04494, 0.18486, -0.00089, -0.15933, -0.07482, 0.02258, 0.00219, 0.00572, -0.01874, 0.1004, -0.04902, -0.0688], [0.08004, 0.02526, -0.03797, -0.04078, -0.09574, 0.13651, -0.24264, -0.00484, -0.01056, -0.03936, -0.13182, 0.17797, 0.06576, 0.07903, -0.03048, -0.00539, 0.075], [-0.06538, 0.07843, 0.01219, -0.04113, -0.08625, 0.0922, -0.10137, -0.00881, 0.0437, -0.0222, -0.00728, -0.01964, 0.14445, 0.00271, -0.02283, -0.04189, 0.04313], [0.26591, -0.09901, -0.00761, 0.19362, -0.0343, 0.13185, 0.03494, 0.10101, -0.15563, 0.11692, 0.01475, -0.02681, -0.2584, -0.20383, -0.12172, 0.09089, -0.0426], [0.26889, -0.04319, 0.01544, 0.08737, 0.0603, 0.01847, 0.13707, -0.05772, -0.02008, -0.04773, 0.10641, -0.15687, -0.02381, -0.10623, -0.01143, -0.21095, -0.01593], [-0.08135, -0.11059, 0.06822, -0.12393, -0.04041, 0.00385, 0.09308, 0.00291, 0.16372, -0.0582, 0.11397, 0.06304, -0.13013, 0.04514, 0.01861, 0.05109, -0.07901], [-0.12888, 0.07327, 0.04337, -0.02787, 0.02761, 0.1615, -0.0263, -0.26153, -0.07821, 0.15728, 0.02338, 0.03134, 0.00567, 0.04708, 0.06859, 0.00602, -0.12232], [0.13882, 0.18091, -0.0946, -0.04123, -0.0878, 0.03327, -0.17144, 0.19242, -0.0459, 0.00098, 0.01696, 0.05081, -0.16243, -0.01759, -0.11185, -0.05586, 0.17453], [-0.0246, -0.03174, 0.01745, -0.00481, 0.07397, -0.04485, 0.0253, -0.04437, -0.01712, -0.05381, -0.0758, -0.21257, 0.00995, 0.09178, 0.09238, 0.01639, 0.18243], [0.10196, -0.02898, -0.29079, 0.01175, -0.09245, 0.10888, -0.15205, 0.01025, 0.15598, 0.0153, 0.11359, 0.17454, -0.1883, 0.01183, -0.00894, -0.0846, 0.14203], [0.22071, 0.04369, -0.08226, -0.11566, -0.15261, -0.04719, -0.05508, 0.13223, -0.02331, -0.00016, 0.04597, -0.07459, -0.04751, 0.07319, -0.11865, 0.04944, 0.15176], [-0.13325, 0.08845, -0.03132, 0.12261, 0.05337, 0.01905, 0.073, 0.11516, 0.15051, -0.03908, -0.04974, 0.02745, -0.01941, -0.13899, -0.06737, -0.12042, -0.05002], [-0.03652, -0.10796, -0.13838, -0.0499, 0.02329, 0.13013, 0.07206, 0.08839, -0.02565, -0.1728, 0.07656, 0.02483, -0.04082, 0.0619, -0.0218, 0.00607, 0.11061], [-0.11682, -0.11439, 0.06771, 0.02166, 0.09474, -0.01642, -0.00511, 0.02592, 0.08974, 0.06424, -0.00754, -0.11313, -0.0584, -0.01564, -0.16085, 0.14607, 0.09821], [0.10681, -0.04069, -0.07532, 0.0491, -0.09331, 0.11286, 0.12039, -0.13028, 0.04787, -0.08734, -0.03086, 0.28818, 0.14551, -0.10695, 0.09562, -0.08292, -0.31867], [-0.06166, -0.07929, 0.0132, -0.08697, -0.08235, 0.04407, 0.06605, 0.02942, 0.04515, -0.00472, 0.00845, 0.09264, -0.01923, -0.05471, -0.0598, 0.06008, 0.08968], [0.10112, -0.03662, 0.05151, 0.06715, 0.01867, 0.07165, 0.18849, -0.07581, -0.21993, -0.21076, 0.0503, -0.06934, 0.00478, 0.14541, 0.04868, 0.00137, -0.13666], [-0.29036, -0.02302, -0.01673, -0.04022, 0.35644, -0.09923, 0.03046, 0.23166, 0.04821, -0.10257, 0.03244, -0.11674, 0.01888, 0.15077, 0.03635, 0.08193, -0.29826], [0.16133, 0.07675, 0.07015, -0.05304, 0.00378, 0.15799, -0.1747, 0.00548, 0.14576, -0.22618, 0.08837, -0.12542, 0.35036, -0.15794, -0.01999, -0.07654, -0.22616], [0.17539, 0.06086, -0.12524, 0.10268, -0.07713, -0.03879, -0.05508, 0.03281, -0.02567, -0.19045, 0.0207, 0.00776, 0.14934, -0.04035, 0.16944, -0.07039, -0.0959], [0.04187, -0.01356, -0.17163, -0.0489, -0.03096, -0.14912, 0.07957, -0.19177, 0.17725, 0.14821, 0.07977, 0.15564, 0.02555, 0.0029, 0.04864, -0.1161, -0.03735], [-0.04533, -0.14799, 0.11014, -0.05656, -0.08348, -0.03742, -0.10848, 0.00907, -0.04934, 0.04923, 0.14158, -0.04356, 0.02222, 0.19227, 0.03434, -0.03377, 0.04708], [-0.13244, 0.08603, 0.00169, -0.073, 0.10865, 0.00035, -0.00175, 0.0652, -0.13923, -0.07122, -0.24625, 0.21837, -0.16862, -0.11088, 0.32112, 0.10042, 0.04157], [-0.0787, 0.01457, -0.11993, 0.17499, 0.09725, -0.05636, -0.04564, 0.10573, -0.02975, 0.07794, -0.18986, -0.06847, 0.01819, 0.0396, -0.20108, 0.10873, 0.15277], [-0.03039, -0.0727, 0.09743, -0.15135, -0.09687, 0.16244, 0.1833, 0.00202, -0.11565, -0.16309, -0.02773, -0.03732, 0.10116, 0.03805, -0.07868, 0.07015, 0.11923], [0.10874, 0.04108, 0.1707, 0.14212, -0.01708, -0.22411, 0.0196, 0.04834, -0.13572, -0.03509, 0.17953, -0.20437, -0.02867, 0.04882, -0.02602, 0.01146, -0.09933], [0.03973, -0.00235, -0.05116, 0.02215, -0.01025, 0.00819, 0.02369, 0.01594, 0.04766, 0.0781, -0.11809, 0.03359, 0.06037, 0.05163, 0.04451, -0.13941, -0.1043], [0.05216, -0.1804, -0.01443, -0.06784, 0.14733, -0.05942, -0.04422, 0.07804, 0.06606, -0.10259, -0.06576, 0.00578, 0.15955, 0.02681, 0.06553, 0.09884, -0.16542], [0.02525, 0.15573, 0.19682, 0.21672, 0.00277, -0.07185, -0.129, -0.07665, -0.02659, -0.06792, 0.08656, 0.04018, -0.08065, -0.01036, -0.07697, -0.10908, -0.07496], [-0.03211, -0.0267, 0.06882, -0.16957, -0.1235, -0.17372, -0.07664, 0.01937, 0.12197, 0.04727, -0.08413, 0.07077, 0.47406, 0.04955, 0.09875, -0.1412, -0.12298], [0.02717, -0.16321, -0.07175, 0.08201, -0.05498, 0.13981, 0.06558, 0.25404, -0.09766, -0.03358, 0.08829, 0.0071, -0.00109, -0.21067, -0.10629, -0.05085, 0.12608], [-0.10618, 0.08666, -0.06204, -0.01386, 0.12394, -0.20814, -0.00246, -0.08843, 0.02551, 0.14435, -0.09524, 0.26744, -0.01478, 0.09712, -0.00704, 0.01742, -0.16426], [0.06114, -0.07042, -0.02357, 0.06234, 0.08702, -0.13818, -0.05167, 0.1606, 0.05908, 0.08481, -0.03615, 0.02383, -0.06547, 0.02657, -0.09354, -0.02673, -0.05966], [0.05461, 0.06144, 0.29162, 0.13993, -0.02504, -0.19176, 0.20217, -0.25556, -0.04127, 0.00457, 0.15066, -0.19817, -0.03654, -0.15089, 0.02354, 0.07981, -0.10912], [-0.01188, -0.03941, -0.04923, 0.08196, -0.09808, 0.05158, 0.03835, -0.0798, 0.00563, 0.08031, 0.02361, 0.19053, -0.1857, 0.06066, -0.0532, 0.03962, -0.05493], [-0.06014, -0.00061, 0.12433, 0.23347, 0.04732, 0.05232, 0.02982, -0.06805, -0.13522, -0.17592, -0.05438, 0.04783, 0.02757, -0.01393, -0.2221, 0.09881, 0.06889], [0.0776, 0.07451, -0.04684, -0.12443, -0.03347, 0.06808, -0.04298, -0.13718, 0.02785, -0.01902, 0.06463, 0.01627, -0.00261, -0.03708, 0.1037, -0.10949, 0.12046], [0.06639, -0.22233, -0.02764, -0.04771, -0.03471, -0.15382, 0.05671, 0.1503, 0.11562, -0.06438, 0.17793, 0.01363, 0.04799, -0.0445, 0.07228, -0.00692, -0.09886], [-0.12637, 0.09666, 0.00279, -0.05898, 0.00145, -0.04396, -0.07222, -0.14167, 0.14693, -0.03854, 0.13693, 0.04398, -0.04307, -0.15768, 0.00904, 0.12722, 0.11749], [-0.06647, -0.03921, -0.19625, -0.04885, -0.17744, 0.09689, 0.03587, 0.03754, 0.10258, 0.03515, -0.03499, 0.1801, 0.05112, -0.08165, 0.10804, 0.00426, -0.00669], [-0.03942, -0.02444, -0.06522, -0.06743, -0.08002, 0.05253, 0.046, -0.1755, 0.03875, 0.08385, -0.10391, -0.01096, -0.15927, 0.12017, 0.17197, -0.06287, 0.27577], [0.10161, -0.12225, -0.02527, -0.0439, -0.07756, 0.08797, -0.00085, 0.06455, 0.00193, 0.00391, 0.03586, 0.19503, 0.04719, -0.04779, 0.13107, -0.12733, -0.22418], [0.106, -0.09671, -0.24261, -0.09894, 0.07853, 0.00381, 0.03833, 0.04536, 0.00152, 0.06791, 0.07353, 0.05474, -0.09786, -0.14729, -0.04873, 0.12174, 0.14068], [-0.05656, 0.04026, -0.07136, 0.08299, -0.03788, 0.08178, -0.15039, -0.03824, -0.01114, 0.05612, -0.13197, 0.02861, 0.05285, 0.16314, -0.02478, -0.02415, 0.04072], [0.0285, -0.08518, 0.07662, 0.04524, -0.0079, -0.01663, 0.05142, 0.07554, 0.02688, -0.10649, -0.03993, -0.10923, -0.14619, 0.17694, -0.07933, 0.09723, 0.01252], [-0.12138, 0.20763, 0.05519, 0.06389, 0.07809, -0.13559, 0.02161, -0.16094, 0.08794, 0.10017, -0.07612, -0.00195, -0.02404, -0.0209, 0.05177, -0.03198, -0.09338], [0.03043, 0.00366, -0.06609, -0.05851, 0.14802, 0.04954, -0.00903, 0.12168, -0.00994, 0.09438, -0.10225, -0.12873, -0.14281, -0.06117, -0.12687, 0.20838, 0.04932], [-0.02106, -0.12783, 0.1498, 0.17211, -0.07664, 0.05981, -0.09876, 0.12893, -0.00175, 0.0317, -0.09065, -0.01107, -0.06123, 0.0224, -0.03784, -0.11518, 0.07725], [0.21989, -0.23545, -0.00258, -0.09853, -0.02864, 0.09213, 0.27242, 0.00627, -0.15015, 0.05144, -0.15458, 0.04781, 0.03963, 0.06604, -0.20413, 0.14862, -0.0702], [-0.00158, -0.08202, 0.06999, 0.03583, 0.13195, 0.29638, -0.00558, -0.08279, 0.01809, 0.01874, -0.03885, -0.0244, -0.01508, -0.04932, -0.2529, 0.04053, -0.05898], [0.04818, -0.17404, -0.01188, -0.11808, 0.14351, 0.18988, -0.00557, -0.015, -0.04478, 0.03293, 0.01151, 0.04454, -0.19027, -0.11665, 0.04516, 0.08152, 0.07905], [-0.04173, 0.0506, -0.02514, -0.0617, 0.15946, 0.03355, -0.0349, -0.191, 0.0163, -0.09484, 0.12853, -0.0188, 0.13383, -0.15557, 0.00171, 0.09336, 0.00634], [-0.09034, -0.0245, 0.1435, 0.00916, -0.01804, 0.06919, 0.03983, -0.14, 0.14494, -0.00067, -0.12101, -0.07948, 0.01009, 0.02675, 0.08737, 0.06307, -0.11987], [-0.09115, -0.03579, 0.11418, -0.01087, -0.06839, -0.10351, 0.02224, -0.03446, 0.06824, -0.02331, -0.07366, 0.05802, 0.1456, 0.00539, -0.0331, -0.04274, 0.1033], [0.14175, -0.03827, -0.05719, -0.12879, 0.06724, 0.19969, -0.01797, 0.12781, -0.04422, 0.0186, -0.06668, -0.05474, -0.07485, -0.10122, 0.29979, -0.0659, -0.20506], [-0.15831, 0.03031, -0.03303, 0.07823, 0.10263, -0.16678, 0.03188, 0.22609, 0.07661, -0.07318, -0.27367, -0.07622, 0.23, -0.03105, 0.11646, 0.00257, -0.08253], [-0.13061, -0.05958, 0.08077, -0.11944, -0.13055, 0.02495, 0.0064, -0.01724, -0.1863, -0.01877, 0.21897, 0.00314, 0.00383, 0.12184, 0.1998, -0.04299, 0.04579], [0.10467, -0.06405, -0.11834, 0.07658, -0.00096, 0.15282, 0.0848, 0.00804, -0.02726, 0.05283, 0.11197, -0.06266, -0.01028, -0.06792, -0.08502, -0.17745, 0.02222], [0.0313, 0.10062, -0.11348, 0.01422, -0.12384, 0.01288, 0.03242, 0.0643, 0.05046, 0.00705, 0.17126, 0.04044, -0.3165, -0.07197, -0.03772, 0.07612, 0.06242], [0.08992, 0.12742, -0.01042, 0.29303, -0.02894, -0.1551, -0.12498, 0.09934, -0.06826, -0.06245, -0.18316, -0.07713, 0.21409, -0.34181, 0.15232, -0.02015, 0.09628], [-0.05566, -0.03194, -0.03521, 0.00469, 0.07374, -0.00791, 0.044, 0.11311, 0.01991, -0.04721, 0.09527, 0.20266, -0.24024, -0.03257, 0.05641, 0.0046, -0.16367], [0.20764, -0.14235, -0.12694, -0.00645, -0.1437, 0.14622, 0.09888, -0.04007, -0.11218, 0.26304, 0.06985, -0.04496, -0.16447, 0.19551, -0.14258, -0.16931, 0.11186], [0.03447, -0.01608, -0.00515, -0.08456, 0.14031, 0.11993, -0.06514, -0.21662, -0.10087, 0.0092, -0.01883, -0.0934, 0.04954, -0.15296, 0.30246, -0.04007, 0.13776], [-0.08452, -0.02066, 0.10727, 0.0642, 0.06219, -0.15395, 0.22433, 0.18254, 0.00825, -0.1249, -0.15871, 0.04592, -0.21844, -0.13705, -0.09037, 0.13909, 0.1548], [0.25281, 0.13186, -0.0513, 0.11575, 0.13326, 0.10277, 0.07325, -0.0193, -0.24447, 0.07966, -0.06322, -0.17725, -0.10375, -0.15429, -0.06661, -0.11108, 0.10193], [-0.16577, 0.07412, 0.03103, 0.12669, 0.04633, -0.16643, -0.03908, -0.07828, 0.04893, -0.00107, -0.14491, 0.03737, 0.15977, 0.02711, 0.08475, -0.10023, 0.05967], [0.03399, -0.07938, 0.02075, 0.05719, -0.18937, 0.14949, -0.11223, -0.1034, 0.0863, -0.1334, 0.09648, -0.03149, -0.0325, 0.16767, -0.04412, 0.07485, 0.03917], [0.0329, -0.0257, -0.07872, 0.19, 0.11458, -0.12192, -0.16623, 0.01299, -0.01099, 0.01419, 0.04316, -0.20189, 0.13354, -0.07355, -0.11399, -0.08394, 0.33558], [0.03797, -0.15164, 0.04063, 0.0142, -0.10529, -0.01074, -0.16374, -0.10212, -0.04633, 0.12399, 0.11729, 0.07963, -0.0218, 0.06959, 0.04268, 0.07453, 0.00114], [0.10552, 0.08528, -0.01981, -0.27442, -0.02911, 0.04209, 0.1006, -0.10814, -0.29324, 0.34261, 0.13833, -0.04604, 0.01542, -0.02632, -0.10897, -0.02013, 0.09631], [0.02643, -0.069, -0.0074, 0.2204, 0.02311, -0.02894, -0.02843, -0.18979, 0.01243, 0.09149, -0.01264, -0.00762, 0.04721, 0.13158, -0.02311, 0.06677, -0.25247], [-0.08214, 0.09389, -0.23559, -0.03584, -0.11049, 0.07427, 0.09683, -0.14301, 0.06126, 0.04954, 0.06512, 0.16472, 0.11916, 0.0345, -0.04972, -0.12483, 0.02236], [-0.03285, -0.01708, -0.1111, -0.07715, 0.06109, 0.05706, 0.03744, 0.03448, -0.05394, 0.00696, 0.01261, 0.12193, -0.03725, 0.02546, 0.01091, -0.13518, 0.09663], [-0.06403, 0.25285, -0.17078, -0.0996, 0.036, -0.10667, 0.22954, -0.11739, -0.2048, 0.03918, 0.04891, 0.02222, -0.15823, 0.15388, 0.03536, 0.18698, -0.08342], [-0.04266, -0.02761, 0.00532, -0.08394, 0.00951, 0.15432, 0.09695, 0.00846, -0.04814, 0.00723, -0.01386, 0.01119, -0.08049, -0.02849, -0.0081, 0.05937, -0.01906], [0.05699, -0.00277, -0.10662, -0.06358, -0.07794, -0.18936, -0.0375, 0.08399, -0.0466, 0.09121, -0.10377, 0.1665, -0.0358, -0.08043, 0.10006, 0.08315, 0.16246], [-0.02426, -0.02446, 0.23979, -0.0506, -0.06935, -0.08762, -0.09393, -0.05433, -0.06575, 0.03354, -0.08555, -0.01017, -0.06014, -0.07483, 0.01071, 0.01182, 0.40513], [-0.12807, -0.01129, 0.14929, -0.1149, -0.01286, 0.07329, 0.04109, 0.01956, -0.02021, -0.11096, -0.06265, 0.08941, -0.03395, -0.02484, 0.07756, -0.00723, 0.07676], [-0.09124, 0.0617, 0.01222, 0.14326, 0.04543, 0.09315, 0.0019, -0.00296, -0.03378, 0.22965, -0.23154, -0.0316, 0.02759, -0.29515, 0.11412, -0.04331, 0.00055], [-0.06169, -0.03881, 0.08316, -0.05066, 0.05392, 0.1471, -0.11187, 0.03734, 0.00058, 0.06018, -0.21121, 0.05977, -0.11182, -0.06598, 0.01289, 0.20632, -0.00922], [-0.00596, 0.00162, -0.00199, 0.07167, 0.04034, 0.00787, -0.1081, 0.04217, 0.0912, -0.11249, 0.07146, -0.0644, 0.11361, -0.08356, 0.05784, -0.02683, -0.09445], [0.08683, 0.12373, 0.07484, -0.003, 0.04174, -0.10983, 0.0347, 0.12446, 0.02573, -0.05875, -0.05372, 0.01, 0.11491, -0.03702, 0.02707, -0.14567, -0.25603], [-0.00715, 0.18728, -0.09275, 0.06334, 0.09193, -0.09966, -0.1003, 0.12048, -0.07108, -0.06064, -0.1623, 0.04842, -0.02923, 0.07229, -0.02979, 0.08804, -0.01889], [-0.08417, 0.01018, -0.09833, 0.07212, -0.20571, 0.11796, 0.04346, -0.04493, 0.16479, -0.11054, -0.10517, -0.01518, 0.21638, -0.04459, 0.07233, -0.02633, 0.03771], [-0.01581, 0.10521, 0.06226, 0.01956, -0.08931, -0.02268, 0.0096, 0.02489, 0.0923, -0.15537, 0.04745, -0.0245, -0.06724, 0.01965, -0.06098, 0.05458, 0.00038], [0.02005, 0.00762, -0.00728, -0.06682, -0.07884, -0.16628, 0.15319, 0.00601, -0.0246, -0.17744, 0.09337, -0.01299, -0.10617, 0.00932, 0.13176, 0.01822, 0.2009], [0.05993, -0.04873, 0.10113, 0.04251, -0.09264, 0.03262, 0.04836, -0.12891, 0.02981, 0.00718, -0.0396, 0.16382, -0.07722, -0.07032, 0.00935, 0.0411, -0.07839], [0.03526, -0.02787, -0.05059, -0.06643, 0.12127, 0.0084, -0.03138, 0.09575, 0.08817, 0.06005, -0.13908, -0.23729, 0.00934, 0.29715, -0.15997, 0.05171, -0.05451], [-0.09192, -0.01076, 0.06073, -0.10179, 0.04277, -0.08537, 0.06022, 0.00351, -0.03042, 0.0541, 0.03892, -0.08692, -0.04279, -0.08508, 0.11893, -0.06985, 0.22574], [0.03369, -0.17456, 0.07646, 0.08393, 0.02363, -0.05649, -0.01812, 0.07748, 0.18044, -0.15888, -0.14789, -0.14869, -0.00268, 0.03327, -0.23767, 0.18899, 0.24708], [0.07049, -0.0085, 0.11692, 0.11539, -0.09766, 0.00483, 0.00189, -0.13629, 0.03323, -0.02878, 0.06314, 0.14585, -0.10066, -0.02259, 0.00832, -0.06806, -0.09753], [-0.12016, 0.12066, 0.01083, 0.11037, 0.00507, -0.00691, 0.07694, -0.00829, -0.14617, -0.01712, 0.05024, 0.0466, -0.16062, 0.0194, 0.01525, 0.11245, -0.10856], [0.05972, 0.07566, -0.10486, -0.09311, 0.13127, -0.03825, -0.005, 0.00703, 0.00446, 0.17397, -0.02295, -0.24144, 0.23386, -0.09307, -0.06251, 0.01289, -0.03767], [0.09659, 0.07592, 0.12239, -0.01368, 0.07466, -0.08331, 0.0456, -0.22215, -0.11979, -0.1224, 0.03676, -0.06214, 0.10555, -0.02435, 0.07183, -0.00755, 0.02606], [-0.03552, -0.00363, -0.06324, 0.07646, 0.02178, 0.09213, -0.06283, 0.11783, -0.16917, 0.11021, 0.10033, -0.04076, -0.15257, 0.17049, -0.00759, -0.09851, -0.05538], [0.05144, -0.08133, -0.08849, -0.02411, 0.06325, 0.17687, -0.00876, -0.1998, -0.06146, 0.05642, 0.16431, -0.12677, -0.18152, 0.2217, -0.01604, 0.13277, -0.07848], [-0.20738, -0.02204, 0.11645, -0.06588, 0.01098, -0.04142, -0.02077, 0.0185, -0.01924, 0.02332, 0.10208, 0.0382, 0.09938, -0.06097, 0.03661, 0.0203, -0.02813], [0.07947, -0.02028, 0.096, 0.04922, 0.03263, -0.05948, -0.15567, 0.04841, 0.11698, -0.12035, 0.09128, -0.0643, 0.00668, -0.02483, -0.04017, 0.10082, -0.13641], [-0.02612, 0.11777, -0.09788, -0.04112, 0.02971, -0.07648, -0.07423, 0.00371, 0.02444, 0.08364, 0.06734, 0.02421, -0.22695, 0.05025, -0.01232, 0.02209, 0.13196], [0.02518, -0.03032, 0.22026, 0.10569, -0.25061, -0.06007, -0.0766, 0.0104, -0.062, 0.18736, 0.0692, 0.13476, -0.05394, -0.05036, -0.06105, 0.02222, -0.1301], [-0.08643, 0.04529, 0.05408, -0.12932, -0.16622, -0.04026, 0.01724, 0.07806, -0.06968, -0.02636, 0.05594, 0.01001, -0.03878, -0.0769, 0.32207, -0.02577, 0.07703], [-0.14856, -0.0073, 0.01956, 0.01666, 0.08068, -0.01775, 0.07204, -0.00784, -0.07355, 0.17263, -0.05343, -0.11229, 0.08452, 0.03904, -0.04972, 0.03627, -0.05095], [0.12671, -0.19539, 0.07118, -0.04759, 0.01251, 0.06692, 0.03088, -0.12548, 0.16146, -0.03843, 0.14229, -0.00444, 0.04674, -0.03324, -0.08189, 0.17465, -0.30688], [-0.03912, 0.07198, -0.18566, 0.08591, 0.0172, 0.00203, -0.12113, 0.09284, 0.12698, 0.00902, -0.09348, 0.12616, -0.1328, -0.00921, -0.0696, 0.08124, 0.03765], [-0.14591, 0.24231, 0.26715, 0.20886, -0.09402, 0.0296, 0.01321, -0.00056, 0.02462, -0.07037, 0.09231, -0.16118, -0.15602, -0.10751, 0.01124, 0.11438, -0.26811], [-0.12487, 0.15064, -0.01483, 0.11347, 0.08704, -0.00785, -0.0396, 0.10821, -0.05431, -0.21773, -0.02865, 0.02652, 0.01803, -0.02871, 0.10602, -0.06132, -0.03206], [-0.09982, 0.12419, -0.05506, 0.02252, 0.09632, -0.17488, 0.11842, -0.13779, 0.09795, 0.14668, -0.0027, 0.25743, -0.08875, -0.21332, -0.03099, 0.06366, -0.12384], [-0.04141, -0.18177, -0.082, -0.04256, -0.06237, -0.03363, 0.14509, 0.06576, 0.1008, 0.0795, 0.09495, 0.01071, -0.14327, 0.06685, 0.0288, -0.04382, 0.03837], [-0.09526, -0.02125, 0.07629, -0.0217, 0.01806, 0.06686, 0.00701, -0.0159, 0.03152, -0.09212, 0.12762, 0.01352, -0.05106, -0.06197, -0.03899, -0.02349, 0.08085], [-0.07421, -0.13673, -0.05444, 0.03663, -0.12709, 0.03839, 0.09045, -0.11846, 0.15018, 0.0648, -0.10615, 0.05094, 0.17567, 0.01589, -0.00388, 0.0665, -0.06848], [0.16228, 0.10788, -0.09172, -0.08204, 0.04296, -0.10554, -0.05982, 0.16627, -0.08399, -0.12927, 0.02666, 0.15525, 0.06396, -0.01092, 0.04972, -0.14943, -0.06226], [-0.04955, 0.08043, -0.06766, 0.11111, 0.07775, 0.07951, -0.18734, 0.15907, -0.17731, -0.10396, 0.05052, 0.06958, 0.13597, -0.06119, 0.19511, -0.09183, -0.2202], [-0.04156, -0.01141, 0.02826, 0.09404, 0.11732, 0.05436, -0.09465, -0.10448, 0.11204, 0.08422, 0.2026, -0.11017, -0.17141, -0.01252, -0.06771, 0.07976, -0.1587], [-0.23143, -0.13108, -0.06241, 0.04035, 0.02883, 0.10624, -0.09563, 0.08456, 0.06592, -0.0041, -0.03101, 0.03103, 0.0659, 0.09646, -0.16184, 0.09799, 0.10023], [-0.09355, -0.02804, 0.08015, 0.04422, 0.03552, 0.04182, 0.06164, -0.21722, -0.07484, 0.07835, 0.02365, -0.02501, -0.14594, 0.16421, -0.07887, 0.00121, 0.1327], [-0.01714, 0.10451, 0.2122, -0.02772, -0.08779, 0.04549, -0.17261, 0.09058, 0.06637, -0.21915, 0.11869, -0.00156, -0.15067, -0.00339, 0.00694, -0.02455, 0.0598], [0.01365, -0.00965, -0.29163, -0.04654, 0.1208, -0.02922, 0.11459, -0.04446, -0.00975, 0.17284, -0.0897, -0.10848, -0.08034, 0.07806, 0.15747, 0.06236, -0.01], [-0.05004, 0.07925, -0.10628, 0.04424, -0.0027, 0.08748, 0.17143, 0.05016, -0.19377, -0.11646, -0.0847, -0.12289, -0.04465, -0.03076, 0.12963, 0.16675, 0.02331], [0.13132, -0.05676, 0.00963, -0.14579, 0.08782, -0.02934, -0.07135, 0.08847, 0.07062, -0.06246, 0.14754, -0.1775, 0.01499, -0.14075, 0.04284, -0.03943, 0.13015], [-0.17898, -0.09831, -0.02629, 0.03333, -0.16601, 0.01969, -0.03367, 0.10582, 0.04577, 0.05154, -0.15121, 0.01453, 0.0974, 0.0464, 0.07857, 0.03271, 0.12871], [-0.02589, -0.08715, 0.04697, -0.07732, 0.1317, -0.078, -0.01427, -0.07097, -0.06297, 0.10664, -0.1096, 0.04404, 0.03178, -0.00938, 0.15411, 0.03369, -0.01338], [-0.06847, -0.05318, 0.14191, 0.08169, -0.10294, -0.16599, -0.15355, 0.19827, -0.06871, -0.03977, 0.10002, -0.20103, 0.10053, 0.073, 0.02401, 0.05957, 0.07465], [-0.14231, -0.13835, 0.10995, -0.06386, -0.03289, 0.1074, 0.01776, 0.03019, 0.06552, 0.01787, -0.01688, -0.09341, -0.11683, 0.25257, -0.16029, -0.02234, 0.18589], [-0.16669, -0.02842, -0.03914, -0.13878, -0.05027, 0.15187, 0.09065, -0.15751, -0.04303, -0.02628, 0.07471, -0.03014, 0.10994, 0.14529, 0.088, -0.14417, 0.16397], [-0.27739, -0.10106, -0.03217, 0.00026, 0.01583, 0.04536, -0.10563, -0.05247, 0.02538, 0.11602, -0.10598, 0.08405, 0.21074, 0.14405, 0.09632, 0.00461, -0.06792], [-0.04693, 0.12369, -0.25505, -0.09144, -0.09031, 0.02042, -0.05562, 0.04018, 0.12047, -0.09538, 0.03674, 0.28249, 0.23514, -0.03576, 0.0548, 0.01288, -0.25632], [0.1569, 0.05309, -0.23775, 0.06466, -0.03852, 0.16484, 0.00913, 0.00955, 0.04197, -0.00601, 0.01848, -0.06998, -0.02273, -0.11869, 0.17136, 0.07241, -0.26869], [-0.05487, 0.20477, -0.222, 0.02917, 0.20153, 0.01092, -0.03513, 0.02687, -0.03583, -0.11579, 0.01044, 0.14556, 0.0043, -0.06039, -0.00151, 0.05658, -0.16461], [0.20979, -0.02361, -0.10859, -0.00997, 0.05218, 0.06255, 0.14432, -0.01922, -0.1499, 0.12902, -0.09248, -0.0279, -0.08427, -0.06898, 0.1071, -0.08929, -0.03073], [0.01843, -0.01308, 0.0222, 0.03968, -0.00457, 0.00841, -0.01486, -0.04234, -0.0374, 0.03249, -0.04491, -0.03358, -0.00742, 0.03099, -0.00741, -0.00872, 0.06209], [0.03735, -0.01622, -0.02062, -0.05551, -0.05675, -0.07303, -0.03036, -0.01796, 0.01843, 0.1058, -0.01413, 0.02534, -0.02819, 0.11232, -0.05875, 0.07695, -0.00468], [0.04006, 0.08854, -0.14708, 0.05025, -0.13449, -0.02044, 0.0447, 0.03736, -0.02307, -0.13785, -0.1437, 0.02869, -0.00884, 0.02267, 0.05115, 0.022, 0.23004], [0.07359, -0.00152, -0.05256, -0.00841, 0.14145, -0.01067, 0.13295, 0.0671, -0.04029, -0.02333, -0.08156, -0.0819, -0.14712, 0.15262, -0.23302, 0.04655, 0.06611], [0.1191, -0.07405, 0.05224, 0.03018, 0.00659, 0.01426, 0.0107, 0.11655, -0.00395, 0.02809, -0.09197, -0.12484, 0.08309, -0.04256, -0.07093, -0.1039, 0.05141], [-0.10793, 0.14236, 0.02332, 0.15681, 0.01966, -0.00705, -0.07159, -0.03272, -0.02806, -0.05224, -0.1892, -0.07676, 0.48176, 0.05295, -0.06835, -0.072, -0.17095], [-0.03893, -0.0341, 0.03341, -0.04111, -0.01235, 0.08607, 0.03633, -0.06423, 0.17877, -0.1616, 0.04476, -0.00329, 0.18069, -0.1084, -0.19242, 0.07106, 0.02534], [-0.0526, -0.06375, -0.08865, -0.02843, -0.03207, -0.01786, 0.16997, -0.07889, 0.13196, -0.05879, -0.01872, -0.04287, 0.00785, -0.05545, 0.05955, -0.16123, 0.32997], [-0.03282, -0.02272, -0.20092, -0.18399, 0.00883, 0.33946, 0.28184, 0.03528, 0.16592, -0.1575, -0.05377, -0.05462, -0.06529, 0.17404, -0.24269, 0.01033, -0.00137], [-0.07034, 0.12225, -0.17504, -0.06231, 0.10962, -0.02212, -0.06597, -0.02737, 0.11348, 0.03353, -0.06707, 0.23971, -0.12773, 0.086, -0.21338, -0.03991, 0.16663], [0.03585, -0.06509, -0.04731, 0.23955, 0.03455, 0.18409, -0.07755, 0.07746, -0.04993, -0.0358, 0.02768, -0.09636, -0.10834, -0.20466, 0.04161, 0.14347, -0.09921], [-0.23985, 0.00933, -0.01937, -0.07965, 0.03323, -0.0255, 0.03338, 0.03226, 0.07315, 0.0713, 0.0571, -0.0814, 0.03646, 0.17619, 0.01657, -0.00573, -0.08747], [0.13615, -0.16859, 0.04259, 0.24247, -0.03145, 0.02384, 0.12039, -0.14397, -0.09617, -0.01487, 0.05961, -0.01743, -0.05767, -0.0113, -0.00485, -0.16464, 0.08589], [0.03406, -0.11512, -0.10842, -0.12462, -0.15042, -0.01828, 0.13466, 0.05552, 0.08161, 0.08144, 0.04313, 0.049, 0.13013, -0.00395, -0.14957, 0.01276, 0.04805], [-0.05797, 0.1196, 0.04464, 0.04104, -0.02965, 0.00014, -0.0436, 0.08837, -0.23038, -0.03121, 0.00371, -0.00285, 0.10743, -0.07411, 0.0763, 0.01507, -0.02654], [-0.03525, 0.28915, -0.19497, 0.14451, -0.2167, 0.04388, 0.08553, -0.11601, -0.16029, 0.00335, 0.19085, -0.01518, 0.18659, -0.01023, -0.04451, 0.04734, -0.19804], [-0.03954, -0.03743, -0.06271, 0.06346, -0.06455, 0.06015, -0.00206, -0.06941, -0.03899, 0.05468, 0.02693, 0.02615, -0.06385, 0.1301, -0.07651, -0.00256, 0.09616], [-0.10984, -0.01287, 0.07268, 0.0329, 0.06335, -0.07103, -0.07547, -0.0492, 0.00426, -0.00427, -0.06737, -0.02879, 0.04111, -0.07746, -0.02199, 0.06671, 0.23727], [0.02368, -0.10503, -0.13446, -0.07489, -0.02074, 0.01991, 0.11229, 0.09849, 0.06307, 0.009, -0.09486, 0.02892, -0.08089, 0.04807, 0.02509, -0.02954, 0.11191], [0.17412, -0.0669, -0.02425, 0.06194, 0.00965, 0.05362, -0.08782, 0.09628, -0.16596, 0.03033, -0.07398, -0.02288, 0.18117, -0.25928, 0.11166, -0.00882, -0.0089], [-0.00886, -0.12438, -0.11031, -0.03701, -0.03076, 0.20354, 0.0961, -0.10888, -0.03646, 0.0835, -0.02227, 0.01085, 0.0929, 0.01525, 0.04406, -0.03969, -0.02758], [-0.01241, -0.08924, -0.03731, 0.05973, -0.15639, -0.06079, -0.00718, 0.04246, -0.02404, -0.04946, -0.06541, 0.10666, 0.1285, 0.18623, -0.07936, 0.03236, 0.02566], [0.26343, 0.02201, 0.02883, -0.04963, -0.26573, 0.03224, 0.22771, -0.14873, -0.16423, -0.09331, -0.02429, 0.11555, 0.13332, 0.07104, 0.02151, -0.10397, -0.06575], [-0.15327, 0.0635, -0.02868, -0.00621, -0.01279, 0.04466, -0.29009, -0.1267, -0.2192, 0.23816, -0.06009, 0.04215, 0.09242, 0.17835, 0.08879, 0.07484, 0.07414], [0.02644, 0.08556, -0.02591, 0.08455, -0.16722, -0.07695, 0.02716, 0.21647, 0.00125, -0.02434, 0.16887, 0.0249, 0.03152, -0.22621, 0.06274, -0.08451, -0.12433], [-0.10842, -0.03692, 0.05211, -0.02134, 0.11931, -0.12331, 0.12623, -0.02699, 0.05939, 0.00398, -0.01663, -0.06244, -0.02421, -0.00878, 0.14684, -0.00017, -0.07864], [-0.12881, 0.04376, -0.06367, -0.03813, -0.01007, -0.1144, -0.17648, -0.16332, 0.18928, -0.08761, 0.13579, -0.02375, -0.05206, 0.08613, 0.00894, 0.1998, 0.19461], [-0.03409, 0.1031, -0.20869, 0.02379, -0.03298, -0.03201, -0.07397, 0.04256, -0.01371, 0.02472, 0.06469, 0.05793, 0.04306, -0.04707, -0.12436, 0.23763, -0.03059], [0.02288, -0.01423, -0.01448, 0.04991, -0.01354, 0.08721, -0.01149, 0.07609, 0.12871, 0.04707, -0.04946, 0.09694, -0.07003, -0.11333, -0.04024, -0.13989, -0.04213], [-0.01054, 0.00619, 0.12447, -0.17338, -0.00215, 0.02115, -0.07673, -0.08035, 0.13208, -0.04018, -0.06415, -0.11768, 0.08469, 0.14368, 0.10912, 0.09226, -0.14849], [-0.0504, -0.17126, 0.09831, -0.14138, 0.14472, 0.03043, 0.04338, 0.09319, 0.03377, -0.01836, 0.03705, -0.02012, 0.10257, 0.14519, -0.18398, -0.02176, -0.12134], [-0.09413, 0.05039, -0.10773, 0.00351, 0.01213, -0.12507, -0.10322, -0.23923, 0.00197, 0.0894, -0.08541, -0.12306, 0.15868, 0.16625, -0.08192, 0.23102, 0.2464], [-0.15193, -0.09565, 0.07022, 0.17043, 0.00865, 0.05843, -0.01176, 0.29001, 0.00338, -0.12949, -0.08855, -0.22351, 0.0011, -0.05779, 0.06131, -0.01609, 0.11124], [0.20644, -0.082, -0.16794, 0.00305, -0.18988, 0.17178, 0.13882, -0.16134, -0.05029, -0.1086, 0.06618, -0.0215, 0.05539, 0.02771, 0.07581, 0.0543, -0.01791], [0.04839, 0.0166, -0.01536, 0.10508, -0.00619, -0.18336, 0.03558, -0.00485, -0.06825, 0.02047, -0.00031, 0.06781, 0.0637, 0.0495, -0.04695, -0.01575, -0.06612], [0.02599, 0.06619, -0.06268, 0.04653, -0.02323, -0.08273, 0.18306, 0.0408, -0.11918, -0.02309, -0.05291, 0.22002, 0.07165, -0.1139, 0.0729, -0.10186, -0.14756], [-0.02293, 0.07685, -0.12386, -0.03669, 0.02702, 0.09875, -0.05383, 0.07865, 0.01038, -0.06661, 0.06602, -0.04218, 0.02727, 0.14934, 0.12233, -0.04538, -0.26512], [-0.13345, -0.02093, -0.22229, -0.18357, -0.16137, 0.04382, -0.1375, 0.11144, 0.1832, 0.1441, -0.02662, 0.33519, -0.16146, -0.1796, 0.07535, 0.08671, 0.24699], [0.01176, 0.15237, -0.05976, 0.01374, 0.01764, -0.05704, 0.02523, -0.14805, 0.11192, 0.01924, 0.07044, 0.07968, -0.14399, -0.10372, 0.02988, 0.10113, -0.12046], [0.04147, -0.12728, 0.04069, -0.0648, -0.05879, 0.12683, -0.05222, -0.07297, 0.05014, -0.06219, 0.18233, -0.02799, 0.04912, 0.10499, 0.00378, -0.12014, -0.01297], [-0.02895, 0.02742, -0.01715, -0.03491, -0.122, 0.07161, -0.03506, 0.11477, 0.03953, 0.10677, -0.07613, -0.08694, -0.02386, -0.01462, 0.04504, 0.02679, 0.00767], [0.04328, 0.14105, 0.03185, -0.0346, 0.05998, -0.10012, -0.02071, 0.14319, 0.10348, -0.15089, 0.12326, -0.04492, -0.14093, -0.31496, 0.16919, -0.04328, 0.03513], [-0.03116, -0.12918, -0.17782, -0.17753, 0.2428, -0.07377, -0.11036, 0.15478, 0.03632, 0.12888, -0.13491, -0.17272, 0.07346, 0.27566, -0.24532, 0.25444, 0.08643], [0.02746, -0.03821, 0.10852, -0.0871, -0.00472, -0.04837, -0.0519, 0.21976, -0.22529, 0.01781, 0.05389, 0.0302, 0.10697, -0.06484, -0.17688, -0.00288, 0.13558], [0.14878, 0.01139, -0.16147, -0.01391, 0.01964, 0.0053, 0.00124, 0.16952, 0.04625, -0.1317, 0.03157, -0.15093, 0.23129, -0.13895, 0.14137, 0.04979, -0.25918], [-0.0927, 0.05811, -0.03704, -0.10943, 0.11398, -0.02713, -0.02484, 0.00681, 0.10164, -0.07509, 0.0324, 0.02107, 0.13851, 0.01666, -0.20284, 0.07825, 0.00165], [0.07582, -0.21922, 0.01948, 0.00845, 0.18727, 0.02153, -0.17135, 0.09409, 0.09059, 0.06077, -0.00878, 0.13031, 0.01296, 0.03289, -0.13724, -0.0509, -0.14667], [-0.043, 0.04631, -0.06029, 0.20212, -0.15614, -0.06718, 0.11179, -0.01179, 0.2142, 0.13555, -0.04525, -0.10142, -0.02617, -0.19381, 0.02456, -0.10788, 0.0784], [0.08229, 0.02018, 0.02476, -0.04232, -0.01196, 0.09146, -0.01091, 0.08861, -0.18432, 0.03874, 0.0333, -0.10302, 0.04554, -0.13408, 0.0402, 0.17256, -0.15102], [0.12332, -0.19481, -0.07335, 0.06013, 0.10974, 0.07222, -0.21496, -0.07143, 0.0996, 0.00823, 0.14359, 0.11358, -0.08502, -0.11776, 0.05812, -0.00198, -0.02921], [0.19338, -0.00253, -0.13554, -0.01487, -0.09473, 0.01934, 0.05105, -0.11138, -0.02712, 0.09715, -0.03122, -0.07442, 0.09103, 0.12441, 0.19861, -0.01697, -0.26621], [-0.0209, -0.06005, 0.00521, 0.08855, -0.14473, 0.13839, 0.00867, -0.10264, -0.00331, 0.15898, 0.02771, -0.13505, 0.21256, 0.02173, -0.08659, 0.01224, -0.12078], [0.05762, -0.16609, -0.11896, -0.15036, 0.00124, 0.16458, 0.12265, 0.09961, -0.0504, -0.02974, -0.02922, -0.09108, 0.34145, -0.10801, -0.01672, -0.04412, 0.01756], [-0.07436, -0.10974, 0.0047, 0.03544, -0.03942, -0.07203, -0.03123, 0.09897, 0.03773, -0.05128, 0.11606, 0.00254, -0.0278, 0.17422, -0.13932, 0.00649, 0.06903], [-0.06122, 0.04926, 0.07629, -0.12691, -0.01287, 0.01581, -0.01662, -0.01302, 0.11404, -0.02273, -0.03928, 0.00182, 0.07247, -0.06115, 0.02975, -0.09028, 0.08462], [-0.20087, 0.02874, 0.19551, 0.00019, 0.00967, 0.08379, 0.11097, -0.12419, 0.18448, 0.19897, -0.05337, 0.09425, -0.30521, -0.17908, 0.01332, 0.06403, -0.12119], [0.08292, 0.1582, 0.01639, -0.02675, -0.0879, 0.0334, -0.0701, 0.01329, 0.04942, -0.18114, 0.13628, -0.02586, 0.14256, -0.09283, -0.01707, 0.04949, -0.18028], [0.11292, -0.24095, -0.011, -0.08897, -0.09861, 0.07709, -0.06221, 0.1714, -0.10442, 0.17395, 0.05419, 0.09543, -0.20638, 0.26714, -0.0924, 0.1015, -0.14868], [-0.04506, -0.04516, 0.13537, 0.05867, -0.02428, 0.01709, 0.14087, 0.14917, 0.00957, -0.14847, -0.06204, 0.02904, 0.11861, -0.18724, -0.00831, -0.09511, -0.04272], [0.13353, 0.05241, -0.02915, -0.08493, 0.03336, 0.06561, -0.07961, 0.00744, -0.11492, 0.04075, -0.08754, 0.06475, -0.02331, 0.01973, 0.08919, -0.06177, -0.02554], [-0.07114, -0.05198, 0.09165, 0.00683, -0.05644, 0.03217, 0.04232, 0.12736, -0.12774, -0.14557, -0.01252, 0.03876, 0.05217, -0.00998, 0.0193, 0.0846, -0.0198], [-0.10072, 0.06845, -0.04552, -0.02094, 0.14036, -0.26535, 0.16306, -0.08724, -0.08294, 0.09503, -0.11037, -0.09994, -0.0456, 0.15834, 0.00674, 0.19104, 0.03558], [0.00438, -0.11844, 0.01684, -0.14726, -0.07042, 0.07034, 0.21957, -0.05391, 0.06312, 0.02246, -0.16672, 0.11286, 0.10476, 0.06717, 0.02028, -0.17181, 0.02676], [-0.15981, -0.17429, -0.05206, -0.08895, 0.133, -0.12983, 0.15003, 0.16151, -0.13778, -0.00626, -0.10134, 0.15056, 0.05141, 0.10213, 0.03764, 0.08545, -0.0214], [0.11169, -0.05445, -0.0746, -0.09549, 0.09979, 0.23232, -0.02979, 0.11299, 0.0556, -0.01661, 0.06101, -0.15041, -0.01637, -0.06677, 0.02987, -0.06004, -0.13875], [0.03388, 0.12993, -0.19242, -0.02756, -0.018, -0.04255, 0.05998, -0.06336, 0.0085, 0.06684, -0.06028, -0.20131, 0.15081, 0.02805, 0.19282, -0.2246, 0.15925], [-0.04774, 0.30425, -0.02363, 0.02595, -0.06051, -0.15201, -0.09582, 0.07797, 0.29455, -0.15939, -0.06895, -0.19523, 0.08031, -0.12384, 0.16279, 0.03602, -0.05472], [0.0578, -0.09901, 0.06569, -0.07105, 0.04537, -0.03276, -0.02032, 0.1232, -0.04953, -0.125, -0.06086, 0.2627, 0.00078, 0.17718, -0.07474, -0.01744, -0.18201], [0.01572, 0.16589, -0.07441, 0.08184, -0.16317, -0.11374, 0.08924, 0.05284, -0.15784, 0.07069, -0.14052, 0.0758, 0.10881, -0.09394, -0.03129, 0.01948, 0.0946], [0.06829, 0.01979, 0.01775, -0.14622, 0.05671, 0.02513, -0.05602, 0.12382, -0.05346, -0.03453, 0.03196, -0.1354, 0.03326, 0.02557, 0.06091, -0.04138, 0.00383], [0.14399, -0.13432, 0.00773, 0.01753, 0.07316, 0.09667, 0.07252, -0.30041, -0.13254, 0.13736, 0.12907, -0.07174, -0.25854, 0.09686, -0.07869, 0.09075, 0.1106], [0.05847, 0.22857, -0.06229, -0.00555, 0.06137, 0.09896, -0.01658, -0.10261, -0.07857, -0.01162, -0.05029, 0.08488, 0.04709, -0.04021, 0.07257, -0.06029, -0.22391], [-0.09606, 0.04081, 0.15347, 0.02732, 0.14579, -0.24415, 0.01511, -0.22758, 0.21862, 0.12955, 0.22635, -0.08401, 0.1824, -0.24957, -0.08359, 0.02158, -0.17606], [0.18518, -0.04229, -0.09476, 0.01704, 0.10014, -0.10357, 0.03894, -0.07058, 0.01196, -0.0277, -0.13395, 0.06396, 0.01362, -0.06991, -0.08934, -0.03231, 0.23357], [-0.0741, -0.0837, 0.00967, 0.15324, 0.14695, 0.01397, -0.07028, 0.09815, -0.08923, 0.07154, 0.12216, -0.04226, -0.21914, -0.0182, 0.03742, 0.06872, -0.12491], [-0.12126, 0.01018, 0.22884, 0.0196, 0.10974, -0.14313, -0.12792, -0.01459, -0.06437, 0.01598, -0.12785, 0.13013, 0.08135, 0.0352, -0.02634, 0.0449, -0.05045], [-0.02255, 0.01182, -0.0752, -0.07295, -0.02827, 0.09753, 0.2886, -0.08201, -0.13681, 0.00706, -0.18556, 0.17377, -0.2923, 0.19342, -0.06576, -0.0977, 0.2869], [0.01186, -0.07841, -0.03979, -0.05006, -0.04353, -0.03824, -0.13015, 0.1804, 0.08637, 0.04261, 0.11975, -0.07291, -0.08041, 0.04361, -0.14183, -0.07944, 0.27017], [-0.08381, 0.04443, 0.04482, 0.09206, 0.00911, -0.07953, -0.03745, -0.09279, -0.02947, 0.05011, -0.05401, -0.15834, 0.13538, -0.05811, -0.07949, 0.11601, 0.1811], [-0.0104, 0.03135, 0.18107, -0.04256, 0.05913, 0.02463, -0.15474, -0.0446, -0.0749, 0.02547, 0.08478, 0.12991, -0.05256, -0.0109, 0.01502, -0.08965, -0.07105], [-0.04169, 0.16245, 0.05446, -0.01547, -0.04115, 0.17537, 0.17819, 0.01692, -0.17265, -0.00887, -0.03417, 0.06056, 0.07065, -0.17557, -0.16755, 0.07803, -0.13949], [0.04288, 0.12512, -0.10534, 0.17179, -0.03907, -0.09694, -0.01125, -0.1828, -0.0791, 0.09179, 0.1312, 0.1197, 0.14049, -0.16606, -0.05193, -0.07589, -0.01459], [-0.09119, -0.00101, 0.12658, -0.08041, 0.04051, -0.03637, 0.02945, -0.23143, 0.0057, 0.1236, -0.1373, -0.13176, 0.02437, 0.26334, -0.23723, 0.33082, 0.0023], [-0.1685, -0.10811, 0.05198, 0.01974, 0.12608, 0.03261, 0.02298, 0.12261, -0.06468, -0.05362, -0.13037, 0.00421, -0.13367, 0.02717, 0.12027, -0.0478, 0.17912], [-0.07485, -0.05245, 0.13611, 0.09466, 0.00553, -0.08469, 0.06853, -0.06732, -0.05805, 0.0242, 0.03752, 0.05685, -0.07652, -0.13859, 0.01577, 0.10561, 0.00768], [-0.09238, -0.19743, -0.12025, -0.12103, -0.04035, 0.16903, 0.01451, -0.11659, 0.28052, 0.18796, 0.1278, 0.08515, -0.07536, -0.10281, -0.15078, 0.06527, 0.08673], [0.03415, -0.17079, -0.02368, -0.06097, 0.03261, -0.06044, -0.03137, 0.01902, 0.00205, -0.03826, 0.05175, -0.04709, 0.17223, 0.02482, -0.01369, 0.0995, 0.01017], [-0.07699, 0.21204, 0.03979, 0.19417, -0.03718, -0.16216, 0.05356, -0.13148, 0.11439, -0.0342, -0.13383, 0.20006, -0.00523, 0.0193, -0.03478, -0.14008, -0.07736], [-0.10962, 0.00391, 0.0358, -0.11852, 0.16707, 0.17526, 0.07138, -0.14581, -0.01295, -0.04957, 0.02545, 0.06466, -0.04772, 0.0282, -0.0755, 0.13989, -0.15193], [-0.01264, -0.12884, 0.06859, -0.07147, -0.02224, 0.05835, 0.02889, 0.16986, -0.09039, 0.17373, -0.13558, -0.12542, -0.17885, 0.05187, 0.05298, 0.10866, 0.0525], [-0.08015, 0.12159, 0.04855, -0.1689, 0.13745, -0.03026, 0.05921, 0.09807, 0.17635, 0.07062, 0.00151, -0.2186, -0.26435, -0.14049, -0.11362, 0.10385, 0.19916], [0.04134, 0.18759, 0.01026, -0.07967, -0.10663, 0.03342, 0.07568, -0.03285, -0.03365, 0.0221, -0.0869, 0.00202, -0.04553, -0.04101, -0.06373, 0.14958, -0.03201], [0.05015, -0.01731, -0.09556, -0.07387, 0.01788, 0.13432, 0.17165, -0.15167, -0.05609, 0.23464, -0.01038, 0.03485, -0.20801, 0.07023, -0.01482, -0.02682, -0.05918], [0.02062, -0.16275, 0.01387, 0.08948, 0.03019, 0.05062, -0.19439, 0.02713, 0.13164, 0.093, -0.03221, -0.21437, 0.11339, 0.14838, -0.1684, 0.03142, 0.02238], [0.00642, -0.06221, -0.06537, -0.0233, 0.10221, 0.08783, -0.1029, 0.01676, -0.00785, 0.00643, -0.0517, -0.09319, -0.06088, 0.11298, 0.02298, -0.05906, 0.17084], [-0.10518, 0.06826, 0.09713, 0.14908, 0.11017, 0.14058, 0.18253, -0.18163, 0.04675, -0.0863, -0.19016, 0.0258, -0.16846, -0.06884, -0.03987, 0.06168, -0.04153], [0.35477, 0.09075, -0.03523, -0.1431, -0.18611, -0.12761, 0.03479, -0.06603, -0.01396, -0.04924, -0.03232, 0.1631, -0.0832, -0.04674, 0.16986, 0.00627, -0.03599], [0.18313, -0.00217, 0.09312, 0.08556, -0.06625, 0.04782, -0.03428, -0.00032, -0.00079, -0.13968, 0.15899, -0.00351, -0.03268, 0.07135, -0.13704, -0.1452, -0.07807], [-0.13228, 0.0858, -0.11284, -0.2355, 0.01845, -0.02756, -8e-05, 0.03467, -0.00981, 0.16661, 0.05698, -0.03409, 0.20498, -0.07548, 0.1318, 0.01872, -0.09036], [0.23033, -0.00343, -0.01813, -0.27828, 0.11562, -0.10527, 0.00632, 0.14379, -0.18363, -0.02633, 0.12172, 0.0433, -0.14288, -0.01967, -0.07139, 0.03817, 0.14975], [-0.06558, 0.36954, -0.24123, -0.11134, -0.17029, 0.19636, 0.10151, -0.12579, 0.16206, -0.14406, -0.04927, 0.0109, 0.18564, -0.17285, 0.15917, 0.07974, -0.18451], [-0.0407, 0.00148, -0.10282, -0.17567, -0.01799, 0.1845, 0.14042, -0.11271, -0.07351, 0.1728, 0.06762, -0.01696, 0.0496, -0.00829, 0.09686, -0.22313, 0.05848], [0.17613, 0.04918, 0.02716, -0.04809, -0.07848, -0.11988, -0.04505, -0.24777, 0.00448, 0.15467, 0.03665, 0.05496, 0.07296, -0.12043, 0.02746, -0.02759, 0.08363], [-0.01697, -0.01416, 0.23749, -0.06669, -0.06013, 0.08666, -0.1022, -0.0849, -0.01793, -0.01928, 0.14351, -0.06554, 0.22439, -0.10681, -0.08889, 0.1013, -0.14985], [0.03208, -0.09081, -0.10867, -0.09248, -0.17959, -0.0828, 0.18729, -0.05546, 0.04315, 0.09943, 0.06969, 0.17745, -0.22919, 0.01569, -0.07954, 0.04186, 0.2519], [0.06739, -0.08186, 0.22008, -0.08035, -0.05958, -0.06163, -0.10617, -0.13534, 0.20029, -0.20492, -0.10139, -0.11748, 0.14281, 0.13975, 0.06079, 0.12183, -0.00423], [0.15183, 0.01443, 0.12829, 0.2417, 0.02147, 0.00358, -0.02174, 0.1413, -0.17443, -0.17284, -0.14338, -0.18008, 0.01872, -0.13707, 0.05022, -0.11694, 0.17495], [-0.0269, 0.03466, -0.13384, 0.00969, -0.04843, 0.06815, -0.07188, 0.04684, -0.03444, 0.19117, 0.13205, -0.14428, 0.02794, 0.05305, -0.07161, -0.0848, 0.05264], [-0.02103, -0.0679, 0.00299, -0.05714, 0.03235, -0.07081, -0.21433, 0.14198, 0.00161, -0.01014, -0.11965, 0.14869, 0.12641, 0.29714, -0.09752, -0.02473, -0.06792], [0.09559, -0.07972, -0.10392, -0.02401, 0.10961, 0.07173, -0.03407, 0.06877, -0.02605, -0.12023, 0.06966, 0.04197, 0.12367, -0.03348, -0.02556, -0.07201, -0.06195], [0.1724, -0.20656, 0.02428, -0.03351, -0.10924, -0.03988, -0.03296, 0.07328, -0.04945, -0.08091, 0.17884, -0.0387, 0.02578, -0.04079, -0.02428, 0.17859, 0.0031], [-0.18546, -0.17849, -0.08628, -0.02051, -0.19193, -0.02031, 0.04971, 0.03686, 0.06455, -0.1178, 0.08852, -0.07272, 0.1587, -0.04118, 0.00541, 0.12806, 0.38287], [-0.182, 0.03654, 0.03116, -0.00025, -0.16149, 0.0654, 0.10326, 0.07765, -0.06505, -0.09213, 0.00648, -0.06618, -0.01409, 0.17459, -0.08755, 0.06728, 0.10639], [-0.03451, 0.02403, -0.0257, -0.32173, 0.08963, 0.06744, 0.03714, -0.14474, -0.14701, 0.26345, 0.07855, 0.09675, -0.06174, 0.09113, -0.02958, -0.02446, 0.04134], [0.05333, 0.1392, 0.07942, -0.05651, 0.06453, -0.02012, 0.039, -0.09276, 0.09793, -0.06819, -0.03917, -0.22222, 0.07855, -0.0987, 0.06411, -0.00055, -0.01786], [0.0431, -0.09293, 0.18428, 0.04258, -0.1215, 0.0987, -0.16976, 0.1732, -0.06941, 0.02875, 0.06092, -0.11564, -0.07085, -0.09381, 0.10349, 0.03784, -0.03895], [0.02573, 0.05305, -0.15242, -0.08777, 0.01241, -0.04326, 0.1879, 0.04671, 0.17709, -0.03569, -0.07993, 0.06721, -0.21628, -0.05318, -0.03869, 0.16614, -0.02903], [-0.02522, -0.18967, -0.00663, -0.02149, -0.02725, 0.15607, -0.04023, 0.02954, 0.08918, 0.04303, -0.0403, 0.1394, -0.00946, 0.01498, 0.0923, -0.21265, 0.0084], [0.01582, -0.12456, -0.04047, 0.32043, -0.17101, 0.04966, -0.0691, -0.13571, -0.12814, -0.18761, 0.0853, 0.18361, -0.05697, 0.08298, 0.16996, 0.08823, -0.08242], [-0.0566, 0.06848, -0.18704, 0.06239, -0.2469, 0.03982, -0.07075, -0.06098, -0.08134, 0.08474, -0.11067, 0.18358, 0.07742, 0.01272, 0.15352, 0.0455, 0.08611], [-0.07744, 0.02079, -0.2194, -0.00049, 0.14359, 0.23966, 0.07251, 0.0612, 0.11991, -0.18802, -0.08234, 0.10906, -0.07781, 0.10984, -0.02903, -0.12173, -0.0803], [0.05682, 0.05713, -0.04219, 0.13283, -0.0409, 0.01008, -0.16183, 0.02982, 0.24748, 0.01155, -0.02796, 0.05933, -0.08636, 0.00818, 0.09796, -0.12081, -0.23116], [0.0322, 0.17861, -0.13216, 0.11137, 0.05263, 0.09142, 0.0716, -0.19568, -0.09473, -0.07301, -0.02541, 0.04156, 0.07996, -0.09617, 0.21151, -0.23017, -0.02354], [0.00283, -0.06777, -0.02279, -0.09331, -0.0152, 0.06379, 0.03973, -0.02876, -0.06152, 0.06164, -0.05759, -0.00513, 0.09522, 0.10263, 0.00386, -0.06388, 0.04625], [-0.07182, 0.17538, 0.17374, -0.0743, -0.06711, 0.15087, 0.12035, 0.07716, -0.05501, -0.07606, -0.18197, -0.18273, 0.06565, -0.1625, 0.27571, -0.06033, -0.10702], [-0.02586, 0.13847, -0.05537, 0.07481, -0.04136, 0.05417, -0.15358, -0.11551, 0.02729, -0.02456, 0.02685, 0.01142, 0.18002, 0.21277, -0.02686, -0.08489, -0.19781], [-0.15955, 0.04954, -0.07056, 0.1313, 0.09474, 0.14718, -0.09905, 0.03521, 0.04183, 0.07803, -0.03439, 0.05463, 0.07819, -0.23531, -0.0043, 0.04212, -0.14962], [-0.07517, -0.11533, 0.07479, -0.22183, -0.0176, -0.06496, 0.00553, -0.03623, 0.00832, 0.09428, 0.05749, 0.00074, 0.14124, -0.09661, -0.16551, 0.0802, 0.33065], [0.00834, -0.07709, -0.05121, -0.00678, -0.03123, 0.06391, 0.06514, -0.15416, -0.0054, 0.03353, 0.06823, 0.02965, -0.0025, 0.03901, 0.04979, 0.06043, -0.08967], [0.03406, 0.03531, -0.02073, 0.03365, 0.02146, 0.01318, -0.10107, 0.09437, 0.06858, -0.12089, 0.14811, 0.09269, -0.03822, -0.13292, 0.05769, -0.05699, -0.12828], [-0.07955, -0.05752, -0.18898, 0.11607, -0.04516, 0.0819, -0.13675, -0.05319, 0.05725, 0.05576, -0.07662, 0.08421, 0.09032, 0.02673, 0.1406, 0.02877, -0.04384], [-0.05458, -0.06499, 0.00075, 0.05527, -0.00535, -0.17739, -0.0317, -0.19874, 0.02418, 0.03432, -0.02856, 0.02936, 0.1908, 0.12507, -0.08899, 0.01429, 0.17625], [-0.13345, 0.1173, 0.01691, -0.09959, 0.13419, -0.16248, 0.09547, 0.07982, -0.07991, -0.02073, -0.02489, -0.04, 0.19084, -0.08906, 0.07258, -0.08829, 0.03129], [-0.10666, 0.1335, -0.17026, -0.14539, 0.12867, -0.08545, -0.06727, -0.10898, 0.01622, -0.05394, -0.03331, 0.11381, 0.00173, 0.04234, -0.11852, 0.14669, 0.30681], [-0.00852, 0.12823, 0.04557, 0.17264, 0.21598, 0.00675, -0.15745, -0.12565, 0.19841, 0.02041, 0.13247, 0.00483, -0.07483, -0.10984, -0.03606, -0.04675, -0.3662], [-0.02927, -0.09003, -0.05638, -0.07672, 0.1292, 0.06084, 0.06402, 0.03327, 0.16581, -0.04578, -0.09854, 0.04167, -0.12477, -0.10029, -0.10622, 0.01618, 0.21702], [-0.00807, 0.10922, -0.01118, 0.1095, 0.1414, 0.20555, -0.06158, -0.06248, -0.05692, 0.0293, -0.05895, 0.02502, 0.00194, -0.03475, 0.05253, -0.20873, -0.17181], [0.03436, 0.12191, 0.06987, 0.0423, 0.10719, 0.06332, 0.0881, -0.08243, -0.10763, -0.06587, -0.06677, -0.11152, 0.05244, -0.06974, 0.02068, -0.01552, -0.08072], [0.15849, 0.10324, -0.02615, -0.01055, -0.10907, 0.00979, -0.02709, 0.03901, 0.03934, 0.1451, 0.04453, 0.01076, -0.16411, -0.15975, 0.0842, -0.0821, -0.05564], [0.02014, -0.05848, 0.00321, -0.09551, -0.04997, -0.18446, 0.09284, -0.02141, 0.04538, -0.09105, -0.02556, -0.06496, -0.05808, 0.11493, -0.03539, 0.19131, 0.21705], [0.06155, 0.02944, -0.27027, 0.14424, 0.14913, 0.02921, -0.09901, 0.25626, 0.06313, 0.11289, -0.10825, -0.02234, -0.01197, 0.1047, -0.11454, -0.24512, -0.07903], [0.21466, 0.02908, -0.11947, 0.09556, -0.10249, -0.00288, 0.02491, -0.119, -0.17103, 0.02616, -0.04897, -0.00918, -0.02209, 0.09828, -0.04561, 0.00761, 0.14447], [0.13542, -0.10555, -0.05234, -0.04978, 0.2054, -0.1032, -0.04697, 0.10495, -0.02115, 0.05759, 0.03753, -0.20717, -0.14464, 0.03504, 0.23787, -0.21596, 0.13296], [-0.02584, -0.01541, -0.03684, 0.04081, 0.04423, 0.01638, -0.00786, -0.04819, 0.00339, -0.01423, -0.10022, -0.0493, 0.00623, 0.05279, 0.20217, -0.01817, -0.04994], [0.0791, 0.32984, -0.05371, -0.05629, 0.05737, 0.0377, -0.02278, -0.16295, 0.0625, -0.07684, 0.03042, 0.13725, 0.06456, -0.04274, -0.14243, -0.15946, -0.08152], [-0.149, 0.0802, 0.00981, 0.16723, 0.11106, -0.1221, 0.02196, 0.21636, -0.11422, -0.09983, -0.18532, -0.02244, 0.03109, -0.15652, 0.14032, 0.11064, -0.03926], [-0.06429, 0.02117, 0.24829, -0.06822, -0.08653, -0.03516, 0.05943, -0.06947, -0.07372, -0.07941, 0.0902, -0.01002, -0.09042, 0.02649, 0.06811, 0.08537, -0.02181], [-0.05785, 0.07761, -0.028, -0.02089, 0.03364, -0.05505, -0.00346, 0.00706, -0.06894, 0.13089, 0.00052, 0.15664, -0.16205, 0.03015, 0.17333, -0.15473, -0.05887], [0.0164, -0.00935, 0.15917, 0.18619, -0.09937, 0.15108, 0.07144, -0.24895, -0.04675, 0.00987, -0.00762, 0.09532, -0.24998, 0.05338, -0.10102, -0.0346, 0.0548], [0.03133, 0.01602, -0.09702, 0.03099, 0.12738, -0.0703, 0.00824, -0.0059, 0.04455, 0.05501, -0.02679, -0.0154, -0.03937, 0.01282, 0.03082, -0.15124, 0.04885], [-0.05892, -0.05484, -0.16587, -0.18712, 0.08765, -0.08398, -0.06117, -0.01596, 0.04118, 0.05423, -0.15148, 0.07977, 0.11221, 0.16761, 0.07895, 0.10168, 0.05605], [0.06872, 0.01703, -0.04584, -0.01583, 0.06651, -0.07764, 0.07418, 0.01666, -0.02628, -0.08286, -0.07262, 0.04414, 0.03093, -0.08164, 0.05582, 0.05354, -0.02482], [-0.12115, 0.05692, 0.07286, -0.09599, -0.00487, -0.22355, 0.15947, 0.02938, -0.04725, 0.08217, -0.17058, 0.20607, -0.04957, 0.034, 0.15962, -0.06281, -0.02474], [-0.05051, -0.09061, 0.00705, 0.08553, 0.05602, -0.05877, 0.00059, -0.02415, 0.00064, 0.01287, -0.04788, -0.06005, 0.0036, 0.08536, -0.11493, 0.20131, -0.00606], [0.10757, -0.06365, 0.02233, 0.12407, 0.16315, -0.17237, -0.08691, -0.21716, -0.08243, -0.00446, 0.06771, 0.09818, -0.0066, -0.04361, -0.02037, 0.26618, -0.15163], [0.19537, -0.11156, 0.11903, 0.00038, 0.07978, -0.02876, -0.18087, 0.03762, -0.05447, 0.07351, 0.08116, -0.03864, -0.06282, -0.1423, -0.08152, 0.02464, 0.08946], [-0.0407, -0.05685, 0.09932, -0.15395, 0.09575, -0.03763, 0.06671, 0.14245, -0.00223, -0.13726, -0.07478, 0.0351, 0.01023, 0.16028, -0.09959, 0.07201, -0.07885], [0.11626, 0.14897, -0.02673, -0.04576, -0.13782, 0.01029, -0.0256, 0.07128, 0.09284, -0.11106, 0.09885, -0.00301, 0.13952, 0.00019, -0.00463, -0.05954, -0.26405], [0.01861, 0.14106, -0.08715, -0.06543, -0.00752, 0.13644, -0.07346, -0.20584, -0.00994, -0.07895, 0.15863, -0.0602, 0.03799, 0.10988, -0.00694, 0.0025, -0.00966], [-0.13665, 0.17476, -0.00433, -0.00157, -0.17941, 0.03063, 0.0499, -0.19975, 0.24311, 0.17149, -0.03932, 0.15483, 0.11082, -0.21079, 0.22422, -0.20519, -0.18273], [-0.01205, 0.02726, -0.39928, -0.13912, 0.17105, 0.11485, -0.00114, -0.03996, 0.15409, -0.01001, -0.00859, 0.01042, 0.21907, -0.00495, -0.13818, -0.04691, 0.10344], [-0.07136, -0.01295, -0.14268, 0.09866, -0.35667, -0.07039, 0.15311, -0.05861, 0.22386, 0.02528, 0.07845, -0.07246, 0.1064, -0.08783, 0.14265, -0.03414, 0.07868], [0.1064, -0.00602, -0.12816, -0.00364, 0.03719, 0.09801, -0.08069, 0.14733, 0.01381, 0.0404, -0.20439, -0.09749, -0.11442, 0.06262, -0.03716, 0.06769, 0.09852], [0.02967, 0.03085, 0.06116, 0.02265, 0.00294, 0.03024, -0.03601, 0.03299, -0.08766, 0.07451, 0.02483, -0.0198, -0.06483, -0.09016, 0.10336, -0.04126, -0.07347], [-0.07133, 0.13073, 0.04361, -0.13606, 0.02068, 0.01787, -0.05268, -0.064, 0.0618, -0.00855, 0.19146, -0.05801, -0.03118, -0.12294, -0.06568, 0.02101, 0.12327], [-0.13788, -0.07964, 0.09192, -0.01984, -0.12214, -0.23099, 0.0284, -0.16461, 0.18558, 0.15222, 0.17167, -0.02741, 0.00201, 0.06576, 0.09672, 0.03303, -0.0448], [0.06899, 0.22342, 0.15837, 0.03555, 0.01797, -0.06142, -0.01497, -0.17435, -0.06478, 0.04958, -0.0584, -0.20908, 0.12989, -0.02982, -0.03309, -0.05635, 0.01848], [-0.00996, 0.02345, -0.05959, 0.08545, -0.04211, -0.00472, 0.23435, 0.03605, -0.10666, -0.05331, -0.04932, -0.04061, 0.06563, 0.01885, -0.00607, -0.02291, -0.06851], [-0.07271, 0.13901, 0.1908, -0.13376, 0.08946, -0.04972, 0.07731, 0.01795, 0.00428, 0.09561, -0.15215, -0.16015, -0.1145, 0.10331, 0.09866, 0.13405, -0.26744], [-0.06225, 0.10254, -0.00963, -0.04324, 0.04614, 0.12821, -0.12134, 0.07618, 0.04231, 0.01762, 0.07936, 0.02479, 0.07927, 0.04904, -0.14998, -0.1199, -0.13912], [0.07812, -0.03055, 0.20236, -0.07011, 0.07165, -0.0562, 0.02451, -0.17732, 0.00713, 0.10564, -0.11097, -0.04669, -0.06127, 0.03678, -0.00191, -0.16804, 0.19687], [0.04506, 0.15887, 0.07535, 0.01331, -0.06615, -0.03515, 0.05869, -0.20403, 0.05629, 0.09265, -0.02146, -0.15174, -0.12416, -0.20684, 0.08183, -0.0399, 0.26739], [-0.08766, -0.01702, 0.0687, -0.11071, 0.02272, -0.12059, -0.0898, -0.07274, -0.03969, -0.00507, -0.108, 0.18838, -0.03179, 0.09102, 0.14409, -0.00841, 0.17658], [-0.2221, 0.03633, -0.11684, 0.1275, 0.04231, 0.0435, -0.02319, 0.33547, 0.04083, -0.17333, 0.12745, 0.05875, 0.00741, -0.25085, -0.15296, -0.03844, 0.15815], [-0.07842, 0.11411, 0.11521, -0.10687, 0.05763, -0.05261, -0.16863, 0.21361, -0.02964, -0.10221, 0.16462, -0.12185, 0.1861, -0.08851, 0.05789, -0.10002, -0.06041], [0.03008, 0.07614, -0.01996, -0.08722, 0.0136, 0.00573, -0.08229, -0.15346, -0.02049, -0.02042, 0.10232, 0.03454, -0.05752, 0.10763, -0.00226, 0.03503, 0.03855], [0.13822, 0.01235, 0.07051, -0.09166, -0.11611, -0.00728, 0.00366, -0.02421, 0.04414, -0.15674, 0.04063, 0.16829, -0.14566, -0.00138, 0.16704, -0.16082, 0.05901], [-0.01668, -0.0024, 0.13267, -0.08121, 0.07681, 0.11781, -0.08911, 0.15769, -0.05108, 0.02049, -0.04011, -0.18457, -0.05013, 0.00219, 0.04053, 0.11922, -0.15213], [-0.01721, -0.03711, -0.0573, 0.02572, 0.1959, -0.03589, 0.01435, -0.07035, 0.03391, -0.06844, -0.02705, -0.11771, 0.09725, 0.05347, 0.16804, 0.001, -0.15859], [-0.04438, 0.0053, -0.03018, -0.00431, -0.09153, 0.01042, -0.00303, -0.19804, 0.04504, -0.03622, 0.02998, -0.09961, 0.01226, 0.14594, 0.13078, 0.08237, 0.0452], [-0.17843, -0.03639, 0.2034, -0.01633, 0.09144, -0.0439, -0.03982, -0.14352, -0.09095, -0.08144, 0.09426, -0.13174, 0.04304, 0.03025, 0.09165, 0.18514, 0.02334], [-0.03714, 0.00765, -0.00622, -0.11633, -0.00465, 0.02696, 0.09154, 0.05146, -0.01957, -0.06596, -0.07575, 0.18342, -0.0566, 0.03738, 0.14979, 0.04498, -0.21097], [-0.10273, -0.13092, 0.17206, -0.08363, 0.03151, -0.16119, -0.21485, 0.136, -0.02407, -0.14218, 0.41463, -0.20133, 0.12882, 0.27098, -0.21326, -0.004, 0.12415], [-0.07649, 0.01422, 0.15698, -0.02228, -0.10007, 0.00953, 6e-05, 0.18547, -0.06106, -0.06913, 0.07211, -0.20181, 0.1282, -0.03358, 0.0378, -0.08966, 0.0497], [0.02421, 0.00038, 0.0194, 0.06555, -0.10652, -0.26376, 0.00628, -0.04661, 0.05353, 0.03832, -0.02648, -0.08905, 0.05022, 0.08236, 0.09927, -0.05402, 0.14691], [0.10031, 0.01629, -0.09639, -0.09135, -0.00484, -0.03107, 0.0057, 0.10709, 0.0435, 0.0073, -0.03543, -0.09774, -0.08057, 0.13386, -0.03043, 0.07637, -0.0226], [0.15592, -0.23264, -0.13251, 0.11602, -0.10265, -0.08914, 0.02713, -0.27331, -0.14558, -0.08654, 0.11388, 0.20706, 0.11741, 0.29725, 0.10461, 0.1057, -0.18261], [0.06175, 0.03528, 0.11774, -0.06183, 0.08033, -0.09098, 0.14446, 0.09083, -0.12456, 0.0881, -0.05229, 0.01657, -0.32708, -0.13627, -0.15793, 0.14793, 0.16795], [-0.10834, 0.12936, 0.0774, 0.05419, -0.06811, -0.06672, 0.08295, 0.02117, -0.09313, 0.1785, -0.30908, -0.11584, 0.0266, 0.07787, -0.05183, 0.12156, 0.04344], [0.08773, -0.19563, 0.10017, -0.14215, -0.00591, 0.03111, 0.02214, 0.22966, 0.13504, -0.02276, 0.03898, 0.05207, 0.01414, -0.04185, -0.14512, -0.03871, -0.1189], [-0.05967, 0.22072, 0.21431, 0.07469, 0.07813, 0.00094, -0.2746, 0.01556, 0.09032, -0.14322, 0.20504, 0.0205, -0.1968, -0.14902, -0.16268, -0.03662, 0.10239], [0.04174, 0.06663, -0.17466, 0.07037, 0.01934, -0.0545, -0.09412, -0.10642, -0.10418, -0.04111, 0.03184, 0.10568, 0.1908, 0.15283, -0.05716, -0.03846, -0.00862], [-0.04937, -0.2278, 0.05782, -0.169, 0.07562, 0.11824, 0.03358, 0.04162, -0.04969, 0.14214, 0.06503, -0.14965, 0.15522, 0.14647, -0.05612, -0.057, -0.0771], [0.01208, -0.13111, 0.01609, -0.08102, 0.00592, -0.02758, 0.15661, -0.13212, -0.02868, -0.03442, -0.01841, -0.08205, -0.09511, 0.07379, -0.03572, 0.09436, 0.30738], [-0.11344, 0.1886, -0.3397, -0.11375, 0.17771, 0.02845, 0.06251, 0.1523, -0.12413, 0.12608, 0.0, -0.07513, 0.02769, 0.0751, -0.08847, -0.01599, 0.03218], [-0.0497, 0.03343, -0.03379, -0.09533, 0.17985, -0.0189, -0.07491, -0.11897, 0.01855, 0.1192, 0.06635, -0.10544, 0.12112, -0.00125, -0.02361, 0.08984, -0.10644], [-0.13601, -0.0387, 0.23075, 0.1298, -0.03768, -0.07122, -0.31446, -0.0126, 0.08154, -0.09056, -0.03803, 0.10142, 0.22617, 0.03123, -0.19659, 0.08728, 0.04765], [-0.08698, -0.0123, -0.00311, -0.05772, -0.12188, 0.08506, -0.00269, -0.03593, 0.04025, -0.12507, 0.05742, 0.06673, -0.01478, 0.10864, -0.15658, 0.0261, 0.23284], [-0.00507, 0.15518, 0.05433, 0.0316, 0.01646, -0.10904, -0.01629, 0.03831, -0.07893, 0.11476, -0.18305, -0.08041, 0.06552, -0.13932, -0.03118, 0.11611, 0.05103], [0.01006, 0.06364, 0.05635, 0.08547, 0.04706, 0.05259, 0.06248, -0.064, -0.03811, 0.10527, -0.24619, -0.06015, 0.00653, 0.16679, -0.0178, -0.05808, -0.17192], [0.04885, -0.0293, -0.03118, 0.09101, -0.18621, 0.08891, -0.05188, -0.00172, -0.19977, -0.11551, 0.24929, 0.1342, 0.13388, -0.00745, -0.02017, -0.26512, 0.16218], [0.14107, 0.07602, -0.05051, 0.12306, 0.05908, -0.0726, 0.08025, -0.01565, -0.00374, -0.16334, -0.02395, -0.0856, -0.06477, 0.20108, 0.01126, -0.22066, 0.00899], [0.03211, 0.01067, -0.00125, 0.18152, -0.14471, -0.02016, -0.18996, 0.03045, -0.14979, -0.18372, 0.19441, 0.08098, -0.22236, -0.05177, 0.01235, 0.00362, 0.41762], [0.1388, -0.10145, -0.12635, -0.14778, 0.06331, 0.07588, -0.07262, 0.15359, 0.10144, -0.10697, 0.09137, -0.14066, -0.06029, 0.06532, -0.07901, 0.07106, 0.07435], [0.15831, 0.22163, 0.0526, 0.04929, -0.0143, 0.1669, -0.01561, -0.02596, -0.13101, 0.0572, -0.06306, -0.16955, -0.0359, -0.13019, 0.09416, -0.12199, -0.0925], [0.06601, -0.04553, 0.06224, -0.08244, 0.13479, 0.05806, -0.02379, 0.09028, 0.21469, 0.10381, 0.00091, -0.21562, -0.22875, -0.00015, -0.23945, -0.03271, 0.13765], [-0.00306, 0.07106, 0.0176, -0.03218, -0.06638, -0.01845, 0.02937, -0.15636, 0.13093, -0.16904, 0.0984, -0.04423, 0.12275, 0.00044, 0.07642, 0.01768, -0.07496], [0.12727, -0.13647, -0.07741, 0.09175, 0.22512, -0.10681, -0.23883, -0.12606, 0.11887, 0.08697, 0.13224, 0.05502, -0.03299, 0.02743, 0.00278, -0.16628, 0.01739], [-0.09336, -0.08511, 0.03515, -0.04399, -0.07874, -0.0075, -0.02391, -0.00064, -0.01245, 0.01871, 0.04986, 0.12854, -0.05691, 0.14202, 0.06131, -0.00109, -0.03191], [0.16487, 0.07738, 0.05753, -0.10713, -0.00071, -0.05343, 0.02003, 0.1187, -0.09569, 0.00561, -0.14936, 0.0081, -0.03235, 0.05346, 0.00419, -0.11394, 0.04273], [-0.03971, -0.17518, -0.01692, -0.22003, 0.0555, 0.01802, 0.04732, -0.08775, -0.02462, 0.02898, 0.04685, 0.11208, 0.24193, 0.05854, 0.08088, 0.01173, -0.13759], [0.02312, 0.04836, -0.00728, 0.14272, 0.08066, 0.04146, -0.04412, 0.01245, -0.04316, 0.02353, -0.11922, 0.1217, -0.03424, -0.09887, -0.09565, -0.08786, 0.03641], [-0.05457, -0.08348, -0.017, 0.14977, 0.06468, 0.03667, -0.24592, -0.13119, 0.27941, -0.00734, 0.00307, -0.02996, -0.22856, 0.00864, -0.03078, 0.14729, 0.13928], [0.15626, -0.16616, 0.15493, -0.17917, -0.10127, -0.08135, -0.16128, 0.1904, -0.00893, 0.07441, 0.23538, 0.05663, -0.02564, -0.01125, -0.1081, -0.01503, -0.00985], [-0.03421, 0.10072, 0.15187, -0.00138, 0.06738, -0.07977, -0.06702, 0.01895, -0.09138, -0.03249, 0.03023, -0.07285, 0.02362, -0.05293, 0.04038, 0.03071, -0.03184], [-0.00468, -0.05328, 0.3463, 0.01363, 0.09547, -0.01165, -0.06754, -0.07893, -0.03469, -0.03775, 0.1175, -0.15949, 0.08307, 0.07017, -0.29032, -0.02252, 0.0347], [-0.03206, -0.14533, -0.0223, -0.0437, 0.02449, 0.12934, -0.00028, 0.14205, -0.04952, 0.166, 0.04491, 0.07352, -0.0805, 0.10852, -0.10741, -0.07192, -0.1358], [0.0253, 0.03505, -0.2527, 0.05125, 0.17964, 0.28425, 0.03357, -0.17166, 0.28195, -0.06879, -0.12109, -0.07758, -0.1173, 0.03462, -0.02812, -0.0637, -0.0247], [-0.12771, -0.01113, 0.00754, -0.28986, 0.00626, -0.05179, 0.05205, 0.17425, 0.09514, -0.05702, 0.06992, 0.00039, 0.32372, -0.24427, -0.00954, 0.03858, 0.02348], [-0.07223, -0.00319, 0.11221, -0.16592, 0.09328, 0.02999, 0.16615, -0.0628, -0.0955, 0.07183, 0.01472, -0.05493, 0.01504, 0.06725, 0.05999, 0.01677, -0.19265], [-0.04521, -0.08661, 0.04772, 0.00586, -0.04722, -0.18562, 0.15562, -0.17482, 0.00667, 0.02973, 0.0684, -0.05158, 0.09353, 0.11483, 0.13614, 0.01242, -0.07986], [0.09157, -0.08357, 0.17763, -0.18032, -0.01909, 0.02409, -0.129, 0.128, 0.11365, 0.01048, 0.00746, -0.14999, -0.01421, -0.01742, -0.03321, 0.14518, -0.07126], [0.05812, -0.20789, -0.09515, 0.02393, -0.02989, -0.02203, 0.01638, 0.05785, 0.08996, 0.13391, -0.09183, 0.17573, -0.00888, 0.0364, 0.04299, -0.17172, -0.0079], [-0.10753, -0.05216, 0.19084, -0.15764, 0.09127, 0.04077, 0.15777, -0.00954, -0.14675, 0.06973, 0.07138, -0.01887, -0.08645, 0.05362, 0.11061, -0.00117, -0.20586], [-0.1619, -0.07256, 0.00757, -0.04636, 0.2179, 0.02735, 0.11561, 0.02161, -0.14098, -0.05722, 0.03012, -0.00232, 0.03094, 0.03568, -0.0677, -0.03179, 0.09404], [0.11222, 0.10664, -0.27797, -0.02174, 0.09208, -0.08667, -0.02321, 0.08355, 0.03597, -0.01454, -0.01803, 0.28025, 0.10258, 0.00647, -0.09204, 0.05561, -0.34117], [0.20305, 0.0152, 0.05588, -0.01418, 0.10542, -0.14008, -0.04461, -0.05539, -0.06955, -0.00206, 0.01805, 0.00479, -0.01735, 0.02354, 0.01341, 0.07182, -0.16795], [-0.08497, 0.20355, -0.18114, 0.10165, -0.03949, 0.11425, -0.01252, -0.1902, 0.00875, 0.00614, -0.06818, -0.04177, 0.12572, -0.10679, 0.01793, 0.14261, 0.00446], [-0.1893, 0.07221, 0.20898, -0.01052, -0.02776, 0.10294, -0.00729, -0.08674, 0.01622, -0.1479, 0.06026, 0.11328, -0.00022, -0.0451, -0.05921, -0.13409, 0.13424], [-0.03297, 0.1643, -0.16765, -0.01387, -0.06853, -0.08915, 0.08635, -0.03064, 0.07928, -0.16366, 0.0867, 0.02478, -0.01831, 0.06969, 0.01358, 0.18503, -0.12493], [-0.09705, 0.046, -0.09839, -0.02819, -0.17842, -0.11889, -0.01535, -0.05482, 0.06863, -0.20316, 0.05363, 0.30946, 0.11063, -0.02218, 0.12786, -0.07443, 0.17466], [0.02038, -0.03852, 0.0376, 0.02466, 0.09778, -0.00865, -0.22344, 0.17722, 0.00429, -0.09381, 0.09701, -0.12376, 0.17227, 0.08902, -0.0304, -0.08601, -0.11563], [0.00972, -0.04424, -0.02562, -0.03123, -0.02082, 0.03563, -0.00286, 0.09044, 0.01345, -0.0155, -0.02529, 0.05111, 0.14228, -0.106, 0.12052, -0.15497, -0.03662], [-0.02534, 0.05394, 0.09867, 0.17518, -0.08805, 0.01044, -0.0021, -0.135, 0.08217, 0.00161, -0.01486, -0.00593, 0.10214, 0.01955, -0.2146, -0.12337, 0.06556], [0.02821, 0.01054, 0.00201, 0.16725, -0.04624, -0.05172, -0.09822, 0.18966, -0.1481, -0.08077, -0.06404, -0.04736, -0.02919, -0.17425, 0.14739, 0.03957, 0.15527], [-0.11789, -0.09568, 0.11579, 0.02967, 0.05144, -0.05248, -0.12865, 0.10726, -0.07475, 0.07766, -0.0317, 0.08905, 0.11088, -0.0668, -0.16741, 0.00886, 0.14477], [-0.13764, 0.13643, -0.07429, 0.17226, 0.00478, -0.03558, 0.28006, 0.01268, -0.07305, -0.11842, -0.21572, -0.05839, -0.04364, 0.21673, -0.11563, -0.049, 0.09839], [0.05104, -0.13894, -0.02918, -0.02594, 0.13042, 0.02679, 0.13351, -0.13702, 0.09459, 0.09362, 0.12372, -0.01153, -0.06634, -0.10574, -0.09702, -0.10846, 0.06648], [-0.05671, 0.07798, -0.0853, -0.03972, -0.06842, 0.06338, -0.16554, -0.10667, 0.01077, 0.07124, 0.16627, -0.04814, 0.19993, -0.12432, 0.08223, -0.08577, 0.10879], [-0.12436, 0.06508, 0.14298, 0.01544, -0.00721, -0.04976, -0.04695, -0.0185, -0.13673, 0.1152, 0.00057, -0.01241, -0.00121, 0.15135, -0.00809, 0.01364, -0.09904], [-0.0728, -0.02222, 0.05846, 0.0472, -0.07452, -0.12488, -0.01216, -0.03638, 0.13318, 0.00719, 0.05535, 0.07161, -0.01494, 0.08269, -0.07101, -0.01628, -0.01049], [-0.07523, 0.32205, -0.0692, 0.02391, 0.05092, 0.06315, 0.08805, -0.27959, -0.11201, -0.14331, -0.0137, -0.04367, 0.06857, 0.10988, 0.08986, 0.04437, -0.12404], [-0.12946, 0.16813, -0.10882, -0.11075, -0.06109, -0.13598, -0.10539, 0.1137, -0.02279, 0.01592, 0.15206, -0.06263, 0.10885, 0.07086, -0.09137, 0.11738, 0.08138], [0.03166, -0.15423, 0.06542, 0.00166, 0.07675, 0.05465, -0.01221, -0.13803, 0.03585, -0.02655, -0.02693, -0.01938, 0.02522, -0.01874, -0.04885, 0.01979, 0.13392], [0.0504, -0.11058, -0.03902, -0.01234, -0.00425, 0.11687, -0.01215, 0.09621, 0.09487, -0.08429, 0.07638, 0.09279, -0.09618, -0.01356, -0.00372, -0.0232, -0.12821], [-0.07731, -0.07594, -0.01634, -0.00976, 0.08828, 0.00274, 0.02665, 0.08461, 0.01649, 0.12395, -0.05913, -0.06583, -0.03449, 0.07489, -0.03113, 0.01655, -0.06423], [0.08384, 0.05806, -0.12131, 0.06316, -0.00484, -0.06367, -0.07701, 0.08677, -0.00157, -0.03262, -0.1099, -0.01937, 0.0726, 0.04419, 0.05168, -0.05895, 0.02892], [-0.02865, -0.1617, -0.02482, 0.03045, 0.04069, 0.07013, -0.0112, 0.17338, 0.01679, -0.04209, -0.0562, 0.05343, -0.01037, -0.04746, -0.14743, 0.07367, 0.07138], [0.06547, -0.14234, -0.04544, 0.08641, 0.09736, 0.02947, 0.01268, 0.18163, -0.0261, -0.04342, 0.15253, -0.18117, -0.26861, 0.05091, -0.03508, 0.02682, 0.03887], [-0.0852, -0.01489, 0.31036, -0.17371, -0.09569, -0.21408, -0.09198, -0.04397, 0.00385, -0.2121, -0.005, 0.02651, -0.05865, 0.13927, 0.0725, 0.18636, 0.25643], [-0.12544, 0.12842, -0.17026, 0.17178, 0.02779, 0.01374, 0.1268, -0.10551, 0.01401, -0.0071, -0.02947, -0.15272, 0.0164, 0.11091, 0.03371, 0.00926, -0.06232], [0.00691, 0.01206, 0.15202, -0.06866, -0.14488, 0.01932, 0.06662, 0.08023, 0.01559, -0.16008, 0.08338, -0.04799, 0.00039, -0.01019, -0.09646, 0.11904, -0.0273], [-0.11784, 0.00485, -0.11397, -0.15307, 0.13906, 0.03923, -0.02822, 0.18474, -0.05411, 0.10521, 0.17602, -0.09433, 0.01967, -0.12158, 0.13935, 0.03332, -0.15834], [0.02303, -0.17493, 0.25333, -0.06057, -0.03851, -0.02439, 0.11844, -0.10741, -0.06457, -0.03651, 0.15884, 0.01607, 0.03293, 0.1059, -0.08213, -0.12497, 0.00547], [0.27018, -0.15396, -0.07423, -0.22325, 0.12868, 0.02237, -0.07824, 0.20837, -0.10918, 0.00757, 0.08383, 0.06205, -0.07607, 0.00892, -0.1053, -0.0654, 0.09365], [-0.02554, 0.08088, -0.07223, 0.21202, -0.09513, -0.04176, 0.13961, 0.02831, -0.08552, -0.10545, -0.04848, -0.09597, 0.02512, 0.02163, 0.11761, -0.00836, -0.04674], [0.0771, -0.0282, 0.1473, 0.15027, 0.17571, -0.08958, -0.04556, 0.00915, -0.01463, 0.01732, 0.19728, -0.34865, -0.18497, -0.09126, -0.15812, 6e-05, 0.18675], [0.01178, -0.20403, 0.12363, 0.04853, 0.09225, -0.01656, -0.09344, 0.07925, 0.00929, 0.055, 0.01955, 0.13979, -0.16056, 0.0961, 0.08375, -0.10514, -0.17918], [0.08168, 0.13873, -0.10097, 0.10268, 0.01337, -0.02778, 0.03469, -0.08016, -0.00409, 0.14435, -0.08899, -0.18075, -0.00912, -0.19099, 0.1657, -0.16169, 0.16331], [0.09759, -0.08567, 0.03451, 0.14276, -0.06733, 0.08618, -0.08904, 0.09919, -0.13289, -0.08803, -0.06231, -0.04994, 0.05211, -0.01147, 0.12159, -0.06125, 0.01401], [-0.06139, -0.0535, 0.13589, -0.19434, 0.31513, -0.0239, -0.08931, 0.12228, 0.00208, 0.07027, -0.01207, 0.03898, -0.00093, -0.00015, -0.23111, -0.15598, 0.13805], [-0.01997, 0.01956, 0.06902, 0.14812, -0.05921, -0.01303, 0.02735, -0.00604, -0.13392, 0.01836, 0.10854, -0.00945, -0.01909, -0.01305, -0.01018, -0.05204, -0.05496], [-0.06724, 0.0194, 0.03653, -0.01064, -0.06609, 0.06422, -0.01988, -0.01908, -0.19441, 0.0505, 0.06304, -0.16303, -0.03947, 0.08592, -0.01851, 0.13828, 0.14047], [0.0123, 0.09951, 0.00742, -0.02726, -0.16913, 0.06056, -0.11443, 0.08439, 0.20527, -0.07969, -0.01765, 0.02772, -0.11854, 0.03169, 0.02094, 0.0412, -0.06429], [-0.04935, 0.05417, -0.12292, -0.27584, 0.02637, -0.08498, 0.10449, -0.06179, 0.05503, 0.20613, -0.15946, 0.16814, 0.13656, 0.08098, -0.22259, 0.03812, 0.10695], [0.05871, -0.12056, -0.10617, -0.00763, 0.10712, -0.08142, -0.17175, -0.08759, 0.08615, 0.21288, 0.04602, -0.16994, 0.0107, 0.06195, -0.05094, 0.08234, 0.13013], [-0.1168, 0.06679, -0.0291, 0.08762, 0.06001, -0.11338, -0.03239, 0.11392, 0.02216, -0.08742, 0.03974, 0.06116, -0.13789, 0.04849, -0.01732, 0.0331, 0.00131], [-0.00318, -0.04428, 0.07266, -0.1412, 0.17722, 0.04019, -0.15413, 0.03067, -0.05923, 0.00653, -0.06008, 0.08342, 0.06803, -0.08466, 0.07678, 0.08451, -0.09324], [0.10256, -0.13282, -0.00029, 0.02176, -0.08638, 0.07544, 0.01757, 0.07221, -0.01025, -0.00949, 0.06107, 0.01933, -0.05729, -0.00853, -0.06662, -0.11511, 0.11684], [0.02529, -0.06359, -0.10649, -0.02658, -0.12994, -0.10191, 0.27524, -0.08728, -0.0185, -0.09664, 0.20083, 0.06845, -0.1359, 0.13332, -0.03478, 0.07424, 0.02424], [0.06451, -0.01905, 0.02161, 0.07983, -0.05945, 0.14544, -0.13518, 0.1021, -0.01766, 0.01058, -0.10459, -0.00836, -0.00298, -0.04842, 0.08793, -0.11839, 0.00209], [0.02403, 0.1691, 0.1091, -0.10491, -0.06809, -0.03297, 0.11168, -0.12809, -0.01091, -0.03999, -0.03364, 0.0792, -0.1047, -0.05933, 0.13399, -0.03576, -0.00868], [-0.15252, 0.15043, 0.19426, 0.22779, 0.05794, 0.01684, 0.04398, -0.10379, -0.08864, -0.21873, 0.16659, -0.16929, -0.23578, -0.11268, 0.15571, 0.14808, -0.0802], [-0.01342, 0.06995, -0.10026, 0.01557, 0.08249, -0.0407, 0.13766, -0.2795, -0.01609, 0.26113, -0.15997, 0.01372, -0.26317, 0.0756, 0.1459, 0.10168, -0.03059], [-0.06291, 0.05451, -0.17992, 0.04119, 0.01708, 0.18041, 0.11826, -0.17848, 0.13996, -0.18347, 0.07162, -0.02851, -0.09798, 0.06732, -0.12157, -0.04648, 0.20897], [-0.10446, 0.13173, -0.04391, 0.12926, -0.02798, -0.03543, 0.02678, -0.15887, -0.01025, -0.03702, -0.09121, -0.07577, 0.06831, 0.00239, 0.12317, 0.09528, 0.008], [-0.06173, 0.00348, -0.15806, 0.12898, -0.06356, -0.10369, 0.16689, -0.13873, -0.08833, -0.03155, -0.03203, 0.15236, -0.16144, -0.07062, 0.0289, -0.00409, 0.43322], [-0.14916, -0.23161, -0.04627, -0.00653, 0.17155, -0.00481, -0.00686, 0.19708, -0.01308, 0.00904, -0.09162, 0.10447, 0.20839, -0.0624, 0.2087, -0.15117, -0.13573], [0.06153, 0.23743, -0.10417, 0.21368, 0.03919, 0.07575, -0.14323, -0.0218, -0.10699, -0.07176, -0.09577, -0.13184, -0.07746, -0.1448, 0.00796, 0.10858, 0.15369], [0.10821, 0.17707, 0.04872, 0.3144, -0.07682, -0.10049, -0.12005, -0.06081, -0.07191, -0.09912, 0.02084, -0.20452, -0.14464, 0.20535, -0.15028, 0.20111, -0.04706], [0.0864, 0.04357, 0.06295, 0.01751, 0.01532, -0.01796, 0.1192, -0.00326, -0.09302, 0.16458, -0.14273, -0.01147, 0.02443, 0.08254, -0.12031, 0.0837, -0.31145], [0.05834, -0.00998, 0.0178, -0.03282, 0.08743, -0.0835, 0.0353, 0.0506, -0.0391, 0.04921, 0.09163, 0.02957, 0.12762, -0.18752, 0.00434, -0.04137, -0.15758], [0.06594, -0.05877, 0.06012, 0.18559, 0.00652, -0.05922, -0.11529, 0.01111, -0.16492, 0.02026, 0.06888, 0.07039, -0.01015, -0.18661, 0.1279, 0.09947, -0.12121], [-0.1246, -0.07118, 0.13315, -0.03029, -0.02626, 0.15037, -0.01498, -0.25224, 0.15569, -0.03131, -0.05427, -0.10649, 0.1558, 0.10799, -0.10181, 0.02522, 0.0852], [0.09208, -0.00437, 0.01905, 0.08456, -0.11913, 0.03103, -0.01231, 0.12179, 0.23006, 0.02989, 0.1479, -0.22638, -0.22928, -0.00307, -0.12241, 0.07957, -0.11896], [0.02559, -0.08638, -0.18271, -0.09051, -0.07716, -0.02504, 0.00182, 0.0347, 0.00448, 0.14186, -0.0918, -0.03985, 0.12875, 0.07894, 0.05345, -0.14449, 0.26835], [0.03353, -0.08934, -0.02794, -0.21447, -0.03056, 0.01981, 0.01565, 0.00824, 0.06954, -0.0145, -0.14493, 0.08074, 0.21495, 0.14878, 0.06151, -0.04849, -0.08253], [-0.14414, 0.00149, -0.16348, -0.08038, 0.07701, 0.0404, 0.04572, 0.22088, -0.07296, -0.0253, -0.0617, 0.04866, 0.01522, -0.02997, 0.0304, 0.11776, -0.01962], [-0.1891, 0.01196, 0.0101, -0.00227, 0.08878, -0.04441, -0.02332, 0.08157, -0.01345, -0.17237, -0.00375, 0.13238, 0.04382, 0.14303, -0.07905, -0.08165, 0.09772], [0.20028, 0.00534, -0.05175, -0.09006, 0.14794, -0.05861, -0.00703, 0.12285, 0.07357, -0.00487, 0.0872, 0.02531, -0.08296, -0.04582, -0.14565, -0.09693, -0.0788], [0.00025, 0.0138, -0.18644, -0.02001, 0.16302, -0.15477, -0.14583, 0.03814, -0.06831, 0.07228, 0.06408, 0.0101, 0.20444, -0.0139, -0.13218, 0.00523, 0.15011], [-0.16769, -0.01434, -0.13642, 0.02133, -0.10455, -0.0793, 0.18029, 0.25774, 0.16782, 0.02534, -0.22349, 0.1287, 0.03366, -0.03285, 0.20388, -0.13871, -0.12139], [-0.04904, -0.06286, -0.08281, 0.04519, 0.09221, -0.06153, -0.04433, -0.14355, 0.02577, -0.06934, 0.15464, -0.02654, -0.01838, 0.0601, 0.16263, -0.05407, 0.07191], [0.14323, 0.01454, 0.09143, -0.11381, 0.02358, 0.01769, 0.22613, -0.19523, -0.01065, -0.13323, 0.03729, 0.07807, -0.14296, 0.03609, -0.02566, -0.08763, 0.0411], [-0.16565, -0.07244, -0.00115, 0.02824, 0.03322, -0.07918, 0.15357, 0.13857, 0.06009, -0.07734, 0.01809, 0.08109, 0.1105, -0.10021, 0.09249, -0.11131, -0.10858], [0.17757, 0.08076, 0.22304, 0.04088, 0.01993, 0.03364, -0.18874, -0.05452, -0.00525, -0.13017, -0.02797, -0.12833, 0.01811, -0.13846, 0.04647, -0.08853, 0.12156], [-0.13994, -0.02785, 0.0821, -0.04953, -0.02322, 0.02271, -0.03734, 0.04151, -0.07791, 0.06573, 0.05597, 0.13474, -0.04832, 0.02566, -0.08212, 0.15618, -0.09838], [0.10038, 0.02716, -0.13595, -0.10796, -0.02521, -0.0191, 0.03739, -0.00209, 0.12415, 0.13574, -0.07257, -0.04776, 0.12632, -0.00225, 0.06513, -0.09816, -0.10522], [-0.06342, 0.04775, 0.03171, 0.09351, 0.05435, -0.16113, 0.05991, -0.00167, -0.06819, -0.05868, -0.07225, 0.08443, 0.05203, -0.11964, -0.05411, -0.02641, 0.20181], [-0.01285, -0.02237, -0.1442, -0.29563, -0.02657, 0.03557, 0.03003, -0.1054, 0.00745, 0.13931, 0.14981, 0.15689, 0.13499, 0.18897, -0.04348, 0.03063, -0.22315], [0.08033, 0.05354, -0.08096, 0.08262, -0.20109, -0.0512, 0.15863, 0.07647, 0.06983, -0.01036, -0.01354, 0.31272, -0.06926, -0.30869, -0.01918, 0.01289, -0.09274], [-0.07802, 0.0201, -0.11249, 0.40821, 0.04228, -0.09803, 0.0248, -0.1935, -0.05177, 0.02507, 0.16028, -0.00797, -0.00333, -0.15462, -0.21441, -0.01531, 0.24871], [-0.0452, -0.0031, -0.07584, 0.12631, -0.16147, -0.01421, 0.04409, 0.18573, -0.05778, 0.09951, 0.01946, 0.02909, 0.005, -0.06413, -0.00804, -0.01146, -0.06796], [0.08627, -0.13839, -0.34977, -0.05168, 0.15652, 0.13227, -0.07323, 0.07292, 0.12145, 0.07705, 0.05592, 0.02904, 0.05816, 0.18193, -0.14625, -0.16505, -0.04717], [0.04973, -0.03661, 0.19587, 0.05084, -0.03301, -0.02036, 0.01032, 0.015, -0.15924, -0.06975, -0.11334, -0.00172, -0.04791, -0.07196, 0.08406, 0.0852, 0.06286], [0.17809, -0.18156, 0.11545, -0.07858, 0.11808, -0.04623, 0.0137, 0.00672, 0.09305, -0.13136, -0.23961, -0.0017, -0.00293, -0.11773, 0.03636, 0.10456, 0.13369], [0.08034, -0.05237, -0.17873, -0.07219, 0.01695, -0.05978, -0.01202, 0.02067, 0.13973, -0.04377, -0.15343, -0.03491, 0.02709, 0.3009, -0.09703, -0.0156, 0.13417], [-0.13237, -0.14343, 0.03969, 0.17012, -0.0569, -0.15844, -0.06047, -0.01121, 0.12449, -0.05155, -0.24261, 0.02338, 0.02231, 0.05027, 0.04151, 0.25029, 0.13494], [-0.13877, -0.0716, 0.22749, 0.11727, 0.09525, -0.12295, 0.17268, -0.22843, -0.08613, 0.11445, -0.1015, -0.03434, -0.07362, 0.09762, -0.175, 0.13758, 0.07], [-0.03821, 0.14302, 0.04701, 0.2018, 0.03742, 0.00789, -0.09942, 0.10313, 0.04249, -0.09704, -0.05986, 0.0225, 0.11441, 0.00537, -0.27544, -0.08745, -0.06763], [-0.02641, -0.05421, 0.16114, -0.09528, 0.02774, -0.0678, -0.12201, -0.12088, -0.02168, -0.11625, 0.02774, 0.10168, 0.18976, 0.16486, 0.03156, 0.11783, -0.19779], [0.04799, 0.02727, 0.01549, -0.07581, -0.08949, -0.13267, 0.21268, -0.02034, -0.02146, 0.12984, 0.01568, 0.02733, -0.01917, 0.08023, 0.07883, 0.08257, -0.35898], [0.10541, -0.11077, 0.00903, -0.0932, 0.05209, 0.0587, 0.02216, 0.02534, 0.10409, 0.12771, -0.14811, -0.04445, -0.14131, 0.0708, -0.12353, 0.10872, -0.02268], [-0.01205, -0.08891, -0.14882, -0.25295, -0.10153, -0.08274, -0.02892, 0.41965, 0.03665, -0.14815, 0.10153, 0.22178, 0.03339, -0.06165, 0.13752, -0.10137, 0.07658], [-0.16888, -0.12441, 0.33322, 0.04403, 0.02411, -0.07275, 0.04628, 0.18189, 0.13842, 0.1063, -0.0663, -0.08366, -0.01776, -0.14725, 0.05342, 0.00305, -0.24973], [0.04348, 0.02528, -0.00508, -0.06231, -0.22823, 0.07145, 0.11488, -0.1287, -0.01183, 0.03126, -0.01376, 0.0708, -0.01179, 0.01019, -0.06341, -0.01199, 0.16976], [-0.21772, 0.11573, 0.12278, 0.06119, 0.03995, -0.05847, -0.03353, 0.04695, -0.12918, 0.06328, -0.09485, -0.01253, 0.07364, 0.0599, -0.11648, -0.1513, 0.23062], [-0.09793, -0.14081, 0.0847, 0.12608, 0.00139, 0.01215, -0.12646, 0.07492, 0.33008, -0.17921, 0.02037, -0.00649, 0.12257, 0.07356, -0.04933, -0.14447, -0.10111], [-0.11938, -0.03448, -0.04883, -0.26384, 0.11794, -0.01943, -0.10275, -0.02793, 0.27373, -0.09467, 0.03101, -0.13229, 0.22282, 0.06064, 0.07759, -0.05445, 0.11433], [0.00074, -0.07538, -0.13959, -0.07454, -0.07844, -0.00301, -0.06418, -0.01427, 0.05885, 0.01729, 0.07749, 0.18411, -0.0912, 0.00619, -0.01517, -0.00834, 0.21946], [0.0482, 0.06702, -0.04882, -0.21043, -9e-05, -0.09226, -0.08838, -0.07645, -0.02096, 0.0574, 0.09823, 0.1671, -0.04882, 0.05561, 0.05299, -0.11397, 0.15364], [-0.00425, -0.24374, 0.07243, -0.00301, -0.13595, 0.01601, 0.06201, -0.04244, 0.15867, -0.03166, 0.1485, 0.00446, -0.01585, 0.19554, -0.03863, 0.00757, -0.14965], [-0.06355, -0.11011, -0.05576, -0.07065, 0.16801, -0.07043, -0.04928, 0.09712, 0.14038, 0.20095, -0.04647, -0.11432, 0.11491, -0.11973, 0.08627, -0.14169, 0.03436], [-0.14865, 0.18884, -0.00829, -0.02495, -0.04666, 0.01798, 0.07121, 0.1753, -0.02172, -0.00156, 0.15368, -0.0001, -0.1798, -0.06814, -0.05213, -0.09331, 0.03829], [0.03382, 0.25003, -0.00477, -0.1474, 0.06657, -0.02412, -0.09031, -0.02715, 0.05169, -0.00311, 0.09269, -0.07785, 0.08832, -0.10897, 0.11131, -0.07251, -0.13824], [-0.15817, -0.08632, 0.19186, -0.06527, 0.04561, -0.00432, -0.1846, -0.08848, 0.05803, 0.19322, 0.21433, -0.08555, -0.00815, 0.02684, -0.15034, 0.14803, -0.0467], [0.00154, -0.08291, 0.10585, 0.02984, 0.0392, -0.07827, 0.02064, -0.09615, -0.02805, -0.02991, -0.00735, -0.01501, 0.09348, 0.09668, -0.03834, -0.14484, 0.13358], [0.04677, 0.16467, 0.05924, 0.07257, 0.05958, -0.12949, -0.14239, 0.05393, 0.04999, -0.07699, -0.05305, 0.08821, -0.00219, -0.07276, 0.1285, -0.12919, -0.1174], [-0.01694, 0.08042, -0.07134, 0.03004, 0.05416, -0.18746, 0.12398, 0.05575, -0.06035, 0.07701, -0.03927, -0.08648, 0.0751, 0.02664, -0.07132, 0.03723, -0.02718], [-0.06283, 0.02992, 0.05023, -0.13675, 0.06604, -0.01879, 0.21569, 0.1205, 0.10298, 0.18152, -0.21609, -0.20983, -0.25518, 0.1963, -0.05287, -0.17363, 0.16278], [-0.08843, -0.02315, 0.06727, -0.03869, 0.08287, -0.01078, -0.02237, 0.03662, 0.19474, -0.13969, -0.00461, -0.09856, 0.11154, 0.08186, -0.01675, -0.00267, -0.12923], [0.11002, 0.0388, 0.02379, -0.09481, -0.16233, 0.00713, 0.11412, -0.10552, -0.06467, -0.02331, 0.04519, -0.00774, -0.0969, 0.0825, 0.00656, 0.01129, 0.11588], [-0.08053, 0.0672, -0.08053, -0.12568, -0.14547, 0.10235, 0.14933, 0.03929, 0.04406, 0.11202, -0.01593, 0.10599, 0.07631, -0.24434, 0.12362, -0.00451, -0.12317], [0.06881, 0.01602, -0.02664, 0.13317, 0.00335, -0.05069, -0.02594, 0.03404, 0.06883, 0.19699, 0.11733, -0.18005, -0.07273, -0.09108, -0.15122, -0.0386, -0.0016], [-0.16317, 0.03629, 0.06155, -0.1004, 0.02722, -0.03525, 0.05353, -0.26798, 0.08877, -0.00476, 0.10689, 0.04734, -0.03953, -0.12105, 0.13143, 0.15717, 0.02196], [-0.07881, 0.02126, 0.09657, -0.04225, -0.03817, 0.05338, 0.02873, -0.00385, 0.02616, -0.02139, 0.03374, 0.11021, -0.16436, -0.08994, -0.0139, 0.05147, 0.03114], [0.05149, 0.02629, 0.25141, 0.07928, 0.03854, 0.08822, -0.07175, -0.00267, -0.06501, 0.04536, -0.05149, -0.15369, 0.20303, -0.10649, -0.12104, -0.07522, -0.13624], [-0.06255, 0.05865, 0.18769, 0.18906, 0.0922, -0.02167, -0.18691, -0.32389, -0.05288, -0.16801, 0.17925, 0.09525, -0.0442, 0.03734, -0.14627, 0.06875, 0.09819], [0.34115, 0.04399, -0.16038, 0.00204, -0.19408, 0.05336, 0.15999, -0.05126, 0.00101, -0.10172, 0.04648, -0.12628, -0.02241, 0.14192, -0.02192, -0.04452, -0.06738], [-0.09449, -0.00703, 0.15423, -0.03191, 0.07147, -0.00128, -0.09664, 0.07455, 0.10951, -0.12236, 0.0532, -0.00226, 0.05, -0.05467, -0.08557, -0.01913, 0.00238], [-0.00391, 0.00941, 0.06276, 0.09142, -0.0022, 0.02321, -0.14772, -0.03083, 0.0575, 0.01419, -0.00888, -0.00507, 0.0289, 0.12533, 0.02374, -0.01804, -0.21982], [-0.01701, 0.08951, 0.07942, -0.04, 0.03786, -0.2258, 0.05328, 0.16648, -0.07365, 0.02357, -0.16812, -0.11956, 0.08649, -0.02743, 0.00983, 0.11608, 0.00905], [-0.03546, -0.07717, 0.17749, 0.01527, -0.01708, 0.00172, 0.12993, 0.19671, 0.0699, -0.01603, -0.15107, -0.06879, -0.04441, -0.10888, -0.22841, 0.08585, 0.07042], [-0.03702, -0.01112, 0.13284, 0.02723, 0.00434, -0.0603, -0.02252, 0.14078, 0.10843, 0.03253, 0.00275, -0.1249, -0.03088, -0.07895, 0.09394, 0.00044, -0.1776], [0.20563, 0.14247, 0.07852, 0.03006, 0.20036, -0.13127, -0.01074, 0.05512, -0.09817, -0.08333, -0.12893, -0.19641, -0.08107, -0.22672, 0.2715, -0.2541, 0.22707], [0.02207, -0.00433, 0.05601, 0.0152, 0.02417, -0.00901, 0.07845, 0.00215, -0.01815, 0.04997, 0.01848, 0.00247, -0.01475, -0.04027, -0.05516, -0.04484, -0.08245], [-0.01639, 0.14014, -0.06584, 0.06899, -0.11948, -0.01696, 0.08096, 0.05491, -0.15456, 0.04588, -0.26658, 0.17356, 0.04054, -0.03527, 0.01435, 0.09168, -0.03593], [-0.03488, 0.01202, -0.16147, -0.03677, -0.02148, -0.10562, 0.04725, 0.04018, -0.01664, -0.17733, 0.1371, 0.0232, 0.06282, -0.01592, 0.03865, 0.00475, 0.20414], [-0.04974, -0.07949, -0.07903, -0.00136, 0.10279, 0.16557, 0.20821, -0.10391, 0.12631, -0.20395, 0.10609, 0.00838, 0.00616, -0.15056, 0.13889, -0.1181, -0.07625], [0.25287, -0.05806, -0.08839, -0.03818, -0.07564, -0.01809, 0.02795, -0.07907, 0.13508, -0.02831, 0.14515, -0.02986, 0.02779, 2e-05, -0.00683, -0.00258, -0.16386], [-0.03765, 0.07455, -0.10118, -0.08318, 0.19659, 0.08752, 0.01115, -0.07622, 0.05084, 0.06169, 0.01094, 0.06729, -0.09172, -0.10844, 0.0681, -0.09463, -0.03567], [0.13918, 0.14219, 0.03528, -0.03059, 0.11146, -0.11583, -0.09392, -0.1987, 0.04178, -0.01614, -0.07933, 0.02863, 0.08004, 0.08329, 0.18832, 0.03538, -0.35104], [0.07114, -0.008, -0.07661, 0.02508, 0.05958, 0.05017, -0.1619, -0.07367, 0.1648, -0.06145, 0.1576, 0.09986, 0.20434, -0.22817, -0.04621, -0.18192, 0.00536], [-0.00716, 0.13872, 0.10924, -0.05786, -0.03413, 0.0157, 0.10093, 0.10253, -0.03616, 0.07255, -0.0389, 0.07245, 0.0507, -0.08892, 0.08028, -0.3194, -0.16057], [0.03969, 0.02997, 0.08176, -0.1014, 0.01645, -0.04394, -0.0265, 0.18085, -0.02404, 0.04688, -0.07037, -0.1189, -0.03012, -0.00465, 0.05159, -0.11893, 0.09165], [0.09824, -0.06379, 0.09034, -0.1275, -0.00532, -0.05855, 0.21656, 0.18948, -0.1357, 0.18958, -0.00832, -0.11852, -0.09454, 0.01909, 0.07218, -0.10372, -0.1595], [-0.05119, -0.16851, -0.09239, -0.13143, 0.10027, 0.02047, -0.00985, 0.09844, 0.08166, -0.05502, 0.05184, 0.05693, 0.06457, -0.10161, 0.01387, -0.03976, 0.16171], [0.09082, 0.07612, -0.18671, -0.09524, 0.00982, -0.07696, -0.07628, -0.01974, 0.19114, 0.0374, 0.0392, 0.01333, -0.08192, 0.14948, -0.06498, 0.09429, -0.09975], [0.02559, -0.00981, -0.07191, -0.06271, 0.09857, -0.07315, 0.07691, 0.04783, -0.08138, -0.0616, -0.10334, 0.03781, 0.2225, -0.04419, 0.05957, 0.01189, -0.07259], [0.23104, 0.00219, -0.02113, 0.00535, 0.10273, -0.04105, -0.00063, 0.18655, -0.19569, -0.13171, 0.02792, 0.06983, -0.2095, 0.08356, 0.18039, -0.04225, -0.2476], [0.13307, 0.04699, 0.10963, 0.08761, -0.10273, 0.04111, -0.24804, -0.04311, -0.0853, -0.08495, 0.14193, 0.08475, 0.05313, -0.02783, 0.10527, -0.15876, -0.05277], [0.044, 0.04742, 0.18463, -0.10604, -0.00194, 0.04758, 0.00737, -0.03377, 0.1013, 0.0736, 0.0549, -0.04777, -0.19562, 0.13043, -0.07379, -0.0768, -0.1555], [0.09907, 0.11207, -0.12654, -0.01959, -0.17589, 0.08649, 0.03798, 0.14229, -0.11077, 0.04967, -0.08552, 0.04194, -0.01106, -0.0487, -0.1161, -0.02842, 0.15307], [0.17176, -0.28161, 0.08833, -0.23141, 0.21541, 0.0853, 0.06069, -0.18673, 0.01024, -0.0432, 0.27713, 0.21526, -0.1782, -0.0465, 0.06109, -0.06318, -0.15437], [0.06386, -0.02511, 0.03167, -0.1268, 0.01643, -0.01147, 0.05071, 0.0303, 0.01815, -0.02614, 0.21813, 0.00297, 0.02858, -0.00716, -0.11445, -0.20936, 0.05972], [0.12521, -0.02572, -0.17359, 0.07603, 0.00503, -0.10283, 0.17829, 0.10351, -0.02179, 0.03928, -0.11651, 0.00678, -0.04797, 0.08641, -0.02285, -0.03179, -0.07749], [0.11799, 0.01356, -0.05922, 0.07564, -0.06575, -0.03482, -0.17908, 0.20818, 0.1253, 0.12869, -0.11348, -0.02094, 0.11635, -0.10286, 0.04412, -0.04527, -0.20839], [-0.03109, -0.09043, 0.05683, 0.05542, 0.08206, 0.0402, 0.04045, 0.1026, 0.03042, -0.02359, -0.0379, -0.03362, -0.15516, -0.0106, 0.00848, -0.00809, -0.02597], [0.09241, -0.08519, 0.12308, -0.0448, 0.0051, -0.13686, -0.00462, -0.01819, -0.09828, 0.07328, -0.01748, 0.01957, 0.12201, 0.09936, 0.04891, -0.14319, -0.03509], [0.03296, -0.10039, 0.02215, 0.14222, -0.15745, -0.17088, 0.01942, 0.22038, -0.05599, -0.08936, 0.08012, 0.05423, 0.07934, -0.02652, 0.11143, -0.15565, -0.00601], [-0.03881, -0.05326, -0.00898, 0.02468, -0.11324, 0.01008, -0.05709, 0.07147, -0.06958, 0.07941, -0.07825, 0.0715, -0.01441, 0.13995, -0.10476, -0.02044, 0.16171], [-0.03643, 0.08752, -0.16127, 0.0439, 0.01819, 0.12632, 0.04704, -0.20519, 0.01793, 0.17151, 0.02954, 0.11453, -0.03539, -0.10456, 0.03519, -0.05604, -0.09277], [0.16888, -0.04, -0.12374, 0.07369, 0.04496, -0.14965, -0.00214, -0.07138, -0.03171, -0.05922, -0.15177, -0.01509, 0.02045, 0.05087, 0.22877, -0.08216, 0.13923], [0.04868, -0.25874, -0.07591, 0.1855, 0.14091, -0.00142, -0.12692, -0.16581, 0.15229, 0.18227, -0.13734, 0.07868, -0.13048, -0.00254, 0.06052, 0.00144, 0.04887], [0.06295, 0.24438, 0.04881, -0.08671, -0.09309, -0.07274, 0.21456, -0.25989, -0.00969, 0.10231, 0.02114, -0.01129, -0.12744, -0.11498, 0.08598, 0.1898, -0.19411], [0.0475, 0.09519, -0.01248, -0.16205, 0.00427, 0.02034, 0.02189, 0.02129, -0.05519, 0.07719, -0.06401, -0.00967, -0.05274, -0.15809, -0.04393, 0.05735, 0.21313], [0.10097, -0.05285, -0.13549, 0.16051, -0.01203, 0.06609, -0.02082, 0.20367, -0.04511, -0.1345, 0.10513, -0.01467, -0.03396, 0.1863, -0.00588, -0.18033, -0.18704], [0.32301, -0.11442, -0.03854, -0.0656, -0.03328, 0.10986, 0.1299, -0.0208, 0.01765, 0.20324, -0.05703, -0.05354, -0.13092, -0.05542, 0.0096, 0.02607, -0.24979], [-0.16156, 0.12071, -0.17204, -0.24568, 0.03894, 0.04273, 0.0394, -0.00592, 0.1744, 0.02835, -0.08866, 0.09934, 0.21017, -0.17539, 0.10506, 0.05604, -0.06588], [0.03356, -0.00973, -0.04119, 0.0643, 0.10668, 0.09541, 0.04002, -0.02702, -0.05741, -0.06601, 0.182, -0.04342, -0.04265, 0.00335, -0.15991, 0.11715, -0.19512], [-0.0301, -0.04032, 0.04708, 0.02583, 0.0865, 0.1348, -0.06731, -0.0832, 0.03615, -0.06215, -0.01403, 0.05026, -0.05189, 0.08981, -0.08788, -0.01635, -0.01718], [-0.06501, -0.02313, 0.17524, 0.03985, -0.03832, -0.00019, -0.24697, 0.28422, -0.02162, -0.01131, -0.29024, -0.14637, 0.08485, 0.13903, 0.0593, 0.12931, -0.06864], [-0.06364, 0.31261, 0.14577, -0.04143, -0.01409, 0.01943, -0.00073, -0.27249, -0.0229, 0.11798, 0.03598, 0.11998, -0.05475, 0.01546, -0.02745, -0.1446, -0.12513], [0.10896, 0.01842, -0.06201, -0.14962, -0.00206, 0.07408, 0.11977, -0.13709, -0.07582, 0.08061, -0.07672, -0.01632, -0.00817, -0.03956, 0.08578, 0.1101, -0.03034], [-0.03107, 0.12286, 0.02711, 0.05594, 0.08859, 0.00352, 0.03076, -0.04211, -0.04843, -0.20124, -0.0969, 0.03255, 0.01465, -0.0741, 0.17886, 0.01798, -0.07899], [-0.02204, 0.10128, 0.06129, -0.00534, -0.01924, -0.08205, 0.30488, -0.08221, -0.15379, -0.03203, 0.03216, -0.1265, -0.04205, 0.19202, -0.1468, 0.19537, -0.17495], [0.08942, 0.03027, -0.08726, 0.05618, -0.19773, 0.01676, 0.14642, -0.12472, -0.16347, 0.13126, 0.02044, -0.03818, -0.19005, -0.04142, 0.02474, 0.05726, 0.27011], [0.10229, -0.0775, 0.14579, -0.0736, -0.01974, 0.09841, -0.12588, 0.16569, -0.12282, -0.00378, -0.11909, -0.12829, -0.04353, 0.24066, -0.00991, 0.13788, -0.16658], [-0.0008, -0.05838, 0.05095, 0.00926, -0.05145, -0.06246, -0.07776, 0.02935, -0.11402, 0.00747, 0.20823, 0.09745, -0.07036, 0.07787, 0.00308, -0.09604, 0.04762], [-0.04685, -0.07157, 0.10047, 0.0294, -0.05391, 0.11417, -0.04768, -0.09568, -0.14518, -0.00929, -0.01268, -0.02183, 0.17326, 0.05582, 0.05778, 0.12045, -0.14667], [0.19226, 0.0295, -0.02416, 0.03475, -0.04904, 0.16194, -0.09547, 0.05387, -0.01629, -0.1869, -0.0149, 0.13366, -0.1633, -0.0023, 0.05079, 0.06257, -0.16698], [0.08566, -0.01118, 0.10918, 0.17253, 0.19426, -0.06846, -0.29011, 0.00279, -0.14522, -0.05219, 0.1508, -0.03087, -0.06695, 0.00378, -0.22189, 0.0429, 0.12497], [-0.04597, 0.06661, -0.13624, 0.15451, -0.045, 0.00644, 0.11035, -0.11923, 0.02913, 0.07503, 0.04443, -0.07426, 0.08915, -0.07877, 0.08011, -0.12203, -0.03425], [-0.02662, -0.12844, -0.07005, 0.07407, 0.05671, 0.00634, 0.13711, 0.03888, -0.01175, -0.02406, 0.00678, -0.1914, 0.05902, -0.01581, -0.12138, -0.00424, 0.21484], [-0.00561, -0.09666, 0.13914, -0.02979, -0.05012, -0.06753, -0.04077, -0.11923, 0.02831, -0.07363, 0.09809, 0.03174, 0.19764, -0.07632, -0.00954, 0.08185, -0.00758], [0.01884, -0.17886, 0.06234, -0.01893, 0.13203, -0.00137, 0.09315, -0.17343, -0.06155, 0.2135, -0.02508, -0.01459, -0.08983, -0.06284, 0.08249, 0.09211, -0.06801], [0.01132, 0.04956, 0.06113, 0.00236, 0.06861, -0.16958, -0.11313, -0.01827, 0.03351, 0.00863, 0.14412, -0.1308, 0.00857, -0.06706, 0.10303, -0.0992, 0.10719], [0.1788, -0.08029, 0.23218, -0.07668, -0.14053, -0.08445, 0.00949, 0.15298, -0.22192, 0.02719, -0.10733, -0.01793, -0.02746, 0.12255, -0.00477, -0.07404, 0.1122], [-0.20748, 0.19589, -0.13558, 0.11083, -0.02208, 0.11649, 0.04559, 0.03579, -0.01134, -0.01849, -0.03125, -0.07825, -0.18536, 0.06118, 0.22198, 0.05827, -0.15617], [0.1286, 0.03591, -0.14958, 0.12047, -0.0734, 0.03221, 0.00273, -0.22466, 0.13646, -0.06611, 0.02898, -0.01965, -0.01661, 0.03945, -0.07248, 0.15794, -0.06029], [-0.10756, -0.04178, 0.05523, 0.229, -0.13003, -0.04139, -0.03178, 0.25026, 0.14618, -0.12501, -0.17553, -0.0025, -0.04211, -0.09317, 0.19426, -0.08363, -0.00044], [-0.01865, 0.02639, 0.10049, -0.11536, 0.16973, 0.08691, -0.2199, -0.06554, -0.03674, 0.05267, -0.19185, 0.0435, 0.11106, 0.03882, 0.03417, 0.0201, -0.0358], [-0.0106, -0.03034, 0.23377, -0.17743, -1e-05, -0.10387, 0.17263, -0.01408, -0.0715, 0.02451, 0.03825, -0.04335, -0.09232, 0.01416, -0.03509, 0.01274, 0.08253], [0.01096, -0.07631, -0.13939, -0.06755, 0.11226, -0.08333, 0.00503, -0.07624, 0.15553, -0.08292, 0.01733, 0.14712, -0.06743, 0.02656, 0.08391, 0.02205, 0.01241], [0.0047, 0.10576, 0.02531, 0.16489, -0.00916, -0.0627, -0.09962, -0.10729, 0.06045, 0.02052, -0.26238, -0.04901, 0.15955, -0.05789, 0.04492, 0.07276, -0.01082], [-0.07232, -0.01823, 0.01722, -0.01623, 0.01947, 0.0492, -0.0259, 0.01851, 0.04863, 0.14738, -0.01488, -0.05122, -0.07751, -0.01385, -0.03277, 0.03155, -0.00905], [-0.07969, -0.12707, 0.09623, 0.01421, -0.16528, 0.0134, 0.18723, -0.0778, -0.15616, 0.11705, 0.03578, 0.0259, -0.07901, 0.03067, -0.06255, 0.19075, 0.03638], [-0.00948, -0.0392, -0.13008, 0.02446, -0.06019, -0.03209, 0.03854, -0.10733, 0.06137, 0.11546, -0.12447, -0.14768, -0.0121, 0.17371, -0.04304, 0.16134, 0.13078], [0.07467, -0.06426, 0.08925, -0.24296, -0.03773, -0.00218, -0.02771, 0.17489, -0.24339, 0.17237, 0.25834, 0.06827, -0.05804, 0.28914, -0.34569, -0.09908, -0.00589], [-0.07042, 0.06484, -0.06761, -0.07369, -0.13334, 0.12913, 0.05111, 0.10034, -0.00012, 0.02247, -0.03539, 0.02939, -0.05461, -0.12674, 0.08962, 0.07147, 0.00355], [-0.12717, 0.18385, 0.09577, -0.20268, -0.11371, 0.04246, 0.0884, -0.07878, 0.00797, -0.03604, 0.0508, 0.10342, -0.10607, 0.10282, 0.05867, -0.15045, 0.08075], [0.00486, 0.00156, -0.11364, 0.03195, -0.0188, 0.14623, -0.09563, 0.02886, -0.02818, -0.23586, 0.13839, -0.00482, 0.07991, -0.09577, 0.10298, 0.11122, -0.05326], [-0.07249, 0.27494, -0.09428, -0.0348, -0.04559, -0.06963, -0.01901, -0.08183, -0.05013, -0.10602, 0.08975, 0.06985, -0.00664, 0.13248, 0.03198, -0.10291, 0.08431], [0.19021, 0.00885, -0.04006, 0.054, -0.09246, -0.03264, -0.0903, 0.0551, 0.12707, -0.0459, 0.05714, 0.15517, 0.04618, 0.08539, -0.1909, -0.12995, -0.1569], [0.05701, 0.08402, -0.05809, 0.1739, 0.08311, 0.24578, -0.02653, -0.00444, -0.11471, -0.00518, -0.03965, -0.16925, 0.03648, -0.08125, -0.01561, -0.01376, -0.15185], [-0.0121, 0.04481, -0.10348, 0.001, 0.00341, 0.00521, -0.03578, 0.03832, -0.01816, 0.11345, 0.04442, -0.04412, -0.02172, 0.13647, -0.12375, -0.01633, -0.01166], [0.06892, -0.11281, -0.04847, -0.0697, 0.07131, 0.11701, -0.00316, -0.00183, -0.08787, -0.25182, 0.20456, 0.0134, -0.03549, 0.29341, 0.0006, -0.04554, -0.11253], [0.18227, -0.00367, 0.24182, 0.17914, -0.16896, -0.31518, 0.01942, -0.12523, 0.17123, -0.08788, -0.14122, -0.05039, 0.18409, -0.11614, 0.14846, 0.13591, -0.25367], [-0.00477, 0.03214, -0.0431, 0.04267, -0.0825, -0.12059, -0.03446, -0.00817, 0.01147, 0.14467, 0.18549, 0.0342, -0.05124, -0.08998, -0.02199, -0.05098, 0.05713], [0.00748, 0.03013, -0.05289, 0.15706, -0.07326, 0.03361, 0.05087, 0.00082, 0.15567, -0.12918, -0.10455, 0.01129, -0.13095, -0.04835, 0.00645, 0.08838, -0.00258], [0.00667, -0.04627, -0.00273, 0.0376, -0.01389, 0.21998, 0.02711, -0.09496, -0.04588, 0.04896, 0.11192, -0.03808, -0.09657, 0.10407, -0.08009, 0.06466, -0.20249], [0.0451, 0.14264, -0.01336, 0.01763, 0.07622, -0.02209, -0.00701, -0.12453, 0.01994, -0.14071, 0.0481, -0.15902, 0.23092, -0.0272, 0.08286, -0.05898, -0.11051], [-0.05602, -0.09499, 0.02505, 0.00481, -0.14826, 0.00372, -0.10169, -0.00316, -0.07995, 0.10861, -0.0677, 0.09097, 0.22429, -0.02531, 0.01283, 0.13918, -0.03237], [0.15016, -0.10579, -0.02186, -0.05144, -0.0169, 0.13714, -0.03164, -0.03379, 0.03836, -0.1084, 0.09607, 0.07151, 0.05883, -0.16913, 0.12805, -0.11668, -0.02448], [0.14753, -0.11714, 0.03428, -0.27245, -0.07695, -0.08657, -0.01014, 0.15375, 0.09717, 0.11635, 0.14433, 0.08984, -0.10149, 0.05449, -0.04678, 0.03531, -0.16154], [-0.08207, 0.05109, 0.08377, 0.15098, 0.01991, -0.03385, -0.02917, -0.00469, -0.06963, -0.10562, 0.09325, -0.17725, -0.02461, 0.01357, 0.09742, 0.0557, -0.0388], [0.1123, -0.08234, -0.11103, 0.11751, -0.02618, 0.10671, 0.05304, 0.20069, 0.0237, 0.01607, -0.11521, -0.09093, 0.03924, -0.07723, 0.04402, -0.21909, 0.00874], [0.03703, -0.02813, -0.02582, -0.07799, 0.01512, -0.01208, -0.04057, 0.00345, 0.16507, 0.05027, -0.00109, -0.02492, -0.21382, -0.22128, 0.10774, 0.19189, 0.07513], [-0.07367, -0.10807, -0.11911, -0.06714, 0.16107, -0.16606, -0.00285, -0.02312, -0.03805, -0.07598, -0.1383, -0.04539, 0.27663, 0.16654, -0.04901, 0.18151, 0.12098], [-0.07453, -0.09666, 0.09318, 0.00947, 0.18718, -0.05316, -0.16464, 0.02235, -0.07651, 0.06416, 0.08798, -0.07387, 0.06465, -0.05673, 0.10487, 0.05965, -0.09739], [-0.10911, 0.07425, 0.00863, 0.23489, -0.03583, -0.14245, 0.11859, -0.05377, -0.11759, 0.00089, -0.0135, 0.04978, 0.22384, 0.12279, 0.01616, -0.1057, -0.27187], [-0.03962, 0.09643, -0.04701, 0.0539, -0.08016, -0.03257, 0.17049, 0.04652, -0.17007, 0.01226, 0.06317, -0.01234, 0.08565, 0.01773, -0.05041, 0.09062, -0.20459], [-0.01868, -0.12613, -0.17407, -0.02661, 0.04909, 0.00242, 0.06369, -0.03241, 0.11999, -0.01426, -0.19263, 0.14137, 0.0957, 0.10081, -0.04748, 0.0679, -0.0087], [0.09228, 0.02234, -0.03747, 0.15948, -0.09926, -0.0631, 0.12121, 0.04528, -0.05593, -0.03146, 0.01154, -0.07003, 0.01975, -0.1017, 0.04932, -0.16375, 0.1015], [0.0235, 0.04319, -0.06123, -0.2075, -0.02124, 0.1177, 0.07529, -0.11699, -0.00731, 0.12184, 0.19489, -0.0662, -0.04791, -0.147, -0.0299, 0.00649, 0.12239], [-0.17517, 0.01614, 0.00365, -0.06033, 0.06716, 0.04807, -0.07007, 0.07916, -0.13888, -0.03154, 0.05087, 0.08764, 0.06872, -0.214, 0.12193, 0.00974, 0.13692], [-0.04789, 0.18115, 0.17435, 0.22502, -0.19092, -0.14744, 0.09444, -0.11985, 0.00911, -0.15167, 0.02111, 0.04184, 0.05329, 0.11359, -0.12789, -0.06728, -0.06095], [-0.22681, -0.07217, 0.05092, -0.15206, 0.21824, -0.06169, -0.09849, 0.28109, 0.08561, -0.00893, -0.13317, 0.04907, -0.11926, 0.0692, -0.18409, 0.17502, 0.12752], [0.2071, -0.05468, -0.17304, -0.07321, -0.01157, 0.03591, -0.17348, 0.03387, -0.02758, 0.02976, 0.0738, 0.09869, 0.10938, 0.02268, -0.03092, 0.00544, -0.07215], [0.07434, -0.09265, -0.14914, -0.00226, 0.01214, 0.07904, 0.09046, -0.04941, -0.09615, 0.06435, 0.09339, -0.0652, 0.04478, -0.07797, 0.00097, 0.02191, 0.05139], [0.01252, -0.00403, -0.09977, 0.03301, 0.11477, -0.02079, -0.18638, -0.0153, -0.0463, -0.05625, -0.02652, -0.00636, -0.00236, -0.1419, 0.02147, 0.09853, 0.32568], [-0.06477, -0.06601, -0.01677, 0.01975, 0.07458, -0.01965, -0.04748, 0.1593, -0.05125, 0.05677, -0.28083, 0.00644, -0.05538, 0.20246, -0.05092, 0.09296, 0.04079], [-0.10432, 0.01413, -0.01924, 0.08497, 0.0676, 0.00649, -0.19426, 0.09277, 0.14147, 0.00149, 0.05606, -0.12338, -0.06166, 0.08281, -0.0938, 0.0495, -0.00064], [0.07524, 0.12557, -0.06226, 0.17762, -0.04398, -0.13507, 0.0527, 0.05748, 0.00376, -0.09034, -0.0872, 0.06026, -0.22847, -0.09271, 0.1962, 0.05352, -0.0623], [0.03009, -0.11809, 0.09131, -0.18305, -0.0018, -0.03058, -0.18287, 0.25977, 0.0227, 0.22602, -0.1581, -0.03519, -0.03622, 0.06451, -0.11333, 0.03823, 0.1266], [-0.00871, 0.15018, -0.23472, -0.07656, -0.01278, 0.00563, 0.14233, -0.01845, 0.0133, -0.01902, 0.00436, 0.05586, 0.02711, -0.1195, 0.10207, 0.08199, -0.09308], [0.05815, 0.0413, 0.07724, -0.02101, -0.10718, 0.12303, 0.0023, -0.08761, -0.12813, -0.05112, 0.11452, -0.07972, 0.04796, -0.01205, 0.12526, -0.17587, 0.07292], [0.1696, 0.00568, 0.22793, -0.00784, -0.20333, -0.03557, 0.06297, -0.09306, -0.14304, 0.04172, 0.03155, 0.2047, 0.04733, -0.04178, -0.05444, -0.2709, 0.05846], [0.073, 0.10162, -0.24413, 0.02034, -0.0877, -0.03004, 0.04488, -0.02267, 0.06891, -0.06516, -0.03216, -0.00908, -0.01091, -0.08035, 0.17773, -0.00951, 0.10523], [-0.08579, 0.04115, 0.05506, 0.04681, 0.23774, -0.19865, -0.20585, 0.03925, -0.04799, 0.22551, 0.02488, -0.17328, 0.20511, -0.02308, -0.14306, 0.09864, -0.09645], [0.10276, 0.14163, 0.21326, -0.07138, -0.03284, -0.18187, 0.20935, -0.23159, 0.01384, -0.00114, -0.11369, 0.04409, -0.17866, 0.11393, -0.01782, 0.14183, -0.15171], [-0.09332, 0.1559, -0.1118, -0.10806, -0.13579, -0.10208, 0.26592, -0.13873, 0.00958, 0.12159, -0.10636, 0.23737, -0.0344, 0.04206, 0.12958, -0.08085, -0.05062], [-0.14153, -0.01699, 0.03512, -0.06678, -0.05294, 0.04085, -0.09946, 0.01867, 0.19555, -0.08606, -0.1138, -0.0411, 0.08333, 0.03529, -0.03394, 0.03149, 0.21232], [-0.01059, 0.06516, 0.17956, 0.00395, -0.01525, 0.03739, -0.07416, -0.07808, -0.02501, 0.02281, 0.01405, -0.13785, -0.01581, 0.14208, -0.08287, 0.02903, -0.05441], [0.02282, 0.1026, 0.11824, 0.09484, -0.03588, -0.17712, -0.24087, 0.04506, -0.1267, 0.01119, 0.00219, 0.09528, 0.09301, -0.07307, -0.05031, 0.1281, -0.00939], [0.09772, 0.01279, -0.14331, -0.11675, -0.17722, -0.00482, 0.08516, -0.05201, 0.05636, -0.05335, -0.00793, 0.13686, -0.13714, 0.06849, 0.05039, 0.11105, 0.07371], [-0.00345, -0.13923, 0.12689, -0.18146, 0.07436, 0.03214, -0.13014, 0.00394, 0.0305, 0.07102, -0.08997, 0.08256, 0.0298, -0.01944, 0.06664, 0.02003, 0.02582], [-0.05718, -0.08576, 0.20466, -0.12456, 0.10404, -0.05783, -0.0445, -0.08511, -0.11446, 0.03775, -0.01562, -0.03217, 0.13187, 0.06948, -0.01404, -0.00198, 0.08542], [0.07673, -0.02589, 0.09578, 0.03499, -0.00144, 0.08678, 0.02439, -0.0674, 0.05375, 0.05393, -0.02582, -0.21416, 0.00314, 0.01061, -0.1202, -0.02484, 0.03964], [0.02884, 0.03142, -0.04015, -0.0332, 0.10241, -0.00501, -0.02841, -0.01828, 0.01422, 0.05406, -0.01449, -0.02395, 0.05765, -0.08045, -0.00723, -0.0281, -0.00932], [0.09166, -0.15219, 0.03766, -0.16704, -0.17124, -0.09929, -0.00816, 0.03092, 0.09504, -0.02887, 0.07605, 0.00864, 0.16873, 0.21621, -0.11609, 0.09126, -0.07328], [-0.01652, -0.06384, -0.15708, 0.01216, 0.03909, -0.02967, -0.00192, 0.09045, 0.02804, 0.07481, -0.0032, -0.07757, 0.02145, -0.01025, -0.11202, 0.12282, 0.08325], [-0.07718, 0.08842, 0.08313, 0.07264, -0.04466, -0.22728, -0.05121, 0.36524, -0.08925, 0.04177, -0.20088, -0.02185, -0.04936, 0.07144, -0.05368, -0.08247, 0.17519], [-0.01959, 0.03311, -0.19968, 0.12792, -0.03363, -0.04941, 0.07165, 0.05251, -0.07005, 0.03612, -0.1364, 0.13085, -0.1342, -0.07587, 0.03899, 0.22201, 0.00566], [-0.00022, -0.05032, 0.00133, -0.00701, 0.04238, 0.03155, -0.03643, 0.09534, 0.02562, 0.28018, -0.08814, -0.16411, -0.10366, 0.02683, -0.06525, 0.05357, -0.04165], [-0.00492, -0.0697, 0.02686, -0.05449, -0.04087, 0.09868, -0.0976, -0.06692, -0.00586, 0.00897, -0.06166, -0.01817, 0.00696, 0.2344, -0.038, -0.0415, 0.12382], [-0.17318, 0.07458, 0.1718, -0.0554, 0.06972, -0.1975, 0.0095, -0.06807, 0.24381, -0.11115, 0.08339, 0.00613, -0.02771, -0.04778, -0.04822, -0.05631, 0.12638], [-0.05732, 0.08629, 0.09215, 0.00476, 0.01149, -0.08631, -0.14425, 0.04102, -0.0126, 0.13726, -0.00556, 0.18481, 0.12825, -0.04426, -0.13776, -0.04574, -0.15224], [-0.02911, -0.16004, 0.09174, -0.0409, 0.15803, 0.03978, 0.05816, 0.06725, 0.10098, -0.06955, -0.04001, -0.01566, 0.00568, -0.0082, -0.10315, -0.12309, 0.06808], [0.00018, 0.05491, 0.06307, 0.07385, -0.14118, 0.0204, 0.18527, -0.18081, -0.0151, 0.03508, 0.08376, 0.24244, -0.12209, -0.04005, -0.10063, -0.13379, -0.0253], [0.07595, 0.04363, -0.12289, 0.06173, 0.02257, -0.05126, -0.08948, -0.19401, 0.13699, -0.00566, 0.05821, -0.02576, 0.09526, 0.23343, -0.08893, 0.01417, -0.16395], [0.22508, -0.04045, -0.23782, -0.01161, -0.04456, 0.08315, -0.02492, -0.00025, 0.03637, 0.12499, -0.01034, -0.02059, 0.06582, -0.1287, -0.09858, -0.06132, 0.14374], [0.01309, -0.04951, -0.06985, 0.01555, -0.13554, 0.08738, 0.02102, -0.05243, -0.0846, 0.14432, 0.16241, 0.08217, -0.14869, 0.00028, -0.03163, 0.05604, -0.01], [-0.11788, 0.04972, 0.00189, -0.0337, 0.00049, 0.0055, 0.21052, 0.17435, -0.15495, -0.02098, -0.0232, -0.03201, 0.10719, -0.19794, 0.04177, 0.08711, -0.09787], [0.01042, 0.02999, 0.08666, -0.25849, -0.05726, 0.13625, 0.11387, -0.06456, -0.14937, -0.10069, 0.18028, 0.10312, -0.10986, -0.09599, 0.10183, 0.18545, -0.11165], [0.05685, -0.1995, 0.13204, -0.07722, 0.02263, 0.14331, -0.07179, 0.10557, 0.01088, 0.1179, 0.06024, -0.0603, 0.0012, -0.06224, -0.19874, 0.1454, -0.12622], [0.10197, -0.02219, 0.11994, 0.02448, -0.09299, 0.0366, -0.00895, -0.06668, -0.0439, 0.03942, -0.06492, -0.08395, -0.02337, 0.10786, -0.01714, 0.03634, -0.04251], [0.11541, 0.0878, -0.10841, 0.0027, -0.22903, 0.06141, 0.17204, -0.1989, 0.05441, -0.11369, 0.13773, 0.14647, -0.0621, 0.03277, -0.05844, -0.10754, 0.06736], [0.07196, -0.11284, -0.10221, -0.05376, -0.09178, -0.01482, 0.22524, -0.08033, -0.06985, 0.07886, 0.10297, 0.05212, -0.05453, 0.07536, -0.03766, -0.06492, 0.0762], [-0.00017, 0.04432, 0.10879, 0.04662, -0.17728, -0.16607, 0.01521, 0.18868, 0.22034, -0.108, -0.05063, -0.22959, 0.04633, 0.07385, 0.08561, -0.10165, 0.00365], [-0.16769, -0.23852, 0.12427, 0.06598, 0.04851, -0.1171, 0.14127, -0.00339, -0.10866, -0.05308, -0.07084, 0.02586, 0.1602, -0.08427, 0.02907, 0.10246, 0.14592], [0.03739, 0.08235, 0.12596, 0.08954, 0.0225, -0.03367, -0.12719, -0.04802, -0.02668, -0.0966, -0.27464, -0.12226, 0.21554, 0.05992, -0.09731, 0.05269, 0.14048], [-0.08576, 0.07025, 0.12537, 0.03001, -0.01374, -0.03699, -0.15347, -0.12166, 0.13448, -0.17325, 0.18678, -0.07527, 0.10541, 0.25177, 0.01069, -0.00526, -0.24937], [-0.01158, -0.20452, -0.18735, 0.14325, 0.12787, 0.06181, -0.01745, 0.11062, 0.19702, -0.11918, -0.06331, -0.06476, 0.00472, -0.06034, -0.02562, 0.11899, -0.01018], [-0.0921, -0.05846, -0.03109, -0.07206, -0.03529, 0.08245, 0.2236, -0.00888, 0.11571, 0.00923, -0.18586, 0.19141, -0.10221, -0.01966, 0.16229, 0.00329, -0.18239], [0.08725, -0.13831, 0.12199, 0.13707, -0.16249, 0.06161, -0.14196, 0.11091, -0.00833, -0.04768, -0.12883, -0.01859, 0.04168, -0.02326, -0.0882, 0.04817, 0.14897], [0.04413, -0.02533, 0.04264, -0.00867, -0.07596, -0.07541, -0.05911, 0.12446, -0.02982, -0.02529, -0.04912, 0.06687, -0.12944, 0.18568, 0.10729, -0.02112, -0.07179], [0.03231, 0.18957, -0.06854, 0.1399, 0.02667, -0.09813, -0.02178, 0.11731, -0.10023, -0.03182, 0.0052, 0.00696, 0.02676, -0.05261, -0.14275, -0.08675, 0.05796], [-0.00795, -0.08817, 0.03543, 0.01565, -0.1371, 0.03485, 0.10856, -0.06583, -0.26131, -0.00328, -0.04052, 0.12165, -0.25199, 0.16646, 0.0832, 0.14974, 0.1406], [0.01864, -0.0101, 0.04248, -0.10477, -0.15891, 0.07998, -0.0091, 0.04772, 0.11839, -0.11434, -0.00649, 0.04099, 0.07423, 0.02909, 0.05041, -0.01849, -0.07971], [-0.27007, -0.03887, -0.08135, 0.25994, -0.07984, 0.01926, 0.11575, 0.07188, 0.07683, 0.02315, -0.13861, -0.07545, 0.10399, -0.0494, -0.11492, -0.00435, 0.18206], [-0.0067, 0.18698, -0.18267, 0.13121, -0.043, -0.03937, 0.01482, 0.17536, 0.10236, 0.13289, -0.06996, 0.00893, -0.1789, -0.06243, -0.03068, 0.05025, -0.18908], [0.13164, 0.02869, -0.11927, 0.17634, 0.08018, -0.02527, 0.01744, -0.01304, -0.06542, -0.02011, -0.12033, -0.0115, -0.09537, 0.02422, -0.01582, -0.0161, 0.0437], [0.02615, -0.19946, 0.09128, -0.08222, 0.07192, 0.03663, 0.0437, 0.11805, -0.0299, -0.02491, 0.1133, -0.10501, 0.06931, -0.1962, -0.06607, 0.0236, 0.10983], [-0.17186, 0.00718, -0.20868, 0.06445, 0.03603, 0.06422, 0.13513, -0.00218, -0.12494, 0.06461, -0.00332, 0.01609, 0.07558, -0.00539, 0.01621, 0.07017, -0.03329], [-0.07718, 0.05403, -0.07885, 0.06507, -0.06315, -0.02838, 0.11647, -0.10671, -0.16887, 0.06418, 0.03807, 0.00471, 0.14069, -0.00686, 0.09156, -0.04755, 0.00277], [0.02334, -0.00714, -0.01241, -0.00781, -0.01275, 0.07586, 0.0799, 0.06623, 0.07051, -0.11633, 0.33524, 0.04698, -0.09244, -0.25263, -0.13276, -0.11971, 0.05592], [0.03972, -0.15243, 0.08566, -0.02159, -0.13126, 0.03223, -0.04111, 0.04649, -0.02629, 0.08371, 0.08559, 0.01332, -0.05265, 0.0256, -0.12321, -0.04939, 0.18562], [-0.05212, -0.02379, 0.13115, 0.08815, -0.01168, -0.0785, 0.01595, 0.0634, 0.20969, 0.00463, 0.11103, -0.1837, -0.02407, -0.14749, -0.20163, 0.06903, 0.02993], [0.15037, -0.07649, 0.01599, -0.13818, -0.08696, 0.17099, 0.05623, -0.04883, 0.2679, -0.06824, 0.01218, -0.0479, 0.00777, -0.11299, -0.15545, 0.0356, 0.01803], [0.12755, 0.09216, -0.03576, -0.0439, -0.24253, -0.07061, -0.03805, -0.02058, 0.07901, 0.03, 0.01004, 0.17569, -0.00347, -0.1168, 0.03894, -0.03594, 0.05426], [0.02714, -0.06647, 0.04227, 0.04817, 0.04032, -0.23711, -0.05479, -0.025, 0.16692, -0.03093, -0.13329, 0.01405, 0.1221, 0.02738, -0.05966, -0.07529, 0.19418], [0.02254, -0.11165, 0.14347, 0.09245, -0.04561, 0.04458, 0.17928, 0.01555, -0.05095, 0.0771, 0.14828, -0.23425, -0.03329, -0.09884, -0.36546, -0.05991, 0.27671], [-0.24276, 0.09851, 0.10231, -0.27577, -0.18423, 0.11786, 0.0694, -0.31225, 0.02391, 0.06475, -0.065, 0.03966, 0.33559, -0.01849, 0.25306, 0.03, -0.03655], [0.07314, 0.03396, -0.15496, 0.03016, -0.08854, 0.07387, 0.02939, -0.18683, -0.08859, 0.00083, 0.01345, 0.13939, 0.00747, -0.03951, 0.23205, -0.00743, -0.06784], [0.04195, -0.14254, -0.16849, 0.00572, 0.07837, 0.16413, -0.1979, 0.01341, 0.13844, -0.03187, 0.03947, 0.05655, 0.12857, 0.17228, -0.03841, -0.04708, -0.21261], [0.11624, 0.13384, 0.00582, 0.1439, -0.11126, -0.13887, 0.17677, -0.06388, -0.08574, -0.04828, 0.20213, -0.06986, 0.09255, -0.02205, 0.03157, -0.19798, -0.16489], [-0.05197, 0.00398, 0.01117, 0.05245, 0.17256, 0.07341, -0.136, 0.16437, 0.09137, -0.19102, -0.02245, 0.02448, -0.05357, -0.2284, -0.0688, 0.13809, 0.02035], [-0.01839, 0.04074, 0.2152, -0.09156, 0.11999, 0.10821, -0.14641, 0.06612, 0.11573, -0.25391, 0.13923, 0.0549, -0.32, -0.07338, 0.04883, 0.16687, -0.17215], [-0.00458, 0.11054, 0.00771, -0.01848, -0.00903, -0.08613, 0.21183, -0.10304, -0.03237, 0.08023, 0.06656, -0.00259, -0.15731, -0.05461, -0.17199, 0.10098, 0.06228], [0.09833, -0.04157, -0.03255, -0.02322, 0.01693, 0.07077, 0.07085, -0.15601, -0.0705, 0.11887, -0.02003, -0.04202, -0.09051, 0.05154, 0.27929, -0.06565, -0.16452], [-0.0789, 0.03811, -0.0126, -0.0698, 0.0655, 0.00644, -0.07357, -0.05562, -0.13185, 0.02842, -0.09282, 0.14291, -0.07973, 0.11394, 0.12335, -0.01502, 0.09123], [-0.10173, 0.13176, 0.10196, -0.10415, 0.00326, -0.01076, 0.05444, -0.04917, -0.12949, 0.18446, -0.16492, -0.07146, -0.08921, -0.02333, 0.21942, 0.06428, -0.01536], [-0.03159, 0.11481, 0.0776, 0.04526, 0.02582, -0.05559, 0.21472, -0.09653, -0.07979, -0.12062, 0.01342, 0.01515, -0.09719, -0.10835, 0.00495, -0.10085, 0.17879], [0.17202, -0.00789, -0.24138, 0.20814, -0.12639, 0.17772, 0.10679, -0.15473, -0.02151, 0.11291, -0.06767, -0.10501, -0.01799, -0.05115, 0.13133, -0.04579, -0.06941], [0.19137, 0.01278, -0.15831, 0.11332, -0.0822, -0.04009, 0.0594, 0.15449, -0.01511, -0.00311, 0.08991, -0.08549, 0.1205, -0.10415, -0.03991, -0.06051, -0.15291], [0.11589, -0.17609, 0.05154, 0.04971, -0.00522, 0.09599, -0.02481, -0.01238, 0.19315, 0.07769, -0.0583, -0.21351, -0.00599, -0.06562, -0.07609, 0.05513, -0.00109], [-0.02279, -0.07923, 0.06671, 0.10819, -0.13492, -0.01617, 0.00951, 0.07445, -0.11867, -0.11864, 0.14557, -0.00223, -0.00236, 0.01685, -0.05578, 0.10053, 0.02897], [0.02749, -0.11409, -0.05919, -0.09962, 0.01192, 0.00479, 0.01971, 0.17682, -0.0009, 0.04936, -0.13215, -0.06721, 0.0403, -0.03594, 0.03088, 0.00407, 0.14374], [0.0155, -0.10768, -0.10139, 0.20921, -0.06344, 0.10135, 0.09371, 0.04538, -0.13747, 0.09178, 0.017, -0.0882, -0.23128, -0.04467, 0.12005, 0.03786, 0.0423], [0.21612, -0.077, 0.07786, -0.1625, -0.01372, 0.12218, 0.10286, 0.14882, 0.10992, -0.03658, -0.00725, 0.0235, -0.09474, -0.12878, -0.02694, -0.08577, -0.16797], [-0.0025, -0.02815, 0.06416, -0.10073, -0.07505, 0.07862, 0.07836, 0.01187, -0.16198, 0.03137, 0.14014, -0.14689, -0.10049, -0.14987, 0.04908, 0.11888, 0.19318], [0.06501, -0.06251, 0.00696, 0.03667, -0.03308, 0.04253, 0.01959, 0.03717, 0.06105, -0.06974, -0.022, 0.07081, -0.27246, 0.12185, -0.18173, -0.05719, 0.23707], [-0.01087, -0.0003, -0.11302, 0.15592, 0.09396, 0.08365, 0.02184, -0.04292, 0.16969, 0.04325, -0.34011, -0.15463, -0.05389, -0.08994, 0.13706, 0.08405, 0.01627], [0.11223, -0.05113, -0.03201, 0.02697, 0.00239, -0.01206, 0.02152, 0.03144, -0.00929, 0.05286, -0.03155, 0.0552, 0.01881, -0.00968, -0.01435, 0.00134, -0.16268], [-0.08396, -0.01297, 0.06995, 0.02569, -0.1067, -0.07952, -0.06702, -0.0484, -0.01139, -0.09973, 0.00532, 0.13094, 0.16644, 0.01294, 0.08107, -0.00844, 0.02578], [-0.08677, -0.10658, -0.02018, -0.03999, 0.15173, 0.0397, -0.05246, -0.12402, -0.13587, -0.02831, 0.11075, -0.05249, 0.06157, 0.14926, 0.09875, -0.00397, 0.03888], [0.01484, -0.20488, 0.0386, -0.08463, -0.02611, 0.17507, -0.04819, -0.13196, 0.03913, 0.18297, 0.13105, -0.11239, -0.03984, 0.04984, -0.01078, 0.01564, 0.01165], [-0.01648, 0.15334, -0.04073, -0.0154, -0.17957, -0.01405, 0.02497, 0.00452, -0.09113, -0.00463, -0.02488, 0.06688, 0.02223, 0.09496, 0.10057, 0.04338, -0.12397], [0.05118, -0.1455, -0.04481, 0.14441, 0.01985, -0.22293, -0.19301, 0.08131, 0.15089, -0.14264, 0.03596, 0.04831, 0.08395, 0.06783, -0.10828, -0.03676, 0.21025], [-0.19892, -0.10322, 0.12073, -0.01392, 0.11774, -0.05075, -0.01386, 0.33428, 0.08882, -0.12824, -0.00507, -0.07548, 0.16615, 0.00315, 0.00717, -0.07914, -0.16944], [-0.08027, 0.02975, -0.07786, 0.11206, 0.05051, -0.1291, -0.09156, 0.02862, 0.0595, 0.03467, 0.1178, 0.04804, 0.1089, 0.10102, -0.14848, -0.11696, -0.04665], [-0.00012, 0.13032, 0.21285, -0.05764, -0.04083, -8e-05, 0.10918, -0.13608, -0.14992, 0.04319, -0.16452, 0.16224, -0.15296, 0.08354, -0.07158, -0.02491, 0.05733], [0.18608, 0.0145, 0.05708, 0.08766, -0.05763, -0.07282, 0.04121, 0.04071, -0.06423, -0.18871, -0.01668, 0.02204, -0.00426, -0.15564, -0.10062, 0.04073, 0.17059], [-0.1479, 0.13594, -0.02937, -0.02182, -0.08366, 0.03453, -0.1056, -0.05455, 0.10026, 0.03376, -0.05121, 0.15664, 0.02178, 0.01934, 0.08018, -0.04883, -0.03947], [-0.0431, 0.01319, -0.04307, -0.06447, 0.05651, 0.05782, 0.02286, -0.07396, 0.23001, 0.17403, -0.12663, -0.09512, -0.18228, -0.05353, 0.06638, 0.08609, -0.02472], [0.20792, 0.15, -0.03564, 0.26901, -0.06307, 0.0458, 0.00466, 0.13552, -0.24033, 0.01023, -0.05576, -0.065, -0.06854, -0.31079, 0.08715, 0.00658, -0.07773], [-0.05431, 0.16592, 0.0637, 0.06047, 0.07272, -0.18704, -0.09047, -0.0477, -0.09363, 0.06039, 0.03463, -0.00929, -0.03829, -0.07958, -0.03368, 0.01553, 0.16064], [-0.06204, 0.03022, -0.10818, 0.19298, 0.16065, -0.0648, 0.0529, -0.01196, 0.07461, 0.17268, -0.04805, -0.01705, -0.15637, -0.20248, 0.126, -0.08513, -0.05395], [0.03167, 0.05657, 0.19224, -0.09776, -0.04512, 0.09967, 0.26542, -0.10419, -0.18209, 0.04879, 0.07384, -0.0869, -0.02845, 0.03165, -0.02808, -0.18026, -0.04699], [-0.05529, -0.1142, 0.00425, 0.00229, 0.09776, 0.0269, 0.23941, -0.10585, -0.17501, 0.10111, 0.05613, -0.07596, -0.11398, 0.05852, -0.10329, 0.11158, 0.04562], [-0.05233, -0.0554, 0.0644, -0.0125, 0.09911, -0.00036, 0.00478, 0.07715, -0.09044, 0.02826, -0.02742, -0.00659, -0.08527, -0.04031, 0.05907, 0.01576, 0.02209], [0.03047, 0.02906, -0.01167, -0.02568, 0.10156, -0.0308, -0.01968, 0.10459, -0.01509, -0.07462, -0.07045, -0.13459, 0.00982, -0.05224, 0.14168, -0.02763, 0.04527], [-0.07252, 0.02706, 0.16083, 0.11865, -0.01041, -0.15343, 0.01212, -0.08007, -0.01473, 0.09654, -0.12113, 0.0312, 0.09375, 0.04283, -0.03191, -0.03789, -0.06088], [0.14, 0.01349, 0.13885, 0.08159, 0.07894, -0.03595, -0.02495, -0.01986, -0.09769, -0.04557, 0.02073, 0.0057, -0.1661, 0.02616, -0.06285, 0.073, -0.12549], [0.11012, 0.10945, -0.06476, -0.11605, -0.03754, -0.12612, -0.00762, 0.05419, 0.18891, -0.06661, -0.07245, 0.08972, -0.04189, -0.16173, 0.11964, 0.06882, -0.04606], [-0.03112, -0.13501, -0.03987, 0.0801, -0.07697, 0.09043, -0.10446, 0.1783, 0.10297, -0.12393, 0.21776, -0.11564, -0.12398, 0.00226, -0.13816, 0.03681, 0.18052], [-0.0779, 0.14409, -0.13467, 0.12786, -0.28429, 0.09856, 0.19079, 0.03082, 0.0166, -0.06972, -0.07198, 0.41263, 0.04288, -0.35718, 0.09605, -0.04449, -0.12007], [-0.05324, 0.00644, 0.07948, -0.10762, -0.13619, -0.11243, -0.1127, 0.02989, 0.10746, 0.08185, -0.06608, 0.07203, 0.20126, 0.13546, 0.08766, -0.09783, -0.11545], [0.01301, 0.14972, -0.05604, -0.00858, -0.03374, 0.00964, -0.169, 0.02945, 0.15038, -0.04627, -0.02782, 0.02071, -0.04742, 0.01345, 0.07781, -0.16497, 0.08967], [-0.07967, -0.16235, 0.30791, 0.16037, -0.08659, -0.19608, -0.0772, 0.11457, -0.03354, -0.00909, 0.05592, -0.02859, 0.06428, 0.0393, -0.02902, -0.0014, -0.03882], [0.00578, 0.04169, -0.05968, 0.16037, 0.01962, 0.11028, -0.12681, -0.17624, -0.06145, -0.05625, 0.10492, 0.10957, -0.16128, -0.07814, -0.07642, 0.07353, 0.17052], [0.10743, -0.1633, 0.00361, 0.02542, 0.0264, 0.09359, -0.15895, -0.0235, 0.05897, -0.02087, 0.10151, 0.07666, -0.05589, -0.08397, 0.09228, -0.03026, -0.04913], [0.05798, -0.03154, -0.03196, -0.05486, 0.17135, 0.03672, 0.20822, 0.04121, -0.2677, 0.0219, 0.13377, -0.0299, -0.05971, 0.04952, 0.09021, -0.10915, -0.22606], [-0.03883, 0.07802, -0.16121, 0.05684, 0.09475, 0.04557, 0.09365, -0.11211, -0.0118, -0.03601, -0.05906, 0.11619, -0.13382, 0.09599, 0.08948, -0.2668, 0.14914], [-0.04012, -0.00113, 0.15655, 0.04867, 0.05135, 0.0396, -0.19589, 0.19152, -0.15405, 0.05894, -0.02519, -0.09805, 0.22384, -0.01604, -0.19635, -0.04375, 9e-05], [0.06771, -0.07563, -0.12837, 0.01337, 0.04961, 0.10042, 0.05395, -0.1812, -0.07137, -0.01303, -0.13129, -0.07312, 0.09152, -0.00776, -0.07877, 0.08151, 0.30245], [0.00846, 0.09903, 0.03481, -0.04835, -0.08447, -0.05588, -0.02298, 0.08671, 0.15485, -0.06464, -0.04211, 0.035, 0.09412, -0.13969, -0.0278, -0.10034, 0.07327], [0.01671, -0.01796, 0.04577, -0.01346, 0.01591, 0.01393, -0.01561, -0.01021, 0.00117, 0.00403, -0.00483, -0.02503, -0.02253, 0.03322, 0.00247, 0.0144, -0.03796], [0.02432, -0.19735, 0.13599, 0.10989, 0.04248, 0.1264, 0.06583, -0.03289, 0.0383, -0.08362, -0.05273, -0.00854, 0.00406, -0.07034, -0.12213, 0.15242, -0.13211], [-0.14181, -0.23082, 0.13426, 0.00321, 0.01366, -0.04221, -0.06181, 0.24883, -0.08671, -0.04175, 0.09616, 0.08146, 0.04712, 0.01991, 0.09991, 0.02009, -0.15953], [0.10936, 0.01429, 0.06639, -0.01212, 0.0351, -0.03203, 0.04265, -0.07334, 0.15097, -0.03514, -0.00072, -0.00672, -0.129, -0.04461, -0.03927, -0.04304, -0.00276], [-0.12434, 0.10725, -0.17273, 0.03625, -0.10422, 0.02174, 0.04401, -0.16985, -0.00457, -0.01671, -0.07644, 0.26922, -0.03705, 0.00726, 0.18792, 0.02314, 0.00914], [-0.03463, 0.11767, 0.05478, -0.14924, 0.02211, 0.17997, -0.01147, -0.17814, -0.16329, 0.12446, -0.21296, 0.00528, 0.07963, 0.12505, 0.14395, -0.02989, -0.07329], [-0.00668, -0.08274, 0.07338, -0.02561, 0.07194, -0.06336, -0.08603, 0.0417, 0.18613, 0.0086, -0.02236, 0.07811, 0.08704, -0.01695, -0.03112, -0.08051, -0.13155], [0.11312, -0.06031, 0.10636, -0.05115, 0.16258, 0.01535, -0.01041, -0.26584, -0.02885, 0.16926, -0.06473, 0.10124, -0.16147, -0.03166, -0.06841, 0.15143, -0.07651], [-0.0348, 0.03971, -0.12801, -0.1473, 0.01701, 0.24992, -0.08029, 0.05435, 0.13262, -0.08082, 0.10728, -0.17686, -0.12048, -0.02024, 0.07287, 0.05737, 0.05765], [0.20262, -0.11789, -0.04762, -0.0406, -0.02795, 0.23659, 0.13397, -0.05635, -0.09959, 0.1598, -0.06091, -0.11445, -0.0693, 0.20558, -0.04053, -0.21692, -0.04645], [-0.06955, -0.10488, 0.22099, -0.11225, 0.01727, -0.18851, -0.19037, 0.21054, 0.01054, 0.11691, 0.02319, -0.20515, 0.17786, -0.02611, -0.14761, 0.0231, 0.24403], [0.02155, 0.08359, 0.04262, 0.22766, -0.05636, 0.00867, -0.01692, 0.01424, 0.06607, 0.01241, 0.0138, -0.20686, -0.0459, -0.03232, -0.06875, -0.09369, 0.0302], [0.1894, 0.10349, -0.00498, 0.08027, -0.12047, -0.0704, -0.03021, 0.13919, -0.15757, 0.03327, -0.24181, -0.09499, 0.04638, -0.11343, 0.14581, -0.04329, 0.13935], [0.04185, -0.144, -0.10817, 0.09772, 0.03098, -0.03654, 0.09476, 0.00589, -0.03767, 0.00707, -0.16433, 0.12122, -0.02585, -0.10188, 0.17866, -0.05934, 0.09962], [0.00209, 0.13791, -0.0138, 0.01648, 0.00937, 0.087, -0.09648, -0.04841, -0.00353, 0.02022, -0.07583, 0.03354, 0.00667, -0.06182, -0.04863, -0.04874, 0.08397], [-0.15133, 0.05054, 0.24428, 0.16664, -0.12626, -0.24709, -0.07302, 0.04195, 0.08794, -0.06777, -0.08059, 0.18343, 0.00854, 0.08511, 0.01007, -0.03634, -0.09612], [-0.00349, 0.098, 0.04831, 0.08424, -0.0984, -0.02499, -0.10034, 0.06134, -0.06966, 0.00266, 0.05771, 0.02157, 0.02435, 0.01344, -0.09342, -0.03474, 0.01343], [0.08984, 0.04206, -0.04367, -0.00577, 0.06414, 0.03062, 0.04761, -0.10934, -0.0565, 0.06516, -0.10898, 0.08504, -0.11205, 0.05598, -0.03141, 0.0265, -0.0392], [0.02876, 0.12127, 0.03238, -0.00692, 0.00579, 0.12829, -0.13498, 0.03764, -0.18286, -0.10172, 0.06988, -0.02927, -0.03769, 0.06394, 0.1291, -0.20281, 0.0792], [-0.03577, -0.11432, 0.0946, 0.06936, -0.02702, 0.0116, -0.11608, 0.10028, 0.0046, -0.01065, 0.06708, -0.0281, -0.13468, 0.10291, -0.15246, 0.01799, 0.15068], [0.07038, -0.20096, 0.0882, 0.05717, -0.13958, 0.0807, 0.06212, 0.03583, 0.00223, -0.10121, 0.08287, 0.06773, -0.03873, -0.04648, -0.12574, -0.01348, 0.11893], [0.00551, 0.02647, -0.08647, 0.24993, -0.0413, -0.02995, 0.00317, 0.0393, -0.16101, -0.16841, -0.10848, 0.02351, 0.00576, 0.12435, -0.02328, 0.10212, 0.03879], [-0.2972, -0.03992, -0.15935, -0.14235, 0.14086, -0.06044, 0.0756, 0.10624, -0.11166, 0.03768, 0.0886, 0.21306, -0.0447, 0.02376, -0.00746, 0.07363, 0.10365], [-0.07426, -0.11566, 0.03309, 0.18332, 0.09682, -0.08575, -0.14086, 0.27624, 0.02383, -0.13938, 0.03923, 0.14472, -0.20453, -0.07327, 0.03632, 0.04073, -0.04061], [0.00655, 0.12692, -0.13944, 0.03186, 0.1361, -0.10239, -0.03552, -0.07482, -0.06357, 0.03319, 0.11722, 0.10332, -0.10638, 0.07268, -0.061, 0.11197, -0.15667], [0.02954, 0.00744, -0.11281, -0.0838, 0.07746, 0.08839, -0.06375, 0.03588, -0.06357, 0.06036, -0.16921, -0.01804, -0.10825, -0.06532, 0.10594, 0.2192, 0.06055], [0.07164, 0.07074, 0.11531, 0.05412, -0.01081, -0.19888, 0.07986, -0.05442, -0.08388, 0.07403, -0.25703, 0.04382, -0.13805, 0.10411, -0.15668, 0.18647, 0.09966]], "b": [-0.00192, 0.00825, -0.01175, -0.00178, -0.00691, -0.00046, -0.00456, 0.00463, 0.00019, -0.00782, 0.00648, -0.01177, -0.00594, -0.00167, -0.00778, -0.01183, 0.05464]}, "family": {"classes": ["code", "design", "sheet", "write", null], "scale": 20.0, "floor": 0.96, "w": [[-0.47266, -0.10841, 0.60076, -0.04378, 0.02408], [-0.11936, 0.14025, 0.16096, -0.46509, 0.28325], [0.31291, -0.1521, -0.22272, -0.09455, 0.15646], [0.29978, 0.20939, -0.01984, -0.54814, 0.05882], [-0.50203, -0.04374, -0.02451, 0.53194, 0.03834], [-0.68746, 0.2084, -0.12187, 0.79757, -0.19663], [-0.23785, -0.05593, 0.07081, 0.0414, 0.18158], [0.19102, -0.263, 0.39457, -0.54734, 0.22474], [0.69749, -0.15699, -0.47786, 0.05065, -0.11329], [0.65726, -0.07398, 0.01315, -0.675, 0.07856], [-0.76557, -0.12408, 0.78486, 0.13756, -0.03276], [-0.22227, -0.51928, -0.03718, 0.66461, 0.11412], [0.00086, 0.03179, -0.27653, -0.5338, 0.77767], [0.07847, -0.25377, 0.6376, -0.80934, 0.34704], [-0.37503, 0.15565, -0.06246, 0.09847, 0.18337], [-0.01472, -0.04937, -0.29075, 0.28024, 0.0746], [-0.0092, -0.24132, 0.4587, -0.64268, 0.43449], [0.15988, 0.37591, -0.01044, -0.52225, -0.00311], [-0.86539, -0.01169, 0.14504, 0.62648, 0.10556], [-0.0857, 0.02165, -0.10135, 0.51728, -0.35188], [-0.45069, 0.15604, -0.31681, 0.77237, -0.16091], [-0.23145, -0.15515, 0.08985, 0.16762, 0.12913], [-0.34763, -0.21061, 0.77062, -0.00545, -0.20692], [0.10761, -0.32601, 0.2581, -0.16017, 0.12047], [0.29233, 0.07979, -0.11499, -0.32424, 0.06712], [0.23035, 0.15921, -0.14596, -0.21528, -0.02832], [0.60792, 0.43357, -0.01723, -0.85973, -0.16454], [0.26274, 0.31444, -0.38915, -0.30685, 0.11882], [-0.28885, -0.02295, -0.18679, 0.30398, 0.19461], [-0.72751, 0.05874, 0.00887, 1.15826, -0.49836], [0.41986, 0.12831, -0.26104, -0.25113, -0.03601], [-0.07645, -0.01992, -0.19552, -0.01656, 0.30844], [-0.1127, -0.01684, 0.38755, -0.36176, 0.10375], [0.43475, -0.21077, 0.31345, -0.04513, -0.49231], [0.72111, -0.04062, 0.0446, -0.70738, -0.0177], [-0.69524, 0.43197, 0.13193, 0.08175, 0.04958], [-0.33847, 0.60781, -0.30293, 0.15102, -0.11743], [-0.07876, -0.02476, 0.01731, -0.212, 0.29821], [0.31844, -0.27415, -0.64222, 0.1887, 0.40922], [-0.70761, -0.26744, -0.07917, 1.04516, 0.00906], [1.14966, -0.1176, -0.1067, -0.23165, -0.69372], [0.56656, 0.3719, 0.06473, -0.74236, -0.26082], [0.40223, 0.29392, 0.04846, -1.00111, 0.25649], [0.06618, 0.31088, -0.01535, 0.34566, -0.70737], [-0.24876, 0.30659, 0.15858, 0.22727, -0.44368], [-0.02094, 0.00725, -0.11789, 0.10843, 0.02316], [0.47534, 0.12235, -0.51466, -0.03263, -0.05039], [0.31841, -0.12302, -0.18792, 0.31522, -0.32269], [0.2927, -0.11899, -0.12153, 0.17517, -0.22735], [-0.18053, 0.0308, -0.15649, 0.24887, 0.05735], [0.18744, -0.30794, 0.20348, 0.24756, -0.33055], [-0.11416, -0.34301, 0.12539, 0.25106, 0.08072], [-0.41695, -0.02014, 0.56791, -0.07833, -0.05248], [0.18758, -0.10978, -0.24179, -0.12359, 0.28759], [0.72749, 0.06034, -0.41408, -0.19539, -0.17838], [0.01249, -0.13114, 0.38589, -0.40888, 0.14163], [-0.29657, -0.04437, 0.0459, 0.17102, 0.12402], [-0.34252, 0.34735, 0.62354, -0.53426, -0.09411], [0.08892, 0.17774, 0.23196, -0.33268, -0.16594], [0.27865, -0.29054, -0.28417, 0.39424, -0.09818], [0.17062, -0.03964, 0.04397, 0.12703, -0.30198], [-0.149, -0.07423, 0.41543, -0.55215, 0.35995], [-0.20559, 0.03779, -0.15505, -0.04075, 0.3636], [0.02276, -0.00709, 0.38328, -0.63078, 0.23183], [-0.27876, -0.30006, 0.17658, -0.09902, 0.50127], [0.08997, 0.17925, -0.18289, 0.04568, -0.13202], [-0.07757, -0.13165, 0.34182, -0.33076, 0.19816], [-0.84382, 0.09956, -0.09688, 0.59202, 0.24913], [0.7468, 0.08258, 0.60336, -0.63362, -0.79913], [0.16163, -0.16481, -0.08173, -0.20661, 0.29151], [0.33913, 0.1109, 0.48048, -0.50421, -0.42629], [-0.17302, -0.00179, -0.73479, 1.58256, -0.67296], [-0.66934, -0.02882, 0.72965, 0.57451, -0.606], [0.30214, 0.21023, 0.11275, -0.48508, -0.14003], [0.46347, -0.13298, -0.02166, -0.19209, -0.11675], [-0.37174, -0.07928, -0.20873, 0.5751, 0.08465], [1.29048, -0.09497, -0.07705, -1.23538, 0.11692], [-0.56872, 0.33575, -0.4098, 0.29014, 0.35263], [-0.10219, -0.27688, 0.24123, -0.19412, 0.33196], [-0.37549, 0.40033, -0.3568, 0.57601, -0.24405], [0.28738, 0.04332, 0.01555, -0.03881, -0.30744], [-0.23644, -0.08796, 0.10215, 0.66008, -0.43783], [0.0587, 0.40214, -0.12735, -0.1776, -0.15589], [0.35069, -0.1854, -0.47519, 0.63011, -0.32021], [-0.48966, 0.10709, 0.42175, -0.21393, 0.17475], [0.61968, -0.15237, -0.48694, 0.38869, -0.36905], [-0.30902, 0.07869, -0.12053, 0.46303, -0.11218], [0.02374, 0.23855, -0.40063, 0.23039, -0.09205], [0.48339, 0.08443, 0.07613, -0.47748, -0.16647], [-0.38676, 0.54661, -0.05509, -0.23962, 0.13487], [0.30624, -0.26602, 0.34466, -0.64176, 0.25688], [-0.02563, -0.09691, -0.21684, 0.38415, -0.04477], [0.10874, -0.0886, -0.4137, 0.01996, 0.37361], [0.48994, -0.04571, 0.18172, -0.49307, -0.13288], [0.4934, -0.16113, 0.09114, -0.99249, 0.56908], [0.38267, -0.10227, 0.55205, -0.29731, -0.53513], [0.00686, -0.19659, 0.26782, -0.36932, 0.29123], [-0.14959, 0.12887, 0.00803, -0.09511, 0.1078], [-0.45246, 0.07133, 0.10325, 0.19584, 0.08204], [0.38625, 0.2005, -0.47401, 0.00991, -0.12265], [-0.52073, -0.13944, 0.2972, 0.17922, 0.18375], [-0.53585, 0.33241, 0.11855, -0.15673, 0.24161], [-0.08631, -0.1701, 0.58165, -0.12165, -0.20358], [-0.72063, 0.0557, 0.65982, 0.09909, -0.09399], [0.02628, -0.42485, 0.33039, -0.18713, 0.25531], [0.05746, -0.09899, 0.01538, -0.06819, 0.09434], [0.17997, 0.05785, 0.04801, -0.00295, -0.28287], [0.16157, 0.03449, -0.30558, -0.01373, 0.12325], [0.0905, -0.17386, 0.65757, -0.11472, -0.45949], [0.38088, 0.30284, -0.70486, 0.34026, -0.31912], [0.36369, -0.21113, -0.3381, 0.20002, -0.01447], [-0.18866, 0.09693, 0.5985, -0.46259, -0.04419], [0.19808, -0.01757, -0.11523, -0.26855, 0.20327], [-0.02029, 0.62365, -0.05568, -0.72713, 0.17946], [0.63008, -0.0746, -0.01767, -0.138, -0.39982], [-0.58472, -0.0439, 0.68854, -0.38775, 0.32783], [0.30392, -0.19914, 0.38809, -0.68272, 0.18986], [0.35863, 0.13183, -0.48704, -0.38596, 0.38253], [-0.09643, 0.16281, 0.45537, -0.71027, 0.18852], [0.49451, 0.29969, -0.58946, -0.3511, 0.14637], [-0.56175, 0.10554, 0.2353, 0.17803, 0.04288], [-0.77101, 0.43472, -0.3778, -0.01556, 0.72966], [-0.42932, 0.07533, 0.2364, 0.10284, 0.01475], [0.18085, -0.4685, 0.27479, -0.20369, 0.21655], [-0.3106, 0.37662, -0.23609, 0.7097, -0.53962], [0.72701, -0.02425, -0.08383, -0.66313, 0.0442], [0.29766, -0.12156, -0.08193, -0.38974, 0.29556], [0.93225, -0.1884, -0.28996, -0.09101, -0.36288], [0.17037, -0.20109, 0.28208, -0.23014, -0.02122], [0.3292, -0.09844, -0.31475, -0.29865, 0.38264], [-0.12995, -0.07662, -0.40324, -0.2723, 0.88212], [0.64149, -0.25221, -0.20001, -0.38817, 0.19889], [0.23756, 0.31771, 0.06411, -0.65474, 0.03536], [-0.15694, -0.12166, 0.2905, 0.01292, -0.02482], [-0.3262, 0.17164, -0.02121, 0.463, -0.28724], [0.37577, -0.03228, 0.11325, 0.17273, -0.62947], [-0.08617, 0.14276, -0.17789, 0.10713, 0.01418], [0.35396, 0.14414, 0.04746, -0.49918, -0.04638], [-0.03844, 0.0644, -0.19262, 0.11945, 0.04721], [0.4726, -0.13179, -0.28787, -0.49228, 0.43935], [0.31574, 0.0529, 0.16552, -0.55558, 0.02142], [-0.80866, -0.16221, 0.09523, 1.00947, -0.13383], [0.18751, -0.21789, -0.19974, -0.28594, 0.51607], [-1.06172, 0.1578, -0.13985, 0.35133, 0.69244], [0.60394, 0.22616, 0.08555, -0.7571, -0.15856], [0.27974, 0.26423, -0.31981, -0.05685, -0.16731], [-0.52682, -0.17764, 0.10061, 0.71319, -0.10934], [0.18722, -0.05299, 0.05604, -0.20053, 0.01026], [-0.35142, 0.00919, 0.15724, 0.23465, -0.04966], [-0.37764, -0.09756, 0.37751, 0.27749, -0.1798], [0.24033, -0.15451, -0.44524, 0.54464, -0.18521], [-0.34112, 0.12392, -0.05119, 0.50696, -0.23857], [0.12394, -0.15644, -0.31408, -0.0224, 0.36898], [0.19093, 0.24323, -0.24816, 0.15984, -0.34585], [0.6129, -0.28855, -0.42327, -0.12556, 0.22448], [-0.33852, 0.01851, -0.2804, 0.6324, -0.03197], [-0.46362, -0.15668, 0.35449, 0.91103, -0.64522], [-0.0541, 0.19454, 0.00479, -0.25642, 0.1112], [0.12672, 0.53225, -0.24196, 0.16552, -0.58254], [0.43776, 0.30609, -0.41164, -0.22668, -0.10554], [0.86212, 0.07838, -0.36861, -0.13278, -0.43911], [-0.01784, -0.17532, -0.06712, 0.19681, 0.06347], [-0.16877, 0.01281, -0.11754, 0.09727, 0.17622], [0.00276, 0.12872, 0.04152, -0.09869, -0.0743], [0.65157, -0.16482, 0.19314, -0.4377, -0.2422], [0.38571, 0.18643, 0.20852, -0.31341, -0.46726], [-0.5816, 0.09906, 0.1582, 0.60951, -0.28517], [-0.47737, 0.07827, -0.22836, 0.57471, 0.05275], [5e-05, 0.02158, 0.00771, -0.22315, 0.19382], [-0.18497, 0.02014, 0.06654, -0.09785, 0.19614], [0.24546, -0.13584, 0.03586, -0.06379, -0.08169], [0.49614, 0.1145, 0.00559, -0.69063, 0.0744], [-0.43625, -0.321, 0.21698, 0.29949, 0.24079], [0.04199, 0.09953, -0.26065, -0.19637, 0.31551], [0.22203, -0.13133, -0.10723, 0.10825, -0.09171], [-0.55721, 0.18962, -0.44431, 0.50256, 0.30934], [-0.59906, -0.11544, -0.04718, 0.24812, 0.51356], [0.35106, -0.33077, 0.0285, -0.3348, 0.28602], [-0.08335, 0.05502, -0.37331, 0.57532, -0.17368], [0.62766, -0.16482, 0.03412, 0.14731, -0.64427], [0.24062, 0.0918, 0.78432, -0.57365, -0.54309], [0.4285, 0.14678, 0.0371, -0.25111, -0.36127], [0.23988, -0.13173, 0.60681, -0.89958, 0.18462], [-0.14765, 0.07821, 0.06693, -0.10711, 0.10962], [-0.1392, -0.11292, 0.00088, 0.21818, 0.03305], [0.26522, 0.11292, -0.0025, -0.84378, 0.46814], [-0.41015, 0.05021, 0.14079, -0.00593, 0.22507], [-0.53962, 0.02609, 0.23455, 0.02592, 0.25307], [-0.3376, 0.44741, -0.09007, 0.34643, -0.36617], [-0.35609, -0.07394, 0.0004, 0.36733, 0.06229], [0.15965, -0.07469, 0.05426, -0.81628, 0.67706], [-0.11642, -0.36033, 0.53463, 0.03662, -0.09451], [0.04413, -0.19238, -0.13544, 0.06238, 0.22131], [-0.46655, 0.42767, 0.37117, -0.12979, -0.20251], [-0.05184, -0.11027, -0.46866, 0.80776, -0.17699], [-0.41555, 0.47533, 0.12425, -0.49612, 0.31209], [-0.08037, -0.28395, -0.00614, 0.31028, 0.06018], [0.29466, 0.14481, -0.10635, -0.36685, 0.03372], [0.433, 0.2795, -0.01667, -0.22822, -0.46761], [-0.05828, 0.04941, -0.09578, 0.00104, 0.10361], [-0.25712, 0.09504, -0.29504, -0.05475, 0.51187], [0.01784, -0.15758, 0.12618, -0.29371, 0.30727], [-0.18964, 0.0292, 0.51317, -0.49824, 0.14551], [0.20945, -0.01958, 0.44851, -0.50023, -0.13815], [-0.16844, 0.08874, -0.07162, 0.18367, -0.03235], [0.7196, -0.03536, 0.68363, -1.08021, -0.28766], [-0.15764, 0.00732, -0.12297, 0.17993, 0.09337], [0.36346, 0.06156, -0.0693, -0.14934, -0.20638], [0.57004, 0.0141, -0.52302, 0.17898, -0.24009], [-0.31065, -0.07311, -0.51908, 0.56148, 0.34136], [-0.15827, -0.00173, -0.20526, 0.61391, -0.24865], [0.10933, 0.05764, 0.17611, -0.2827, -0.06039], [-0.20559, -0.39141, 0.08598, 0.67861, -0.16759], [-0.56311, -0.26374, 0.03545, 1.04558, -0.25417], [-0.52367, 0.11315, -0.4041, 0.26711, 0.54752], [-0.66505, 0.3991, -0.14983, 0.06227, 0.35351], [0.0648, -0.02953, 0.63523, -0.50741, -0.1631], [0.43619, 0.29223, -0.10288, -0.54548, -0.08007], [0.90173, 0.05941, -0.18523, -0.49971, -0.27621], [0.14922, -0.02921, 0.21777, 0.23028, -0.56806], [0.61635, -0.46936, -0.17406, -0.53034, 0.55741], [0.68199, 0.10368, -0.01287, -0.53372, -0.23908], [-0.2432, -0.25822, 0.30919, 0.32106, -0.12883], [-0.22353, -0.13474, 0.13135, 0.18532, 0.04159], [0.27922, -0.07588, -0.15749, -0.20587, 0.16002], [-1.17005, -0.3498, 0.13588, 1.22152, 0.16245], [-0.31766, -0.08116, -0.1433, 0.19257, 0.34956], [0.02308, 0.01591, 0.2119, 0.32241, -0.5733], [-0.17965, -0.16592, -0.27583, 0.59964, 0.02177], [-0.71117, -0.12751, 0.33764, 0.70147, -0.20044], [0.0796, 0.3565, -0.21846, -0.26221, 0.04458], [-0.43591, 0.04258, 0.27147, 0.37909, -0.25723], [-0.33149, 0.1079, 0.47797, -0.16354, -0.09084], [0.29606, -0.0724, 0.45895, 0.05771, -0.74032], [-0.53998, 0.15334, 0.2756, 0.38784, -0.27681], [-0.29861, -0.31776, 0.42646, 0.17237, 0.01754], [-0.56867, 0.07001, -0.3439, 0.69133, 0.15122], [-0.03952, -0.2287, -0.07054, 0.13669, 0.20207], [0.29785, -0.02925, -0.20471, 0.37651, -0.4404], [-0.20102, 0.02339, 0.33772, 0.28537, -0.44546], [-0.51197, -0.19586, 0.35393, 0.61562, -0.26172], [0.23894, 0.14473, -0.20466, -0.18066, 0.00165], [0.43487, -0.25155, 0.33539, -0.6162, 0.0975], [0.09428, 0.02655, -0.02808, -0.05787, -0.03488], [0.15813, -0.02193, -0.70341, 0.65404, -0.08684], [0.55121, -0.37748, 0.22159, -0.38112, -0.0142], [0.31761, -0.07253, -0.66221, 0.51859, -0.10146], [-0.44937, -0.21763, 0.67247, 0.33868, -0.34415], [0.22446, 0.08031, -0.02467, -0.49571, 0.21561], [0.2516, 0.09938, -0.30044, 0.14774, -0.19828], [0.19487, -0.13817, 0.03682, 0.40601, -0.49953], [0.42462, 0.19798, -0.25474, -0.56242, 0.19456], [-0.31293, -0.26375, 0.32464, 0.28488, -0.03284], [-0.33165, -0.09486, 0.53605, -0.37386, 0.26431], [0.83548, -0.08595, 0.2877, -0.54775, -0.48947], [-0.10807, 0.0122, -0.72537, 1.11351, -0.29226], [0.01995, 0.00493, 0.07659, -0.88401, 0.78253], [-0.20572, 0.26572, -0.21127, 0.40945, -0.25818], [-0.05597, -0.05439, -0.40034, 0.60318, -0.09248], [0.84486, -0.12766, 0.07264, -1.28041, 0.49057], [-0.56895, -0.21902, -0.12535, 0.39561, 0.51772], [-0.4504, 0.21426, -0.30978, 0.19089, 0.35504], [0.0658, -0.06272, 0.08465, -0.08042, -0.00731], [0.2712, 0.09056, 0.17544, -0.0338, -0.50341], [0.22973, 0.36883, -0.06745, -0.43797, -0.09315], [-0.72286, -0.23286, -0.26417, 1.0989, 0.12099], [0.33519, -0.02197, -0.26671, -0.43578, 0.38927], [0.10645, 0.1854, -0.42341, 0.16806, -0.03651], [-0.33097, -0.25873, 0.18153, 0.19754, 0.21065], [-0.46778, -0.09997, 0.01432, 0.52783, 0.0256], [0.68587, 0.44095, -0.41046, -0.38233, -0.33403], [0.22269, -0.33522, 0.08666, 0.20882, -0.18294], [-0.38161, -0.12719, 0.11796, 0.1969, 0.19395], [-0.36181, -0.38786, -0.27092, 0.37602, 0.64457], [0.3091, -0.14551, 0.13437, -0.18098, -0.11698], [0.34728, -0.09925, 0.39816, -0.56028, -0.08591], [-1.49198, 0.25078, 0.23206, 1.00317, 0.00596], [-0.4662, -0.09632, 0.18409, -0.06649, 0.44492], [0.36955, 0.34399, 0.02487, -0.46064, -0.27778], [0.85712, -0.26991, 0.35854, -0.82, -0.12575], [-0.29104, 0.17601, 0.26153, -0.04325, -0.10325], [0.34448, -0.56024, -0.44875, 0.74751, -0.08299], [-0.07649, -0.61979, 0.13293, 0.06953, 0.49383], [1.16327, -0.21192, 0.31205, -0.62474, -0.63866], [0.56201, -0.34367, 0.27625, -0.65044, 0.15585], [0.21018, -0.17266, -0.09799, -0.20437, 0.26484], [-0.59221, -0.00433, -0.0152, 0.7954, -0.18366], [0.22543, -0.29358, -0.21824, -0.1599, 0.44629], [-0.53327, -0.09847, 0.05475, 0.52771, 0.04927], [-0.41385, 0.48292, 0.50147, -1.11065, 0.5401], [-0.36353, -0.00343, 0.07143, 0.16321, 0.13232], [-0.2271, -0.07574, -0.0146, 0.65243, -0.33499], [-0.21472, -0.04761, 0.35856, 0.0928, -0.18903], [-0.5185, -0.14791, 0.20125, 0.32379, 0.14135], [-0.36956, -0.02064, -0.60536, 0.06097, 0.93459], [-0.03495, 0.00123, -0.3518, 0.26809, 0.11744], [0.39105, -0.6734, 0.17312, 0.04246, 0.06677], [-0.18036, -0.10196, 0.12824, 0.23208, -0.078], [-0.49796, 0.10634, 0.22746, 0.23794, -0.07379], [0.63147, -0.25174, 0.02673, -0.44222, 0.03576], [0.12126, -0.03116, 0.34831, -0.47268, 0.03428], [0.56893, 0.62095, 0.15326, -1.13498, -0.20816], [0.55409, 0.03853, 0.079, -0.87762, 0.20599], [0.45739, -0.04859, 0.4828, -0.62994, -0.26165], [0.13183, 0.21083, 0.09964, -0.00738, -0.43493], [0.91392, 0.29952, 0.29221, -1.45366, -0.05198], [-0.00303, -0.22705, 0.18643, 0.02224, 0.02142], [0.5878, -0.0861, 0.25528, -0.64235, -0.11463], [0.01862, 0.22736, 0.08507, 0.24737, -0.57843], [-0.1435, 0.32061, -0.0361, 0.26527, -0.40628], [-0.63991, -0.44012, -0.30879, 0.62897, 0.75985], [0.13359, -0.10907, 0.16377, 0.10477, -0.29306], [-0.01065, 0.07932, 0.1823, 0.03632, -0.28728], [0.11811, 0.24048, 0.15488, -0.36928, -0.14419], [-0.22533, 0.09362, -0.54931, 0.26649, 0.41452], [0.59942, -0.18376, -0.66718, 0.17158, 0.07994], [0.06694, -0.29076, -0.4365, -0.22392, 0.88424], [-0.19472, 0.31488, 0.07201, 0.59833, -0.7905], [-0.14166, -0.05732, 0.00432, -0.29723, 0.49189], [0.04647, 0.24362, 0.39232, -0.27434, -0.40807], [0.1339, 0.19877, 0.09121, -0.18191, -0.24197], [0.30754, -0.13023, 0.31819, -0.31032, -0.18517], [-0.15294, -0.17957, -0.26462, 0.21125, 0.38587], [-0.35426, 0.34871, 0.28221, -0.07022, -0.20645], [-0.15438, 0.0996, 0.25948, -0.49654, 0.29184], [-0.31104, -0.21406, -0.03701, 0.33888, 0.22324], [0.14595, 0.03697, 0.06295, -0.17073, -0.07513], [0.42624, -0.06188, 0.13743, -0.38904, -0.11275], [0.47184, 0.47852, -0.54404, -0.25857, -0.14775], [0.23457, -0.14309, -0.22512, 0.22183, -0.08819], [0.7113, -0.0478, -0.18811, -0.29847, -0.17691], [0.20007, 0.36855, 0.42539, -1.03872, 0.04471], [0.10861, -0.03155, 0.02927, -0.08406, -0.02227], [0.1944, -0.28245, -0.14113, 0.08045, 0.14872], [0.33339, -0.00519, 0.06385, -0.29423, -0.09781], [1.32034, -0.25965, -0.6677, -0.32583, -0.06716], [-0.42143, 0.15616, -0.33112, 0.52911, 0.06729], [-0.25273, 0.26746, -0.17348, 0.46084, -0.3021], [-0.46555, -0.02387, 0.16563, 0.0887, 0.2351], [-0.19554, -0.31522, -0.19613, 0.98306, -0.27617], [0.11714, -0.10523, 0.26843, 0.33347, -0.61382], [-0.08539, -0.15475, 0.22545, 0.05007, -0.03539], [0.89456, 0.091, -0.0962, -0.34289, -0.54647], [-0.31934, -0.23124, 0.28361, -0.02444, 0.2914], [0.25876, 0.07944, -0.34808, -0.0169, 0.02678], [-0.58765, 0.09539, 0.53176, -0.21806, 0.17856], [0.11414, 0.0819, 0.27372, -0.27463, -0.19513], [0.00501, -0.2519, -0.23637, 0.29648, 0.18679], [0.1627, -0.04995, -0.58742, 0.65996, -0.18529], [-0.3319, 0.13931, -0.17803, 0.2857, 0.08492], [0.34161, 0.12087, 0.09013, -0.49361, -0.059], [0.41611, -0.15924, -0.26652, 0.47878, -0.46913], [-0.04623, -0.14277, 0.15477, 0.36158, -0.32735], [-0.24577, -0.09354, -0.00883, -0.01909, 0.36723], [0.17661, 0.08024, -0.07903, -0.77142, 0.59361], [0.487, -0.24907, -0.29373, -0.27812, 0.33392], [-0.0257, 0.26161, -0.35753, -0.27331, 0.39494], [-0.2977, -0.20639, -0.26023, 0.79266, -0.02834], [-0.093, -0.24815, 0.00905, 0.23745, 0.09466], [0.86718, -0.24138, 0.04313, -0.82127, 0.15234], [-0.68696, -0.1538, 0.30527, 0.86987, -0.33438], [-0.07569, 0.12956, -0.01382, 0.32365, -0.3637], [-0.00485, -0.00508, -0.07129, -0.0431, 0.12432], [-0.29389, -0.05746, -0.47135, 0.8018, 0.0209], [0.97767, -0.2277, 0.00064, -0.15319, -0.59742], [-1.21476, -0.0966, -0.62372, 1.56941, 0.36567], [-0.15137, 0.07079, -0.29946, 0.44878, -0.06874], [-0.09704, 0.16243, -0.61699, 0.28733, 0.26426], [-0.11365, -0.13129, 0.13955, 0.16616, -0.06077], [0.27251, 0.2248, 0.14404, -0.102, -0.53934], [-0.09972, -0.18956, -0.06561, -0.18577, 0.54067], [0.09666, 0.11955, -0.26513, -0.00866, 0.05758], [-0.44595, -0.29036, 0.39847, 0.46444, -0.12659], [-0.43014, 0.25895, -0.06927, 0.0543, 0.18616], [0.01691, 0.05733, 0.09717, -0.17897, 0.00757], [-0.91864, -0.31941, 0.24825, 1.071, -0.08121], [-0.03168, -0.20012, -0.10094, -0.36364, 0.69637], [0.48945, -0.1084, -0.1211, -0.24813, -0.01182], [-0.30445, -0.14292, -0.14269, 0.73098, -0.14092], [-0.97077, 0.30656, -0.42056, 0.91008, 0.17468], [-0.17944, -0.09311, 0.01449, -0.162, 0.42006], [-0.01433, 0.08171, -0.41893, 0.17659, 0.17496], [-0.04336, 0.14744, 0.12104, 0.30609, -0.53121], [0.20566, 0.12857, 0.05827, -0.67708, 0.28458], [0.08666, 0.2708, 0.28122, -0.55081, -0.08787], [-0.00702, 0.35899, -0.12847, -1.10422, 0.88072], [-0.62413, -0.27657, 0.32463, 0.4142, 0.16187], [-0.15584, 0.08876, 0.74162, -0.44606, -0.22849], [-1.02945, -0.15424, 0.18293, 0.63697, 0.36379], [0.01855, -0.13662, 0.04685, 0.25124, -0.18001], [-0.49505, 0.08016, -0.02992, 0.48689, -0.04208], [0.41383, -0.14182, -0.34974, 0.20331, -0.12559], [0.23159, -0.17749, 0.00797, -0.14819, 0.08612], [0.34467, -0.41229, 0.15751, 0.14035, -0.23024], [-0.04991, 0.27737, 0.18814, -0.52397, 0.10838], [-0.70978, 0.22092, -0.04756, 0.29269, 0.24373], [-0.70174, -0.39136, 0.05235, 1.00759, 0.03316], [0.04275, 0.02508, -0.26676, 0.27821, -0.07928], [-1.11303, 0.04965, -0.05764, 0.94841, 0.17261], [-0.29776, -0.13106, 0.218, 0.44966, -0.23884], [-0.0724, 0.18279, 0.63995, -0.61718, -0.13317], [0.13894, -0.53412, -0.32543, 0.49353, 0.22708], [0.23975, -0.23819, -0.11429, 0.5269, -0.41416], [0.3126, -0.05165, -0.39592, 0.31782, -0.18286], [-0.7123, -0.43233, 0.22288, 1.10482, -0.18307], [0.06913, -0.06738, 0.11894, -0.1729, 0.0522], [0.30081, -0.34072, -0.0828, 0.44248, -0.31977], [0.22255, 0.00963, -0.34037, -0.15308, 0.26128], [0.57702, -0.07832, 0.20217, 0.08738, -0.78825], [0.02443, -0.03894, 0.04812, 0.43818, -0.47179], [0.0641, 0.16152, 0.19251, -0.37582, -0.04231], [0.13502, -0.04744, -0.32511, -0.22676, 0.46429], [0.67444, -0.02356, -0.23525, -0.09395, -0.32169], [0.67193, 0.00844, -0.4329, -0.60085, 0.35339], [-0.79158, 0.0846, 0.00545, 0.95161, -0.25009], [0.24778, -0.10602, 0.08304, -0.09614, -0.12866], [-0.35555, 0.28765, -0.00562, -0.1117, 0.18522], [-0.029, 0.41347, -0.03511, -0.64265, 0.29329], [-0.6501, 0.09609, -0.39803, 0.6566, 0.29544], [0.4907, 0.42379, -0.33293, -0.68694, 0.10537], [-0.13404, -0.22651, 0.00759, 0.12054, 0.23241], [-0.3672, -0.14822, 0.14999, 0.23663, 0.1288], [0.09068, 0.02837, -0.38538, 0.48843, -0.2221], [0.0522, 0.1442, -0.34098, 0.1403, 0.00428], [0.63345, 0.08028, 0.00148, -0.39578, -0.31942], [-0.13758, -0.14058, -0.37136, 0.51431, 0.13521], [-0.35113, -0.02489, 0.11624, -0.00452, 0.26429], [-0.09054, -0.03442, 0.31108, -0.00686, -0.17927], [-0.22426, 0.00936, -0.15931, 0.48675, -0.11254], [-0.22035, 0.1199, 0.0578, 0.02955, 0.0131], [-0.52229, 0.04435, 0.22037, 0.01969, 0.23789], [-0.60033, 0.10234, 0.13554, 0.27634, 0.08611], [0.08939, -0.38921, -0.58426, 0.2732, 0.61087], [0.26874, 0.30327, -0.16508, -0.31023, -0.09671], [-0.13654, -0.14961, -0.08364, 0.43058, -0.06078], [0.07899, -0.23544, -0.25564, 0.63298, -0.22089], [-0.13056, -0.15937, -0.12403, 0.42342, -0.00946], [-0.42074, -0.51431, 0.47611, 0.19671, 0.26223], [0.25364, 0.37944, -0.00497, -0.55283, -0.07527], [-1.22837, 0.26864, -0.08095, 0.49415, 0.54653], [0.01141, 0.17427, -0.04741, 0.28636, -0.42463], [0.07054, 0.23829, 0.02501, -0.70759, 0.37375], [-0.3403, 0.25982, 0.41606, -0.29194, -0.04364], [-0.29668, -0.40255, -0.20978, 0.514, 0.39501], [0.02719, 0.29761, -0.14785, -0.11117, -0.06578], [-0.50307, -0.0763, 0.0014, 0.15213, 0.42584], [-0.00527, 0.00137, 0.15464, 0.00068, -0.15143], [0.28691, -0.64273, -0.10138, 0.19272, 0.26448], [-0.95748, -0.10729, -0.05065, 0.76786, 0.34756], [0.17089, 0.19891, -0.36982, 0.04722, -0.0472], [-0.24001, -0.28849, 0.13241, 0.54572, -0.14963], [-0.27606, 0.03572, 0.20057, -0.29914, 0.33891], [0.59385, -0.16228, -0.32826, -0.11807, 0.01477], [-0.12884, 0.12539, 0.33122, -0.20495, -0.12283], [0.80849, -0.26243, 0.08849, -0.7247, 0.09015], [0.22212, 0.50353, -0.33521, -0.19679, -0.19364], [0.4952, 0.05148, -0.34258, -0.10743, -0.09668], [0.07161, 0.17039, 0.36172, -0.8465, 0.24278], [0.46301, 0.27235, -0.18067, -0.50443, -0.05026], [0.65368, 0.25195, -0.41801, -1.51863, 1.031], [0.26265, 0.00531, -0.4277, 0.33213, -0.17238], [-0.0675, 0.44139, 0.23827, -0.95719, 0.34503], [-0.6602, 0.66589, 0.02813, 0.16795, -0.20176], [0.14545, 0.08671, 0.27375, 0.27937, -0.78528], [0.11351, -0.0349, -0.05679, 0.33347, -0.35528], [-0.01317, 0.38874, 0.08829, -0.17679, -0.28707], [-0.75919, -0.04493, 0.05454, 0.51885, 0.23073], [-0.68187, 0.13966, 0.14533, 0.48991, -0.09302], [-0.35075, -0.16747, -0.10926, 0.10503, 0.52245], [0.24846, -0.48138, 0.28908, 0.17929, -0.23545], [0.17703, -0.10665, 0.0116, -0.05989, -0.0221], [0.33064, 0.02028, -0.61449, 0.02856, 0.23501], [-0.39304, -0.15771, 0.38193, 0.31929, -0.15047], [-0.4914, 0.02084, -0.31314, 0.50767, 0.27603], [0.88489, -0.01162, -0.45931, -0.10178, -0.31218], [0.11668, 0.09967, -0.24947, -0.11823, 0.15135], [0.68057, -0.29884, 0.25311, -0.7701, 0.13526], [0.46679, 0.24884, -0.45748, -0.05337, -0.20478], [-0.18001, 0.10956, 0.314, -0.41984, 0.17628], [0.12536, -0.14462, -0.2336, 0.30067, -0.04781], [0.33801, -0.27151, 0.31376, -0.08722, -0.29304], [0.20191, 0.24283, -0.58335, -0.38893, 0.52754], [0.29207, -0.64709, 0.158, 0.58944, -0.39242], [1.01264, 0.19006, 0.06513, -0.95208, -0.31575], [-0.44966, 0.89139, -0.42747, -0.54131, 0.52705], [0.16086, 0.30152, -0.07046, 2e-05, -0.39194], [-0.59331, -0.13793, 0.51518, 0.34945, -0.13339], [0.12087, 0.12829, -0.08137, -0.29712, 0.12933], [-0.16695, -0.22972, 0.10435, -0.1715, 0.46382], [-0.3578, -0.16712, 0.24947, 0.08772, 0.18773], [-0.00332, 0.28535, -0.61642, 0.05188, 0.28251], [-0.37145, 0.24835, -0.48602, 0.55737, 0.05175], [-0.47781, 0.47538, 0.07964, 0.09828, -0.17548], [-0.01721, -0.14619, -0.1725, 0.71063, -0.37474], [0.55347, -0.15793, -0.1911, 0.58585, -0.7903], [-0.58495, -0.2909, 0.41041, 0.60427, -0.13884], [0.62454, -0.51978, -0.11413, -0.19956, 0.20893], [-0.17631, 0.16481, -0.25293, 0.7117, -0.44727], [0.47218, -0.2298, 0.26184, -0.87159, 0.36738], [-0.23528, 0.18711, -0.44076, 0.12155, 0.36738], [-0.46416, 0.26854, -0.39013, 0.82388, -0.23812], [-0.35003, -0.50253, -0.18883, 0.7864, 0.25498], [0.11152, -0.2164, -0.18634, -0.30377, 0.59499], [0.36196, -0.4733, -0.02576, -0.23598, 0.37308], [-0.46693, -0.12954, 0.13033, 0.73481, -0.26866], [-0.15926, -0.17889, -0.26185, 0.40935, 0.19065], [0.32257, -0.00203, -0.17967, -0.17233, 0.03146], [0.26397, -0.20937, 0.11601, 0.02508, -0.19569], [-0.89611, -0.15973, -0.34936, 1.54643, -0.14123], [-0.23158, 0.08823, -0.19747, 0.09616, 0.24466], [0.31134, 0.19414, -0.009, -0.23733, -0.25915], [0.02541, 0.08067, -0.39529, 0.41543, -0.12622], [-0.09816, -0.24252, -0.06004, 0.03838, 0.36234], [-0.36022, -0.02211, -0.02319, 0.58035, -0.17484], [0.29956, -0.21843, 0.12995, -0.44767, 0.2366], [0.68827, -0.2005, -0.0034, -0.31251, -0.17185], [-0.72989, 0.29549, 0.03293, 0.31234, 0.08913], [0.55134, -0.201, -0.40768, -0.01527, 0.07262], [0.38917, -0.1369, -0.05707, -0.2607, 0.0655], [-0.60153, 0.21403, 0.27827, 0.402, -0.29277], [-0.24965, 0.38278, -0.27194, -0.219, 0.3578], [0.04855, -0.04771, 0.63188, -0.4841, -0.14862], [-0.3282, -0.05537, -0.27084, 0.70056, -0.04615], [-0.04701, 0.20928, 0.13304, 0.08064, -0.37595], [-0.07329, 0.01397, -0.55631, 0.41141, 0.20422], [-0.32892, 0.07218, -0.11352, 0.26376, 0.10651], [-0.01598, 0.00922, -0.05683, 0.47773, -0.41414], [0.53337, 0.08139, -0.03683, -0.9631, 0.38518], [7e-05, 0.08612, 0.0228, 0.22402, -0.33301], [0.5337, 0.19031, -0.17221, -0.49366, -0.05814], [0.18952, -0.04229, -0.54492, -0.00668, 0.40437], [0.58448, -0.01392, 0.39066, -0.65865, -0.30257], [-0.14452, -0.11714, 0.62723, 0.14782, -0.51339], [0.27895, -0.11839, 0.13186, -0.09424, -0.19819], [0.47487, -0.13087, 0.17089, 0.3525, -0.86739], [-0.18188, 0.07127, 0.1412, -0.03602, 0.00544], [0.60909, -0.01209, -0.1026, -0.08566, -0.40874], [0.14967, -0.2166, -0.16457, -0.00194, 0.23345], [0.18257, -0.33833, 0.09745, 0.24018, -0.18187], [-0.12403, -0.31509, -0.04469, 0.06611, 0.4177], [-0.29241, -0.10503, 0.15931, 0.41845, -0.18031], [0.29838, -0.08137, -0.04344, -0.0158, -0.15777], [0.48524, -0.01133, 0.47066, -0.43444, -0.51012], [0.06233, 0.17522, 0.30461, -0.32079, -0.22137], [-0.1476, -0.20033, 0.06931, 0.59883, -0.32021], [0.15261, -0.13985, 0.35125, -0.66898, 0.30496], [0.06284, -0.40739, 0.42485, 0.24383, -0.32414], [-0.07439, -0.20747, -0.01816, 0.18352, 0.11649], [0.17222, 0.17254, 0.14454, -0.18847, -0.30083], [-0.33143, 0.17743, 0.19187, 0.28891, -0.32678], [-0.1307, 0.13818, 0.05265, -0.01547, -0.04466], [0.05849, -0.04123, -0.04094, 0.11368, -0.08999], [0.30583, 0.30759, -0.40444, -0.06705, -0.14194], [-0.3496, 0.12311, -0.18128, 0.04295, 0.36482], [0.43016, 0.03963, 0.13616, -0.39194, -0.21401], [0.07262, 0.1515, -0.01979, -0.44539, 0.24107], [-0.58658, 0.32672, 0.05097, 0.00994, 0.19895], [0.81746, -0.21563, -0.12418, -0.0456, -0.43205], [0.07327, -0.37446, -0.01798, -0.20624, 0.52541], [-0.10942, 0.39317, 0.26629, -0.08714, -0.46289], [-0.10265, -0.19035, 0.83725, -0.0408, -0.50344], [0.73698, -0.41008, -0.11825, -0.23971, 0.03107], [-0.45665, 0.0641, 0.31264, 0.43474, -0.35484], [-0.10316, 0.00958, 0.11873, 0.06124, -0.08639], [-0.84377, 0.08621, 0.0075, 0.7602, -0.01015], [0.72007, -0.15916, -0.10063, -0.30837, -0.1519], [0.42803, -0.42424, 0.39058, -0.37494, -0.01944], [0.59557, 0.13014, -0.12379, -0.39835, -0.20356], [0.03914, 0.01669, -0.10115, 0.43906, -0.39374], [0.42246, 0.0907, 0.08854, -1.0552, 0.45349], [-0.80199, -0.13981, 0.52451, 0.69201, -0.27472], [0.03409, 0.03589, -0.254, 0.01337, 0.17065], [-0.17908, 0.00634, 0.15394, 0.29413, -0.27533], [0.21041, 0.03196, 0.77072, -0.65423, -0.35885], [-1.17456, 0.27799, 0.03226, 0.55885, 0.30546], [0.36141, 0.2301, -0.0905, -0.4018, -0.09921], [-0.73385, 0.08294, -0.19874, 0.35783, 0.49182], [-0.18972, -0.0101, -0.18588, 0.37329, 0.01242], [-0.05983, -0.02659, -0.17402, 0.43741, -0.17697], [0.09507, 0.03063, -0.22601, -0.10016, 0.20047], [-0.28802, -0.06127, 0.15191, -0.1377, 0.33508], [0.56888, 0.30408, 0.01385, -0.52816, -0.35865], [-0.23203, 0.25759, 0.35852, -0.27191, -0.11217], [0.33858, 0.53429, -0.23581, -0.6247, -0.01236], [0.06119, -0.30622, 0.16949, 0.05232, 0.02322], [0.12524, -0.36816, -0.22501, 0.27289, 0.19505], [0.36452, -0.13889, -0.09492, -0.30061, 0.16989], [-0.09763, 0.40204, -0.06163, -0.25301, 0.01023], [-0.13699, 0.01129, -0.00162, 0.09264, 0.03468], [0.15775, -0.03443, -0.1441, -0.10868, 0.12945], [-0.37128, 0.02488, -0.04455, 0.04037, 0.35058], [-0.49744, -0.50572, 0.13667, 0.8244, 0.04208], [0.3913, -0.14636, 0.02971, -0.33673, 0.06208], [0.79784, -0.40747, -0.16278, -0.50292, 0.27534], [0.05832, 0.02798, 0.13816, -0.02762, -0.19683], [0.60183, 0.00809, -0.31799, -0.38873, 0.09679], [-0.15896, 0.19408, 0.20764, 0.01453, -0.2573], [-0.30725, 0.37613, 0.61221, -0.25624, -0.42485], [-0.29424, -0.10413, -0.00132, 0.54201, -0.14232], [-0.12561, -0.07124, 0.3601, 0.11172, -0.27498], [-0.0558, 0.55085, -0.32957, 0.50152, -0.66701], [-0.0503, 0.02017, -0.26928, 0.15502, 0.1444], [0.1179, 0.33283, 0.08714, -0.49934, -0.03853], [-0.10706, 0.05704, 0.46642, 0.10242, -0.51882], [-0.19127, 0.07755, 0.09695, 0.28212, -0.26535], [-0.14701, -0.02842, 0.01873, 0.19853, -0.04182], [0.17169, -0.17962, 0.54234, -0.60353, 0.06912], [-0.09614, -0.58795, 0.16351, 0.74922, -0.22863], [-0.13248, 0.36181, -0.26717, 0.14965, -0.11181], [-0.18749, 0.27018, 0.41106, -0.44379, -0.04996], [-0.07443, -0.15847, 0.02206, 0.02295, 0.18789], [-0.31201, -0.11831, -0.2862, 0.52833, 0.18819], [-0.48701, -0.02549, -0.32228, 0.99302, -0.15823], [0.59252, 0.56201, -0.57752, 0.2675, -0.8445], [0.26181, 0.17406, 0.02105, 0.02862, -0.48554], [0.02655, -0.04688, -0.1654, 0.1636, 0.02212], [0.29445, 0.26715, 0.02934, -0.75905, 0.1681], [0.06648, -0.46377, 0.10979, -0.05107, 0.33858], [0.16667, -0.14177, -0.27056, -0.05891, 0.30458], [0.54955, 0.50478, -0.48646, -0.19358, -0.37429], [-0.49887, -0.15239, -0.57788, 0.86728, 0.36186], [-0.24008, -0.16696, 0.43734, 0.15192, -0.18222], [-0.09186, -0.05463, 0.29519, -0.3073, 0.15861], [-0.23553, 0.07875, -0.03106, -0.5969, 0.78474], [-0.26307, 0.07494, -0.08317, 0.20161, 0.0697], [-0.83524, 0.14944, -0.21267, 1.01029, -0.11182], [0.8158, 0.38481, -0.14362, -1.01184, -0.04515], [-0.95927, -0.40866, 0.06978, 0.81277, 0.48538], [0.71098, -0.18851, -0.05599, -0.32707, -0.13941], [0.14328, 0.00019, 0.1886, -0.45474, 0.12267], [0.61227, -0.07356, 0.18987, -0.93711, 0.20852], [0.50925, 0.03685, 0.06622, -0.85605, 0.24374], [-0.90798, 0.05128, -0.39816, 1.49841, -0.24356], [0.77138, -0.05482, -0.12024, -0.24176, -0.35456], [1.47289, -0.13897, -0.46161, -0.82627, -0.04604], [-0.33661, -0.02745, -0.22913, 0.15485, 0.43833], [-0.54241, 0.07286, 0.04661, 0.52401, -0.10107], [-0.07086, 0.16712, -0.3119, 0.26754, -0.0519], [0.62484, -0.23895, 0.18142, -0.87063, 0.30331], [-0.25299, -0.45398, 0.04964, 0.55513, 0.1022], [-0.21571, -0.16775, -0.25292, 0.54911, 0.08728], [-0.82064, 0.05333, 0.42815, 0.26409, 0.07508], [-0.08575, -0.12281, 0.03694, 0.19844, -0.02682], [-0.49745, -0.3581, 0.07341, 0.9533, -0.17117], [-0.59331, 0.05578, -0.16407, 0.43856, 0.26304], [-0.21115, 0.27731, -0.45565, 0.04064, 0.34885], [0.63887, 0.20263, 0.09113, -0.84982, -0.08281], [-0.56123, -0.13432, 0.09909, 0.58424, 0.01222], [-0.52415, -0.13578, 0.1826, 0.30614, 0.17119], [0.22424, -0.0424, -0.81278, 0.30685, 0.32409], [-0.11474, 0.02131, -0.31917, 0.71665, -0.30405], [-0.33907, -0.05851, -0.16305, 0.42103, 0.1396], [0.78385, 0.11274, 0.05948, -0.85937, -0.09671], [-0.45768, 0.05045, 0.1764, 0.52754, -0.29671], [-0.42766, -0.06714, 0.65121, -0.51645, 0.36005], [-0.0012, 0.00658, 0.1832, -0.19159, 0.00301], [0.62387, -0.11463, -0.33169, -0.03992, -0.13763], [0.74666, -0.54531, 0.19175, -0.17034, -0.22276], [-0.83474, -0.17721, 0.39427, 0.77292, -0.15524], [-0.31468, 0.04798, 0.29079, 0.14498, -0.16907], [0.6629, -0.06576, 0.225, -0.98192, 0.15979], [0.27642, -0.12149, 0.15797, -0.46946, 0.15654], [-0.27839, 0.09635, -0.29324, 0.41671, 0.05857], [0.15177, 0.25295, -0.58554, -0.04674, 0.22755], [-0.55493, 0.30898, 0.07395, -0.06271, 0.23471], [-0.23764, 0.06768, -0.27618, 0.98782, -0.54168], [-0.76021, 0.33836, 0.09762, 0.43316, -0.10893], [0.9699, -0.14647, 0.14866, -0.60935, -0.36273], [-0.79332, 0.26321, 0.35162, -0.17344, 0.35192], [0.33054, -0.07468, -0.12131, 0.0606, -0.19514], [0.06815, 0.35567, -0.26858, -0.16528, 0.01005], [0.3926, 0.03613, -0.08415, -0.66668, 0.32211], [0.13851, -0.23372, 0.18226, 0.05007, -0.13712], [-0.17455, 0.51575, -0.40024, -0.24131, 0.30034], [0.35594, 0.26825, -0.05887, -0.31811, -0.2472], [0.03432, 0.37703, 0.25176, -0.7177, 0.05459], [-0.54437, -0.26245, 0.14488, 0.43879, 0.22315], [0.34049, 0.15792, -0.13977, -0.26112, -0.09752], [0.59638, 0.1523, -0.32368, -0.35472, -0.07028], [-0.22103, -0.06447, 0.08223, 0.08421, 0.11907], [-0.40865, 0.00283, 0.08248, -0.20528, 0.52862], [-0.79379, 0.18415, -0.36341, 0.86563, 0.10742], [-0.35869, -0.35167, 0.60111, 0.15569, -0.04645], [0.61713, -0.06592, -0.04783, -0.6572, 0.15383], [-0.20844, 0.09829, -0.30963, -0.17388, 0.59365], [-0.99331, 0.08447, 0.04275, 0.22775, 0.63834], [0.91393, -0.52109, -0.20907, -0.11964, -0.06414], [0.88603, 0.01456, 0.33346, -0.98438, -0.24966], [-0.3127, -0.04175, 0.38498, 0.36589, -0.39642], [0.24479, 0.33304, 0.02438, -0.33922, -0.263], [-0.34867, 0.164, -0.01634, -0.04831, 0.24931], [0.06524, -0.21406, -0.09236, 0.55356, -0.31238], [0.35762, -0.07633, -0.23483, -0.14415, 0.09769], [0.5164, 0.00483, 0.17691, -0.35054, -0.34761], [0.36898, -0.12665, -0.11079, -0.3109, 0.17936], [0.52069, -0.31349, -0.19004, -0.08333, 0.06617], [0.79444, 0.13664, -0.23619, -1.02239, 0.3275], [0.24554, 0.34339, 0.66096, -1.09942, -0.15047], [-0.18838, 0.17959, 0.45091, -0.16629, -0.27583], [-1.09988, 0.06953, 0.43222, 0.69691, -0.09878], [-0.13856, 0.20573, -0.11014, -0.01832, 0.06128], [-0.13999, -0.25777, 0.0927, -0.00864, 0.3137], [-0.12573, 0.40303, 0.26722, -0.72159, 0.17707], [0.26414, -0.371, 0.63978, -0.11929, -0.41362], [-0.25074, -0.21194, 0.15093, -0.12474, 0.43649], [-0.21281, 0.00692, 0.06328, -0.3253, 0.4679], [0.04545, 0.26856, 0.3711, -0.5881, -0.09701], [-0.08371, 0.05962, 0.28062, 0.10031, -0.35684], [0.25907, 0.08242, -0.39989, 0.11959, -0.0612], [-0.06229, -0.12152, -0.1268, 0.26255, 0.04806], [-0.91937, -0.28822, 0.32282, 0.79815, 0.08661], [0.70352, -0.05922, -0.03372, -0.32769, -0.28289], [-0.64483, 0.24377, -0.40243, 0.0893, 0.71418], [-0.28877, -0.09167, -0.44058, 1.14795, -0.32693], [-0.23554, 0.24289, -0.4186, 0.44039, -0.02914], [0.87083, -0.06139, 0.07663, -0.8445, -0.04156], [0.17361, 0.10908, 0.07299, -0.52925, 0.17356], [0.59183, 0.00305, -0.23125, -0.22266, -0.14098], [-0.01157, -0.15517, 0.12256, 0.07242, -0.02823], [0.19189, 0.43455, 0.3842, -0.92848, -0.08216], [0.02668, 0.18327, -0.49989, -0.0956, 0.38554], [0.34185, 0.34823, -0.23939, -0.36808, -0.08261], [0.2746, -0.19446, 0.28959, -0.37562, 0.00589], [-0.20974, -0.10589, -0.04844, 0.31387, 0.05019], [0.18777, 0.01706, -0.10333, -0.12279, 0.02128], [-0.02287, 0.04499, 0.01695, -0.14313, 0.10407], [0.10721, 0.28502, -0.4205, 0.19472, -0.16646], [-0.26534, 0.23239, 0.15395, 0.11193, -0.23293], [0.62956, -0.19381, -0.04693, -0.42707, 0.03825], [-0.92799, 0.20593, 0.26276, 0.15443, 0.30488], [1.63812, 0.32839, 0.12039, -1.71676, -0.37014], [0.13113, -0.2811, -0.39323, 0.75038, -0.20718], [0.14924, 0.01928, 0.22207, -0.55902, 0.16844], [-0.34603, 0.38529, -0.60171, 0.5741, -0.01165], [0.231, 0.3151, 0.07535, -0.95006, 0.32861], [-0.25595, -0.01626, 0.43352, -0.23991, 0.0786], [0.29283, -0.1803, 0.16072, 0.04188, -0.31513], [0.64175, 0.0674, -0.00601, -1.02087, 0.31774], [-0.88061, 0.14785, 0.01748, 0.58149, 0.13379], [-0.43018, 0.11448, 0.44224, -0.8793, 0.75277], [0.10605, -0.08325, -0.17562, -0.01159, 0.16441], [-0.10827, -0.02854, 0.07782, 0.15048, -0.0915], [-0.45197, 0.25372, 0.21572, 0.23663, -0.25411], [-0.09664, -0.02936, -0.33549, 0.76619, -0.3047], [-0.05215, 0.03185, 0.13253, -0.04865, -0.06358], [1.12692, 0.06529, -0.02793, -1.03303, -0.13126], [0.36553, -0.2862, 0.34564, -0.24651, -0.17845], [-0.21853, -0.0971, -0.03101, 0.6642, -0.31757], [-0.05016, -0.13769, 0.21882, 0.09824, -0.12921], [-0.36967, -0.30089, 0.33665, 0.36876, -0.03485], [-0.2612, -0.13864, 0.78247, -0.20187, -0.18077], [-1.20291, -0.14685, -0.44576, 1.19749, 0.59804], [-0.46909, 0.50046, 0.00225, -0.06107, 0.02745], [0.08333, 0.21505, 0.18172, -0.85271, 0.37261], [0.40626, 0.28993, -0.08907, -0.70284, 0.09573], [-0.06463, -0.00043, 0.0953, -0.2098, 0.17955], [0.32275, 0.39205, -0.66045, 0.16436, -0.21871], [-0.21286, 0.21686, -0.2183, 0.18995, 0.02434], [0.30204, -0.02236, 0.20739, -0.42581, -0.06127], [0.16515, -0.01718, 0.422, -0.63894, 0.06898], [-0.72506, 0.22628, -0.18403, 0.27821, 0.40461], [-0.65622, 0.15664, 0.33745, -0.18893, 0.35106], [0.04226, 0.51841, 0.08662, -0.61329, -0.034], [0.47517, -0.30826, -0.57083, 0.15705, 0.24687], [-0.11041, 0.34748, -0.34546, 0.17956, -0.07117], [0.24889, 0.11784, -0.21422, 0.10195, -0.25447], [-0.0067, -0.19156, 0.37353, -0.32165, 0.14639], [-0.00175, 0.1624, -0.07998, -0.16344, 0.08278]], "b": [-0.03003, -0.01796, -0.03331, -0.02212, 0.10343]}} \ No newline at end of file diff --git a/packages/work-labeller/test/classifier.test.ts b/packages/work-labeller/test/classifier.test.ts new file mode 100644 index 0000000000..b17284ed4e --- /dev/null +++ b/packages/work-labeller/test/classifier.test.ts @@ -0,0 +1,174 @@ +import { describe, expect, test } from "bun:test"; +import { createHash } from "node:crypto"; +import { mkdtemp, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; + +import { + labelEmbedding, + loadWorkClassifier, + MANIFEST, + meanPool, + WORK_ACTIONS, + WORK_HEAD, + WorkClassifierSource, + type OrtRuntime, + type WorkHead, + type WorkModelManifest, +} from "../src/node.js"; + +const sha = (bytes: string | Buffer) => createHash("sha256").update(bytes).digest("hex"); + +/** Two dimensions: along the first is code, along the second is not work. No kind of work. */ +const HEAD: WorkHead = { + prefix: "query: ", + action: null, + family: { classes: ["code", null], scale: 20, floor: 0.6, w: [[1, 0], [0, 1]], b: [0, 0] }, +}; +/** Three dimensions: a fix, a test, or not work; the family head knows code from not work. */ +const BOTH: WorkHead = { + prefix: "query: ", + action: { classes: ["fix", "test", null], scale: 20, floor: 0.6, w: [[1, 0, 0], [0, 1, 0], [0, 0, 1]], b: [0, 0, 0] }, + family: { classes: ["code", null], scale: 20, floor: 0.6, w: [[1, 0], [1, 0], [0, 1]], b: [0, 0] }, +}; + +const TOKENIZER = JSON.stringify({ + added_tokens: [ + { id: 0, content: "", special: true }, + { id: 2, content: "", special: true }, + { id: 3, content: "", special: true }, + ], + normalizer: { type: "Sequence", normalizers: [{ type: "Replace" }] }, + pre_tokenizer: { type: "Metaspace", replacement: "\u2581" }, + model: { type: "Unigram", unk_id: 3, vocab: [["", 0], ["", 0], ["", 0], ["", 0], ["\u2581fix", -1], ["\u2581query:", -1]] }, +}); + +/** An encoder whose every token vector is `vector`, recording what it was fed. */ +function fakeOrt(vector: number[], seen: bigint[][] = []): OrtRuntime { + return { + Tensor: class { + constructor( + readonly type: string, + readonly data: BigInt64Array, + readonly dims: readonly number[], + ) {} + }, + InferenceSession: { + create: async () => ({ + inputNames: ["input_ids", "attention_mask"], + run: async (feeds: Record) => { + const ids = feeds.input_ids; + const length = ids && typeof ids === "object" && "data" in ids && ids.data instanceof BigInt64Array ? ids.data.length : 0; + if (ids && typeof ids === "object" && "data" in ids && ids.data instanceof BigInt64Array) seen.push([...ids.data]); + const data = new Float32Array(length * vector.length); + for (let t = 0; t < length; t += 1) data.set(vector, t * vector.length); + return { last_hidden_state: { data, dims: [1, length, vector.length] } }; + }, + }), + }, + }; +} + +/** The manifest the tests trust: what MANIFEST is for the real model. */ +const PINNED: WorkModelManifest = { + id: "test/encoder", + revision: "0123456789abcdef", + license: "MIT", + model: { file: "model.onnx", sha256: sha("weights"), url: "https://example.test/model.onnx" }, + tokenizer: { file: "tokenizer.json", sha256: sha(TOKENIZER), url: "https://example.test/tokenizer.json" }, +}; + +async function modelDir(tokenizer = TOKENIZER) { + const dir = await mkdtemp(join(tmpdir(), "work-model-")); + await writeFile(join(dir, "model.onnx"), "weights"); + await writeFile(join(dir, "tokenizer.json"), tokenizer); + return dir; +} + +describe("work classifier", () => { + test("the package trusts e5-base from the release, and its head names every kind of work and family", () => { + expect(MANIFEST.id).toBe("Xenova/multilingual-e5-base"); + for (const file of [MANIFEST.model, MANIFEST.tokenizer]) { + expect(file.url).toBe(`https://github.com/redrob-labs/redrob-cowork/releases/download/insights-model-e5-base-2026.10/${file.file}`); + } + expect(WORK_HEAD.prefix).toBe("query: "); + expect(WORK_HEAD.family.classes).toEqual(["code", "design", "sheet", "write", null]); + expect(WORK_HEAD.family.w).toHaveLength(768); + expect(WORK_HEAD.action?.classes).toEqual([...[...WORK_ACTIONS].sort(), null]); + expect(WORK_HEAD.action?.w).toHaveLength(768); + }); + + test("a kind of work above its floor brings its family; below it, the family head may still name one", () => { + expect(labelEmbedding(BOTH, Float32Array.from([1, 0, 0]))).toMatchObject({ action: "fix", family: "code" }); + // Torn between a fix and a test, so no kind of work, but surely code. + expect(labelEmbedding(BOTH, Float32Array.from([0.5, 0.5, 0]))).toMatchObject({ action: null, family: "code" }); + expect(labelEmbedding(BOTH, Float32Array.from([0, 0, 1]))).toMatchObject({ action: null, family: null }); + }); + + test("names the family above the floor, and nothing for not work or below it", () => { + expect(labelEmbedding(HEAD, Float32Array.from([1, 0])).family).toBe("code"); + expect(labelEmbedding(HEAD, Float32Array.from([0, 1])).family).toBeNull(); + const unsure = labelEmbedding(HEAD, Float32Array.from([0.51, 0.49])); + expect(unsure.family).toBeNull(); + expect(unsure.confidence).toBeGreaterThan(0.5); + }); + + test("mean-pools the tokens and normalises the result", () => { + expect([...meanPool(Float32Array.from([3, 0, 1, 4]), 2, 2)].map((value) => Math.round(value * 1000) / 1000)).toEqual([0.707, 0.707]); + }); + + test("reads the message with the query prefix, at most 256 tokens, and labels it", async () => { + const dir = await modelDir(); + const seen: bigint[][] = []; + const classifier = await loadWorkClassifier(dir, fakeOrt([2, 0], seen), { manifest: PINNED, head: HEAD }); + expect(classifier.id).toBe("test/encoder@01234567"); + expect((await classifier.label("fix")).family).toBe("code"); + expect(seen[0]).toEqual([0n, 5n, 4n, 2n]); + await classifier.label("fix ".repeat(400)); + expect(seen[1]).toHaveLength(256); + expect(await classifier.label(" ")).toEqual({ action: null, family: null, confidence: 0 }); + expect(seen).toHaveLength(2); + }); + + test("refuses files that do not hash to the manifest it trusts", async () => { + const otherModel = { ...PINNED, model: { ...PINNED.model, sha256: sha("other weights") } }; + await expect(loadWorkClassifier(await modelDir(), fakeOrt([1, 0]), { manifest: otherModel })).rejects.toThrow(/model file does not match/); + await expect(loadWorkClassifier(await modelDir(TOKENIZER.replace("fix", "fox")), fakeOrt([1, 0]), { manifest: PINNED })).rejects.toThrow( + /tokenizer does not match/, + ); + }); + + test("the source says why there is no model, and a folder holding another model loads nothing", async () => { + expect(new WorkClassifierSource({ directory: null }).status()).toEqual({ state: "absent", reason: "no work model is installed" }); + const dir = await modelDir(); + const other = new WorkClassifierSource({ directory: dir, manifest: { ...PINNED, model: { ...PINNED.model, sha256: sha("other") } }, loadRuntime: async () => fakeOrt([1, 0]) }); + expect(await other.label("fix the login bug")).toBeNull(); + expect(other.status()).toMatchObject({ state: "failed", reason: expect.stringMatching(/integrity check/) }); + const trusted = new WorkClassifierSource({ directory: dir, manifest: PINNED, loadRuntime: async () => fakeOrt([1, 0]) }); + expect(trusted.status()).toEqual({ state: "not-loaded" }); + expect(await trusted.label("fix")).not.toBeNull(); + expect(trusted.status()).toEqual({ state: "ready", model: "test/encoder@01234567" }); + }); + + test("a model that fails mid-run labels nothing from then on", async () => { + let calls = 0; + const empty = new WorkClassifierSource({ directory: import.meta.dir, manifest: PINNED }); + expect(empty.status()).toEqual({ state: "absent", reason: "the work model folder has no model" }); + const ready = new WorkClassifierSource({ + directory: await modelDir(), + manifest: PINNED, + loadRuntime: async () => fakeOrt([1, 0]), + load: async () => ({ + id: "x", + label: async () => { + calls += 1; + throw new Error("boom"); + }, + }), + }); + expect(await ready.label("a")).toBeNull(); + expect(await ready.label("b")).toBeNull(); + expect(calls).toBe(1); + expect(ready.status()).toMatchObject({ state: "failed" }); + }); +}); diff --git a/packages/work-labeller/test/download.test.ts b/packages/work-labeller/test/download.test.ts new file mode 100644 index 0000000000..b8a64f1a8e --- /dev/null +++ b/packages/work-labeller/test/download.test.ts @@ -0,0 +1,141 @@ +import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import { createHash } from "node:crypto"; +import { existsSync } from "node:fs"; +import { mkdir, mkdtemp, readFile, readdir, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; + +import { ensureWorkModel, MIN_FREE_BYTES, modelDirectory, WorkModelFetcher, type WorkModelManifest } from "../src/node.js"; + +const sha = (bytes: Uint8Array | string) => createHash("sha256").update(bytes).digest("hex"); +const MODEL = new Uint8Array(300_000).map((_, i) => (i * 31) % 251); +const TOKENIZER = new TextEncoder().encode('{"model":"tok"}'); +const PLENTY = () => MIN_FREE_BYTES * 2; + +/** A release host like GitHub's: /release/* redirects to /assets/*, which honours byte ranges. */ +type Hit = { path: string; range: string | null }; +let hits: Hit[] = []; +let corrupt = false; +let ignoreRanges = false; +let server: ReturnType; +let base = ""; + +beforeAll(() => { + server = Bun.serve({ + port: 0, + fetch: (request) => { + const url = new URL(request.url); + hits.push({ path: url.pathname, range: request.headers.get("range") }); + if (url.pathname.startsWith("/release/")) return Response.redirect(`${base}/assets/${url.pathname.slice(9)}`, 302); + const bytes = url.pathname.endsWith("model.onnx") ? (corrupt ? MODEL.map((b) => b ^ 1) : MODEL) : TOKENIZER; + const range = /^bytes=(\d+)-$/.exec(request.headers.get("range") ?? ""); + if (range && !ignoreRanges) { + const start = Number(range[1]); + return new Response(bytes.slice(start), { + status: 206, + headers: { "content-range": `bytes ${start}-${bytes.length - 1}/${bytes.length}`, "content-length": String(bytes.length - start) }, + }); + } + return new Response(bytes, { headers: { "content-length": String(bytes.length) } }); + }, + }); + base = `http://127.0.0.1:${server.port}`; +}); +afterAll(() => server.stop(true)); + +const manifest = (): WorkModelManifest => ({ + id: "test/encoder", + revision: "rev2", + license: "MIT", + model: { file: "model.onnx", sha256: sha(MODEL), url: `${base}/release/model.onnx` }, + tokenizer: { file: "tokenizer.json", sha256: sha(TOKENIZER), url: `${base}/release/tokenizer.json` }, +}); + +const fresh = () => mkdtemp(join(tmpdir(), "work-cache-")); +const reset = () => { + hits = []; + corrupt = false; + ignoreRanges = false; +}; + +describe("download on first use", () => { + test("follows the release redirect, verifies both files, and later finds them without the network", async () => { + reset(); + const root = await fresh(); + const progress: number[] = []; + const dir = await ensureWorkModel(root, { manifest: manifest(), freeBytes: PLENTY, onProgress: (p) => p.file === "model.onnx" && progress.push(p.received) }); + expect(dir).toBe(modelDirectory(root, manifest())); + expect(new Uint8Array(await readFile(join(dir, "model.onnx")))).toEqual(MODEL); + expect(hits.map((h) => h.path)).toEqual(["/release/tokenizer.json", "/assets/tokenizer.json", "/release/model.onnx", "/assets/model.onnx"]); + expect(progress.at(-1)).toBe(MODEL.length); + hits = []; + expect(await ensureWorkModel(root, { manifest: manifest(), freeBytes: PLENTY })).toBe(dir); + expect(hits).toEqual([]); + }); + + test("resumes a broken download with a byte range, and verifies the whole file", async () => { + reset(); + const root = await fresh(); + const dir = modelDirectory(root, manifest()); + await mkdir(dir, { recursive: true }); + await writeFile(join(dir, "model.onnx.partial"), MODEL.slice(0, 120_000)); + await ensureWorkModel(root, { manifest: manifest(), freeBytes: PLENTY }); + expect(hits.find((h) => h.path === "/assets/model.onnx")?.range).toBe("bytes=120000-"); + expect(sha(new Uint8Array(await readFile(join(dir, "model.onnx"))))).toBe(sha(MODEL)); + expect(existsSync(join(dir, "model.onnx.partial"))).toBe(false); + }); + + test("starts again when the host ignores the range", async () => { + reset(); + ignoreRanges = true; + const root = await fresh(); + const dir = modelDirectory(root, manifest()); + await mkdir(dir, { recursive: true }); + await writeFile(join(dir, "model.onnx.partial"), MODEL.slice(0, 50_000)); + await ensureWorkModel(root, { manifest: manifest(), freeBytes: PLENTY }); + expect(sha(new Uint8Array(await readFile(join(dir, "model.onnx"))))).toBe(sha(MODEL)); + }); + + test("refuses bytes that do not match, and keeps nothing of them", async () => { + reset(); + corrupt = true; + const root = await fresh(); + await expect(ensureWorkModel(root, { manifest: manifest(), freeBytes: PLENTY })).rejects.toThrow(/does not match the pinned SHA-256/); + const dir = modelDirectory(root, manifest()); + expect(await readdir(dir)).toEqual(["tokenizer.json"]); + }); + + test("refuses to start without enough space, and removes other revisions once ready", async () => { + reset(); + const root = await fresh(); + await expect(ensureWorkModel(root, { manifest: manifest(), freeBytes: () => 10 * 1024 * 1024 })).rejects.toThrow(/only 10 MB free/); + expect(hits).toEqual([]); + await mkdir(join(root, "rev1"), { recursive: true }); + await writeFile(join(root, "rev1", "model.onnx"), "old"); + await ensureWorkModel(root, { manifest: manifest(), freeBytes: PLENTY }); + expect(await readdir(root)).toEqual(["rev2"]); + }); + + test("the fetcher downloads once, reports its state, and waits before retrying a failure", async () => { + reset(); + corrupt = true; + let now = 1_000; + const states: string[] = []; + const fetcher = new WorkModelFetcher(await fresh(), { manifest: manifest(), freeBytes: PLENTY, now: () => now }); + fetcher.onChange((s) => states.at(-1) !== s.state && states.push(s.state)); + expect(fetcher.state()).toEqual({ state: "absent" }); + const [a, b] = await Promise.all([fetcher.request(), fetcher.request()]); + expect([a, b]).toEqual([null, null]); + expect(hits.filter((h) => h.path === "/assets/model.onnx")).toHaveLength(1); + expect(fetcher.state()).toMatchObject({ state: "failed", retryAt: 61_000 }); + hits = []; + corrupt = false; + expect(await fetcher.request()).toBeNull(); + expect(hits).toEqual([]); + now = 61_000; + const dir = await fetcher.request(); + expect(dir).not.toBeNull(); + expect(fetcher.state()).toEqual({ state: "ready", directory: dir! }); + expect(states).toEqual(["downloading", "failed", "downloading", "ready"]); + }); +}); diff --git a/packages/work-labeller/test/fixtures/unigram-parity.json b/packages/work-labeller/test/fixtures/unigram-parity.json new file mode 100644 index 0000000000..aa099e6942 --- /dev/null +++ b/packages/work-labeller/test/fixtures/unigram-parity.json @@ -0,0 +1,10 @@ +{ +"source":"Xenova/multilingual-e5-base@1ec92430 tokenizer.json, encoded with tokenizers 0.23.2, truncation 256; pieces is the subset every case can reach", +"unkId":3, +"minScore":-20.3647518157959, +"specials":{"":0,"":1,"":2,"":3,"":250001}, +"lstrip":[""], +"charsmap":"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gAkAAIRlAAD9GwCAzNAHAMzwBwAFHACAkYkAAMxMBgDNBAYAzHAGAM10BgDMQAcAmy0PAMyoBwDNrAcAhg0AAIdVDwCEQQ8ACQsAgIIBDACDVQ8AgDUBAIHZAQCkDACAj+kAAIztAACSDACA3R0AgIv1AACIbQ8AiQ0AAA8LAIC0CwCAgiUAAE0MAICBQQAAUwwAgBUeAIANHgCAJR4AgB0eAIAtHgCABR4AgIApAACBKQAA/AsAgA0cAICEeQAAFRwAgIFNAQCAoQEAGAsAgKP9DwDMOAIAzUgDAB0cAICBWQAAzXwCAMykDQAkCwCAWQwAgKjJDwCHOQAA1wkAgImhDwADCwCAkREAAJ4MAIDaCQCAmQsAgF8MAICAuQ8AgbkPANUdAICDjQ8A9gsAgCUcAICEBQAALRwAgB4LAIA1HACAKgsAgIGdDwCHIQAAh7UPAMyoAgDN6AIAzLQMAM3cDACmzQAAp8UAAE0cAICPgQ8AjIkPAKPlAAAwCwCAPRwAgDwLAICxyQAAhwUAAFUcAIBFHACAhz0AAF0cAIBxDACANgsAgKMFDwCB+QAAzKgDAGUcAIBICwCAjEkAAKPxAABtHACAdwwAgEILAICnlQAAfRwAgHUcAIDMrAMAzcgAAN0JAICHaQAA4AkAgIG9AACCeQAA4wkAgIe5AQBOCwCAkaUAAIEdAACdHACAVAsAgIgFAAClHACAm5EAAFoLAIDmCQCAjJEBANILAIDGCwCAwAsAgMwLAICDRQAAgrkBAIG5AQCApQEAPR4AgIZxAABgCwCAhEkAAIsVAACKPQAAiTkAAIhFAACP+QAAZgsAgLoLAICMBQAAp1EBAKZJAQBlDACAsHkAAKNZAQCMqQAAgKkAAIGpAACBlQAAgJUAAK1xAQBrDACAogsAgISNAABNHgCARR4AgKMhAABdHgCAVR4AgGUeAICBbQAAgG0AALEFAQCkOQAANR4AgIUcAIBsCwCAqAUAAJUcAICNHACArQkAAMywAQCBvQMAgL0DAIPNAwCtHACAtRwAgL0cAIDMvAEAzYQBAInpAwDMHAEAgdkCAIDFAgDNOAEAzDwBAMxoAgDNRAIAg00AAMUcAICH2QAAhy0AAIBFAACBEQAAggUAAHILAIDVHACAzRwAgN0cAIDMOAIAiBUAAIjhAACAbQAAgTkAAMyEAgDNUAEA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vBkBAL0ZAQC+fQEAv3UBAKPtAQCeOwCAojsAgKY7AICqOwCApu0BAKXtAQCuOwCAq3kBAKpxAQCyOwCAtjsAgK85AQCuMQEArVUBAKxVAQC6OwCAvjsAgMI7AIDGOwCAyjsAgOGsAQDOOwCA42AGANI7AIDWOwCA2jsAgO9UBgDeOwCA4jsAgL60GgDmOwCA6jsAgO47AICGaBwAh4wDAPI7AID2OwCA+jsAgP47AICAOQAAgTkAAIIFAAACPACACjwAgA48AIASPACAFjwAgKgdAwCpQQMAqkEDAKtBAwCsQQMArUkDAK5xAwCvcQMAhCAdABo8AIAePACAIjwAgCY8AIAqPACALjwAgDI8AIC46QAAufUAALr9AAC78QAAvJEAAL2RAAC+iQAAv4kAALDhAACx4QAAsuEAALPhAAC04QAAte0AALbZAAC32QAA4wwHAOEgBwDhMAEA4wgHADY8AIA6PACAPjwAgEI8AIBGPACASjwAgE48AIBSPACA75gHAFY8AIBaPACA74gHALOJAgBePACAYjwAgL6AGgBmPACAtokCALWJAgBqPACAu2UBALplAQBuPACAcjwAgL9pAQC+ZQEAvXUBALx1AQC3PQYAtj0GALU9BgC0IQYAszUGALI1BgCxAQYAsAkGAL9ZBgC+UQYAvVkGALxNBgC7bQYAunkGALlxBgC4eQYAgJ0AAIGtAACCpQAAejwAgH48AICCPACAhjwAgIo8AICvcQYArmkGAK1tBgCsbQYAq4EGAKqZBgCpkQYAqJkGAAY8AIB2PACAjjwAgKPFHQCSPACApcUdAKbFHQCWPACAhgADAIdkAwCqKR4AqykeAKw5HgCtOR4ArikeAK8lHgCzOR4AmjwAgJ48AICiPACApjwAgLb9HgC1/R4AqjwAgLvZHgC60R4ArjwAgLI8AIC/aR8AvmEfAL1pHwC8wR4AqPEeAKnxHgCq8R4Aq/EeAKw1HgCtPR4ArjUeAK8tHgC2PACAujwAgL48AIDCPACAxjwAgMo8AIDOPACA0jwAgLjlHwC57R8AuuUfALv5HwC86R8AvZEfAL6RHwC/jR8AsFUeALFdHgCyVR4As/0fALTlHwC17R8AtuUfALfdHwCjeR8A1jwAgNo8AIDePACA4jwAgKa9HwClvR8A5jwAgKuZHwCqkR8AhogAAIdMAQCvKR4AriEeAK0pHgCsgR8AgEkAAIFJAACCWQAAs5keAOo8AIC1iR4AtlEBAO48AIDyPACA9jwAgLotAQC7JQEAvD0BAL0lAQC+JQEAvxUBAKhNHgCpVR4Aql0eAKtVHgCsTR4ArZ0BAK6JAQCvgQEAhKwBAPo8AID+PACAAj0AgAY9AIAKPQCADj0AgBI9AIC4ZQEAuW0BALplAQC7fQEAvGUBAL1tAQC+ZQEAv9kAALClAQCxrQEAsqUBALO9AQC0rQEAtZ0BALaVAQC3XQEAo9UdABY9AIAaPQCAHj0AgCI9AICmHQIApcUdACY9AICraQIAqmECACo9AIAuPQCAr1kCAK5pAgCtaQIArHECADI9AIA2PQCAOj0AgD49AIBCPQCARj0AgEo9AIBOPQCAgDkAAIE5AACCBQAAUj0AgFo9AIBePQCAh0ADAIZcBACETAQAYj0AgGY9AICEBAUA4yABAGo9AIDhqAEAbj0AgO+UGgByPQCAdj0AgHo9AIB+PQCAgj0AgIY9AICKPQCAs6EDAI49AICSPQCAlj0AgJo9AIC2fQMAtX0DAJ49AIC7WQMAulEDAKI9AICmPQCAv/0AAL79AAC9/QAAvEEDAKhRAgCpWQIAqmkCAKtpAgCstQIArb0CAK61AgCvrQIAhKgHAKo9AICuPQCAsj0AgIKpAAC2PQCAgKkAAIGpAAC4aQEAuWkBALoJAQC7CQEAvBkBAL0ZAQC+CQEAvwkBALDVAgCx3QIAstUCALNpAQC0eQEAtXkBALZpAQC3YQEA4bgBAOHUHwDjOB8A4wwbALo9AIC+PQCAwj0AgMo9AIDOPQCA0j0AgNY9AIDaPQCAvjwJAN49AIDvhBsA74QbAKOhAgDiPQCAhugEAIe8BQDmPQCApn0CAKV9AgDqPQCAq1kCAKpRAgDuPQCA8j0AgK/9AQCu/QEArf0BAKxBAgCzhQYAxj0AgPY9AID6PQCA/j0AgLaJBgC1jQYAAj4AgLuRBgC6iQYABj4AgAo+AIC/9QYAvokGAL2BBgC8iQYADj4AgBI+AIAWPgCAGj4AgB4+AIAiPgCAJj4AgO+EHQAqPgCA4QAEAC4+AIDj/AQAgBEAAIEdAACCBQAAMj4AgKjxBgCp8QYAqg0GAKsFBgCsBQYArQkGAK49BgCvNQYANj4AgDo+AICGiAAAhxADAD4+AIBCPgCA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GkUAgB5FAIAiRQCAJkUAgIANAACBFQAAgh0AACpFAIAuRQCAMkUAgIR4AQC+FAAA4xQPADpFAIDh4A0AhAADAIawBACHFAMAPkUAgEJFAIBGRQCASkUAgE5FAIBSRQCA78APAFZFAIBaRQCAXkUAgGJFAIBmRQCAakUAgLNtAwBuRQCAtX0DALZ1AwByRQCAdkUAgHpFAIC6UQMAu1EDALz1AwC9/QMAvukDAL/hAwB+RQCAgkUAgIZFAICKRQCAjkUAgJJFAICWRQCAmkUAgKhxAgCpeQIAqokDAKuJAwCsmQMArZkDAK6JAwCviQMAsPkDALH5AwCyTQMAs0UDALRBAwC1SQMAtnEDALdxAwC4IQMAuSEDALohAwC7IQMAvCEDAL0hAwC+IQMAvyEDAICdAQCBEQAAghEAAIQEBQDvFAAAnkUAgKJFAIC+EAUA48gAAKpFAIDh0AEArkUAgLJFAIC2RQCAukUAgL5FAICqeQIAq3kCAIboBACHYAUArsECAK/JAgCs3QIArdUCAMJFAICjRQIAxkUAgMpFAICmXQIAzkUAgNJFAIClVQIA1kUAgNpFAIDeRQCA4kUAgOZFAIDqRQCA7kUAgO+EDgC+rAQA4dAOAPJFAIDjFAEA9kUAgPpFAID+RQCAAkYAgLPdAQAGRgCACkYAgA5GAIASRgCAtv0BALX9AQAaRgCAu90BALrdAQCE4AQAHkYAgL+hAQC+vQEAvb0BALy9AQCoBQYAqR0GAKoVBgCrLQYArDUGAK09BgCuNQYArykGAKZFAICC9QcAgeUHAIDlBwAWRgCAIkYAgIYcAACHsAMAuCUGALnFBgC6zQYAu8UGALzdBgC9xQYAvs0GAL/FBgCwWQYAsVkGALIpBgCzKQYAtDkGALUlBgC2JQYAtx0GAKOdBgAmRgCAKkYAgC5GAIAyRgCApr0GAKW9BgA2RgCAq50GAKqdBgA6RgCAPkYAgK/hBgCu/QYArf0GAKz9BgBCRgCAs/UHAEZGAIBKRgCAtu0HAE5GAIBSRgCAteUHALqNBwC7kQcAVkYAgFpGAIC+dQcAv30HALyBBwC9fQcAqCUGAKkpBgCqOQYAqzkGAKwpBgCtKQYArnkGAK91BgBeRgCAYkYAgGZGAIBqRgCAbkYAgHJGAIB2RgCAekYAgLjVBgC53QYAuuEGALv9BgC85QYAve0GAL7lBgC/mQYAsA0GALERBgCyEQYAs+0GALT1BgC1/QYAtvUGALftBgCjsQYAgi0AAIEVAACAsQAANkUAgKapBgCloQYAfkYAgKvVBgCqyQYAgkYAgL5oAQCvOQYArjEGAK05BgCsxQYAikYAgLPxAQCGaAAAh3wBALZdAQCORgCAkkYAgLVVAQC6SQEAu0kBAJZGAICaRgCAvj0BAL8hAQC8OQEAvTUBAJ5GAICiRgCAhAQDAL6AHACmRgCA4RwGAKpGAIDjAAYAvwguAK5GAICyRgCA78gHALZGAIC6RgCAvkYAgMJGAIDGRgCAykYAgKN9AgDORgCApdkCANJGAIDWRgCAptECANpGAIDeRgCAq8UCAKrFAgCtuQIArLUCAK+tAgCusQIAqW0FAKhZBQCrDQIAqrkCAK0dAgCsHQIArwUCAK4NAgC+aB0A4kYAgOZGAIDqRgCAgB0AAIEJAACCmQEA7kYAgLnhAwC4KQIAu+EDALrpAwC94QMAvPkDAL/hAwC+6QMAsU0CALBNAgCzIQIAsi0CALUlAgC0OQIAtxECALYlAgCowQIAqdECAKrRAgCr5QIArP0CAK0VAQCuHQEArw0BAPJGAID6RgCA/kYAgAJHAIAGRwCACkcAgA5HAIASRwCAuAUBALkJAQC6HQEAuxUBALwxAQC9MQEAvv0BAL/1AQCweQEAsUEBALJBAQCzXQEAtEUBALVNAQC2RQEAtz0BAIagHQCHxB0AFkcAgO/YAAAaRwCAHkcAgCJHAIDvxAYAhGwcAOH0BgAmRwCA47AGACpHAIDhlAEALkcAgONEBgCzGQIAMkcAgDZHAIA6RwCAhewsALbVAQC1NQIAPkcAgLvFAQC6/QEAQkcAgEZHAIC/yQEAvsEBAL3JAQC81QEAo9kdAPZGAIBKRwCATkcAgFJHAICmFR4ApfUdAFZHAICrBR4Aqj0eAFpHAIBeRwCArwkeAK4BHgCtCR4ArBUeAIBpAACBaQAAggUAAGJHAIBmRwCAakcAgIcQAwCGfAMAbkcAgHJHAIB2RwCAekcAgH5HAICCRwCAhkcAgIpHAICopR8Aqa0fAKqlHwCrvR8ArKUfAK2tHwCupR8ArxUfAI5HAICSRwCAlkcAgJpHAICeRwCAokcAgKZHAICqRwCAuA0fALkZHwC6IR8AuyEfALzZAAC92QAAvskAAL/BAACwcR8AsXEfALJxHwCzRR8AtEEfALVNHwC2PR8AtzUfALMtHgCuRwCAskcAgLZHAIC6RwCAti0eALUtHgC+RwCAu7UeALq1HgDCRwCAxkcAgL+JHgC+hR4AvZEeALylHgCCKQAAo2keAIAdAACBFQAApmkeAMpHAIDORwCApWkeAKrxHgCr8R4A0kcAgITgAQCuwR4Ar80eAKzhHgCt1R4AqNUBAKnlAQCq7QEAq+UBAKz9AQCt5QEAru0BAK/lAQC+oAEAhkYAgNZHAIDaRwCAhhAAAId0AQDeRwCA4kcAgLh9AQC5wQAAusEAALvBAAC8wQAAvckAAL7xAAC/8QAAsJ0BALFFAQCyTQEAs0UBALRdAQC1RQEAtk0BALdFAQDmRwCA6kcAgO5HAIDyRwCA9kcAgO80AgDv7B4A+kcAgOHwHQDj4AIA4zAeAOGEAQD+RwCAAkgAgAZIAIAKSACAsyUCAJQAAAAOSACAEkgAgBZIAIC2JQIAtTUCABpIAIC7wQIAuhkCAB5IAIAiSACAv8ECAL7ZAgC90QIAvNkCACZIAIAqSACALkgAgKPpAgAySACApfkCAKbpAgA2SACAOkgAgD5IAICq1QIAqw0CAKwVAgCtHQIArhUCAK8NAgCAYQAAgWEAAIIFAABCSACASkgAgIQABAC+FAQATkgAgIbABACHUAMAUkgAgFZIAIBaSACAXkgAgGJIAIBmSACAqK0CAKm9AgCqtQIAqw0BAKwVAQCtHQEArhUBAK8NAQCE7AQAakgAgG5IAIBySACAdkgAgHpIAIB+SACAgkgAgLgdAQC5LQEAuiUBALvNAQC81QEAvd0BAL7JAQC/wQEAsH0BALFVAQCyXQEAs1UBALRNAQC1PQEAtjUBALctAQDhGB4AhkgAgOM4HgCKSACAjkgAgJJIAICWSACAmkgAgJ5IAICiSACAvmAEAKZIAICBdQAAgHUAAO/gHwCCbQAAqkgAgK5IAICG6AQAh3wFALJIAIDhkAEAukgAgOOgAAC+SACAwkgAgMZIAIDvtAAAykgAgM5IAIDSSACA1kgAgLUFBgBGSACAtkgAgLYFBgDaSACA3kgAgLOlBQDiSACAvRkGALwRBgC/YQYAvhEGAOZIAIDqSACAuwkGALohBgCj/QUA7kgAgPJIAID2SACA+kgAgKZdBgClXQYA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sY0CALKFAgCzbQEAtHkBALV5AQC2aQEAt2kBAIYgBACHCAUAYksAgGZLAIBqSwCAbksAgHJLAIDvXAAAhOwEAOFcDgB2SwCA44wOAHpLAIB+SwCAgksAgIZLAICjVQIAiksAgI5LAICSSwCAlksAgKYdAgClHQIAmksAgKsJAgCqOQIAnksAgKJLAICv/QEArv0BAK35AQCsEQIAqGkGAKlpBgCqeQYAq3kGAKxpBgCtaQYArp0GAK+VBgBWSwCApksAgKpLAICuSwCAsksAgLZLAIC6SwCAvksAgLj1BgC5+QYAuo0GALuFBgC8nQYAvYUGAL6FBgC/tQYAsO0GALH1BgCy/QYAs/UGALTtBgC10QYAttEGALfRBgCz8QYAghUAAIG1AACAtQAAwksAgLbpBgC14QYAvtQDALsxBgC6KQYAxksAgMpLAIC/FQYAvikGAL0hBgC8KQYAzksAgKO1BgCGyAAAh8gAAKatBgDSSwCA1ksAgKWlBgCqbQYAq3UGANpLAIDeSwCArm0GAK9RBgCsbQYArWUGAKg1BgCpOQYAqoEGAKuBBgCsgQYArYEGAK6BBgCvtQYA4ksAgOZLAIDqSwCA7ksAgPJLAID2SwCA+ksAgP5LAIC4nQYAua0GALqlBgC7aQEAvHkBAL15AQC+aQEAv2kBALDRBgCx0QYAstEGALPRBgC0tQYAtb0GALa1BgC3rQYAswkGAAJMAIAGTACACkwAgA5MAIC2AQYAtQkGABJMAIC7FQYAuhUGABZMAIAaTACAv3kGAL5xBgC9BQYAvAUGAB5MAICjTQYAIkwAgOZKAICmRQYAJkwAgCpMAIClTQYAqlEGAKtRBgAuTACAMkwAgK41BgCvPQYArEEGAK1BBgCB6QMAgN0DAISIAwCC4QMAhrA8AIeIAgC+VAMAOkwAgD5MAIBCTACARkwAgEpMAIBOTACAUkwAgFZMAIBaTACA4/AGAF5MAIDhMAYAhAA8AGJMAIBmTACAakwAgG5MAIByTACAhTQ9AHZMAIB6TACA77AHAH5MAICCTACAhkwAgIpMAICOTACAkkwAgL7EPACWTACAgp0BAIGdAQCAnQEAqA0CAKllAgCqfQIAq3UCAKxZAgCtWQIArpkDAK+ZAwCw6QMAsekDALL5AwCz+QMAtOkDALXpAwC2XQMAt1UDALhtAwC5dQMA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t/0eALO5HgBeUgCAYlIAgGZSAIBqUgCAtsUeALXVHgBuUgCAu8EeALr5HgByUgCAdlIAgL/FHgC+2R4AvdEeALzZHgB6UgCAo/0eAH5SAICCUgCApoEeAIZSAICKUgCApZEeAKq9HgCrhR4AjlIAgJJSAICunR4Ar4EeAKydHgCtlR4AqCkeAKkpHgCqVR4Aq20eAKx1HgCtfR4ArnUeAK9pHgCWUgCAmlIAgJ5SAICiUgCAplIAgKpSAICuUgCAslIAgLjpHgC59R4Auv0eALv1HgC87R4AvZEeAL6RHgC/kR4AsB0eALHlHgCy7R4As+UeALT9HgC15R4Atu0eALflHgCz3R4AtlIAgLpSAIC+UgCAwlIAgLb9HgC1/R4AhFgBALshHgC62R4AvigAAMpSAIC/IR4AvjkeAL0xHgC8OR4AgU0AAIBNAACjlR4Agl0AAKW1HgDGUgCAzlIAgKa1HgB2UQCA0lIAgKtpHgCqkR4ArXkeAKxxHgCvaR4ArnEeAIYABACHRAMAs4ECANZSAIC1gQIA2lIAgN5SAIC2gQIAiAAAAOJSAIC74QIAuu0CAL3lAgC8+QIAv9ECAL7lAgDmUgCA6lIAgIREAwC+jAMA4UgCAO5SAIDjAAIA7/wfAPJSAIDhPB4A79wCAONgHwD2UgCA+lIAgP5SAIACUwCAqQUCAKixAgCrBQIAqgUCAK0NAgCsBQIArzUCAK41AgCEbAUABlMAgApTAIAOUwCAElMAgBZTAIAaUwCAHlMAgLnpAwC44QMAu/kDALrhAwC96QMAvOEDAL9dAwC+4QMAsSkCALAlAgCzPQIAsiECALUZAgC0LQIAt9kDALYRAgAiUwCAJlMAgCpTAICjhQMALlMAgKWFAwCmhQMAMlMAgDpTAIA+UwCAqukDAKvlAwCs/QMAreEDAK7hAwCv1QMAgEkAAIFVAACCVQAAo6kCAL6YBAClQQEApkEBAEJTAICG4AUAh+AFAKotAQCrOQEArBEBAK0FAQCuDQEArwUBAEZTAIBKUwCATlMAgO/cAABSUwCAVlMAgFpTAIDviB4AhCwHAOHsHgBeUwCA4xweAGJTAIDhlAEAZlMAgOMwAACzJQIAhWDmAGpTAIBuUwCAclMAgLbNAQC1zQEAdlMAgLu1AQC6oQEAelMAgH5TAIC/iQEAvoEBAL2JAQC8nQEA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qoECAKuBAgCsgQIArYECAK6FAgCvHQEAAlYAgAZWAIAKVgCADlYAgBJWAIAWVgCAGlYAgIS4BQC4dQEAuX0BALp1AQC7CQEAvBkBAL0ZAQC+CQEAvwEBALBlAQCxbQEAsmUBALN9AQC0aQEAtV0BALZVAQC3TQEAHlYAgCJWAIAmVgCAKlYAgC5WAIAyVgCA7zQAAO/ADgDhXA4A4UwPAOOUAADjnA4ANlYAgIJlAACBfQAAgH0AADpWAIA+VgCAvsQHALNFAgBCVgCAtUUCALZNAgBKVgCAhkAGAIeQBAC67QEAu+UBALz9AQC95QEAvuEBAL/VAQCflQgAngUIAJ3dDQCcPQwAmzEMAJr1DQCZ7RAAmD0QAJfVEQCWsRUAlQUUAJTlFQCTtRkAkjEYAJE5GACQDRwAj2EcANZVAICz1QYATlYAgLX9BgBGVgCAUlYAgLaRBgBWVgCAWlYAgLuVBgC6lQYAvVUHALxVBwC/VQcAvlUHAF5WAIBiVgCAqo0GAKuFBgCsnQYArYUGAK6BBgCvtQYAhKgAAGZWAIBqVgCAoyUFAG5WAIClJQUApi0FAHJWAIB2VgCAelYAgH5WAICCVgCAhlYAgIpWAICOVgCAklYAgJZWAICaVgCAnlYAgKJWAICjqQUAotEEAKHZBACgZQUAgiEdAIM1HQCmVgCAqlYAgIaVGACH3RQAhBkZAIUZGQCKDRUAi7EUAK5WAICyVgCAjsURAI/VDACMzRAAjR0RAJJhDQCTdQ0AvkwAALpWAICWxQkAl80EAJSNDACVXQkAmkEFAJtBBQCGyP8Ah0wAAIFZAACAeQAAnCEEAIJRAAChxQEAvlYAgKMB/ACi2QEApRX9AKS1/QCnufkApgH4AKkJ+AColfkAqwX1AKqt9QCtsfEArAHwAK8d8ACurfEAseHtALAB7ACzAegAsv3sALVd6QC09ekAwlYAgMZWAIDKVgCAzlYAgNJWAIDWVgCA2lYAgN5WAIDiVgCA5lYAgKiNBACplQQAqpUEAKulBACsvQQArdkEAK75BACv8QQAhGz8AOpWAIDuVgCA8lYAgPZWAID6VgCA/lYAgAJXAIC4eQUAucUFALrNBQC7xQUAvN0FAL3FBQC+zQUAv+0FALCZBACxmQQAskkFALNJBQC0WQUAtVkFALZJBQC3SQUAox0EAL7M/AAGVwCAClcAgA5XAICmWQQApTUEABJXAICrXQQAql0EABZXAIAaVwCAr50FAK6dBQCtnQUArJ0FAB5XAICznQIAIlcAgCpXAIC2UQIALlcAgDJXAIC1uQIAukkCALtVAgCGSP0Ah8D8AL41AgC/PQIAvEUCAL09AgCo3QQAqUkDAKpRAwCrbQMArHUDAK2VAwCunQMAr7kDAICNAQCB5QEAguEBADZXAIA6VwCAPlcAgEJXAIBGVwCAuJUDALmdAwC6lQMAu60DALy1AwC9vQMAvrUDAL9VAgCwyQMAsdUDALLVAwCzrQMAtLUDALW9AwC2tQMAt60DAEpXAIBOVwCAo9EDAFJXAICl9QMAVlcAgFpXAICmHQMAXlcAgGJXAICrGQMAqgUDAK1xAwCsCQMAr3EDAK55AwDhKAcAZlcAgOPkBgBqVwCA4SgGAG5XAIDjaAEAclcAgHZXAIB6VwCA71gAAH5XAICCVwCAhlcAgO/IBgCKVwCAqE39AKmB/QCq0f0Aq9H9AKzx/QCt8f0ArvH9AK/x/QAmVwCAghEAAIEZAACA0f8AjlcAgJJXAICEdAMAvnQDALh1/gC5ff4AunX+ALvF/gC83f4AvcX+AL7F/gC/9f4AsJH9ALGR/QCykf0As5H9ALRV/gC1Xf4AtlX+ALdN/gCzWf0AllcAgIasAACHRAMAmlcAgLZx/QC1ef0AnlcAgLtV/QC6Vf0AolcAgKZXAIC/mf4AvpH+AL1F/QC8Rf0AqlcAgKMd/QCuVwCAslcAgKY1/QC2VwCAulcAgKU9/QCqEf0AqxH9AL5XAIDCVwCArtX+AK/d/gCsAf0ArQH9AKjN/wCp0f8AqtH/AKsh/gCsIf4ArSH+AK4h/gCvIf4AxlcAgMpXAIDOVwCA0lcAgNZXAIDaVwCA3lcAgOJXAIC4jf4AuZH+ALqV/gC7rf4AvLX+AL25/gC+qf4Av6n+ALDh/gCx4f4AsuX+ALP5/gC06f4AtdX+ALbd/gC3uf4As1n/AOZXAIC2VgCA6lcAgO5XAIC2of4Atan+APJXAIC7Jf4AuiX+APZXAID6VwCAvxH+AL4t/gC9Lf4AvDH+AIIZAACjHf8AgGUAAIEZAACm5f4A/lcAgAJYAICl7f4AqmH+AKth/gCEZAEAviAAAK5p/gCvVf4ArHX+AK1p/gAKWACA4zT+AA5YAIDhfP0AhrAEAIcIAwASWACAFlgAgBpYAIAeWACAhCQDAIQkBAAiWACA70j+ACZYAIAqWACAs+kCAC5YAIC+RAQAvkAFADJYAIC2nQIAtZkCADZYAIC7iQIAur0CADpYAIA+WACAv1kDAL5RAwC9WQMAvJECAKkdAgCoFQIAqyUCAKolAgCtWQIArFUCAK9NAgCuUQIAvmQGAEJYAIBGWACASlgAgE5YAIBSWACAVlgAgFpYAIC5+QMAuPEDALtNAwC68QMAvUEDALxZAwC/cQMAvkEDALEJAgCwPQIAs8kDALIBAgC12QMAtNEDALfJAwC20QMA4ZABAF5YAIDj8AAAYlgAgGZYAICCPQAAgT0AAIA9AABqWACAblgAgHJYAIB6WACAflgAgIJYAIDvLAAAhlgAgKPpAwCKWACAhugEAIdgBQCOWACApp0DAKWZAwCSWACAq4kDAKq9AwCWWACAmlgAgK9ZAgCuUQIArVkCAKyRAwCeWACAolgAgKZYAICqWACArlgAgLJYAIC2WACA71gBAISgBADhVP8AulgAgOOEAQC+WACAwlgAgMZYAIDKWACAs9kBAM5YAICFzBkA0lgAgNZYAIC28QEAtfkBANpYAIC7pQEAutkBAN5YAIDiWACAv50BAL6dAQC9pQEAvK0BAKgBBgCpDQYAqhEGAKsRBgCsMQYArTEGAK4pBgCvJQYAdlgAgILJBwCBwQcAgPEHAOZYAIDqWACAhhwAAIf8AwC47QYAufUGALr9BgC79QYAvO0GAL1RBwC+VQcAv00HALBdBgCxIQYAsjkGALMxBgC0GQYAtRkGALbdBgC31QYAo5kGAO5YAIDyWACA9lgAgPpYAICmsQYApbkGAP5YAICr5QYAqpkGAAJZAIAGWQCAr90GAK7dBgCt5QYArO0GAApZAICz8QcADlkAgBJZAIC2gQcAFlkAgBpZAIC1mQcAuo0HALtlBwAeWQCAIlkAgL59BwC/ZQcAvH0HAL11BwCoLQYAqTUGAKo9BgCrMQYArFUGAK1FBgCuRQYAr3UGACZZAIAqWQCALlkAgDJZAIA2WQCAOlkAgD5ZAIBCWQCAuOkGALn1BgC6/QYAu/UGALztBgC9kQYAvpUGAL+NBgCwDQYAseUGALLtBgCz5QYAtP0GALXlBgC27QYAt+UGAKO1BgBGWQCASlkAgE5ZAIBSWQCA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nlsAgLshBwC6yQcAolsAgKZbAIC/KQcAviEHAL0pBwC8NQcAqlsAgKOBBwCuWwCAslsAgKaBBwC2WwCAulsAgKWRBwCqjQcAq2UHAL5bAIDCWwCArmUHAK9tBwCscQcArW0HAKgVAQCpgQEAqoEBAKuBAQCsgQEArYkBAK6xAQCvsQEAxlsAgMpbAIDOWwCA0lsAgNZbAIDaWwCA3lsAgOJbAIC4ZQAAuW0AALplAAC7fQAAvGUAAL1tAAC+ZQAAv90AALChAQCxrQEAsqUBALO5AQC0qQEAtZ0BALaVAQC3XQAA5lsAgIIdAACBHQAAgB0AAOpbAIDuWwCA8lsAgL5YAQCErAIA9lsAgIcIAQCGjAEA+lsAgKZaAID+WwCAAlwAgLNJAQAGXACAClwAgA5cAIASXACAtkkBALVJAQAWXACAuykBALolAQAaXACAHlwAgL8ZAQC+LQEAvS0BALwxAQC+2AMAIlwAgO/4BgAmXACAKlwAgC5cAIDv4AIAMlwAgOGUAQA2XACA43QCADpcAIDhmAUAPlwAgOMMBwBCXACARlwAgEpcAICjwQIAhIwDAKXBAgBOXACAUlwAgKbBAgBWXACAWlwAgKuhAgCqrQIAraUCAKy5AgCvkQIArqUCAKgxAwCpPQMAqjUDAKtJAwCsWQMArVkDAK5JAwCvQQMAgMUAAIEJAACCGQAAXlwAgGJcAIBqXACAh2wDAIYcHAC47QAAufEAALr1AAC7jQAAvJUAAL2BAAC+gQAAv70AALAJAwCxCQMAsu0AALPhAAC04QAAteEAALblAAC32QAAblwAgHJcAIB2XACAs7ECAHpcAIC13QIAttUCAH5cAICCXACAhlwAgLrBAgC7wQIAvDUBAL05AQC+KQEAvykBAKaNAgCKXACAjlwAgKWFAgCSXACAo+kCAJZcAICaXACArnEBAK9xAQCsbQEArWEBAKqZAgCrmQIAnlwAgKJcAICmXACA4YQGAKpcAIDjJAYArlwAgOGUAQCyXACA4ywAAL7oHQC2XACAulwAgO/IAACE/B0AvvAcAL5cAIDvSAcAwlwAgMZcAIDKXACAzlwAgIEdAACAHQAA0lwAgIIFAACGQBwAh8QcANpcAIDeXACA4lwAgOZcAIDqXACA7lwAgKi1HgCpBR8Aqg0fAKsFHwCsAR8ArQkfAK45HwCvOR8A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rmU+AK1xPgCsAT4A0mIAgNZiAIDaYgCA3mIAgOJiAIDmYgCA6mIAgO5iAICAOQAAgTkAAIIFAADyYgCAvrgBAIS4AQD6YgCA/mIAgKitAgCp1QIAqtUCAKstAwCsNQMArT0DAK41AwCvLQMAAmMAgAZjAIAKYwCADmMAgBJjAIAWYwCAGmMAgB5jAIC46QMAuekDALqJAwC7iQMAvJkDAL2ZAwC+iQMAv4kDALBVAwCxXQMAslUDALPpAwC0+QMAtfkDALbpAwC34QMAs10CACJjAICGKAQAh8wDACZjAIC2vQMAtb0DACpjAIC7mQMAupEDAC5jAIAyYwCAvz0DAL49AwC9PQMAvIEDAIUAFACjGQIANmMAgDpjAICm+QMAPmMAgEJjAICl+QMAqtUDAKvdAwBGYwCASmMAgK55AwCveQMArMUDAK15AwDjVD4A4dw/AOHQPgDjPD4ATmMAgO8cAABSYwCAVmMAgFpjAIDjwAAAXmMAgOHUAQDvYD4AYmMAgGpjAIDvRD8AgGEAAIFtAACCfQAAhAAFAIbwBACHnAUAvhAFAG5jAIByYwCAdmMAgHpjAIB+YwCAgmMAgIZjAICKYwCAjmMAgLiJPQC5iT0Aupk9ALuRPQC8uT0Avbk9AL7RPQC/0T0AsAU+ALENPgCyBT4Asx0+ALQFPgC1DT4AtgU+ALe5PQConT4Aqa0+AKqlPgCrvT4ArKU+AK2tPgCupT4Ar30+AISsBAC+rAQAkmMAgJZjAICaYwCAnmMAgKJjAICmYwCAqPkFAKn5BQCqKQYAqykGAKw5BgCtOQYArikGAK8pBgBmYwCAqmMAgK5jAICyYwCAtmMAgLpjAIC+YwCAwmMAgLiNBgC5kQYAupEGALulBgC8vQYAvUUHAL5BBwC/QQcAsFkGALFZBgCy7QYAs/0GALTtBgC13QYAttUGALe1BgCzoQYAxmMAgMpjAIDOYwCA0mMAgLa5BgC1sQYA2mMAgLudBgC6nQYA1mMAgPZiAIC/GQYAvikGAL0pBgC8OQYAglEAAKPlBgCAQQAAgUEAAKb9BgDeYwCA4mMAgKX1BgCq2QYAq9kGAIZIAACHbAAArm0GAK9dBgCsfQYArW0GAKg5BgCpWQYAqmkGAKtpBgCseQYArXkGAK5pBgCvaQYA5mMAgOpjAIDuYwCA8mMAgPZjAID6YwCA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uNEGALnZBgC64QYAu+EGALyRBgC9nQYAvpUGAL+JBgCwSQYAsUkGALJdBgCzVQYAtE0GALXxBgC28QYAt/EGALDhBwCx4QcAsgkHALMJBwC0GQcAtRkHALYJBwC3CQcAuDkHALkNBwC6GQcAuxkHALwJBwC9CQcAvn0HAL9xBwCCZgCAlmUAgIZmAICKZgCAjmYAgJJmAICWZgCAmmYAgKjxBwCpxQcAqsEHAKvdBwCsyQcArb0HAK6pBwCvoQcAsykGAJ5mAICiZgCApmYAgKpmAIC2XQYAtSEGAK5mAIC7RQYAukUGALJmAIC2ZgCAv70GAL69BgC9vQYAvL0GALpmAICjbQYAvmYAgMJmAICmGQYAxmYAgMpmAIClZQYAqgEGAKsBBgDOZgCA0mYAgK75BgCv+QYArPkGAK35BgCobQYAqbEBAKpJAQCrRQEArF0BAK1FAQCuTQEAr0UBANZmAICCHQAAgR0AAIAdAADaZgCA3mYAgOJmAIC+VAEAuIEAALmNAAC6hQAAu5kAALyJAAC9vQAAvrUAAL99AACwPQEAseEAALLhAACz4QAAtOEAALXpAAC20QAAt9EAALsFAwC62QIAhiwCAIcsAwC/DQMAvgUDAL0VAwC8FQMAs+ECAOpmAIDuZgCAhCwDAPJmAIC25QIAtfUCAPZmAICqnQIAq0EDAPpmAID+ZgCArkEDAK9JAwCsUQMArVEDAAJnAICjpQIABmcAgApnAICmoQIADmcAgBJnAIClsQIAqakAAKihAACrtQAAqr0AAK3dAACs3QAAr/EAAK79AAC+LBwAFmcAgBpnAIAeZwCAImcAgCZnAIAqZwCALmcAgLl9AAC4fQAAu80BALrNAQC93QEAvN0BAL/NAQC+zQEAsZUAALCJAACzTQAAspUAALVdAAC0XQAAt00AALZNAAAyZwCANmcAgDpnAIA+ZwCAQmcAgEZnAIBKZwCATmcAgIA5AACBOQAAggUAAFJnAIBaZwCAXmcAgIf4AgCGfB0A4bgEAL7IHADjQAYAYmcAgGZnAIBqZwCAbmcAgHJnAIB2ZwCAemcAgH5nAICCZwCAhmcAgIpnAIDvsAcAjmcAgJJnAICWZwCAmmcAgO/IAACeZwCAomcAgKZnAIDvQAYAqmcAgOH8BgCuZwCA4xwGALJnAIDhlAEAtmcAgONkBgCAEQAAgRkAAIIpAACz/QEAumcAgLWdAQC2lQEAvmcAgMJnAICEbB0AuoUBALuZAQC8iQEAvVEBAL5RAQC/UQEAozEeAFZnAIDGZwCAymcAgM5nAICmWR4ApVEeANJnAICrVR4AqkkeAIYIAwCHbAMAr50eAK6dHgCtnR4ArEUeANZnAICzCR8A2mcAgN5nAIC2CR8A4mcAgOZnAIC1CR8AugUfALsNHwDqZwCA7mcAgL4FHwC/CR8AvBUfAL0NHwCw5R8Ase0fALLlHwCz/R8AtOUfALXpHwC2GR8AtxkfALgpHwC5NR8Auj0fALs1HwC8ER8AvR0fAL4JHwC/BR8A8mcAgPZnAIDmZgCA+mcAgP5nAIACaACABmgAgApoAICo0R8AqdEfAKqlHwCrvR8ArKUfAK2tHwCupR8Ar50fAKNNHgAOaACAEmgAgBZoAIAaaACApk0eAKVNHgAeaACAq0keAKpBHgAiaACAJmgAgK9NHgCuQR4ArUkeAKxRHgCADQAAgRUAAIIdAAAqaACALmgAgDJoAICEtAEAvrQBAL/oAQA6aACAhkgHAIc0AACEvAYAPmgAgEJoAIC+tAYAqI0BAKmVAQCqlQEAq80BAKzZAQCt2QEArs0BAK/FAQBGaACASmgAgE5oAIBSaACAVmgAgFpoAIBeaACAYmgAgLgdAQC5wQAAusEAALvBAAC8wQAAvckAAL7xAAC/8QAAsIkBALGJAQCyKQEAsykBALQ9AQC1JQEAti0BALclAQC7bQIAum0CAGZoAIBqaACAv8ECAL7ZAgC93QIAvN0CALM9AgBuaACAcmgAgHZoAICE/AYAtnkCALVxAgB6aACAqikCAKspAgB+aACAgmgAgK6dAgCvhQIArJkCAK2ZAgCGaACAo3kCAIpoAICOaACApj0CAJJoAICWaACApTUCAIJtJwCDjSoAhqgFAIdsAwCGmS4Ah80vAIQRLgCFmS4AiiESAIspEgCaaACAnmgAgI6RFgCPHRYAjBESAI0RFgCScRoAk+UaAKJoAIDvlHYAlvEeAJflHgCUSRoAlRkeAJopAgCb4QIAqmgAgK5oAICyaACA4SASAJzxAgDjIBYAnyEfAJ7BHwCdmRsAnC0bAJuhGwCavRcAmTkXAJixFwCXiRMAlqkTAJWpEwCUdS4AkzkvAJIxLwCRsS8AkDUrAI+tJgDjeB8A0gAAAOFcHwCCmQEAtmgAgIDxAQCB8QEAvqgHALpoAIC+aACAwmgAgIS8BgDvLB8AxmgAgMpoAIDhpB4A48wAAON8HgDhvAEAzmgAgNJoAIDWaACAhJwGANpoAIC+bAYA3mgAgOJoAIDmaACA7xAAAO8EHgDqaACA7mgAgPJoAID2aACA+mgAgP5oAIACaQCABmkAgAppAICAPQAAgQkAAILJBwAOaQCAo/kDAKLxAwChMQMAoM0fALBJcQCxAXwAsgl8ALMhfQC0AXgAtRV4ADZoAICmaACAEmkAgL4oDgCGDAAAh4wDABZpAIAaaQCAHmkAgCJpAIAmaQCAoV0AAKJVAACjfQAApAEMAKUVDACm9QwApwEIAKghCACpxQgAqgF0AKsJdACsAXQArR11AK55cACveXAAqOUFAKnxBQCq8QUAqy0FAKw1BQCtPQUArjUFAK8tBQAqaQCALmkAgDJpAIA2aQCAOmkAgD5pAIBCaQCARmkAgLj9BgC5jQYAuoUGALutBgC8uQYAvbkGAL6tBgC/pQYAsFUFALFdBQCyVQUAs+UGALT9BgC10QYAttEGALfRBgCzeQQASmkAgE5pAIBSaQCAVmkAgLa9BAC1vQQAWmkAgLuZBAC6kQQAXmkAgGJpAIC/FQcAvjkHAL0xBwC8gQQAZmkAgKM9BABqaQCAbmkAgKb5BAByaQCAdmkAgKX5BACq1QQAq90EAHppAIB+aQCArn0HAK9RBwCsxQQArXUHAKhpBwCpaQcAqnkHAKvZBgCs9QYArf0GAK71BgCv5QYAgMkAAIHJAACCBQAAgmkAgIZwDwCHNAAAimkAgI5pAIC4fQYAuQUGALoNBgC7BQYAvB0GAL0FBgC+DQYAvwUGALCdBgCxdQYAsn0GALN1BgC0UQYAtV0GALZVBgC3TQYAs/EEAJJpAICWaQCAmmkAgJ5pAIC2fQUAtX0FAKJpAIC7sQUAulkFAKZpAICqaQCAv5kFAL6VBQC9oQUAvKkFAK5pAICjtQQAsmkAgLZpAICmOQUAumkAgL5pAIClOQUAqh0FAKv1BQDCaQCAxmkAgK7RBQCv3QUArO0FAK3lBQCpuQIAqLECAKvJAgCqsQIArTUCAKw1AgCvNQIArjUCAMppAIDOaQCA0mkAgNZpAIDaaQCA3mkAgOJpAIDmaQCAuekDALjZAwC7iQMAuuEDAL2dAwC8nQMAv4EDAL6JAwCxVQIAsFUCALNVAgCyVQIAtfkDALTxAwC36QMAtvEDALM9AwDqaQCA7mkAgPJpAID6aQCAtrEDALW5AwD+aQCAu5UDALqVAwCGiAwAh6ANAL85AgC+MQIAvYUDALyFAwACagCAo3kDAAZqAIAKagCApvUDAA5qAIASagCApf0DAKrRAwCr0QMAFmoAgBpqAICudQIAr30CAKzBAwCtwQMAgIUAAIGNAACChQAA79AGAOOwBwDj9AQA4QgHAOHsBADvOAYA7yAEAL6kDAAeagCAImoAgOGEAQAmagCA49wGACpqAIAuagCAhMANALPJAQAyagCAtdkBALbJAQA2agCAOmoAgD5qAIC6xQEAu60BALy5AQC9uQEAvq0BAL+lAQCwLQ4AsUUOALJBDgCzQQ4AtEUOALVNDgC2cQ4At3EOALiBDgC5gQ4AuoEOALuBDgC8gQ4AvYEOAL6BDgC/gQ4A9mkAgEJqAIBGagCASmoAgIZpAIBOagCAUmoAgFZqAICo2Q0AqdkNAKptDgCrZQ4ArH0OAK1lDgCuZQ4Ar1UOAKOFDgCCLQAAgRUAAIAdAABaagCApoUOAKWVDgBeagCAq+EOAKqJDgBiagCAZmoAgK/pDgCu4Q4ArfUOAKz1DgBqagCAs4UPAIZoAACHHAMAtoUPAG5qAIByagCAtZEPALqNDwC7SQ8AdmoAgHpqAIC+MQ8AvzEPALxJDwC9RQ8AqBEOAKkZDgCqSQ4Aq0UOAKxdDgCtQQ4ArkEOAK91DgB+agCAgmoAgIZqAICKagCAjmoAgJJqAICWagCAmmoAgLihDgC5oQ4Aug0BALsFAQC8HQEAvQEBAL4BAQC/AQEAsA0OALHJDgCy2Q4As9UOALSxDgC1sQ4AtqkOALehDgCjwQ4AnmoAgKJqAICmagCAqmoAgKbBDgCl1Q4ArmoAgKsNDgCqyQ4AsmoAgLZqAICvdQ4ArnUOAK0BDgCsDQ4AumoAgL5qAIDCagCAxmoAgIANAACBNQAAgj0AAMpqAIDOagCA0moAgISEAQC+hAEAhjAHAIf4AADaagCA3moAgKjBAgCp0QIAqtECAKvlAgCs/QIArTUDAK49AwCvNQMA4moAgOZqAIDqagCA7moAgPJqAID2agCA+moAgP5qAIC40QMAudkDALrhAwC74QMAvJEDAL2RAwC+kQMAv5EDALBNAwCxVQMAsl0DALNVAwC0TQMAtfEDALbxAwC38QMAu7EDALqpAwACawCAvoQDAL8VAwC+qQMAvaEDALypAwCzeQIABmsAgAprAIAOawCAEmsAgLaVAwC1VQIAFmsAgKrtAwCr9QMAGmsAgB5rAICu7QMAr1EDAKztAwCt5QMAImsAgKM9AgAmawCAKmsAgKbRAwAuawCAMmsAgKURAgA2awCAgiEAAIEVAACAFQAA7wQAAISUAgA6awCAPmsAgOPYAABCawCA4fgBAEprAIBOawCAUmsAgFZrAIBaawCAhmAFAIcIBQBeawCAs20BAGJrAIC1fQEAtnUBAGZrAIBqawCAbmsAgLpRAQC7UQEAvPkBAL3RAQC+0QEAv9EBAHJrAICjpQEAdmsAgHprAICmvQEAfmsAgIJrAICltQEAqpkBAKuZAQCGawCAimsAgK4ZAQCvGQEArDEBAK0ZAQCOawCA4fQOAJJrAIDjFA4A9AAAAOF8DACWawCA41AKAJprAICeawCAviAEAO8wDQCiawCApmsAgIQ0BADvrA4AsDkGALE5BgCygQYAs6kGALS5BgC1uQYAtqkGALehBgC46QYAuekGALrJBgC7xQYAvN0GAL3BBgC+wQYAvz0HAEZrAICCHQAAgR0AAIAdAACqawCArmsAgLJrAIDWagCAqJkFAKmZBQCqSQYAq0kGAKxZBgCtWQYArkkGAK9JBgCorQcAqbUHAKq9BwCrtQcArK0HAK3dBwCuyQcAr8EHALZrAIC6awCAhogDAIcQAwC+awCAwmsAgMZrAIDKawCAuG0HALkFBwC6AQcAuxUHALwxBwC9MQcAvikHAL8pBwCwgQcAsYEHALJpBwCzZQcAtH0HALVhBwC2YQcAt1UHALM1BgDOawCA0msAgNZrAIDaawCAtl0GALUlBgDeawCAu0UGALpFBgDiawCA5msAgL+lBgC+uQYAvbEGALy9BgDqawCAo3EGAO5rAIDyawCAphkGAPZrAID6awCApWEGAKoBBgCrAQYA/msAgAJsAICu/QYAr+EGAKz5BgCt9QYAqCUBAKk1AQCqPQEAqzUBAKwtAQCtkQAArpEAAK+RAAAGbACACmwAgA5sAIASbACAFmwAgIK9AwCBvQMAgL0DALiZAAC5rQAAuqUAALttAAC8dQAAvX0AAL51AAC/bQAAsPEAALH5AACywQAAs8EAALSxAAC1vQAAtrUAALepAAAabACAHmwAgCJsAICEgAIAvhwCACpsAICG+HwAh8wCAISsAwAubACAMmwAgDZsAIA6bACAPmwAgEJsAIBGbACAs/UCAEpsAIBObACAkgAAAFJsAIC2UQMAteUCAFZsAIC7fQMAunUDAFpsAIBebACAvzkDAL41AwC9VQMAvFUDAKM1AgBibACAZmwAgGpsAIBubACAppEDAKUlAgBybACAq70DAKq1AwB2bACAemwAgK/5AwCu9QMArZUDAKyVAwC+wAMAfmwAgIJsAICGbACAgA0AAIE1AACCPQAAimwAgI5sAICSbACAhsh8AIcAAwCabACAnmwAgKJsAICmbACAqmwAgK5sAICybACAtmwAgLpsAIC+bACAwmwAgO/0AwCE7HwA4ZQBAMZsAIDjMAMAymwAgM5sAIDSbACA1mwAgLNpAQDabACA3mwAgOJsAIDmbACAtmEBALVpAQDqbACAuykBALohAQDubACA8mwAgL8dAQC+HQEAvSUBALwtAQD2bACA+mwAgP5sAICjpQEAAm0AgKWlAQCmrQEAvlR8AIaAfACH7HwAqu0BAKvlAQCs4QEArekBAK7RAQCv0QEACm0AgOGcBgCEBH8A4yQGAOPUBgAObQCA4TAEABJtAIDvlAcAgnUAAIFhAACAaQAAFm0AgBptAIAebQCA7+wGALiNfgC5lX4AupV+ALulfgC8vX4AvdF+AL7RfgC/0X4AsGV+ALFtfgCyeX4As3F+ALRZfgC1WX4Atr1+ALe1fgCoVX4AqWF+AKphfgCrYX4ArGF+AK1hfgCuYX4Ar2F+ACJtAICWbACAJmwAgCZtAIAGbQCAKm0AgC5tAIAybQCAqHF+AKlxfgCqcX4Aq3F+AKyRfwCtkX8ArpF/AK+RfwA2bQCAOm0AgD5tAIBCbQCARm0AgEptAIBObQCAUm0AgLiFfwC5jX8AuoV/ALudfwC8jX8Avb1/AL61fwC/XX8AsPF/ALHxfwCy8X8As8V/ALTBfwC1wX8AtsF/ALfBfwCz+X8AVm0AgFptAIBebQCAYm0AgLYRfgC1GX4AZm0AgLs1fgC6NX4Aam0AgG5tAIC/BX4AvgV+AL0RfgC8JX4AghUAAKO9fwCAYQAAgWEAAKZVfgBybQCAvpABAKVdfgCqcX4Aq3F+AHZtAIB6bQCArkF+AK9BfgCsYX4ArVV+AKhBfgCpUX4AqlV+AKt9fgCsZX4ArW1+AK75AQCv8QEAhgAAAIc0AQB+bQCAgm0AgIZtAICKbQCAjm0AgJJtAIC4dQEAuX0BALp1AQC7yQAAvNkAAL3ZAAC+yQAAv8EAALCVAQCxnQEAspUBALNNAQC0VQEAtV0BALZVAQC3TQEAs919AJZtAICabQCAnm0AgKJtAIC27X0Ate19AKZtAIC7WQIAulECAKptAICubQCAv5kCAL6RAgC9mQIAvEECALJtAICjmX0Atm0AgLptAICmqX0Avm0AgMJtAIClqX0AqhUCAKsdAgDGbQCAym0AgK7VAgCv3QIArAUCAK3dAgDObQCA0m0AgNZtAIDabQCAgB0AAIEJAACCOQAA3m0AgOJtAIC+AAQA6m0AgO5tAIDybQCA9m0AgPptAID+bQCAhIwDAAJuAICHCAMAhuwEAAZuAIDviAIACm4AgA5uAICEbAQA4zQCABJuAIDhVAEAFm4AgBpuAIAebgCAIm4AgKhtAgCprQIAqqUCAKu9AgCspQIAra0CAK6lAgCvGQEAvqwEACZuAIAqbgCALm4AgDJuAIA2bgCAOm4AgD5uAIC4DQEAuREBALoRAQC7JQEAvD0BAL3VAQC+3QEAv9UBALBpAQCxaQEAsnkBALNxAQC0WQEAtVkBALY5AQC3NQEAsy0CAEJuAIBGbgCASm4AgE5uAIC2LQIAtS0CAFJuAIC7rQEAuq0BAFpuAIBebgCAv50BAL6dAQC9pQEAvK0BAIBNAACBVQAAglUAAO9sAABibgCA7+x/AO+8fgBmbgCA4RB/AOPUfwDj2H4A4ex/AGpuAIDhTH4Abm4AgOMkfgDmbQCAVm4AgKsFBgCqBQYArQ0GAKwFBgCvNQYArjUGAIYAAwCHKAMAo4UFAHJuAIClhQUAdm4AgHpuAICmhQUAs/EGAH5uAICCbgCAhm4AgIpuAIC26QYAteEGAI5uAIC7vQYAur0GAJJuAICWbgCAv4kGAL6BBgC9iQYAvJUGAKgpBgCpKQYAqjkGAKs5BgCsKQYArSkGAK5dBgCvTQYAmm4AgJ5uAICibgCApm4AgKpuAICubgCAsm4AgLZuAIC46QcAuekHALr5BwC7+QcAvOkHAL3pBwC+XQcAv1UHALA5BgCxOQYAsgEGALMdBgC0BQYAtQ0GALYFBgC32QcAo7EHAIItAACBFQAAgB0AALpuAICmqQcApaEHAL5uAICr/QcAqv0HAMJuAICEpAIAr8kHAK7BBwCtyQcArNUHAL7MAQCzlQYAxm4AgMpuAIC2qQYAzm4AgNJuAIC1rQYAulkBALshAQCGyAAAhwwBAL4hAQC/KQEAvDEBAL0xAQCoKQYAqSkGAKpZBgCrUQYArGEGAK1tBgCutQEAr6kBAITgAQDWbgCA2m4AgN5uAIDibgCA5m4AgOpuAIDubgCAuGEBALlhAQC6YQEAu2EBALxhAQC9YQEAvmEBAL9hAQCw2QEAsaEBALKhAQCzoQEAtKEBALWpAQC2kQEAt5EBAKPRBQDybgCA9m4AgPpuAID+bgCApu0FAKXpBQACbwCAq2UCAKodAgAGbwCACm8AgK9tAgCuZQIArXUCAKx1AgAObwCAEm8AgBZvAIAabwCAHm8AgCJvAIAmbwCAKm8AgIA9AACBCQAAghkAAC5vAIAybwCAOm8AgL48AwA+bwCAhgAMAIcUAwBCbwCAs9UDAEZvAIC1PQMAtjUDAEpvAIBObwCAv4wKALoRAwC7EQMAvLUAAL29AAC+tQAAv60AAFJvAIDjdAEAVm8AgOG8AQBabwCAXm8AgGJvAIBmbwCAam8AgG5vAIBybwCAdm8AgHpvAIDvdAIAfm8AgIJvAICoTQIAqVECAKpRAgCrqQIArLkCAK25AgCuqQIAr6kCAIRsDQCGbwCAim8AgI5vAICSbwCAlm8AgJpvAIC+dA0AuG0BALkFAQC6DQEAuwUBALwdAQC9BQEAvg0BAL8FAQCw2QIAsdkCALJtAQCzZQEAtH0BALVlAQC2ZQEAt1UBAOG4AQDhUAcA47QAAON8BwCAqQAAgQkAAII5AACebwCAom8AgKpvAICubwCAsm8AgO4AAAC2bwCA7wAAAO9kBgCGYAwAh+QMAKORAgC6bwCApXkCAL5vAIDCbwCApnECAMZvAIDKbwCAq1UCAKpVAgCt+QEArPEBAK/pAQCu8QEApm8AgDZvAIDObwCA0m8AgNZvAIDabwCA3m8AgOJvAICoVQ4AqVkOAKqhDgCrvQ4ArK0OAK2VDgCu+Q4Ar/UOALCRDgCxkQ4AspEOALORDgC0sQ4AtbEOALaxDgC3sQ4AuJEOALmdDgC6lQ4Au0kPALxZDwC9WQ8AvkkPAL9JDwCzCQ4A5m8AgOpvAIDubwCA8m8AgLY1DgC1BQ4A9m8AgLt1DgC6dQ4A+m8AgP5vAIC/VQ4AvlUOAL1lDgC8ZQ4AAnAAgKNNDgAGcACACnAAgKZxDgAOcACAEnAAgKVBDgCqMQ4AqzEOAISkAwC+pAMArhEOAK8RDgCsIQ4ArSEOAKilDgCprQ4AqqUOAKu5DgCs3Q4ArcEOAK7BDgCv/Q4AgO0BAIHxAQCC8QEAFnAAgIaQAQCHtAEAGnAAgB5wAIC4yQEAuckBALrZAQC70QEAvPkBAL35AQC+mQEAv5UBALCFDgCxbQEAsmUBALN9AQC0ZQEAtW0BALZlAQC3+QEAsy0OACJwAIAmcACAKnAAgC5wAIC2QQ4AtVUOADJwAIC7qQEAukEOADZwAIA6cACAv6kBAL6hAQC9qQEAvLEBAD5wAICjaQ4AQnAAgEZwAICmBQ4ASnAAgE5wAIClEQ4AqgUOAKvtAQBScACAVnAAgK7lAQCv7QEArPUBAK3tAQCoOQMAqTkDAKqNAwCrhQMArJ0DAK2FAwCuhQMAr7UDAFpwAIBecACAYnAAgGZwAIBqcACAbnAAgHJwAIB2cACAuGEAALlhAAC6YQAAu2EAALxhAAC9YQAAvmEAAL9hAACwzQMAsaUDALKhAwCzoQMAtKUDALWtAwC2kQMAt5EDAIANAACBEQAAghEAAHpwAIDv9AIAfnAAgIJwAIC+HAMA4xQCAISIAgDhgAEAinAAgI5wAICScACAh8gDAIY8BAC7AQMAumkDAJZwAICacACAvwkDAL4BAwC9FQMAvBUDALNlAwCecACAonAAgKZwAICqcACAtmUDALV1AwCucACAsnAAgLZwAIC6cACAo4kCAL5wAIClmQIApokCAMJwAICELAIAxnAAgKqFAgCr7QIArPkCAK35AgCu7QIAr+UCAMpwAIDOcACAvkQFAIRMBQDScACA1nAAgNpwAIDecACA4nAAgOZwAIDqcACA7nAAgIAZAACBGQAAggUAAPJwAIDhGA8A4VwOAOO4DgDjdAEA+nAAgP5wAIACcQCABnEAgIYABACHZAUACnEAgA5xAIAScQCAFnEAgO98DgDvqAEAs3UBABpxAIAecQCAInEAgCZxAIC2MQEAtRUBACpxAIC7HQEAuhUBAC5xAIAycQCAv+EAAL79AAC9/QAAvP0AAPZwAIA2cQCAOnEAgD5xAICGcACAQnEAgEZxAIBKcQCAqI0GAKmVBgCqnQYAq+UGAKz9BgCt0QYArtEGAK/RBgCwsQYAsbkGALJJBwCzSQcAtFkHALVFBwC2RQcAt3kHALghBwC5IQcAujkHALs5BwC8KQcAvSkHAL4ZBwC/GQcAozUGAE5xAIBScQCAVnEAgFpxAICmcQYApVUGAF5xAICrXQYAqlUGAGJxAIC+oAMAr6EHAK69BwCtvQcArL0HAIBRAACBWQAAgmEAALNVBwCF9AAAtX0HALZ1BwBmcQCAhgAcAIfkAQC6LQcAuyUHALw9BwC9JQcAviUHAL8VBwCokQYAqZEGAKqRBgCrkQYArLkGAK25BgCuqQYAr6kGAGpxAIBucQCAcnEAgHZxAICiIQEAozUBAKA5BQChEQQAuEkBALlJAQC6XQEAu1UBALxNAQC90QEAvtEBAL/RAQCwpQYAsa0GALKlBgCzvQYAtK0GALWdBgC2lQYAt3kBAKMZBgCPnXkAenEAgH5xAICCcQCApjkGAKUxBgCGcQCAq2kGAKphBgCKcQCAjnEAgK9ZBgCuaQYArWkGAKxxBgCeiQgAn8EFAJzJCQCdyQkAmqENAJu9DACYsQ0AmbkNAJahcQCXRXEAlEV1AJWxcQCSoXUAk7V1AJDleQCRzXkAil1yAItFcgCScQCAvoAcAI51DgCPZQ4AjLlyAI11DgCCOXoAgzl6AJZxAICacQCAhnF2AIeZdgCECXoAhW12AJptBwCbVQIAnnEAgKJxAICmcQCA4ZAAAJxZAgDjCBoAkgkPAJNlCgCqcQCA7zgWAJZ1BgCXdQYAlH0KAJU1CwCpjRYAqIUWAKsBEACqMRYArXESAKy1EgCvuS4ArgEsAKF9AgCucQCAo6EeAKKpHgClsRoApPUfAKflGwCmsRoAhMwDAIRMHACycQCAtnEAgLpxAIC+cQCAwnEAgMZxAICxASgAsNkuALONKgCy6SoAtfUmALQBJACEcB0AynEAgID9AQCBFQAAgh0AAL6AHADOcQCA0nEAgIe4AgCGPB0A2nEAgN5xAIDicQCA5nEAgOpxAIDucQCA8nEAgPZxAID6cQCA/nEAgAJyAIAGcgCA44ADAApyAIDhoAEADnIAgO+UAwAScgCAFnIAgBpyAIAecgCAInIAgCZyAIAqcgCALnIAgOE8BgAycgCA49AGADZyAIDhMAcAOnIAgOOsBgCAOQAAgRUAAIIdAADvHAYAPnIAgEJyAIC+uB8A7+gBALPpAgBKcgCAh8QcAIbsHABOcgCAtlkCALVRAgBScgCAu00CALpNAgBWcgCAWnIAgL+5AQC+2QEAvdEBALz1AQCjKR0A1nEAgEZyAIBecgCAYnIAgKaZHQClkR0AZnIAgKuNHQCqjR0AanIAgG5yAICveR4ArhkeAK0RHgCsNR4AcnIAgLNtHwB2cgCAenIAgLZlHwB+cgCAgnIAgLVtHwC6IR8AuyEfAIZyAICKcgCAviUfAL8pHwC8MR8AvTEfAKihHwCpoR8AqqEfAKuhHwCsoR8AraEfAK6hHwCvoR8AjnIAgJJyAICWcgCAmnIAgJ5yAICicgCApnIAgKpyAIC4rR8AubUfALq9HwC7tR8AvK0fAL1VHwC+UR8Av00fALChHwCxoR8AsqEfALOhHwC0pR8AtakfALadHwC3lR8AoykeAIIZAACBGQAAgLEBAK5yAICmIR4ApSkeALJyAICrZR4AqmUeAIaIAACH/AEAr20eAK5hHgCtdR4ArHUeALZyAICzmR4AunIAgL5yAIC2XQEAwnIAgMZyAIC1sR4AukkBALtJAQDKcgCAznIAgL49AQC/IQEAvDkBAL01AQCoRR4AqVUeAKpVHgCrZR4ArH0eAK2ZAQCuiQEAr4EBAISsAADScgCA1nIAgNpyAIDecgCA4nIAgOZyAIDqcgCAuK0BALllAQC6bQEAu2UBALx9AQC9ZQEAvm0BAL9lAQCwyQEAsckBALKpAQCzpQEAtL0BALWhAQC2oQEAt5UBALhpHAC5oRwAusEcALvBHAC8wRwAvcEcAL7BHAC/wRwAsIkfALGJHwCyIRwAswUcALQdHAC1fRwAtnUcALdtHACoYR8AqWEfAKphHwCrYR8ArNkfAK3ZHwCuyR8Ar8EfAO5yAIDycgCA9nIAgPpyAID+cgCAAnMAgAZzAIAKcwCADnMAgBJzAIC+AAQAo1EdABZzAICleR0AppUCABpzAIAecwCAInMAgKqBAgCrgQIArPECAK39AgCu9QIAr+kCACpzAIDh9AEALnMAgON8AQCATQAAgXUAAIJ9AAAycwCAhsAEAIekBAA2cwCAOnMAgD5zAIBCcwCARnMAgO+MAgCoSQIAqUkCAKpdAgCrVQIArHkCAK15AgCuvQIAr7UCAISgBQBKcwCATnMAgFJzAIC+vAQAVnMAgFpzAIBecwCAuC0BALk1AQC6PQEAuzUBALwtAQC91QEAvt0BAL/NAQCwzQIAsdUCALLdAgCz1QIAtM0CALUVAQC2HQEAtxUBAOGEHgDjbB8A41wfAOFYHgBicwCAZnMAgGpzAIBucwCAcnMAgHZzAIB6cwCAfnMAgOkAAADv9B4A70weAIJzAICzlQIAhnMAgIpzAICOcwCAknMAgLa5AgC1sQIAmnMAgLtRAgC6SQIAhsgEAIesBAC/kQEAvkkCAL1BAgC8SQIAJnMAgKNRBQCecwCAlnMAgKZ9BQCicwCApnMAgKV1BQCqjQUAq5UFAKpzAICucwCAro0FAK9VBgCsjQUArYUFAICJBwCBiQcAgpkHALORBgCycwCAtbkGALapBgC2cwCAunMAgL5zAIC6TQcAu0UHALxdBwC9QQcAvkEHAL9BBwCoQQYAqU0GAKpVBgCrZQYArH0GAK1lBgCubQYAr2UGAMJzAIDGcwCAynMAgM5zAIDScwCA1nMAgNpzAIDecwCAuFkHALlZBwC6aQcAu2kHALx5BwC9eQcAvmUHAL8ZBwCwxQcAsc0HALLFBwCz2QcAtMkHALXJBwC2aQcAt2kHAKPdBwDicwCA5nMAgOpzAIDucwCApuUHAKX1BwDycwCAqwkGAKoBBgD2cwCA+nMAgK8NBgCuDQYArQ0GAKwRBgCAbQAAgQkAAIIZAAD+cwCAAnQAgISYAQC+kAEABnQAgIbAAACH5AEACnQAgA50AIASdACAFnQAgBp0AIAedACAqF0GAKmNAQCqnQEAq5UBAKy5AQCtuQEArskBAK/BAQCEoAAAInQAgCZ0AIAqdACALnQAgDJ0AIA2dACAOnQAgLh5AQC5eQEAus0AALvFAAC83QAAvcUAAL7FAAC/9QAAsIEBALGBAQCySQEAs0kBALRZAQC1WQEAtkkBALdJAQCzFQIAPnQAgEJ0AIBGdACASnQAgLY5AgC1MQIATnQAgLtFAgC6RQIAUnQAgFZ0AIC/nQIAvp0CAL2dAgC8nQIAhXw+AKNRAgBadACAXnQAgKZ9AgBidACAZnQAgKV1AgCqAQIAqwECAGp0AIBudACArtkCAK/ZAgCs2QIArdkCAIDpAACB6QAAggUAAHJ0AIC+AAwAenQAgIeoAwCGvAwAfnQAgIJ0AICGdACAinQAgI50AICSdACAlnQAgJp0AICedACAonQAgKZ0AICqdACA42ABAK50AIDhoAEAsnQAgO+IAgC2dACAunQAgL50AIDCdACAxnQAgMp0AIDOdACAqGkCAKlpAgCqeQIAq3kCAKxpAgCtaQIArr0CAK+1AgC+rAwA0nQAgNZ0AIDadACAgB0AAIEJAACCqQAA3nQAgLhRAQC5WQEAumEBALthAQC8GQEAvRkBAL4NAQC/BQEAsM0CALHVAgCy3QIAs9UCALTNAgC1cQEAtnEBALdxAQDjxAAA4XwHAOF4BgDjvAYA4nQAgIQYDQCGuAwAhzwNAL4sDwDqdACA7nQAgPJ0AIDvEAAA9nQAgPp0AIDvdAYA/nQAgAJ1AIAGdQCAs70CAAp1AIC1rQIAtqUCAA51AIASdQCAFnUAgLpFAgC7XQIAvEUCAL1NAgC+RQIAv/kBAHZ0AIClfQ0ApnUNAOZ0AIAadQCAHnUAgCJ1AICjbQ0ArJUNAK2dDQCulQ0ArykOACZ1AIAqdQCAqpUNAKuNDQCz5Q4ALnUAgDJ1AIA2dQCAOnUAgLblDgC19Q4APnUAgLuhDgC62Q4AQnUAgEZ1AIC/pQ4AvrkOAL2xDgC8uQ4AqBUOAKklDgCqLQ4AqyUOAKw9DgCtJQ4Ari0OAK8lDgCADQAAgRUAAIIdAABKdQCATnUAgFJ1AICEMAMAVnUAgLgpDgC5KQ4AujkOALs5DgC8KQ4AvSkOAL79DwC/9Q8AsF0OALElDgCyLQ4AsyUOALQ9DgC1IQ4AtiUOALcZDgCjpQ8AWnUAgIYoAQCHTAEAXnUAgKalDwCltQ8AYnUAgKvhDwCqmQ8AZnUAgGp1AICv5Q8ArvkPAK3xDwCs+Q8AbnUAgLPpDgBydQCAdnUAgLaRDgB6dQCAfnUAgLXlDgC6sQ4Au7kOAIJ1AICGdQCAvmEBAL9hAQC8mQ4AvZkOAKglDgCpLQ4AqiUOAKs5DgCsKQ4ArVUOAK5dDgCvVQ4AinUAgI51AICSdQCAlnUAgJp1AICedQCAonUAgKZ1AIC49QEAuYEBALqBAQC7gQEAvIEBAL2JAQC+sQEAv7EBALAxDgCxOQ4AsgkOALMJDgC04QEAteEBALbhAQC3zQEAo60NAKp1AICudQCAsnUAgLZ1AICm1Q0ApaENALp1AICr/Q0AqvUNAL51AIDCdQCAryUCAK4lAgCt3Q0ArN0NAIBdAACBbQAAgmUAALNRAwC+nAMAtXkDALYZAwDKdQCAhOACAM51AIC6PQMAuzUDALwZAwC9GQMAvtkDAL/ZAwCohQMAqZUDAKqVAwCrpQMArL0DAK3VAwCu0QMAr9EDAIYABACHNAMAv6AzANJ1AIDWdQCA2nUAgN51AIDidQCAuHEDALlxAwC6cQMAu3EDALzVAAC93QAAvtUAAL/NAACwtQMAsb0DALKBAwCzgQMAtFEDALVRAwC2UQMAt1EDAO+oAwDmdQCA6nUAgO51AICEHAIA8nUAgPZ1AID6dQCAviwFAP51AIACdgCABnYAgONAAwAKdgCA4SgAAA52AICjXQIAEnYAgBZ2AIAadgCAHnYAgKYVAgCldQIAInYAgKs5AgCqMQIAJnYAgCp2AICv1QIArtUCAK0VAgCsFQIA4ygBAOEADwDhCA4A4wgOAID9AACBCQAAgjkAAC52AIAydgCAOnYAgD52AIBCdgCA7+gOAEZ2AIBKdgCA72QOALNtAQBOdgCAhugEAIcMBQBSdgCAtm0BALVtAQBWdgCAu+0AALrtAABadgCAXnYAgL/VAAC+6QAAveEAALzpAACoXQYAqWEGAKqlBgCrvQYArKUGAK2tBgCupQYArxkHADZ2AIBidgCAZnYAgGp2AIBudgCAcnYAgHZ2AIB6dgCAuHUHALl5BwC6DQcAuwUHALwdBwC9BQcAvgUHAL81BwCwaQcAsWkHALJ9BwCzdQcAtG0HALVRBwC2UQcAt1EHAKMtBgB+dgCAgnYAgIZ2AICKdgCApi0GAKUtBgCOdgCAq60HAKqtBwCSdgCAlnYAgK+VBwCuqQcAraEHAKypBwCADQAAgRUAAIIdAACadgCAnnYAgKJ2AICEVAMAvlwAAKZ2AICqdgCAhugAAIdMAwCudgCAsnYAgLZ2AIC6dgCAvnYAgOMEBADCdgCA4bQFAMZ2AIDKdgCAznYAgNJ2AIDWdgCA2nYAgN52AIDidgCA5nYAgO/sBADqdgCA7nYAgLPtBgDydgCA9nYAgPp2AID+dgCAtpEGALXhBgACdwCAu40GALqNBgAGdwCACncAgL9BAQC+WQEAvVEBALxZAQCoJQYAqS0GAKolBgCrOQYArCkGAK1RBgCuSQYAr0EGAIDNAACBCQAAghkAAA53AIASdwCAhCwBAL40AAAadwCAuP0BALlBAQC6QQEAu0EBALxBAQC9SQEAvnEBAL9xAQCwCQYAsQkGALLNAQCzxQEAtN0BALXFAQC2zQEAt8UBAIagPACHRAMAHncAgKOhBQAidwCApa0FAKbdBQAmdwCAKncAgL4oPACqwQUAq8EFAKwVAgCtHQIArhUCAK8NAgC2QQMALncAgDJ3AIC1sQIANncAgLOhAgA6dwCAPncAgL5FAwC/TQMAvHUDAL1NAwC6ZQMAu20DAEJ3AIBGdwCASncAgE53AIDGdQCAUncAgFZ3AIBadwCAXncAgGJ3AICoRQIAqVUCAKpdAgCrVQIArE0CAK21AwCusQMAr60DALDVAwCx3QMAstUDALPtAwC09QMAtf0DALb1AwC37QMAuNkDALnZAwC6rQMAu6UDALy9AwC9pQMAvqUDAL+VAwCj9QMAZncAgGp3AIBudwCAcncAgKYVAgCl5QMAdncAgKs5AgCqMQIAencAgH53AICvGQIArhECAK0ZAgCsIQIAgGkAAIFpAACCBQAAgncAgIp3AICOdwCAkncAgO8cAACEbAIA4ZQBAJZ3AIDjyAAAmncAgJ53AICGWDwAh1A9AKJ3AICmdwCAqncAgISEPQCudwCAsncAgLZ3AIDvuAEAvmw8AOF0BgC6dwCA42QBAL53AIDCdwCAxncAgMp3AICz0QEAzncAgNJ3AIDWdwCA2ncAgLaRAQC1+QEA3ncAgLu9AQC6vQEA4ncAgOZ3AIC/dQEAvnUBAL2FAQC8hQEAqL09AKkNPgCqGT4AqxE+AKwxPgCtUT4ArlE+AK9NPgCGdwCAgh0AAIEdAACAHQAA6ncAgO53AIDydwCA9ncAgLjVPgC53T4AutU+ALtJPwC8WT8AvVk/AL5JPwC/QT8AsDk+ALE5PgCyET4AsxE+ALTxPgC18T4AtvU+ALftPgCjkT4A+ncAgIYoAACHwAMA/ncAgKbRPgCluT4AAngAgKv9PgCq/T4ABngAgAp4AICvNT4ArjU+AK3FPgCsxT4ADngAgLOdPwASeACAFngAgLalPwAaeACAHngAgLWtPwC6aT8Au3U/ACJ4AIAmeACAvlk/AL9FPwC8bT8A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IoUAgOH8AQBWgwCAJoUAgO/IBgAqhQCALoUAgDKFAICzjQMANoUAgLWNAwA6hQCAPoUAgLa1AwBChQCARoUAgLtBAwC6SQMAvUEDALxZAwC/QQMAvkkDAKNFDACmhACAFoUAgEqFAIBOhQCApn0MAKVFDABShQCAq4kMAKqBDABWhQCAWoUAgK+JDACugQwArYkMAKyRDACAFQ8AgR0PAIIhDwCzIQ4AXoUAgLUhDgC2JQ4AYoUAgGaFAIBqhQCAusEOALvBDgC8wQ4AvcEOAL7BDgC/wQ4AqK0OAKntDgCq5Q4Aq/0OAKzlDgCt6Q4ArjkOAK85DgBuhQCAcoUAgHaFAIB6hQCAgB0AAIEJAACCvQEAfoUAgLjNDwC51Q8AutUPALvlDwC8/Q8AvZUPAL6RDwC/kQ8AsEkOALFJDgCyWQ4As1kOALRJDgC1SQ4Atv0PALf1DwCjbQ8AgoUAgL6EAQCKhQCAjoUAgKZpDwClbQ8AkoUAgKuNDwCqjQ8AhogAAIdsAQCvjQ8Aro0PAK2NDwCsjQ8AloUAgLPtDgCahQCAnoUAgLaRDgCihQCApoUAgLXhDgC6tQ4Au70OAKqFAICuhQCAvn0BAL9lAQC8mQ4AvZkOAKgRDgCpJQ4AqiEOAKs5DgCsLQ4ArVUOAK5dDgCvUQ4AhKgAALKFAIC2hQCAuoUAgL6FAIDChQCAxoUAgMqFAIC47QEAuZUBALqVAQC7rQEAvLUBAL11AQC+fQEAv3UBALA1DgCxPQ4AsgkOALMJDgC0/QEAteUBALblAQC31QEAo6kNAM6FAIDShQCA1oUAgNqFAICm1Q0ApaUNAN6FAICr+Q0AqvENAOKFAIDmhQCAryECAK45AgCt3Q0ArN0NAIANAACBFQAAgh0AAOqFAIDuhQCA8oUAgIeQAwCGfAQAvuwEAPqFAID+hQCAAoYAgAaGAIAKhgCADoYAgBKGAICyLQ4AszUOALAtDgCxJQ4Ati0OALedDwC0LQ4AtSUOALq9DwC7jQ8AuKUPALm9DwC+LQ8AvxUPALyVDwC9JQ8AFoYAgBqGAIAehgCAIoYAgCaGAIAqhgCALoYAgDKGAICqpQ4Aq7UOAKjFDgCp3Q4Arp0OAK9VDgCspQ4ArZUOAKgNAgCpFQIAqhUCAKtNAgCsWQIArVkCAK5NAgCvRQIAhKgFADaGAIA6hgCA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mogAgJ6IAIC+cAMAgGkAAIFpAACCeQAAhAAEAIbwBACHdAMAoogAgO8MHwCmiACA4aweAKqIAIDj8B4ArogAgLKIAIC2iACAuogAgL6IAIDCiACAxogAgMqIAIDvVAIAzogAgNKIAIDWiACA46QCANqIAIDhgAEA3ogAgOKIAIDmiACA6ogAgO6IAICzRQMA8ogAgPaIAID6iACA/ogAgLZFAwC1VQMAAokAgLshAwC6SQMAvqAEAAqJAIC/KQMAviEDAL01AwC8OQMAqDkCAKk5AgCqjQIAq4UCAKydAgCthQIAroUCAK+1AgCA7QEAgfUBAIL1AQAOiQCAhpAEAIcEBQASiQCAFokAgLhFAQC5TQEAukUBALtdAQC8SQEAvUkBAL55AQC/eQEAsM0CALGlAgCyrQIAs6ECALSlAgC1rQIAtp0CALd9AQAaiQCAHokAgCKJAIAmiQCAKokAgC6JAIAyiQCA74gBAITsBADhVB4ANokAgONUAQA6iQCAPokAgEKJAIBGiQCAo0UCAEqJAIBOiQCAUokAgFaJAICmRQIApVUCAFqJAICrIQIAqkkCAF6JAIBiiQCArykCAK4hAgCtNQIArDkCAKg1BgCpPQYAqlEGAKttBgCseQYArWUGAK5tBgCvZQYABokAgGaJAIBqiQCAbokAgIAZAACBGQAAggUAAHKJAIC45QYAuekGALr5BgC7+QYAvOkGAL3pBgC+nQYAv5UGALAdBgCx5QYAsu0GALPlBgC0/QYAteEGALbhBgC34QYAs9kGAL7QAwB2iQCAeokAgH6JAIC25QYAtfEGAIKJAIC7IQYAutkGAIaYAACHeAMAvyUGAL45BgC9MQYAvDkGAIaJAICjnQYAiokAgI6JAICmoQYAkokAgJaJAICltQYAqp0GAKtlBgCaiQCAnokAgK59BgCvYQYArH0GAK11BgCo7QcAqSkGAKoxBgCrMQYArJEGAK2RBgCukQYAr5EGAKKJAICmiQCAqokAgK6JAICyiQCAtokAgLqJAIC+iQCAuIUGALmNBgC6hQYAu50GALyNBgC9vQYAvrUGAL95AQCw8QYAsfEGALLxBgCzxQYAtMEGALXBBgC2wQYAt8EGALO5BgDCiQCAxokAgMqJAIDOiQCAthEGALUZBgDSiQCAuzUGALo1BgDWiQCA2okAgL8FBgC+BQYAvREGALwlBgClQQYA3okAgOKJAICmSQYAgRUAAIB5AACj4QYAghUAAK1JBgCsfQYAr10GAK5dBgCENAEAlogAgKttBgCqbQYAvswDAOqJAICzlQIA7okAgLXZAgDyiQCA9okAgLbRAgCGgAwAhzgDALvFAgC6xQIAvRUDALwVAwC/FQMAvhUDAPqJAID+iQCA71gGAIRAAwACigCABooAgAqKAIAOigCAEooAgBaKAIAaigCAHooAgOE4BgAiigCA4yQGAL5wDACsSQIArUkCAK5dAgCvVQIAqB0CAKkFAgCqBQIAq10CAISoDAAmigCAKooAgC6KAIC+vA0AMooAgDaKAIA6igCAvE0DAL1VAwC+VQMAv2UDALjpAwC56QMAul0DALtVAwC0yQMAtckDALbZAwC32QMAsBkCALEZAgCy2QMAs9kDAD6KAIDj5AAAQooAgOG8AQBGigCAgj0AAIE9AACAPQAASooAgE6KAIBSigCAWooAgF6KAIDvzAMAYooAgGaKAICj3QMAaooAgIboDACHYA0AbooAgKaZAwClkQMAcooAgKuNAwCqjQMAdooAgHqKAICvXQIArl0CAK1dAgCsXQIAfooAgIKKAICGigCAiooAgI6KAICSigCAlooAgO/gAQCEvAwA4YwGAJqKAIDjHAYAnooAgKKKAICmigCAqooAgLPVAQCuigCAsooAgLaKAIC6igCAtpEBALWZAQC+igCAu70BALq9AQDCigCAyooAgL+dAQC+nQEAvZ0BALydAQCoBQ4AqQkOAKodDgCrFQ4ArFEOAK1RDgCuSQ4Ar0kOAFaKAICCzQ8AgfUPAID9DwDGigCAzooAgIYcAACHsAMAuOkOALnpDgC6/Q4Au/UOALztDgC9VQ8AvlEPAL9NDwCwOQ4AsTkOALIJDgCzCQ4AtBkOALUZDgC2DQ4At9kOAKOVDgDSigCA1ooAgNqKAIDeigCAptEOAKXZDgDiigCAq/0OAKr9DgDmigCA6ooAgK/dDgCu3Q4Ard0OAKzdDgDuigCAs/0PAPKKAID2igCAtoEPAPqKAID+igCAtZkPALqNDwC7ZQ8AAosAgAaLAIC+fQ8Av2UPALx9DwC9dQ8AqC0OAKk1DgCqMQ4AqzEOAKxVDgCtRQ4ArkUOAK91DgAKiwCADosAgBKLAIAWiwCAGosAgB6LAIAiiwCAJosAgLjpDgC59Q4Auv0OALv1DgC87Q4AvZEOAL6RDgC/kQ4AsA0OALHlDgCy7Q4As+UOALT9DgC15Q4Atu0OALflDgCjuQ4Agi0AAIEVAACAHQAAKosAgKbFDgCl3Q4ALosAgKshDgCqyQ4AMosAgL4sAQCvIQ4ArjkOAK0xDgCsOQ4AOosAgLZVAQC1RQEANosAgLNVAQA+iwCAhngAAIdcAAC/OQEAvjEBAL0lAQC8JQEAuzEBALpZAQDmiQCAQosAgEaLAIBKiwCAhAQDAKOJAgBOiwCApZkCAKaJAgBSiwCAvyg5AFaLAICqhQIAq+0CAKz5AgCt+QIAru0CAK/lAgDjWAIA78AOAOGIAQBaiwCAXosAgGKLAIBmiwCAaosAgG6LAIByiwCAdosAgHqLAIDvKAIA4ygOAH6LAIDhRA4AqbUCAKhpDQCrAQIAqgkCAK0BAgCsGQIArzECAK4BAgC+AAQAgosAgIaLAICKiwCAjosAgJKLAICWiwCAmosAgLnlAwC45QMAu+UDALrlAwC95QMAvOUDAL/lAwC+5QMAsSECALBJAgCzJQIAsiUCALUpAgC0IQIAtxUCALYVAgCowQIAqdECAKr1AgCrDQEArBUBAK0FAQCuBQEArzkBAJ6LAICiiwCAqosAgK6LAICyiwCAtosAgLqLAIC+iwCAuC0BALk9AQC67QEAu+UBALz9AQC95QEAvu0BAL/lAQCwLQEAsTUBALI9AQCzNQEAtC0BALUVAQC2HQEAtxUBAIA9AQCBpQAAgq0AAO/YAACGsAUAh9gFAMKLAIDv1A8AhGwEAOH0DgDGiwCA4xwPAMqLAIDhlAEAzosAgOMMDgCzPQIA0osAgNaLAIDaiwCA3osAgLbFAQC13QEA4osAgLuxAQC6qQEA5osAgOqLAIC/kQEAvqkBAL2hAQC8qQEAposAgO6LAICqRQYAq10GAKxFBgCtTQYArkUGAK99BgDyiwCA9osAgPqLAICj0QUA/osAgKUxBgCmKQYAAowAgAaMAICCHQAAgR0AAIAdAAAKjACADowAgBKMAIC+lAMAFowAgBqMAICGSAMAh8wDAB6MAIAijACAJowAgCqMAICoqQcAqakHAKq5BwCruQcArKkHAK2pBwCuAQcArzUHAC6MAIAyjACANowAgDqMAIA+jACAQowAgEaMAIBKjACAuC0HALnBAAC66QAAu+kAALz5AAC95QAAvuUAAL+dAACwUQcAsV0HALItBwCzJQcAtD0HALUlBwC2JQcAtxUHALMxBgBOjACAUowAgFaMAIBajACAtikGALUhBgBejACAu5kGALqVBgBijACAZowAgL/hBgC++QYAvfEGALz5BgBqjACAo3UGAG6MAIByjACApm0GAHaMAIB6jACApWUGAKrRBgCr3QYAfowAgIKMAICuvQYAr6UGAKy9BgCttQYAqOUBAKn1AQCq/QEAq/UBAKztAQCtNQEArj0BAK81AQCA+QAAgc0AAILFAACEYAEAvngBAIqMAICHrAAAhpABALjRAAC52QAAuuEAALvhAAC8kQAAvZ0AAL6VAAC/iQAAsE0BALFVAQCyXQEAs1UBALRNAQC18QAAtvEAALfxAACzdQIAjowAgJKMAICWjACAmowAgLa1AgC1ZQIAnowAgLuRAgC6iQIAoowAgKaMAIC/NQMAvokCAL2BAgC8iQIAqowAgKMxAgCujACAhMADAKbxAgCyjACAtowAgKUhAgCqzQIAq9UCALqMAIC+jACArs0CAK9xAwCszQIArcUCAKuNAACqjQAAqY0AAKg5AwCvvQAArr0AAK2FAACsjQAAqgAAAKsAAADCjACAxowAgMqMAIDOjACA0owAgNaMAIC7fQAAun0AALl9AAC4fQAAv90BAL7dAQC93QEAvN0BALO5AACysQAAsaEAALCtAAC3XQAAtl0AALWVAAC0lQAA2owAgN6MAIDijACA5owAgIE1AACADQAA6owAgII1AAC+rD0A7owAgPKMAICFaD0A+owAgP6MAICGODwAh8ACALNJAQACjQCA0AAAAAaNAIAKjQCAtkkBALVJAQAOjQCAuykBALolAQASjQCAFo0AgL8dAQC+HQEAvSEBALwpAQDjNDYA4QwGAOGwAgDjPAYAGo0AgB6NAIAijQCAJo0AgIQsPwC+oD8AKo0AgC6NAIDvfDcAMo0AgDaNAIDvGAEAOo0AgD6NAICGaD4Ah8w/AEKNAIBGjQCASo0AgO+UAABOjQCA4ZQBAFKNAIDjUAAAVo0AgILpPwCB6T8AgPE/AKMJPgCPASQA9owAgFqNAIBejQCApgk+AKUJPgBijQCAq2k+AKplPgBmjQCAao0AgK9dPgCuXT4ArWE+AKxpPgCeYTgA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vY0CAL69AgC/fQMAsFkCALFZAgCy7QIAs+UCALT9AgC15QIAtuUCALfVAgCjUQUAEpIAgBaSAIAakgCAHpIAgKZ5BQClcQUAIpIAgKudAgCqnQIAJpIAgCqSAICvIQIArjkCAK0xAgCsOQIAghEAAC6SAICAZQAAgQkAADKSAIC+mAMAOpIAgD6SAICEJAMAQpIAgIdoAwCGjBwARpIAgEqSAIBOkgCAUpIAgFaSAIBakgCAs6ECAITAHAC10QIAXpIAgGKSAIC21QIAZpIAgGqSAIC7wQIAuvUCAL0RAQC82QIAvxEBAL4ZAQBukgCAcpIAgHaSAIB6kgCAfpIAgIKSAICGkgCA77gGAIqSAIDhnAQAjpIAgON0BgCSkgCAlpIAgJqSAICekgCAgPkAAIH5AACCBQAAopIAgL5YHACEWB8A71wAAO9ABgDhkAEA4fwGAOM8AADjdAYAqpIAgK6SAICGmBwAh/QcAKNpAgC+DB8AspIAgLaSAIC6kgCAph0CAKUZAgC+kgCAqwkCAKo9AgDCkgCAxpIAgK/ZAQCu0QEArdkBAKwRAgCokR0AqZkdAKqhHQCroR0ArNEdAK3dHQCu1R0Ar8kdADaSAICmkgCAypIAgM6SAIDSkgCA1pIAgNqSAIDekgCAuHkeALl5HgC6zR4Au8UeALzdHgC9xR4AvsUeAL/1HgCwuR0AsY0dALKFHQCzTR4AtFUeALVdHgC2VR4At0keALjNHwC51R8Aut0fALvVHwC88R8Avf0fAL7pHwC/6R8AsKUfALGxHwCysR8As40fALSVHwC19R8Atv0fALf1HwCoGR4AqRkeAKotHgCrPR4ArCUeAK0tHgCuJR4Ar90fAOKSAIDmkgCA6pIAgO6SAIDykgCAxpEAgPaSAID6kgCAs+UfAP6SAIACkwCABpMAgAqTAIC27R8Ate0fAA6TAIC7NR4AuiEeABKTAIAWkwCAv3EeAL4RHgC9GR4AvCUeAIJpAACjoR8AgFkAAIFRAACmqR8AGpMAgB6TAIClqR8AqmUeAKtxHgCGAAQAh+wBAK5VHgCvNR4ArGEeAK1dHgCoMR4AqTEeAKpBHgCrQR4ArEEeAK1JHgCucR4Ar3EeACKTAIAmkwCAKpMAgC6TAIAykwCANpMAgDqTAIA+kwCAuCkBALkpAQC6OQEAuzUBALwtAQC90QAAvtEAAL/RAACwyQEAsckBALLZAQCz2QEAtMkBALXJAQC2GQEAtxkBALPJHQBCkwCARpMAgEqTAIBOkwCAtskdALXJHQBSkwCAuw0CALoNAgBWkwCAWpMAgL8NAgC+DQIAvQ0CALwNAgBekwCAo40dAGKTAIBmkwCApo0dAGqTAIBukwCApY0dAKpJAgCrSQIAcpMAgHaTAICuSQIAr0kCAKxJAgCtSQIAgA0AAIERAACCEQAAepMAgO/MAgB+kwCAgpMAgISQAgDjLAIAvigDAOHYAQCKkwCAhhAEAIfUAwCOkwCAkpMAgLNhAwCWkwCAmpMAgJ6TAICikwCAtnkDALVxAwCmkwCAu10DALpdAwCqkwCArpMAgL/hAAC++QAAvfEAALz5AACjoQIAspMAgLaTAIC6kwCAvpMAgKa5AgClsQIAwpMAgKudAgCqnQIAxpMAgMqTAICvIQEArjkBAK0xAQCsOQEAzpMAgNKTAIDvZB8A1pMAgNqTAIDekwCA4pMAgOaTAICADQAAgREAAIIVAADqkwCA4eAcAO6TAIDjiB8A8pMAgISAAgC+jAUAh0gFAIYsBAD6kwCA/pMAgO+kHgDv9B4A4QAeAOFQHwDjLB4A47AeAAKUAIAGlACACpQAgA6UAIASlACAFpQAgISEBACzcQEAGpQAgLUdAQC2FQEAHpQAgCKUAIAmlACAugEBALsBAQC89QAAvf0AAL71AAC/7QAAqK0GAKm9BgCqtQYAq8kGAKzZBgCt2QYArskGAK/BBgAqlACALpQAgDKUAIA2lACAOpQAgD6UAIBClACARpQAgLhtBwC5BQcAug0HALsBBwC8AQcAvQEHAL4BBwC/AQcAsIkGALGJBgCybQcAs2UHALR9BwC1ZQcAtmUHALdVBwCGkwCAozkGAEqUAID2kwCApl0GAE6UAIBSlACApVUGAKpJBgCrSQYAVpQAgFqUAICuvQcAr6UHAKy9BwCttQcAgG0AAIEJAACCGQAAXpQAgGKUAIC+nAMAZpQAgGqUAICGQAAAh2AAAG6UAIBylACAdpQAgHqUAIB+lACAgpQAgKiRBgCpkQYAqrkGAKu5BgCsqQYArakGAK7ZBgCv2QYAhpQAgIqUAICOlACAkpQAgJaUAICalACAnpQAgKKUAIC4cQEAuXEBALpxAQC7cQEAvNkBAL3BAQC+wQEAv/UBALCxBgCxuQYAsokGALOJBgC0UQEAtVEBALZRAQC3UQEAszEGAKaUAICqlACArpQAgLKUAIC2KQYAtSEGALaUAIC7fQYAunUGALqUAIC+lACAv5UBAL6VAQC9XQYAvF0GAMKUAICjdQYAxpQAgMqUAICmbQYAzpQAgNKUAIClZQYAqjEGAKs5BgCErAEAvqABAK7RAQCv0QEArBkGAK0ZBgCo3QIAqe0CAKrlAgCr/QIArOUCAK3tAgCu5QIArz0DANqUAIDelACA4pQAgL5kDADmlACA6pQAgO6UAIDylACAuMkDALnJAwC62QMAu9EDALz5AwC9+QMAvpkDAL+VAwCwRQMAsU0DALJFAwCzXQMAtEUDALVNAwC2RQMAt/kDAIFVAwCASQMAs2UCAIJVAwC1ZQIA9pQAgPqUAIC2ZQIAhgAMAIfkAwC7gQMAuokDAL2BAwC8mQMAv4EDAL6JAwCjLQIA/pQAgAKVAIAGlQCACpUAgKYtAgClLQIADpUAgKvJAwCqwQMAEpUAgBaVAICvyQMArsEDAK3JAwCs0QMA49gGAOGsBwDhnAYA45wGABqVAICEWA0AHpUAgCKVAIAmlQCAKpUAgC6VAIAylQCA7xwBADaVAIA6lQCA70AGAIB5AACBFQAAghEAAIQADAA+lQCA46wAAEKVAIDhpAEASpUAgO9wAACGyAwAh6QNAE6VAIBSlQCAVpUAgFqVAIC6yQUAu8kFALilBQC5zQUAvvkFAL/5BQC8zQUAvcUFALKlBQCzrQUAsBEGALERBgC2rQUAt50FALS1BQC1rQUAqmEGAKthBgConQYAqZUGAK5hBgCvYQYArHEGAK1xBgBelQCAYpUAgGaVAIBqlQCAbpUAgHKVAIC+sAwAdpUAgKghDgCpIQ4AqiEOAKs9DgCsJQ4ArS0OAK4lDgCviQ4ARpUAgHqVAIB+lQCAgpUAgIaVAICKlQCAjpUAgJKVAIC4UQ8AuV0PALpVDwC7bQ8AvHUPAL19DwC+dQ8Av2kPALD5DgCxoQ4AsqEOALOhDgC0oQ4AtakOALaRDgC3kQ4As6kOAJaVAIDWlACAmpUAgJ6VAIC2rQ4Ata0OAKKVAIC7ZQ4Auj0OAKaVAICqlQCAv20OAL5lDgC9dQ4AvHUOAIIZAACj7Q4AgGUAAIEZAACm6Q4ArpUAgLKVAICl6Q4AqnkOAKshDgC2lQCAupUAgK4hDgCvKQ4ArDEOAK0xDgCoYQ4AqXUOAKp9DgCrdQ4ArG0OAK31DgCu/Q4Ar/UOAIaAAQCHpAEAvpUAgMKVAIDGlQCAypUAgM6VAIDSlQCAuHUBALl9AQC6dQEAu8kBALzdAQC9xQEAvsUBAL/1AQCwjQ4AsZUOALKdDgCzkQ4AtFUBALVdAQC2VQEAt00BALP1DgDWlQCA2pUAgN6VAIDilQCAtnUOALXlDgDmlQCAu1EOALpJDgDqlQCA7pUAgL+ZAQC+kQEAvUUOALxJDgDylQCAo7EOAPaVAID6lQCApjEOAP6VAIAClgCApaEOAKoNDgCrFQ4ABpYAgAqWAICu1QEAr90BAKwNDgCtAQ4AqO0CAKktAwCqJQMAqz0DAKwlAwCtLQMAriUDAK+ZAwAOlgCAEpYAgBaWAIAalgCAHpYAgCKWAIC+dAIAKpYAgLiNAwC5kQMAupEDALulAwC8vQMAvXUAAL59AAC/dQAAsOkDALHpAwCy+QMAs/EDALTZAwC12QMAtrkDALe1AwCArQAAgbUAAIK9AACzoQMALpYAgLWhAwC2oQMAMpYAgITgAgA2lgCAuiEDALshAwC8IQMAvSkDAL4RAwC/EQMAo+0DAIXABACFtG8AOpYAgD6WAICm7QMApe0DAEKWAICrbQMAqm0DAIZIBQCHbAMAr10DAK5dAwCtZQMArG0DAEaWAIDjAA4A71hsAOG0DwBKlgCATpYAgFKWAIBWlgCAoakDAKD9DwCjwQMAog0DAOHgAwDv4A8A4+QDAFqWAIBelgCAYpYAgIQEBAC+BAQAZpYAgO+UAwBqlgCAbpYAgHKWAIDj1AMAdpYAgOFUAAB6lgCAfpYAgIKWAICGlgCAgA0AAIEVAACCHQAAipYAgI6WAICSlgCAj5EbAO+cDgCE4AcA4dQOAJqWAIDj8A4AnpYAgKKWAICGGAcAh5AEAJnlFwCY5RcAm+kLAJo5CwCd/QoAnPELAJ9VDwCeXQ8AkSkfAJDNGwCTJR8Aks0fAJXREwCUKRMAlxkXAJZ1EwCM4RAAjSUQAI4tEACP+QwAJpYAgJaWAICKORQAi5UUAITpGACFBRgAhuUYAIfxFACmlgCAqpYAgIIxHACDFRwAnKkEAK6WAICylgCAtpYAgLqWAIC+lgCAmtEEAJt9BACUTQ0AleUIAJblCACXtQgAwpYAgMaWAICSWQwAk1kMAKGRAADKlgCAowF8AKKZAACluXwApJF8AKeZeACm4X0AqYF5AKiheACriXQAqgF0AK0BcACsWXQAr4VwAK6dcACx4WwAsAFsALMBaACyHWwAtfVoALT1aADOlgCA0pYAgNaWAIDalgCA3pYAgOKWAIDmlgCA6pYAgO6WAIDylgCAqD0HAKmVBwCqlQcAq6kHAKzdBwCtxQcArsUHAK8dBgD2lgCAgh0AAIEdAACAHQAA+pYAgP6WAIAClwCAvmABALgZBgC5GQYAuikGALslBgC8IQYAvSEGAL4hBgC/IQYAsHEGALFxBgCycQYAs3EGALRNBgC1NQYAtj0GALctBgCzHQcACpcAgIYoAACHqAAADpcAgLZFBwC1VQcAEpcAgLu1BgC6tQYAFpcAgBqXAIC/8QYAvokGAL2lBgC8pQYAHpcAgKNZBwAilwCAJpcAgKYBBwAqlwCALpcAgKURBwCq8QYAq/EGADKXAIA2lwCArs0GAK+1BgCs4QYAreEGAKipBQCptQUAqr0FAKs9AgCsJQIArVECAK5RAgCvUQIAOpcAgD6XAIBClwCARpcAgIQ8AwBKlwCATpcAgFKXAIC4pQIAua0CALqlAgC7vQIAvKUCAL2tAgC+pQIAv30DALAxAgCxMQIAshkCALMZAgC09QIAta0CALalAgC3nQIAVpcAgFqXAIBelwCAszkFAGKXAIC1oQIAtt0CAGaXAIBqlwCAbpcAgLr5AgC7+QIAvMECAL3BAgC+PQIAv2UCAHKXAICmgQIApf0CAHqXAICjZQUAvlh8AIbYfACHnHwArzkCAK5hAgCtnQIArJ0CAKulAgCqpQIAfpcAgIKXAICohQIAqZUCAKqVAgCrpQIArL0CAK3VAgCu0QIAr9ECAIGFAQCAhQEAhpcAgILtAQCKlwCAjpcAgJKXAICWlwCAuHUBALl9AQC6dQEAu80BALzVAQC93QEAvskBAL/BAQCwtQIAsb0CALKBAgCzgQIAtFEBALVRAQC2UQEAt1EBAJqXAICelwCAopcAgKaXAIDhMAYA4WQHAOMoBgDjxAYAhCB9AKqXAIDvbAAA7xgGAK6XAICylwCAtpcAgLqXAICzXQIAvkh8AL6XAIDClwCAxpcAgLYVAgC1dQIAypcAgLs5AgC6MQIAzpcAgNKXAIC/1QEAvtUBAL0VAgC8FQIAo519AHaXAIDWlwCA2pcAgN6XAICm1X0ApbV9AOKXAICr+X0AqvF9AOaXAIDqlwCArxV+AK4VfgCt1X0ArNV9AIBNAACBVQAAglUAALOxfgDulwCAtWV/ALZtfwDylwCAhkADAIcEAwC66X8Au+l/ALz5fwC9+X8Avt1/AL/NfwD2lwCA+pcAgAaXAID+lwCAApgAgAaYAIAKmACADpgAgKhtfgCpXX4AqlV+AKuFfwCsgX8ArYF/AK6BfwCvgX8AsEF/ALFBfwCyQX8As0F/ALR1fwC1ZX8Atm1/ALdlfwC4XX8AuS1/ALolfwC7PX8AvC1/AL0dfwC+FX8Av/UAAKP9fwASmACAFpgAgBqYAIAemACApiF+AKUpfgAimACAq6V+AKqlfgAmmACAKpgAgK+BfgCukX4ArbV+AKy1fgAumACAMpgAgDaYAIA6mACAPpgAgEKYAIBGmACASpgAgIA9AACBCQAAghkAAE6YAIBSmACAhLgBAL6wAQBWmACAqK0BAKnVAQCq1QEAqw0BAKwVAQCtGQEArgkBAK8JAQCGAAQAhwQBAFqYAIBemACAYpgAgGaYAIBqmACAbpgAgLjtAAC5hQAAuo0AALuFAAC8nQAAvYUAAL6NAAC/hQAAsHkBALF5AQCy7QAAs+UAALT9AAC15QAAtuUAALfVAACzXQIAcpgAgHaYAIB6mACAfpgAgLaZAgC1nQIAgpgAgLu9AgC6vQIAhpgAgIqYAIC/IQMAvjkDAL0xAwC8OQMAvigDAKMZAgCOmACAkpgAgKbdAgCWmACAmpgAgKXZAgCq+QIAq/kCAJ6YAICimACArn0DAK9lAwCsfQMArXUDAL7IBACmmACAqpgAgL7EBQCumACAspgAgLaYAIC6mACAgD0AAIEJAACCGQAAvpgAgMKYAICEOAMAypgAgM6YAIDveAIA0pgAgIZIBACHVAMA1pgAgNqYAIDemACA4pgAgOaYAIDqmACA7pgAgPKYAIDjVAIA9pgAgOFAAQD6mACA/pgAgOMkfwACmQCA4Zx8AAaZAIAKmQCADpkAgBKZAICEbAUAFpkAgBqZAIAemQCAIpkAgO8YfwAmmQCAKpkAgLPxAgAumQCAMpkAgDqZAIA+mQCAtukCALXhAgBCmQCAu3EBALppAQCHoAUAhswEAL85AQC+WQEAvVEBALxhAQDhQH8ARpkAgOM4fgCEwAQAgtkAAO8UAACApQAAgdkAAEqZAIDjwAAATpkAgOHUAQBSmQCAVpkAgO+EfgBamQCAqs0BAKvVAQBemQCAYpkAgK79AQCvnQEArMUBAK31AQBmmQCAo1UCAGqZAIBumQCApk0CAHKZAIB2mQCApUUCAMaYAIA2mQCAepkAgH6ZAICCmQCAhpkAgIqZAICOmQCAqJkGAKmZBgCq7QYAq/0GAKzlBgCt7QYAruUGAK/dBgCwpQYAsa0GALKlBgCzuQYAtK0GALVVBwC2UQcAt00HALh1BwC5fQcAunUHALtJBwC8WQcAvVkHAL5JBwC/RQcAs0UGAJKZAICWmQCAmpkAgJ6ZAIC2TQYAtU0GAKKZAIC7SQYAukEGAIYIAACHjAAAv7EHAL5JBgC9TQYAvFEGAIJdAACjAQYAgEUAAIFdAACmCQYAqpkAgK6ZAIClCQYAqgUGAKsNBgCymQCAtpkAgK4NBgCv9QcArBUGAK0JBgCoTQYAqVUGAKpVBgCriQYArLEGAK29BgCuqQYAr6kGAKaZAIC6mQCAvpkAgMKZAIDGmQCAypkAgM6ZAIDSmQCAuEkBALlJAQC6WQEAu1kBALxJAQC9SQEAvt0BAL/VAQCw3QYAsa0GALKlBgCzjQYAtJkGALWZBgC2jQYAt4UGALPdBgDWmQCA2pkAgN6ZAIDimQCAtj0GALU5BgDmmQCAu2kGALoZBgDqmQCA7pkAgL9dBgC+XQYAvVkGALxxBgDymQCAo5kGAPaZAID6mQCApnkGAP6ZAIACmgCApX0GAKpdBgCrLQYABpoAgAqaAICuGQYArxkGAKw1BgCtHQYAqNUCAKndAgCq4QIAq+ECAKw1AwCtPQMArjUDAK8tAwCAzQMAgQkAAIIZAAAOmgCAEpoAgIQYAgC+dAMAGpoAgLjpAwC56QMAuokDALuFAwC8nQMAvYEDAL6BAwC/tQMAsFUDALFdAwCyVQMAs+kDALT5AwC1+QMAtukDALfhAwCGIAwAhxADAB6aAIAimgCAJpoAgCqaAIAumgCA71wCADKaAIDhFAAANpoAgOOIAgC++AwAOpoAgD6aAIBCmgCAu/kDALrxAwC+gA0ARpoAgL9dAwC+XQMAvV0DALzhAwCzCQIASpoAgE6aAIBSmgCAVpoAgLbdAwC13QMAWpoAgKipBgCpqQYAqrkGAKu5BgCsqQYArakGAK4dBQCvFQUAXpoAgGKaAIBmmgCAapoAgG6aAIBymgCAdpoAgHqaAIC4GQUAuS0FALolBQC7yQUAvNkFAL3FBQC+zQUAv8UFALBtBQCxdQUAsnUFALNFBQC0XQUAtT0FALY1BQC3KQUA4fQGAOFUBwDjFAYA47wGAIEJAACAqQAAfpoAgII5AACE7A0AgpoAgIeIDACGDAwAipoAgI6aAIDvzAcA78QHAKMpAwCSmgCAlpoAgJqaAICemgCApv0CAKX9AgCimgCAq9kCAKrRAgCmmgCAqpoAgK99AgCufQIArX0CAKzBAgCoPQ4AqY0OAKqFDgCrnQ4ArIUOAK2NDgCuuQ4Ar7UOAIaaAICumgCAspoAgLaaAIC6mgCAvpoAgMKaAIDGmgCAuL0OALllDwC6bQ8Au2UPALx9DwC9ZQ8Avm0PAL9lDwCw1Q4Asd0OALLVDgCzoQ4AtJUOALWdDgC2lQ4At40OALMNDgDKmgCAzpoAgNKaAIDWmgCAtg0OALUNDgDamgCAuxkOALoRDgDemgCAFpoAgL9ZDgC+UQ4AvXUOALwBDgDimgCAo0kOAOaaAIDqmgCApkkOAO6aAIDymgCApUkOAKpVDgCrXQ4AhKQDAPaaAICuFQ4Arx0OAKxFDgCtMQ4AqLEOAKmxDgCqzQ4Aq8UOAKzdDgCtxQ4ArsUOAK/1DgCA7QEAgfEBAILxAQD6mgCAhpABAIe0AQD+mgCAApsAgLjFAQC5zQEAusUBALvdAQC8zQEAvf0BAL6ZAQC/lQEAsI0OALFBAQCyQQEAs0EBALRBAQC1QQEAtkEBALdBAQCzRQ4ABpsAgAqbAIAOmwCAEpsAgLZFDgC1VQ4AFpsAgLuFAQC6SQ4AGpsAgB6bAIC/hQEAvoUBAL2VAQC8lQEAIpsAgKMBDgAmmwCAKpsAgKYBDgAumwCAMpsAgKURDgCqDQ4Aq8EBADabAIA6mwCArsEBAK/BAQCs0QEArdEBAKgtAwCpPQMAqjUDAKuJAwCsmQMArZkDAK6JAwCvgQMAPpsAgEKbAIBGmwCASpsAgE6bAIBSmwCAVpsAgFqbAIC4rQMAuWUAALptAAC7ZQAAvH0AAL1lAAC+bQAAv2UAALDJAwCxyQMAsqkDALOlAwC0vQMAtaEDALahAwC3lQMAgL0AAIEJAACCGQAAXpsAgGKbAIC+2AMAapsAgG6bAICErAIAcpsAgIfoAwCGDAQAdpsAgHqbAIB+mwCAgpsAgLP9AwCGmwCAipsAgI6bAICSmwCAtlkDALVRAwCWmwCAu00DALpNAwCamwCAnpsAgL8lAwC+OQMAvTEDALw9AwCimwCAppsAgKqbAICumwCA71gPALKbAIC2mwCAupsAgOOQDgC+mwCA4bAPAMKbAIDGmwCAypsAgM6bAIDSmwCAgHUAAIF9AACCdQAAhBgFAO88AwDamwCAvhQFAN6bAIDj0AMA4psAgOFAAADmmwCAhtAEAIdYBQDqmwCA7psAgPKbAID2mwCA+psAgP6bAIACnACABpwAgAqcAIDvrA8AhOwEAOEQDgAOnACA41QBABKcAIAWnACAGpwAgB6cAICj/QIAIpwAgCacAIAqnACALpwAgKZZAgClUQIAMpwAgKtNAgCqTQIANpwAgDqcAICvJQIArjkCAK0xAgCsPQIAqJkGAKmZBgCqrQYAq70GAKylBgCtrQYArqUGAK/ZBgDWmwCAghEAAIEZAACAwQcAPpwAgEKcAIC+cAMARpwAgLhJBwC5SQcAul0HALtVBwC8TQcAvXEHAL51BwC/bQcAsKkGALGpBgCyuQYAs7EGALSZBgC1mQYAtnkHALd5BwC1NQYASpwAgE6cAIC2NQYAhjAAAIdcAwCzPQYAUpwAgL19BgC8dQYAv0UGAL5FBgBmmwCAVpwAgLt1BgC6dQYAo2UGAFqcAIBenACAYpwAgGacAICmbQYApW0GAGqcAICrLQYAqi0GAG6cAIBynACArx0GAK4dBgCtJQYArC0GAKhVBgCpWQYAqm0GAKthBgCsaQYArWkGAK6ZBgCvmQYAdpwAgHqcAIB+nACAgpwAgIacAICKnACAjpwAgJKcAIC4+QYAufkGALqNBgC7hQYAvJ0GAL2FBgC+hQYAv7UGALDpBgCx6QYAsvkGALP5BgC06QYAtd0GALbJBgC3yQYAs+UGAJacAICanACAnpwAgKKcAIC26QYAteEGAKacAIC7LQYAui0GAKqcAICunACAvxkGAL4tBgC9LQYAvC0GAIIVAACjoQYAgGEAAIFhAACmrQYAspwAgL6QAQClpQYAqmkGAKtpBgCEpAEAupwAgK5pBgCvXQYArGkGAK1pBgCohQIAqY0CAKqVAgCruQIArNUCAK3dAgCu1QIAr80CAIaAHACHZAMAvpwAgL5gAwDCnACAxpwAgMqcAIDOnACAuHUDALl9AwC6dQMAu8kDALzZAwC92QMAvskDAL/BAwCwvQIAsY0CALKFAgCzTQMAtFUDALVdAwC2VQMAt00DALMdAgDSnACAhAgDANacAIDanACAtl0CALVdAgDenACAu0kCALp5AgDinACA5pwAgL+ZAwC+kQMAvZkDALxRAgCwAAAAo1kCAOqcAIDunACAphkCAPKcAID2nACApRkCAKo9AgCrDQIA+pwAgP6cAICu1QMAr90DAKwVAgCt3QMAAp0AgAadAIAKnQCA76wGAA6dAIASnQCAFp0AgBqdAIC+6BwAHp0AgCKdAIAqnQCALp0AgOGABwAynQCA42AGAIBdAACBYQAAgmEAALN9AQA2nQCAtW0BALZlAQA6nQCAhiAdAIdYHQC6+QEAu/EBALzZAQC92QEAvrEBAL+xAQDvoAAAPp0AgEKdAIBGnQCASp0AgE6dAIBSnQCA71wBAIRsHADhzAYAVp0AgOMcBgDjSAAAWp0AgOEwAQBenQCAo/EBAGKdAICFABQAZp0AgGqdAICm6QEApeEBAG6dAICrfQEAqnUBAHKdAIB2nQCArz0BAK49AQCtVQEArFUBAKjtHQCpLR4AqjkeAKs5HgCsKR4ArSkeAK6dHgCvkR4AJp0AgHqdAIB+nQCAgp0AgIadAICC+QAAgfEAAID9AAC4qR4AuakeALpJHwC7SR8AvFkfAL1FHwC+TR8Av0UfALDxHgCx+R4AssEeALPBHgC0uR4AtbkeALatHgC3pR4AsBEfALERHwCyER8AsyUfALQlHwC1KR8Atl0fALdRHwC4cR8AuXkfALpBHwC7QR8AvJUAAL2dAAC+lQAAv40AAIqdAIC2nACAjp0AgJKdAICWnQCAmp0AgIb4AwCH0AAAqM0fAKnVHwCq0R8Aq70fAKytHwCtcR8ArnEfAK9xHwCzOR4Anp0AgKKdAICmnQCAqp0AgLaRHgC1RR4Arp0AgLu1HgC6tR4Asp0AgLadAIC/jR4AvoEeAL2RHgC8pR4Aup0AgKN9HgC+nQCAwp0AgKbVHgDGnQCAyp0AgKUBHgCq8R4Aq/EeAM6dAIDSnQCArsUeAK/JHgCs4R4A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gqIAgIaiAICKogCAjqIAgO9EBgCSogCA4dQGAJaiAIDjDAcAmqIAgJ6iAICiogCApqIAgLP1AQCqogCArqIAgLKiAIC2ogCAtkUBALXlAQC6ogCAuzEBALopAQC+ogCAwqIAgL8dAQC+HQEAvRkBALwlAQCoLT4AqTU+AKo9PgCrNT4ArC0+AK2FPgCuhT4Ar7k+AGaiAIDGogCAyqIAgM6iAICAGQAAgRkAAIIFAADSogCAuLk+ALm5PgC6ST8Au0k/ALxZPwC9WT8Avk0/AL9BPwCwrT4AsbU+ALKxPgCzjT4AtJk+ALWZPgC2iT4At4k+AKO1PgCEjAIA1qIAgNqiAIDeogCApgU+AKWlPgDiogCAq3E+AKppPgCGCAAAh2gDAK9dPgCuXT4ArVk+AKxlPgDmogCAs5E/AOqiAIDuogCAtlk/APKiAID2ogCAtbk/ALp1PwC7fT8A+qIAgP6iAIC+QT8Av0E/ALxZPwC9VT8AsJU+ALGdPgCyqT4As6U+ALShPgC1oT4AtqE+ALehPgC45T4Aue0+ALrlPgC7/T4AvO0+AL3dPgC+1T4AvxkBAAKjAIAGowCACqMAgA6jAIASowCA9qEAgBajAIAaowCAqF0+AKkhPgCqPT4AqzU+AKwVPgCt/T4ArvU+AK/tPgCj1T4AHqMAgCKjAIAmowCAKqMAgKYdPgCl/T4ALqMAgKs5PgCqMT4AMqMAgDajAICvBT4ArgU+AK0RPgCsHT4AgREAAIANAAA6owCAghkAAD6jAIBCowCAhJQBAL4QAACGQAcAhwABAEqjAIBOowCAUqMAgFajAIBaowCAXqMAgKiNAgCplQIAqpUCAKvNAgCs2QIArdkCAK7NAgCvxQIAYqMAgGajAIBqowCAbqMAgIwAAAByowCAdqMAgHqjAIC4HQMAucEDALrBAwC7wQMAvMEDAL3JAwC+8QMAv/EDALCJAgCxiQIAsikDALMpAwC0OQMAtTkDALYpAwC3JQMAsx0CAH6jAICCowCAhqMAgIqjAIC2WQIAtVECAI6jAIC7TQIAuk0CAJKjAICWowCAv/0DAL79AwC9/QMAvP0DAJqjAICeowCAoqMAgKajAIDhDD4AqqMAgOOoPwCuowCAgT0AAIAxAADvUD8Agh0AALKjAIC++AQAhhgFAIdMAwCEDAIA48wAALqjAIDhvAEA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tUkCACKmAIC7hQIAuoUCACamAIAqpgCAv4UCAL6FAgC9lQIAvJUCAIU8GgCjVQIALqYAgDKmAICmDQIANqYAgDqmAIClDQIAqsECAKvBAgA+pgCAQqYAgK7BAgCvwQIArNECAK3RAgCCGQAARqYAgIAZAACBGQAASqYAgE6mAIBSpgCAWqYAgL4ABABepgCAYqYAgGamAIBqpgCAbqYAgHKmAIB2pgCA7+gOAHqmAICG6AQAh1ADAH6mAICCpgCA74ACAIamAIDhlAEAiqYAgONYAQCOpgCA4wAOAJKmAIDhaA0AlqYAgKhxAgCpcQIAqnECAKupAgCsuQIArbkCAK6pAgCvqQIAhKwFAJqmAICepgCAoqYAgKamAICqpgCArqYAgLKmAIC4bQEAuQ0BALoFAQC7GQEAvAkBAL09AQC+NQEAv9kBALDZAgCx2QIAsm0BALNlAQC0fQEAtWUBALZlAQC3VQEA4WAPAOP0AADjHA4A4bwBALamAICCOQAAgTEAAIA9AAC6pgCAvigEAL6mAIDCpgCAvjwHAO8QAADv0A4AyqYAgIbgBACHyAQAzqYAgLO1AgDSpgCAtX0CALZ1AgDWpgCA2qYAgN6mAIC6UQIAu1ECALz1AQC9/QEAvvUBAL/tAQBWpgCAxqYAgKqxBQCrsQUArBUGAK0dBgCuFQYArw0GAOKmAIDmpgCA6qYAgKNVBQDupgCApZ0FAKaVBQDypgCAs+kGAPamAID6pgCA/qYAgAKnAIC24QYAtekGAAanAIC7sQYAuqEGAAqnAIAOpwCAv50GAL6RBgC9pQYAvKkGAKgdBgCpIQYAqiEGAKshBgCsIQYArSEGAK4hBgCvIQYAEqcAgBanAIAapwCAHqcAgCKnAIAmpwCAKqcAgC6nAIC45QcAue0HALrlBwC7/QcAvOUHAL3tBwC+5QcAv00HALAlBgCxNQYAsj0GALMxBgC0FQYAtRkGALYNBgC3AQYAo6kHAIIVAACBtQEAgLUBADKnAICmoQcApakHADanAICr8QcAquEHAISgAgA6pwCAr90HAK7RBwCt5QcArOkHAD6nAICzlQYAhugAAIcYAQC2tQYAQqcAgEanAIC1vQYAukkBALtVAQBKpwCATqcAgL45AQC/OQEAvEUBAL05AQCoPQYAqU0GAKpZBgCrUQYArHEGAK1xBgCuuQEAr7kBAISsAQBSpwCAVqcAgFqnAIBepwCAYqcAgGanAIBqpwCAuKkBALmpAQC6aQEAu2kBALx5AQC9eQEAvmkBAL9pAQCwyQEAsdUBALLVAQCzqQEAtLkBALW5AQC2qQEAt6EBAKPRBQBupwCAcqcAgHanAIB6pwCApvEFAKX5BQB+pwCAqxECAKoNAgCCpwCAhqcAgK99AgCufQIArX0CAKwBAgCKpwCAjqcAgJKnAICWpwCAgTEAAIANAACapwCAgjkAAJ6nAICipwCAviQDAKqnAICupwCAsqcAgIbYHACHTAMAtqcAgLqnAIC+pwCAhMAcAOMgAQDCpwCA4cgBAManAIDvMAIAyqcAgM6nAIDSpwCA1qcAgNqnAIDepwCA4qcAgLOVAwDmpwCA6qcAgO6nAIDypwCAtrkDALWxAwD2pwCAu1EDALpJAwD6pwCA/qcAgL/1AAC+SQMAvUEDALxJAwCoLQIAqUUCAKpdAgCrVQIArHkCAK15AgCuvQIAr7UCAL5oHQACqACABqgAgAqoAICAHQAAgQkAAIKpAAAOqACAuFEBALlZAQC6YQEAu2EBALwRAQC9EQEAvhEBAL8RAQCwzQIAsdUCALLdAgCz1QIAtM0CALVxAQC2cQEAt3EBAOFYBgDhVAcA47AAAOO8BgASqACAGqgAgIYYHACHVB0AHqgAgCKoAIAmqACAKqgAgL74HAAuqACA7/AGAO/gBgCjlQIAMqgAgDaoAIA6qACAPqgAgKa5AgClsQIAQqgAgKtRAgCqSQIARqgAgEqoAICv9QEArkkCAK1BAgCsSQIAqG0eAKl1HgCqfR4Aq40eAKyVHgCtnR4Aro0eAK+BHgAWqACATqgAgFKoAIBWqACAWqgAgF6oAIBiqACAZqgAgLiJHgC5iR4AupkeALuRHgC8uR4AvbkeAL59HwC/dR8AsMUeALHNHgCyxR4As90eALTFHgC1zR4AtsUeALe5HgCz9R4AaqgAgG6oAIByqACAdqgAgLYdHgC1HR4AeqgAgLsJHgC6AR4AfqgAgIKoAIC/CR4AvgEeAL0JHgC8ER4Agm0AAKOxHgCAVQAAgWUAAKZZHgCEmAMAv9ABAKVZHgCqRR4Aq00eAIYABACHmAEArkUeAK9NHgCsVR4ArU0eAIqoAICOqACAhCQAAJKoAICWqACAmqgAgKanAICGqACA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5qsAgIR0BwDqqwCA72gBAO6rAIDyqwCApXkCAKbNAQD2qwCAgCEAAIEhAACC3QcAo2kCAKzJAQCtyQEArqEBAK+hAQD6qwCA/qsAgKrpAQCr4QEAlqsAgAKsAIC+QAIABqwAgIYwAwCHMAMACqwAgA6sAICoOQcAqTkHAKoNBwCrHQcArAUHAK0NBwCuBQcAr3kHALAJBwCxCQcAshkHALMRBwC0OQcAtTkHALbdBwC3yQcAuPkHALn5BwC6zQcAu8EHALzFBwC9yQcAvrkHAL+xBwCzpQcAEqwAgBasAIAarACAHqwAgLatBwC1rQcAIqwAgLvtBwC67QcAJqwAgCqsAIC/3QcAvt0HAL3lBwC87QcALqwAgKPhBwAyrACANqwAgKbpBwA6rACAPqwAgKXpBwCqqQcAq6kHAEKsAIBGrACArpkHAK+ZBwCsqQcAraEHAEqsAIBOrACAUqwAgFasAIBarACAXqwAgGKsAIBmrACAgREAAIANAABqrACAghkAAG6sAIByrACAvuQBAHasAICG4AAAhxgBAHqsAIB+rACAgqwAgIasAICKrACA77AEAI6sAIDh1AYAkqwAgONcBACWrACAmqwAgJ6sAICirACAqJkBAKmZAQCqDQEAqwUBAKwdAQCtBQEArgUBAK81AQCEiAEApqwAgKqsAICurACAsqwAgLasAIC6rACAvqwAgLjBAAC5wQAAusEAALvBAAC8wQAAvcEAAL7BAAC/wQAAsE0BALElAQCyIQEAsyEBALQlAQC1LQEAthEBALcRAQDCrACAxqwAgLONAgDKrACAtZ0CAM6sAIDSrACAto0CANasAIDarACAu+kCALqBAgC9/QIAvP0CAL/hAgC+6QIA3qwAgKbVAgClxQIAvggDAKPVAgCCLQAAgRkAAIB5AACvuQIArrECAK2lAgCspQIAq7ECAKrZAgDirACA6qwAgO80AgDurACAhxgDAIYs/ADyrACA9qwAgPqsAID+rACAAq0AgAatAIAKrQCADq0AgOMAAQASrQCA4eABABatAIC6tQMAu70DABqtAIAerQCAvnkDAL95AwC8pQMAvXkDACarAICztQMAIq0AgCatAIC2kQMAKq0AgC6tAIC1pQMAqEkCAKlJAgCqWQIAq1kCAKxJAgCtdQIArnECAK9tAgC+aP0AvqT/ADKtAIA2rQCA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s1kGAA2yAIARsgCAFbIAgBmyAIC2ZQYAtXUGAB2yAIC7KQYAuiEGACGyAIAlsgCAvxUGAL4VBgC9JQYAvC0GAKOZBgCPmfwAKbIAgDGyAIA1sgCApqUGAKW1BgA5sgCAq+kGAKrhBgCGKB8Ah5wAAK/VBgCu1QYAreUGAKztBgCebQkAn30HAJwNCwCd7QkAmvENAJs5DQCY5fAAmQ0PAJbh8QCX6fEAlMX1AJUN8wCSHfcAk/H1AJD9+QCR7fkAgh3/AIMB+gA9sgCAQbIAgIYV9gCHOfYAhAn6AIXx9ACKwfAAiyXyAEWyAIBJsgCAjuEMAI8VDgCMNfIAjQHzAJKtDgCTgQgATbIAgFGyAICW6QQAl3UGAJR5CgCV8QoAmtEGAJvJAABVsgCAWbIAgIEdAwCAHQMAnFkCAIL1AwCrARAAqpUWAKmNFgCojRYAr5UuAK4BLACt/RIArJkSAKOlHgCipR4AoY0CAN2wAICnGRoAppUaAKUBGACknR8AXbIAgGGyAIBlsgCAabIAgG2yAIBxsgCAdbIAgHmyAICz5SoAsuUqALGtLwCw5S4AfbIAgIGyAIC1ASQAtBEqAKgpAwCpNQMAqj0DAKs1AwCsLQMArbUDAK69AwCvtQMAhbIAgImyAICNsgCAkbIAgIAdAACBCQAAgrkAAJWyAIC4TQIAuV0CALptAgC7CQIAvBkCAL0ZAgC+CQIAvwECALDNAwCx1QMAst0DALPVAwC0zQMAtXUCALZ9AgC3dQIAmbIAgITIHQChsgCAvgwfAKWyAICpsgCA70gGAO9YBwDhWAYA4ZgGAOOUAQDjAAYAhhAcAId8HQC+9B4ArbIAgLGyAIC2ZQMAtfUDALWyAICz5QMAubIAgL2yAIDBsgCAv+ECAL5ZAwC9UQMAvFkDALtBAwC6WQMAxbIAgMmyAIAtsgCAnbIAgM2yAIDRsgCA1bIAgNmyAIDdsgCA4bIAgKitHQCptR0AqrUdAKslHgCsPR4ArR0eAK4VHgCvdR4AsA0eALEtHgCyJR4As40eALSVHgC1nR4AtpUeALeNHgC4tR4Aub0eALq1HgC7nR4AvIUeAL1VHwC+XR8Av1UfALMdHQDlsgCA6bIAgO2yAIDxsgCAtr0eALWVHgD1sgCAu8keALrpHgD5sgCA/bIAgL95HgC+cR4AvXkeALzRHgCCKQAAo1kdAIAdAACBFQAApvkeAAGzAIAFswCApdEeAKqtHgCrjR4ACbMAgITgAwCuNR4Arz0eAKyVHgCtPR4AqIkeAKmVHgCqnR4Aq7EeAKzRHgCt2R4Ars0eAK/FHgANswCAEbMAgIaIAACHbAEAFbMAgBmzAIAdswCAIbMAgLhdAQC5wQEAusEBALvBAQC8wQEAvckBAL7xAQC/8QEAsL0eALGdHgCylR4As2UBALR9AQC1ZQEAtm0BALdlAQCqLR0AqzUdACWzAIApswCAri0dAK+VHACsLR0ArSUdAISMAQCjkR0ALbMAgDGzAICmER0ANbMAgDmzAIClgR0As1UeAD2zAIBBswCARbMAgEmzAIC2GR4AtRkeAE2zAIC7GR4AujkeAFGzAIBVswCAv+EBAL75AQC98QEAvAEeAFmzAIBdswCAYbMAgKOZHQBlswCApdUdAKbVHQBpswCAbbMAgHGzAICq9R0Aq9UdAKzNHQCtPQIArjUCAK8tAgCAZQAAgRUAAIIdAACEAAQAdbMAgHmzAICHcAMAhvwEAIGzAICFswCAibMAgI2zAICRswCAlbMAgJmzAICdswCAvsgEAKGzAIClswCAqbMAgK2zAICxswCAtbMAgO/cHwC5swCA4ZQBAL2zAIDjHAEAwbMAgMWzAIDJswCAzbMAgLt1AwC6aQMAvkgGANGzAIC/HQMAvh0DAL0dAwC8ZQMAs9UDANWzAIDZswCA3bMAgOGzAIC2fQMAtcUDAIRwBQCoJQIAqTUCAKo9AgCrNQIArC0CAK2dAgCulQIAr7UCAIIVAADlswCAgNkBAIEJAADEAAAA6bMAgPGzAID1swCAuKkCALmpAgC6SQEAu0kBALxZAQC9RQEAvkUBAL99AQCwzQIAsdECALLRAgCzqQIAtLkCALW5AgC2qQIAt6ECAOEoHgDhNBwA43QBAOMYHgD5swCA/bMAgIa4BACHVAUAhDgHAAG0AIAFtACACbQAgL6sBwANtACA78weAO/IGgCj9QIAEbQAgBW0AIAZtACAHbQAgKZdAgCl5QIAIbQAgKtVAgCqSQIAJbQAgCm0AICvPQIArj0CAK09AgCsRQIAqGEGAKlhBgCqYQYAq2EGAKxhBgCtYQYArmEGAK9hBgDtswCALbQAgDG0AIA1tACAObQAgD20AIBBtACARbQAgLjxBgC58QYAuvEGALvxBgC8nQYAvbEGAL6xBgC/sQYAsOUGALHtBgCy5QYAs/0GALTlBgC17QYAttkGALfVBgCz6QYASbQAgE20AIBRtACAVbQAgLbhBgC16QYAWbQAgLspBgC6IQYAXbQAgGG0AIC/KQYAviEGAL0pBgC8MQYAgl0AAKOtBgCARQAAgV0AAKalBgBltACAabQAgKWtBgCqZQYAq20GAIYADACHQAMArmUGAK9tBgCsdQYArW0GAG20AIDvfAUAcbQAgHW0AIB5tACAfbQAgIG0AICFtACAibQAgI20AICRtACAlbQAgJm0AIDjaAUAnbQAgOF4BQCz0QYAobQAgKW0AICptACArbQAgLb9BgC1/QYAsbQAgLupBgC6oQYAtbQAgLm0AIC/mQYAvqkGAL2pBgC8sQYAqLkGAKm5BgCqGQYAqxkGAKw1BgCtPQYArjUGAK8pBgC9tACAgh0AAIEdAACAHQAAwbQAgMW0AIDJtACA0bQAgLjpAQC56QEAuvkBALv5AQC86QEAvekBAL5dAQC/VQEAsCUGALEtBgCyJQYAsz0GALQtBgC1HQYAthUGALfZAQCGgAwAh+QCANW0AICjnQUA2bQAgKWxBQCmsQUA3bQAgOG0AIDltACAqu0FAKvlBQCs/QUAreUFAK7lBQCv1QUAtk0DAOm0AICExAMAtUUDAO20AICzjQIA8bQAgPW0AIC+SQMAv0kDALxJAwC9SQMAumkDALtpAwD5tACA/bQAgAG1AICmiQMApYEDAAW1AICjSQIACbUAgA21AIARtQCAr40DAK6NAwCtjQMArI0DAKutAwCqrQMAfbMAgBW1AIAZtQCAHbUAgIW0PQAhtQCAJbUAgCm1AIAttQCAMbUAgIA9AACBCQAAgh0AADW1AIC+sAMAObUAgIc4AwCG3AwAQbUAgEW1AIBJtQCATbUAgFG1AIDvXAYAVbUAgFm1AIC+6AwA45QGAF21AIDh3AEAYbUAgGW1AIBptQCAbbUAgLNRAQBxtQCAdbUAgHm1AIB9tQCAtnEBALV5AQCBtQCAuz0BALo9AQCFtQCAibUAgL/9AQC+9QEAvQUBALwFAQCNtQCAkbUAgJW1AICEQAwAmbUAgJ21AIChtQCA76wHAKW1AIDhJAYAqbUAgONABwCGkAwAh/wMALG1AIC1tQCAgFkAAIFlAACCYQAAo90BALm1AICl9QEApv0BAL21AIDBtQCAxbUAgKqxAQCrsQEArIkBAK2JAQCueQEAr3EBAM20AIA9tQCAybUAgM21AICttQCA0bUAgNW1AIDZtQCAqJ0NAKktDgCqOQ4AqzEOAKwRDgCtEQ4Arn0OAK9tDgCwGQ4AsRkOALIxDgCzMQ4AtNEOALXZDgC2zQ4At8UOALj9DgC52Q4AuqkOALupDgC8vQ4AvaUOAL6tDgC/pQ4AqIEPAKmBDwCqgQ8Aq4EPAKyBDwCtjQ8AroUPAK+1DwDdtQCA4bUAgOW1AIDptQCA7bUAgPG1AID1tQCA+bUAgLidDwC5rQ8AuqUPALtNDwC8VQ8AvV0PAL5JDwC/SQ8AsNEPALHRDwCy0Q8As9EPALS1DwC1vQ8AtrUPALetDwCzCQ4A/bUAgAG2AIAFtgCACbYAgLYNDgC1CQ4ADbYAgLsVDgC6FQ4AEbYAgBW2AIC/eQ4AvnEOAL0FDgC8BQ4AghUAAKNNDgCAYQAAgWEAAKZJDgAZtgCAvhABAKVNDgCqUQ4Aq1EOAIQkAQAhtgCArjUOAK89DgCsQQ4ArUEOAKg5DgCpOQ4AqlkOAKtRDgCscQ4ArXEOAK6RAQCvkQEAhgAAAIeEAAAltgCAKbYAgC22AIAxtgCANbYAgDm2AIC4dQEAuX0BALp1AQC7yQAAvNkAAL3ZAAC+yQAAv8EAALD1AQCx/QEAsvUBALNNAQC0VQEAtV0BALZVAQC3TQEAuk0PALtVDwC4TQ8AuUUPAL59DwC/tQ8AvEUPAL11DwCyAQ8AswEPALAxDwCxMQ8AtgEPALcNDwC0EQ8AtREPAKqZDgCrRQ8AqOUOAKmZDgCuQQ8Ar0EPAKxRDwCtUQ8APbYAgEG2AIBFtgCASbYAgE22AIBRtgCAVbYAgFm2AICzUQ0AXbYAgGG2AIBltgCAabYAgLZxDQC1eQ0AbbYAgLu5AgC6sQIAcbYAgHW2AIC/GQIAvhECAL0ZAgC8oQIAebYAgKMVDQB9tgCAgbYAgKY1DQCFtgCAibYAgKU9DQCq9QIAq/0CAIToAwCRtgCArlUCAK9dAgCs5QIArV0CAKhtAgCprQIAqqUCAKu9AgCspQIAra0CAK6lAgCvfQEAgO0BAIHxAQCC8QEAvqAFAJW2AICZtgCAh2gFAIYcBQC4yQEAuckBALrZAQC70QEAvPkBAL35AQC+mQEAv5UBALAFAQCxDQEAsgUBALMdAQC0BQEAtQ0BALYFAQC3+QEA4WQPAOGcDwDjFA4A49QPAJ22AIDhPA4AobYAgOPkAAC+rAQApbYAgKm2AIDvDAAArbYAgLG2AIDvYA4A77QPALW2AIC5tgCAhEQEALNhAgC9tgCAtWECALZhAgDBtgCAxbYAgMm2AIC6jQEAu4UBALydAQC9hQEAvo0BAL+FAQCjrQUAjbYAgM22AIDRtgCA1bYAgKatBQClrQUA2bYAgKtJBgCqQQYA3bYAgOG2AICvSQYArkEGAK1JBgCsUQYA5bYAgOm2AIDttgCA8bYAgIAdAACBCQAAgjkAAPW2AID5tgCA/bYAgIbIAACHIAMAAbcAgAW3AIAJtwCADbcAgKhtBgCptQcAqr0HAKsdBwCsCQcArTEHAK4xBwCvLQcAhKgDABG3AIAVtwCAGbcAgB23AIAhtwCAJbcAgCm3AIC4zQAAudUAALrVAAC75QAAvP0AAL2VAAC+nQAAv5UAALBVBwCxJQcAsi0HALM9BwC0LQcAtRUHALYdBwC39QAALbcAgOG8BgAxtwCA4/QFADW3AIA5twCAPbcAgEG3AIBFtwCASbcAgE23AIBRtwCAVbcAgFm3AIBdtwCA7+gEALN1BgCCLQAAgRUAAIAdAABhtwCAtvEGALXBBgBltwCAu6EGALrRBgBptwCAvmwBAL+RBgC+qQYAvakGALy5BgCjtQYAcbcAgIYoAACHTAEAdbcAgKYxBgClAQYAebcAgKthBgCqEQYAfbcAgIG3AICvUQYArmkGAK1pBgCseQYAhbcAgLO9AQCJtwCAjbcAgLZ5AQCRtwCAlbcAgLV5AQC6VQEAu10BAJm3AICdtwCAvvkAAL/lAAC8RQEAvf0AAKhxAgCpcQIAqnECAKtxAgCstQIArb0CAK61AgCvrQIAhOw8AKG3AICltwCAqbcAgK23AICxtwCAtbcAgLm3AIC4XQMAuWUDALptAwC7ZQMAvH0DAL1lAwC+bQMAv2UDALDVAgCx3QIAstUCALNtAwC0eQMAtWUDALZtAwC3ZQMAHbYAgL23AIDBtwCAo/UCAMW3AIClMQIApjECAMm3AIDNtwCA0bcAgKodAgCrFQIArA0CAK21AwCusQMAr60DAIBlAACBCQAAghkAANW3AIDZtwCA4bcAgL4QPADltwCAhsA8AIcgAwDptwCA7bcAgPG3AID1twCA+bcAgP23AICohQIAqZUCAKqVAgCrpQIArL0CAK3VAgCu0QIAr9ECAAG4AIAFuACACbgAgA24AIARuACAFbgAgBm4AIAduACAuHUBALl9AQC6dQEAu8kBALzZAQC9xQEAvsUBAL/9AQCwtQIAsb0CALKBAgCzgQIAtFUBALVdAQC2VQEAt00BAOGkBgAhuACA41AGAL6APACEHDwAvoA/ACW4AIApuACALbgAgDG4AIA1uACAObgAgD24AIBBuACA7+AGAEW4AICBfQAAgHEAAEm4AICCBQAAUbgAgFW4AIDvTAAAWbgAgOGQAQBduACA41gBAGG4AIBluACAabgAgIZYPwCH/DwAs509AN23AIBNuACAbbgAgHG4AIC21T0AtbU9AHW4AIC7+T0AuvE9AHm4AIB9uACAvxk+AL4RPgC91T0AvNU9AIG4AICj2T0AhbgAgIm4AICmkT0AjbgAgJG4AICl8T0AqrU9AKu9PQCVuACAmbgAgK5VPgCvXT4ArJE9AK2RPQCoVT4AqVk+AKphPgCrYT4ArGE+AK1hPgCuYT4Ar2E+AISoAwCduACAobgAgKW4AICpuACArbgAgLG4AIC1uACAuEU/ALldPwC6VT8Au20/ALx1PwC9fT8AvnU/AL9tPwCwwT8AscE/ALLBPwCzwT8AtME/ALXBPwC2wT8At8E/AIC5AQCBuQEAggUAALm4AIDhgD4AwbgAgOMoPQDFuACAhoAAAIcEAQDvCD0AybgAgM24AIDRuACA1bgAgNm4AICzqT8AvbgAgN24AIDhuACA5bgAgLahPwC1qT8A6bgAgLtFPgC6RT4A7bgAgPG4AIC/RT4AvkU+AL1VPgC8VT4Ao2k/APW4AID5uACA/bgAgAG5AICmYT8ApWk/AAW5AICrhT4AqoU+AAm5AIANuQCAr4U+AK6FPgCtlT4ArJU+ABG5AICzGT4AFbkAgBm5AIC2IT4AHbkAgCG5AIC1MT4AuvEBALv5AQAluQCAKbkAgL6xAQC/vQEAvNEBAL3RAQCo0T0AqdE9AKrVPQCr6T0ArP09AK3lPQCu7T0ArxECAID5AwCBzQMAgsUDAIQkAwC+AAQAMbkAgIesAwCGvAQAuBkCALktAgC6JQIAu+kCALz5AgC9+QIA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eLsAgOE0AgB8uwCA4zQBAIC7AIDjCAwAhLsAgOEIDQChoQEAiLsAgKMJBQCibQMApc0EAKQRBQCnHRkAph0ZAKmhHQCoORkAq+kcAKqpHQCtkREArAEQAK8BFACuUREAsfkVALDlFQCz6WkAsgFoALUBbAC0eWkAjLsAgJC7AICUuwCAmLsAgJy7AICguwCAowkDAKIZDQCh/Q0AoP0NAIIlJgCDBToApLsAgKi7AICGqTwAhzU+AIQdOgCFPTsAiok+AIslMgCsuwCAsLsAgI6xNACPMTYAjD0yAI0tMgCSJTYAk9EIAIREAwC+wAQAlhULAJdVDgCUXQoAlVUKAJplDgCbiQ4AtLsAgLi7AIC8uwCAwLsAgJyBAADEuwCAuLUCALm9AgC6tQIAuwkCALwZAgC9GQIAvgkCAL8BAgCwdQ0AsX0NALJJDQCzSQ0AtJUCALWdAgC2lQIAt40CAKi9DQCpUQ0AqlUNAKtpDQCsfQ0ArWUNAK5tDQCvEQ0AZLsAgILtAQCBHQAAgB0AAMi7AIDMuwCAfboAgL5wBQCznQwAhIwFANC7AIDYuwCA3LsAgLalDAC1tQwA4LsAgLv5DAC68QwAhigFAIcgBQC/GQMAvhEDAL3dDAC83QwA5LsAgKPZDADouwCA7LsAgKbhDADwuwCA9LsAgKXxDACqtQwAq70MAPi7AID8uwCArlUDAK9dAwCsmQwArZkMAAC8AIAEvACACLwAgAy8AIAQvACAFLwAgBi8AIDvvAEAHLwAgOF8DgAgvACA41ABACS8AIAovACALLwAgDC8AICzlQIANLwAgDi8AIA8vACAQLwAgLa9AgC1uQIASLwAgLs5AgC6YQIAhsgEAIesBAC/GQIAvhECAL0ZAgC8IQIAo1UFAILVBwCBxQcAgMUHAEy8AICmfQUApXkFAFC8AICr+QUAqqEFAFS8AIBYvACAr9kFAK7RBQCt2QUArOEFAFy8AICzWQcAYLwAgGS8AIC2HQcAaLwAgGy8AIC1FQcAugkHALsJBwBwvACAdLwAgL75BwC/+QcAvPkHAL35BwDUuwCARLwAgHi8AIB8vACAgLwAgIS8AICIvACAjLwAgKitBwCptQcAqrUHAKvtBwCs+QcArfkHAK7tBwCv5QcAsKkHALGpBwCySQcAs0kHALRZBwC1WQcAtkkHALdJBwC4eQcAuUUHALpBBwC7XQcAvEUHAL1NBwC+RQcAvzkHAKMdBgCQvACAlLwAgJi8AICcvACAplkGAKVRBgCgvACAq00GAKpNBgCkvACAqLwAgK+9BgCuvQYArb0GAKy9BgCAbQAAgQkAAIIZAACsvACAsLwAgISYAQC+kAEAtLwAgIYAHACHxAEAuLwAgLy8AIDAvACAxLwAgMi8AIDMvACAqF0GAKmVAQCqlQEAq6UBAKy9AQCt1QEArtEBAK/RAQDQvACA1LwAgNi8AIDcvACA4LwAgOS8AIDovACA7LwAgLhZAQC5WQEAus0AALvFAAC83QAAvcUAAL7FAAC/9QAAsLUBALG9AQCygQEAs4EBALR5AQC1eQEAtmkBALdpAQCzHQIA8LwAgPS8AIC+gBwA+LwAgLZVAgC1NQIA/LwAgLt5AgC6cQIAAL0AgAS9AIC/vQIAvr0CAL1VAgC8VQIACL0AgKNZAgAMvQCAEL0AgKYRAgAUvQCAGL0AgKVxAgCqNQIAqz0CABy9AIAgvQCArvkCAK/5AgCsEQIArRECACi9AIAsvQCAvgQdAL4AHgAwvQCANL0AgDi9AIA8vQCAgPkAAIHNAACCxQAAhCADAIawHACHlAMAQL0AgES9AIBIvQCATL0AgFC9AIBUvQCA42wCAFi9AIDhoAEAXL0AgO8UAgBgvQCAZL0AgGi9AIBsvQCAcL0AgHS9AIB4vQCA4fAGAOE0BgDjTAAA4xgGAHy9AICAvQCAhL0AgIi9AICAPQAAgQkAAIIZAACMvQCAkL0AgIS8HQDvmAAA7zgHALMxAgDRAAAAh9gdAIZsHACYvQCAtikCALUhAgCcvQCAu80CALrNAgCgvQCApL0AgL/NAgC+zQIAvc0CALzNAgCyXQYAs2UGALANBgCxVQYAtn0GALedBQC0fQYAtXUGALqNBQC7zQUAuKUFALmFBQC+xQUAv8kFALzVBQC9zQUAqL0AgKy9AICwvQCAtL0AgLi9AIC8vQCAwL0AgMS9AICqtQYAq70GAKgBBwCpvQYAroEGAK+NBgCsmQYArZUGAKNxHQDIvQCAzL0AgNC9AIDUvQCApmkdAKVhHQDYvQCAq40dAKqNHQDcvQCA4L0AgK+NHQCujR0ArY0dAKyNHQDkvQCAs9UeAOi9AIDsvQCAts0eAPC9AID0vQCAtcUeALqhHgC7oR4A+L0AgPy9AIC+pR4Av6keALyxHgC9sR4AJL0AgJS9AIAAvgCAhAQDAID5AACB+QAAghEAAAS+AICoIR4AqSEeAKo5HgCrOR4ArCkeAK0pHgCuAR4ArwEeALABHgCxAR4AsgEeALMBHgC0BR4AtQkeALY9HgC3NR4AuA0eALkVHgC6HR4AuxUeALwNHgC95R8Avu0fAL/lHwCjkR8ACL4AgIYoAQCHSAEADL4AgKaJHwClgR8AEL4AgKvlHwCq5R8AFL4AgBi+AICv7R8AruEfAK31HwCs9R8AHL4AgLMtHgAgvgCAJL4AgLaVHgAovgCALL4AgLWdHgC6sR4Au7EeADC+AIA0vgCAvnUBAL99AQC8oR4AvaEeAKjRHgCp2R4AquEeAKvhHgCsUR4ArVEeAK5RHgCvUR4AOL4AgDy+AIBAvgCARL4AgEi+AIBMvgCAUL4AgFS+AIC43QEAue0BALrlAQC7jQEAvJkBAL2ZAQC+jQEAv4UBALAxHgCxMR4AsjEeALMxHgC09QEAtf0BALb1AQC37QEAo2kdAFi+AIBcvgCAYL4AgGS+AICm0R0ApdkdAGi+AICr9R0AqvUdAGy+AIBwvgCArzkCAK4xAgCt5R0ArOUdAIFpAACAWQAAvgAEAIJhAAB4vgCAfL4AgIC+AICEvgCAhOwDAIi+AICHiAMAhuwEAIy+AICQvgCAlL4AgJi+AICohQMAqZUDAKqVAwCrpQMArL0DAK3VAwCu0QMAr9EDAJy+AICgvgCApL4AgKi+AICsvgCAsL4AgLS+AIC4vgCAuHEDALlxAwC6cQMAu3EDALzVAAC93QAAvtUAAL/NAACwtQMAsb0DALKBAwCzgQMAtFEDALVRAwC2UQMAt1EDAOFUHgDhrB8A45QBAOMoHgDjYAMAvL4AgOEIAADAvgCA75ADAMS+AIDIvgCAzL4AgNC+AIDUvgCA70wfAO9MHwCzXQIA2L4AgNy+AIDgvgCA6L4AgLYVAgC1dQIA7L4AgLs5AgC6MQIAhCQFAL7gBAC/1QIAvtUCAL0VAgC8FQIAuJEdALmZHQC6oR0Au6EdALzRHQC93R0AvtUdAL/JHQCwCR4AsQkeALIZHgCzGR4AtAkeALUJHgC2vR0At7UdAKipHgCpqR4AqrkeAKu5HgCsqR4ArakeAK55HgCveR4AgKUAAIGtAACCpQAA8L4AgIbQBACH+AQA9L4AgPi+AIB0vgCA5L4AgPy+AIAAvwCABL8AgAi/AIAMvwCAEL8AgKhxBgCpcQYAqnEGAKtxBgCsVQYArUUGAK5NBgCvRQYAsD0GALHlBgCy7QYAs+UGALT9BgC15QYAtu0GALflBgC43QYAuXEHALp1BwC7SQcAvFkHAL1ZBwC+SQcAv0kHALPZBgAUvwCAGL8AgBy/AIAgvwCAtuUGALX9BgAkvwCAuwEGALrZBgAovwCALL8AgL8BBgC+GQYAvREGALwZBgAwvwCAo9kFADS/AIA4vwCAppEFADy/AIBAvwCApfEFAKq1BQCrvQUARL8AgEi/AICuUQUAr1EFAKyRBQCtkQUAo1kHAIIZAACBGQAAgOEBAEy/AICmZQcApX0HAFC/AICrgQcAqlkHAISgAgC+rAEAr4EHAK6ZBwCtkQcArJkHAFS/AICzqQYAhugAAIcsAQC2WQEAWL8AgFy/AIC1oQYAunUBALt9AQBgvwCAZL8AgL75AQC/+QEAvGUBAL35AQCo0QYAqdkGAKplBgCrdQYArG0GAK2dAQCulQEAr40BAITsAQBovwCAbL8AgHC/AIB0vwCAeL8AgHy/AICAvwCAuGkBALlpAQC6CQEAuwUBALwdAQC9AQEAvgEBAL81AQCw9QEAsf0BALL1AQCzaQEAtHkBALV5AQC2aQEAt2EBAIS/AICIvwCAjL8AgKPhBQCQvwCApekFAKYRAgCUvwCAmL8AgJy/AICqPQIAqzUCAKwtAgCtsQIArrECAK+xAgCgvwCApL8AgL4EAwCEAAwAqL8AgKy/AICwvwCAtL8AgIANAACBFQAAgh0AALi/AIC8vwCAwL8AgIdEAwCG3AwAs+kDAMi/AIDMvwCA0L8AgNS/AIC2PQMAtT0DANi/AIC7GQMAuhEDANy/AIDgvwCAv7kAAL6xAAC9uQAAvAEDAOS/AIDhlAEA6L8AgON8AQDsvwCA8L8AgPS/AID4vwCA/L8AgADAAIAEwACACMAAgAzAAIAQwACAFMAAgO9MAgCoVQIAqV0CAKphAgCrYQIArLUCAK29AgCutQIAr60CAL5oDQAYwACAHMAAgCDAAIAkwACAgq0AAIGtAACArQAAuGEBALlhAQC6CQEAuwkBALwBAQC9AQEAvgEBAL8BAQCw1QIAsd0CALLVAgCzbQEAtHUBALV9AQC2aQEAt2EBAOFoBgDh8AcA47AAAOP0BgAowACALMAAgDDAAIA4wACAPMAAgEDAAIBEwACASMAAgL78DABMwACA72wAAO8oBgCjqQIAUMAAgIZoDACHBA0AVMAAgKZ9AgClfQIAWMAAgKtZAgCqUQIAXMAAgGDAAICv+QEArvEBAK35AQCsQQIAqIUOAKmNDgCqhQ4Aq50OAKyNDgCtvQ4ArrUOAK/dDgA0wACAZMAAgGjAAIBswACAcMAAgHTAAIB4wACAfMAAgLitDgC5tQ4Aur0OALu1DgC8dQ8AvX0PAL51DwC/bQ8AsKkOALG1DgCyvQ4As7UOALStDgC1lQ4Atp0OALeVDgCzDQ4AgMAAgITAAICIwACAjMAAgLY9DgC1BQ4AkMAAgLtxDgC6bQ4AlMAAgJjAAIC/UQ4AvmkOAL1hDgC8aQ4AghkAAKNJDgCAZQAAgRkAAKZ5DgCcwACAoMAAgKVBDgCqKQ4AqzUOAIS8AwCkwACAri0OAK8VDgCsLQ4ArSUOAKidDgCppQ4Aqq0OAKulDgCsvQ4AraEOAK7dDgCvzQ4AhiABAIdkAQCowACArMAAgLDAAIC0wACAuMAAgLzAAIC4eQEAuXkBALrNAQC7xQEAvN0BAL3FAQC+xQEAv/UBALC9DgCxjQ4AsoUOALNJAQC0WQEAtVkBALZJAQC3SQEAtS0OAMDAAIDEwACAtjkOAMjAAIDMwACAsz0OANDAAIC9hQEAvEkOAL+FAQC+hQEA1MAAgMS/AIC7UQ4AumEOAKNlDgDYwACA3MAAgODAAIDkwACApmEOAKV1DgDowACAqwkOAKo5DgDswACA8MAAgK/dAQCu3QEArd0BAKwRDgD0wACA+MAAgO/QDwD8wACAAMEAgATBAIAIwQCADMEAgBDBAIC+aAMAGMEAgBzBAIDhVA4AIMEAgONkDgAkwQCAgFkAAIFZAACCaQAAhIwDAIbwBACHFAMAKMEAgCzBAIAwwQCANMEAgDjBAIA8wQCAQMEAgETBAIBIwQCATMEAgFDBAIBUwQCAWMEAgFzBAIBgwQCAZMEAgGjBAIBswQCAqIkDAKmJAwCqmQMAq5kDAKyJAwCtiQMArj0DAK81AwCwUQMAsVEDALJVAwCzfQMAtBUDALUdAwC2FQMAtw0DALg9AwC5DQMAugUDALvtAAC89QAAvfkAAL7pAAC/6QAAcMEAgHTBAIB4wQCAsz0CAHzBAIC1LQIAtiUCAIDBAIC+aAUAiMEAgLq5AgC7uQIAvK0CAL2FAgC+/QIAv/UCAIBJAACBVQAAglUAAIQABQDvjAMAvhgEAId0BQCG/AQA4zwDAIzBAIDhUAAAkMEAgJTBAICYwQCAnMEAgKDBAICkwQCAqMEAgKzBAICwwQCAtMEAgLjBAIC8wQCA79QOAL4oBgDhdA4AwMEAgONUAQDEwQCAyMEAgMzBAIDQwQCAo/ECANTBAIDYwQCA3MEAgODBAICm6QIApeECAOTBAICrdQIAqnUCAOjBAIDswQCArzkCAK4xAgCtSQIArGECAKgpBgCpKQYAqj0GAKsxBgCsSQYArUkGAK55BgCveQYAhMEAgIIVAACBxQcAgMUHAPDBAICEaAMA9MEAgPjBAIC4yQYAuckGALrZBgC72QYAvMkGAL3JBgC+WQcAv1kHALAJBgCxCQYAshkGALMZBgC0CQYAtQkGALb5BgC3+QYAs7UGAPzBAICGrAAAh0ADAADCAIC2yQYAtcEGAATCAIC7zQYAus0GAAjCAIAMwgCAv80GAL7NBgC9zQYAvM0GABDCAICj8QYAFMIAgBjCAICmjQYAHMIAgCDCAIClhQYAqokGAKuJBgAkwgCAKMIAgK6JBgCviQYArIkGAK2JBgCoJQYAqWEGAKplBgCrfQYArGUGAK1tBgCuZQYAr50GACzCAIAwwgCANMIAgDjCAIA8wgCAQMIAgETCAIBIwgCAuPUGALn9BgC69QYAu4kGALyZBgC9mQYAvokGAL+BBgCw5QYAse0GALLlBgCz/QYAtOUGALXtBgC20QYAt80GAEzCAIC2/QYAtf0GAFDCAICz/QYAVMIAgFjCAIBcwgCAvzkGAL4xBgC9OQYAvCEGALs5BgC6MQYAFMEAgGDCAICjrQYAgnkAAIFVAACAVQAAhFwBAKatBgClrQYAaMIAgKtpBgCqYQYAhkh/AIfkAACvaQYArmEGAK1pBgCscQYAbMIAgO/cBwBwwgCAdMIAgHjCAIB8wgCAgMIAgITCAICIwgCAhKADAIzCAIC/JHkAkMIAgONoBwCUwgCA4XQGALPRAgCYwgCAvgQDAISAfQCcwgCAtvkCALXxAgCgwgCAu7UCALqpAgCkwgCAqMIAgL9RAwC+mQIAvZECALylAgCpBQIAqLkCAKsVAgCqHQIArT0CAKw9AgCvUQIArl0CAL5ofQCswgCAsMIAgLTCAIC4wgCAvMIAgMDCAIDEwgCAufEDALjpAwC78QMAuvkDAL1RAwC86QMAv00DAL5RAwCxNQIAsCkCALMBAgCyNQIAtdEDALQZAgC30QMAttkDAIIpAACjlQMAgB0AAIEVAACmvQMAyMIAgMzCAICltQMAqu0DAKvxAwDQwgCA2MIAgK7dAwCvFQIArOEDAK3VAwCGYH0Ah3h9ALNBAQCEAH8AtUEBANzCAIDgwgCAtkkBAOTCAIDowgCAu0EBALpNAQC9SQEAvEUBAL8pAQC+OQEA7MIAgO/cBgDwwgCA9MIAgPjCAID8wgCAAMMAgO8wBgCELH4A4eAGAATDAIDjiAEACMMAgON0AAAMwwCA4SwBAKPJAQAQwwCAFMMAgIVweQAYwwCApsEBAKXJAQAcwwCAq8kBAKrFAQAgwwCAJMMAgK+hAQCusQEArcEBAKzNAQCo3X0AqQV+AKoBfgCrAX4ArAF+AK0BfgCuAX4ArwF+ANTCAIAowwCALMMAgDDDAIA0wwCAgp0AAIGdAACAnQAAuC1+ALnhfgC64X4Au+F+ALzhfgC94X4AvuF+AL/hfgCwQX4AsU1+ALJZfgCzVX4AtDV+ALUlfgC2JX4AtxV+AKitfwCp0X8AqtF/AKvtfwCs9X8ArRV/AK4RfwCvEX8AOMMAgDzDAIBAwwCARMMAgIbwAwCHuAAASMMAgEzDAIC4EX8AuRl/ALohfwC7IX8AvPUAAL39AAC+9QAAv+0AALBxfwCxcX8AsnF/ALNFfwC0QX8AtU1/ALY9fwC3NX8As1l+AFDDAIBUwwCAWMMAgFzDAIC2lX4AtX1+AGDDAIC7tX4AurV+AGTDAIBowwCAv4l+AL6FfgC9kX4AvKV+AGzDAICjHX4AcMMAgHTDAICm0X4AeMMAgHzDAIClOX4AqvF+AKvxfgCAwwCAhMMAgK7BfgCvzX4ArOF+AK3VfgCwrQAAscUAALLBAACzwQAAtMUAALXNAAC28QAAt/EAALhhAAC5YQAAumEAALt9AAC8ZQAAvW0AAL5lAAC/vQMAiMMAgIzDAICQwwCAZMIAgJTDAICYwwCAnMMAgKDDAICoWQEAqVkBAKrtAACr5QAArP0AAK3lAACu5QAAr9UAAKTDAICCHQAAgR0AAIAdAACowwCArMMAgLDDAIC+VAIAhoAEAIfsAgC4wwCAvMMAgMDDAIDEwwCAyMMAgL54AwDjdH4AzMMAgOG4fQDQwwCA1MMAgNjDAIDcwwCA4MMAgOTDAIDowwCA7MMAgPDDAIDvwH4A9MMAgPjDAID8wwCAs4UDAADEAIAExACACMQAgAzEAIC2hQMAtZUDABDEAIC74QMAuokDAL4kBgAUxACAv+kDAL7hAwC99QMAvPUDAIIpAACjwQMAgB0AAIEVAACmwQMAGMQAgBzEAICl0QMAqs0DAKulAwAgxACAheAFAK6lAwCvrQMArLEDAK2xAwDh+AMAKMQAgONcHwAsxACA7/QDADDEAICGPAcAh6wCAON8fgA0xACA4YABADjEAIA8xACAQMQAgO/kEwBExACAs3EBAEjEAIBMxACAUMQAgFTEAIC2EQEAtWEBAFjEAIC7OQEAujEBAFzEAIBgxACAvxkBAL4RAQC9GQEAvCEBAGTEAIBoxACAbMQAgHDEAIB0xACAeMQAgHzEAIDvxH8AgMQAgOH8fgCExACA4/B/AIANAACBdQAAgn0AAIjEAICMxACAkMQAgKP5AQC+AAgApekBAJjEAICcxACAppkBAISoBQCgxACAq7EBAKq5AQCtkQEArKkBAK+RAQCumQEAqCkGAKkpBgCqOQYAqzkGAKwpBgCtUQYArlUGAK9NBgAkxACAhCABAKTEAICUxACAo+EBAKKZBAChGQQAoPEFALg5BgC5OQYAus0GALvFBgC83QYAvcUGAL7FBgC/8QYAsDUGALE9BgCyNQYAsw0GALQVBgC1HQYAthUGALcJBgCPoWwAs5EHAIYoAQCHfAMAtqEHAKjEAICsxACAtbEHALrlBwC77QcAsMQAgLTEAIC+7QcAv90HALz1BwC97QcAn/l4AJ7leACdcXkAnCF8AJvxfACaYX0AmZlxAJjZcACX4XAAlnl0AJVtdACUbXQAk61pAJJxaACReWgAkB1uAIIhbQCD5W8AuMQAgLzEAICGTWgAh5V1AISZaQCFmWkAiqV1AIu5dQDAxACAxMQAgI5xcACPgXwAjDlxAI05cQCSYX0Ak6l9AMjEAIDMxACAlml5AJeZBACU4XgAlX15AJpBBQCbyQUA0MQAgNTEAIDYxACA3MQAgJypAADgxACAo4ENAKKpAQChqQEA5MQAgKexCQCmAQgApU0NAKSZDQCrkRUAqoUVAKkBFACocQkArx0QAK7pEQCtvREArAEQALMBGACy8RwAscEdALDJHQC0wwCA6MQAgLXhGAC0/RkA7MQAgPDEAID0xACA+MQAgIAdAACBCQAAgv0DAPzEAICjFQUAAMUAgIaIDACHPAMACMUAgKYlBQClNQUADMUAgKtpBQCqYQUAEMUAgBTFAICvWQUArmkFAK1pBQCscQUAGMUAgBzFAICEBAwAIMUAgCTFAIDhbAYAKMUAgOPsewAsxQCAMMUAgDTFAIDvqAYAOMUAgDzFAIBAxQCARMUAgKmNBQCogQUAq60FAKqZBQCtoQUArLkFAK+lBQCuqQUAhGgNAEjFAIBMxQCAUMUAgFTFAIBYxQCAXMUAgL70DAC5SQUAuEEFALtZBQC6QQUAvUkFALxBBQC/cQUAvn0FALGpBQCwoQUAs7kFALKhBQC1mQUAtKkFALd5BQC2kQUAqNUEAKndBACq7QQAqyUDAKyFAwCtjQMArrEDAK+xAwBgxQCAZMUAgGjFAIBsxQCAgBkAAIEZAACCBQAAcMUAgLgxAgC5MQIAujUCALvBAgC8hQIAvbUCAL69AgC/tQIAsGkCALFpAgCyQQIAs0ECALQ5AgC1OQIAthECALcRAgCGoAwAh0wNAHjFAIB8xQCA76QGAIDFAICExQCA78wHAOOUAQDhpAYA4TgBAONcBgCIxQCAjMUAgJDFAICUxQCAmMUAgJzFAICzLQQAoMUAgLVFAwCkxQCAqMUAgLZFAwCsxQCAsMUAgLvlAgC65QIAvd0CALzdAgC/tQIAvrUCAATFAIB0xQCAtMUAgLjFAIC8xQCAwMUAgMTFAIDIxQCAqDEOAKk5DgCqAQ4AqwEOAKxxDgCtcQ4ArnUOAK9tDgCwGQ4AsSUOALItDgCzJQ4AtCEOALUhDgC2IQ4AtyEOALjFDgC5zQ4AusUOALvdDgC8xQ4Avc0OAL5ZDwC/WQ8As6kOAMzFAIDQxQCA1MUAgNjFAIC20Q4AtdkOANzFAIC7wQ4Auv0OAODFAIC+LAAAv8UOAL7FDgC90Q4AvNkOAIJpAACj7Q4AgFkAAIFRAACmlQ4A5MUAgOjFAIClnQ4AqrkOAKuFDgCGyAAAh6wAAK6BDgCvgQ4ArJ0OAK2VDgDsxQCAs5EOAPDFAID0xQCAtqUOAPjFAID8xQCAta0OALrhDgC74Q4AAMYAgATGAIC+6Q4Av9UOALz1DgC96Q4Ao6UKAAjGAIAMxgCAEMYAgBTGAICmzQ0Apc0NABjGAICrbQwAqm0MABzGAIAgxgCArz0MAK49DACtVQwArFUMAKgJDgCpCQ4Aqh0OAKsVDgCsIQ4ArSEOAK4hDgCvIQ4AJMYAgCjGAIAsxgCAMMYAgDTGAIA4xgCAPMYAgEDGAIC4zQEAudUBALrdAQC71QEAvM0BAL1RAQC+UQEAv1EBALAhDgCxIQ4AsiUOALM5DgC0KQ4AtRUOALYdDgC39QEARMYAgEjGAIBMxgCAo5kNAFDGAIClpQ0Apq0NAL7cAgCE7AMAWMYAgKrpDQCr6Q0ArP0NAK3hDQCu4Q0Ar90NAIBFAACBTQAAglkAAKNFAwBcxgCApUEDAKZBAwBgxgCAhsAEAIcAAwCqLQMAqyUDAKw9AwCtJQMAriUDAK8VAwCoWQIAqYUDAKqBAwCrgQMArIUDAK2NAwCusQMAr7EDAGTGAIBoxgCAbMYAgHDGAIB0xgCAeMYAgHzGAICAxgCAuGUDALltAwC6ZQMAu30DALxlAwC9bQMAvmUDAL/dAACwpQMAsa0DALKlAwCzvQMAtK0DALWdAwC2lQMAt10DALMJAgCExgCAiMYAgIzGAICQxgCAtg0CALUNAgCUxgCAu2kCALphAgCYxgCAnMYAgL9ZAgC+aQIAvWkCALxxAgCgxgCApMYAgKjGAICsxgCA4aABALDGAIDjaAMAtMYAgIEVAACAFQAA74wDAIIVAAC4xgCAvMYAgMDGAIC+cAUA4RgOAOGUDwDjOA8A49QPAISUAgDIxgCAzMYAgNDGAIDUxgCA2MYAgNzGAIDgxgCA5MYAgOjGAIDv7AEA7/gPAIZgBACHBAUAs5UBAITMBQC1dQEA7MYAgPDGAIC2dQEA9MYAgPjGAIC7UQEAulkBAL31AAC8SQEAv/UAAL71AACoJQYAqVUGAKpVBgCrrQYArLUGAK29BgCutQYAr60GAMTGAID8xgCAAMcAgATHAIAIxwCADMcAgBDHAIAUxwCAuGkHALlpBwC6CQcAuwkHALwZBwC9GQcAvg0HAL8BBwCw1QYAsd0GALLVBgCzaQcAtHkHALV5BwC2aQcAt2EHAKPdBgAYxwCAHMcAgCDHAIAkxwCApj0GAKU9BgAoxwCAqxkGAKoRBgAsxwCAMMcAgK+9BwCuvQcArb0HAKwBBgCAXQAAgW0AAIJlAACzUQcAvtgDALVxBwC2cQcANMcAgIbgAACHFAMAul0HALs5BwC8KQcAvRUHAL4dBwC/2QAAqJUGAKmdBgCqlQYAq60GAKy1BgCtvQYArrUGAK+tBgA4xwCAPMcAgEDHAIBExwCASMcAgEzHAIBQxwCAVMcAgLhxAQC5cQEAunEBALtxAQC81QEAvd0BAL7VAQC/zQEAsNUGALGxBgCysQYAs40GALSVBgC1UQEAtlEBALdRAQBYxwCAoxkGAFzHAIBgxwCApjkGAFTGAIBkxwCApTkGAKoVBgCrcQYAaMcAgGzHAICuVQYAr5EBAKxhBgCtXQYAcMcAgHTHAIB4xwCAfMcAgIDHAICExwCAiMcAgIzHAICQxwCAlMcAgJjHAICcxwCAgBkAAIEZAACCBQAAoMcAgISAAgC+gAMAhwwDAIasHADhaAYAqMcAgOOYBwCsxwCAsMcAgLTHAIDvrAcAuMcAgLzHAIDAxwCAxMcAgMjHAIDMxwCA0McAgNTHAICzZQMA2McAgLVlAwC2bQMA3McAgODHAIDkxwCAuukDALvlAwC8/QMAve0DAL7RAwC/0QMA6McAgOzHAIDwxwCA9McAgPjHAID8xwCAAMgAgATIAICogQMAqYEDAKqBAwCrgQMArIEDAK2BAwCugQMAr4EDALBBAwCxTQMAskUDALNVAwC0eQMAtXkDALYZAwC3GQMAuCkDALkpAwC6OQMAuzkDALwpAwC9KQMAvhkDAL8ZAwCBGQAAgBEAAKMhAgCCLQAApSECAAjIAIAMyACApikCABDIAIAYyACAq6ECAKqtAgCtqQIArLkCAK+VAgCulQIAhEwCAL5IHQCHZB0AhuwcAONAAwAcyACA4aABACDIAIDvnAMAJMgAgCjIAIAsyACAMMgAgDTIAIA4yACAPMgAgEDIAIBEyACASMgAgEzIAIBQyACAVMgAgFjIAIDvtAEAhKgdAOF8BgBcyACA43AGAGDIAIBkyACAaMgAgGzIAICz4QEAcMgAgHTIAIB4yACAfMgAgLblAQC19QEAgMgAgLuhAQC62QEAvuQcAIjIAIC/rQEAvqUBAL2xAQC8uQEAqBUeAKkZHgCqKR4AqykeAKw9HgCtJR4Ari0eAK8lHgAUyACAgvkfAIH5HwCA4R8AhMgAgIzIAICGHAAAh7ADALjBHgC5wR4AusEeALvBHgC8wR4AvcEeAL7BHgC/wR4AsF0eALElHgCyLR4AsyUeALQhHgC1KR4AthkeALcZHgCjoR4AkMgAgJTIAICYyACAnMgAgKalHgCltR4AoMgAgKvhHgCqmR4ApMgAgKjIAICv7R4AruUeAK3xHgCs+R4ArMgAgLOZHwCwyACAtMgAgLa9HwC4yACAvMgAgLW1HwC6mR8Au5kfAMDIAIDEyACAvnkfAL95HwC8eR8AvXkfAKglHgCpUR4AqlUeAKtpHgCseR4ArXkeAK5pHgCvaR4AyMgAgMzIAIDQyACA1MgAgNjIAIDcyACA4MgAgOTIAIC42R4Aue0eALr5HgC7+R4AvOkeAL3pHgC+nR4Av5UeALAZHgCxGR4AsukeALPpHgC0+R4AtfkeALbpHgC36R4Ao90eAIIpAACBFQAAgB0AAOjIAICm+R4ApfEeAOzIAICr3R4Aqt0eAKTHAIDwyACArz0eAK49HgCtPR4ArD0eAITIAgCzQQEAvgwBAPjIAIC2QQEA/MgAgADJAIC1UQEAuk0BALslAQCGSAAAh1ABAL4lAQC/LQEAvDEBAL0xAQAEyQCACMkAgIQEAwC+gAQADMkAgO+oHwAQyQCAFMkAgL8oMQDjdB8AGMkAgOE4HgAcyQCAIMkAgCTJAIAoyQCALMkAgDDJAICjzQIANMkAgKXdAgA4yQCAPMkAgKbNAgBAyQCARMkAgKupAgCqwQIArb0CAKy9AgCvoQIArqkCAKm1AgCoaR0AqwECAKoJAgCtAQIArBkCAK8xAgCuAQIAhGwFAEjJAIBMyQCAUMkAgFTJAICCnQEAgZ0BAICdAQC55QMAuOUDALvlAwC65QMAveUDALzlAwC/5QMAvuUDALEhAgCwSQIAsyUCALIlAgC1KQIAtCECALcVAgC2FQIAqM0CAKnRAgCq0QIAqw0BAKwVAQCtBQEArgEBAK8BAQBYyQCAXMkAgGDJAIBoyQCAvvgEAGzJAIBwyQCAdMkAgLgVAQC5HQEAuikBALspAQC89QEAvf0BAL71AQC/7QEAsEkBALFVAQCyXQEAs1UBALRNAQC1NQEAtj0BALcxAQCGoAUAh8gFAHjJAIDvvAAA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t6EFALa9BQC1vQUAtL0FAKu9BgCqvQYAqb0GAKi9BgCvfQYArn0GAK19BgCsfQYAJNMAgCjTAIAs0wCAMNMAgDTTAIA40wCAPNMAgEDTAICo7R0AqS0eAKoxHgCrMR4ArJUeAK2dHgCulR4Ar40eAATTAIBE0wCASNMAgEzTAIBQ0wCAVNMAgFjTAIBc0wCAuKkeALmpHgC6XR8Au1EfALxxHwC9cR8AvnUfAL9pHwCw/R4Asc0eALLFHgCzrR4AtLkeALW5HgC2rR4At6UeALO5HgBg0wCAZNMAgGjTAICU0gCAth0eALUdHgBs0wCAuwkeALo5HgBw0wCAhOADAL99HgC+fR4AvXkeALwRHgCCaQAAo/0eAIBFAACBUQAAplkeAL6cAwB00wCApVkeAKp9HgCrTR4AhkgAAIdsAACuOR4ArzkeAKxVHgCtPR4AqF0eAKltHgCqZR4Aq30eAKxlHgCtbR4ArmUeAK/9HgB40wCAfNMAgIDTAICE0wCAiNMAgIzTAICQ0wCAlNMAgLhpAQC5aQEAunkBALt5AQC8aQEAvWkBAL7dAQC/1QEAsIUeALGNHgCyhR4As50eALSFHgC1jR4AtoUeALdZAQCz7R4AmNMAgJzTAICg0wCApNMAgLbtHgC17R4AqNMAgLtJHgC6QR4ArNMAgLDTAIC/SR4AvkEeAL1JHgC8UR4AtNMAgKOpHgC40wCAvNMAgKapHgDA0wCAxNMAgKWpHgCqBR4Aqw0eAMjTAIDM0wCArgUeAK8NHgCsFR4ArQ0eAKghAwCpIQMAqiEDAKshAwCsIQMArSEDAK4hAwCvIQMA0NMAgNTTAIDY0wCAvmACANzTAIDg0wCA6NMAgOzTAIC4iQMAuYkDALqdAwC7lQMAvLkDAL25AwC+eQAAv3kAALDlAwCx7QMAsuUDALP9AwC07QMAtd0DALbVAwC3vQMAgKkAAIG1AACCvQAAs6UDAPDTAIC1pQMAtq0DAPTTAICE4AIA+NMAgLotAwC7JQMAvD0DAL0lAwC+JQMAvxUDAKPpAwD80wCAhmgEAIeAAwAA1ACApuEDAKXpAwAE1ACAq2kDAKphAwAI1ACADNQAgK9ZAwCuaQMArWkDAKxxAwAQ1ACAFNQAgBjUAIAc1ACAINQAgOE8HwAk1ACA40AeACjUAIAs1ACAMNQAgO+MHgA01ACAONQAgDzUAIBA1ACARNQAgIIlAACBEQAAgB0AAEjUAIDj5AMATNQAgOGsAQBQ1ACA77ADAIRkAgC+YAUAhtAEAIdEBQBY1ACAXNQAgGDUAIBk1ACAaNQAgGzUAIBw1ACAdNQAgHjUAIDvsAEAhKQFAOHcHgB81ACA4xABAIDUAICE1ACAiNQAgIzUAICzUQEAkNQAgJTUAICY1ACAnNQAgLYRAQC1fQEAoNQAgLsNAQC6DQEApNQAgKjUAIC//QAAvv0AAL39AAC8/QAAqDkGAKk5BgCqmQYAq5EGAKy1BgCt0QYArskGAK/BBgBU1ACArNQAgLDUAIC01ACAgA0AAIGxAACCsQAAuNQAgLhhBwC5YQcAumEHALt9BwC8ZQcAvW0HAL5lBwC/HQcAsIkGALGJBgCyaQcAs2kHALR5BwC1eQcAtmkHALdlBwCjEQYAvNQAgMDUAIC+gAMAxNQAgKZRBgClPQYAyNQAgKtNBgCqTQYAhggAAId8AwCvvQcArr0HAK29BwCsvQcAzNQAgNDUAICzSQcA1NQAgLVZBwDY1ACA3NQAgLZRBwDg1ACA5NMAgLtBBwC6dQcAvUUHALxFBwC/RQcAvkUHAKh5BgCpeQYAqokGAKuJBgCsmQYArZkGAK6JBgCviQYA5NQAgOjUAIDs1ACA8NQAgPTUAID41ACA/NQAgADVAIC4jQYAuZUGALqVBgC7pQYAvL0GAL1xAQC+cQEAv3EBALD5BgCxzQYAstkGALPZBgC0yQYAtckGALa9BgC3tQYAowEGAATVAIAI1QCADNUAgBDVAICmGQYApREGABTVAICrCQYAqj0GABjVAIAc1QCArw0GAK4NBgCtDQYArA0GACDVAIAk1QCAKNUAgCzVAICAGQAAgRkAAIIFAAAw1QCAhKwBAL6sAQCH6AAAhkwPADjVAIA81QCAQNUAgETVAIConQIAqcUCAKrNAgCrwQIArMUCAK3NAgCu+QIArz0DAEjVAIBM1QCAUNUAgFTVAIC+PAwAWNUAgFzVAIBg1QCAuMkDALnJAwC62QMAu9EDALz5AwC9+QMAvpkDAL+ZAwCwRQMAsU0DALJFAwCzXQMAtEUDALVNAwC2RQMAt/kDALNFAgBk1QCAaNUAgGzVAIBw1QCAtk0CALVNAgB01QCAu4kDALqBAwB41QCAfNUAgL+JAwC+gQMAvYkDALyRAwCA1QCAowECAITVAICI1QCApgkCAIzVAICQ1QCApQkCAKrFAwCrzQMAlNUAgJjVAICuxQMAr80DAKzVAwCtzQMAgO0BAIEVAACCEQAAhAACAJzVAIDhpAEAoNUAgOPsAACo1QCArNUAgLDVAIDvMAAAtNUAgLjVAIC81QCAwNUAgIbgDACH9AIAxNUAgMjVAIDM1QCA0NUAgO/MBgDU1QCA4bAHANjVAIDjEAYA3NUAgODVAIDk1QCA6NUAgOzVAIDw1QCA9NUAgPjVAID81QCAANYAgATWAIAI1gCA7+gBAIUYDwDhzAYADNYAgOMcBgCAKQAAgR0AAIIFAAAQ1gCAszkCAITMDQCGaA8Ah/wMAOHQ0gO28QEAtfkBABjWAIC72QEAutEBAL7kDAAc1gCAv30BAL59AQC9fQEAvMEBAKjxDQCp8Q0AqvENAKvxDQCsMQ4ArTEOAK4xDgCvMQ4ApNUAgBTWAIAg1gCAJNYAgCjWAIAs1gCAMNYAgDTWAIC46Q4AuekOALqJDgC7hQ4AvJ0OAL2BDgC+gQ4Av7UOALBVDgCxXQ4AslUOALPpDgC0+Q4AtfkOALbpDgC34Q4Ao3kNADjWAIA81gCAQNYAgETWAICmsQ4ApbkOAEjWAICrmQ4AqpEOAEzWAIBQ1gCArz0OAK49DgCtPQ4ArIEOAFTWAICz7Q8AWNYAgFzWAIC26Q8AYNYAgGTWAIC16Q8Auq0PALu1DwA01QCAaNYAgL6VDwC/mQ8AvK0PAL2hDwCoIQ4AqSEOAKohDgCrPQ4ArCUOAK0tDgCuJQ4Ar1UOAGzWAIBw1gCAdNYAgHjWAICAHQAAgQkAAIK9AAB81gCAuDkOALk5DgC6yQ4Au8kOALzZDgC92Q4AvskOAL/JDgCwLQ4AsTUOALI9DgCzMQ4AtBUOALUZDgC2CQ4AtwkOAKOpDgCA1gCAhIACAL6AAQCFAAQApq0OAKWtDgCI1gCAq/EOAKrpDgCGKAcAhxgAAK/dDgCu0Q4AreUOAKzpDgCM1gCAs+0BAJDWAICU1gCAtuUBAJjWAICc1gCAte0BALplAQC7bQEAoNYAgKTWAIC+bQEAv10BALx1AQC9bQEAqN0NAKnpDQCqIQIAqyECAKwhAgCtIQIAriECAK8hAgCo1gCArNYAgLDWAIC01gCAohECAKMRAgCgqQ4AodUCALiJAgC5iQIAup0CALuVAgC8vQIAvXUDAL59AwC/dQMAsOUCALHtAgCy5QIAs/0CALTtAgC13QIAttUCALe9AgCjqQIAj8UaALjWAIC81gCAwNYAgKahAgClqQIAxNYAgKspAgCqIQIAyNYAgMzWAICvGQIArikCAK0pAgCsMQIAniUOAJ/lDgCc6QoAnRUKAJpFFgCbRQoAmFkWAJlRFgCWcRIAl4ETAJRVEgCV7RIAktEeAJPZHgCQtRoAkVUeAISpHwCFJR8AhiUfAIexEwDQ1gCA1NYAgIJZGwCDURsAjEUSAI2lFwCOpRcAj7kXAIA5+wHY1gCAijkTAIutEwCUmQsAlaEPAJZpDwCX3Q8A3NYAgO+cDwCSyQsAk30LAJxFAwDjeA4A4NYAgOGYDADk1gCAhHgCAJqRAwCbXQMA4QQAAL6IBQDj3OoD6NYAgOzWAIDw1gCA7+wAAO+MDgDhcA4A4fwOAOMwAADjeA4AgSEAAIA5AADvtO0DgikAALMJAgD41gCAhmgEAIcsBQD81gCAtg0CALUNAgAA1wCAu8UBALrFAQAE1wCACNcAgL99AQC+fQEAvdUBALzVAQCE1gCA9NYAgAzXAIAQ1wCAFNcAgBjXAIAc1wCAINcAgKi9BQCp5QUAquEFAKvhBQCs5QUAre0FAK7RBQCv0QUAsGEGALFhBgCyYQYAs2EGALTZBgC12QYAtskGALfBBgC4yQYAuckGALp5BwC7eQcAvEUHAL0lBwC+EQcAvw0HAKNJBQAk1wCAKNcAgCzXAIAw1wCApk0FAKVNBQA01wCAq4UGAKqFBgA41wCAPNcAgK89BgCuPQYArZUGAKyVBgBA1wCARNcAgEjXAIBM1wCAUNcAgFTXAIBY1wCAXNcAgIA5AACBOQAAggUAAGDXAIC+uAMAhLgDAGjXAIBs1wCAqMUGAKnVBgCq1QYAq+UGAKz9BgCtHQEArhUBAK8NAQBk1wCAcNcAgIaIAQCHHAEAdNcAgHjXAIB81wCAgNcAgLjpAQC56QEAuokBALuJAQC8mQEAvZkBAL6JAQC/iQEAsHUBALF9AQCydQEAs+kBALT5AQC1+QEAtukBALfhAQCzXQYAhNcAgIjXAICM1wCAhLwBALadAQC1dQYAkNcAgLu5AQC6sQEAlNcAgJjXAIC/PQEAvj0BAL09AQC8oQEA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gNwAgLYVAgC1dQIAhNwAgLs5AgC6MQIAiNwAgIzcAIC/2QEAvtEBAL0VAgC8FQIAo50FADTcAICQ3ACAlNwAgJjcAICm1QUApbUFAJzcAICr+QUAqvEFAKDcAICk3ACArxkGAK4RBgCt1QUArNUFAIBRAACBWQAAgmEAALOVBgCo3ACAtXEHALZxBwCs3ACAhkADAIdUAwC67QcAu+UHALzlBwC97QcAvtEHAL/NBwCw3ACAtNwAgLjcAIC83ACAwNwAgMTcAIDvQAQAyNwAgOEwBwDM3ACA45QEANDcAIDU3ACA2NwAgNzcAIDg3ACAoxkGAOTcAIDo3ACA7NwAgPDcAICm/QcApf0HAPTcAICraQcAqmEHAPjcAID83ACAr0EHAK5dBwCtYQcArGkHAKjNBwCp0QcAqtEHAKstBgCsNQYArT0GAK41BgCvnQYAAN0AgATdAIAI3QCADN0AgIAZAACBGQAAggUAABDdAIC4iQYAuYkGALqZBgC7kQYAvLkGAL25BgC+UQEAv1EBALDlBgCx7QYAsv0GALP1BgC02QYAtcUGALbBBgC3uQYAqNEBAKnZAQCqCQEAqwkBAKwZAQCtGQEArgkBAK8JAQCEYAEAvnwBAIeoAACGjAEAGN0AgBzdAIAg3QCAJN0AgLgJAQC5CQEAuhkBALsRAQC8OQEAvTkBAL75AAC/+QAAsH0BALFBAQCyRQEAs10BALRFAQC1TQEAtkUBALc5AQAo3QCALN0AgDDdAICzjQIANN0AgLWdAgC2lQIAON0AgDzdAIBA3QCAurUCALuJAgC8nQIAvYUCAL6NAgC/hQIAps0CAETdAIBI3QCApcUCAEzdAICj1QIAUN0AgFTdAICu1QIAr90CAKzFAgCt3QIAqu0CAKvRAgCE9AMAWN0AgKgxAwCpMQMAqjEDAKsxAwCskQAArZEAAK6RAACvjQAAXN0AgGDdAIBk3QCAaN0AgGzdAIBw3QCAdN0AgHjdAIC4vQAAuWUAALptAAC7ZQAAvH0AAL1lAAC+bQAAv2UAALD9AACxxQAAss0AALOpAAC0uQAAtaUAALahAAC3oQAAgL0BAIEJAACCGQAAfN0AgIDdAIC+WAIAhxQdAIacHQCEbB0AxNsAgIjdAICM3QCAvrwcAJDdAICU3QCAmN0AgLP5AgCc3QCAoN0AgKTdAICo3QCA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gQkAAIIdAABM4gCA4cgGAFDiAIDjSAQAVOIAgKO1BgBY4gCAhigAAIdAAQBc4gCAptkGAKXRBgBg4gCAqyEGAKrNBgBk4gCAaOIAgK8pBgCuIQYArSkGAKw1BgBs4gCAs70BAHDiAIB04gCAtnkBAHjiAIB84gCAtXkBALpVAQC7XQEAgOIAgITiAIC++QAAv/kAALxFAQC9+QAAqHECAKlxAgCqcQIAq3ECAKy1AgCtvQIArrUCAK+tAgC+rDwAiOIAgIziAICQ4gCAlOIAgJjiAICc4gCAoOIAgLhpAwC5aQMAugkDALsJAwC8HQMAvQUDAL4NAwC/BQMAsNUCALHdAgCy1QIAs2kDALR5AwC1eQMAtmkDALdhAwCk4gCAqOIAgKziAICj9QIAsOIAgKUxAgCmMQIAtOIAgLjiAIC84gCAqh0CAKsVAgCsDQIArbEDAK6xAwCvsQMA7xgCAIIVAACBbQAAgG0AAMDiAIDI4gCAhvg8AIcYAwDM4gCA0OIAgNTiAIDY4gCA42wHAAThAIDhaAEA3OIAgKiFAgCplQIAqpUCAKulAgCsvQIArdUCAK7RAgCv0QIA4OIAgOTiAIDo4gCA7OIAgPDiAID04gCA+OIAgPziAIC4dQEAuX0BALp1AQC7zQEAvNUBAL3dAQC+yQEAv8EBALC1AgCxvQIAsoECALOBAgC0VQEAtV0BALZVAQC3TQEA4bQGAADjAIDj9AYABOMAgIQYPQAI4wCADOMAgBDjAIAU4wCAGOMAgBzjAIAg4wCAJOMAgCjjAIDvWAYALOMAgIF9AACAcQAAMOMAgIIFAAA44wCAPOMAgO+AAQC+VDwA4ZABAEDjAIDjfAYAROMAgEjjAIBM4wCAhtg8AIf0PACjnT0AxOIAgDTjAIBQ4wCAVOMAgKbVPQCltT0AWOMAgKv5PQCq8T0AXOMAgGDjAICvGT4ArhE+AK3VPQCs1T0AZOMAgLOhPgBo4wCAbOMAgLatPgBw4wCAdOMAgLWxPgC6ST8Au0k/AHjjAIB84wCAvkk/AL9JPwC8ST8AvUk/AKhVPgCpZT4Aqm0+AKtlPgCsfT4ArWk+AK65PwCvuT8AgOMAgITjAICI4wCAjOMAgJDjAICU4wCAmOMAgJzjAIC4VT8AuV0/ALpVPwC7bT8AvHU/AL19PwC+dT8Av20/ALDJPwCxyT8A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rjUCAK1VAgCsVQIAPOcAgEDnAIBE5wCASOcAgEznAIBQ5wCAVOcAgO/4AQC+bAQA4YAOAFjnAIDjFAEAXOcAgGDnAIBk5wCAaOcAgGznAIBw5wCAdOcAgLPdAQB45wCAtf0BALb1AQB85wCAgOcAgITnAIC6sQEAu4UBALydAQC9NQEAvj0BAL81AQCpBQYAqLkFAKsVBgCqHQYArT0GAKw9BgCvTQYArl0GACTnAICCHQAAgR0AAIAdAACI5wCAjOcAgJDnAICU5wCAuUEHALidBgC7QQcAukkHAL1FBwC8WQcAv0UHAL5FBwCxCQYAsD0GALOpBgCyAQYAtbkGALSxBgC3rQYAtrEGAKORBgCEjAIAhigAAIfAAwCY5wCAprkGAKWxBgCc5wCAq8kGAKr9BgCg5wCApOcAgK95BgCucQYArXkGAKzRBgCo5wCAs5kHAKznAICw5wCAtlEHALTnAIC45wCAtbEHALptBwC7dQcAvOcAgMDnAIC+WQcAv0UHALxtBwC9ZQcAxOcAgMjnAIDM5wCA0OcAgNTnAIDY5wCA3OcAgO+oBQDg5wCA4TQFAOTnAIDjdAUA6OcAgOznAIDw5wCA9OcAgKMdBgCCLQAAgRUAAIAdAAD45wCAptUGAKU1BgD85wCAq/EGAKrpBgAA6ACAhCgBAK/BBgCu3QYAreEGAKzpBgCoxQYAqdUGAKrVBgCr5QYArP0GAK0VBgCuHQYArxUGAL7sAQAI6ACAhggAAIcgAAAM6ACAEOgAgBToAIAY6ACAuH0GALkFBgC6DQYAuwUGALwBBgC9CQYAvjkGAL85BgCwbQYAsXUGALJ9BgCzdQYAtFkGALVFBgC2TQYAt0UGAKiRAgCpmQIAqqECAKuhAgCs0QIArd0CAK7VAgCvyQIAHOgAgCDoAIAk6ACAvyweACjoAIAs6ACAMOgAgDToAIC4VQMAuV0DALppAwC7ZQMAvGEDAL1hAwC+YQMAv2EDALC5AgCxjQIAsoUCALNtAwC0dQMAtX0DALZ1AwC3bQMAOOgAgDzoAICzIQIAQOgAgLVRAgCEiAMAROgAgLZVAgC05gCAvigcALtBAgC6dQIAvbEDALxZAgC/sQMAvrkDAKNpAgBI6ACATOgAgFDoAIBU6ACAph0CAKUZAgBY6ACAqwkCAKo9AgBc6ACAYOgAgK/5AwCu8QMA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hLkHAIW5BwCG2QcAh9kHAIjpBwCJ6QcAivkHAIv5BwCM6QcAjekHAI7RBwCP0QcAkLEHAJGxBwCSSQEAk0kBAJRZAQCVWQEAlkkBAJdJAQCYeQEAmXkBAJpJAQCbSQEAnFkBAJ1ZAQCeSQEAn0kBAKC5AQChuQEAoskBAKPJAQCk2QEApdkBAKbJAQCnyQEAqPkBAKn5AQCqyQEAq8kBAKzZAQCt2QEArskBAK/JAQCwuQEAsbkBALJJAQCzSQEAtFkBALVZAQC2SQEAt0kBALh5AQC5eQEAukkBALtJAQC8WQEAvVkBAL5JAQC/SQEA0jEAgNYxAIDaMQCAkjIAgNoyAIDmMgCA6jIAgO4yAIDyMgCA+jIAgP4yAIASMwCALjMAgDYzAIB2MwCAejMAgIIzAICGMwCAjjMAgJIzAIC2MwCAujMAgNYzAIDaMwCA3jMAgOIzAID2MwCAGjQAgB40AIAiNACARjQAgIY0AICKNACAqjQAgLo0AIDCNACA4jQAgAY1AIBKNQCAUjUAgGY1AIByNQCAejUAgII1AICGNQCAijUAgKI1AICmNQCAwjUAgMo1AIDSNQCA1jUAgOI1AIDqNQCA7jUAgPI1AID6NQCA/jUAgJ42AICyNgCAnoUMAOY2AIDqNgCA8jYAgIC5AwCBuQMAgskDAIPJAwCE2QMAhdkDAIbJAwCHyQMAiPkDAIn5AwCKyQMAi8kDAIzZAwCN2QMAjs0DAI/FAwCQvQMAkQEMAJJJDgCTSQ4AlFkOAJVZDgCWSQ4Al0kOAJh5DgCZeQ4AmkkOAJtJDgCcWQ4AnVkOAJ5JDgCfSQ4AoLkOAKG5DgCiyQ4Ao8kOAKTZDgCl2Q4ApskOAKfJDgCo+Q4AqfkOAKrJDgCryQ4ArNkOAK3ZDgCuyQ4Ar8kOALC5DgCxuQ4AskkOALNJDgC0WQ4AtVkOALZJDgC3SQ4AuHkOALl5DgC6SQ4Au0kOALxZDgC9WQ4AvkkOAL9JDgC8eQQAvXkEAL6JBAC/nQQAuHUEALl9BAC6aQQAu2kEALRxBAC1cQQAtnEEALdxBACwcQQAsXEEALJxBACzcQQArGkEAK1pBACucQQAr3EEAKhBBACpQQQAqkEEAKtBBACknQUApWEEAKZhBACnYQQAoJ0FAKGFBQCijQUAo4UFAJxdBQCdZQUAnm0FAJ9lBQCYXQUAmUUFAJpNBQCbRQUAlB0FAJVlBQCWbQUAl2UFAJAdBQCRBQUAkg0FAJMFBQCMMQcAjTEHAI4xBwCPMQcAiDEHAIkxBwCKMQcAizEHAIQxBwCFMQcAhjEHAIcxBwCAMQcAgTEHAIIxBwCDMQcAJjcAgC43AIA2NwCAcjcAgHY3AIB+NwCAgjcAgIY3AICyNwCAtjcAgL43AIDSNwCA1jcAgPI3AID6NwCA/jcAgCI4AIBCOACAUjgAgFY4AIBeOACAijgAgI44AICeOACAwjgAgM44AIDeOACA9jgAgP44AIACOQCABjkAgAo5AIAWOQCAGjkAgCI5AIA+OQCAQjkAgEY5AIBeOQCAYjkAgGo5AIB+OQCAgjkAgIY5AICOOQCAkjkAgJY5AICaOQCAnjkAgK45AIDGOQCAyjkAgNY5AIDaOQCA3jkAgOI5AIDqOQCA7jkAgPI5AID+OQCABjoAgA46AIASOgCAGjoAgIC5AQCBuQEAgskBAIPJAQCE2QEAhdkBAIbJAQCHyQEAiPkBAIn5AQCKyQEAi8kBAIzZAQCN2QEAjskBAI/JAQCQuQEAkbkBAJIRAACTEQAAlDEAAJUxAAAeOgCAIjoAgCo6AIAyOgCAPSMAgGUsAIBpLACAJSQAgIJgAgCZ4QAAgIAAAIGYAACC5AYAg4gEAITUGwCFlBoAhhgfALMjAICIxB4AiQAQAIqoEwCLrBEAjAAoAI20KwCOuCoAj7wpAOOwAgC+dAIAnlUAAOMUAgCCbAIAtyMAgJkNAAC+RAIAnjUAAIJoAgCZBQAAuyMAgO/MAgC+oAAAgoQAAO/YAgDj7AEA4/QBAL8jAIDjCAMAwyMAgOM4AwDHIwCA44gDAMsjAIDv4AMAzyMAgO+IAwDvPAEA78QDANMjAIDv1AMA4+wDAB43AIDXIwCA4+wDAOPsAwDj5AMA2yMAgOO4AwDvXAMA70wDAN8jAIDvSAMA7/QDAOMjAIDnIwCA7zQDAON8AwDjlAQA6yMAgO8jAIDzIwCA47QEAPcjAID7IwCA/yMAgO9sBAADJACAByQAgO9YBADvUAQACyQAgBYkAIAaJACAvQAAgOP4BADCAACAMSQAgB4kAIBtKQCA45wEAAglAIBrJQCAriUAgO9QBADaJQCABCYAgO88BAApJgCAgAlLAoYcdwC+RAIAgnQCAL5QAgA+JgCAmREBAJkNAQCPrAIAggQCAI1oAQCewQIAi3wBAJ49AQCeKQEAvggCAJfQAgCZXQEAldACAJ5VAQCT0AIAmXUBAJHQAgC+SAIAn7gCAEYmAICdtAIAnk0BAJuwAgCZXQEAmbQCAL6EAgCeqQEApowCAGImAICkgAIAmakBAGomAIChSAIAgqwCAK/kAgCCtAIAglwCAJnlAQC+CAIAgnwCAIIABACopAIAnvkBAL5wAgC1HAQAnoUBAL6oBQCyhAIAtrECAL6sBQC4KQkAuYkCALqZAgCCjAUAu+gEAIKcBQByJgCAuPAEAJ5ZBgCZbQYAnmEGAJl5BgC+fAIAnmEGAIJcAgC+QAIAmVkGAJ5dBgCCYAIAmaUGAL58AgCevQYAghwCAL4UAgCZzQYAvkwCAIJMAgCa3QYAnt0GAJ/FBgDjDAIAgrwCAJn5BgC+ZAIA7/QCAJrxBgCe6QYAn+kGAJ7ZBgCf1QYA4wQCAJklBgCaIQYAgngCAJk9BgDjBAIAgkQCAJolBgC+cAIA75wCAJ4FBgCfFQYA7+gCAJp1BgCZBQYAggQCAL5wAgDjcAIAnnUGAJ8NBgCeAQYAvnwCAOM0AgCZDQYAvmACAIJsAgDv8AIAmTUGAIKQAwDv2AIAniEGAIQmAICbxQcAmeUHAL58AgCe7QcAn8UHAOPsAwCdUAIAnNEHAIJsAgDv1AIAmc0HAIJ8AgC+cAIAmd0HAJ7dBwC+AAIA42gCAJ6tBwCZuQcA42gCAIJ8AgDjDAIAvkgCAJmpBwCCWAIA78QCAJ6ZBwC+bAIA77gCAIKUAgCejQcA77gCALsAAACZeQcAuQwAAJ5xBwC/AAAAglQCAL0EAAC+aAIAs9QDAJmxBgCxcAMAggQCALc4AACeoQYAtTQAAL5wAgCrWAMAnqEGAO9cAgCZqQYArxADAIJQAgCtFAMAmYUHAJlpBgC+WAIAnmEGAL58AgCCaAIApqACAOOQAgCZaQYA43wBAOOYAQDjrAEA49ABAOPoAQC+dAIAno0FAOMwAgDvzAIAgmgCAJnRBQDvlAIA71QBAO9wAQDvJAEA7ygBAL58AgCevQUA4wwCAIJ4AgCZrQIAvnQCAJ6lAgDjNAIAgmACAJkZAAC+YAIA7/wCAJ4NAACClAIA79QCAJAmAIDj/AIAmQkAAL5gAgCYJgCAnh0AAOMAAgCwJSoAglgCAJkNAADv9AIAvmQCAK4mAIDvwAIAnhkAAIIYAgCCOAIA43ACAJkRAACaNQAAmSkBAL50AgDsJgCAnyUAAJ4JAACZ6QEAvrQDAL7gAwCazQEA79gCAJ4RAQCC2AMA/SYAgIHEAgDjsAMAHycAgOP8AwC+/AIAhMQCAIIoAgCGEAIAKicAgIg8AgCeIQAAnw0AAHonAIDvKAMAj3QCAO8sAwCCiAIAmXUAAJoVAACSxAMAldADAJktAACa0QAAjicAgL7IAgCYaAMAm3wDAILEAwCeQQAAnykAALAnAICChAIA45ACAL4IAwC+JwCABigAgJ8ZAACe7QAA49ACAJlxAACaFQAAvhQCAO8wAgCZIQAA71gCABQoAICv7AMAggQCALFMHACwABwAniUAALJMHACeXQAAn2EAAOO8AgCZIQAA+QAAAHEpAIDvlAIAdSkAgL08HACCgB0Av8EfAHkpAIDjtB0AvnQCAJ71HwDj8B0AmQUAAH0pAIC+fAIAngkAAIJgAgCZDQAAiSkAgL5gAgDvzAIAnh0AAOklAIDv3AIA42gCAPkYAIDjPB0AIRoAgP0YAIABGQCAJRoAgCkaAIAtGgCAMRoAgDUaAIA5GgCA76QCAD0aAIDvJB0AQRoAgLHFAAAFGQCAs8UAALLdAAC1yQAAtMEAALcdAAC2wQAAuWUAALhlAAC7zQAAus0AAL3dAAC83QAAv8UAAL7JAAAJGQCADRkAgE0ZAIBhGQCAERkAgBUZAIDvFHgD7wBIA+HYTQPhOKgC41x5A+O0UAOtGQCAsRkAgLUZAIC5GQCAgMkBAIHVAQCC3QEAg20CAITdAQCFcQIAhgEEAIcdBQCIJQUAiTUFAIo9BQCLbQUAjHUFAI1lBQCObQUAj80BAJC1AQCRvQEAkrUBAJNNAwCUVQMAlV0DAJZVAwCXTQMAmHUDAJl9AwCadQMAm00DAJxVAwCdWQMAnkkDAJ9JAwCguQMAobkDAKLBAwCj3QMApMUDAKXNAwCmxQMAp/0DAKjJAwCpyQMAqtEDAKvRAwCsMQMArTEDAK4xAwCvMQMAsFEDALFRAwCyUQMAs1EDALRxAwC1cQMAtnEDALdxAwC4UQMAuVEDALpRAwC7UQMAvDEDAL0xAwC+MQMAvzEDAL0ZAIDBGQCAxRkAgMkZAIDNGQCA0RkAgNUZAIDZGQCA3RkAgOEZAIDwIAIA5RkAgOkZAIDtGQCA8RkAgPUZAICc9TYAnf02APkZAICRkAIA/RkAgKkZAIBFGQCASRkAgEUaAIC6adgASRoAgE0aAIC4sTYAubE2AFEaAIBVGgCAWRoAgF0aAIBRGQCAYRoAgGUaAIBVGQCAWRkAgF0ZAIBlGQCAaRkAgG0ZAIBxGQCAdRkAgHkZAIB9GQCAgRkAgIUZAICJGQCAjRkAgJEZAICVGQCAglgCAJkZAIBpGgCA8FgCAG0aAICdGQCAoRkAgKUZAIABGgCABRoAgJF0AwDhtDsCCRoAgOPYIgINGgCAERoAgBUaAIAZGgCAHRoAgKUqAIBVLQCAqSoAgMEqAICtKgCAljMAgO/IPwK1KgCA4ZTzAuGY0gLjlPcC4xDGAuGUtgLhkJ0C44SiAuMIhwIZGQCAHRkAgO+4swLvOIsCnSoAgOAtAIDvIJcC7+DgAoLkAgBpLQCACAIAgLrF2QAOAgCAFAIAgBoCAIAgAgCAJgIAgCwCAIAyAgCAOAIAgD4CAIBEAgCASgIAgFACAIDhgHgC8OQGAOMUagKCgAgA4aAPAuEIEwLjhA4C4xgeAlYCAIA0AwCA7zQ7Au8wHwI6AwCAQAMAgO8MEgJGAwCAJRkAgCkZAIBMAwCAUgMAgC0ZAIAxGQCAWAMAgF4DAIB2AwCAggMAgIgDAICOAwCAlAMAgJoDAIB8AwCAZAMAgDUZAIA5GQCAbQMAgFwCAIA9GQCAQRkAgHQCAIBoAgCAvAIAgHoCAICYAgCAYgIAgJICAIBuAgCApAIAgNQCAICAUQYAgV0GAIJVBgCDaQYAhHkGAIV5BgCGaQYAh2kGAIhZBgCJoQcAiqUHAIu9BwCMpQcAja0HAI6lBwDyAgCA7AIAgOACAICSCRQAkxUUAJTxBwCV8QcAlvEHAJfxBwCY0QcAmdEHAJo5FACb0QcAnIEHAJ2BBwCefQcAnx0UAJktAQCYLQEAmz0BAJo9AQCdLQEAnC0BACEZAICeVQEAkd0GAJDRBgCTJQEAkiUBAJUtAQCULQEAlx0BAJYdAQCJ8QYAiOkGAIvxBgCK+QYAjbEGAIzpBgCPqQYAjrkGAIHxBgCA7QYAg/EGAIL5BgCF0QYAhOkGAIfRBgCG2QYAua0DALitAwC7vQMAur0DAL2tAwC8rQMAv90DAL7dAwCxrQMAsK0DALO9AwCyvQMAta0DALStAwC3nQMAtp0DAKm5AQCosQEAq3UBAKqxAQCtFQEArBUBAK/dAwCu3QMAobkBAKCpAQCjiQEAorEBAKWZAQCkkQEAp4kBAKaRAQAuAwCAwgIAgM4CAIDmAgCA2gIAgAQDAICwAgCA+AIAgCIDAIAKAwCAngIAgIACAIC2AgCAyAIAgP4CAICGAgCAKAMAgKoCAIAQAwCAjAIAgBYDAIAcAwCACS0AgOsuAIDKNACAhAcAgAYFAIAVBQCAJAUAgDMFAIBCBQCASwUAgPAsOABUBQCAXQUAgGYFAICSBQCA40huA5sFAIDhTG4DpAUAgO/0AQOnBQCAqgUAgK0FAIBGOgCApkwAgNZVAIA2aACAZnEAgJZ6AID2jACAVp8AgIaoAIDtugCAJMQAgFTNAICE1gCAtN8AgDG7AIA6rgCABqUAgPkqAICJKwCAoSoAgOUqAIBBMQCAATEAgE40AIDVLACABjMAgIo3AIBiNACAHSwAgJI0AICeMwCAEjgAgFkrAICFLACA+jEAgCY5AIAdKwCArSsAgJ4xAIC8LgCAySwAgFksAIA4LgCALC4AgJGgBgDuMwCAGSsAgJ43AIB1LACAzS0AgLAFAIDh1D8D4VgaA+PcLwPjUA4D4RTyA+FA0wPjQOoD40DDA7MFAIC2BQCA73jrA+9c8gO5BQCA5QUAgO9E3gPvmCUD4bSLA+E8lwPjfKID45iLA+EwQQDhUKwD4xx/AOOIRgDoBQCA6wUAgO84ewDv4EEA7gUAgPEFAIDvzIoD7yCHA4DBGACB3RgAgikLAIMpCwCE6Q4AhekOAIYZDwCH8RgAiCUPAIntGgCK5RsAiyEdAIw5HQCN5RsAjmkQAI/VGgCQhRsAkU0PAJJFDwCTXQ8AlEUPAJVNDwCWRQ8Al30PAJhFDwCZTQ8AmkUPAJtpGwCcQQ8AnUEPAJ5BDwCfQQ8AoMEPAKHBDwCiwQ8Ao8EPAKS5CwCluQsApqkLAKfNDwCo9Q8Aqf0PAKr1DwCrzQ8ArNkPAK3ZDwCuyQ8Ar8kPALC5DwCxuQ8AsmkPALNpDwC0YQ8AtWEPALY5DwC3OQ8AuBEPALkRDwC66QEAu+kBALz5AQC9+QEAvukBAL/pAQD0BQCA9wUAgPoFAID9BQCAAAYAgCAGAIDhBACAgAUAgNMFAIAOBgCANAYAgEsGAIBoBgCAfwYAgJYGAIDdAwCA9gMAgA8EAIASBwCAQQgAgD4IAIA/BwCAOSQAgHIkAICjJACAyCQAgLkmAIDEJgCAyCYAgMwmAIDQJgCALygAgG4oAICWKACAmigAgL8oAIDHKACA4ygAgPUoAID5KACA/SgAgLrp0wAVKQCAMCkAgEspAIA9JACASiQAgFckAIBkJACAdiQAgIMkAICVJACApyQAgLckAIDMJACA1iQAgOQkAIDuJACA+yQAgAwlAIAWJQCAbyUAgHYlAIAkJQCAgBkDAIEZAwCCKQMAgykDAIQ5AwCFOQMAhikDAIcpAwCIGQMAiRkDAIppAwCLaQMAjHkDAI15AwCOaQMAj2kDAJAZAwCRGQMAkgEEAJMtAwCUNQMAlVUGAJZdBgCXVQYAmG0GAJl1BgCafQYAm3UGAJxtBgCdNQYAnj0GAJ81BgCgzQYAodUGAKLdBgCj1QYApPkDAKX5AwCm6QMAp+kDAKjZAwCp+QYAqikGAKspBgCsOQYArTkGAK7FAwCvPQMAsEUDALFNAwCyRQMAs10DALRFAwC1TQMAtkUDALd9AwC4SQMAuUkDALpZAwC7fQYAvGUGAL1tBgC+ZQYAgCUAgKkVDwCoAQ8Aq00PAKpNDwCtRQ8ArEUPAK+hDQCuqQ0AoXULAKBhCwCj7QsAoqkLAKXlCwCk5QsApzkPAKZZCAC5oQ0AuJkNALuhDQC6qQ0AvaENALy5DQAxJQCAvqkNALGhDQCw2Q0As6ENALKpDQC1oQ0AtLkNALehDQC2qQ0AOCUAgEglAIBbJQCAsiUAgLwlAICRJQCAoSUAgNAlAICB7Q0AgO0NAIP9DQCC/Q0Ahe0NAITtDQCH2Q0AhiEYAJlNDQCYTQ0Am1ENAJpdDQCdeQ0AnHUNAJ9pDQCecQ0AkYkNAJCBDQCTmQ0AkoENAJWJDQCUgQ0Al30NAJaBDQDgJACAICUAgI0lAIDMJQCA3iUAgAgmAIAtJgCAQiYAgPAlAID6JQCADCYAgBkmAIAxJgCATiYAgFgmAIB2JgCASiYAgGYmAIBuJgCAgCYAgIwmAICUJgCAoyYAgN4mAICcJgCAsiYAgKcmAIC9JgCA1CYAgOImAIABJwCAEScAgBsnAIBPJwCAkicAgOcnAIBPKQCAXSkAgGEpAIBlKQCA8CYAgC4nAIA+JwCASCcAgCMnAIBTJwCAYycAgH4nAIBwJwCAlicAgMInAIDJJwCApicAgNMnAIDdJwCAtCcAgBgoAIAKKACA6ycAgCUoAIDyJwCA/CcAgDMoAIBAKACASigAgFQoAIBeKACAcigAgH8oAICGKACAnigAgKUoAICyKACAyygAgNUoAIDnKACAASkAgA4pAIAZKQCAIykAgDQpAIA7KQCAUykAgMMDAIDmBACAhQUAgNgFAIATBgCAOQYAgFAGAIBtBgCAhAYAgJsGAIDjAwCA/AMAgBUEAIAoBACAOwQAgE4EAIBhBACAdAQAgIcEAICaBACAAAUAgA8FAIAeBQCALQUAgDwFAIBjCACAJAgAgMEGAID8BwCAHQkAgOMoEwAzCQCAKggAgC0IAIAxCACAJAcAgNwuAIDKMACA2S0AgLswAIBFMQCAJwkAgO/sEwAGCQCA3A0AgM8IAICDCACAMQcAgEwHAID8BgCACggAgJQIAIAqCQCACQkAgOANAIDsDQCA2wgAgJkIAIAVBwCAhggAgFUHAID/BgCApgcAgJEkAIDwDQCA4ggAgCcIAICcCACAWAgAgBUJAID0DQCA5QgAgBQIAICfCACA6AgAgBcIAIDJCACAoggAgOwIAIAbCACAzAgAgKYIAID3CACA/QgAgIgHAICKCACAWQcAgAMHAIA9CQCAQQkAgEkJAIA2CQCAGAkAgPgNAID0CACALQkAgAwJAIDkDQCA0ggAgI4IAIBdBwCAMAkAgA8JAIDoDQCA1QgAgJEIAIBgBwCArQgAgGMHAIDjSBIA4xQSAOP4EwDjuBMA4+wSAOOgEgDjbBIA43gSAO/ADQDv2A0A73QSAO9QEgDvqBIA79wSAO8oEwDvIBMA6QcAgMwGAIAOCACAEQgAgNgGAIDUBgCAIQgAgAcHAIBnCACADAcAgHYIAIA0BwCANwcAgKoIAIC2CACAuQgAgOPYEADjoBAA46AQAON0EQDjNBAA4wgQAOPkEADj9BAA77wQAO/gEADvzBAA7zgQAO8QEADvcBAA73AQAO9MEADjhBMA4+gTAOMwEADjEBAA42ATAONAEwDjpBMA47QTAO/IEwDvtBMA75gTAO98EwDvXBMA70wTAO8UEwDv6BAAgO08AIH1PACC/TwAg/U8AITtPACFFT0Ahh09AIcVPQCILT0AiTU9AIo9PQCLNT0AjC09AI0VPQCOHT0AjxU9AJBtPQCRdT0Akn09AJN1PQCUbT0AlRU9AJYdPQCXFT0AmC09AJk1PQCaPT0AmzU9AJwtPQCdFT0Anh09AJ8VPQCg7T0AofU9AKL9PQCj9T0ApO09AKUVPQCmHT0ApxU9AKgtPQCpNT0Aqj09AKs1PQCsLT0ArRU9AK4dPQCvFT0AsG09ALF1PQCyfT0As3U9ALRtPQC1FT0AthE9ALcRPQC4MT0AuTE9ALoxPQC7MT0AvBE9AL0RPQC+ET0AvxE9AIDxPACB/TwAgvU8AIMNPwCEFT8AhR0/AIYVPwCHDT8AiDU/AIk9PwCKNT8Aiw0/AIwVPwCNHT8AjhU/AI8NPwCQdT8AkX0/AJJ1PwCTDT8AlBU/AJUZPwCWCT8Alwk/AJg5PwCZOT8Amgk/AJsJPwCcGT8AnRk/AJ4JPwCfCT8AoPk/AKH5PwCiCT8Aowk/AKQZPwClGT8Apgk/AKcJPwCoOT8AqTk/AKoJPwCrCT8ArBk/AK0ZPwCuCT8Arwk/ALB5PwCxeT8Asgk/ALMJPwC0GT8AtRk/ALYJPwC3CT8AuDk/ALk5PwC6CT8Auwk/ALwZPwC9GT8Avgk/AL8JPwCA+TwAgfk8AIJJPQCDST0AhFk9AIVZPQCGST0Ah0k9AIh5PQCJeT0Aikk9AItJPQCMWT0AjVk9AI5JPQCPST0AkDk9AJE5PQCSAQQAk00GAJRVBgCVXQYAllUGAJdNBgCYdQYAmX0GAJp1BgCbTQYAnFUGAJ1dBgCeVQYAn00GAKC1BgChvQYAorUGAKPNBgCk1QYApd0GAKbVBgCnzQYAqPUGAKn9BgCq9QYAq80GAKzVBgCt3QYArtUGAK/NBgCwtQYAsb0GALK1BgCzTQYAtFUGALVdBgC2VQYAt00GALh1BgC5fQYAunUGALtNBgC8VQYAvV0GAL5VBgC/TQYArH0/AK2lPwCurT8Ar6U/AKh9PwCpZT8Aqm0/AKtlPwCkHT8ApUU/AKZNPwCnRT8AoB0/AKEFPwCiDT8AowU/ALydPwC9pT8Avq0/AL+lPwC4nT8AuYU/ALqNPwC7hT8AtN0/ALWlPwC2rT8At6U/ALDdPwCxxT8Ass0/ALPFPwCMZToAjW06AI5lOgCPfToAiEU6AIlNOgCKRToAi306AIRlOgCFbToAhmU6AId9OgCABToA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ACDZjgAg2Y7ZkQAg2Y8AINmP2ZEAINmQACDZkNmRACDZkQAg2ZHZsAAg2ZIAIOOCmQAg44KaACEAISEAIT8AIgAjACQAJQAmACcAKAAoMSkAKDEwKQAoMTEpACgxMikAKDEzKQAoMTQpACgxNSkAKDE2KQAoMTcpACgxOCkAKDE5KQAoMikAKDIwKQAoMykAKDQpACg1KQAoNikAKDcpACg4KQAoOSkAKEEpAChCKQAoQykAKEQpAChFKQAoRikAKEcpAChIKQAoSSkAKEopAChLKQAoTCkAKE0pAChOKQAoTykAKFApAChRKQAoUikAKFMpAChUKQAoVSkAKFYpAChXKQAoWCkAKFkpAChaKQAoYSkAKGIpAChjKQAoZCkAKGUpAChmKQAoZykAKGgpAChpKQAoaikAKGspAChsKQAobSkAKG4pAChvKQAocCkAKHEpAChyKQAocykAKHQpACh1KQAodikAKHcpACh4KQAoeSkAKHopACjhhIApACjhhIIpACjhhIMpACjhhIUpACjhhIYpACjhhIcpACjhhIkpACjhhIspACjhhIwpACjhhI4pACjhhI8pACjhhJApACjhhJEpACjhhJIpACjkuIApACjkuIMpACjkuIkpACjkuZ0pACjkuowpACjkupQpACjku6MpACjkvIEpACjkvJEpACjlhaspACjlha0pACjlirQpACjljYEpACjljZQpACjlkI0pACjlkbwpACjlm5spACjlnJ8pACjlraYpACjml6UpACjmnIgpACjmnIkpACjmnKgpACjmoKopACjmsLQpACjngaspACjnibkpACjnm6MpACjnpL4pACjnpZ0pACjnpa0pACjoh6opACjoh7MpACjosqEpACjos4cpACjph5EpACjqsIApACjrgpgpACjri6QpACjrnbwpACjrp4gpACjrsJQpACjsgqwpACjslYQpACjsmKTsoIQpACjsmKTtm4QpACjsnpApACjso7wpACjssKgpACjsubQpACjtg4ApACjtjIwpACjtlZgpACkAKgArACwALQAuAC4uAC4uLgAvADAAMCwAMC4AMOKBhDMAMOeCuQAxADEsADEuADEwADEwLgAxMOaXpQAxMOaciAAxMOeCuQAxMQAxMS4AMTHml6UAMTHmnIgAMTHngrkAMTIAMTIuADEy5pelADEy5pyIADEy54K5ADEzADEzLgAxM+aXpQAxM+eCuQAxNAAxNC4AMTTml6UAMTTngrkAMTUAMTUuADE15pelADE154K5ADE2ADE2LgAxNuaXpQAxNueCuQAxNwAxNy4AMTfml6UAMTfngrkAMTgAMTguADE45pelADE454K5ADE5ADE5LgAxOeaXpQAxOeeCuQAx4oGEADHigYQxMAAx4oGEMgAx4oGEMwAx4oGENAAx4oGENQAx4oGENgAx4oGENwAx4oGEOAAx4oGEOQAx5pelADHmnIgAMeeCuQAyADIsADIuADIwADIwLgAyMOaXpQAyMOeCuQAyMQAyMeaXpQAyMeeCuQAyMgAyMuaXpQAyMueCuQAyMwAyM+aXpQAyM+eCuQAyNAAyNOaXpQAyNOeCuQAyNQAyNeaXpQAyNgAyNuaXpQAyNwAyN+aXpQAyOAAyOOaXpQAyOQAyOeaXpQAy4oGEMwAy4oGENQAy5pelADLmnIgAMueCuQAzADMsADMuADMwADMw5pelADMxADMx5pelADMyADMzADM0ADM1ADM2ADM3ADM4ADM5ADPigYQ0ADPigYQ1ADPigYQ4ADPml6UAM+aciAAz54K5ADQANCwANC4ANDAANDEANDIANDMANDQANDUANDYANDcANDgANDkANOKBhDUANOaXpQA05pyIADTngrkANQA1LAA1LgA1MAA14oGENgA14oGEOAA15pelADXmnIgANeeCuQA2ADYsADYuADbml6UANuaciAA254K5ADcANywANy4AN+KBhDgAN+aXpQA35pyIADfngrkAOAA4LAA4LgA45pelADjmnIgAOOeCuQA5ADksADkuADnml6UAOeaciAA554K5ADoAOjo9ADsAPAA9AD09AD09PQA+AD8APyEAPz8AQABBAEFVAEHiiJVtAEIAQnEAQwBDRABDby4AQ+KIlWtnAEQAREoARFoARHoARMW9AETFvgBFAEYARkFYAEcAR0IAR0h6AEdQYQBHeQBIAEhQAEhWAEhnAEh6AEkASUkASUlJAElKAElVAElWAElYAEoASwBLQgBLSwBLTQBMAExKAExURABMagBMwrcATQBNQgBNQwBNRABNSHoATVBhAE1WAE1XAE3OqQBOAE5KAE5qAE5vAE8AUABQSABQUE0AUFBWAFBSAFBURQBQYQBRAFIAUnMAUwBTRABTTQBTUwBTdgBUAFRFTABUSHoAVE0AVQBWAFZJAFZJSQBWSUlJAFbiiJVtAFcAV0MAV1oAV2IAWABYSQBYSUkAWQBaAFsAXABdAF4AXwBgAGEAYS5tLgBhL2MAYS9zAGHKvgBiAGJhcgBjAGMvbwBjL3UAY2FsAGNjAGNkAGNtAGNtMgBjbTMAZABkQgBkYQBkbABkbQBkbTIAZG0zAGR6AGTFvgBlAGVWAGVyZwBmAGZmAGZmaQBmZmwAZmkAZmwAZm0AZwBnYWwAaABoUGEAaGEAaQBpaQBpaWkAaWoAaW4AaXYAaXgAagBrAGtBAGtIegBrUGEAa1YAa1cAa2NhbABrZwBrbABrbQBrbTIAa20zAGt0AGvOqQBsAGxqAGxtAGxuAGxvZwBseABswrcAbQBtMgBtMwBtQQBtVgBtVwBtYgBtZwBtaWwAbWwAbW0AbW0yAG1tMwBtb2wAbXMAbeKIlXMAbeKIlXMyAG4AbkEAbkYAblYAblcAbmoAbm0AbnMAbwBvVgBwAHAubS4AcEEAcEYAcFYAcFcAcGMAcHMAcQByAHJhZAByYWTiiJVzAHJhZOKIlXMyAHMAc3IAc3QAdAB1AHYAdmkAdmlpAHZpaWkAdwB4AHhpAHhpaQB5AHoAewB8AH0AwqIAwqMAwqUAwqYAwqwAwrBDAMKwRgDCtwDDgADDgQDDggDDgwDDhADDhQDDhgDDhwDDiADDiQDDigDDiwDDjADDjQDDjgDDjwDDkQDDkgDDkwDDlADDlQDDlgDDmQDDmgDDmwDDnADDnQDDoADDoQDDogDDowDDpADDpQDDpwDDqADDqQDDqgDDqwDDrADDrQDDrgDDrwDDsADDsQDDsgDDswDDtADDtQDDtgDDuQDDugDDuwDDvADDvQDDvwDEgADEgQDEggDEgwDEhADEhQDEhgDEhwDEiADEiQDEigDEiwDEjADEjQDEjgDEjwDEkgDEkwDElADElQDElgDElwDEmADEmQDEmgDEmwDEnADEnQDEngDEnwDEoADEoQDEogDEowDEpADEpQDEpgDEpwDEqADEqQDEqgDEqwDErADErQDErgDErwDEsADEsQDEtADEtQDEtgDEtwDEuQDEugDEuwDEvADEvQDEvgDFgwDFhADFhQDFhgDFhwDFiADFiwDFjADFjQDFjgDFjwDFkADFkQDFkwDFlADFlQDFlgDFlwDFmADFmQDFmgDFmwDFnADFnQDFngDFnwDFoADFoQDFogDFowDFpADFpQDFqADFqQDFqgDFqwDFrADFrQDFrgDFrwDFsADFsQDFsgDFswDFtADFtQDFtgDFtwDFuADFuQDFugDFuwDFvADFvQDFvgDGjgDGkADGoADGoQDGqwDGrwDGsADHjQDHjgDHjwDHkADHkQDHkgDHkwDHlADHlQDHlgDHlwDHmADHmQDHmgDHmwDHnADHngDHnwDHoADHoQDHogDHowDHpgDHpwDHqADHqQDHqgDHqwDHrADHrQDHrgDHrwDHsADHtADHtQDHuADHuQDHugDHuwDHvADHvQDHvgDHvwDIgADIgQDIggDIgwDIhADIhQDIhgDIhwDIiADIiQDIigDIiwDIjADIjQDIjgDIjwDIkADIkQDIkgDIkwDIlADIlQDIlgDIlwDImADImQDImgDImwDIngDInwDIogDIpgDIpwDIqADIqQDIqgDIqwDIrADIrQDIrgDIrwDIsADIsQDIsgDIswDItwDJkADJkQDJkgDJlADJlQDJmQDJmwDJnADJnwDJoQDJowDJpQDJpgDJqADJqQDJqgDJqwDJrQDJrwDJsADJsQDJsgDJswDJtADJtQDJuADJuQDJuwDKgQDKggDKgwDKiQDKigDKiwDKjADKkADKkQDKkgDKlQDKnQDKnwDKuQDKvG4AzIAAzIEAzIjMgQDMkwDOhgDOiADOiQDOigDOjADOjgDOjwDOkADOkQDOkgDOkwDOlADOlQDOlgDOlwDOmADOmQDOmgDOmwDOnADOnQDOngDOnwDOoADOoQDOowDOpADOpQDOpgDOpwDOqADOqQDOqgDOqwDOrADOrQDOrgDOrwDOsADOsQDOsgDOswDOtADOtQDOtgDOtwDOuADOuQDOugDOuwDOvADOvEEAzrxGAM68VgDOvFcAzrxnAM68bADOvG0AzrxzAM69AM6+AM6/AM+AAM+BAM+CAM+DAM+EAM+FAM+GAM+HAM+IAM+JAM+KAM+LAM+MAM+NAM+OAM+cAM+dANCAANCBANCDANCHANCMANCNANCOANCZANC5ANC9ANGKANGMANGQANGRANGTANGXANGcANGdANGeANG2ANG3ANOBANOCANOQANORANOSANOTANOWANOXANOaANObANOcANOdANOeANOfANOiANOjANOkANOlANOmANOnANOqANOrANOsANOtANOuANOvANOwANOxANOyANOzANO0ANO1ANO4ANO5ANWl1oIA1bTVpQDVtNWrANW01a0A1bTVtgDVvtW2ANeQANeQ1rcA15DWuADXkNa8ANeQ15wA15EA15HWvADXkda/ANeSANeS1rwA15MA15PWvADXlADXlNa8ANeV1rkA15XWvADXlta8ANeY1rwA15nWtADXmda8ANea1rwA15sA15vWvADXm9a/ANecANec1rwA150A157WvADXoNa8ANeh1rwA16IA16PWvADXpNa8ANek1r8A16bWvADXp9a8ANeoANeo1rwA16nWvADXqda814EA16nWvNeCANep14EA16nXggDXqgDXqta8ANey1rcA2KEA2KIA2KMA2KQA2KUA2KYA2KbYpwDYptisANim2K0A2KbYrgDYptixANim2LIA2KbZhQDYptmGANim2YcA2KbZiADYptmJANim2YoA2KbbhgDYptuHANim24gA2KbbkADYptuVANinANin2YPYqNixANin2YTZhNmHANin2YsA2KfZtADYqADYqNisANio2K0A2KjYrdmKANio2K4A2KjYrtmKANio2LEA2KjYsgDYqNmFANio2YYA2KjZhwDYqNmJANio2YoA2KkA2KoA2KrYrADYqtis2YUA2KrYrNmJANiq2KzZigDYqtitANiq2K3YrADYqtit2YUA2KrYrgDYqtiu2YUA2KrYrtmJANiq2K7ZigDYqtixANiq2LIA2KrZhQDYqtmF2KwA2KrZhditANiq2YXYrgDYqtmF2YkA2KrZhdmKANiq2YYA2KrZhwDYqtmJANiq2YoA2KsA2KvYrADYq9ixANir2LIA2KvZhQDYq9mGANir2YcA2KvZiQDYq9mKANisANis2K0A2KzYrdmJANis2K3ZigDYrNmEINis2YTYp9mE2YcA2KzZhQDYrNmF2K0A2KzZhdmJANis2YXZigDYrNmJANis2YoA2K0A2K3YrADYrdis2YoA2K3ZhQDYrdmF2YkA2K3ZhdmKANit2YkA2K3ZigDYrgDYrtisANiu2K0A2K7ZhQDYrtmJANiu2YoA2K8A2LAA2LDZsADYsQDYsdiz2YjZhADYsdmwANix24zYp9mEANiyANizANiz2KwA2LPYrNitANiz2KzZ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AOGEjQDhhI4A4YSPAOGEkADhhJEA4YSSAOGElADhhJUA4YSaAOGEnADhhJ0A4YSeAOGEoADhhKEA4YSiAOGEowDhhKcA4YSpAOGEqwDhhKwA4YStAOGErgDhhK8A4YSyAOGEtgDhhYAA4YWHAOGFjADhhZcA4YWYAOGFmQDhhaAA4YWhAOGFogDhhaMA4YWkAOGFpQDhhaYA4YWnAOGFqADhhakA4YWqAOGFqwDhhawA4YWtAOGFrgDhha8A4YWwAOGFsQDhhbIA4YWzAOGFtADhhbUA4YaEAOGGhQDhhogA4YaRAOGGkgDhhpQA4YaeAOGGoQDhhqoA4YasAOGGrQDhhrAA4YaxAOGGsgDhhrMA4Ya0AOGGtQDhh4cA4YeIAOGHjADhh44A4YeTAOGHlwDhh5kA4YedAOGHnwDhh7EA4YeyAOGshgDhrIgA4ayKAOGsjADhrI4A4aySAOGsuwDhrL0A4a2AAOGtgQDhrYMA4bSCAOG0lgDhtJcA4bScAOG0nQDhtKUA4bW7AOG2hQDhuIAA4biBAOG4ggDhuIMA4biEAOG4hQDhuIYA4biHAOG4iADhuIkA4biKAOG4iwDhuIwA4biNAOG4jgDhuI8A4biQAOG4kQDhuJIA4biTAOG4lADhuJUA4biWAOG4lwDhuJgA4biZAOG4mgDhuJsA4bicAOG4nQDhuJ4A4bifAOG4oADhuKEA4biiAOG4owDhuKQA4bilAOG4pgDhuKcA4bioAOG4qQDhuKoA4birAOG4rADhuK0A4biuAOG4rwDhuLAA4bixAOG4sgDhuLMA4bi0AOG4tQDhuLYA4bi3AOG4uADhuLkA4bi6AOG4uwDhuLwA4bi9AOG4vgDhuL8A4bmAAOG5gQDhuYIA4bmDAOG5hADhuYUA4bmGAOG5hwDhuYgA4bmJAOG5igDhuYsA4bmMAOG5jQDhuY4A4bmPAOG5kADhuZEA4bmSAOG5kwDhuZQA4bmVAOG5lgDhuZcA4bmYAOG5mQDhuZoA4bmbAOG5nADhuZ0A4bmeAOG5nwDhuaAA4bmhAOG5ogDhuaMA4bmkAOG5pQDhuaYA4bmnAOG5qADhuakA4bmqAOG5qwDhuawA4bmtAOG5rgDhua8A4bmwAOG5sQDhubIA4bmzAOG5tADhubUA4bm2AOG5twDhubgA4bm5AOG5ugDhubsA4bm8AOG5vQDhub4A4bm/AOG6gADhuoEA4bqCAOG6gwDhuoQA4bqFAOG6hgDhuocA4bqIAOG6iQDhuooA4bqLAOG6jADhuo0A4bqOAOG6jwDhupAA4bqRAOG6kgDhupMA4bqUAOG6lQDhupYA4bqXAOG6mADhupkA4bqgAOG6oQDhuqIA4bqjAOG6pADhuqUA4bqmAOG6pwDhuqgA4bqpAOG6qgDhuqsA4bqsAOG6rQDhuq4A4bqvAOG6sADhurEA4bqyAOG6swDhurQA4bq1AOG6tgDhurcA4bq4AOG6uQDhuroA4bq7AOG6vADhur0A4bq+AOG6vwDhu4AA4buBAOG7ggDhu4MA4buEAOG7hQDhu4YA4buHAOG7iADhu4kA4buKAOG7iwDhu4wA4buNAOG7jgDhu48A4buQAOG7kQDhu5IA4buTAOG7lADhu5UA4buWAOG7lwDhu5gA4buZAOG7mgDhu5sA4bucAOG7nQDhu54A4bufAOG7oADhu6EA4buiAOG7owDhu6QA4bulAOG7pgDhu6cA4buoAOG7qQDhu6oA4burAOG7rADhu60A4buuAOG7rwDhu7AA4buxAOG7sgDhu7MA4bu0AOG7tQDhu7YA4bu3AOG7uADhu7kA4byAAOG8gQDhvIIA4byDAOG8hADhvIUA4byGAOG8hwDhvIgA4byJAOG8igDhvIsA4byMAOG8jQDhvI4A4byPAOG8kADhvJEA4bySAOG8kwDhvJQA4byVAOG8mADhvJkA4byaAOG8mwDhvJwA4bydAOG8oADhvKEA4byiAOG8owDhvKQA4bylAOG8pgDhvKcA4byoAOG8qQDhvKoA4byrAOG8rADhvK0A4byuAOG8rwDhvLAA4byxAOG8sgDhvLMA4by0AOG8tQDhvLYA4by3AOG8uADhvLkA4by6AOG8uwDhvLwA4by9AOG8vgDhvL8A4b2AAOG9gQDhvYIA4b2DAOG9hADhvYUA4b2IAOG9iQDhvYoA4b2LAOG9jADhvY0A4b2QAOG9kQDhvZIA4b2TAOG9lADhvZUA4b2WAOG9lwDhvZkA4b2bAOG9nQDhvZ8A4b2gAOG9oQDhvaIA4b2jAOG9pADhvaUA4b2mAOG9pwDhvagA4b2pAOG9qgDhvasA4b2sAOG9rQDhva4A4b2vAOG9sADhvbIA4b20AOG9tgDhvbgA4b26AOG9vADhvoAA4b6BAOG+ggDhvoMA4b6EAOG+hQDhvoYA4b6HAOG+iADhvokA4b6KAOG+iwDhvowA4b6NAOG+jgDhvo8A4b6QAOG+kQDhvpIA4b6TAOG+lADhvpUA4b6WAOG+lwDhvpgA4b6ZAOG+mgDhvpsA4b6cAOG+nQDhvp4A4b6fAOG+oADhvqEA4b6iAOG+owDhvqQA4b6lAOG+pgDhvqcA4b6oAOG+qQDhvqoA4b6rAOG+rADhvq0A4b6uAOG+rwDhvrAA4b6xAOG+sgDhvrMA4b60AOG+tgDhvrcA4b64AOG+uQDhvroA4b68AOG/ggDhv4MA4b+EAOG/hgDhv4cA4b+IAOG/igDhv4wA4b+QAOG/kQDhv5IA4b+WAOG/lwDhv5gA4b+ZAOG/mgDhv6AA4b+hAOG/ogDhv6QA4b+lAOG/pgDhv6cA4b+oAOG/qQDhv6oA4b+sAOG/sgDhv7MA4b+0AOG/tgDhv7cA4b+4AOG/ugDhv7wA4oCQAOKAkwDigJQA4oCy4oCyAOKAsuKAsuKAsgDigLLigLLigLLigLIA4oC14oC1AOKAteKAteKAtQDigqkA4oaQAOKGkQDihpIA4oaTAOKGmgDihpsA4oauAOKHjQDih44A4oePAOKIggDiiIQA4oiHAOKIiQDiiIwA4oiRAOKIkgDiiKQA4oimAOKIq+KIqwDiiKviiKviiKsA4oir4oir4oir4oirAOKIruKIrgDiiK7iiK7iiK4A4omBAOKJhADiiYcA4omJAOKJoADiiaIA4omtAOKJrgDiia8A4omwAOKJsQDiibQA4om1AOKJuADiibkA4oqAAOKKgQDiioQA4oqFAOKKiADiiokA4oqsAOKKrQDiiq4A4oqvAOKLoADii6EA4ouiAOKLowDii6oA4ourAOKLrADii60A4pSCAOKWoADil4sA4qaFAOKmhgDiq53MuADitaEA44CBAOOAggDjgIgA44CJAOOAigDjgIsA44CMAOOAjQDjgI4A44CPAOOAkADjgJEA44CSAOOAlADjgJRT44CVAOOAlOS4ieOAlQDjgJTkuozjgJUA44CU5Yud44CVAOOAlOWuieOAlQDjgJTmiZPjgJUA44CU5pWX44CVAOOAlOacrOOAlQDjgJTngrnjgJUA44CU55uX44CVAOOAlQDjgJYA44CXAOOBjADjgY4A44GQAOOBkgDjgZQA44GWAOOBmADjgZoA44GcAOOBngDjgaAA44GiAOOBpQDjgacA44GpAOOBsADjgbEA44GzAOOBtADjgbYA44G3AOOBuQDjgboA44G744GLAOOBvADjgb0A44KI44KKAOOClADjgpkA44KaAOOCngDjgqEA44KiAOOCouODkeODvOODiADjgqLjg6vjg5XjgqEA44Ki44Oz44Oa44KiAOOCouODvOODqwDjgqMA44KkAOOCpOODi+ODs+OCsADjgqTjg7Pjg4EA44KlAOOCpgDjgqbjgqnjg7MA44KnAOOCqADjgqjjgrnjgq/jg7zjg4kA44Ko44O844Kr44O8AOOCqQDjgqoA44Kq44Oz44K5AOOCquODvOODoADjgqsA44Kr44Kk44OqAOOCq+ODqeODg+ODiADjgqvjg63jg6rjg7wA44KsAOOCrOODreODswDjgqzjg7Pjg54A44KtAOOCreODpeODquODvADjgq3jg60A44Kt44Ot44Kw44Op44OgAOOCreODreODoeODvOODiOODqwDjgq3jg63jg6/jg4Pjg4gA44KuAOOCruOCrADjgq7jg4vjg7wA44Ku44Or44OA44O8AOOCrwDjgq/jg6vjgrzjgqTjg60A44Kv44Ot44O844ONAOOCsADjgrDjg6njg6AA44Kw44Op44Og44OI44OzAOOCsQDjgrHjg7zjgrkA44KyAOOCswDjgrPjgrMA44Kz44OIAOOCs+ODq+ODigDjgrPjg7zjg50A44K0AOOCtQDjgrXjgqTjgq/jg6sA44K144Oz44OB44O844OgAOOCtgDjgrcA44K344Oq44Oz44KwAOOCuADjgrkA44K6AOOCuwDjgrvjg7Pjg4EA44K744Oz44OIAOOCvADjgr0A44K+AOOCvwDjg4AA44OA44O844K5AOODgQDjg4IA44ODAOODhADjg4UA44OGAOODhwDjg4fjgrcA44OIAOODiOODswDjg4kA44OJ44OrAOODigDjg4rjg44A44OLAOODjADjg40A44OOAOODjuODg+ODiADjg48A44OP44Kk44OEAOODkADjg5Djg7zjg6zjg6sA44ORAOODkeODvOOCu+ODs+ODiADjg5Hjg7zjg4QA44OSAOODkwDjg5Pjg6sA44OUAOODlOOCouOCueODiOODqwDjg5Tjgq/jg6sA44OU44KzAOODlQDjg5XjgqHjg6njg4Pjg4kA44OV44Kj44O844OIAOODleODqeODswDjg5YA44OW44OD44K344Kn44OrAOODlwDjg5gA44OY44Kv44K/44O844OrAOODmOODq+ODhADjg5kA44OZ44O844K/AOODmgDjg5rjgr0A44Oa44OL44OSAOODmuODs+OCuQDjg5rjg7zjgrgA44ObAOODm+ODswDjg5vjg7zjg6sA44Ob44O844OzAOODnADjg5zjg6vjg4gA44OdAOODneOCpOODs+ODiADjg53jg7Pjg4kA44OeAOODnuOCpOOCr+ODrQDjg57jgqTjg6sA44Oe44OD44OPAOODnuODq+OCrwDjg57jg7Pjgrfjg6fjg7MA44OfAOODn+OCr+ODreODswDjg5/jg6oA44Of44Oq44OQ44O844OrAOODoADjg6EA44Oh44KsAOODoeOCrOODiOODswDjg6Hjg7zjg4jjg6sA44OiAOODowDjg6QA44Ok44O844OJAOODpOODvOODqwDjg6UA44OmAOODpuOCouODswDjg6cA44OoAOODqQDjg6oA44Oq44OD44OI44OrAOODquODqQDjg6sA44Or44OU44O8AOODq+ODvOODluODqwDjg6wA44Os44OgAOODrOODs+ODiOOCsuODswDjg60A44OvAOODr+ODg+ODiADjg7AA44OxAOODsgDjg7MA44O0AOODtwDjg7gA44O5AOODugDjg7sA44O8AOODvgDjkp4A45K5AOOSuwDjk58A45SVAOObrgDjm7wA456BAOOgrwDjoaIA46G8AOOjhwDjo6MA46ScAOOkugDjqK4A46msAOOrpADjrIgA46yZAOOtiQDjrp0A47CYAOOxjgDjtLMA47aWAOO6rADjurgA47ybAOO/vADkgIgA5ICYAOSAuQDkgYYA5IKWAOSDowDkhK8A5IiCAOSIpwDkiqAA5IyBAOSMtADkjZkA5I+VAOSPmQDkkIsA5JGrAOSUqwDklZ0A5JWhAOSVqwDkl5cA5Je5AOSYtQDkmr4A5JuHAOSmlQDkp6YA5KmuAOSptgDkqrIA5KyzAOSvjgDks44A5LOtAOSzuADktZYA5LiAAOS4gQDkuIMA5LiJAOS4igDkuIsA5LiNAOS4mQDkuKYA5Lio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jQDmr5QA5q+bAOawjwDmsJQA5rC0AOaxjgDmsacA5rKIAOayvwDms4wA5rONAOazpQDms6gA5rSWAOa0mwDmtJ4A5rS0AOa0vgDmtYEA5rWpAOa1qgDmtbcA5rW4AOa2hQDmt4sA5reaAOa3qgDmt7kA5riaAOa4rwDmua4A5rqAAOa6nADmuroA5ruHAOa7iwDmu5EA5rubAOa8jwDmvJQA5ryiAOa8owDmva4A5r+GAOa/qwDmv74A54CbAOeAngDngLkA54GKAOeBqwDngbAA54G3AOeBvQDngpkA54KtAOeDiADng5kA54ShAOeFhQDnhYkA54WuAOeGnADnh44A54eQAOeIkADniJsA54ioAOeIqgDniKsA54i1AOeItgDniLsA54i/AOeJhwDniZAA54mZAOeJmwDniaIA54m5AOeKgADnipUA54qsAOeKrwDni4AA54u8AOeMqgDnjbUA5426AOeOhADnjocA546JAOeOiwDnjqUA546yAOePngDnkIYA55CJAOeQogDnkYcA55GcAOeRqQDnkbEA55KFAOeSiQDnkpgA55OKAOeTnADnk6YA55SGAOeUmADnlJ8A55SkAOeUqADnlLAA55SyAOeUswDnlLcA55S7AOeUvgDnlZkA55WlAOeVsADnlosA55aSAOeXogDnmJAA55idAOeYnwDnmYIA55mpAOeZtgDnmb0A55quAOeavwDnm4oA55ubAOebowDnm6cA55uuAOebtADnnIEA55yeAOecnwDnnYAA552KAOeeiwDnnqcA55+bAOefogDnn7MA56GOAOehqwDnoowA56KRAOejigDno4wA56O7AOekqgDnpLoA56S8AOekvgDnpYgA56WJAOelkADnpZYA56WdAOelngDnpaUA56W/AOemgQDnpo0A56aOAOemjwDnpq4A56a4AOemvgDnp4oA56eYAOenqwDnqJwA56mAAOepigDnqY8A56m0AOepugDnqoEA56qxAOeriwDnq64A56u5AOesoADnro8A56+AAOevhgDnr4kA57C+AOexoADnsbMA57G7AOeykgDnsr4A57OSAOezlgDns6MA57OnAOezqADns7gA57SAAOe0kADntKIA57SvAOe1ggDntZsA57WjAOe2oADntr4A57eHAOe3tADnuIIA57iJAOe4twDnuYEA57mFAOe8tgDnvL4A572RAOe9sgDnvbkA5726AOe+hQDnvooA576VAOe+mgDnvr0A57+6AOiAgQDogIUA6ICMAOiAkgDogLMA6IGGAOiBoADoga8A6IGwAOiBvgDogb8A6IKJAOiCiwDogq0A6IKyAOiEgwDohL4A6IeYAOiHowDoh6gA6IeqAOiHrQDoh7MA6Ie8AOiIgQDoiIQA6IiMAOiImADoiJsA6IifAOiJrgDoia8A6ImyAOiJuADoibkA6IqLAOiKkQDoip0A6IqxAOiKswDoir0A6IulAOiLpgDojJ0A6IyjAOiMtgDojZIA6I2TAOiNowDojq0A6I69AOiPiQDoj4oA6I+MAOiPnADoj6cA6I+vAOiPsQDokL0A6JGJAOiRlwDok64A6JOxAOiTswDok7wA6JSWAOiVpADol40A6Je6AOiYhgDomJIA6JitAOiYvwDomY0A6JmQAOiZnADomacA6JmpAOiZqwDomogA6JqpAOibogDonI4A6JyoAOidqwDonbkA6J6GAOieugDon6EA6KCBAOignwDooYAA6KGMAOihoADooaMA6KOCAOijjwDoo5cA6KOeAOijoQDoo7gA6KO6AOikkADopYEA6KWkAOilvgDopoYA6KaLAOimlgDop5IA6KejAOiogADoqqAA6KqqAOiqvwDoq4sA6KuSAOirlgDoq60A6Ku4AOirvgDorIEA6Ky5AOitmADoroAA6K6KAOiwtwDosYYA6LGIAOixlQDosbgA6LKdAOiyoQDosqkA6LKrAOizgQDos4IA6LOHAOiziADos5MA6LSIAOi0mwDotaQA6LWwAOi1twDotrMA6La8AOi3iwDot68A6LewAOi6qwDou4oA6LuUAOi8pgDovKoA6Ly4AOi8uwDovaIA6L6bAOi+ngDovrAA6L61AOi+tgDpgKMA6YC4AOmBigDpgakA6YGyAOmBvADpgo8A6YKRAOmClADpg44A6YOeAOmDsQDpg70A6YSRAOmEmwDphYkA6YWqAOmGmQDphrQA6YeGAOmHjADph48A6YeRAOmItADpiLgA6Ym2AOmJvADpi5cA6YuYAOmMhADpjYoA6Y+5AOmQlQDplbcA6ZaAAOmWiwDplq0A6Za3AOmYnADpmK4A6ZmLAOmZjQDpmbUA6Zm4AOmZvADpmoYA6ZqjAOmatgDpmrcA6Zq4AOmauQDpm4MA6ZuiAOmbowDpm6gA6Zu2AOmbtwDpnKMA6ZyyAOmdiADpnZEA6Z2WAOmdngDpnaIA6Z2pAOmfiwDpn5sA6Z+gAOmfrQDpn7MA6Z+/AOmggQDpoIUA6aCLAOmgmADpoKkA6aC7AOmhngDpoqgA6aObAOmjnwDpo6IA6aOvAOmjvADppKgA6aSpAOmmlgDpppkA6aanAOmmrADpp4IA6aexAOmnvgDpqaoA6aqoAOmrmADpq58A6aySAOmspQDprK8A6ayyAOmsvADprZoA6a2vAOmxgADpsZcA6bOlAOmzvQDptacA6ba0AOm3ugDpuJ4A6bm1AOm5vwDpupcA6bqfAOm6pQDpursA6buDAOm7jQDpu44A6buRAOm7uQDpu70A6bu+AOm8hQDpvI4A6byPAOm8kwDpvJYA6bygAOm8uwDpvYMA6b2KAOm9kgDpvo0A6b6OAOm+nADpvp8A6b6gAOqcpwDqna8A6qy3AOqtkgDqsIAA6rCBAOqwggDqsIMA6rCEAOqwhQDqsIYA6rCHAOqwiADqsIkA6rCKAOqwiwDqsIwA6rCNAOqwjgDqsI8A6rCQAOqwkQDqsJIA6rCTAOqwlADqsJUA6rCWAOqwlwDqsJgA6rCZAOqwmgDqsJsA6rCcAOqwnQDqsJ4A6rCfAOqwoADqsKEA6rCiAOqwowDqsKQA6rClAOqwpgDqsKcA6rCoAOqwqQDqsKoA6rCrAOqwrADqsK0A6rCuAOqwrwDqsLAA6rCxAOqwsgDqsLMA6rC0AOqwtQDqsLYA6rC3AOqwuADqsLkA6rC6AOqwuwDqsLwA6rC9AOqwvgDqsL8A6rGAAOqxgQDqsYIA6rGDAOqxhADqsYUA6rGGAOqxhwDqsYgA6rGJAOqxigDqsYsA6rGMAOqxjQDqsY4A6rGPAOqxkADqsZEA6rGSAOqxkwDqsZQA6rGVAOqxlgDqsZcA6rGYAOqxmQDqsZoA6rGbAOqxnADqsZ0A6rGeAOqxnwDqsaAA6rGhAOqxogDqsaMA6rGkAOqxpQDqsaYA6rGnAOqxqADqsakA6rGqAOqxqwDqsawA6rGtAOqxrgDqsa8A6rGwAOqxsQDqsbIA6rGzAOqxtADqsbUA6rG2AOqxtwDqsbgA6rG5AOqxugDqsbsA6rG8AOqxvQDqsb4A6rG/AOqygADqsoEA6rKCAOqygwDqsoQA6rKFAOqyhgDqsocA6rKIAOqyiQDqsooA6rKLAOqyjADqso0A6rKOAOqyjwDqspAA6rKRAOqykgDqspMA6rKUAOqylQDqspYA6rKXAOqymADqspkA6rKaAOqymwDqspwA6rKdAOqyngDqsp8A6rKgAOqyoQDqsqIA6rKjAOqypADqsqUA6rKmAOqypwDqsqgA6rKpAOqyqgDqsqsA6rKsAOqyrQDqsq4A6rKvAOqysADqsrEA6rKyAOqyswDqsrQA6rK1AOqytgDqsrcA6rK4AOqyuQDqsroA6rK7AOqyvADqsr0A6rK+AOqyvwDqs4AA6rOBAOqzggDqs4MA6rOEAOqzhQDqs4YA6rOHAOqziADqs4kA6rOKAOqziwDqs4wA6rONAOqzjgDqs48A6rOQAOqzkQDqs5IA6rOTAOqzlADqs5UA6rOWAOqzlwDqs5gA6rOZAOqzmgDqs5sA6rOcAOqznQDqs54A6rOfAOqzoADqs6EA6rOiAOqzowDqs6QA6rOlAOqzpgDqs6cA6rOoAOqzqQDqs6oA6rOrAOqzrADqs60A6rOuAOqzrwDqs7AA6rOxAOqzsgDqs7MA6rO0AOqztQDqs7YA6rO3AOqzuADqs7kA6rO6AOqzuwDqs7wA6rO9AOqzvgDqs78A6rSAAOq0gQDqtIIA6rSDAOq0hADqtIUA6rSGAOq0hwDqtIgA6rSJAOq0igDqtIsA6rSMAOq0jQDqtI4A6rSPAOq0kADqtJEA6rSSAOq0kwDqtJQA6rSVAOq0lgDqtJcA6rSYAOq0mQDqtJoA6rSbAOq0nADqtJ0A6rSeAOq0nwDqtKAA6rShAOq0ogDqtKMA6rSkAOq0pQDqtKYA6rSnAOq0qADqtKkA6rSqAOq0qwDqtKwA6rStAOq0rgDqtK8A6rSwAOq0sQDqtLIA6rSzAOq0tADqtLUA6rS2AOq0twDqtLgA6rS5AOq0ugDqtLsA6rS8AOq0vQDqtL4A6rS/AOq1gADqtYEA6rWCAOq1gwDqtYQA6rWFAOq1hgDqtYcA6rWIAOq1iQDqtYoA6rWLAOq1jADqtY0A6rWOAOq1jwDqtZAA6rWRAOq1kgDqtZMA6rWUAOq1lQDqtZYA6rWXAOq1mADqtZkA6rWaAOq1mwDqtZwA6rWdAOq1ngDqtZ8A6rWgAOq1oQDqtaIA6rWjAOq1pADqtaUA6rWmAOq1pwDqtagA6rWpAOq1qgDqtasA6rWsAOq1rQDqta4A6rWvAOq1sADqtbEA6rWyAOq1swDqtbQA6rW1AOq1tgDqtbcA6rW4AOq1uQDqtboA6rW7AOq1vADqtb0A6rW+AOq1vwDqtoAA6raBAOq2ggDqtoMA6raEAOq2hQDqtoYA6raHAOq2iADqtokA6raKAOq2iwDqtowA6raNAOq2jgDqto8A6raQAOq2kQDqtpIA6raTAOq2lADqtpUA6raWAOq2lwDqtpgA6raZAOq2mgDqtpsA6racAOq2nQDqtp4A6rafAOq2oADqtqEA6raiAOq2owDqtqQA6ralAOq2pgDqtqcA6raoAOq2qQDqtqoA6rarAOq2rADqtq0A6rauAOq2rwDqtrAA6raxAOq2sgDqtrMA6ra0AOq2tQDqtrYA6ra3AOq2uADqtrkA6ra6AOq2uwDqtrwA6ra9AOq2vgDqtr8A6reAAOq3gQDqt4IA6reDAOq3hADqt4UA6reGAOq3hwDqt4gA6reJAOq3igDqt4sA6reMAOq3jQDqt44A6rePAOq3kADqt5EA6reSAOq3kwDqt5QA6reVAOq3lgDqt5cA6reYAOq3mQDqt5oA6rebAOq3nADqt50A6reeAOq3nwDqt6AA6rehAOq3ogDqt6MA6rekAOq3pQDqt6YA6renAOq3qADqt6kA6reqAOq3qwDqt6wA6retAOq3rgDqt68A6rewAOq3sQDqt7IA6rezAOq3tADqt7UA6re2AOq3twDqt7gA6re5AOq3ugDqt7sA6re8AOq3vQDqt74A6re/AOq4gADquIEA6riCAOq4gwDquIQA6riFAOq4hgDquIcA6riIAOq4iQDquIoA6riLAOq4jADquI0A6riOAOq4jwDquJAA6riRAOq4kgDquJMA6riUAOq4lQDquJYA6riXAOq4mADquJkA6riaAOq4mwDquJwA6ridAOq4ngDquJ8A6rigAOq4oQDquKIA6rijAOq4pADquKUA6rimAOq4pwDquKgA6ripAOq4qgDquKsA6risAOq4rQDquK4A6rivAOq4sADquLEA6riyAOq4swDquLQA6ri1AOq4tgDquLcA6ri4AOq4uQDquLoA6ri7AOq4vADquL0A6ri+AOq4vwDquYAA6rmBAOq5ggDquYMA6rmEAOq5hQDquYYA6rmHAOq5iADquYkA6rmKAOq5iwDquYwA6rmNAOq5jgDquY8A6rmQAOq5kQDquZIA6rmTAOq5lADquZUA6rmWAOq5lwDquZgA6rmZAOq5mgDquZsA6rmcAOq5nQDquZ4A6rmfAOq5oADquaEA6rmiAOq5owDquaQA6rmlAOq5pgDquacA6rmoAOq5qQDquaoA6rmrAOq5rADqua0A6rmuAOq5rwDqubAA6rmxAOq5sgDqubMA6rm0AOq5tQDqubYA6rm3AOq5uADqubkA6rm6AOq5uwDqubwA6rm9AOq5vgDqub8A6rqAAOq6gQDquoIA6rqDAOq6hADquoUA6rqGAOq6hwDquogA6rqJAOq6igDquosA6rqMAOq6jQDquo4A6rqPAOq6kADqupEA6rqSAOq6kwDqupQA6rqVAOq6lgDqupcA6rqYAOq6mQDqupoA6rqbAOq6nADqup0A6rqeAOq6nwDquqAA6rqhAOq6ogDquqMA6rqkAOq6pQDquqYA6rqnAOq6qADquqkA6rqqAOq6qwDquqwA6rqtAOq6rgDquq8A6rqwAOq6sQDqurIA6rqzAOq6tADqurUA6rq2AOq6twDqurgA6rq5AOq6ugDqursA6rq8AOq6vQDqur4A6rq/AOq7gADqu4EA6ruCAOq7gwDqu4QA6ruFAOq7hgDqu4cA6ruIAOq7iQDqu4oA6ruLAOq7jADqu40A6ruOAOq7jwDqu5AA6ruRAOq7kgDqu5MA6ruUAOq7lQDqu5YA6ruXAOq7mADqu5kA6ruaAOq7mwDqu5wA6rudAOq7ngDqu58A6rugAOq7oQDqu6IA6rujAOq7pADqu6UA6rumAOq7pwDqu6gA6rupAOq7qgDqu6sA6rusAOq7rQDqu64A6ruvAOq7sADqu7EA6ruyAOq7swDqu7QA6ru1AOq7tgDqu7cA6ru4AOq7uQDqu7oA6ru7AOq7vADqu70A6ru+AOq7vwDqvIAA6ryBAOq8ggDqvIMA6ryEAOq8hQDqvIYA6ryHAOq8iADqvIkA6ryKAOq8iwDqvIwA6ryNAOq8jgDqvI8A6ryQAOq8kQDqvJIA6ryTAOq8lADqvJUA6ryWAOq8lwDqvJgA6ryZAOq8mgDqvJsA6rycAOq8nQDqvJ4A6ryfAOq8oADqvKEA6ryiAOq8owDqvKQA6rylAOq8pgDqvKcA6ryoAOq8qQDqvKoA6ryrAOq8rADqvK0A6ryuAOq8rwDqvLAA6ryxAOq8sgDqvLMA6ry0AOq8tQDqvLYA6ry3AOq8uADqvLkA6ry6AOq8uwDqvLwA6ry9AOq8vgDqvL8A6r2AAOq9gQDqvYIA6r2DAOq9hADqvYUA6r2GAOq9hwDqvYgA6r2JAOq9igDqvYsA6r2MAOq9jQDqvY4A6r2PAOq9kADqvZEA6r2SAOq9kwDqvZQA6r2VAOq9lgDqvZcA6r2YAOq9mQDqvZoA6r2bAOq9nADqvZ0A6r2eAOq9nwDqvaAA6r2hAOq9ogDqvaMA6r2kAOq9pQDqvaYA6r2nAOq9qADqvakA6r2qAOq9qwDqvawA6r2tAOq9rgDqva8A6r2wAOq9sQDqvbIA6r2zAOq9tADqvbUA6r22AOq9twDqvbgA6r25AOq9ugDqvbsA6r28AOq9vQDqvb4A6r2/AOq+gADqvoEA6r6CAOq+gwDqvoQA6r6FAOq+hgDqvocA6r6IAOq+iQDqvooA6r6LAOq+jADqvo0A6r6OAOq+jwDqvpAA6r6RAOq+kgDqvpMA6r6UAOq+lQDqvpYA6r6XAOq+mADqvpkA6r6aAOq+mwDqvpwA6r6dAOq+ngDqvp8A6r6gAOq+oQDqvqIA6r6jAOq+pADqvqUA6r6mAOq+pwDqvqgA6r6pAOq+qgDqvqsA6r6sAOq+rQDqvq4A6r6vAOq+sADqvrEA6r6yAOq+swDqvrQA6r61AOq+tgDqvrcA6r64AOq+uQDqvroA6r67AOq+vADqvr0A6r6+AOq+vwDqv4AA6r+BAOq/ggDqv4MA6r+EAOq/hQDqv4YA6r+HAOq/iADqv4kA6r+KAOq/iwDqv4wA6r+NAOq/jgDqv48A6r+QAOq/kQDqv5IA6r+TAOq/lADqv5UA6r+WAOq/lwDqv5gA6r+ZAOq/mgDqv5sA6r+cAOq/nQDqv54A6r+fAOq/oADqv6EA6r+iAOq/owDqv6QA6r+lAOq/pgDqv6cA6r+oAOq/qQDqv6oA6r+rAOq/rADqv60A6r+uAOq/rwDqv7AA6r+xAOq/sgDqv7MA6r+0AOq/tQDqv7YA6r+3AOq/uADqv7kA6r+6AOq/uwDqv7wA6r+9AOq/vgDqv78A64CAAOuAgQDrgIIA64CDAOuAhADrgIUA64CGAOuAhwDrgIgA64CJAOuAigDrgIsA64CMAOuAjQDrgI4A64CPAOuAkADrgJEA64CSAOuAkwDrgJQA64CVAOuAlgDrgJcA64CYAOuAmQDrgJoA64CbAOuAnADrgJ0A64CeAOuAnwDrgKAA64ChAOuAogDrgKMA64CkAOuApQDrgKYA64CnAOuAqADrgKkA64CqAOuAqwDrgKwA64CtAOuArgDrgK8A64CwAOuAsQDrgLIA64CzAOuAtADrgLUA64C2AOuAtwDrgLgA64C5AOuAugDrgLsA64C8AOuAvQDrgL4A64C/AOuBgADrgYEA64GCAOuBgwDrgYQA64GFAOuBhgDrgYcA64GIAOuBiQDrgYoA64GLAOuBjADrgY0A64GOAOuBjwDrgZAA64GRAOuBkgDrgZMA64GUAOuBlQDrgZYA64GXAOuBmADrgZkA64GaAOuBmwDrgZwA64GdAOuBngDrgZ8A64GgAOuBoQDrgaIA64GjAOuBpADrgaUA64GmAOuBpwDrgagA64GpAOuBqgDrgasA64GsAOuBrQDrga4A64GvAOuBsADrgbEA64GyAOuBswDrgbQA64G1AOuBtgDrgbcA64G4AOuBuQDrgboA64G7AOuBvADrgb0A64G+AOuBvwDrgoAA64KBAOuCggDrgoMA64KEAOuChQDrgoYA64KHAOuCiADrgokA64KKAOuCiwDrgowA64KNAOuCjgDrgo8A64KQAOuCkQDrgpIA64KTAOuClADrgpUA64KWAOuClwDrgpgA64KZAOuCmgDrgpsA64KcAOuCnQDrgp4A64KfAOuCoADrgqEA64KiAOuCowDrgqQA64KlAOuCpgDrgqcA64KoAOuCqQDrgqoA64KrAOuCrADrgq0A64KuAOuCrwDrgrAA64KxAOuCsgDrgrMA64K0AOuCtQDrgrYA64K3AOuCuADrgrkA64K6AOuCuwDrgrwA64K9AOuCvgDrgr8A64OAAOuDgQDrg4IA64ODAOuDhADrg4UA64OGAOuDhwDrg4gA64OJAOuDigDrg4sA64OMAOuDjQDrg44A64OPAOuDkADrg5EA64OSAOuDkwDrg5QA64OVAOuDlgDrg5cA64OYAOuDmQDrg5oA64ObAOuDnADrg50A64OeAOuDnwDrg6AA64OhAOuDogDrg6MA64OkAOuDpQDrg6YA64OnAOuDqADrg6kA64OqAOuDqwDrg6wA64OtAOuDrgDrg68A64OwAOuDsQDrg7IA64OzAOuDtADrg7UA64O2AOuDtwDrg7gA64O5AOuDugDrg7sA64O8AOuDvQDrg74A64O/AOuEgADrhIEA64SCAOuEgwDrhIQA64SFAOuEhgDrhIcA64SIAOuEiQDrhIoA64SLAOuEjADrhI0A64SOAOuEjwDrhJAA64SRAOuEkgDrhJMA64SUAOuElQDrhJYA64SXAOuEmADrhJkA64SaAOuEmwDrhJwA64SdAOuEngDrhJ8A64SgAOuEoQDrhKIA64SjAOuEpADrhKUA64SmAOuEpwDrhKgA64SpAOuEqgDrhKsA64SsAOuErQDrhK4A64SvAOuEsADrhLEA64SyAOuEswDrhLQA64S1AOuEtgDrhLcA64S4AOuEuQDrhLoA64S7AOuEvADrhL0A64S+AOuEvwDrhYAA64WBAOuFggDrhYMA64WEAOuFhQDrhYYA64WHAOuFiADrhYkA64WKAOuFiwDrhYwA64WNAOuFjgDrhY8A64WQAOuFkQDrhZIA64WTAOuFlADrhZUA64WWAOuFlwDrhZgA64WZAOuFmgDrhZsA64WcAOuFnQDrhZ4A64WfAOuFoADrhaEA64WiAOuFowDrhaQA64WlAOuFpgDrhacA64WoAOuFqQDrhaoA64WrAOuFrADrha0A64WuAOuFrwDrhbAA64WxAOuFsgDrhbMA64W0AOuFtQDrhbYA64W3AOuFuADrhbkA64W6AOuFuwDrhbwA64W9AOuFvgDrhb8A64aAAOuGgQDrhoIA64aDAOuGhADrhoUA64aGAOuGhwDrhogA64aJAOuGigDrhosA64aMAOuGjQDrho4A64aPAOuGkADrhpEA64aSAOuGkwDrhpQA64aVAOuGlgDrhpcA64aYAOuGmQDrhpoA64abAOuGnADrhp0A64aeAOuGnwDrhqAA64ahAOuGogDrhqMA64akAOuGpQDrhqYA64anAOuGqADrhqkA64aqAOuGqwDrhqwA64atAOuGrgDrhq8A64awAOuGsQDrhrIA64azAOuGtADrhrUA64a2AOuGtwDrhrgA64a5AOuGugDrhrsA64a8AOuGvQDrhr4A64a/AOuHgADrh4EA64eCAOuHgwDrh4QA64eFAOuHhgDrh4cA64eIAOuHiQDrh4oA64eLAOuHjADrh40A64eOAOuHjwDrh5AA64eRAOuHkgDrh5MA64eUAOuHlQDrh5YA64eXAOuHmADrh5kA64eaAOuHmwDrh5wA64edAOuHngDrh58A64egAOuHoQDrh6IA64ejAOuHpADrh6UA64emAOuHpwDrh6gA64epAOuHqgDrh6sA64esAOuHrQDrh64A64evAOuHsADrh7EA64eyAOuHswDrh7QA64e1AOuHtgDrh7cA64e4AOuHuQDrh7oA64e7AOuHvADrh70A64e+AOuHvwDriIAA64iBAOuIggDriIMA64iEAOuIhQDriIYA64iHAOuIiADriIkA64iKAOuIiwDriIwA64iNAOuIjgDriI8A64iQAOuIkQDriJIA64iTAOuIlADriJUA64iWAOuIlwDriJgA64iZAOuImgDriJsA64icAOuInQDriJ4A64ifAOuIoADriKEA64iiAOuIowDriKQA64ilAOuIpgDriKcA64ioAOuIqQDriKoA64irAOuIrADriK0A64iuAOuIrwDriLAA64ixAOuIsgDriLMA64i0AOuItQDriLYA64i3AOuIuADriLkA64i6AOuIuwDriLwA64i9AOuIvgDriL8A64mAAOuJgQDriYIA64mDAOuJhADriYUA64mGAOuJhwDriYgA64mJAOuJigDriYsA64mMAOuJjQDriY4A64mPAOuJkADriZEA64mSAOuJkwDriZQA64mVAOuJlgDriZcA64mYAOuJmQDriZoA64mbAOuJnADriZ0A64meAOuJnwDriaAA64mhAOuJogDriaMA64mkAOuJpQDriaYA64mnAOuJqADriakA64mqAOuJqwDriawA64mtAOuJrgDria8A64mwAOuJsQDribIA64mzAOuJtADribUA64m2AOuJtwDribgA64m5AOuJugDribsA64m8AOuJvQDrib4A64m/AOuKgADrioEA64qCAOuKgwDrioQA64qFAOuKhgDriocA64qIAOuKiQDriooA64qLAOuKjADrio0A64qOAOuKjwDripAA64qRAOuKkgDripMA64qUAOuKlQDripYA64qXAOuKmADripkA64qaAOuKmwDripwA64qdAOuKngDrip8A64qgAOuKoQDriqIA64qjAOuKpADriqUA64qmAOuKpwDriqgA64qpAOuKqgDriqsA64qsAOuKrQDriq4A64qvAOuKsADrirEA64qyAOuKswDrirQA64q1AOuKtgDrircA64q4AOuKuQDriroA64q7AOuKvADrir0A64q+AOuKvwDri4AA64uBAOuLggDri4MA64uEAOuLhQDri4YA64uHAOuLiADri4kA64uKAOuLiwDri4wA64uNAOuLjgDri48A64uQAOuLkQDri5IA64uTAOuLlADri5UA64uWAOuLlwDri5gA64uZAOuLmgDri5sA64ucAOuLnQDri54A64ufAOuLoADri6EA64uiAOuLowDri6QA64ulAOuLpgDri6cA64uoAOuLqQDri6oA64urAOuLrADri60A64uuAOuLrwDri7AA64uxAOuLsgDri7MA64u0AOuLtQDri7YA64u3AOuLuADri7kA64u6AOuLuwDri7wA64u9AOuLvgDri78A64yAAOuMgQDrjIIA64yDAOuMhADrjIUA64yGAOuMhwDrjIgA64yJAOuMigDrjIsA64yMAOuMjQDrjI4A64yPAOuMkADrjJEA64ySAOuMkwDrjJQA64yVAOuMlgDrjJcA64yYAOuMmQDrjJoA64ybAOuMnADrjJ0A64yeAOuMnwDrjKAA64yhAOuMogDrjKMA64ykAOuMpQDrjKYA64ynAOuMqADrjKkA64yqAOuMqwDrjKwA64ytAOuMrgDrjK8A64ywAOuMsQDrjLIA64yzAOuMtADrjLUA64y2AOuMtwDrjLgA64y5AOuMugDrjLsA64y8AOuMvQDrjL4A64y/AOuNgADrjYEA642CAOuNgwDrjYQA642FAOuNhgDrjYcA642IAOuNiQDrjYoA642LAOuNjADrjY0A642OAOuNjwDrjZAA642RAOuNkgDrjZMA642UAOuNlQDrjZYA642XAOuNmADrjZkA642aAOuNmwDrjZwA642dAOuNngDrjZ8A642gAOuNoQDrjaIA642jAOuNpADrjaUA642mAOuNpwDrjagA642pAOuNqgDrjasA642sAOuNrQDrja4A642vAOuNsADrjbEA642yAOuNswDrjbQA6421AOuNtgDrjbcA6424AOuNuQDrjboA6427AOuNvADrjb0A642+AOuNvwDrjoAA646BAOuOggDrjoMA646EAOuOhQDrjoYA646HAOuOiADrjokA646KAOuOiwDrjowA646NAOuOjgDrjo8A646QAOuOkQDrjpIA646TAOuOlADrjpUA646WAOuOlwDrjpgA646ZAOuOmgDrjpsA646cAOuOnQDrjp4A646fAOuOoADrjqEA646iAOuOowDrjqQA646lAOuOpgDrjqcA646oAOuOqQDrjqoA646rAOuOrADrjq0A646uAOuOrwDrjrAA646xAOuOsgDrjrMA6460AOuOtQDrjrYA6463AOuOuADrjrkA6466AOuOuwDrjrwA6469AOuOvgDrjr8A64+AAOuPgQDrj4IA64+DAOuPhADrj4UA64+GAOuPhwDrj4gA64+JAOuPigDrj4sA64+MAOuPjQDrj44A64+PAOuPkADrj5EA64+SAOuPkwDrj5QA64+VAOuPlgDrj5cA64+YAOuPmQDrj5oA64+bAOuPnADrj50A64+eAOuPnwDrj6AA64+hAOuPogDrj6MA64+kAOuPpQDrj6YA64+nAOuPqADrj6kA64+qAOuPqwDrj6wA64+tAOuPrgDrj68A64+wAOuPsQDrj7IA64+zAOuPtADrj7UA64+2AOuPtwDrj7gA64+5AOuPugDrj7sA64+8AOuPvQDrj74A64+/AOuQgADrkIEA65CCAOuQgwDrkIQA65CFAOuQhgDrkIcA65CIAOuQiQDrkIoA65CLAOuQjADrkI0A65COAOuQjwDrkJAA65CRAOuQkgDrkJMA65CUAOuQlQDrkJYA65CXAOuQmADrkJkA65CaAOuQmwDrkJwA65CdAOuQngDrkJ8A65CgAOuQoQDrkKIA65CjAOuQpADrkKUA65CmAOuQpwDrkKgA65CpAOuQqgDrkKsA65CsAOuQrQDrkK4A65CvAOuQsADrkLEA65CyAOuQswDrkLQA65C1AOuQtgDrkLcA65C4AOuQuQDrkLoA65C7AOuQvADrkL0A65C+AOuQvwDrkYAA65GBAOuRggDrkYMA65GEAOuRhQDrkYYA65GHAOuRiADrkYkA65GKAOuRiwDrkYwA65GNAOuRjgDrkY8A65GQAOuRkQDrkZIA65GTAOuRlADrkZUA65GWAOuRlwDrkZgA65GZAOuRmgDrkZsA65GcAOuRnQDrkZ4A65GfAOuRoADrkaEA65GiAOuRowDrkaQA65GlAOuRpgDrkacA65GoAOuRqQDrkaoA65GrAOuRrADrka0A65GuAOuRrwDrkbAA65GxAOuRsgDrkbMA65G0AOuRtQDrkbYA65G3AOuRuADrkbkA65G6AOuRuwDrkbwA65G9AOuRvgDrkb8A65KAAOuSgQDrkoIA65KDAOuShADrkoUA65KGAOuShwDrkogA65KJAOuSigDrkosA65KMAOuSjQDrko4A65KPAOuSkADrkpEA65KSAOuSkwDrkpQA65KVAOuSlgDrkpcA65KYAOuSmQDrkpoA65KbAOuSnADrkp0A65KeAOuSnwDrkqAA65KhAOuSogDrkqMA65KkAOuSpQDrkqYA65KnAOuSqADrkqkA65KqAOuSqwDrkqwA65KtAOuSrgDrkq8A65KwAOuSsQDrkrIA65KzAOuStADrkrUA65K2AOuStwDrkrgA65K5AOuSugDrkrsA65K8AOuSvQDrkr4A65K/AOuTgADrk4EA65OCAOuTgwDrk4QA65OFAOuThgDrk4cA65OIAOuTiQDrk4oA65OLAOuTjADrk40A65OOAOuTjwDrk5AA65ORAOuTkgDrk5MA65OUAOuTlQDrk5YA65OXAOuTmADrk5kA65OaAOuTmwDrk5wA65OdAOuTngDrk58A65OgAOuToQDrk6IA65OjAOuTpADrk6UA65OmAOuTpwDrk6gA65OpAOuTqgDrk6sA65OsAOuTrQDrk64A65OvAOuTsADrk7EA65OyAOuTswDrk7QA65O1AOuTtgDrk7cA65O4AOuTuQDrk7oA65O7AOuTvADrk70A65O+AOuTvwDrlIAA65SBAOuUggDrlIMA65SEAOuUhQDrlIYA65SHAOuUiADrlIkA65SKAOuUiwDrlIwA65SNAOuUjgDrlI8A65SQAOuUkQDrlJIA65STAOuUlADrlJUA65SWAOuUlwDrlJgA65SZAOuUmgDrlJsA65ScAOuUnQDrlJ4A65SfAOuUoADrlKEA65SiAOuUowDrlKQA65SlAOuUpgDrlKcA65SoAOuUqQDrlKoA65SrAOuUrADrlK0A65SuAOuUrwDrlLAA65SxAOuUsgDrlLMA65S0AOuUtQDrlLYA65S3AOuUuADrlLkA65S6AOuUuwDrlLwA65S9AOuUvgDrlL8A65WAAOuVgQDrlYIA65WDAOuVhADrlYUA65WGAOuVhwDrlYgA65WJAOuVigDrlYsA65WMAOuVjQDrlY4A65WPAOuVkADrlZEA65WSAOuVkwDrlZQA65WVAOuVlgDrlZcA65WYAOuVmQDrlZoA65WbAOuVnADrlZ0A65WeAOuVnwDrlaAA65WhAOuVogDrlaMA65WkAOuVpQDrlaYA65WnAOuVqADrlakA65WqAOuVqwDrlawA65WtAOuVrgDrla8A65WwAOuVsQDrlbIA65WzAOuVtADrlbUA65W2AOuVtwDrlbgA65W5AOuVugDrlbsA65W8AOuVvQDrlb4A65W/AOuWgADrloEA65aCAOuWgwDrloQA65aFAOuWhgDrlocA65aIAOuWiQDrlooA65aLAOuWjADrlo0A65aOAOuWjwDrlpAA65aRAOuWkgDrlpMA65aUAOuWlQDrlpYA65aXAOuWmADrlpkA65aaAOuWmwDrlpwA65adAOuWngDrlp8A65agAOuWoQDrlqIA65ajAOuWpADrlqUA65amAOuWpwDrlqgA65apAOuWqgDrlqsA65asAOuWrQDrlq4A65avAOuWsADrlrEA65ayAOuWswDrlrQA65a1AOuWtgDrlrcA65a4AOuWuQDrlroA65a7AOuWvADrlr0A65a+AOuWvwDrl4AA65eBAOuXggDrl4MA65eEAOuXhQDrl4YA65eHAOuXiADrl4kA65eKAOuXiwDrl4wA65eNAOuXjgDrl48A65eQAOuXkQDrl5IA65eTAOuXlADrl5UA65eWAOuXlwDrl5gA65eZAOuXmgDrl5sA65ecAOuXnQDrl54A65efAOuXoADrl6EA65eiAOuXowDrl6QA65elAOuXpgDrl6cA65eoAOuXqQDrl6oA65erAOuXrADrl60A65euAOuXrwDrl7AA65exAOuXsgDrl7MA65e0AOuXtQDrl7YA65e3AOuXuADrl7kA65e6AOuXuwDrl7wA65e9AOuXvgDrl78A65iAAOuYgQDrmIIA65iDAOuYhADrmIUA65iGAOuYhwDrmIgA65iJAOuYigDrmIsA65iMAOuYjQDrmI4A65iPAOuYkADrmJEA65iSAOuYkwDrmJQA65iVAOuYlgDrmJcA65iYAOuYmQDrmJoA65ibAOuYnADrmJ0A65ieAOuYnwDrmKAA65ihAOuYogDrmKMA65ikAOuYpQDrmKYA65inAOuYqADrmKkA65iqAOuYqwDrmKwA65itAOuYrgDrmK8A65iwAOuYsQDrmLIA65izAOuYtADrmLUA65i2AOuYtwDrmLgA65i5AOuYugDrmLsA65i8AOuYvQDrmL4A65i/AOuZgADrmYEA65mCAOuZgwDrmYQA65mFAOuZhgDrmYcA65mIAOuZiQDrmYoA65mLAOuZjADrmY0A65mOAOuZjwDrmZAA65mRAOuZkgDrmZMA65mUAOuZlQDrmZYA65mXAOuZmADrmZkA65maAOuZmwDrmZwA65mdAOuZngDrmZ8A65mgAOuZoQDrmaIA65mjAOuZpADrmaUA65mmAOuZpwDrmagA65mpAOuZqgDrmasA65msAOuZrQDrma4A65mvAOuZsADrmbEA65myAOuZswDrmbQA65m1AOuZtgDrmbcA65m4AOuZuQDrmboA65m7AOuZvADrmb0A65m+AOuZvwDrmoAA65qBAOuaggDrmoMA65qEAOuahQDrmoYA65qHAOuaiADrmokA65qKAOuaiwDrmowA65qNAOuajgDrmo8A65qQAOuakQDrmpIA65qTAOualADrmpUA65qWAOualwDrmpgA65qZAOuamgDrmpsA65qcAOuanQDrmp4A65qfAOuaoADrmqEA65qiAOuaowDrmqQA65qlAOuapgDrmqcA65qoAOuaqQDrmqoA65qrAOuarADrmq0A65quAOuarwDrmrAA65qxAOuasgDrmrMA65q0AOuatQDrmrYA65q3AOuauADrmrkA65q6AOuauwDrmrwA65q9AOuavgDrmr8A65uAAOubgQDrm4IA65uDAOubhADrm4UA65uGAOubhwDrm4gA65uJAOubigDrm4sA65uMAOubjQDrm44A65uPAOubkADrm5EA65uSAOubkwDrm5QA65uVAOublgDrm5cA65uYAOubmQDrm5oA65ubAOubnADrm50A65ueAOubnwDrm6AA65uhAOubogDrm6MA65ukAOubpQDrm6YA65unAOubqADrm6kA65uqAOubqwDrm6wA65utAOubrgDrm68A65uwAOubsQDrm7IA65uzAOubtADrm7UA65u2AOubtwDrm7gA65u5AOubugDrm7sA65u8AOubvQDrm74A65u/AOucgADrnIEA65yCAOucgwDrnIQA65yFAOuchgDrnIcA65yIAOuciQDrnIoA65yLAOucjADrnI0A65yOAOucjwDrnJAA65yRAOuckgDrnJMA65yUAOuclQDrnJYA65yXAOucmADrnJkA65yaAOucmwDrnJwA65ydAOucngDrnJ8A65ygAOucoQDrnKIA65yjAOucpADrnKUA65ymAOucpwDrnKgA65ypAOucqgDrnKsA65ysAOucrQDrnK4A65yvAOucsADrnLEA65yyAOucswDrnLQA65y1AOuctgDrnLcA65y4AOucuQDrnLoA65y7AOucvADrnL0A65y+AOucvwDrnYAA652BAOudggDrnYMA652EAOudhQDrnYYA652HAOudiADrnYkA652KAOudiwDrnYwA652NAOudjgDrnY8A652QAOudkQDrnZIA652TAOudlADrnZUA652WAOudlwDrnZgA652ZAOudmgDrnZsA652cAOudnQDrnZ4A652fAOudoADrnaEA652iAOudowDrnaQA652lAOudpgDrnacA652oAOudqQDrnaoA652rAOudrADrna0A652uAOudrwDrnbAA652xAOudsgDrnbMA6520AOudtQDrnbYA6523AOuduADrnbkA6526AOuduwDrnbwA6529AOudvgDrnb8A656AAOuegQDrnoIA656DAOuehADrnoUA656GAOuehwDrnogA656JAOueigDrnosA656MAOuejQDrno4A656PAOuekADrnpEA656SAOuekwDrnpQA656VAOuelgDrnpcA656YAOuemQDrnpoA656bAOuenADrnp0A656eAOuenwDrnqAA656hAOueogDrnqMA656kAOuepQDrnqYA656nAOueqADrnqkA656qAOueqwDrnqwA656tAOuergDrnq8A656wAOuesQDrnrIA656zAOuetADrnrUA6562AOuetwDrnrgA6565AOueugDrnrsA6568AOuevQDrnr4A656/AOufgADrn4EA65+CAOufgwDrn4QA65+FAOufhgDrn4cA65+IAOufiQDrn4oA65+LAOufjADrn40A65+OAOufjwDrn5AA65+RAOufkgDrn5MA65+UAOuflQDrn5YA65+XAOufmADrn5kA65+aAOufmwDrn5wA65+dAOufngDrn58A65+gAOufoQDrn6IA65+jAOufpADrn6UA65+mAOufpwDrn6gA65+pAOufqgDrn6sA65+sAOufrQDrn64A65+vAOufsADrn7EA65+yAOufswDrn7QA65+1AOuftgDrn7cA65+4AOufuQDrn7oA65+7AOufvADrn70A65++AOufvwDroIAA66CBAOugggDroIMA66CEAOughQDroIYA66CHAOugiADroIkA66CKAOugiwDroIwA66CNAOugjgDroI8A66CQAOugkQDroJIA66CTAOuglADroJUA66CWAOuglwDroJgA66CZAOugmgDroJsA66CcAOugnQDroJ4A66CfAOugoADroKEA66CiAOugowDroKQA66ClAOugpgDroKcA66CoAOugqQDroKoA66CrAOugrADroK0A66CuAOugrwDroLAA66CxAOugsgDroLMA66C0AOugtQDroLYA66C3AOuguADroLkA66C6AOuguwDroLwA66C9AOugvgDroL8A66GAAOuhgQDroYIA66GDAOuhhADroYUA66GGAOuhhwDroYgA66GJAOuhigDroYsA66GMAOuhjQDroY4A66GPAOuhkADroZEA66GSAOuhkwDroZQA66GVAOuhlgDroZcA66GYAOuhmQDroZoA66GbAOuhnADroZ0A66GeAOuhnwDroaAA66GhAOuhogDroaMA66GkAOuhpQDroaYA66GnAOuhqADroakA66GqAOuhqwDroawA66GtAOuhrgDroa8A66GwAOuhsQDrobIA66GzAOuhtADrobUA66G2AOuhtwDrobgA66G5AOuhugDrobsA66G8AOuhvQDrob4A66G/AOuigADrooEA66KCAOuigwDrooQA66KFAOuihgDroocA66KIAOuiiQDroooA66KLAOuijADroo0A66KOAOuijwDropAA66KRAOuikgDropMA66KUAOuilQDropYA66KXAOuimADropkA66KaAOuimwDropwA66KdAOuingDrop8A66KgAOuioQDroqIA66KjAOuipADroqUA66KmAOuipwDroqgA66KpAOuiqgDroqsA66KsAOuirQDroq4A66KvAOuisADrorEA66KyAOuiswDrorQA66K1AOuitgDrorcA66K4AOuiuQDroroA66K7AOuivADror0A66K+AOuivwDro4AA66OBAOujggDro4MA66OEAOujhQDro4YA66OHAOujiADro4kA66OKAOujiwDro4wA66ONAOujjgDro48A66OQAOujkQDro5IA66OTAOujlADro5UA66OWAOujlwDro5gA66OZAOujmgDro5sA66OcAOujnQDro54A66OfAOujoADro6EA66OiAOujowDro6QA66OlAOujpgDro6cA66OoAOujqQDro6oA66OrAOujrADro60A66OuAOujrwDro7AA66OxAOujsgDro7MA66O0AOujtQDro7YA66O3AOujuADro7kA66O6AOujuwDro7wA66O9AOujvgDro78A66SAAOukgQDrpIIA66SDAOukhADrpIUA66SGAOukhwDrpIgA66SJAOukigDrpIsA66SMAOukjQDrpI4A66SPAOukkADrpJEA66SSAOukkwDrpJQA66SVAOuklgDrpJcA66SYAOukmQDrpJoA66SbAOuknADrpJ0A66SeAOuknwDrpKAA66ShAOukogDrpKMA66SkAOukpQDrpKYA66SnAOukqADrpKkA66SqAOukqwDrpKwA66StAOukrgDrpK8A66SwAOuksQDrpLIA66SzAOuktADrpLUA66S2AOuktwDrpLgA66S5AOukugDrpLsA66S8AOukvQDrpL4A66S/AOulgADrpYEA66WCAOulgwDrpYQA66WFAOulhgDrpYcA66WIAOuliQDrpYoA66WLAOuljADrpY0A66WOAOuljwDrpZAA66WRAOulkgDrpZMA66WUAOullQDrpZYA66WXAOulmADrpZkA66WaAOulmwDrpZwA66WdAOulngDrpZ8A66WgAOuloQDrpaIA66WjAOulpADrpaUA66WmAOulpwDrpagA66WpAOulqgDrpasA66WsAOulrQDrpa4A66WvAOulsADrpbEA66WyAOulswDrpbQA66W1AOultgDrpbcA66W4AOuluQDrpboA66W7AOulvADrpb0A66W+AOulvwDrpoAA66aBAOumggDrpoMA66aEAOumhQDrpoYA66aHAOumiADrpokA66aKAOumiwDrpowA66aNAOumjgDrpo8A66aQAOumkQDrppIA66aTAOumlADrppUA66aWAOumlwDrppgA66aZAOummgDrppsA66acAOumnQDrpp4A66afAOumoADrpqEA66aiAOumowDrpqQA66alAOumpgDrpqcA66aoAOumqQDrpqoA66arAOumrADrpq0A66auAOumrwDrprAA66axAOumsgDrprMA66a0AOumtQDrprYA66a3AOumuADrprkA66a6AOumuwDrprwA66a9AOumvgDrpr8A66eAAOungQDrp4IA66eDAOunhADrp4UA66eGAOunhwDrp4gA66eJAOunigDrp4sA66eMAOunjQDrp44A66ePAOunkADrp5EA66eSAOunkwDrp5QA66eVAOunlgDrp5cA66eYAOunmQDrp5oA66ebAOunnADrp50A66eeAOunnwDrp6AA66ehAOunogDrp6MA66ekAOunpQDrp6YA66enAOunqADrp6kA66eqAOunqwDrp6wA66etAOunrgDrp68A66ewAOunsQDrp7IA66ezAOuntADrp7UA66e2AOuntwDrp7gA66e5AOunugDrp7sA66e8AOunvQDrp74A66e/AOuogADrqIEA66iCAOuogwDrqIQA66iFAOuohgDrqIcA66iIAOuoiQDrqIoA66iLAOuojADrqI0A66iOAOuojwDrqJAA66iRAOuokgDrqJMA66iUAOuolQDrqJYA66iXAOuomADrqJkA66iaAOuomwDrqJwA66idAOuongDrqJ8A66igAOuooQDrqKIA66ijAOuopADrqKUA66imAOuopwDrqKgA66ipAOuoqgDrqKsA66isAOuorQDrqK4A66ivAOuosADrqLEA66iyAOuoswDrqLQA66i1AOuotgDrqLcA66i4AOuouQDrqLoA66i7AOuovADrqL0A66i+AOuovwDrqYAA66mBAOupggDrqYMA66mEAOuphQDrqYYA66mHAOupiADrqYkA66mKAOupiwDrqYwA66mNAOupjgDrqY8A66mQAOupkQDrqZIA66mTAOuplADrqZUA66mWAOuplwDrqZgA66mZAOupmgDrqZsA66mcAOupnQDrqZ4A66mfAOupoADrqaEA66miAOupowDrqaQA66mlAOuppgDrqacA66moAOupqQDrqaoA66mrAOuprADrqa0A66muAOuprwDrqbAA66mxAOupsgDrqbMA66m0AOuptQDrqbYA66m3AOupuADrqbkA66m6AOupuwDrqbwA66m9AOupvgDrqb8A66qAAOuqgQDrqoIA66qDAOuqhADrqoUA66qGAOuqhwDrqogA66qJAOuqigDrqosA66qMAOuqjQDrqo4A66qPAOuqkADrqpEA66qSAOuqkwDrqpQA66qVAOuqlgDrqpcA66qYAOuqmQDrqpoA66qbAOuqnADrqp0A66qeAOuqnwDrqqAA66qhAOuqogDrqqMA66qkAOuqpQDrqqYA66qnAOuqqADrqqkA66qqAOuqqwDrqqwA66qtAOuqrgDrqq8A66qwAOuqsQDrqrIA66qzAOuqtADrqrUA66q2AOuqtwDrqrgA66q5AOuqugDrqrsA66q8AOuqvQDrqr4A66q/AOurgADrq4EA66uCAOurgwDrq4QA66uFAOurhgDrq4cA66uIAOuriQDrq4oA66uLAOurjADrq40A66uOAOurjwDrq5AA66uRAOurkgDrq5MA66uUAOurlQDrq5YA66uXAOurmADrq5kA66uaAOurmwDrq5wA66udAOurngDrq58A66ugAOuroQDrq6IA66ujAOurpADrq6UA66umAOurpwDrq6gA66upAOurqgDrq6sA66usAOurrQDrq64A66uvAOursADrq7EA66uyAOurswDrq7QA66u1AOurtgDrq7cA66u4AOuruQDrq7oA66u7AOurvADrq70A66u+AOurvwDrrIAA66yBAOusggDrrIMA66yEAOushQDrrIYA66yHAOusiADrrIkA66yKAOusiwDrrIwA66yNAOusjgDrrI8A66yQAOuskQDrrJIA66yTAOuslADrrJUA66yWAOuslwDrrJgA66yZAOusmgDrrJsA66ycAOusnQDrrJ4A66yfAOusoADrrKEA66yiAOusowDrrKQA66ylAOuspgDrrKcA66yoAOusqQDrrKoA66yrAOusrADrrK0A66yuAOusrwDrrLAA66yxAOussgDrrLMA66y0AOustQDrrLYA66y3AOusuADrrLkA66y6AOusuwDrrLwA66y9AOusvgDrrL8A662AAOutgQDrrYIA662DAOuthADrrYUA662GAOuthwDrrYgA662JAOutigDrrYsA662MAOutjQDrrY4A662PAOutkADrrZEA662SAOutkwDrrZQA662VAOutlgDrrZcA662YAOutmQDrrZoA662bAOutnADrrZ0A662eAOutnwDrraAA662hAOutogDrraMA662kAOutpQDrraYA662nAOutqADrrakA662qAOutqwDrrawA662tAOutrgDrra8A662wAOutsQDrrbIA662zAOuttADrrbUA6622AOuttwDrrbgA6625AOutugDrrbsA6628AOutvQDrrb4A662/AOuugADrroEA666CAOuugwDrroQA666FAOuuhgDrrocA666IAOuuiQDrrooA666LAOuujADrro0A666OAOuujwDrrpAA666RAOuukgDrrpMA666UAOuulQDrrpYA666XAOuumADrrpkA666aAOuumwDrrpwA666dAOuungDrrp8A666gAOuuoQDrrqIA666jAOuupADrrqUA666mAOuupwDrrqgA666pAOuuqgDrrqsA666sAOuurQDrrq4A666vAOuusADrrrEA666yAOuuswDrrrQA6661AOuutgDrrrcA6664AOuuuQDrrroA6667AOuuvADrrr0A666+AOuuvwDrr4AA66+BAOuvggDrr4MA66+EAOuvhQDrr4YA66+HAOuviADrr4kA66+KAOuviwDrr4wA66+NAOuvjgDrr48A66+QAOuvkQDrr5IA66+TAOuvlADrr5UA66+WAOuvlwDrr5gA66+ZAOuvmgDrr5sA66+cAOuvnQDrr54A66+fAOuvoADrr6EA66+iAOuvowDrr6QA66+lAOuvpgDrr6cA66+oAOuvqQDrr6oA66+rAOuvrADrr60A66+uAOuvrwDrr7AA66+xAOuvsgDrr7MA66+0AOuvtQDrr7YA66+3AOuvuADrr7kA66+6AOuvuwDrr7wA66+9AOuvvgDrr78A67CAAOuwgQDrsIIA67CDAOuwhADrsIUA67CGAOuwhwDrsIgA67CJAOuwigDrsIsA67CMAOuwjQDrsI4A67CPAOuwkADrsJEA67CSAOuwkwDrsJQA67CVAOuwlgDrsJcA67CYAOuwmQDrsJoA67CbAOuwnADrsJ0A67CeAOuwnwDrsKAA67ChAOuwogDrsKMA67CkAOuwpQDrsKYA67CnAOuwqADrsKkA67CqAOuwqwDrsKwA67CtAOuwrgDrsK8A67CwAOuwsQDrsLIA67CzAOuwtADrsLUA67C2AOuwtwDrsLgA67C5AOuwugDrsLsA67C8AOuwvQDrsL4A67C/AOuxgADrsYEA67GCAOuxgwDrsYQA67GFAOuxhgDrsYcA67GIAOuxiQDrsYoA67GLAOuxjADrsY0A67GOAOuxjwDrsZAA67GRAOuxkgDrsZMA67GUAOuxlQDrsZYA67GXAOuxmADrsZkA67GaAOuxmwDrsZwA67GdAOuxngDrsZ8A67GgAOuxoQDrsaIA67GjAOuxpADrsaUA67GmAOuxpwDrsagA67GpAOuxqgDrsasA67GsAOuxrQDrsa4A67GvAOuxsADrsbEA67GyAOuxswDrsbQA67G1AOuxtgDrsbcA67G4AOuxuQDrsboA67G7AOuxvADrsb0A67G+AOuxvwDrsoAA67KBAOuyggDrsoMA67KEAOuyhQDrsoYA67KHAOuyiADrsokA67KKAOuyiwDrsowA67KNAOuyjgDrso8A67KQAOuykQDrspIA67KTAOuylADrspUA67KWAOuylwDrspgA67KZAOuymgDrspsA67KcAOuynQDrsp4A67KfAOuyoADrsqEA67KiAOuyowDrsqQA67KlAOuypgDrsqcA67KoAOuyqQDrsqoA67KrAOuyrADrsq0A67KuAOuyrwDrsrAA67KxAOuysgDrsrMA67K0AOuytQDrsrYA67K3AOuyuADrsrkA67K6AOuyuwDrsrwA67K9AOuyvgDrsr8A67OAAOuzgQDrs4IA67ODAOuzhADrs4UA67OGAOuzhwDrs4gA67OJAOuzigDrs4sA67OMAOuzjQDrs44A67OPAOuzkADrs5EA67OSAOuzkwDrs5QA67OVAOuzlgDrs5cA67OYAOuzmQDrs5oA67ObAOuznADrs50A67OeAOuznwDrs6AA67OhAOuzogDrs6MA67OkAOuzpQDrs6YA67OnAOuzqADrs6kA67OqAOuzqwDrs6wA67OtAOuzrgDrs68A67OwAOuzsQDrs7IA67OzAOuztADrs7UA67O2AOuztwDrs7gA67O5AOuzugDrs7sA67O8AOuzvQDrs74A67O/AOu0gADrtIEA67SCAOu0gwDrtIQA67SFAOu0hgDrtIcA67SIAOu0iQDrtIoA67SLAOu0jADrtI0A67SOAOu0jwDrtJAA67SRAOu0kgDrtJMA67SUAOu0lQDrtJYA67SXAOu0mADrtJkA67SaAOu0mwDrtJwA67SdAOu0ngDrtJ8A67SgAOu0oQDrtKIA67SjAOu0pADrtKUA67SmAOu0pwDrtKgA67SpAOu0qgDrtKsA67SsAOu0rQDrtK4A67SvAOu0sADrtLEA67SyAOu0swDrtLQA67S1AOu0tgDrtLcA67S4AOu0uQDrtLoA67S7AOu0vADrtL0A67S+AOu0vwDrtYAA67WBAOu1ggDrtYMA67WEAOu1hQDrtYYA67WHAOu1iADrtYkA67WKAOu1iwDrtYwA67WNAOu1jgDrtY8A67WQAOu1kQDrtZIA67WTAOu1lADrtZUA67WWAOu1lwDrtZgA67WZAOu1mgDrtZsA67WcAOu1nQDrtZ4A67WfAOu1oADrtaEA67WiAOu1owDrtaQA67WlAOu1pgDrtacA67WoAOu1qQDrtaoA67WrAOu1rADrta0A67WuAOu1rwDrtbAA67WxAOu1sgDrtbMA67W0AOu1tQDrtbYA67W3AOu1uADrtbkA67W6AOu1uwDrtbwA67W9AOu1vgDrtb8A67aAAOu2gQDrtoIA67aDAOu2hADrtoUA67aGAOu2hwDrtogA67aJAOu2igDrtosA67aMAOu2jQDrto4A67aPAOu2kADrtpEA67aSAOu2kwDrtpQA67aVAOu2lgDrtpcA67aYAOu2mQDrtpoA67abAOu2nADrtp0A67aeAOu2nwDrtqAA67ahAOu2ogDrtqMA67akAOu2pQDrtqYA67anAOu2qADrtqkA67aqAOu2qwDrtqwA67atAOu2rgDrtq8A67awAOu2sQDrtrIA67azAOu2tADrtrUA67a2AOu2twDrtrgA67a5AOu2ugDrtrsA67a8AOu2vQDrtr4A67a/AOu3gADrt4EA67eCAOu3gwDrt4QA67eFAOu3hgDrt4cA67eIAOu3iQDrt4oA67eLAOu3jADrt40A67eOAOu3jwDrt5AA67eRAOu3kgDrt5MA67eUAOu3lQDrt5YA67eXAOu3mADrt5kA67eaAOu3mwDrt5wA67edAOu3ngDrt58A67egAOu3oQDrt6IA67ejAOu3pADrt6UA67emAOu3pwDrt6gA67epAOu3qgDrt6sA67esAOu3rQDrt64A67evAOu3sADrt7EA67eyAOu3swDrt7QA67e1AOu3tgDrt7cA67e4AOu3uQDrt7oA67e7AOu3vADrt70A67e+AOu3vwDruIAA67iBAOu4ggDruIMA67iEAOu4hQDruIYA67iHAOu4iADruIkA67iKAOu4iwDruIwA67iNAOu4jgDruI8A67iQAOu4kQDruJIA67iTAOu4lADruJUA67iWAOu4lwDruJgA67iZAOu4mgDruJsA67icAOu4nQDruJ4A67ifAOu4oADruKEA67iiAOu4owDruKQA67ilAOu4pgDruKcA67ioAOu4qQDruKoA67irAOu4rADruK0A67iuAOu4rwDruLAA67ixAOu4sgDruLMA67i0AOu4tQDruLYA67i3AOu4uADruLkA67i6AOu4uwDruLwA67i9AOu4vgDruL8A67mAAOu5gQDruYIA67mDAOu5hADruYUA67mGAOu5hwDruYgA67mJAOu5igDruYsA67mMAOu5jQDruY4A67mPAOu5kADruZEA67mSAOu5kwDruZQA67mVAOu5lgDruZcA67mYAOu5mQDruZoA67mbAOu5nADruZ0A67meAOu5nwDruaAA67mhAOu5ogDruaMA67mkAOu5pQDruaYA67mnAOu5qADruakA67mqAOu5qwDruawA67mtAOu5rgDrua8A67mwAOu5sQDrubIA67mzAOu5tADrubUA67m2AOu5twDrubgA67m5AOu5ugDrubsA67m8AOu5vQDrub4A67m/AOu6gADruoEA67qCAOu6gwDruoQA67qFAOu6hgDruocA67qIAOu6iQDruooA67qLAOu6jADruo0A67qOAOu6jwDrupAA67qRAOu6kgDrupMA67qUAOu6lQDrupYA67qXAOu6mADrupkA67qaAOu6mwDrupwA67qdAOu6ngDrup8A67qgAOu6oQDruqIA67qjAOu6pADruqUA67qmAOu6pwDruqgA67qpAOu6qgDruqsA67qsAOu6rQDruq4A67qvAOu6sADrurEA67qyAOu6swDrurQA67q1AOu6tgDrurcA67q4AOu6uQDruroA67q7AOu6vADrur0A67q+AOu6vwDru4AA67uBAOu7ggDru4MA67uEAOu7hQDru4YA67uHAOu7iADru4kA67uKAOu7iwDru4wA67uNAOu7jgDru48A67uQAOu7kQDru5IA67uTAOu7lADru5UA67uWAOu7lwDru5gA67uZAOu7mgDru5sA67ucAOu7nQDru54A67ufAOu7oADru6EA67uiAOu7owDru6QA67ulAOu7pgDru6cA67uoAOu7qQDru6oA67urAOu7rADru60A67uuAOu7rwDru7AA67uxAOu7sgDru7MA67u0AOu7tQDru7YA67u3AOu7uADru7kA67u6AOu7uwDru7wA67u9AOu7vgDru78A67yAAOu8gQDrvIIA67yDAOu8hADrvIUA67yGAOu8hwDrvIgA67yJAOu8igDrvIsA67yMAOu8jQDrvI4A67yPAOu8kADrvJEA67ySAOu8kwDrvJQA67yVAOu8lgDrvJcA67yYAOu8mQDrvJoA67ybAOu8nADrvJ0A67yeAOu8nwDrvKAA67yhAOu8ogDrvKMA67ykAOu8pQDrvKYA67ynAOu8qADrvKkA67yqAOu8qwDrvKwA67ytAOu8rgDrvK8A67ywAOu8sQDrvLIA67yzAOu8tADrvLUA67y2AOu8twDrvLgA67y5AOu8ugDrvLsA67y8AOu8vQDrvL4A67y/AOu9gADrvYEA672CAOu9gwDrvYQA672FAOu9hgDrvYcA672IAOu9iQDrvYoA672LAOu9jADrvY0A672OAOu9jwDrvZAA672RAOu9kgDrvZMA672UAOu9lQDrvZYA672XAOu9mADrvZkA672aAOu9mwDrvZwA672dAOu9ngDrvZ8A672gAOu9oQDrvaIA672jAOu9pADrvaUA672mAOu9pwDrvagA672pAOu9qgDrvasA672sAOu9rQDrva4A672vAOu9sADrvbEA672yAOu9swDrvbQA6721AOu9tgDrvbcA6724AOu9uQDrvboA6727AOu9vADrvb0A672+AOu9vwDrvoAA676BAOu+ggDrvoMA676EAOu+hQDrvoYA676HAOu+iADrvokA676KAOu+iwDrvowA676NAOu+jgDrvo8A676QAOu+kQDrvpIA676TAOu+lADrvpUA676WAOu+lwDrvpgA676ZAOu+mgDrvpsA676cAOu+nQDrvp4A676fAOu+oADrvqEA676iAOu+owDrvqQA676lAOu+pgDrvqcA676oAOu+qQDrvqoA676rAOu+rADrvq0A676uAOu+rwDrvrAA676xAOu+sgDrvrMA6760AOu+tQDrvrYA6763AOu+uADrvrkA6766AOu+uwDrvrwA6769AOu+vgDrvr8A67+AAOu/gQDrv4IA67+DAOu/hADrv4UA67+GAOu/hwDrv4gA67+JAOu/igDrv4sA67+MAOu/jQDrv44A67+PAOu/kADrv5EA67+SAOu/kwDrv5QA67+VAOu/lgDrv5cA67+YAOu/mQDrv5oA67+bAOu/nADrv50A67+eAOu/nwDrv6AA67+hAOu/ogDrv6MA67+kAOu/pQDrv6YA67+nAOu/qADrv6kA67+qAOu/qwDrv6wA67+tAOu/rgDrv68A67+wAOu/sQDrv7IA67+zAOu/tADrv7UA67+2AOu/twDrv7gA67+5AOu/ugDrv7sA67+8AOu/vQDrv74A67+/AOyAgADsgIEA7ICCAOyAgwDsgIQA7ICFAOyAhgDsgIcA7ICIAOyAiQDsgIoA7ICLAOyAjADsgI0A7ICOAOyAjwDsgJAA7ICRAOyAkgDsgJMA7ICUAOyAlQDsgJYA7ICXAOyAmADsgJkA7ICaAOyAmwDsgJwA7ICdAOyAngDsgJ8A7ICgAOyAoQDsgKIA7ICjAOyApADsgKUA7ICmAOyApwDsgKgA7ICpAOyAqgDsgKsA7ICsAOyArQDsgK4A7ICvAOyAsADsgLEA7ICyAOyAswDsgLQA7IC1AOyAtgDsgLcA7IC4AOyAuQDsgLoA7IC7AOyAvADsgL0A7IC+AOyAvwDsgYAA7IGBAOyBggDsgYMA7IGEAOyBhQDsgYYA7IGHAOyBiADsgYkA7IGKAOyBiwDsgYwA7IGNAOyBjgDsgY8A7IGQAOyBkQDsgZIA7IGTAOyBlADsgZUA7IGWAOyBlwDsgZgA7IGZAOyBmgDsgZsA7IGcAOyBnQDsgZ4A7IGfAOyBoADsgaEA7IGiAOyBowDsgaQA7IGlAOyBpgDsgacA7IGoAOyBqQDsgaoA7IGrAOyBrADsga0A7IGuAOyBrwDsgbAA7IGxAOyBsgDsgbMA7IG0AOyBtQDsgbYA7IG3AOyBuADsgbkA7IG6AOyBuwDsgbwA7IG9AOyBvgDsgb8A7IKAAOyCgQDsgoIA7IKDAOyChADsgoUA7IKGAOyChwDsgogA7IKJAOyCigDsgosA7IKMAOyCjQDsgo4A7IKPAOyCkADsgpEA7IKSAOyCkwDsgpQA7IKVAOyClgDsgpcA7IKYAOyCmQDsgpoA7IKbAOyCnADsgp0A7IKeAOyCnwDsgqAA7IKhAOyCogDsgqMA7IKkAOyCpQDsgqYA7IKnAOyCqADsgqkA7IKqAOyCqwDsgqwA7IKtAOyCrgDsgq8A7IKwAOyCsQDsgrIA7IKzAOyCtADsgrUA7IK2AOyCtwDsgrgA7IK5AOyCugDsgrsA7IK8AOyCvQDsgr4A7IK/AOyDgADsg4EA7IOCAOyDgwDsg4QA7IOFAOyDhgDsg4cA7IOIAOyDiQDsg4oA7IOLAOyDjADsg40A7IOOAOyDjwDsg5AA7IORAOyDkgDsg5MA7IOUAOyDlQDsg5YA7IOXAOyDmADsg5kA7IOaAOyDmwDsg5wA7IOdAOyDngDsg58A7IOgAOyDoQDsg6IA7IOjAOyDpADsg6UA7IOmAOyDpwDsg6gA7IOpAOyDqgDsg6sA7IOsAOyDrQDsg64A7IOvAOyDsADsg7EA7IOyAOyDswDsg7QA7IO1AOyDtgDsg7cA7IO4AOyDuQDsg7oA7IO7AOyDvADsg70A7IO+AOyDvwDshIAA7ISBAOyEggDshIMA7ISEAOyEhQDshIYA7ISHAOyEiADshIkA7ISKAOyEiwDshIwA7ISNAOyEjgDshI8A7ISQAOyEkQDshJIA7ISTAOyElADshJUA7ISWAOyElwDshJgA7ISZAOyEmgDshJsA7IScAOyEnQDshJ4A7ISfAOyEoADshKEA7ISiAOyEowDshKQA7ISlAOyEpgDshKcA7ISoAOyEqQDshKoA7ISrAOyErADshK0A7ISuAOyErwDshLAA7ISxAOyEsgDshLMA7IS0AOyEtQDshLYA7IS3AOyEuADshLkA7IS6AOyEuwDshLwA7IS9AOyEvgDshL8A7IWAAOyFgQDshYIA7IWDAOyFhADshYUA7IWGAOyFhwDshYgA7IWJAOyFigDshYsA7IWMAOyFjQDshY4A7IWPAOyFkADshZEA7IWSAOyFkwDshZQA7IWVAOyFlgDshZcA7IWYAOyFmQDshZoA7IWbAOyFnADshZ0A7IWeAOyFnwDshaAA7IWhAOyFogDshaMA7IWkAOyFpQDshaYA7IWnAOyFqADshakA7IWqAOyFqwDshawA7IWtAOyFrgDsha8A7IWwAOyFsQDshbIA7IWzAOyFtADshbUA7IW2AOyFtwDshbgA7IW5AOyFugDshbsA7IW8AOyFvQDshb4A7IW/AOyGgADshoEA7IaCAOyGgwDshoQA7IaFAOyGhgDshocA7IaIAOyGiQDshooA7IaLAOyGjADsho0A7IaOAOyGjwDshpAA7IaRAOyGkgDshpMA7IaUAOyGlQDshpYA7IaXAOyGmADshpkA7IaaAOyGmwDshpwA7IadAOyGngDshp8A7IagAOyGoQDshqIA7IajAOyGpADshqUA7IamAOyGpwDshqgA7IapAOyGqgDshqsA7IasAOyGrQDshq4A7IavAOyGsADshrEA7IayAOyGswDshrQA7Ia1AOyGtgDshrcA7Ia4AOyGuQDshroA7Ia7AOyGvADshr0A7Ia+AOyGvwDsh4AA7IeBAOyHggDsh4MA7IeEAOyHhQDsh4YA7IeHAOyHiADsh4kA7IeKAOyHiwDsh4wA7IeNAOyHjgDsh48A7IeQAOyHkQDsh5IA7IeTAOyHlADsh5UA7IeWAOyHlwDsh5gA7IeZAOyHmgDsh5sA7IecAOyHnQDsh54A7IefAOyHoADsh6EA7IeiAOyHowDsh6QA7IelAOyHpgDsh6cA7IeoAOyHqQDsh6oA7IerAOyHrADsh60A7IeuAOyHrwDsh7AA7IexAOyHsgDsh7MA7Ie0AOyHtQDsh7YA7Ie3AOyHuADsh7kA7Ie6AOyHuwDsh7wA7Ie9AOyHvgDsh78A7IiAAOyIgQDsiIIA7IiDAOyIhADsiIUA7IiGAOyIhwDsiIgA7IiJAOyIigDsiIsA7IiMAOyIjQDsiI4A7IiPAOyIkADsiJEA7IiSAOyIkwDsiJQA7IiVAOyIlgDsiJcA7IiYAOyImQDsiJoA7IibAOyInADsiJ0A7IieAOyInwDsiKAA7IihAOyIogDsiKMA7IikAOyIpQDsiKYA7IinAOyIqADsiKkA7IiqAOyIqwDsiKwA7IitAOyIrgDsiK8A7IiwAOyIsQDsiLIA7IizAOyItADsiLUA7Ii2AOyItwDsiLgA7Ii5AOyIugDsiLsA7Ii8AOyIvQDsiL4A7Ii/AOyJgADsiYEA7ImCAOyJgwDsiYQA7ImFAOyJhgDsiYcA7ImIAOyJiQDsiYoA7ImLAOyJjADsiY0A7ImOAOyJjwDsiZAA7ImRAOyJkgDsiZMA7ImUAOyJlQDsiZYA7ImXAOyJmADsiZkA7ImaAOyJmwDsiZwA7ImdAOyJngDsiZ8A7ImgAOyJoQDsiaIA7ImjAOyJpADsiaUA7ImmAOyJpwDsiagA7ImpAOyJqgDsiasA7ImsAOyJrQDsia4A7ImvAOyJsADsibEA7ImyAOyJswDsibQA7Im1AOyJtgDsibcA7Im4AOyJuQDsiboA7Im7AOyJvADsib0A7Im+AOyJvwDsioAA7IqBAOyKggDsioMA7IqEAOyKhQDsioYA7IqHAOyKiADsiokA7IqKAOyKiwDsiowA7IqNAOyKjgDsio8A7IqQAOyKkQDsipIA7IqTAOyKlADsipUA7IqWAOyKlwDsipgA7IqZAOyKmgDsipsA7IqcAOyKnQDsip4A7IqfAOyKoADsiqEA7IqiAOyKowDsiqQA7IqlAOyKpgDsiqcA7IqoAOyKqQDsiqoA7IqrAOyKrADsiq0A7IquAOyKrwDsirAA7IqxAOyKsgDsirMA7Iq0AOyKtQDsirYA7Iq3AOyKuADsirkA7Iq6AOyKuwDsirwA7Iq9AOyKvgDsir8A7IuAAOyLgQDsi4IA7IuDAOyLhADsi4UA7IuGAOyLhwDsi4gA7IuJAOyLigDsi4sA7IuMAOyLjQDsi44A7IuPAOyLkADsi5EA7IuSAOyLkwDsi5QA7IuVAOyLlgDsi5cA7IuYAOyLmQDsi5oA7IubAOyLnADsi50A7IueAOyLnwDsi6AA7IuhAOyLogDsi6MA7IukAOyLpQDsi6YA7IunAOyLqADsi6kA7IuqAOyLqwDsi6wA7IutAOyLrgDsi68A7IuwAOyLsQDsi7IA7IuzAOyLtADsi7UA7Iu2AOyLtwDsi7gA7Iu5AOyLugDsi7sA7Iu8AOyLvQDsi74A7Iu/AOyMgADsjIEA7IyCAOyMgwDsjIQA7IyFAOyMhgDsjIcA7IyIAOyMiQDsjIoA7IyLAOyMjADsjI0A7IyOAOyMjwDsjJAA7IyRAOyMkgDsjJMA7IyUAOyMlQDsjJYA7IyXAOyMmADsjJkA7IyaAOyMmwDsjJwA7IydAOyMngDsjJ8A7IygAOyMoQDsjKIA7IyjAOyMpADsjKUA7IymAOyMpwDsjKgA7IypAOyMqgDsjKsA7IysAOyMrQDsjK4A7IyvAOyMsADsjLEA7IyyAOyMswDsjLQA7Iy1AOyMtgDsjLcA7Iy4AOyMuQDsjLoA7Iy7AOyMvADsjL0A7Iy+AOyMvwDsjYAA7I2BAOyNggDsjYMA7I2EAOyNhQDsjYYA7I2HAOyNiADsjYkA7I2KAOyNiwDsjYwA7I2NAOyNjgDsjY8A7I2QAOyNkQDsjZIA7I2TAOyNlADsjZUA7I2WAOyNlwDsjZgA7I2ZAOyNmgDsjZsA7I2cAOyNnQDsjZ4A7I2fAOyNoADsjaEA7I2iAOyNowDsjaQA7I2lAOyNpgDsjacA7I2oAOyNqQDsjaoA7I2rAOyNrADsja0A7I2uAOyNrwDsjbAA7I2xAOyNsgDsjbMA7I20AOyNtQDsjbYA7I23AOyNuADsjbkA7I26AOyNuwDsjbwA7I29AOyNvgDsjb8A7I6AAOyOgQDsjoIA7I6DAOyOhADsjoUA7I6GAOyOhwDsjogA7I6JAOyOigDsjosA7I6MAOyOjQDsjo4A7I6PAOyOkADsjpEA7I6SAOyOkwDsjpQA7I6VAOyOlgDsjpcA7I6YAOyOmQDsjpoA7I6bAOyOnADsjp0A7I6eAOyOnwDsjqAA7I6hAOyOogDsjqMA7I6kAOyOpQDsjqYA7I6nAOyOqADsjqkA7I6qAOyOqwDsjqwA7I6tAOyOrgDsjq8A7I6wAOyOsQDsjrIA7I6zAOyOtADsjrUA7I62AOyOtwDsjrgA7I65AOyOugDsjrsA7I68AOyOvQDsjr4A7I6/AOyPgADsj4EA7I+CAOyPgwDsj4QA7I+FAOyPhgDsj4cA7I+IAOyPiQDsj4oA7I+LAOyPjADsj40A7I+OAOyPjwDsj5AA7I+RAOyPkgDsj5MA7I+UAOyPlQDsj5YA7I+XAOyPmADsj5kA7I+aAOyPmwDsj5wA7I+dAOyPngDsj58A7I+gAOyPoQDsj6IA7I+jAOyPpADsj6UA7I+mAOyPpwDsj6gA7I+pAOyPqgDsj6sA7I+sAOyPrQDsj64A7I+vAOyPsADsj7EA7I+yAOyPswDsj7QA7I+1AOyPtgDsj7cA7I+4AOyPuQDsj7oA7I+7AOyPvADsj70A7I++AOyPvwDskIAA7JCBAOyQggDskIMA7JCEAOyQhQDskIYA7JCHAOyQiADskIkA7JCKAOyQiwDskIwA7JCNAOyQjgDskI8A7JCQAOyQkQDskJIA7JCTAOyQlADskJUA7JCWAOyQlwDskJgA7JCZAOyQmgDskJsA7JCcAOyQnQDskJ4A7JCfAOyQoADskKEA7JCiAOyQowDskKQA7JClAOyQpgDskKcA7JCoAOyQqQDskKoA7JCrAOyQrADskK0A7JCuAOyQrwDskLAA7JCxAOyQsgDskLMA7JC0AOyQtQDskLYA7JC3AOyQuADskLkA7JC6AOyQuwDskLwA7JC9AOyQvgDskL8A7JGAAOyRgQDskYIA7JGDAOyRhADskYUA7JGGAOyRhwDskYgA7JGJAOyRigDskYsA7JGMAOyRjQDskY4A7JGPAOyRkADskZEA7JGSAOyRkwDskZQA7JGVAOyRlgDskZcA7JGYAOyRmQDskZoA7JGbAOyRnADskZ0A7JGeAOyRnwDskaAA7JGhAOyRogDskaMA7JGkAOyRpQDskaYA7JGnAOyRqADskakA7JGqAOyRqwDskawA7JGtAOyRrgDska8A7JGwAOyRsQDskbIA7JGzAOyRtADskbUA7JG2AOyRtwDskbgA7JG5AOyRugDskbsA7JG8AOyRvQDskb4A7JG/AOySgADskoEA7JKCAOySgwDskoQA7JKFAOyShgDskocA7JKIAOySiQDskooA7JKLAOySjADsko0A7JKOAOySjwDskpAA7JKRAOySkgDskpMA7JKUAOySlQDskpYA7JKXAOySmADskpkA7JKaAOySmwDskpwA7JKdAOySngDskp8A7JKgAOySoQDskqIA7JKjAOySpADskqUA7JKmAOySpwDskqgA7JKpAOySqgDskqsA7JKsAOySrQDskq4A7JKvAOySsADskrEA7JKyAOySswDskrQA7JK1AOyStgDskrcA7JK4AOySuQDskroA7JK7AOySvADskr0A7JK+AOySvwDsk4AA7JOBAOyTggDsk4MA7JOEAOyThQDsk4YA7JOHAOyTiADsk4kA7JOKAOyTiwDsk4wA7JONAOyTjgDsk48A7JOQAOyTkQDsk5IA7JOTAOyTlADsk5UA7JOWAOyTlwDsk5gA7JOZAOyTmgDsk5sA7JOcAOyTnQDsk54A7JOfAOyToADsk6EA7JOiAOyTowDsk6QA7JOlAOyTpgDsk6cA7JOoAOyTqQDsk6oA7JOrAOyTrADsk60A7JOuAOyTrwDsk7AA7JOxAOyTsgDsk7MA7JO0AOyTtQDsk7YA7JO3AOyTuADsk7kA7JO6AOyTuwDsk7wA7JO9AOyTvgDsk78A7JSAAOyUgQDslIIA7JSDAOyUhADslIUA7JSGAOyUhwDslIgA7JSJAOyUigDslIsA7JSMAOyUjQDslI4A7JSPAOyUkADslJEA7JSSAOyUkwDslJQA7JSVAOyUlgDslJcA7JSYAOyUmQDslJoA7JSbAOyUnADslJ0A7JSeAOyUnwDslKAA7JShAOyUogDslKMA7JSkAOyUpQDslKYA7JSnAOyUqADslKkA7JSqAOyUqwDslKwA7JStAOyUrgDslK8A7JSwAOyUsQDslLIA7JSzAOyUtADslLUA7JS2AOyUtwDslLgA7JS5AOyUugDslLsA7JS8AOyUvQDslL4A7JS/AOyVgADslYEA7JWCAOyVgwDslYQA7JWFAOyVhgDslYcA7JWIAOyViQDslYoA7JWLAOyVjADslY0A7JWOAOyVjwDslZAA7JWRAOyVkgDslZMA7JWUAOyVlQDslZYA7JWXAOyVmADslZkA7JWaAOyVmwDslZwA7JWdAOyVngDslZ8A7JWgAOyVoQDslaIA7JWjAOyVpADslaUA7JWmAOyVpwDslagA7JWpAOyVqgDslasA7JWsAOyVrQDsla4A7JWvAOyVsADslbEA7JWyAOyVswDslbQA7JW1AOyVtgDslbcA7JW4AOyVuQDslboA7JW7AOyVvADslb0A7JW+AOyVvwDsloAA7JaBAOyWggDsloMA7JaEAOyWhQDsloYA7JaHAOyWiADslokA7JaKAOyWiwDslowA7JaNAOyWjgDslo8A7JaQAOyWkQDslpIA7JaTAOyWlADslpUA7JaWAOyWlwDslpgA7JaZAOyWmgDslpsA7JacAOyWnQDslp4A7JafAOyWoADslqEA7JaiAOyWowDslqQA7JalAOyWpgDslqcA7JaoAOyWqQDslqoA7JarAOyWrADslq0A7JauAOyWrwDslrAA7JaxAOyWsgDslrMA7Ja0AOyWtQDslrYA7Ja3AOyWuADslrkA7Ja6AOyWuwDslrwA7Ja9AOyWvgDslr8A7JeAAOyXgQDsl4IA7JeDAOyXhADsl4UA7JeGAOyXhwDsl4gA7JeJAOyXigDsl4sA7JeMAOyXjQDsl44A7JePAOyXkADsl5EA7JeSAOyXkwDsl5QA7JeVAOyXlgDsl5cA7JeYAOyXmQDsl5oA7JebAOyXnADsl50A7JeeAOyXnwDsl6AA7JehAOyXogDsl6MA7JekAOyXpQDsl6YA7JenAOyXqADsl6kA7JeqAOyXqwDsl6wA7JetAOyXrgDsl68A7JewAOyXsQDsl7IA7JezAOyXtADsl7UA7Je2AOyXtwDsl7gA7Je5AOyXugDsl7sA7Je8AOyXvQDsl74A7Je/AOyYgADsmIEA7JiCAOyYgwDsmIQA7JiFAOyYhgDsmIcA7JiIAOyYiQDsmIoA7JiLAOyYjADsmI0A7JiOAOyYjwDsmJAA7JiRAOyYkgDsmJMA7JiUAOyYlQDsmJYA7JiXAOyYmADsmJkA7JiaAOyYmwDsmJwA7JidAOyYngDsmJ8A7JigAOyYoQDsmKIA7JijAOyYpADsmKUA7JimAOyYpwDsmKgA7JipAOyYqgDsmKsA7JisAOyYrQDsmK4A7JivAOyYsADsmLEA7JiyAOyYswDsmLQA7Ji1AOyYtgDsmLcA7Ji4AOyYuQDsmLoA7Ji7AOyYvADsmL0A7Ji+AOyYvwDsmYAA7JmBAOyZggDsmYMA7JmEAOyZhQDsmYYA7JmHAOyZiADsmYkA7JmKAOyZiwDsmYwA7JmNAOyZjgDsmY8A7JmQAOyZkQDsmZIA7JmTAOyZlADsmZUA7JmWAOyZlwDsmZgA7JmZAOyZmgDsmZsA7JmcAOyZnQDsmZ4A7JmfAOyZoADsmaEA7JmiAOyZowDsmaQA7JmlAOyZpgDsmacA7JmoAOyZqQDsmaoA7JmrAOyZrADsma0A7JmuAOyZrwDsmbAA7JmxAOyZsgDsmbMA7Jm0AOyZtQDsmbYA7Jm3AOyZuADsmbkA7Jm6AOyZuwDsmbwA7Jm9AOyZvgDsmb8A7JqAAOyagQDsmoIA7JqDAOyahADsmoUA7JqGAOyahwDsmogA7JqJAOyaigDsmosA7JqMAOyajQDsmo4A7JqPAOyakADsmpEA7JqSAOyakwDsmpQA7JqVAOyalgDsmpcA7JqYAOyamQDsmpoA7JqbAOyanADsmp0A7JqeAOyanwDsmqAA7JqhAOyaogDsmqMA7JqkAOyapQDsmqYA7JqnAOyaqADsmqkA7JqqAOyaqwDsmqwA7JqtAOyargDsmq8A7JqwAOyasQDsmrIA7JqzAOyatADsmrUA7Jq2AOyatwDsmrgA7Jq5AOyaugDsmrsA7Jq8AOyavQDsmr4A7Jq/AOybgADsm4EA7JuCAOybgwDsm4QA7JuFAOybhgDsm4cA7JuIAOybiQDsm4oA7JuLAOybjADsm40A7JuOAOybjwDsm5AA7JuRAOybkgDsm5MA7JuUAOyblQDsm5YA7JuXAOybmADsm5kA7JuaAOybmwDsm5wA7JudAOybngDsm58A7JugAOyboQDsm6IA7JujAOybpADsm6UA7JumAOybpwDsm6gA7JupAOybqgDsm6sA7JusAOybrQDsm64A7JuvAOybsADsm7EA7JuyAOybswDsm7QA7Ju1AOybtgDsm7cA7Ju4AOybuQDsm7oA7Ju7AOybvADsm70A7Ju+AOybvwDsnIAA7JyBAOycggDsnIMA7JyEAOychQDsnIYA7JyHAOyciADsnIkA7JyKAOyciwDsnIwA7JyNAOycjgDsnI8A7JyQAOyckQDsnJIA7JyTAOyclADsnJUA7JyWAOyclwDsnJgA7JyZAOycmgDsnJsA7JycAOycnQDsnJ4A7JyfAOycoADsnKEA7JyiAOycowDsnKQA7JylAOycpgDsnKcA7JyoAOycqQDsnKoA7JyrAOycrADsnK0A7JyuAOycrwDsnLAA7JyxAOycsgDsnLMA7Jy0AOyctQDsnLYA7Jy3AOycuADsnLkA7Jy6AOycuwDsnLwA7Jy9AOycvgDsnL8A7J2AAOydgQDsnYIA7J2DAOydhADsnYUA7J2GAOydhwDsnYgA7J2JAOydigDsnYsA7J2MAOydjQDsnY4A7J2PAOydkADsnZEA7J2SAOydkwDsnZQA7J2VAOydlgDsnZcA7J2YAOydmQDsnZoA7J2bAOydnADsnZ0A7J2eAOydnwDsnaAA7J2hAOydogDsnaMA7J2kAOydpQDsnaYA7J2nAOydqADsnakA7J2qAOydqwDsnawA7J2tAOydrgDsna8A7J2wAOydsQDsnbIA7J2zAOydtADsnbUA7J22AOydtwDsnbgA7J25AOydugDsnbsA7J28AOydvQDsnb4A7J2/AOyegADsnoEA7J6CAOyegwDsnoQA7J6FAOyehgDsnocA7J6IAOyeiQDsnooA7J6LAOyejADsno0A7J6OAOyejwDsnpAA7J6RAOyekgDsnpMA7J6UAOyelQDsnpYA7J6XAOyemADsnpkA7J6aAOyemwDsnpwA7J6dAOyengDsnp8A7J6gAOyeoQDsnqIA7J6jAOyepADsnqUA7J6mAOyepwDsnqgA7J6pAOyeqgDsnqsA7J6sAOyerQDsnq4A7J6vAOyesADsnrEA7J6yAOyeswDsnrQA7J61AOyetgDsnrcA7J64AOyeuQDsnroA7J67AOyevADsnr0A7J6+AOyevwDsn4AA7J+BAOyfggDsn4MA7J+EAOyfhQDsn4YA7J+HAOyfiADsn4kA7J+KAOyfiwDsn4wA7J+NAOyfjgDsn48A7J+QAOyfkQDsn5IA7J+TAOyflADsn5UA7J+WAOyflwDsn5gA7J+ZAOyfmgDsn5sA7J+cAOyfnQDsn54A7J+fAOyfoADsn6EA7J+iAOyfowDsn6QA7J+lAOyfpgDsn6cA7J+oAOyfqQDsn6oA7J+rAOyfrADsn60A7J+uAOyfrwDsn7AA7J+xAOyfsgDsn7MA7J+0AOyftQDsn7YA7J+3AOyfuADsn7kA7J+6AOyfuwDsn7wA7J+9AOyfvgDsn78A7KCAAOyggQDsoIIA7KCDAOyghADsoIUA7KCGAOyghwDsoIgA7KCJAOygigDsoIsA7KCMAOygjQDsoI4A7KCPAOygkADsoJEA7KCSAOygkwDsoJQA7KCVAOyglgDsoJcA7KCYAOygmQDsoJoA7KCbAOygnADsoJ0A7KCeAOygnwDsoKAA7KChAOygogDsoKMA7KCkAOygpQDsoKYA7KCnAOygqADsoKkA7KCqAOygqwDsoKwA7KCtAOygrgDsoK8A7KCwAOygsQDsoLIA7KCzAOygtADsoLUA7KC2AOygtwDsoLgA7KC5AOygugDsoLsA7KC8AOygvQDsoL4A7KC/AOyhgADsoYEA7KGCAOyhgwDsoYQA7KGFAOyhhgDsoYcA7KGIAOyhiQDsoYoA7KGLAOyhjADsoY0A7KGOAOyhjwDsoZAA7KGRAOyhkgDsoZMA7KGUAOyhlQDsoZYA7KGXAOyhmADsoZkA7KGaAOyhmwDsoZwA7KGdAOyhngDsoZ8A7KGgAOyhoQDsoaIA7KGjAOyhpADsoaUA7KGmAOyhpwDsoagA7KGpAOyhqgDsoasA7KGsAOyhrQDsoa4A7KGvAOyhsADsobEA7KGyAOyhswDsobQA7KG1AOyhtgDsobcA7KG4AOyhuQDsoboA7KG7AOyhvADsob0A7KG+AOyhvwDsooAA7KKBAOyiggDsooMA7KKEAOyihQDsooYA7KKHAOyiiADsookA7KKKAOyiiwDsoowA7KKNAOyijgDsoo8A7KKQAOyikQDsopIA7KKTAOyilADsopUA7KKWAOyilwDsopgA7KKZAOyimgDsopsA7KKcAOyinQDsop4A7KKfAOyioADsoqEA7KKiAOyiowDsoqQA7KKlAOyipgDsoqcA7KKoAOyiqQDsoqoA7KKrAOyirADsoq0A7KKuAOyirwDsorAA7KKxAOyisgDsorMA7KK0AOyitQDsorYA7KK3AOyiuADsorkA7KK6AOyiuwDsorwA7KK9AOyivgDsor8A7KOAAOyjgQDso4IA7KODAOyjhADso4UA7KOGAOyjhwDso4gA7KOJAOyjigDso4sA7KOMAOyjjQDso44A7KOPAOyjkADso5EA7KOSAOyjkwDso5QA7KOVAOyjlgDso5cA7KOYAOyjmQDso5oA7KObAOyjnADso50A7KOeAOyjnwDso6AA7KOhAOyjogDso6MA7KOkAOyjpQDso6YA7KOnAOyjqADso6kA7KOqAOyjqwDso6wA7KOtAOyjrgDso68A7KOwAOyjsQDso7IA7KOzAOyjtADso7UA7KO2AOyjtwDso7gA7KO5AOyjugDso7sA7KO8AOyjvOydmADso70A7KO+AOyjvwDspIAA7KSBAOykggDspIMA7KSEAOykhQDspIYA7KSHAOykiADspIkA7KSKAOykiwDspIwA7KSNAOykjgDspI8A7KSQAOykkQDspJIA7KSTAOyklADspJUA7KSWAOyklwDspJgA7KSZAOykmgDspJsA7KScAOyknQDspJ4A7KSfAOykoADspKEA7KSiAOykowDspKQA7KSlAOykpgDspKcA7KSoAOykqQDspKoA7KSrAOykrADspK0A7KSuAOykrwDspLAA7KSxAOyksgDspLMA7KS0AOyktQDspLYA7KS3AOykuADspLkA7KS6AOykuwDspLwA7KS9AOykvgDspL8A7KWAAOylgQDspYIA7KWDAOylhADspYUA7KWGAOylhwDspYgA7KWJAOyligDspYsA7KWMAOyljQDspY4A7KWPAOylkADspZEA7KWSAOylkwDspZQA7KWVAOyllgDspZcA7KWYAOylmQDspZoA7KWbAOylnADspZ0A7KWeAOylnwDspaAA7KWhAOylogDspaMA7KWkAOylpQDspaYA7KWnAOylqADspakA7KWqAOylqwDspawA7KWtAOylrgDspa8A7KWwAOylsQDspbIA7KWzAOyltADspbUA7KW2AOyltwDspbgA7KW5AOylugDspbsA7KW8AOylvQDspb4A7KW/AOymgADspoEA7KaCAOymgwDspoQA7KaFAOymhgDspocA7KaIAOymiQDspooA7KaLAOymjADspo0A7KaOAOymjwDsppAA7KaRAOymkgDsppMA7KaUAOymlQDsppYA7KaXAOymmADsppkA7KaaAOymmwDsppwA7KadAOymngDspp8A7KagAOymoQDspqIA7KajAOympADspqUA7KamAOympwDspqgA7KapAOymqgDspqsA7KasAOymrQDspq4A7KavAOymsADsprEA7KayAOymswDsprQA7Ka1AOymtgDsprcA7Ka4AOymuQDsproA7Ka7AOymvADspr0A7Ka+AOymvwDsp4AA7KeBAOynggDsp4MA7KeEAOynhQDsp4YA7KeHAOyniADsp4kA7KeKAOyniwDsp4wA7KeNAOynjgDsp48A7KeQAOynkQDsp5IA7KeTAOynlADsp5UA7KeWAOynlwDsp5gA7KeZAOynmgDsp5sA7KecAOynnQDsp54A7KefAOynoADsp6EA7KeiAOynowDsp6QA7KelAOynpgDsp6cA7KeoAOynqQDsp6oA7KerAOynrADsp60A7KeuAOynrwDsp7AA7KexAOynsgDsp7MA7Ke0AOyntQDsp7YA7Ke3AOynuADsp7kA7Ke6AOynuwDsp7wA7Ke9AOynvgDsp78A7KiAAOyogQDsqIIA7KiDAOyohADsqIUA7KiGAOyohwDsqIgA7KiJAOyoigDsqIsA7KiMAOyojQDsqI4A7KiPAOyokADsqJEA7KiSAOyokwDsqJQA7KiVAOyolgDsqJcA7KiYAOyomQDsqJoA7KibAOyonADsqJ0A7KieAOyonwDsqKAA7KihAOyoogDsqKMA7KikAOyopQDsqKYA7KinAOyoqADsqKkA7KiqAOyoqwDsqKwA7KitAOyorgDsqK8A7KiwAOyosQDsqLIA7KizAOyotADsqLUA7Ki2AOyotwDsqLgA7Ki5AOyougDsqLsA7Ki8AOyovQDsqL4A7Ki/AOypgADsqYEA7KmCAOypgwDsqYQA7KmFAOyphgDsqYcA7KmIAOypiQDsqYoA7KmLAOypjADsqY0A7KmOAOypjwDsqZAA7KmRAOypkgDsqZMA7KmUAOyplQDsqZYA7KmXAOypmADsqZkA7KmaAOypmwDsqZwA7KmdAOypngDsqZ8A7KmgAOypoQDsqaIA7KmjAOyppADsqaUA7KmmAOyppwDsqagA7KmpAOypqgDsqasA7KmsAOyprQDsqa4A7KmvAOypsADsqbEA7KmyAOypswDsqbQA7Km1AOyptgDsqbcA7Km4AOypuQDsqboA7Km7AOypvADsqb0A7Km+AOypvwDsqoAA7KqBAOyqggDsqoMA7KqEAOyqhQDsqoYA7KqHAOyqiADsqokA7KqKAOyqiwDsqowA7KqNAOyqjgDsqo8A7KqQAOyqkQDsqpIA7KqTAOyqlADsqpUA7KqWAOyqlwDsqpgA7KqZAOyqmgDsqpsA7KqcAOyqnQDsqp4A7KqfAOyqoADsqqEA7KqiAOyqowDsqqQA7KqlAOyqpgDsqqcA7KqoAOyqqQDsqqoA7KqrAOyqrADsqq0A7KquAOyqrwDsqrAA7KqxAOyqsgDsqrMA7Kq0AOyqtQDsqrYA7Kq3AOyquADsqrkA7Kq6AOyquwDsqrwA7Kq9AOyqvgDsqr8A7KuAAOyrgQDsq4IA7KuDAOyrhADsq4UA7KuGAOyrhwDsq4gA7KuJAOyrigDsq4sA7KuMAOyrjQDsq44A7KuPAOyrkADsq5EA7KuSAOyrkwDsq5QA7KuVAOyrlgDsq5cA7KuYAOyrmQDsq5oA7KubAOyrnADsq50A7KueAOyrnwDsq6AA7KuhAOyrogDsq6MA7KukAOyrpQDsq6YA7KunAOyrqADsq6kA7KuqAOyrqwDsq6wA7KutAOyrrgDsq68A7KuwAOyrsQDsq7IA7KuzAOyrtADsq7UA7Ku2AOyrtwDsq7gA7Ku5AOyrugDsq7sA7Ku8AOyrvQDsq74A7Ku/AOysgADsrIEA7KyCAOysgwDsrIQA7KyFAOyshgDsrIcA7KyIAOysiQDsrIoA7KyLAOysjADsrI0A7KyOAOysjwDsrJAA7KyRAOyskgDsrJMA7KyUAOyslQDsrJYA7KyXAOysmADsrJkA7KyaAOysmwDsrJwA7KydAOysngDsrJ8A7KygAOysoQDsrKIA7KyjAOyspADsrKUA7KymAOyspwDsrKgA7KypAOysqgDsrKsA7KysAOysrQDsrK4A7KyvAOyssADsrLEA7KyyAOysswDsrLQA7Ky1AOystgDsrLcA7Ky4AOysuQDsrLoA7Ky7AOysvADsrL0A7Ky+AOysvwDsrYAA7K2BAOytggDsrYMA7K2EAOythQDsrYYA7K2HAOytiADsrYkA7K2KAOytiwDsrYwA7K2NAOytjgDsrY8A7K2QAOytkQDsrZIA7K2TAOytlADsrZUA7K2WAOytlwDsrZgA7K2ZAOytmgDsrZsA7K2cAOytnQDsrZ4A7K2fAOytoADsraEA7K2iAOytowDsraQA7K2lAOytpgDsracA7K2oAOytqQDsraoA7K2rAOytrADsra0A7K2uAOytrwDsrbAA7K2xAOytsgDsrbMA7K20AOyttQDsrbYA7K23AOytuADsrbkA7K26AOytuwDsrbwA7K29AOytvgDsrb8A7K6AAOyugQDsroIA7K6DAOyuhADsroUA7K6GAOyuhwDsrogA7K6JAOyuigDsrosA7K6MAOyujQDsro4A7K6PAOyukADsrpEA7K6SAOyukwDsrpQA7K6VAOyulgDsrpcA7K6YAOyumQDsrpoA7K6bAOyunADsrp0A7K6eAOyunwDsrqAA7K6hAOyuogDsrqMA7K6kAOyupQDsrqYA7K6nAOyuqADsrqkA7K6qAOyuqwDsrqwA7K6tAOyurgDsrq8A7K6wAOyusQDsrrIA7K6zAOyutADsrrUA7K62AOyutwDsrrgA7K65AOyuugDsrrsA7K68AOyuvQDsrr4A7K6/AOyvgADsr4EA7K+CAOyvgwDsr4QA7K+FAOyvhgDsr4cA7K+IAOyviQDsr4oA7K+LAOyvjADsr40A7K+OAOyvjwDsr5AA7K+RAOyvkgDsr5MA7K+UAOyvlQDsr5YA7K+XAOyvmADsr5kA7K+aAOyvmwDsr5wA7K+dAOyvngDsr58A7K+gAOyvoQDsr6IA7K+jAOyvpADsr6UA7K+mAOyvpwDsr6gA7K+pAOyvqgDsr6sA7K+sAOyvrQDsr64A7K+vAOyvsADsr7EA7K+yAOyvswDsr7QA7K+1AOyvtgDsr7cA7K+4AOyvuQDsr7oA7K+7AOyvvADsr70A7K++AOyvvwDssIAA7LCBAOywggDssIMA7LCEAOywhQDssIYA7LCHAOywiADssIkA7LCKAOywiwDssIwA7LCNAOywjgDssI8A7LCQAOywkQDssJIA7LCTAOywlADssJUA7LCWAOywlwDssJgA7LCZAOywmgDssJsA7LCcAOywnQDssJ4A7LCfAOywoADssKEA7LCiAOywowDssKQA7LClAOywpgDssKcA7LCoAOywqQDssKoA7LCrAOywrADssK0A7LCuAOywrwDssLAA7LCxAOywsgDssLMA7LC0AOywtQDssLYA7LC3AOywuADssLjqs6AA7LC5AOywugDssLsA7LC8AOywvQDssL4A7LC/AOyxgADssYEA7LGCAOyxgwDssYQA7LGFAOyxhgDssYcA7LGIAOyxiQDssYoA7LGLAOyxjADssY0A7LGOAOyxjwDssZAA7LGRAOyxkgDssZMA7LGUAOyxlQDssZYA7LGXAOyxmADssZkA7LGaAOyxmwDssZwA7LGdAOyxngDssZ8A7LGgAOyxoQDssaIA7LGjAOyxpADssaUA7LGmAOyxpwDssagA7LGpAOyxqgDssasA7LGsAOyxrQDssa4A7LGvAOyxsADssbEA7LGyAOyxswDssbQA7LG1AOyxtgDssbcA7LG4AOyxuQDssboA7LG7AOyxvADssb0A7LG+AOyxvwDssoAA7LKBAOyyggDssoMA7LKEAOyyhQDssoYA7LKHAOyyiADssokA7LKKAOyyiwDssowA7LKNAOyyjgDsso8A7LKQAOyykQDsspIA7LKTAOyylADsspUA7LKWAOyylwDsspgA7LKZAOyymgDsspsA7LKcAOyynQDssp4A7LKfAOyyoADssqEA7LKiAOyyowDssqQA7LKlAOyypgDssqcA7LKoAOyyqQDssqoA7LKrAOyyrADssq0A7LKuAOyyrwDssrAA7LKxAOyysgDssrMA7LK0AOyytQDssrYA7LK3AOyyuADssrkA7LK6AOyyuwDssrwA7LK9AOyyvgDssr8A7LOAAOyzgQDss4IA7LODAOyzhADss4UA7LOGAOyzhwDss4gA7LOJAOyzigDss4sA7LOMAOyzjQDss44A7LOPAOyzkADss5EA7LOSAOyzkwDss5QA7LOVAOyzlgDss5cA7LOYAOyzmQDss5oA7LObAOyznADss50A7LOeAOyznwDss6AA7LOhAOyzogDss6MA7LOkAOyzpQDss6YA7LOnAOyzqADss6kA7LOqAOyzqwDss6wA7LOtAOyzrgDss68A7LOwAOyzsQDss7IA7LOzAOyztADss7UA7LO2AOyztwDss7gA7LO5AOyzugDss7sA7LO8AOyzvQDss74A7LO/AOy0gADstIEA7LSCAOy0gwDstIQA7LSFAOy0hgDstIcA7LSIAOy0iQDstIoA7LSLAOy0jADstI0A7LSOAOy0jwDstJAA7LSRAOy0kgDstJMA7LSUAOy0lQDstJYA7LSXAOy0mADstJkA7LSaAOy0mwDstJwA7LSdAOy0ngDstJ8A7LSgAOy0oQDstKIA7LSjAOy0pADstKUA7LSmAOy0pwDstKgA7LSpAOy0qgDstKsA7LSsAOy0rQDstK4A7LSvAOy0sADstLEA7LSyAOy0swDstLQA7LS1AOy0tgDstLcA7LS4AOy0uQDstLoA7LS7AOy0vADstL0A7LS+AOy0vwDstYAA7LWBAOy1ggDstYMA7LWEAOy1hQDstYYA7LWHAOy1iADstYkA7LWKAOy1iwDstYwA7LWNAOy1jgDstY8A7LWQAOy1kQDstZIA7LWTAOy1lADstZUA7LWWAOy1lwDstZgA7LWZAOy1mgDstZsA7LWcAOy1nQDstZ4A7LWfAOy1oADstaEA7LWiAOy1owDstaQA7LWlAOy1pgDstacA7LWoAOy1qQDstaoA7LWrAOy1rADsta0A7LWuAOy1rwDstbAA7LWxAOy1sgDstbMA7LW0AOy1tQDstbYA7LW3AOy1uADstbkA7LW6AOy1uwDstbwA7LW9AOy1vgDstb8A7LaAAOy2gQDstoIA7LaDAOy2hADstoUA7LaGAOy2hwDstogA7LaJAOy2igDstosA7LaMAOy2jQDsto4A7LaPAOy2kADstpEA7LaSAOy2kwDstpQA7LaVAOy2lgDstpcA7LaYAOy2mQDstpoA7LabAOy2nADstp0A7LaeAOy2nwDstqAA7LahAOy2ogDstqMA7LakAOy2pQDstqYA7LanAOy2qADstqkA7LaqAOy2qwDstqwA7LatAOy2rgDstq8A7LawAOy2sQDstrIA7LazAOy2tADstrUA7La2AOy2twDstrgA7La5AOy2ugDstrsA7La8AOy2vQDstr4A7La/AOy3gADst4EA7LeCAOy3gwDst4QA7LeFAOy3hgDst4cA7LeIAOy3iQDst4oA7LeLAOy3jADst40A7LeOAOy3jwDst5AA7LeRAOy3kgDst5MA7LeUAOy3lQDst5YA7LeXAOy3mADst5kA7LeaAOy3mwDst5wA7LedAOy3ngDst58A7LegAOy3oQDst6IA7LejAOy3pADst6UA7LemAOy3pwDst6gA7LepAOy3qgDst6sA7LesAOy3rQDst64A7LevAOy3sADst7EA7LeyAOy3swDst7QA7Le1AOy3tgDst7cA7Le4AOy3uQDst7oA7Le7AOy3vADst70A7Le+AOy3vwDsuIAA7LiBAOy4ggDsuIMA7LiEAOy4hQDsuIYA7LiHAOy4iADsuIkA7LiKAOy4iwDsuIwA7LiNAOy4jgDsuI8A7LiQAOy4kQDsuJIA7LiTAOy4lADsuJUA7LiWAOy4lwDsuJgA7LiZAOy4mgDsuJsA7LicAOy4nQDsuJ4A7LifAOy4oADsuKEA7LiiAOy4owDsuKQA7LilAOy4pgDsuKcA7LioAOy4qQDsuKoA7LirAOy4rADsuK0A7LiuAOy4rwDsuLAA7LixAOy4sgDsuLMA7Li0AOy4tQDsuLYA7Li3AOy4uADsuLkA7Li6AOy4uwDsuLwA7Li9AOy4vgDsuL8A7LmAAOy5gQDsuYIA7LmDAOy5hADsuYUA7LmGAOy5hwDsuYgA7LmJAOy5igDsuYsA7LmMAOy5jQDsuY4A7LmPAOy5kADsuZEA7LmSAOy5kwDsuZQA7LmVAOy5lgDsuZcA7LmYAOy5mQDsuZoA7LmbAOy5nADsuZ0A7LmeAOy5nwDsuaAA7LmhAOy5ogDsuaMA7LmkAOy5pQDsuaYA7LmnAOy5qADsuakA7LmqAOy5qwDsuawA7LmtAOy5rgDsua8A7LmwAOy5sQDsubIA7LmzAOy5tADsubUA7Lm2AOy5twDsubgA7Lm5AOy5ugDsubsA7Lm8AOy5vQDsub4A7Lm/AOy6gADsuoEA7LqCAOy6gwDsuoQA7LqFAOy6hgDsuocA7LqIAOy6iQDsuooA7LqLAOy6jADsuo0A7LqOAOy6jwDsupAA7LqRAOy6kgDsupMA7LqUAOy6lQDsupYA7LqXAOy6mADsupkA7LqaAOy6mwDsupwA7LqdAOy6ngDsup8A7LqgAOy6oQDsuqIA7LqjAOy6pADsuqUA7LqmAOy6pwDsuqgA7LqpAOy6qgDsuqsA7LqsAOy6rQDsuq4A7LqvAOy6sADsurEA7LqyAOy6swDsurQA7Lq1AOy6tgDsurcA7Lq4AOy6uQDsuroA7Lq7AOy6vADsur0A7Lq+AOy6vwDsu4AA7LuBAOy7ggDsu4MA7LuEAOy7hQDsu4YA7LuHAOy7iADsu4kA7LuKAOy7iwDsu4wA7LuNAOy7jgDsu48A7LuQAOy7kQDsu5IA7LuTAOy7lADsu5UA7LuWAOy7lwDsu5gA7LuZAOy7mgDsu5sA7LucAOy7nQDsu54A7LufAOy7oADsu6EA7LuiAOy7owDsu6QA7LulAOy7pgDsu6cA7LuoAOy7qQDsu6oA7LurAOy7rADsu60A7LuuAOy7rwDsu7AA7LuxAOy7sgDsu7MA7Lu0AOy7tQDsu7YA7Lu3AOy7uADsu7kA7Lu6AOy7uwDsu7wA7Lu9AOy7vgDsu78A7LyAAOy8gQDsvIIA7LyDAOy8hADsvIUA7LyGAOy8hwDsvIgA7LyJAOy8igDsvIsA7LyMAOy8jQDsvI4A7LyPAOy8kADsvJEA7LySAOy8kwDsvJQA7LyVAOy8lgDsvJcA7LyYAOy8mQDsvJoA7LybAOy8nADsvJ0A7LyeAOy8nwDsvKAA7LyhAOy8ogDsvKMA7LykAOy8pQDsvKYA7LynAOy8qADsvKkA7LyqAOy8qwDsvKwA7LytAOy8rgDsvK8A7LywAOy8sQDsvLIA7LyzAOy8tADsvLUA7Ly2AOy8twDsvLgA7Ly5AOy8ugDsvLsA7Ly8AOy8vQDsvL4A7Ly/AOy9gADsvYEA7L2CAOy9gwDsvYQA7L2FAOy9hgDsvYcA7L2IAOy9iQDsvYoA7L2LAOy9jADsvY0A7L2OAOy9jwDsvZAA7L2RAOy9kgDsvZMA7L2UAOy9lQDsvZYA7L2XAOy9mADsvZkA7L2aAOy9mwDsvZwA7L2dAOy9ngDsvZ8A7L2gAOy9oQDsvaIA7L2jAOy9pADsvaUA7L2mAOy9pwDsvagA7L2pAOy9qgDsvasA7L2sAOy9rQDsva4A7L2vAOy9sADsvbEA7L2yAOy9swDsvbQA7L21AOy9tgDsvbcA7L24AOy9uQDsvboA7L27AOy9vADsvb0A7L2+AOy9vwDsvoAA7L6BAOy+ggDsvoMA7L6EAOy+hQDsvoYA7L6HAOy+iADsvokA7L6KAOy+iwDsvowA7L6NAOy+jgDsvo8A7L6QAOy+kQDsvpIA7L6TAOy+lADsvpUA7L6WAOy+lwDsvpgA7L6ZAOy+mgDsvpsA7L6cAOy+nQDsvp4A7L6fAOy+oADsvqEA7L6iAOy+owDsvqQA7L6lAOy+pgDsvqcA7L6oAOy+qQDsvqoA7L6rAOy+rADsvq0A7L6uAOy+rwDsvrAA7L6xAOy+sgDsvrMA7L60AOy+tQDsvrYA7L63AOy+uADsvrkA7L66AOy+uwDsvrwA7L69AOy+vgDsvr8A7L+AAOy/gQDsv4IA7L+DAOy/hADsv4UA7L+GAOy/hwDsv4gA7L+JAOy/igDsv4sA7L+MAOy/jQDsv44A7L+PAOy/kADsv5EA7L+SAOy/kwDsv5QA7L+VAOy/lgDsv5cA7L+YAOy/mQDsv5oA7L+bAOy/nADsv50A7L+eAOy/nwDsv6AA7L+hAOy/ogDsv6MA7L+kAOy/pQDsv6YA7L+nAOy/qADsv6kA7L+qAOy/qwDsv6wA7L+tAOy/rgDsv68A7L+wAOy/sQDsv7IA7L+zAOy/tADsv7UA7L+2AOy/twDsv7gA7L+5AOy/ugDsv7sA7L+8AOy/vQDsv74A7L+/AO2AgADtgIEA7YCCAO2AgwDtgIQA7YCFAO2AhgDtgIcA7YCIAO2AiQDtgIoA7YCLAO2AjADtgI0A7YCOAO2AjwDtgJAA7YCRAO2AkgDtgJMA7YCUAO2AlQDtgJYA7YCXAO2AmADtgJkA7YCaAO2AmwDtgJwA7YCdAO2AngDtgJ8A7YCgAO2AoQDtgKIA7YCjAO2ApADtgKUA7YCmAO2ApwDtgKgA7YCpAO2AqgDtgKsA7YCsAO2ArQDtgK4A7YCvAO2AsADtgLEA7YCyAO2AswDtgLQA7YC1AO2AtgDtgLcA7YC4AO2AuQDtgLoA7YC7AO2AvADtgL0A7YC+AO2AvwDtgYAA7YGBAO2BggDtgYMA7YGEAO2BhQDtgYYA7YGHAO2BiADtgYkA7YGKAO2BiwDtgYwA7YGNAO2BjgDtgY8A7YGQAO2BkQDtgZIA7YGTAO2BlADtgZUA7YGWAO2BlwDtgZgA7YGZAO2BmgDtgZsA7YGcAO2BnQDtgZ4A7YGfAO2BoADtgaEA7YGiAO2BowDtgaQA7YGlAO2BpgDtgacA7YGoAO2BqQDtgaoA7YGrAO2BrADtga0A7YGuAO2BrwDtgbAA7YGxAO2BsgDtgbMA7YG0AO2BtQDtgbYA7YG3AO2BuADtgbkA7YG6AO2BuwDtgbwA7YG9AO2BvgDtgb8A7YKAAO2CgQDtgoIA7YKDAO2ChADtgoUA7YKGAO2ChwDtgogA7YKJAO2CigDtgosA7YKMAO2CjQDtgo4A7YKPAO2CkADtgpEA7YKSAO2CkwDtgpQA7YKVAO2ClgDtgpcA7YKYAO2CmQDtgpoA7YKbAO2CnADtgp0A7YKeAO2CnwDtgqAA7YKhAO2CogDtgqMA7YKkAO2CpQDtgqYA7YKnAO2CqADtgqkA7YKqAO2CqwDtgqwA7YKtAO2CrgDtgq8A7YKwAO2CsQDtgrIA7YKzAO2CtADtgrUA7YK2AO2CtwDtgrgA7YK5AO2CugDtgrsA7YK8AO2CvQDtgr4A7YK/AO2DgADtg4EA7YOCAO2DgwDtg4QA7YOFAO2DhgDtg4cA7YOIAO2DiQDtg4oA7YOLAO2DjADtg40A7YOOAO2DjwDtg5AA7YORAO2DkgDtg5MA7YOUAO2DlQDtg5YA7YOXAO2DmADtg5kA7YOaAO2DmwDtg5wA7YOdAO2DngDtg58A7YOgAO2DoQDtg6IA7YOjAO2DpADtg6UA7YOmAO2DpwDtg6gA7YOpAO2DqgDtg6sA7YOsAO2DrQDtg64A7YOvAO2DsADtg7EA7YOyAO2DswDtg7QA7YO1AO2DtgDtg7cA7YO4AO2DuQDtg7oA7YO7AO2DvADtg70A7YO+AO2DvwDthIAA7YSBAO2EggDthIMA7YSEAO2EhQDthIYA7YSHAO2EiADthIkA7YSKAO2EiwDthIwA7YSNAO2EjgDthI8A7YSQAO2EkQDthJIA7YSTAO2ElADthJUA7YSWAO2ElwDthJgA7YSZAO2EmgDthJsA7YScAO2EnQDthJ4A7YSfAO2EoADthKEA7YSiAO2EowDthKQA7YSlAO2EpgDthKcA7YSoAO2EqQDthKoA7YSrAO2ErADthK0A7YSuAO2ErwDthLAA7YSxAO2EsgDthLMA7YS0AO2EtQDthLYA7YS3AO2EuADthLkA7YS6AO2EuwDthLwA7YS9AO2EvgDthL8A7YWAAO2FgQDthYIA7YWDAO2FhADthYUA7YWGAO2FhwDthYgA7YWJAO2FigDthYsA7YWMAO2FjQDthY4A7YWPAO2FkADthZEA7YWSAO2FkwDthZQA7YWVAO2FlgDthZcA7YWYAO2FmQDthZoA7YWbAO2FnADthZ0A7YWeAO2FnwDthaAA7YWhAO2FogDthaMA7YWkAO2FpQDthaYA7YWnAO2FqADthakA7YWqAO2FqwDthawA7YWtAO2FrgDtha8A7YWwAO2FsQDthbIA7YWzAO2FtADthbUA7YW2AO2FtwDthbgA7YW5AO2FugDthbsA7YW8AO2FvQDthb4A7YW/AO2GgADthoEA7YaCAO2GgwDthoQA7YaFAO2GhgDthocA7YaIAO2GiQDthooA7YaLAO2GjADtho0A7YaOAO2GjwDthpAA7YaRAO2GkgDthpMA7YaUAO2GlQDthpYA7YaXAO2GmADthpkA7YaaAO2GmwDthpwA7YadAO2GngDthp8A7YagAO2GoQDthqIA7YajAO2GpADthqUA7YamAO2GpwDthqgA7YapAO2GqgDthqsA7YasAO2GrQDthq4A7YavAO2GsADthrEA7YayAO2GswDthrQA7Ya1AO2GtgDthrcA7Ya4AO2GuQDthroA7Ya7AO2GvADthr0A7Ya+AO2GvwDth4AA7YeBAO2HggDth4MA7YeEAO2HhQDth4YA7YeHAO2HiADth4kA7YeKAO2HiwDth4wA7YeNAO2HjgDth48A7YeQAO2HkQDth5IA7YeTAO2HlADth5UA7YeWAO2HlwDth5gA7YeZAO2HmgDth5sA7YecAO2HnQDth54A7YefAO2HoADth6EA7YeiAO2HowDth6QA7YelAO2HpgDth6cA7YeoAO2HqQDth6oA7YerAO2HrADth60A7YeuAO2HrwDth7AA7YexAO2HsgDth7MA7Ye0AO2HtQDth7YA7Ye3AO2HuADth7kA7Ye6AO2HuwDth7wA7Ye9AO2HvgDth78A7YiAAO2IgQDtiIIA7YiDAO2IhADtiIUA7YiGAO2IhwDtiIgA7YiJAO2IigDtiIsA7YiMAO2IjQDtiI4A7YiPAO2IkADtiJEA7YiSAO2IkwDtiJQA7YiVAO2IlgDtiJcA7YiYAO2ImQDtiJoA7YibAO2InADtiJ0A7YieAO2InwDtiKAA7YihAO2IogDtiKMA7YikAO2IpQDtiKYA7YinAO2IqADtiKkA7YiqAO2IqwDtiKwA7YitAO2IrgDtiK8A7YiwAO2IsQDtiLIA7YizAO2ItADtiLUA7Yi2AO2ItwDtiLgA7Yi5AO2IugDtiLsA7Yi8AO2IvQDtiL4A7Yi/AO2JgADtiYEA7YmCAO2JgwDtiYQA7YmFAO2JhgDtiYcA7YmIAO2JiQDtiYoA7YmLAO2JjADtiY0A7YmOAO2JjwDtiZAA7YmRAO2JkgDtiZMA7YmUAO2JlQDtiZYA7YmXAO2JmADtiZkA7YmaAO2JmwDtiZwA7YmdAO2JngDtiZ8A7YmgAO2JoQDtiaIA7YmjAO2JpADtiaUA7YmmAO2JpwDtiagA7YmpAO2JqgDtiasA7YmsAO2JrQDtia4A7YmvAO2JsADtibEA7YmyAO2JswDtibQA7Ym1AO2JtgDtibcA7Ym4AO2JuQDtiboA7Ym7AO2JvADtib0A7Ym+AO2JvwDtioAA7YqBAO2KggDtioMA7YqEAO2KhQDtioYA7YqHAO2KiADtiokA7YqKAO2KiwDtiowA7YqNAO2KjgDtio8A7YqQAO2KkQDtipIA7YqTAO2KlADtipUA7YqWAO2KlwDtipgA7YqZAO2KmgDtipsA7YqcAO2KnQDtip4A7YqfAO2KoADtiqEA7YqiAO2KowDtiqQA7YqlAO2KpgDtiqcA7YqoAO2KqQDtiqoA7YqrAO2KrADtiq0A7YquAO2KrwDtirAA7YqxAO2KsgDtirMA7Yq0AO2KtQDtirYA7Yq3AO2KuADtirkA7Yq6AO2KuwDtirwA7Yq9AO2KvgDtir8A7YuAAO2LgQDti4IA7YuDAO2LhADti4UA7YuGAO2LhwDti4gA7YuJAO2LigDti4sA7YuMAO2LjQDti44A7YuPAO2LkADti5EA7YuSAO2LkwDti5QA7YuVAO2LlgDti5cA7YuYAO2LmQDti5oA7YubAO2LnADti50A7YueAO2LnwDti6AA7YuhAO2LogDti6MA7YukAO2LpQDti6YA7YunAO2LqADti6kA7YuqAO2LqwDti6wA7YutAO2LrgDti68A7YuwAO2LsQDti7IA7YuzAO2LtADti7UA7Yu2AO2LtwDti7gA7Yu5AO2LugDti7sA7Yu8AO2LvQDti74A7Yu/AO2MgADtjIEA7YyCAO2MgwDtjIQA7YyFAO2MhgDtjIcA7YyIAO2MiQDtjIoA7YyLAO2MjADtjI0A7YyOAO2MjwDtjJAA7YyRAO2MkgDtjJMA7YyUAO2MlQDtjJYA7YyXAO2MmADtjJkA7YyaAO2MmwDtjJwA7YydAO2MngDtjJ8A7YygAO2MoQDtjKIA7YyjAO2MpADtjKUA7YymAO2MpwDtjKgA7YypAO2MqgDtjKsA7YysAO2MrQDtjK4A7YyvAO2MsADtjLEA7YyyAO2MswDtjLQA7Yy1AO2MtgDtjLcA7Yy4AO2MuQDtjLoA7Yy7AO2MvADtjL0A7Yy+AO2MvwDtjYAA7Y2BAO2NggDtjYMA7Y2EAO2NhQDtjYYA7Y2HAO2NiADtjYkA7Y2KAO2NiwDtjYwA7Y2NAO2NjgDtjY8A7Y2QAO2NkQDtjZIA7Y2TAO2NlADtjZUA7Y2WAO2NlwDtjZgA7Y2ZAO2NmgDtjZsA7Y2cAO2NnQDtjZ4A7Y2fAO2NoADtjaEA7Y2iAO2NowDtjaQA7Y2lAO2NpgDtjacA7Y2oAO2NqQDtjaoA7Y2rAO2NrADtja0A7Y2uAO2NrwDtjbAA7Y2xAO2NsgDtjbMA7Y20AO2NtQDtjbYA7Y23AO2NuADtjbkA7Y26AO2NuwDtjbwA7Y29AO2NvgDtjb8A7Y6AAO2OgQDtjoIA7Y6DAO2OhADtjoUA7Y6GAO2OhwDtjogA7Y6JAO2OigDtjosA7Y6MAO2OjQDtjo4A7Y6PAO2OkADtjpEA7Y6SAO2OkwDtjpQA7Y6VAO2OlgDtjpcA7Y6YAO2OmQDtjpoA7Y6bAO2OnADtjp0A7Y6eAO2OnwDtjqAA7Y6hAO2OogDtjqMA7Y6kAO2OpQDtjqYA7Y6nAO2OqADtjqkA7Y6qAO2OqwDtjqwA7Y6tAO2OrgDtjq8A7Y6wAO2OsQDtjrIA7Y6zAO2OtADtjrUA7Y62AO2OtwDtjrgA7Y65AO2OugDtjrsA7Y68AO2OvQDtjr4A7Y6/AO2PgADtj4EA7Y+CAO2PgwDtj4QA7Y+FAO2PhgDtj4cA7Y+IAO2PiQDtj4oA7Y+LAO2PjADtj40A7Y+OAO2PjwDtj5AA7Y+RAO2PkgDtj5MA7Y+UAO2PlQDtj5YA7Y+XAO2PmADtj5kA7Y+aAO2PmwDtj5wA7Y+dAO2PngDtj58A7Y+gAO2PoQDtj6IA7Y+jAO2PpADtj6UA7Y+mAO2PpwDtj6gA7Y+pAO2PqgDtj6sA7Y+sAO2PrQDtj64A7Y+vAO2PsADtj7EA7Y+yAO2PswDtj7QA7Y+1AO2PtgDtj7cA7Y+4AO2PuQDtj7oA7Y+7AO2PvADtj70A7Y++AO2PvwDtkIAA7ZCBAO2QggDtkIMA7ZCEAO2QhQDtkIYA7ZCHAO2QiADtkIkA7ZCKAO2QiwDtkIwA7ZCNAO2QjgDtkI8A7ZCQAO2QkQDtkJIA7ZCTAO2QlADtkJUA7ZCWAO2QlwDtkJgA7ZCZAO2QmgDtkJsA7ZCcAO2QnQDtkJ4A7ZCfAO2QoADtkKEA7ZCiAO2QowDtkKQA7ZClAO2QpgDtkKcA7ZCoAO2QqQDtkKoA7ZCrAO2QrADtkK0A7ZCuAO2QrwDtkLAA7ZCxAO2QsgDtkLMA7ZC0AO2QtQDtkLYA7ZC3AO2QuADtkLkA7ZC6AO2QuwDtkLwA7ZC9AO2QvgDtkL8A7ZGAAO2RgQDtkYIA7ZGDAO2RhADtkYUA7ZGGAO2RhwDtkYgA7ZGJAO2RigDtkYsA7ZGMAO2RjQDtkY4A7ZGPAO2RkADtkZEA7ZGSAO2RkwDtkZQA7ZGVAO2RlgDtkZcA7ZGYAO2RmQDtkZoA7ZGbAO2RnADtkZ0A7ZGeAO2RnwDtkaAA7ZGhAO2RogDtkaMA7ZGkAO2RpQDtkaYA7ZGnAO2RqADtkakA7ZGqAO2RqwDtkawA7ZGtAO2RrgDtka8A7ZGwAO2RsQDtkbIA7ZGzAO2RtADtkbUA7ZG2AO2RtwDtkbgA7ZG5AO2RugDtkbsA7ZG8AO2RvQDtkb4A7ZG/AO2SgADtkoEA7ZKCAO2SgwDtkoQA7ZKFAO2ShgDtkocA7ZKIAO2SiQDtkooA7ZKLAO2SjADtko0A7ZKOAO2SjwDtkpAA7ZKRAO2SkgDtkpMA7ZKUAO2SlQDtkpYA7ZKXAO2SmADtkpkA7ZKaAO2SmwDtkpwA7ZKdAO2SngDtkp8A7ZKgAO2SoQDtkqIA7ZKjAO2SpADtkqUA7ZKmAO2SpwDtkqgA7ZKpAO2SqgDtkqsA7ZKsAO2SrQDtkq4A7ZKvAO2SsADtkrEA7ZKyAO2SswDtkrQA7ZK1AO2StgDtkrcA7ZK4AO2SuQDtkroA7ZK7AO2SvADtkr0A7ZK+AO2SvwDtk4AA7ZOBAO2TggDtk4MA7ZOEAO2ThQDtk4YA7ZOHAO2TiADtk4kA7ZOKAO2TiwDtk4wA7ZONAO2TjgDtk48A7ZOQAO2TkQDtk5IA7ZOTAO2TlADtk5UA7ZOWAO2TlwDtk5gA7ZOZAO2TmgDtk5sA7ZOcAO2TnQDtk54A7ZOfAO2ToADtk6EA7ZOiAO2TowDtk6QA7ZOlAO2TpgDtk6cA7ZOoAO2TqQDtk6oA7ZOrAO2TrADtk60A7ZOuAO2TrwDtk7AA7ZOxAO2TsgDtk7MA7ZO0AO2TtQDtk7YA7ZO3AO2TuADtk7kA7ZO6AO2TuwDtk7wA7ZO9AO2TvgDtk78A7ZSAAO2UgQDtlIIA7ZSDAO2UhADtlIUA7ZSGAO2UhwDtlIgA7ZSJAO2UigDtlIsA7ZSMAO2UjQDtlI4A7ZSPAO2UkADtlJEA7ZSSAO2UkwDtlJQA7ZSVAO2UlgDtlJcA7ZSYAO2UmQDtlJoA7ZSbAO2UnADtlJ0A7ZSeAO2UnwDtlKAA7ZShAO2UogDtlKMA7ZSkAO2UpQDtlKYA7ZSnAO2UqADtlKkA7ZSqAO2UqwDtlKwA7ZStAO2UrgDtlK8A7ZSwAO2UsQDtlLIA7ZSzAO2UtADtlLUA7ZS2AO2UtwDtlLgA7ZS5AO2UugDtlLsA7ZS8AO2UvQDtlL4A7ZS/AO2VgADtlYEA7ZWCAO2VgwDtlYQA7ZWFAO2VhgDtlYcA7ZWIAO2ViQDtlYoA7ZWLAO2VjADtlY0A7ZWOAO2VjwDtlZAA7ZWRAO2VkgDtlZMA7ZWUAO2VlQDtlZYA7ZWXAO2VmADtlZkA7ZWaAO2VmwDtlZwA7ZWdAO2VngDtlZ8A7ZWgAO2VoQDtlaIA7ZWjAO2VpADtlaUA7ZWmAO2VpwDtlagA7ZWpAO2VqgDtlasA7ZWsAO2VrQDtla4A7ZWvAO2VsADtlbEA7ZWyAO2VswDtlbQA7ZW1AO2VtgDtlbcA7ZW4AO2VuQDtlboA7ZW7AO2VvADtlb0A7ZW+AO2VvwDtloAA7ZaBAO2WggDtloMA7ZaEAO2WhQDtloYA7ZaHAO2WiADtlokA7ZaKAO2WiwDtlowA7ZaNAO2WjgDtlo8A7ZaQAO2WkQDtlpIA7ZaTAO2WlADtlpUA7ZaWAO2WlwDtlpgA7ZaZAO2WmgDtlpsA7ZacAO2WnQDtlp4A7ZafAO2WoADtlqEA7ZaiAO2WowDtlqQA7ZalAO2WpgDtlqcA7ZaoAO2WqQDtlqoA7ZarAO2WrADtlq0A7ZauAO2WrwDtlrAA7ZaxAO2WsgDtlrMA7Za0AO2WtQDtlrYA7Za3AO2WuADtlrkA7Za6AO2WuwDtlrwA7Za9AO2WvgDtlr8A7ZeAAO2XgQDtl4IA7ZeDAO2XhADtl4UA7ZeGAO2XhwDtl4gA7ZeJAO2XigDtl4sA7ZeMAO2XjQDtl44A7ZePAO2XkADtl5EA7ZeSAO2XkwDtl5QA7ZeVAO2XlgDtl5cA7ZeYAO2XmQDtl5oA7ZebAO2XnADtl50A7ZeeAO2XnwDtl6AA7ZehAO2XogDtl6MA7ZekAO2XpQDtl6YA7ZenAO2XqADtl6kA7ZeqAO2XqwDtl6wA7ZetAO2XrgDtl68A7ZewAO2XsQDtl7IA7ZezAO2XtADtl7UA7Ze2AO2XtwDtl7gA7Ze5AO2XugDtl7sA7Ze8AO2XvQDtl74A7Ze/AO2YgADtmIEA7ZiCAO2YgwDtmIQA7ZiFAO2YhgDtmIcA7ZiIAO2YiQDtmIoA7ZiLAO2YjADtmI0A7ZiOAO2YjwDtmJAA7ZiRAO2YkgDtmJMA7ZiUAO2YlQDtmJYA7ZiXAO2YmADtmJkA7ZiaAO2YmwDtmJwA7ZidAO2YngDtmJ8A7ZigAO2YoQDtmKIA7ZijAO2YpADtmKUA7ZimAO2YpwDtmKgA7ZipAO2YqgDtmKsA7ZisAO2YrQDtmK4A7ZivAO2YsADtmLEA7ZiyAO2YswDtmLQA7Zi1AO2YtgDtmLcA7Zi4AO2YuQDtmLoA7Zi7AO2YvADtmL0A7Zi+AO2YvwDtmYAA7ZmBAO2ZggDtmYMA7ZmEAO2ZhQDtmYYA7ZmHAO2ZiADtmYkA7ZmKAO2ZiwDtmYwA7ZmNAO2ZjgDtmY8A7ZmQAO2ZkQDtmZIA7ZmTAO2ZlADtmZUA7ZmWAO2ZlwDtmZgA7ZmZAO2ZmgDtmZsA7ZmcAO2ZnQDtmZ4A7ZmfAO2ZoADtmaEA7ZmiAO2ZowDtmaQA7ZmlAO2ZpgDtmacA7ZmoAO2ZqQDtmaoA7ZmrAO2ZrADtma0A7ZmuAO2ZrwDtmbAA7ZmxAO2ZsgDtmbMA7Zm0AO2ZtQDtmbYA7Zm3AO2ZuADtmbkA7Zm6AO2ZuwDtmbwA7Zm9AO2ZvgDtmb8A7ZqAAO2agQDtmoIA7ZqDAO2ahADtmoUA7ZqGAO2ahwDtmogA7ZqJAO2aigDtmosA7ZqMAO2ajQDtmo4A7ZqPAO2akADtmpEA7ZqSAO2akwDtmpQA7ZqVAO2algDtmpcA7ZqYAO2amQDtmpoA7ZqbAO2anADtmp0A7ZqeAO2anwDtmqAA7ZqhAO2aogDtmqMA7ZqkAO2apQDtmqYA7ZqnAO2aqADtmqkA7ZqqAO2aqwDtmqwA7ZqtAO2argDtmq8A7ZqwAO2asQDtmrIA7ZqzAO2atADtmrUA7Zq2AO2atwDtmrgA7Zq5AO2augDtmrsA7Zq8AO2avQDtmr4A7Zq/AO2bgADtm4EA7ZuCAO2bgwDtm4QA7ZuFAO2bhgDtm4cA7ZuIAO2biQDtm4oA7ZuLAO2bjADtm40A7ZuOAO2bjwDtm5AA7ZuRAO2bkgDtm5MA7ZuUAO2blQDtm5YA7ZuXAO2bmADtm5kA7ZuaAO2bmwDtm5wA7ZudAO2bngDtm58A7ZugAO2boQDtm6IA7ZujAO2bpADtm6UA7ZumAO2bpwDtm6gA7ZupAO2bqgDtm6sA7ZusAO2brQDtm64A7ZuvAO2bsADtm7EA7ZuyAO2bswDtm7QA7Zu1AO2btgDtm7cA7Zu4AO2buQDtm7oA7Zu7AO2bvADtm70A7Zu+AO2bvwDtnIAA7ZyBAO2cggDtnIMA7ZyEAO2chQDtnIYA7ZyHAO2ciADtnIkA7ZyKAO2ciwDtnIwA7ZyNAO2cjgDtnI8A7ZyQAO2ckQDtnJIA7ZyTAO2clADtnJUA7ZyWAO2clwDtnJgA7ZyZAO2cmgDtnJsA7ZycAO2cnQDtnJ4A7ZyfAO2coADtnKEA7ZyiAO2cowDtnKQA7ZylAO2cpgDtnKcA7ZyoAO2cqQDtnKoA7ZyrAO2crADtnK0A7ZyuAO2crwDtnLAA7ZyxAO2csgDtnLMA7Zy0AO2ctQDtnLYA7Zy3AO2cuADtnLkA7Zy6AO2cuwDtnLwA7Zy9AO2cvgDtnL8A7Z2AAO2dgQDtnYIA7Z2DAO2dhADtnYUA7Z2GAO2dhwDtnYgA7Z2JAO2digDtnYsA7Z2MAO2djQDtnY4A7Z2PAO2dkADtnZEA7Z2SAO2dkwDtnZQA7Z2VAO2dlgDtnZcA7Z2YAO2dmQDtnZoA7Z2bAO2dnADtnZ0A7Z2eAO2dnwDtnaAA7Z2hAO2dogDtnaMA7Z2kAO2dpQDtnaYA7Z2nAO2dqADtnakA7Z2qAO2dqwDtnawA7Z2tAO2drgDtna8A7Z2wAO2dsQDtnbIA7Z2zAO2dtADtnbUA7Z22AO2dtwDtnbgA7Z25AO2dugDtnbsA7Z28AO2dvQDtnb4A7Z2/AO2egADtnoEA7Z6CAO2egwDtnoQA7Z6FAO2ehgDtnocA7Z6IAO2eiQDtnooA7Z6LAO2ejADtno0A7Z6OAO2ejwDtnpAA7Z6RAO2ekgDtnpMA7Z6UAO2elQDtnpYA7Z6XAO2emADtnpkA7Z6aAO2emwDtnpwA7Z6dAO2engDtnp8A7Z6gAO2eoQDtnqIA7Z6jAPCRgpoA8JGCnADwkYKrAPCRhK4A8JGErwDwkY2LAPCRjYwA8JGSuwDwkZK8APCRkr4A8JGWugDwkZa7APCdhZfwnYWlAPCdhZjwnYWlAPCdhZjwnYWl8J2FrgDwnYWY8J2FpfCdha8A8J2FmPCdhaXwnYWwAPCdhZjwnYWl8J2FsQDwnYWY8J2FpfCdhbIA8J2GufCdhaUA8J2GufCdhaXwnYWuAPCdhrnwnYWl8J2FrwDwnYa68J2FpQDwnYa68J2FpfCdha4A8J2GuvCdhaXwnYWvAPCghKIA8KCUnADwoJSlAPCglYsA8KCYugDwoKCEAPCgo54A8KCorADwoK2jAPChk6QA8KGaqADwoZuqAPChp4gA8KGsmADwobSLAPCht6QA8KG3pgDwooaDAPCihp8A8KKMsQDwopuUAPCioYQA8KKhigDwoqyMAPCir7EA8KOAigDwo4q4APCjjZ8A8KOOkwDwo46cAPCjj4MA8KOPlQDwo5GtAPCjmqMA8KOipwDwo6qNAPCjq7oA8KOyvADwo7SeAPCju5EA8KO9ngDwo76OAPCkiaMA8KSLrgDwpI6rAPCkmIgA8KSctQDwpKCUAPCksLYA8KSykgDwpL6hAPCkvrgA8KWBhADwpYOyAPClg7MA8KWEmQDwpYSzAPCliYkA8KWQnQDwpZimAPClmpoA8KWbhQDwpaW8APClqqcA8KWuqwDwpbKAAPCls5AA8KW+hgDwpoeaAPCmiKgA8KaJhwDwpouZAPCmjL4A8KaTmgDwppSjAPCmlqgA8KaepwDwpp61APCmrLwA8KawtgDwprOVAPCmtasA8Ka8rADwpr6xAPCng5IA8KePigDwp5mnAPCnoq4A8KelpgDwp7KoAPCnu5MA8Ke8rwDwqJeSAPCol60A8KicrgDwqK+6APCotbcA8KmFhQDwqYefAPCpiJoA8KmQigDwqZKWAPCplrYA8KmssADwqoOOAPCqhIUA8KqIjgDwqoqRAPCqjpIA8KqYgAA=", +"pieces":{"":[0,0.0],"":[1,0.0],"":[2,0.0],"":[3,0.0],",":[4,-3.4635426998138428],".":[5,-3.625642776489258],"▁":[6,-3.9299705028533936],"s":[7,-5.072621822357178],"▁de":[8,-5.306643009185791],"-":[9,-5.404437065124512],"▁a":[10,-5.530364990234375],"a":[11,-5.5477118492126465],":":[12,-5.629745960235596],"e":[13,-5.701941967010498],"i":[14,-5.785372257232666],"▁(":[15,-5.926211357116699],")":[16,-5.9974517822265625],"▁i":[17,-6.0461626052856445],"t":[18,-6.071900844573975],"n":[19,-6.093497276306152],"▁-":[20,-6.1764984130859375],"▁la":[21,-6.233835697174072],"▁en":[22,-6.31805419921875],"▁in":[23,-6.3201680183410645],"▁na":[24,-6.327768802642822],"'":[25,-6.345553398132324],"▁e":[28,-6.3929057121276855],"o":[31,-6.417782306671143],"?":[32,-6.460666179656982],"en":[33,-6.465692520141602],"u":[34,-6.467804431915283],"▁o":[36,-6.582267761230469],"m":[39,-6.647110939025879],"▁se":[40,-6.716159820556641],"▁que":[41,-6.732594966888428],"r":[42,-6.7604851722717285],"▁di":[45,-6.818948268890381],"▁to":[47,-6.913968563079834],"▁da":[48,-6.9197258949279785],"▁un":[51,-6.960879325866699],"y":[53,-6.976414203643799],"er":[56,-7.031227111816406],"▁sa":[57,-7.0481696128845215],"▁A":[62,-7.08988618850708],"/":[64,-7.158257007598877],"an":[66,-7.205831050872803],"te":[67,-7.230983257293701],"▁the":[70,-7.283115386962891],"d":[71,-7.293672561645508],"in":[73,-7.297125816345215],"▁u":[75,-7.319528579711914],"na":[76,-7.320949554443359],"▁si":[78,-7.355116367340088],"da":[85,-7.412682056427002],"ne":[86,-7.417489528656006],"▁I":[87,-7.424222946166992],"es":[90,-7.441272735595703],"▁s":[91,-7.452380657196045],"k":[92,-7.471577644348144],"▁le":[95,-7.475855827331543],"▁l":[96,-7.482025623321533],"▁z":[97,-7.490857124328613],"▁on":[98,-7.491168022155762],"▁at":[99,-7.494873046875],"▁for":[100,-7.498734951019287],"ta":[102,-7.511834144592285],"▁d":[104,-7.537978649139404],"▁1":[106,-7.551031589508057],"re":[107,-7.563330173492432],"▁ne":[108,-7.563854217529297],"▁no":[110,-7.56878137588501],"▁of":[111,-7.573562145233154],"de":[112,-7.589335918426514],"▁y":[113,-7.591180801391602],"▁2":[116,-7.619575500488281],"▁per":[117,-7.621859550476074],"ti":[118,-7.62448787689209],"▁te":[120,-7.653661727905273],"et":[126,-7.697822093963623],"h":[127,-7.701241970062256],"(":[132,-7.722129821777344],"le":[133,-7.727717399597168],"▁and":[136,-7.75172758102417],"▁3":[138,-7.759578704833984],"▁til":[139,-7.760351657867432],"l":[141,-7.762022495269775],"▁an":[142,-7.762918949127197],"la":[143,-7.770702362060547],"▁al":[144,-7.77080488204956],"ar":[147,-7.794132709503174],"▁w":[148,-7.80467700958252],"li":[150,-7.818939208984375],"no":[157,-7.8542914390563965],"▁con":[158,-7.861650943756104],"▁S":[159,-7.863271236419678],"▁po":[160,-7.864959716796875],"as":[162,-7.871861934661865],"▁me":[163,-7.873553276062012],"is":[164,-7.876260757446289],"▁und":[165,-7.879409313201904],"▁su":[166,-7.880402088165283],"z":[169,-7.898513317108154],"j":[170,-7.900866031646728],"si":[172,-7.915489196777344],"g":[177,-7.932966709136963],"ي":[179,-7.946563243865967],"▁O":[180,-7.966879844665527],"se":[184,-7.985258102416992],"▁ar":[187,-7.993113040924072],"to":[188,-8.000646591186523],"▁5":[190,-8.026392936706543],"on":[191,-8.028497695922852],"ma":[192,-8.039029121398926],"em":[195,-8.047385215759277],"▁les":[199,-8.06153392791748],"▁4":[201,-8.062232971191406],"ul":[202,-8.066244125366211],"ch":[206,-8.075675010681152],"ga":[208,-8.08101749420166],"▁10":[209,-8.092198371887207],"ing":[214,-8.10777473449707],"it":[217,-8.12078857421875],"ra":[219,-8.134736061096191],"▁so":[221,-8.140031814575195],"us":[223,-8.146340370178223],"▁des":[224,-8.153715133666992],"os":[232,-8.170713424682617],"▁op":[233,-8.17135238647461],"▁as":[237,-8.189149856567383],"c":[238,-8.199555397033691],"▁'":[242,-8.20328426361084],"▁att":[243,-8.205853462219238],"do":[246,-8.21650505065918],"),":[247,-8.222518920898438],"▁/":[248,-8.223021507263184],"▁pa":[249,-8.223164558410645],"ة":[250,-8.223382949829102],"p":[254,-8.232597351074219],"at":[257,-8.248958587646484],"ا":[258,-8.25012493133545],"▁wa":[259,-8.251487731933594],"▁af":[261,-8.259132385253906],"mi":[266,-8.26934814453125],"]":[268,-8.270896911621094],"st":[271,-8.2816801071167],"ve":[272,-8.281817436218262],"b":[275,-8.289443016052246],"▁M":[276,-8.293008804321289],"com":[277,-8.293252944946289],"▁pe":[280,-8.298158645629883],"が":[281,-8.302067756652832],"me":[282,-8.302555084228516],"A":[284,-8.304994583129883],"al":[289,-8.325163841247559],"▁ma":[291,-8.327710151672363],"S":[294,-8.335785865783691],"ed":[297,-8.355191230773926],"am":[302,-8.36097240447998],"2":[304,-8.369061470031738],"▁6":[305,-8.376090049743652],"om":[306,-8.37712574005127],"▁ta":[308,-8.378125190734863],"un":[309,-8.381165504455566],"▁ke":[311,-8.390829086303711],"▁C":[313,-8.396952629089355],"▁cu":[314,-8.398150444030762],"ci":[318,-8.413408279418945],"ce":[329,-8.450657844543457],"va":[330,-8.4537353515625],"v":[334,-8.47355842590332],"▁B":[335,-8.477783203125],"▁bo":[337,-8.481490135192871],"▁L":[339,-8.484365463256836],"▁K":[341,-8.490921020507812],"ek":[343,-8.49502944946289],"ak":[344,-8.496010780334473],"▁U":[345,-8.497254371643066],"▁m":[347,-8.4979887008667],"ke":[350,-8.504961013793945],"▁em":[352,-8.507031440734863],"▁ال":[359,-8.52457332611084],"▁In":[360,-8.524736404418945],"▁7":[361,-8.525569915771484],"3":[363,-8.533885955810547],"lo":[365,-8.545232772827148],"의":[367,-8.548405647277832],"be":[372,-8.558698654174805],"▁bu":[373,-8.560547828674316],"▁com":[375,-8.566923141479492],"▁ca":[377,-8.569270133972168],"▁[":[378,-8.569624900817871],"il":[379,-8.571856498718262],"▁T":[384,-8.577641487121582],"▁20":[387,-8.58205795288086],"▁by":[390,-8.587043762207031],"▁D":[391,-8.591439247131348],"▁é":[393,-8.59322738647461],"D":[397,-8.609557151794434],"ia":[399,-8.611927032470703],"▁li":[400,-8.615797996520996],"ba":[402,-8.622004508972168],"▁ce":[405,-8.626120567321777],"ca":[408,-8.631218910217285],"▁mai":[409,-8.63427448272705],"을":[413,-8.642354965209961],"ri":[416,-8.647806167602539],"1":[418,-8.649255752563477],"f":[420,-8.649986267089844],"▁15":[423,-8.653078079223633],"x":[425,-8.660321235656738],"▁12":[427,-8.663192749023438],"di":[428,-8.6665678024292],"ge":[429,-8.66818904876709],"mo":[432,-8.675875663757324],"sa":[433,-8.679758071899414],"w":[434,-8.682831764221191],"▁P":[436,-8.68532657623291],"C":[441,-8.699597358703613],"▁it":[442,-8.702272415161133],"▁am":[444,-8.705870628356934],"é":[446,-8.712347030639648],"ng":[449,-8.720099449157715],"▁that":[450,-8.72273063659668],"_":[454,-8.72813892364502],"▁re":[456,-8.729783058166504],"tu":[458,-8.734413146972656],"▁lo":[459,-8.736749649047852],"im":[464,-8.739598274230957],"▁#":[468,-8.741698265075684],"이":[469,-8.746895790100098],"▁k":[472,-8.752243041992188],"ur":[474,-8.754871368408203],"ie":[478,-8.761056900024414],"에":[480,-8.765233993530273],"ir":[481,-8.765268325805664],"▁pri":[494,-8.787092208862305],"▁30":[496,-8.791316032409668],"ho":[497,-8.792523384094238],"▁c":[501,-8.796775817871094],"▁Se":[503,-8.802419662475586],"ai":[508,-8.807412147521973],"ten":[510,-8.811378479003906],"中":[514,-8.817706108093262],"ov":[515,-8.817838668823242],"ro":[516,-8.818936347961426],"go":[519,-8.825934410095215],"est":[525,-8.8350191116333],"▁G":[527,-8.841058731079102],"ha":[528,-8.841383934020996],"▁au":[531,-8.866000175476074],"id":[532,-8.866331100463867],"▁11":[534,-8.870092391967773],"ly":[538,-8.873795509338379],"nu":[539,-8.873832702636719],"▁N":[541,-8.878573417663574],"▁co":[552,-8.900552749633789],"▁F":[563,-8.916865348815918],"I":[568,-8.919625282287598],"B":[571,-8.923480033874512],"▁The":[581,-8.943010330200195],"el":[583,-8.945587158203125],"co":[587,-8.9508695602417],"sta":[590,-8.956795692443848],"ل":[593,-8.963071823120117],"M":[594,-8.964536666870117],"lik":[597,-8.972264289855957],"▁W":[601,-8.98157024383545],"▁her":[604,-8.984784126281738],"K":[605,-8.985796928405762],"▁ad":[606,-8.98613166809082],"▁dat":[607,-8.988334655761719],"ת":[609,-8.990631103515625],"▁14":[616,-8.998332977294922],"4":[617,-8.99893856048584],"T":[618,-9.00064754486084],"▁R":[627,-9.0201997756958],"▁ou":[628,-9.020796775817873],"wa":[634,-9.028922080993652],"日":[635,-9.031612396240234],"▁we":[642,-9.039949417114258],"▁over":[645,-9.040912628173828],"E":[647,-9.044665336608888],"ية":[648,-9.046391487121582],"▁n":[653,-9.052701950073242],"ji":[658,-9.062299728393556],"ी":[659,-9.066560745239258],"nt":[660,-9.067607879638672],"▁Po":[663,-9.069149017333984],"O":[670,-9.076007843017578],"▁with":[678,-9.09117603302002],"P":[683,-9.098166465759276],"ok":[685,-9.102860450744627],"vi":[686,-9.103118896484377],"를":[688,-9.106209754943848],"은":[697,-9.116799354553224],"▁ge":[700,-9.124996185302734],"▁g":[706,-9.131820678710938],"▁or":[707,-9.134698867797852],"י":[710,-9.137608528137209],"ad":[712,-9.13996124267578],"가":[713,-9.140023231506348],"ter":[720,-9.146991729736328],"G":[724,-9.1488676071167],"ze":[731,-9.15980339050293],"gi":[735,-9.16303253173828],"▁go":[738,-9.165409088134766],"or":[748,-9.172828674316406],"▁all":[756,-9.17773723602295],"5":[758,-9.180099487304688],"ban":[761,-9.18553352355957],"pa":[763,-9.186735153198242],"▁he":[764,-9.18873119354248],"는":[769,-9.197030067443848],"po":[771,-9.199155807495115],"ik":[783,-9.217286109924316],"ou":[796,-9.239537239074709],"▁Ne":[799,-9.243203163146973],"▁t":[808,-9.253575325012209],"▁fi":[809,-9.255378723144531],"ver":[814,-9.257781982421877],"ot":[818,-9.267127990722656],"der":[820,-9.268291473388672],"lu":[822,-9.268874168395996],"ste":[824,-9.270514488220217],"ر":[835,-9.2794771194458],"bo":[837,-9.282983779907228],"N":[839,-9.288337707519531],"mos":[840,-9.288402557373049],"io":[846,-9.292072296142578],"▁Re":[853,-9.299670219421388],"V":[856,-9.304312705993652],"q":[864,-9.32458209991455],"L":[866,-9.324870109558104],"tar":[867,-9.32560920715332],"ig":[872,-9.330278396606444],"▁b":[876,-9.331740379333496],"▁ا":[878,-9.33310604095459],"ru":[882,-9.334487915039062],"ina":[885,-9.335424423217772],"▁inte":[892,-9.339412689208984],"oj":[897,-9.346899032592772],"▁this":[903,-9.35264015197754],"6":[910,-9.360912322998049],"▁Ma":[911,-9.36208724975586],"▁p":[915,-9.365259170532228],"au":[916,-9.367286682128906],"F":[919,-9.36932373046875],"th":[927,-9.384464263916016],"ol":[929,-9.387616157531738],"▁Da":[930,-9.387701034545898],"▁mo":[931,-9.38770866394043],"▁ze":[932,-9.390381813049316],"ts":[933,-9.390750885009766],"ach":[934,-9.39092254638672],"ty":[939,-9.393775939941406],"que":[944,-9.400616645812988],"▁sy":[954,-9.412508964538574],"▁not":[959,-9.417351722717283],"▁ba":[961,-9.417988777160645],"10":[963,-9.42248821258545],"vo":[965,-9.424642562866213],"7":[966,-9.427630424499512],"bu":[978,-9.437965393066406],"hi":[979,-9.438912391662598],"@":[981,-9.441329956054688],"ren":[982,-9.441865921020508],"tur":[987,-9.44681167602539],"des":[988,-9.447047233581545],"▁Y":[990,-9.448863983154297],"so":[991,-9.451133728027344],"한":[993,-9.45376968383789],"न":[998,-9.46140956878662],"ut":[1003,-9.46432113647461],"cu":[1010,-9.470626831054688],"sen":[1015,-9.47447681427002],"▁수":[1020,-9.47888469696045],"fa":[1021,-9.479153633117676],"▁x":[1022,-9.481934547424316],"fi":[1029,-9.48967456817627],"▁ac":[1030,-9.490610122680664],"ye":[1033,-9.492547988891602],"sk":[1042,-9.498204231262209],"are":[1046,-9.50424575805664],"도":[1048,-9.505677223205566],"R":[1052,-9.508118629455566],"▁ti":[1053,-9.509035110473633],"U":[1062,-9.51954174041748],"[":[1065,-9.522266387939451],"nde":[1067,-9.524624824523926],"▁fa":[1071,-9.527026176452637],"tas":[1073,-9.528417587280272],"고":[1077,-9.533198356628418],"pe":[1081,-9.535565376281738],"로":[1083,-9.536968231201172],"sti":[1084,-9.539387702941896],"▁h":[1096,-9.553081512451172],"ken":[1098,-9.554195404052734],"▁qu":[1103,-9.556811332702637],"he":[1106,-9.557723999023438],"▁mar":[1108,-9.56204891204834],"▁40":[1112,-9.566628456115724],"▁ex":[1119,-9.569488525390623],"han":[1121,-9.569931983947754],"9":[1126,-9.574579238891602],"hu":[1132,-9.57785987854004],"`":[1135,-9.581768035888672],"▁sig":[1144,-9.587881088256836],"ene":[1151,-9.59463596343994],"▁tra":[1152,-9.594686508178713],"zo":[1158,-9.599873542785645],"su":[1159,-9.600014686584473],"we":[1177,-9.614883422851562],"net":[1179,-9.616982460021973],"에서":[1180,-9.61751651763916],"ll":[1181,-9.62045955657959],"지":[1190,-9.625944137573242],"ami":[1191,-9.62611198425293],"ع":[1195,-9.628833770751951],"30":[1197,-9.629667282104492],"▁Ko":[1204,-9.635401725769045],"ine":[1212,-9.642523765563965],"▁Ta":[1218,-9.644025802612305],"ks":[1224,-9.65139865875244],"gu":[1234,-9.655814170837402],"ant":[1236,-9.657833099365234],"▁f":[1238,-9.658580780029297],"min":[1249,-9.663958549499512],"▁up":[1257,-9.670775413513184],"▁Li":[1261,-9.673724174499512],"per":[1264,-9.67483139038086],"by":[1272,-9.67880153656006],"▁hi":[1274,-9.678874969482422],"·":[1280,-9.681750297546388],"ال":[1282,-9.682504653930664],"rea":[1283,-9.682531356811523],"▁but":[1284,-9.682559967041016],"tor":[1290,-9.685091018676758],"과":[1291,-9.685598373413086],"ry":[1294,-9.69105052947998],"ber":[1297,-9.693892478942873],"▁As":[1301,-9.698895454406738],"▁post":[1305,-9.702012062072754],"な":[1308,-9.70376205444336],"▁Co":[1311,-9.705989837646484],"ers":[1314,-9.706972122192385],"ب":[1325,-9.714176177978516],"ile":[1340,-9.71994400024414],"ere":[1357,-9.733800888061523],"tion":[1363,-9.73834228515625],"=":[1369,-9.746337890625],"▁@":[1374,-9.750085830688477],"▁ag":[1377,-9.751761436462402],"▁under":[1379,-9.754140853881836],"ei":[1399,-9.77113914489746],"val":[1405,-9.775945663452148],"lan":[1414,-9.782549858093262],"iz":[1418,-9.783759117126465],"ist":[1419,-9.78423023223877],"che":[1430,-9.789331436157228],"pi":[1434,-9.791221618652344],"cha":[1436,-9.79363250732422],"nes":[1444,-9.799863815307615],"W":[1456,-9.80726718902588],"ang":[1463,-9.814218521118164],"▁dig":[1466,-9.816262245178224],"nte":[1479,-9.82237720489502],"ite":[1486,-9.825878143310549],"▁sen":[1490,-9.82648468017578],"sh":[1495,-9.830385208129885],"▁60":[1496,-9.83043384552002],"ana":[1500,-9.830772399902344],"기":[1503,-9.832951545715332],"▁이":[1504,-9.833052635192873],"ger":[1505,-9.83632469177246],"mas":[1510,-9.839102745056152],"ster":[1515,-9.84419059753418],"本":[1516,-9.844562530517578],"tra":[1517,-9.845602989196776],"12":[1530,-9.852426528930664],"20":[1549,-9.859763145446776],"인":[1571,-9.870577812194824],"les":[1577,-9.87338161468506],"sin":[1596,-9.885518074035645],"일":[1599,-9.887825012207031],"▁zo":[1602,-9.888474464416504],"▁cha":[1608,-9.89179229736328],"▁one":[1632,-9.90587043762207],"tes":[1636,-9.909648895263672],"으로":[1654,-9.91943645477295],"11":[1662,-9.924934387207031],"og":[1663,-9.924964904785156],"ud":[1674,-9.929936408996582],"▁r":[1690,-9.938166618347168],"era":[1704,-9.944847106933594],"Y":[1723,-9.954444885253906],"ata":[1724,-9.954557418823242],"mar":[1727,-9.956571578979492],"ker":[1728,-9.956841468811035],"▁time":[1733,-9.960152626037598],"lig":[1746,-9.965150833129885],"▁ap":[1747,-9.965554237365724],"ens":[1755,-9.967814445495604],"iga":[1758,-9.96905517578125],"ic":[1771,-9.977563858032228],"▁Dr":[1773,-9.978767395019531],"▁plan":[1774,-9.980316162109377],"ns":[1779,-9.98166847229004],"▁out":[1810,-9.999876976013184],"▁us":[1821,-10.005047798156738],"ion":[1830,-10.007582664489746],"▁they":[1836,-10.009111404418944],"15":[1837,-10.009882926940918],"다":[1875,-10.031167030334473],"cia":[1883,-10.036248207092283],"▁like":[1884,-10.03654670715332],"ati":[1888,-10.04028606414795],"ting":[1916,-10.051998138427734],"▁sta":[1924,-10.05655574798584],"▁lang":[1937,-10.064451217651367],"▁inter":[1940,-10.065033912658691],"var":[1961,-10.076531410217283],"해":[1963,-10.077872276306152],"let":[1974,-10.084388732910156],"ב":[1982,-10.088537216186523],"mer":[1991,-10.093677520751951],"와":[2020,-10.108624458312988],"▁Am":[2022,-10.11007308959961],"up":[2037,-10.117767333984377],"▁net":[2043,-10.12051486968994],"▁get":[2046,-10.121017456054688],"▁data":[2053,-10.126009941101074],"ab":[2055,-10.128340721130373],"▁ro":[2062,-10.132527351379396],"ica":[2063,-10.132535934448242],"mail":[2065,-10.133148193359377],"ling":[2069,-10.136800765991213],"▁pag":[2070,-10.137310981750488],"리":[2085,-10.141365051269531],"사":[2099,-10.148526191711426],"ili":[2104,-10.149961471557615],"하는":[2123,-10.157720565795898],"op":[2146,-10.16852569580078],"▁pi":[2147,-10.169116020202637],"▁On":[2161,-10.174945831298828],"시":[2166,-10.17652702331543],"스":[2171,-10.17860984802246],"rat":[2175,-10.180675506591797],"ate":[2182,-10.182609558105469],"ser":[2189,-10.184370994567873],"od":[2199,-10.188192367553713],"nd":[2208,-10.192818641662598],"어":[2211,-10.194202423095703],"mat":[2227,-10.201783180236816],"fe":[2242,-10.20844841003418],"line":[2256,-10.213820457458496],"ac":[2263,-10.216479301452637],"ret":[2264,-10.216818809509276],"자":[2268,-10.220314025878906],"con":[2271,-10.220809936523438],"pen":[2278,-10.22235107421875],"수":[2280,-10.22321605682373],"서":[2293,-10.228710174560549],"~":[2306,-10.232641220092772],"tta":[2310,-10.237249374389648],"tin":[2311,-10.238265991210938],"ation":[2320,-10.240924835205078],"the":[2347,-10.252835273742676],"▁New":[2356,-10.255802154541016],"▁what":[2367,-10.260702133178713],"▁ano":[2373,-10.263166427612305],"하고":[2382,-10.266958236694336],"0":[2389,-10.270647048950195],"lin":[2397,-10.273252487182615],"af":[2407,-10.27530002593994],"cy":[2408,-10.275564193725586],"▁ye":[2422,-10.28310203552246],"pl":[2424,-10.2833890914917],"ר":[2442,-10.290753364562988],"▁our":[2446,-10.2923002243042],"wi":[2452,-10.294123649597168],"할":[2461,-10.296403884887695],"for":[2472,-10.300384521484377],"ft":[2480,-10.302947998046877],"ity":[2481,-10.30307960510254],"par":[2500,-10.308599472045898],"▁Mo":[2501,-10.30864143371582],"ide":[2506,-10.31063747406006],"eg":[2507,-10.310992240905762],"las":[2512,-10.312142372131348],"ara":[2514,-10.313234329223633],"▁lan":[2515,-10.313328742980955],"ent":[2517,-10.313552856445312],"文":[2564,-10.328255653381348],"▁word":[2565,-10.328483581542969],"25":[2588,-10.33994483947754],"14":[2592,-10.341371536254885],"ck":[2594,-10.341519355773926],"owe":[2600,-10.343954086303713],"vel":[2601,-10.344741821289062],"imi":[2605,-10.34861183166504],"ici":[2624,-10.355048179626465],"▁그":[2625,-10.356576919555664],"ap":[2631,-10.35852336883545],"▁let":[2633,-10.359158515930176],"▁pan":[2652,-10.364526748657228],"ble":[2661,-10.36789608001709],"▁top":[2663,-10.368497848510742],"▁300":[2668,-10.37183952331543],"mp":[2676,-10.375411033630373],"rin":[2677,-10.37561321258545],"년":[2680,-10.376415252685549],"▁most":[2684,-10.37738037109375],"주":[2688,-10.378337860107422],"ag":[2703,-10.384281158447266],">":[2740,-10.39428424835205],"▁who":[2750,-10.398574829101562],"ית":[2754,-10.399799346923828],"▁Mu":[2758,-10.401588439941406],"rit":[2783,-10.407776832580566],"sto":[2785,-10.408238410949709],"40":[2839,-10.425334930419922],"bra":[2844,-10.427148818969728],"ring":[2852,-10.430377006530762],"▁them":[2856,-10.43118667602539],"fer":[2875,-10.436775207519531],"able":[2886,-10.440007209777832],"정":[2905,-10.445311546325684],"ova":[2914,-10.447529792785645],"▁cel":[2927,-10.45139980316162],"and":[2940,-10.45492172241211],"hat":[2943,-10.456612586975098],"19":[2947,-10.457674980163574],"tro":[2955,-10.460393905639648],"ice":[2980,-10.465516090393066],"tem":[2982,-10.466638565063477],"ito":[2986,-10.467925071716309],"▁Cu":[3003,-10.47216796875],"장":[3013,-10.475115776062012],"대":[3032,-10.480751037597656],"▁test":[3034,-10.481038093566896],"din":[3035,-10.481141090393066],"द":[3044,-10.484370231628418],"tter":[3055,-10.487408638000488],"tt":[3062,-10.489277839660645],"lang":[3066,-10.490046501159668],"▁한":[3103,-10.497684478759766],"ige":[3112,-10.499937057495115],"▁ru":[3114,-10.500371932983398],"ua":[3116,-10.50047206878662],"fu":[3125,-10.503440856933594],"▁link":[3126,-10.504199981689451],"ves":[3132,-10.50530242919922],"eve":[3134,-10.505517959594728],"tte":[3135,-10.505537986755373],"lim":[3141,-10.50583553314209],"▁Ad":[3145,-10.508672714233398],"게":[3156,-10.512680053710938],"nou":[3165,-10.51527976989746],"pan":[3180,-10.519183158874512],"만":[3184,-10.51952838897705],"if":[3190,-10.521430015563965],"rt":[3198,-10.523581504821776],"wan":[3206,-10.525075912475586],"아":[3222,-10.52936840057373],"tha":[3238,-10.533196449279783],"ec":[3240,-10.533754348754885],"▁tas":[3251,-10.536897659301758],"ย":[3265,-10.541543960571287],"br":[3267,-10.542113304138184],"▁Com":[3288,-10.546387672424316],"▁tha":[3319,-10.55436897277832],"her":[3334,-10.558793067932127],"ay":[3337,-10.558917045593262],"▁email":[3340,-10.559274673461914],"ex":[3355,-10.562864303588867],"ian":[3378,-10.567450523376465],"ท":[3380,-10.568387031555176],"상":[3394,-10.57007884979248],"▁ann":[3398,-10.570634841918944],"▁ev":[3404,-10.571887016296388],"ure":[3408,-10.572360038757324],"▁pla":[3412,-10.57325267791748],"라":[3440,-10.578653335571287],"▁want":[3444,-10.579343795776367],"▁id":[3447,-10.580293655395508],"pro":[3454,-10.58215618133545],"har":[3467,-10.5840425491333],"ket":[3473,-10.58580493927002],"sia":[3478,-10.58627700805664],"나":[3497,-10.590023040771484],"▁than":[3501,-10.591230392456056],"set":[3509,-10.59201717376709],"▁new":[3525,-10.597224235534668],"▁were":[3542,-10.601404190063477],"ि":[3558,-10.604382514953612],"▁end":[3564,-10.605533599853516],"원":[3575,-10.607780456542969],"fo":[3584,-10.609647750854492],"日本":[3589,-10.61032772064209],"nti":[3598,-10.613425254821776],"ime":[3602,-10.614575386047363],"end":[3611,-10.616128921508787],"wo":[3613,-10.616158485412598],"부":[3614,-10.616432189941406],"▁전":[3626,-10.619794845581056],"▁tom":[3627,-10.619990348815918],"one":[3630,-10.62038230895996],"▁$":[3650,-10.62550449371338],"트":[3659,-10.6273832321167],"화":[3665,-10.630173683166504],"lag":[3668,-10.630544662475586],"ted":[3674,-10.6329927444458],"til":[3675,-10.633220672607422],"unk":[3678,-10.633880615234377],"eren":[3683,-10.635190963745115],"▁Fi":[3698,-10.63893985748291],"▁pol":[3722,-10.644521713256836],"23":[3742,-10.649659156799316],"vit":[3760,-10.652471542358398],"적":[3761,-10.652782440185549],"전":[3776,-10.655546188354492],"월":[3785,-10.65719985961914],"get":[3794,-10.65964412689209],"mon":[3796,-10.65986442565918],"xa":[3798,-10.660585403442385],"ह":[3849,-10.672579765319824],"▁ch":[3863,-10.675163269042969],"▁pos":[3864,-10.675272941589355],"▁need":[3871,-10.676177978515623],"▁ana":[3877,-10.677079200744627],"ano":[3922,-10.686440467834473],"ori":[3929,-10.68796730041504],"▁into":[3934,-10.6882905960083],"adi":[3938,-10.689024925231934],"%":[3949,-10.691938400268556],"nce":[3956,-10.692818641662598],"The":[3957,-10.693048477172852],"art":[3960,-10.69340705871582],"▁lite":[3961,-10.693577766418455],"gr":[3964,-10.693774223327637],"▁Kor":[3970,-10.694382667541504],"mit":[4007,-10.701736450195312],"ong":[4021,-10.704148292541504],"▁app":[4027,-10.705123901367188],"dd":[4028,-10.70519733428955],"use":[4032,-10.705951690673828],"진":[4033,-10.706058502197266],"▁start":[4034,-10.706148147583008],"ero":[4036,-10.70627784729004],"▁pr":[4083,-10.714747428894045],"ix":[4084,-10.714842796325684],"lis":[4086,-10.715089797973633],"드":[4087,-10.715336799621582],"hr":[4097,-10.71687126159668],"ע":[4113,-10.720516204833984],"In":[4153,-10.72837734222412],"동":[4156,-10.728917121887209],"kt":[4164,-10.73136043548584],"liga":[4172,-10.73279857635498],"ら":[4182,-10.735257148742676],"ges":[4188,-10.73671531677246],"ett":[4204,-10.740470886230469],"eri":[4207,-10.741018295288086],"▁--":[4210,-10.741857528686523],"rd":[4216,-10.742291450500488],"bus":[4223,-10.743752479553224],"Se":[4233,-10.746171951293944],"ef":[4240,-10.74713134765625],"면":[4253,-10.749700546264648],"inu":[4266,-10.752889633178713],"비":[4274,-10.75441551208496],"int":[4288,-10.756415367126465],"rs":[4295,-10.757959365844728],"pad":[4299,-10.758810997009276],"▁tr":[4307,-10.759953498840332],"▁wo":[4323,-10.761848449707031],"▁design":[4331,-10.76347541809082],"Re":[4332,-10.763513565063477],"lit":[4353,-10.767278671264648],"▁help":[4358,-10.768178939819336],"$":[4369,-10.770792007446287],"iv":[4371,-10.771116256713867],"्":[4377,-10.772406578063965],"zer":[4383,-10.773547172546388],"of":[4390,-10.775018692016602],"▁back":[4420,-10.780427932739258],"▁<":[4426,-10.781867027282717],"ms":[4432,-10.782703399658203],"don":[4445,-10.787264823913574],"tr":[4448,-10.787964820861816],"thi":[4450,-10.788078308105469],"▁gr":[4452,-10.788141250610352],"pat":[4453,-10.788232803344728],"hin":[4505,-10.795955657958984],"mor":[4514,-10.79673671722412],"ep":[4517,-10.797229766845703],"ore":[4524,-10.79817008972168],"▁use":[4527,-10.798662185668944],"ente":[4574,-10.80748176574707],"구":[4584,-10.809459686279297],"age":[4588,-10.80976104736328],"post":[4594,-10.81084156036377],"60":[4598,-10.811643600463867],"▁ban":[4599,-10.811649322509766],"Ma":[4613,-10.814335823059082],"▁bank":[4620,-10.816513061523438],"제":[4654,-10.823037147521973],"por":[4680,-10.82792854309082],"erna":[4688,-10.829288482666016],"aga":[4729,-10.83771800994873],"▁only":[4734,-10.838662147521973],"chu":[4776,-10.844799041748049],"ys":[4778,-10.845044136047363],"dig":[4803,-10.851587295532228],"ev":[4854,-10.860957145690918],"sy":[4861,-10.861842155456545],"log":[4867,-10.862459182739258],"este":[4896,-10.867850303649902],"ff":[4902,-10.869224548339844],"#":[4904,-10.869548797607422],"sor":[4970,-10.880399703979492],"90":[5039,-10.89376735687256],"선":[5050,-10.894790649414062],"like":[5062,-10.896495819091797],"ean":[5073,-10.8983793258667],"▁loo":[5078,-10.89915943145752],"tim":[5083,-10.89977741241455],"요":[5144,-10.906970977783203],"sid":[5151,-10.907408714294434],"▁say":[5154,-10.907816886901855],"▁day":[5155,-10.907822608947754],"dat":[5164,-10.909542083740234],"ces":[5170,-10.910429000854492],"▁main":[5201,-10.91452407836914],"▁sp":[5213,-10.91666316986084],"▁유":[5241,-10.920682907104492],"hed":[5252,-10.922823905944824],"lay":[5259,-10.923389434814451],"pri":[5293,-10.929638862609863],"신":[5301,-10.93061351776123],"▁list":[5303,-10.931191444396973],"▁bus":[5324,-10.934947967529297],"▁ע":[5332,-10.935863494873049],"용":[5358,-10.93943977355957],"▁special":[5361,-10.940034866333008],"▁120":[5390,-10.94435691833496],"pet":[5408,-10.946587562561035],"▁ide":[5415,-10.94773006439209],"ins":[5425,-10.948890686035156],"▁system":[5426,-10.948989868164062],"wr":[5429,-10.949507713317873],"▁중":[5432,-10.950014114379885],"over":[5465,-10.954078674316406],"했다":[5476,-10.95668888092041],"qu":[5490,-10.95865535736084],"▁br":[5491,-10.958693504333496],"न्":[5500,-10.960076332092283],"ost":[5510,-10.962897300720217],"▁tim":[5527,-10.964725494384766],"▁الع":[5537,-10.966026306152344],"mai":[5545,-10.966943740844728],"tio":[5565,-10.969518661499023],"▁aga":[5575,-10.97060489654541],"명":[5576,-10.970749855041504],"all":[5584,-10.971650123596191],"▁sou":[5595,-10.973382949829102],"▁side":[5609,-10.975884437561035],"star":[5613,-10.976736068725586],"▁date":[5622,-10.97793960571289],"▁spa":[5623,-10.977968215942385],"day":[5636,-10.97898292541504],"미":[5645,-10.98058032989502],"oli":[5674,-10.98490047454834],"▁th":[5675,-10.984980583190918],"하게":[5681,-10.985615730285645],"gra":[5739,-10.994563102722168],"▁York":[5753,-10.995923042297363],"세":[5770,-10.997725486755373],"▁off":[5773,-10.997976303100586],"▁fo":[5775,-10.998577117919922],"ivo":[5777,-10.998699188232422],"마":[5779,-10.998960494995115],"▁too":[5792,-11.000832557678224],"▁보":[5807,-11.0034761428833],"입니다":[5826,-11.007415771484377],"▁주":[5837,-11.00845718383789],"ive":[5844,-11.00887393951416],"plan":[5868,-11.011960983276367],"zon":[5870,-11.01216983795166],"eva":[5874,-11.012725830078123],"pol":[5877,-11.01350212097168],"보":[5878,-11.013664245605469],"▁week":[5895,-11.01567554473877],"▁내":[5920,-11.018776893615724],"hor":[5922,-11.018965721130373],"tom":[5928,-11.019749641418455],"단":[5931,-11.020421028137209],"▁사":[5939,-11.020978927612305],"200":[5955,-11.023048400878906],"▁Th":[6003,-11.029213905334473],"sis":[6023,-11.031338691711426],"time":[6032,-11.032899856567385],"▁대":[6050,-11.035837173461914],"out":[6056,-11.036591529846191],"▁star":[6057,-11.03663158416748],"▁가":[6081,-11.039809226989746],"▁고":[6086,-11.04018497467041],"▁September":[6088,-11.040363311767578],"▁더":[6116,-11.043927192687988],"▁thi":[6117,-11.044097900390623],"ane":[6130,-11.045287132263184],"▁rol":[6136,-11.045879364013672],"▁st":[6138,-11.046082496643066],"amo":[6144,-11.046452522277832],"Fi":[6159,-11.048052787780762],"▁wan":[6165,-11.049257278442385],"inte":[6191,-11.052376747131348],"▁sor":[6217,-11.056463241577148],"▁control":[6226,-11.05733871459961],"nal":[6236,-11.059962272644045],"ding":[6238,-11.06030559539795],"led":[6259,-11.06272315979004],"pt":[6328,-11.072108268737791],"▁600":[6331,-11.072393417358398],"cin":[6333,-11.07298755645752],"pp":[6366,-11.077187538146973],"bro":[6369,-11.077474594116213],"하":[6395,-11.07976531982422],"Ne":[6433,-11.085351943969728],"tok":[6448,-11.088004112243652],"▁시":[6452,-11.088151931762695],"▁pl":[6456,-11.088854789733888],"ds":[6468,-11.09005069732666],"wer":[6488,-11.091752052307127],"mb":[6492,-11.092516899108888],"▁Bre":[6499,-11.09321403503418],"▁신":[6521,-11.096720695495604],"차":[6547,-11.100345611572266],"▁One":[6561,-11.101881980895996],"list":[6562,-11.10201930999756],"▁일":[6571,-11.103545188903809],"▁제":[6600,-11.106950759887695],"ence":[6620,-11.109137535095217],"ture":[6644,-11.112164497375488],"ord":[6651,-11.112574577331545],"oc":[6652,-11.112852096557615],"▁것":[6668,-11.114280700683594],"ike":[6669,-11.114402770996094],"▁다":[6685,-11.115857124328612],"▁look":[6713,-11.11941623687744],"관":[6720,-11.120051383972168],"조":[6740,-11.122514724731444],"ann":[6763,-11.124284744262695],"▁~":[6780,-11.126018524169922],"oval":[6785,-11.126445770263672],"ell":[6796,-11.12794589996338],"▁aut":[6798,-11.12798023223877],"ier":[6815,-11.129545211791992],"gin":[6820,-11.130034446716309],"분":[6832,-11.130892753601074],"▁reg":[6835,-11.131176948547363],"imit":[6836,-11.131391525268556],"hel":[6865,-11.134947776794434],"▁apo":[6885,-11.137414932250977],"▁안":[6888,-11.138062477111816],"tag":[6936,-11.14264965057373],"유":[6943,-11.143487930297852],"▁Yo":[6949,-11.144046783447266],"sing":[6953,-11.145059585571287],"test":[6954,-11.145101547241213],"igh":[6958,-11.145437240600586],"osti":[6965,-11.146319389343262],"port":[6982,-11.148542404174805],"sp":[7008,-11.151771545410156],"und":[7030,-11.153879165649414],"ไทย":[7034,-11.154094696044922],"ee":[7039,-11.15463924407959],"재":[7046,-11.155180931091309],"00":[7049,-11.15546703338623],"▁정":[7063,-11.157060623168944],"방":[7084,-11.15982723236084],"▁비":[7091,-11.160754203796388],"중":[7094,-11.16127872467041],"▁after":[7103,-11.162342071533203],"▁bro":[7155,-11.167312622070312],"▁아":[7159,-11.167718887329102],"▁team":[7175,-11.169198036193848],"rk":[7190,-11.170422554016112],"Po":[7192,-11.170493125915527],"▁PM":[7198,-11.172161102294922],"▁mem":[7199,-11.172179222106934],"eti":[7207,-11.17304515838623],"까지":[7214,-11.173483848571776],"ral":[7263,-11.178455352783203],"무":[7286,-11.181636810302734],"pla":[7290,-11.182144165039062],"▁mos":[7304,-11.18450164794922],"호":[7346,-11.188040733337402],"esi":[7373,-11.19109344482422],"ness":[7432,-11.197345733642578],"ey":[7460,-11.20029067993164],"▁기":[7463,-11.200502395629885],"pos":[7522,-11.206706047058104],"니":[7529,-11.207395553588867],"lli":[7532,-11.207437515258787],"olo":[7537,-11.207874298095703],"▁sh":[7547,-11.20878791809082],"dit":[7564,-11.210424423217772],"nk":[7570,-11.210705757141112],"▁show":[7639,-11.219915390014648],"당":[7641,-11.219938278198242],"▁Mat":[7656,-11.221369743347168],"rna":[7676,-11.22342300415039],"▁Fu":[7680,-11.223873138427734],"nat":[7695,-11.22529411315918],"nci":[7700,-11.225610733032228],"hem":[7701,-11.22562026977539],"wn":[7710,-11.226059913635254],"▁Dat":[7716,-11.226799011230469],"300":[7739,-11.228793144226074],"rom":[7761,-11.230905532836914],"ets":[7831,-11.239068031311035],"lia":[7884,-11.24457836151123],"들":[7901,-11.246031761169434],"모":[7923,-11.24844455718994],"▁chu":[7933,-11.249974250793455],"ont":[7934,-11.250136375427246],"▁hel":[7943,-11.251313209533691],"nder":[7944,-11.251404762268066],"atu":[7945,-11.251422882080078],"연":[7956,-11.252520561218262],"▁anal":[7968,-11.253569602966309],"▁support":[8060,-11.26331901550293],"▁business":[8063,-11.263785362243652],"ls":[8080,-11.265901565551758],"▁q":[8096,-11.26711654663086],"iri":[8133,-11.270973205566406],"▁무":[8143,-11.27257251739502],"}":[8152,-11.273359298706056],"ust":[8160,-11.27427101135254],"여":[8177,-11.275630950927734],"wal":[8202,-11.278514862060549],"ove":[8206,-11.27919101715088],"문":[8247,-11.282113075256348],"ams":[8256,-11.282991409301758],"물":[8267,-11.284343719482422],"▁해":[8280,-11.285369873046877],"rai":[8287,-11.28594970703125],"▁through":[8305,-11.287227630615234],"▁never":[8306,-11.28724193572998],"▁ea":[8394,-11.295029640197754],"gro":[8407,-11.296409606933594],"영":[8443,-11.300012588500977],"hang":[8467,-11.302733421325684],"▁poli":[8478,-11.30371379852295],"ace":[8509,-11.30630874633789],"▁자":[8511,-11.306499481201172],"gat":[8554,-11.309732437133787],"tera":[8560,-11.310336112976074],"▁ord":[8597,-11.3140230178833],"▁bom":[8634,-11.318317413330078],"▁anno":[8668,-11.322301864624023],"ette":[8676,-11.323094367980955],"usi":[8702,-11.325136184692385],"▁인":[8740,-11.32763385772705],"side":[8752,-11.329096794128418],"nc":[8766,-11.330531120300291],"ow":[8770,-11.33102798461914],"but":[8789,-11.332175254821776],"안":[8825,-11.335808753967283],"▁pic":[8834,-11.33649444580078],"nel":[8876,-11.340459823608398],"국":[8925,-11.345049858093262],"▁Pla":[8950,-11.347725868225098],"ith":[8962,-11.349720001220703],"▁5-":[8967,-11.350260734558104],"cel":[8969,-11.350642204284668],"app":[9007,-11.354920387268066],"ern":[9022,-11.356411933898926],"bl":[9030,-11.357394218444824],"Mo":[9083,-11.36188793182373],"語":[9089,-11.362540245056152],"unt":[9109,-11.364507675170898],"▁integr":[9114,-11.364738464355469],"lic":[9120,-11.365224838256836],"▁마":[9170,-11.369617462158203],"bot":[9190,-11.37153434753418],"▁page":[9191,-11.37156105041504],"udi":[9198,-11.371891021728516],"▁ह":[9214,-11.37359619140625],"spe":[9217,-11.373814582824709],"▁unde":[9232,-11.375018119812012],"char":[9254,-11.37706470489502],"llo":[9284,-11.37984561920166],"▁Full":[9312,-11.381576538085938],"ther":[9319,-11.38224983215332],"▁sent":[9325,-11.382798194885254],"금":[9362,-11.385490417480469],"ug":[9387,-11.387622833251951],"ï":[9392,-11.388117790222168],"less":[9393,-11.388123512268066],"▁한국":[9397,-11.388388633728027],"gs":[9405,-11.388886451721191],"▁미":[9450,-11.392934799194336],"거":[9452,-11.393147468566896],"▁`":[9473,-11.395010948181152],"▁말":[9478,-11.395370483398438],"gh":[9486,-11.396036148071287],"Li":[9506,-11.39859676361084],"03":[9513,-11.399048805236816],"tic":[9523,-11.399713516235352],"02":[9550,-11.401899337768556],"tit":[9613,-11.407621383666992],"gio":[9702,-11.415977478027344],"ht":[9703,-11.416049003601074],"bank":[9802,-11.423013687133787],"▁open":[9803,-11.423019409179688],"tab":[9843,-11.426276206970217],"Ta":[9874,-11.428128242492676],"에게":[9913,-11.430975914001465],"▁comp":[9969,-11.436087608337402],"▁lett":[9993,-11.438468933105469],"hir":[10011,-11.43960189819336],"mark":[10015,-11.439749717712402],"カ":[10045,-11.442017555236816],"cc":[10060,-11.443315505981444],"프":[10068,-11.444049835205078],"TM":[10111,-11.447134971618652],"ans":[10133,-11.449017524719238],"data":[10135,-11.449274063110352],"link":[10187,-11.452584266662598],"▁ret":[10267,-11.458575248718262],"pr":[10287,-11.459908485412598],"▁스":[10324,-11.46257209777832],"▁head":[10336,-11.463360786437988],"▁모":[10338,-11.463440895080566],"▁원":[10380,-11.466634750366213],"rig":[10384,-11.46706199645996],"ngu":[10393,-11.467949867248535],"inter":[10433,-11.471906661987305],"hur":[10437,-11.472126960754396],"내":[10459,-11.474356651306152],"▁선":[10486,-11.476154327392578],"▁다른":[10492,-11.476871490478516],"ath":[10519,-11.479371070861816],"▁조":[10524,-11.479783058166504],"▁mea":[10548,-11.481566429138184],"rg":[10566,-11.48293399810791],"Co":[10625,-11.486896514892578],"▁{":[10666,-11.490466117858888],"▁ren":[10670,-11.490683555603027],"Mu":[10685,-11.49212646484375],"nn":[10713,-11.493908882141112],"600":[10715,-11.494145393371582],"Com":[10770,-11.498631477355955],"▁region":[10776,-11.498910903930664],"タ":[10793,-11.500421524047852],"ants":[10840,-11.503300666809082],"▁PR":[10865,-11.505362510681152],"not":[10869,-11.50570011138916],"reg":[10901,-11.507977485656738],"▁rep":[10958,-11.511597633361816],"▁사용":[10993,-11.51357364654541],"rov":[11010,-11.515219688415527],"lai":[11032,-11.516785621643066],"AB":[11040,-11.517717361450195],"cker":[11050,-11.518492698669434],"anno":[11071,-11.519659996032717],"▁재":[11105,-11.523000717163086],"▁하":[11164,-11.528536796569824],"행":[11199,-11.53184986114502],"점":[11208,-11.532771110534668],"하지":[11289,-11.539305686950684],"▁AB":[11321,-11.542012214660645],"▁Play":[11356,-11.544753074645996],"▁두":[11385,-11.546388626098633],"AI":[11388,-11.54649257659912],"sho":[11412,-11.54843521118164],"hara":[11416,-11.548628807067873],"raf":[11431,-11.549554824829102],"▁거":[11470,-11.552666664123535],"gol":[11490,-11.553985595703123],"▁lin":[11508,-11.55479907989502],"터":[11564,-11.558992385864258],"▁연":[11573,-11.560015678405762],"▁Pop":[11584,-11.560808181762695],"93":[11591,-11.56121063232422],"▁run":[11675,-11.566335678100586],"GE":[11679,-11.566519737243652],"cus":[11680,-11.566536903381348],"usa":[11684,-11.566720962524414],"ph":[11727,-11.56961154937744],"▁next":[11737,-11.570199012756348],"▁서":[11753,-11.57097625732422],"▁Us":[11756,-11.571087837219238],"Da":[11866,-11.57774543762207],"ema":[11883,-11.57871437072754],"pag":[11902,-11.58030891418457],"계":[11931,-11.582534790039062],"▁gro":[11969,-11.584660530090332],"rica":[12056,-11.589139938354492],"파":[12057,-11.58914279937744],"▁sort":[12096,-11.592474937438965],"Ko":[12110,-11.593304634094238],"ked":[12225,-11.601335525512695],"Ra":[12248,-11.60288429260254],"업":[12258,-11.603448867797852],"ric":[12259,-11.603466987609863],"포":[12284,-11.604860305786133],"종":[12286,-11.604957580566406],"건":[12322,-11.60765266418457],"بي":[12337,-11.608412742614746],"▁세":[12362,-11.610559463500977],"mil":[12397,-11.612990379333496],"타":[12412,-11.61402988433838],"רי":[12415,-11.61416721343994],"크":[12431,-11.615002632141112],"▁led":[12441,-11.615488052368164],"운":[12451,-11.615965843200684],"44":[12465,-11.616986274719238],"nto":[12529,-11.621333122253418],"eme":[12549,-11.622525215148926],"ssi":[12551,-11.622611045837402],"cou":[12600,-11.625798225402832],"back":[12620,-11.627479553222656],"▁each":[12638,-11.62826442718506],"▁log":[12684,-11.631032943725586],"दी":[12686,-11.631061553955078],"rri":[12713,-11.633137702941896],"rol":[12722,-11.633478164672852],"stin":[12729,-11.634025573730469],"ines":[12741,-11.634560585021973],"레":[12764,-11.63548755645752],"▁Link":[12779,-11.636297225952148],"발":[12788,-11.636627197265623],"역":[12812,-11.638147354125977],"sent":[12832,-11.639695167541504],"▁pagina":[12978,-11.648482322692873],"▁order":[12989,-11.648983001708984],"cil":[13003,-11.64974880218506],"▁Br":[13008,-11.649994850158691],"fla":[13034,-11.65173053741455],"SO":[13055,-11.653076171875],"▁ove":[13088,-11.655084609985352],"nke":[13116,-11.657061576843262],"tiv":[13122,-11.657275199890137],"nl":[13169,-11.65949249267578],"입":[13187,-11.660447120666504],"▁usa":[13280,-11.666595458984377],"그":[13304,-11.667414665222168],"▁days":[13312,-11.667686462402344],"▁line":[13315,-11.667964935302734],"dt":[13384,-11.671663284301758],"ue":[13388,-11.671995162963867],"cco":[13400,-11.672710418701172],"설":[13420,-11.673788070678713],"▁again":[13438,-11.674600601196287],"fir":[13448,-11.67524528503418],"ome":[13450,-11.67534351348877],"בר":[13458,-11.675874710083008],"hre":[13520,-11.679494857788086],"rap":[13631,-11.685821533203123],"▁Mak":[13676,-11.688605308532717],"▁단":[13706,-11.690218925476074],"▁발":[13745,-11.692468643188477],"top":[13784,-11.694918632507324],"통":[13811,-11.69651699066162],"▁bot":[13820,-11.697134017944336],"료":[13891,-11.70154094696045],"▁spe":[13986,-11.707054138183594],"현":[14020,-11.709148406982422],"ink":[14068,-11.712671279907228],"olog":[14071,-11.712821006774902],"evi":[14083,-11.71351146697998],"riz":[14096,-11.71396255493164],"심":[14111,-11.714987754821776],"임":[14142,-11.7171049118042],"rou":[14179,-11.71908187866211],"sine":[14186,-11.71993923187256],"▁Asia":[14237,-11.723270416259766],"부터":[14243,-11.723697662353516],"루":[14413,-11.73279857635498],"▁family":[14449,-11.735381126403809],"더":[14501,-11.738758087158203],"lea":[14507,-11.738873481750488],"fil":[14580,-11.74266529083252],"ivi":[14681,-11.74876594543457],"▁exp":[14700,-11.749826431274414],"wit":[14817,-11.75582504272461],"출":[14842,-11.756784439086914],"rke":[14897,-11.759540557861328],"lys":[14907,-11.759973526000977],"▁파":[14971,-11.762772560119627],"gina":[14985,-11.763742446899414],"▁chur":[15003,-11.76490592956543],"▁both":[15044,-11.766767501831056],"kl":[15066,-11.76796817779541],"▁العربية":[15073,-11.768497467041016],"हि":[15159,-11.773929595947266],"버":[15164,-11.774125099182127],"배":[15170,-11.774474143981934],"PI":[15185,-11.775334358215332],"▁add":[15190,-11.775540351867676],"SS":[15268,-11.7794189453125],"mpa":[15293,-11.78044605255127],"िन":[15356,-11.783754348754885],"AP":[15383,-11.785372734069824],"dige":[15386,-11.785554885864258],"ct":[15390,-11.785682678222656],"ial":[15403,-11.786603927612305],"▁account":[15426,-11.788008689880373],"직":[15438,-11.78868579864502],"rte":[15492,-11.791619300842283],"▁change":[15549,-11.794370651245115],"row":[15555,-11.794770240783691],"eco":[15595,-11.796940803527832],"▁Comp":[15612,-11.797658920288086],"▁liter":[15659,-11.799606323242188],"▁another":[15700,-11.80191707611084],"63":[15748,-11.80413818359375],"▁sho":[15756,-11.804518699645996],"▁perfect":[15787,-11.806478500366213],"▁sup":[15811,-11.807342529296877],"▁हि":[15848,-11.80972957611084],"vie":[15959,-11.815436363220217],"래":[15960,-11.815465927124023],"fl":[15991,-11.817044258117676],"▁불":[15996,-11.817225456237791],"nts":[16037,-11.819422721862791],"▁lit":[16060,-11.820650100708008],"▁trai":[16071,-11.821189880371094],"pare":[16082,-11.821931838989258],"<":[16093,-11.822518348693848],"▁panel":[16138,-11.824666976928713],"bs":[16145,-11.825191497802734],"▁mark":[16188,-11.826948165893556],"품":[16276,-11.832038879394531],"청":[16295,-11.832977294921877],"린":[16314,-11.833969116210938],"▁예":[16385,-11.836926460266112],"데":[16404,-11.838058471679688],"gua":[16407,-11.83809757232666],"run":[16428,-11.839280128479004],"lain":[16442,-11.839958190917969],"▁배":[16493,-11.842535018920898],"fun":[16498,-11.842778205871582],"oo":[16635,-11.84962272644043],"ffe":[16670,-11.851123809814451],"-7":[16709,-11.852743148803713],"spec":[16711,-11.852835655212402],"off":[16713,-11.852897644042969],"system":[16751,-11.854866027832031],"uer":[16763,-11.855449676513672],"▁neve":[16775,-11.856125831604004],"ole":[16836,-11.859699249267578],"iter":[16840,-11.859808921813965],"션":[16874,-11.861042976379396],"▁AP":[16885,-11.861591339111328],"atur":[16989,-11.866878509521484],"chan":[17032,-11.868876457214355],"rati":[17131,-11.873939514160156],"start":[17137,-11.874098777770996],"PR":[17255,-11.87948513031006],"▁three":[17262,-11.879730224609377],"CI":[17304,-11.88132667541504],"▁hea":[17305,-11.881428718566896],"예":[17320,-11.8822603225708],"▁nev":[17326,-11.882624626159668],"low":[17336,-11.883294105529783],"▁contro":[17340,-11.883389472961426],"▁lig":[17358,-11.884169578552246],"▁using":[17368,-11.884371757507324],"▁says":[17378,-11.884974479675291],"작":[17407,-11.8867826461792],"▁차":[17418,-11.887077331542969],"후":[17421,-11.887248039245604],"▁confi":[17438,-11.887994766235352],"fs":[17447,-11.888572692871094],"ナ":[17456,-11.888788223266602],"▁limit":[17475,-11.889686584472656],"date":[17489,-11.89026927947998],"▁sorte":[17497,-11.890759468078612],"tea":[17615,-11.896240234375],"▁시작":[17677,-11.89912223815918],"lau":[17697,-11.900176048278809],"ged":[17704,-11.900615692138672],"하면":[17801,-11.90447235107422],"▁또는":[17822,-11.905406951904297],"fec":[17928,-11.910392761230469],"▁second":[17932,-11.910626411437988],"limi":[17975,-11.913514137268066],"رب":[17977,-11.913728713989258],"▁wer":[18014,-11.915696144104004],"▁admin":[18022,-11.916019439697266],"증":[18128,-11.9202880859375],"격":[18129,-11.920392036437988],"▁code":[18151,-11.921182632446287],"▁Dra":[18186,-11.922303199768066],"ffer":[18234,-11.924254417419434],"▁emo":[18255,-11.925360679626465],"fte":[18266,-11.925649642944336],"rro":[18304,-11.92733097076416],"cla":[18347,-11.928955078125],"▁class":[18507,-11.936860084533691],"dev":[18548,-11.938271522521973],"▁offer":[18645,-11.942840576171877],"oji":[18689,-11.945167541503906],"키":[18693,-11.945311546325684],"pic":[18695,-11.945402145385742],"rite":[18781,-11.949018478393556],"▁ref":[18831,-11.951236724853516],"zone":[18979,-11.95744800567627],"블":[19087,-11.961977005004885],"ngo":[19120,-11.963539123535156],"ort":[19135,-11.964073181152344],"▁sec":[19216,-11.967170715332031],"CS":[19283,-11.969970703125],"dle":[19298,-11.970752716064451],"▁Mus":[19314,-11.971540451049805],"두":[19322,-11.971911430358888],"spa":[19341,-11.97318172454834],"phi":[19379,-11.974849700927734],"egi":[19384,-11.975040435791016],"rc":[19437,-11.977672576904297],"As":[19659,-11.986581802368164],"▁continu":[19686,-11.987548828125],"ws":[19725,-11.989131927490234],"mpe":[19738,-11.989789009094238],"key":[19770,-11.990951538085938],"tivi":[19805,-11.992589950561523],"지만":[19847,-11.994170188903809],"▁liga":[19881,-11.995701789855955],"cke":[20013,-12.001420021057127],"light":[20016,-12.001497268676758],"ily":[20102,-12.004626274108888],"▁xxx":[20112,-12.004863739013672],"각":[20198,-12.008411407470703],"rac":[20251,-12.010886192321776],"PM":[20266,-12.011430740356444],"▁zone":[20288,-12.012250900268556],"On":[20320,-12.013345718383787],"say":[20347,-12.014389991760254],"alu":[20365,-12.014863014221191],"vice":[20375,-12.01522731781006],"mbe":[20439,-12.01844882965088],"▁audi":[20461,-12.019171714782717],"▁하나":[20463,-12.01924991607666],"dl":[20469,-12.019536018371582],"sig":[20561,-12.022972106933594],"▁미국":[20598,-12.024641036987305],"▁integra":[20603,-12.024803161621094],"ual":[20605,-12.024991989135742],"ize":[20650,-12.02658462524414],"▁zer":[20667,-12.027257919311523],"gai":[20701,-12.028803825378418],"eo":[20756,-12.031079292297363],"Th":[20800,-12.03269100189209],"120":[20840,-12.034219741821287],"▁tab":[20928,-12.038469314575195],"▁임":[20945,-12.038976669311523],"▁또":[21099,-12.04483127593994],"표":[21244,-12.05063247680664],"▁continue":[21342,-12.054726600646973],"▁char":[21441,-12.059208869934082],"into":[21579,-12.064566612243652],"vic":[21605,-12.06552028656006],"▁America":[21629,-12.06654930114746],"스트":[21648,-12.067252159118652],"▁Sep":[21693,-12.06926727294922],"than":[21732,-12.070878982543944],"ars":[21816,-12.074572563171388],"nev":[21817,-12.074708938598633],"ain":[21845,-12.07554054260254],"▁날":[21858,-12.076166152954102],"▁Fr":[21894,-12.07746696472168],"cing":[21896,-12.077484130859377],"▁interna":[22157,-12.086776733398438],"▁출":[22190,-12.08818817138672],"▁Tab":[22193,-12.088231086730955],"rf":[22206,-12.088375091552734],"약":[22208,-12.088390350341797],"tors":[22230,-12.088906288146973],"poli":[22232,-12.08904266357422],"환":[22325,-12.092379570007324],"Ad":[22409,-12.095484733581545],"량":[22442,-12.097039222717283],"page":[22469,-12.0982084274292],"ight":[22553,-12.10163688659668],"agi":[22630,-12.104886054992676],"▁light":[22729,-12.108301162719728],"▁심":[22740,-12.10859489440918],"view":[22751,-12.1090669631958],"▁four":[22759,-12.109463691711426],"tern":[22766,-12.109711647033691],"▁key":[22799,-12.110793113708496],"▁리":[22803,-12.110984802246094],"table":[22819,-12.11146068572998],"▁cont":[22832,-12.11175537109375],"nge":[23023,-12.118983268737791],"해서":[23069,-12.12081813812256],"▁일본":[23071,-12.120901107788086],"▁staff":[23082,-12.121438026428224],"Am":[23135,-12.12327766418457],"근":[23147,-12.123571395874023],"upp":[23157,-12.12397003173828],"▁table":[23180,-12.124913215637209],"ET":[23385,-12.132400512695312],"wor":[23432,-12.134441375732422],"▁posti":[23452,-12.13506031036377],"emo":[23800,-12.147035598754885],"cti":[23835,-12.148194313049316],"함":[23928,-12.151596069335938],"ters":[23962,-12.152620315551758],"▁40%":[24051,-12.155889511108398],"erd":[24069,-12.156463623046877],"▁sign":[24092,-12.15754508972168],"elli":[24134,-12.158964157104492],"▁되":[24141,-12.159106254577637],"▁until":[24189,-12.160871505737305],"▁영":[24204,-12.161511421203612],"wed":[24243,-12.163175582885742],"처":[24247,-12.16325569152832],"▁allo":[24286,-12.164621353149414],"▁lik":[24310,-12.165358543395996],"BC":[24318,-12.165584564208984],"▁arri":[24387,-12.168381690979004],"너":[24650,-12.177346229553224],"under":[24658,-12.177714347839355],"ect":[24762,-12.181073188781738],"▁exact":[24763,-12.181090354919434],"too":[24838,-12.18290901184082],"{":[24854,-12.183343887329102],"▁선택":[24865,-12.183696746826172],"main":[24931,-12.186606407165527],"tho":[24948,-12.187131881713867],"fund":[25018,-12.18917465209961],"▁sep":[25040,-12.190081596374512],"ors":[25251,-12.196948051452637],"▁포":[25284,-12.19812297821045],"ithi":[25320,-12.199212074279783],"결":[25354,-12.200056076049805],"apo":[25395,-12.201623916625977],"▁pagi":[25396,-12.20168113708496],"▁Lin":[25497,-12.204635620117188],"email":[25501,-12.204791069030762],"▁Date":[25512,-12.205117225646973],"▁charge":[25534,-12.20596408843994],"▁tok":[25636,-12.209460258483888],"▁regi":[25703,-12.21129322052002],"▁운영":[25763,-12.213491439819336],"ail":[25820,-12.215062141418455],"▁CS":[25841,-12.215686798095703],"본":[25912,-12.218070030212402],"날":[25999,-12.220873832702637],"▁사진":[26084,-12.223599433898926],"말":[26106,-12.224088668823242],"itor":[26111,-12.224435806274414],"cial":[26136,-12.225339889526367],"▁tea":[26156,-12.22593116760254],"▁제품":[26157,-12.22598361968994],"▁Make":[26176,-12.22656536102295],"▁화":[26191,-12.227149963378906],"▁café":[26216,-12.227787017822266],"mber":[26278,-12.229665756225586],"▁Korea":[26320,-12.230815887451172],"▁hir":[26364,-12.232275009155272],"yw":[26376,-12.232526779174805],"eed":[26420,-12.233963966369627],"▁ask":[26458,-12.23513889312744],"▁against":[26548,-12.238089561462402],"▁CI":[26550,-12.238173484802246],"▁cla":[26580,-12.239265441894531],"▁없":[26653,-12.241409301757812],"lp":[26775,-12.244888305664062],"▁means":[26950,-12.249975204467772],"ery":[26976,-12.250384330749512],"▁cod":[27044,-12.252760887145996],"▁needs":[27117,-12.254828453063965],"▁건":[27223,-12.257891654968262],"quer":[27227,-12.2579984664917],"lite":[27287,-12.259565353393556],"번":[27367,-12.262479782104492],"ember":[27417,-12.263775825500488],"ifi":[27430,-12.264175415039062],"valu":[27494,-12.266154289245604],"▁연구":[27568,-12.268330574035645],"rge":[27616,-12.26986026763916],"att":[27639,-12.270493507385254],"▁들어":[27681,-12.271319389343262],"ated":[27686,-12.27138614654541],"wl":[27751,-12.27378273010254],"▁있":[27849,-12.27657985687256],"cket":[27853,-12.276688575744627],"▁문":[27940,-12.279159545898438],"▁act":[27992,-12.280632972717283],"▁within":[28032,-12.281641960144045],"ake":[28088,-12.283486366271973],"▁From":[28090,-12.28357982635498],"▁pane":[28238,-12.28800106048584],"으":[28644,-12.299710273742676],"atio":[28645,-12.299717903137209],"▁fam":[28763,-12.303223609924316],"▁1200":[28797,-12.304553031921388],"▁competi":[28813,-12.305030822753906],"▁적":[28827,-12.305734634399414],"름":[28913,-12.308345794677734],"Dr":[28928,-12.308619499206545],"▁만":[28985,-12.31021499633789],"▁Pl":[29016,-12.31092929840088],"링":[29029,-12.31124210357666],"까":[29044,-12.311540603637695],"xt":[29062,-12.312089920043944],"ref":[29087,-12.312837600708008],"▁Add":[29117,-12.313983917236328],"rr":[29161,-12.315420150756836],"▁들":[29186,-12.31612777709961],"Pi":[29348,-12.320690155029297],"페이지":[29357,-12.321027755737305],"▁mean":[29459,-12.323569297790527],"▁SS":[29581,-12.327177047729492],"▁통":[29587,-12.327374458312988],"▁줄":[29800,-12.333612442016602],"file":[29822,-12.33420181274414],"oth":[29827,-12.334267616271973],"▁devi":[30170,-12.34427261352539],"lling":[30319,-12.347880363464355],"ever":[30441,-12.351285934448242],"ration":[30494,-12.35251522064209],"meri":[30547,-12.353870391845703],"▁wi":[30629,-12.356657028198242],"▁return":[30646,-12.35725212097168],"▁보고":[30861,-12.363245010375977],"fé":[30913,-12.364696502685549],"his":[31047,-12.368581771850586],"rvi":[31087,-12.370024681091309],"head":[31251,-12.374279022216797],"▁export":[31255,-12.374351501464844],"sign":[31304,-12.37546157836914],"▁letter":[31330,-12.376200675964355],"▁source":[31344,-12.376514434814451],"show":[31374,-12.377429962158203],"pte":[31385,-12.377642631530762],"▁role":[31486,-12.38122272491455],"ongo":[31525,-12.382222175598145],"terna":[31586,-12.384037017822266],"택":[31651,-12.38556671142578],"▁tes":[31785,-12.388976097106934],"▁가격":[31820,-12.390276908874512],"▁browser":[31842,-12.39083766937256],"불":[31950,-12.39395523071289],"▁List":[32036,-12.396066665649414],"nten":[32043,-12.396395683288574],"▁lim":[32060,-12.396900177001951],"中文":[32095,-12.397505760192873],"tw":[32290,-12.40255641937256],"wid":[32306,-12.403072357177734],"▁책":[32326,-12.403593063354492],"▁관":[32438,-12.405948638916016],"▁space":[32628,-12.410964012145996],"것":[32657,-12.411654472351074],"▁member":[32786,-12.414359092712402],"iff":[32920,-12.418258666992188],"=1":[33000,-12.42046356201172],"▁메":[33004,-12.420488357543944],"▁write":[33022,-12.420966148376465],"액":[33054,-12.4218111038208],"규":[33108,-12.423137664794922],"▁cl":[33139,-12.4239501953125],"Cu":[33177,-12.424989700317385],"▁dev":[33245,-12.426793098449709],"례":[33371,-12.430183410644531],"rep":[33581,-12.435795783996582],"rv":[33760,-12.439963340759276],"팅":[33994,-12.445082664489746],"▁العربي":[34081,-12.446861267089844],"▁words":[34153,-12.448638916015623],"design":[34198,-12.449691772460938],"ppo":[34241,-12.45072078704834],"완":[34433,-12.455347061157228],"our":[34639,-12.460345268249512],"cell":[34680,-12.461312294006348],"kto":[34691,-12.461600303649902],"▁올":[34781,-12.463582992553713],"▁日本":[34891,-12.466257095336914],"cl":[34937,-12.467638969421388],"되고":[35184,-12.473590850830078],"▁가능":[35345,-12.477337837219238],"▁종":[35467,-12.480541229248049],"now":[35613,-12.48419189453125],"▁appro":[35707,-12.486250877380373],"퍼":[35725,-12.486527442932127],"메":[35740,-12.486913681030272],"▁좀":[35744,-12.487153053283691],"بية":[35779,-12.487735748291016],"▁이후":[35825,-12.488757133483888],"항":[35831,-12.488872528076172],"▁직접":[36037,-12.493402481079102],"opo":[36400,-12.502171516418455],"▁금":[36527,-12.505105018615724],"ew":[36550,-12.505645751953123],"▁quer":[36649,-12.507915496826172],"lette":[36711,-12.509248733520508],"▁내용":[36728,-12.509624481201172],"▁Use":[36836,-12.512131690979004],"▁lead":[37105,-12.517858505249023],"mem":[37138,-12.51856517791748],"ไ":[37146,-12.518738746643066],"▁zon":[37258,-12.52127456665039],"lett":[37356,-12.523561477661133],"न्द":[37418,-12.52480697631836],"mea":[37440,-12.525341033935549],"▁시장":[37444,-12.525453567504885],"니다":[37478,-12.526141166687012],"▁자료":[37619,-12.529983520507812],"▁123":[37638,-12.530166625976562],"rce":[37910,-12.53541660308838],"▁Asi":[37933,-12.536224365234377],"▁wide":[38134,-12.54031753540039],"▁번":[38347,-12.54489040374756],"wei":[38384,-12.545860290527344],"▁intern":[38478,-12.54802703857422],"▁chan":[38572,-12.5497407913208],"▁Kore":[38633,-12.550985336303713],"▁AI":[38730,-12.552967071533203],"어요":[38736,-12.55303955078125],"rde":[38737,-12.553075790405272],"페":[38739,-12.553078651428224],"▁cell":[38750,-12.553306579589844],"03.":[38775,-12.553800582885742],"lian":[38820,-12.554779052734377],"▁user":[38937,-12.557040214538574],"firm":[38949,-12.557269096374512],"▁만들어":[39064,-12.559426307678224],"▁않":[39243,-12.563260078430176],"mpar":[39442,-12.567639350891112],"▁confirm":[39563,-12.570490837097168],"▁pick":[39580,-12.571037292480469],"▁있어":[39649,-12.572553634643556],"sec":[39797,-12.575701713562012],"liter":[39798,-12.57573127746582],"▁찾아":[40109,-12.58220386505127],"▁speci":[40140,-12.582743644714355],"능":[40351,-12.587359428405762],"▁less":[40715,-12.595396041870115],"▁hero":[40814,-12.597234725952148],"code":[40899,-12.5989990234375],"audi":[41004,-12.601097106933594],"ick":[41113,-12.60355281829834],"▁Fro":[41149,-12.604414939880373],"▁amount":[41170,-12.604744911193848],"올":[41356,-12.60843276977539],"graph":[41382,-12.608824729919434],"irin":[41503,-12.611425399780272],"한국":[41526,-12.611884117126465],"팀":[41564,-12.612523078918455],"llow":[41566,-12.612552642822266],"each":[41581,-12.612948417663574],"되":[41589,-12.613107681274414],"▁직":[41669,-12.614877700805664],"etu":[41680,-12.615072250366213],"▁#1":[41766,-12.616684913635254],"▁계":[41813,-12.617754936218262],"▁고객":[41863,-12.61884593963623],"bom":[41940,-12.620441436767578],"가지":[41962,-12.620928764343262],"친":[41967,-12.621055603027344],"테":[42090,-12.623640060424805],"▁author":[42179,-12.625532150268556],"thro":[42294,-12.62796115875244],"▁드":[42372,-12.62963581085205],"▁bac":[42427,-12.630695343017578],"":[250001,0.0]}, +"cases":[{"text":"query: Customer says they were charged twice for the annual plan and wants one charge back. Draft a reply under 120 words, apologetic but not grovelling, that confirms the refund goes out in 5-7 business days.","ids":[0,41,1294,12,124765,17378,1836,3542,25534,71,186351,100,70,77253,1774,136,86171,1632,25534,4420,5,18186,2480,10,75836,1379,5390,34153,4,6885,45614,9523,1284,959,111632,13,30319,4,450,39563,7,70,127402,60899,1810,23,109317,8063,13312,5,2]},{"text":"query: 사파리에서 내보내기 버튼이 안 눌린다는 버그 신고가 들어왔어요. 재현했다는 것, 임시 해결책(크롬 사용 또는 설정의 CSV 링크), 금요일까지 업데이트 드린다는 내용으로 두 문단짜리 답장을 써 주세요.","ids":[0,41,1294,12,5939,12057,2085,1180,5920,5878,171740,6,150507,469,6888,6,243583,115322,769,48905,13304,119925,713,27681,249981,38736,5,11105,14020,162701,6668,4,20945,2166,63054,47440,132,12431,170049,10993,17822,60366,367,313,43486,141459,247,36527,5144,83124,99797,42372,115322,769,36728,1654,11385,27940,5931,74280,2085,108251,61817,123281,130649,5,2]},{"text":"query: From the activity export attached, write the weekly digest for our top 10 accounts: one line each on usage change, open tickets and renewal date, sorted by renewal.","ids":[0,41,1294,12,28090,70,103488,31255,220642,4,33022,70,5895,538,1466,525,100,2446,2663,209,15426,7,12,1632,13315,12638,98,127689,15549,4,9803,137384,136,75312,8202,5622,4,17497,71,390,75312,8202,5,2]},{"text":"query: 이 스레드 세 줄 요약","ids":[0,41,1294,12,1504,10324,144017,12362,29800,214139,2]},{"text":"query: 하버라인 운영 책임자에게 보낼 갱신 안내 메일을 써 주세요. 계약은 11월 30일 종료, 올해 사용량 40% 증가, 11월 15일까지 서명하면 올해 가격 유지. 친근하게, 300자 이내, 요청은 하나만.","ids":[0,41,1294,12,11164,15164,56470,25763,85391,96994,5807,110046,6,193117,5301,46039,33004,1599,413,123281,130649,5,99414,697,534,3785,496,1599,203560,4,50912,10993,22442,24051,59127,4,534,3785,423,83124,11753,5576,17801,50912,31820,57104,5,90388,23147,5681,4,2668,2268,122184,4,96045,697,20463,3184,5,2]},{"text":"query: Compare the three main competitors in the attached list on pricing, SSO support and audit logs. A table with one row per competitor, and a source link per cell.","ids":[0,41,1294,12,113307,13,70,17262,5201,28813,22230,23,70,220642,5303,98,494,21896,4,159,13055,8060,136,44200,12684,7,5,62,23180,678,1632,6,15555,117,28813,1290,4,136,10,31344,3126,117,38750,5,2]},{"text":"query: 한국과 일본의 B2B 송장 자동화 시장 규모를 2025년 이후 자료로 찾아서 짧은 표로 정리해 주세요.","ids":[0,41,1294,12,9397,1291,23071,367,335,304,571,59501,3013,120188,3665,37444,143879,688,76924,2680,35825,37619,1083,40109,2293,196522,50284,1083,115038,1963,130649,5,2]},{"text":"query: Make a pivot table of this CSV by region","ids":[0,41,1294,12,26176,10,80953,18,23180,111,903,313,43486,390,10776,2]},{"text":"query: Add GET /v1/teams/:id/members to the API: admin or the team lead only, paginated with limit/offset like /v1/logs, returns id, email and role. Add an integration test that a member of another team gets 403.","ids":[0,41,1294,12,29117,6,79794,248,334,50412,44420,7,64,12,532,64,39,27417,7,47,70,61687,12,18022,707,70,7175,37105,4734,4,12978,3674,678,17475,64,16713,3509,1884,248,334,50412,4867,7,4,30646,7,3447,4,3340,136,31486,5,29117,142,157353,3034,450,10,32786,111,15700,7175,62163,201,38775,2]},{"text":"query: 사용량 페이지용 DateRangePicker 컴포넌트를 만들어 주세요. 7일·30일·90일 프리셋과 직접 선택, 키보드 접근 가능, 키트의 Popover 사용. 사용량 페이지에 적용되고 좁은 화면 테스트가 통과하면 완료입니다.","ids":[0,41,1294,12,10993,22442,74102,5358,25512,1052,51459,29348,11050,6,93721,12284,227540,114900,39064,130649,5,361,1599,1280,1197,1599,1280,5039,1599,98793,135608,1291,36037,24865,4,45996,117660,140058,35345,4,45996,3659,367,11584,5465,10993,5,10993,22442,74102,480,50223,35184,6,219660,697,124922,153924,713,195027,17801,114921,5826,5,2]},{"text":"query: The date picker shows yesterday for users in New York. Fix it so dates use the browser's time zone, and add a test with America/New_York.","ids":[0,41,1294,12,581,5622,39580,56,45831,131101,100,72095,23,2356,5753,5,96746,442,221,112474,4527,70,31842,25,7,1733,20288,4,136,15190,10,3034,678,21629,64,46568,454,185302,5,2]},{"text":"query: 프로필 사진이 안 뜨는 버그가 있어","ids":[0,41,1294,12,54099,49123,26084,469,6888,6,90603,769,48905,13304,713,39649,2]},{"text":"query: PR #193을 보안 관점으로 리뷰해 주세요. 기기가 다른 사용자나 다른 앱의 세션을 보고할 수 있나요? 발견 사항마다 파일과 줄 번호를, 심각한 것부터. 스타일은 무시해 주세요.","ids":[0,41,1294,12,10865,41766,11591,413,135108,199835,1654,79712,1963,130649,5,7463,59054,10492,77812,3497,10492,93672,367,12362,16874,413,30861,2461,1020,194904,32,95616,87198,92325,61886,1291,29800,6,62143,688,4,22740,20198,993,6668,14243,5,100072,697,8143,2166,1963,130649,5,2]},{"text":"query: Write a Playwright test for sign-in through device code: start authorize, approve as admin in the browser, poll until the key arrives. Must run headless in CI under 30 seconds.","ids":[0,41,1294,12,601,18781,10,11356,434,54969,3034,100,24092,9,73,8305,75186,18151,12,4034,42179,20650,4,35707,272,237,18022,23,70,31842,4,160,1181,24189,70,22799,54410,7,5,74275,11675,10336,9393,23,26550,1379,496,94131,5,2]},{"text":"query: 날짜 헬퍼에 테스트가 하나도 없어요. 서머타임 전환을 포함해서 Asia/Seoul과 America/New_York의 주 시작일을 예상값을 직접 적어서 검증해 주세요.","ids":[0,41,1294,12,182236,6,120245,35725,480,153924,713,20463,1048,77977,5144,5,11753,43777,119389,152981,413,45070,23069,14237,64,4233,31,202,1291,21629,64,46568,454,185302,367,5837,17677,1599,413,96453,78064,413,36037,173206,2293,224999,1963,130649,5,2]},{"text":"query: Break the classifier evaluation into tasks of a day or less, in order, with what 'done' means for each.","ids":[0,41,1294,12,131904,70,18507,85789,219836,3934,66211,7,111,10,5155,707,40715,4,23,12989,4,678,2367,242,64007,25,26950,100,12638,5,2]},{"text":"query: Mock up the Insights overview page for an admin: hero sentence, four tiles, teams table, and a 'worth a look' panel. Use the design system tokens, desktop at 1440 wide, light theme.","ids":[0,41,1294,12,2501,2594,1257,70,211018,7,645,22751,9191,100,142,18022,12,40814,149357,4,22759,139,90,4,87199,23180,4,136,10,242,93017,10,6713,25,16138,5,36836,70,4331,5426,47,84694,4,86983,99,616,2839,38134,4,22729,73986,5,2]},{"text":"query: 출시 배너 시안 세 가지를 1200x630으로 만들어 주세요. 레드롭 블루, 헤드라인은 'AI와 일하는 팀의 모습을 보세요', 인물 스톡 사진은 쓰지 말고요.","ids":[0,41,1294,12,79025,16493,24650,6452,8825,12362,44276,688,28797,425,910,1197,1654,39064,130649,5,6,144017,82017,6,19087,14413,4,97089,4087,56470,697,242,11388,2020,6571,2123,61474,367,113661,6,89865,25,4,161732,10324,128285,26084,697,61286,1190,173990,5144,5,2]},{"text":"query: LinkedIn post announcing the Korean launch, under 600 characters, one emoji at most, ends with the signup link.","ids":[0,41,1294,12,92502,1305,8668,34,60636,70,133915,83184,4,1379,6331,124850,4,1632,28,121505,99,2684,4,3564,7,678,70,24092,2037,3126,5,2]},{"text":"query: 마케팅 문구 좀 써줘","ids":[0,41,1294,12,113463,27940,4584,35744,123281,134267,2]},{"text":"query: 아래 제 답장을 미국 고객에게 보낼 영어로 번역해 주세요. 정중하지만 딱딱하지 않게, 제품명은 그대로, 내용은 더하지 말고요.","ids":[0,41,1294,12,58749,6600,108251,61817,20598,41863,9913,5807,110046,66135,1083,134799,1963,130649,5,7063,7094,90576,135408,243675,11289,219365,4,26157,5576,697,104579,4,144476,6116,11289,173990,5144,5,2]},{"text":"query: Draft an internal policy on using AI tools with customer data: what's allowed, what needs approval, what's never allowed, and who to ask. One page, plain language, for all staff.","ids":[0,41,1294,12,18186,2480,142,70796,44930,98,17368,38730,72977,678,43373,2053,12,2367,25,7,107003,4,2367,27117,35707,1405,4,2367,25,7,8306,107003,4,136,2750,47,26458,5,6561,9191,4,111719,46876,4,100,756,23082,5,2]},{"text":"query: 이 비밀유지계약서상 고객사 이름을 사례 연구에 써도 되나요? 해당 조항을 인용하고 가능, 불가, 불분명 중 하나로 답해 주세요.","ids":[0,41,1294,12,1504,190521,6943,1190,178780,2293,3394,41863,2099,178709,98817,27568,480,123281,1048,24141,88901,32,44661,10524,35831,413,8740,5358,2382,35345,4,167746,4,15996,6832,5576,5432,20463,1083,108251,1963,130649,5,2]},{"text":"query: help me write an offer letter","ids":[0,41,1294,12,4358,163,33022,142,18645,31330,2]},{"text":"query: Reconcile the September bank export against the ledger export, both attached. List unmatched lines on each side with amount and date, and the net difference. Match within 2 days and exact amount.","ids":[0,41,1294,12,154807,83797,70,6088,4620,31255,26548,70,12441,1505,31255,4,15044,220642,5,32036,51,98753,297,124519,98,12638,5609,678,41170,136,5622,4,136,70,2043,60212,5,67407,28032,116,13312,136,24763,41170,5,2]},{"text":"query: 거래처 송장 12건을 발주서와 대조해서 수량, 단가, 세금이 다른 건을 표시하고 차액을 원화로 보여 주세요. 송장마다 한 행.","ids":[0,41,1294,12,109163,24247,59501,3013,427,12322,413,13745,2688,2293,2020,6050,6740,23069,1020,22442,4,13706,713,4,219887,469,10492,27223,413,92571,2382,17418,33054,413,10380,3665,1083,91206,130649,5,59501,3013,92325,3103,72858,5,2]},{"text":"query: continue","ids":[0,41,1294,12,21342,2]},{"text":"query: thanks, that's perfect","ids":[0,41,1294,12,45458,4,450,25,7,15787,2]},{"text":"query: churn data 보고 왜 떠났는지 analysis 해줘","ids":[0,41,1294,12,15003,19,2053,30861,46679,84775,106219,104706,114137,8280,134267,2]},{"text":"query: we're hiring a PM, need the posting by tomorrow","ids":[0,41,1294,12,642,25,107,1274,2852,10,7198,4,3871,70,75220,390,127773,2]},{"text":"query: ","ids":[0,41,1294,12,2]},{"text":" leading spaces and\ttabs\nnewlines\r\n end ","ids":[0,105207,32628,7,136,20928,7,3525,59801,3564,2]},{"text":"Fullwidth ABC 123 カタカナ","ids":[0,9312,146984,47457,37638,6,10045,10793,10045,17456,2]},{"text":"é café naïve fi ligature ① ½ ™","ids":[0,393,26216,24,9392,272,809,19881,6644,106,78660,50523,2]},{"text":"emoji 👩‍💻 🇰🇷 👍🏽 family 👨‍👩‍👧","ids":[0,28,121505,6,244785,6,246382,6,245463,245080,6,118280,245164,14449,6,244314,6,244785,6,245719,2]},{"text":"control \u0000\u0007​‍ zero-width nbsp","ids":[0,6226,6,3,45234,9,146984,6,82678,2]},{"text":"한국어 자모 ㄱㄴㄷ 가각 똠방각하 뷁","ids":[0,193751,8511,7923,6,244134,244197,231596,6081,20198,6,3,7084,20198,6395,6,3,2]},{"text":"中文 日本語 ひらがな العربية עברית हिन्दी ไทย","ids":[0,6,32095,6,98449,6,47093,4182,281,1308,15073,177034,66997,6,7034,2]},{"text":"weird special tokens","ids":[0,179459,0,5361,2,250001,3,1,47,84694,2]},{"text":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","ids":[0,20112,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,43883,2]},{"text":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b ","ids":[0,6,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,83151,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,2]},{"text":"🦖🦕🧬􏿿 unknown chars ⿰⿱ 𓀀𓀁","ids":[0,6,3,51,69723,19,21441,7,6,3,6,3,2]},{"text":"`code` {braces} [x] (y) $var @user #tag ~/path/to/file.ts --flag=1","ids":[0,9473,40899,1135,10666,2844,5170,8152,378,425,268,15,53,16,3650,1961,1374,65918,468,6936,6780,64,128405,64,188,64,29822,5,933,4210,190872,33000,2]},{"text":"Tab\tafter ideographic space
line sep","ids":[0,22193,7103,47674,48461,32628,13315,25040,2]},{"text":"trailing space ","ids":[0,141037,214,32628,2]},{"text":"a b ","ids":[0,10,250001,876,250001,2]},{"text":"literal ▁ marker ▁▁x","ids":[0,15659,289,71323,1022,2]},{"text":"…nextbom᠎mongolian","ids":[0,11737,8634,3,39,31525,38820,2]}] +} diff --git a/packages/work-labeller/test/labels.test.ts b/packages/work-labeller/test/labels.test.ts new file mode 100644 index 0000000000..df0a18ec3f --- /dev/null +++ b/packages/work-labeller/test/labels.test.ts @@ -0,0 +1,34 @@ +import { describe, expect, test } from "bun:test"; +import { createHash } from "node:crypto"; + +import { externalIdOf, labelSession, SessionRecorder, sha256Hex, type LabeledSession, type LabelingApp } from "../src/index.js"; + +const OFFICE: LabelingApp = { toolKey: "office", idPrefix: "of_", labelerId: "office", labelerVersion: "1" }; + +describe("labels, for any app", () => { + test("sha256Hex is SHA-256", () => { + for (const text of ["", "abc", "세션-123", "x".repeat(55), "x".repeat(56), "x".repeat(64), "y".repeat(1000)]) { + expect(sha256Hex(text)).toBe(createHash("sha256").update(text).digest("hex")); + } + }); + + test("ids and labels carry the app's tool, prefix and labeler", () => { + expect(externalIdOf(OFFICE, "chat-1")).toBe(`of_${createHash("sha256").update("chat-1").digest("hex").slice(0, 32)}`); + const session = labelSession(OFFICE, { + rootSessionID: "chat-1", startedAt: 0, lastActivityAt: 0, userTurns: 1, firstAttachedSource: false, assistantMessages: 1, + toolCalls: 0, artifacts: 1, checks: 0, sends: 0, delegations: 0, peakConcurrentAgents: 0, subagentMinutes: 0, busyMinutes: 0, + attentionMinutes: 0, permissionsAsked: 0, permissionsAlways: 0, aborted: 0, redirected: 0, sensitiveSends: 0, unmaskedSends: 0, + action: "spec", family: "write", + }); + expect(session).toMatchObject({ toolKey: "office", labelerId: "office", labelerVersion: "1", mode: 2, actionKey: "spec", familyKey: "write" }); + }); + + test("the recorder labels a finished session under its app", async () => { + const out: LabeledSession[] = []; + const recorder = new SessionRecorder(OFFICE, (s) => void out.push(s), 1000); + recorder.observe({ kind: "user-turn", sessionID: "chat-1", messageID: "m1", at: 0, attachedSource: false }); + await recorder.observeFirstMessage("chat-1", "m1", "Write the spec", async () => ({ action: "spec", family: "write", confidence: 0.9 })); + expect(await recorder.sweep(5000)).toBe(1); + expect(out[0]).toMatchObject({ externalId: externalIdOf(OFFICE, "chat-1"), toolKey: "office", actionKey: "spec" }); + }); +}); diff --git a/packages/work-labeller/test/unigram.test.ts b/packages/work-labeller/test/unigram.test.ts new file mode 100644 index 0000000000..3fc05eada5 --- /dev/null +++ b/packages/work-labeller/test/unigram.test.ts @@ -0,0 +1,25 @@ +import { describe, expect, test } from "bun:test"; + +import parity from "./fixtures/unigram-parity.json" with { type: "json" }; +import { Unigram } from "../src/unigram.js"; + +describe("Unigram", () => { + const specials = new Map(Object.entries(parity.specials)); + const tokenizer = new Unigram({ + pieces: new Map(Object.entries(parity.pieces).map(([piece, [id, score]]) => [piece, { id: id!, score: score! }])), + unkId: parity.unkId, + minScore: parity.minScore, + charsmap: Uint8Array.from(atob(parity.charsmap), (char) => char.charCodeAt(0)), + specials, + lstrip: new Set(parity.lstrip), + whitespaceSplit: true, + bosId: specials.get("")!, + eosId: specials.get("")!, + }); + + for (const sample of parity.cases) { + test(`matches Hugging Face tokenizers: ${JSON.stringify(sample.text.slice(0, 40))}`, () => { + expect(tokenizer.encode(sample.text, 256)).toEqual(sample.ids); + }); + } +}); diff --git a/packages/work-labeller/tsconfig.json b/packages/work-labeller/tsconfig.json new file mode 100644 index 0000000000..7c6344b755 --- /dev/null +++ b/packages/work-labeller/tsconfig.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "@tsconfig/bun/tsconfig.json", + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["ES2022", "DOM"], + "rootDir": ".", + "outDir": "dist", + "declaration": true, + "strict": true, + "noUncheckedIndexedAccess": true, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "noEmit": true, + "allowImportingTsExtensions": true + }, + "include": ["src/**/*", "scripts/**/*", "test/**/*", "model/**/*"] +} diff --git a/packages/work-labeller/tsup.config.ts b/packages/work-labeller/tsup.config.ts new file mode 100644 index 0000000000..ea4683590b --- /dev/null +++ b/packages/work-labeller/tsup.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { index: "src/index.ts", node: "src/node.ts" }, + format: ["esm"], + dts: true, + clean: true, + target: "es2022", + platform: "neutral", + sourcemap: false, + splitting: true, + treeshake: true, + external: ["onnxruntime-node", "onnxruntime-web", "zod", "node:fs", "node:fs/promises", "node:path"], + loader: { ".json": "json" }, +}); From 7593f5fad4aa6ae167e4128dcfb6ad86c7d41b4e Mon Sep 17 00:00:00 2001 From: flxkm522 Date: Mon, 12 Oct 2026 21:02:58 +0900 Subject: [PATCH 2/2] docs(labelling): explain the on-device encoders, pin the compat contract, clarify CI Answers the four questions the CTO raised, as docs + tests, no runtime change. Stacked on the engine consolidation (#80), where the labeller packages live. - docs/ON-DEVICE-LABELLING.md (new): the single why-we-wrote-encoder-code answer. We wrap pinned off-the-shelf models (distiluse, multilingual-e5-base), not our own encoders, for on-device privacy + one implementation across products. Only the small trained layers are ours and live in git (work-head.json 159KB, prototypes.json 232KB); the base weights are hash-pinned downloads. Includes the where-the-tensors-live table, the model-free-CI vs opt-in-eval story, and the backwards-compat model for third-party clients. Also carries the pending checklist to move the e5 release asset from redrob-cowork to redrob-code (the SHA pins stay; only the url changes once the asset is re-hosted -- not flipped now because a not-yet-uploaded redrob-code release would 404 every download). - httpapi-chat-completion.test.ts: two new v1-contract cases -- the newer optional fields (max_completion_tokens, reasoning_effort, user) stay accepted, and unknown request fields (a Console-style redrob block, a bogus key) are IGNORED not rejected. The second is the exact forward/third-party-compat guarantee; it fails CI if someone makes the schema reject excess properties. - test.yml: expand the labellers job comment so the model-free-CI vs needs-the-real-model-only-for-opt-in-eval distinction is written where a maintainer reads it (the CTO's "tests seem to assume local files" concern). Verified: redrob typecheck clean; the 7 contract cases pass (the local 5s-timeout flakes are the Windows in-process app+DB startup, ~7s each -- green at --timeout 30000 and on Linux CI). --- .github/workflows/test.yml | 10 ++ docs/ON-DEVICE-LABELLING.md | 126 ++++++++++++++++++ .../server/httpapi-chat-completion.test.ts | 51 +++++++ 3 files changed, 187 insertions(+) create mode 100644 docs/ON-DEVICE-LABELLING.md diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f506b25edf..ca097337b9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -186,6 +186,16 @@ jobs: # Tests resolve the package `src` via the `development` export condition. route-labeller # ships no unit suite (its checks are the `eval` + prototype scripts); work-labeller # carries the 77-test classifier/tokeniser/dataset suite under test/ and model/. + # + # These suites are MODEL-FREE on purpose, which is why they run here with nothing + # downloaded: classifier.test.ts uses a stub ONNX runtime and a synthetic tokenizer, + # download.test.ts stands up a local fake release server with a tiny synthetic model, + # and the model/ tests check training-DATA invariants against the committed JSON. The + # real ~140MB / ~278MB encoders are needed ONLY by the opt-in developer commands + # (`bun run model`, route-labeller's `bun run eval`), which are deliberately NOT on the + # PR path -- a per-run multi-hundred-MB download is not worth gating merges on. If + # accuracy-in-CI is ever wanted, add a MANUAL/scheduled job restoring a cached model + # artifact; do not put the model fetch here. See docs/ON-DEVICE-LABELLING.md. - name: Run work-labeller tests working-directory: packages/work-labeller run: bun --conditions=development test test model diff --git a/docs/ON-DEVICE-LABELLING.md b/docs/ON-DEVICE-LABELLING.md new file mode 100644 index 0000000000..676a4983f8 --- /dev/null +++ b/docs/ON-DEVICE-LABELLING.md @@ -0,0 +1,126 @@ +# On-device labelling: the encoders, the tensors, and compatibility + +Two packages in this repo label a request on the person's own machine so that only +the labels — never the message text — leave it: `@redrob-labs/route-labeller` +(profession × task, for how Redrob Auto routes) and `@redrob-labs/work-labeller` +(kind of work, mode and outcome, for the Console's insights). Redrob Cowork, Office +and Design all consume them, so a request labels the same way in every product. + +This document is the design of record for *why* that code exists in the shape it does, +*where* the model data lives, how it is tested, and how older or third-party clients +stay compatible. It is the one place to send someone asking "why did we build our own +encoders". + +## 1. Why there is encoder code at all (we did not train encoders) + +We did **not** build sentence encoders from scratch. `encoder.ts` (route-labeller) +and `classifier.ts` (work-labeller) are a few hundred lines of glue around +**pinned, off-the-shelf open-source models**: + +| Package | Base model (not ours) | What our code is | +| --- | --- | --- | +| route-labeller | `sentence-transformers/distiluse-base-multilingual-cased-v2`, int8 ONNX | tokenize → run the ONNX transformer on `onnxruntime` → mean-pool over the attention mask → the model's own 768→512 Dense+tanh projection | +| work-labeller | `Xenova/multilingual-e5-base`, int8 ONNX | the same pipeline shape, feeding two small trained heads | + +There is encoder *code* — rather than a call to a hosted embeddings API — for three +reasons, in priority order: + +1. **Privacy is the feature.** The whole point is that classification happens on the + user's device and only the resulting labels are sent. A hosted embeddings API would + require sending the text off the machine, which defeats it. +2. **One implementation, three runtimes.** The encoder is runtime-neutral (bytes in, + no filesystem, no `node:crypto`; integrity uses WebCrypto). The *same* code runs in + `redrob-server` (Node), Office's Electron main process, and Design's webview, so a + request labels **identically** everywhere. Three separate integrations could not + guarantee that. +3. **Cross-language coverage for free.** distiluse was chosen specifically because it + reuses the exact BERT WordPiece tokenizer the privacy detector already ships (no + second tokenizer to maintain) and because it maps a sentence and its translation + close together across ~50 languages — which is what lets **one** set of prototype + sentences cover English, Korean and Hindi, the three ModelGuide languages. + +So: our code, borrowed models. + +## 2. Where the fine-tuned tensors live + +Only the small, task-specific layers are ours. They are **committed to git**. The +large base encoders are **not** in git — they are downloaded at a pinned revision and +verified by SHA-256. + +| Tier | What | Where it is now | Size | +| --- | --- | --- | --- | +| **Ours (trained)** | work-labeller's two classifier heads (`WORK_HEAD`) | `packages/work-labeller/src/work-head.json` (in git) | ~159 KB | +| **Ours (trained)** | route-labeller's per-cell prototype vectors (`PROTOTYPES`) | `packages/route-labeller/src/prototypes.json` (in git) | ~232 KB | +| Off-the-shelf | distiluse int8 ONNX | downloaded from Hugging Face, pinned revision + SHA | ~140 MB | +| Off-the-shelf | multilingual-e5-base int8 ONNX | downloaded from a GitHub **release asset**, pinned revision + SHA | ~278 MB | + +The "router" is not a neural net: routing is `prototypes.json` (one prototype +sentence per profession × task) plus a lexical word table — both tiny text files in +git. Nothing proprietary is a multi-hundred-MB blob. + +### Pending: move the e5 release asset to this repo + +`packages/work-labeller/src/manifest.json` currently points the e5 model and tokenizer +URLs at a **`redrob-labs/redrob-cowork`** release (`insights-model-e5-base-2026.10`). +Since redrob-code is now the single source of truth and publisher for these packages, +that asset should be re-hosted here and the two `url` fields updated. **The SHA-256 +pins do not change** — they are the real integrity guarantee; the URL is only where to +fetch from. Checklist: + +1. Upload `model_int8.onnx` and `tokenizer.json` (byte-identical to the pinned SHAs) as + a redrob-code release, e.g. `insights-model-e5-base-2026.10`. +2. Update the two `url` fields in `manifest.json` to the redrob-code release. +3. Leave `revision` and both `sha256` values unchanged; a mirrored asset that does not + match the pins is rejected by the downloader, which is the point. + +Until that asset exists, the manifest keeps the working cowork URL — pointing it at a +not-yet-uploaded redrob-code release would 404 every download. + +## 3. Tests, and the CI story + +The unit suites are **model-free and CI-safe** — they do not need the real multi-hundred-MB +models, which is why `labellers (linux)` runs green in CI with nothing downloaded: + +- `work-labeller/test/classifier.test.ts` uses a stub ONNX runtime (`fakeOrt`) and a + synthetic tokenizer; it writes tiny temp fixtures with `mkdtemp`. +- `work-labeller/test/download.test.ts` stands up a local `Bun.serve` fake release host + and a 300 KB synthetic model to exercise resume / hashing / retry — no network, no + real file. +- The `model/` tests check **training-data invariants** (coverage, no train/eval + leakage, label validity) against the committed JSON — not model tensors. +- route-labeller ships **no unit suite**; its accuracy check is the `eval/` held-out + script, run by hand. + +What genuinely needs the real model is the **opt-in developer path**, and that is +deliberately out of CI (a 278 MB download per run is not worth gating PRs on): + +- `pnpm model` fetches and verifies the real model into a local folder. +- `pnpm eval` (route-labeller) reports top-1 / top-3 on the held-out set. + +If accuracy-in-CI is ever wanted, add a **manual / scheduled** workflow that restores a +**cached** model artifact and runs `eval` — never on the PR path. + +## 4. Backwards compatibility, including third-party model APIs + +A stock OpenAI/Anthropic SDK, or an older client, knows nothing about `redrob.route`, +`x-redrob-session`, or the `/redrob/*` endpoints. It keeps working, by three +mechanisms (see `docs/LOCAL-ENGINE-API.md` for the engine contract): + +1. **Additive, path-versioned contract.** The contract is versioned by URL (`/v1/...`), + never by engine version. **Unknown request fields are ignored, not rejected**, so a + stock client posting to `/v1/chat/completions` works unchanged and our + `redrob.route` rides along as an ignored extra for anyone who does not set it. + Removing or redefining a field requires `/v2`, and `/v1` is served for two minor + versions after. A contract test pins the v1 request/response shape and fails CI if a + field is dropped (see `packages/redrob/test/server/httpapi-chat-completion.test.ts`). +2. **Graceful degradation of the labeller.** With no model present the labeller still + answers by words alone and marks `labeller.mode = "lexical"`. The Console routes on + the ModelGuide only for `"embedding"` labels; **lexical labels, and requests with no + label at all, fall back to the legacy task-type table** — they route the old way + rather than failing. +3. **"Preference, not override" semantics.** Even the routing hints are lenient: an + unknown or ineligible model id falls back to the table rather than failing the + request. + +The net: our additions are opt-in extras layered on an OpenAI-compatible surface, so a +third-party client that knows none of them is unaffected. diff --git a/packages/redrob/test/server/httpapi-chat-completion.test.ts b/packages/redrob/test/server/httpapi-chat-completion.test.ts index 25dac31b9f..54284c037d 100644 --- a/packages/redrob/test/server/httpapi-chat-completion.test.ts +++ b/packages/redrob/test/server/httpapi-chat-completion.test.ts @@ -144,4 +144,55 @@ describe("POST /v1/chat/completions", () => { expect(message.toLowerCase()).not.toContain("is missing") }), ) + + // v1 CONTRACT, the newer-but-promised fields. `max_completion_tokens`, + // `reasoning_effort` and `user` are in the documented request and must stay + // ACCEPTED; same 400-for-the-model, not-a-decode-error technique as above. + it.instance("accepts the newer optional fields (max_completion_tokens, reasoning_effort, user)", () => + Effect.gen(function* () { + const tmp = yield* TestInstance + const response = yield* post(tmp.directory, { + model: "no-such-provider/no-such-model", + messages: [{ role: "user", content: "ping" }], + max_completion_tokens: 64, + reasoning_effort: "low", + user: "someone", + }) + + expect(response.status).toBe(400) + const body = yield* json(response) + const message = String(body.error?.message ?? "") + expect(message.toLowerCase()).not.toContain("expected") + expect(message.toLowerCase()).not.toContain("is missing") + }), + ) + + // BACKWARDS / FORWARD COMPATIBILITY. The engine's request is an OpenAI subset; + // unknown fields are ignored, not rejected, so a stock OpenAI SDK and a newer + // client both talk to it without a version check. This pins that promise: a + // request carrying fields the schema does not name (a Console-style `redrob` + // block a client may add, and an outright bogus key) is still ACCEPTED — the + // failure is the unknown model, never a decode rejection of the extra fields. + // If someone makes the schema reject excess properties, this fails and names + // the regression. (See docs/LOCAL-ENGINE-API.md and docs/ON-DEVICE-LABELLING.md.) + it.instance("ignores unknown request fields rather than rejecting them", () => + Effect.gen(function* () { + const tmp = yield* TestInstance + const response = yield* post(tmp.directory, { + model: "no-such-provider/no-such-model", + messages: [{ role: "user", content: "ping" }], + redrob: { route: { profession: "lawyer", task: "review" } }, + not_a_real_field: 123, + }) + + // Accepted and decoded (unknown fields dropped), so we reach the model and + // get the unknown-model 400 — NOT a 400 complaining about the extra fields. + expect(response.status).toBe(400) + const body = yield* json(response) + const message = String(body.error?.message ?? "") + expect(message.toLowerCase()).not.toContain("redrob") + expect(message.toLowerCase()).not.toContain("not_a_real_field") + expect(message.toLowerCase()).not.toContain("unexpected") + }), + ) })