diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fb0cf22d60..0730bdc9c4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -158,6 +158,19 @@ jobs: mkdir -p ~/test-logs cd worker npm install + - name: Run Jawn + working-directory: valhalla/jawn + env: + SUPABASE_CREDS: '{"url": "http://localhost:54321", "service_role_key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU"}' + SUPABASE_DATABASE_URL: "postgresql://postgres:postgres@localhost:54322/postgres" + VERCEL_ENV: "development" + S3_ENDPOINT: "http://localhost:9000" + S3_ACCESS_KEY: "minioadmin" + S3_SECRET_KEY: "minioadmin" + S3_BUCKET_NAME: "request-response-storage" + run: | + yarn + yarn dev > ~/test-logs/jawn.log & - name: Start proxy worker run: | cd worker @@ -192,7 +205,14 @@ jobs: run: supabase start db,api - name: Install python dependencies run: | - pip install requests pytest psycopg2 python-dotenv helicone httpx + pip install requests pytest psycopg2 python-dotenv helicone httpx minio + - name: Wait for Jawn + run: | + echo "Waiting for Jawn to be ready..." + while ! curl -s http://localhost:8585/healthcheck; do + echo "Waiting for Jawn to be ready..." + sleep 5 + done - name: Run integration tests working-directory: tests env: diff --git a/helicone-python/poetry.lock b/helicone-python/poetry.lock index e03d602b3e..5956676f10 100644 --- a/helicone-python/poetry.lock +++ b/helicone-python/poetry.lock @@ -110,6 +110,63 @@ files = [ [package.dependencies] frozenlist = ">=1.1.0" +[[package]] +name = "argon2-cffi" +version = "23.1.0" +description = "Argon2 for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea"}, + {file = "argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08"}, +] + +[package.dependencies] +argon2-cffi-bindings = "*" + +[package.extras] +dev = ["argon2-cffi[tests,typing]", "tox (>4)"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-notfound-page"] +tests = ["hypothesis", "pytest"] +typing = ["mypy"] + +[[package]] +name = "argon2-cffi-bindings" +version = "21.2.0" +description = "Low-level CFFI bindings for Argon2" +optional = false +python-versions = ">=3.6" +files = [ + {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f"}, + {file = "argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a"}, +] + +[package.dependencies] +cffi = ">=1.0.1" + +[package.extras] +dev = ["cogapp", "pre-commit", "pytest", "wheel"] +tests = ["pytest"] + [[package]] name = "async-timeout" version = "4.0.2" @@ -150,6 +207,70 @@ files = [ {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] +[[package]] +name = "cffi" +version = "1.16.0" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, +] + +[package.dependencies] +pycparser = "*" + [[package]] name = "charset-normalizer" version = "3.1.0" @@ -375,6 +496,24 @@ files = [ {file = "lockfile-0.12.2.tar.gz", hash = "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799"}, ] +[[package]] +name = "minio" +version = "7.2.7" +description = "MinIO Python SDK for Amazon S3 Compatible Cloud Storage" +optional = false +python-versions = "*" +files = [ + {file = "minio-7.2.7-py3-none-any.whl", hash = "sha256:59d1f255d852fe7104018db75b3bebbd987e538690e680f7c5de835e422de837"}, + {file = "minio-7.2.7.tar.gz", hash = "sha256:473d5d53d79f340f3cd632054d0c82d2f93177ce1af2eac34a235bea55708d98"}, +] + +[package.dependencies] +argon2-cffi = "*" +certifi = "*" +pycryptodome = "*" +typing-extensions = "*" +urllib3 = "*" + [[package]] name = "multidict" version = "6.0.4" @@ -528,6 +667,58 @@ files = [ {file = "psycopg2-2.9.9.tar.gz", hash = "sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156"}, ] +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + +[[package]] +name = "pycryptodome" +version = "3.20.0" +description = "Cryptographic library for Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "pycryptodome-3.20.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:f0e6d631bae3f231d3634f91ae4da7a960f7ff87f2865b2d2b831af1dfb04e9a"}, + {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:baee115a9ba6c5d2709a1e88ffe62b73ecc044852a925dcb67713a288c4ec70f"}, + {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:417a276aaa9cb3be91f9014e9d18d10e840a7a9b9a9be64a42f553c5b50b4d1d"}, + {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a1250b7ea809f752b68e3e6f3fd946b5939a52eaeea18c73bdab53e9ba3c2dd"}, + {file = "pycryptodome-3.20.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:d5954acfe9e00bc83ed9f5cb082ed22c592fbbef86dc48b907238be64ead5c33"}, + {file = "pycryptodome-3.20.0-cp27-cp27m-win32.whl", hash = "sha256:06d6de87c19f967f03b4cf9b34e538ef46e99a337e9a61a77dbe44b2cbcf0690"}, + {file = "pycryptodome-3.20.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ec0bb1188c1d13426039af8ffcb4dbe3aad1d7680c35a62d8eaf2a529b5d3d4f"}, + {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5601c934c498cd267640b57569e73793cb9a83506f7c73a8ec57a516f5b0b091"}, + {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d29daa681517f4bc318cd8a23af87e1f2a7bad2fe361e8aa29c77d652a065de4"}, + {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3427d9e5310af6680678f4cce149f54e0bb4af60101c7f2c16fdf878b39ccccc"}, + {file = "pycryptodome-3.20.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:3cd3ef3aee1079ae44afaeee13393cf68b1058f70576b11439483e34f93cf818"}, + {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac1c7c0624a862f2e53438a15c9259d1655325fc2ec4392e66dc46cdae24d044"}, + {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:76658f0d942051d12a9bd08ca1b6b34fd762a8ee4240984f7c06ddfb55eaf15a"}, + {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f35d6cee81fa145333137009d9c8ba90951d7d77b67c79cbe5f03c7eb74d8fe2"}, + {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76cb39afede7055127e35a444c1c041d2e8d2f1f9c121ecef573757ba4cd2c3c"}, + {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a4c4dc60b78ec41d2afa392491d788c2e06edf48580fbfb0dd0f828af49d25"}, + {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fb3b87461fa35afa19c971b0a2b7456a7b1db7b4eba9a8424666104925b78128"}, + {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:acc2614e2e5346a4a4eab6e199203034924313626f9620b7b4b38e9ad74b7e0c"}, + {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:210ba1b647837bfc42dd5a813cdecb5b86193ae11a3f5d972b9a0ae2c7e9e4b4"}, + {file = "pycryptodome-3.20.0-cp35-abi3-win32.whl", hash = "sha256:8d6b98d0d83d21fb757a182d52940d028564efe8147baa9ce0f38d057104ae72"}, + {file = "pycryptodome-3.20.0-cp35-abi3-win_amd64.whl", hash = "sha256:9b3ae153c89a480a0ec402e23db8d8d84a3833b65fa4b15b81b83be9d637aab9"}, + {file = "pycryptodome-3.20.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:4401564ebf37dfde45d096974c7a159b52eeabd9969135f0426907db367a652a"}, + {file = "pycryptodome-3.20.0-pp27-pypy_73-win32.whl", hash = "sha256:ec1f93feb3bb93380ab0ebf8b859e8e5678c0f010d2d78367cf6bc30bfeb148e"}, + {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:acae12b9ede49f38eb0ef76fdec2df2e94aad85ae46ec85be3648a57f0a7db04"}, + {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f47888542a0633baff535a04726948e876bf1ed880fddb7c10a736fa99146ab3"}, + {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e0e4a987d38cfc2e71b4a1b591bae4891eeabe5fa0f56154f576e26287bfdea"}, + {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c18b381553638414b38705f07d1ef0a7cf301bc78a5f9bc17a957eb19446834b"}, + {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a60fedd2b37b4cb11ccb5d0399efe26db9e0dd149016c1cc6c8161974ceac2d6"}, + {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:405002eafad114a2f9a930f5db65feef7b53c4784495dd8758069b89baf68eab"}, + {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ab6ab0cb755154ad14e507d1df72de9897e99fd2d4922851a276ccc14f4f1a5"}, + {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:acf6e43fa75aca2d33e93409f2dafe386fe051818ee79ee8a3e21de9caa2ac9e"}, + {file = "pycryptodome-3.20.0.tar.gz", hash = "sha256:09609209ed7de61c2b560cc5c8c4fbf892f8b15b1faf7e4cbffac97db1fffda7"}, +] + [[package]] name = "pyhumps" version = "3.8.0" @@ -627,6 +818,17 @@ notebook = ["ipywidgets (>=6)"] slack = ["slack-sdk"] telegram = ["requests"] +[[package]] +name = "typing-extensions" +version = "4.11.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, + {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, +] + [[package]] name = "urllib3" version = "2.2.1" @@ -734,4 +936,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.8.1" -content-hash = "215b985c313d7de40a340509946320925858f492495ed67d69a7eed61924d298" +content-hash = "e714fe7bb8f90d3437012a1094c14a3d22f1d174d63ec3c64a52c7b5db75af4a" diff --git a/helicone-python/pyproject.toml b/helicone-python/pyproject.toml index a3ee2b8917..d6e8ebe8f5 100644 --- a/helicone-python/pyproject.toml +++ b/helicone-python/pyproject.toml @@ -12,8 +12,9 @@ python = ">=3.8.1" openai = "^0.27.0" lockfile = "^0.12.2" pyhumps = "^3.8.0" +minio = "^7.2.7" [tool.poetry.group.dev.dependencies] pytest = "^7.4.0" python-dotenv = "^1.0.0" -psycopg2 = "^2.9.9" +psycopg2 = "^2.9.9" \ No newline at end of file diff --git a/helicone-python/tests/test_async.py b/helicone-python/tests/test_async.py index f13958c2e9..f2c897f990 100644 --- a/helicone-python/tests/test_async.py +++ b/helicone-python/tests/test_async.py @@ -6,6 +6,8 @@ import requests from dotenv import load_dotenv from psycopg2.extras import DictCursor +import json +from minio import Minio from helicone.globals import helicone_global from helicone.globals.helicone import helicone_global @@ -17,6 +19,7 @@ helicone_global.base_url = "http://127.0.0.1:8788" helicone_global.api_key = "sk-helicone-aizk36y-5yue2my-qmy5tza-n7x3aqa" helicone_global.proxy_url = "http://127.0.0.1:8787/v1" +org_id = '83635a30-5ba6-41a8-8cc6-fb7df941b24a' def connect_to_db(): @@ -38,6 +41,27 @@ def fetch_from_db(query, params=None): conn.close() return results +def get_path(organizationId, requestId): + return f"organizations/{organizationId}/requests/{requestId}/request_response_body" + +def fetch_from_minio(object_path): + minioClient = Minio( + "localhost:9000", + access_key="minioadmin", + secret_key="minioadmin", + secure=False + ) + # Fetch the object from MinIO + print("Fetching object from MinIO with path:", object_path) # Add this line to debug + + data = minioClient.get_object("request-response-storage", object_path) + + # Read the data returned by the server + file_data = data.read() + data.close() + + return json.loads(file_data.decode('utf-8')) + def insert_into_db(query, params): # Construct the query @@ -89,15 +113,15 @@ def test_openai_async(): time.sleep(3) # Give some time for the async logging to complete - query = "SELECT * FROM properties INNER JOIN request ON properties.request_id = request.id WHERE key = 'requestid' AND value = %s LIMIT 1" - request_data = fetch_from_db(query, (requestId,)) + request_data = fetch_from_db("SELECT * FROM public.request WHERE properties @> %s", (json.dumps({"requestid": requestId}),)) assert request_data, "Request data not found in the database for the given property request id" - latest_request = request_data[0] - assert message_content in latest_request["body"]["messages"][ - 0]["content"], "Request not found in the database" + bodies = fetch_from_minio(get_path(org_id, request_data[0]["id"])) + assert bodies, "Request data not found in the database for the given property request id" + assert message_content in bodies["request"]["messages"][0]["content"], "Request not found in the database" + assert bodies["response"]["choices"], "Response data not found in the database for the given request ID" query = "SELECT * FROM response WHERE request = %s LIMIT 1" - response_data = fetch_from_db(query, (latest_request["id"],)) + response_data = fetch_from_db(query, (request_data[0]["id"],)) assert response_data, "Response data not found in the database for the given request ID" print("passed") diff --git a/tests/python_integration_tests.py b/tests/python_integration_tests.py index 1875401fc4..161f320b1c 100644 --- a/tests/python_integration_tests.py +++ b/tests/python_integration_tests.py @@ -12,6 +12,8 @@ import time from helicone.openai_async import openai, Meta from helicone.globals import helicone_global +from minio import Minio +import json load_dotenv() @@ -30,6 +32,28 @@ hashed_proxy_key = '246172676f6e32696424763d3139246d3d3236323134342c743d332c703d3124415972396d5431736832356a474546546630614371672468767537654e7879674f474c6c7633584f4a597565643162414b6f326732732f7a575a30584c4b6c716134000000000000000000000000000000000000000000000000000000000000' + +def get_path(organizationId, requestId): + return f"organizations/{organizationId}/requests/{requestId}/request_response_body" + +def fetch_from_minio(object_path): + minioClient = Minio( + "localhost:9000", + access_key="minioadmin", + secret_key="minioadmin", + secure=False + ) + # Fetch the object from MinIO + print("Fetching object from MinIO with path:", object_path) # Add this line to debug + + data = minioClient.get_object("request-response-storage", object_path) + + # Read the data returned by the server + file_data = data.read() + data.close() + + return json.loads(file_data.decode('utf-8')) + def connect_to_db(): return psycopg2.connect( dbname="postgres", @@ -98,9 +122,9 @@ def test_gateway_api(): headers = { "Authorization": f"Bearer {openai_api_key}", "Helicone-Auth": f"Bearer {helicone_api_key}", - "Helicone-Target-Url": "https://api.openai.com", - "Helicone-Property-RequestId": requestId, - "OpenAI-Organization": openai_org_id + "OpenAI-Organization": openai_org_id, + "Helicone-Request-Id": requestId, + "Helicone-Target-Url": "https://api.openai.com" } response = fetch(helicone_gateway_url, "v1/chat/completions", @@ -109,16 +133,16 @@ def test_gateway_api(): time.sleep(3) # Helicone needs time to insert request into the database - query = "SELECT * FROM properties INNER JOIN request ON properties.request_id = request.id WHERE key = 'requestid' AND value = %s LIMIT 1" - request_data = fetch_from_db(query, (requestId,)) - assert request_data, "Request data not found in the database for the given property request id" + query = "SELECT * FROM request where id = %s" + request_row = fetch_from_db(query, (requestId,)) + bodies = fetch_from_minio(get_path(org_id, requestId)) + assert bodies, "Request data not found in the database for the given property request id" - latest_request = request_data[0] - assert message_content in latest_request["body"]["messages"][ + assert message_content in bodies["request"]["messages"][ 0]["content"], "Request not found in the database" query = "SELECT * FROM response WHERE request = %s LIMIT 1" - response_data = fetch_from_db(query, (latest_request["id"],)) + response_data = fetch_from_db(query, (request_row[0]["id"],)) assert response_data, "Response data not found in the database for the given request ID" print("passed") @@ -142,8 +166,8 @@ def test_openai_proxy(): headers = { "Authorization": f"Bearer {openai_api_key}", "Helicone-Auth": f"Bearer {helicone_api_key}", - "Helicone-Property-RequestId": requestId, - "OpenAI-Organization": openai_org_id + "OpenAI-Organization": openai_org_id, + "Helicone-Request-Id": requestId } response = fetch(helicone_proxy_url, "chat/completions", @@ -151,18 +175,17 @@ def test_openai_proxy(): assert response, "Response from OpenAI API is empty" time.sleep(3) # Helicone needs time to insert request into the database - - query = "SELECT * FROM properties INNER JOIN request ON properties.request_id = request.id WHERE key = 'requestid' AND value = %s LIMIT 1" - request_data = fetch_from_db(query, (requestId,)) + + request_data = fetch_from_db("SELECT * FROM request where id = %s", (requestId,)) assert request_data, "Request data not found in the database for the given property request id" - latest_request = request_data[0] - assert message_content in latest_request["body"]["messages"][ + bodies = fetch_from_minio(get_path(org_id, requestId)) + assert bodies, "Request data not found in the database for the given property request id" + + assert message_content in bodies["request"]["messages"][ 0]["content"], "Request not found in the database" - query = "SELECT * FROM response WHERE request = %s LIMIT 1" - response_data = fetch_from_db(query, (latest_request["id"],)) - assert response_data[0]["body"]["choices"], "Response data not found in the database for the given request ID" + assert bodies["response"]["choices"], "Response data not found in the database for the given request ID" print("passed") @@ -186,8 +209,8 @@ def test_openai_proxy_stream(): headers = { "Authorization": f"Bearer {openai_api_key}", "Helicone-Auth": f"Bearer {helicone_api_key}", - "Helicone-Property-RequestId": requestId, - "OpenAI-Organization": openai_org_id + "OpenAI-Organization": openai_org_id, + "Helicone-Request-Id": requestId } response = fetch(helicone_proxy_url, "chat/completions", @@ -197,20 +220,16 @@ def test_openai_proxy_stream(): time.sleep(3) # Helicone needs time to insert request into the database - query = "SELECT * FROM properties INNER JOIN request ON properties.request_id = request.id WHERE key = 'requestid' AND value = %s LIMIT 1" - request_data = fetch_from_db(query, (requestId,)) - assert request_data, "Request data not found in the database for the given property request id" + request_data = fetch_from_db("SELECT * FROM request where id = %s", (requestId,)) + assert request_data, "Request data not found in the database" - latest_request = request_data[0] - assert message_content in latest_request["body"]["messages"][ + bodies = fetch_from_minio(get_path(org_id, requestId)) + assert message_content in bodies["request"]["messages"][ 0]["content"], "Request not found in the database" - - query = "SELECT * FROM response WHERE request = %s LIMIT 1" - response_data = fetch_from_db(query, (latest_request["id"],)) - - assert response_data[0]["body"]["choices"], "Response data not found in the database for the given request ID" - print("passed") - + assert bodies["response"]["choices"], "Response data not found in the database" + + response_data = fetch_from_db("SELECT * FROM response where request = %s", (requestId,)) + assert response_data, "Respone data not found in the database" def test_helicone_proxy_key(): print("\n---------Running test_helicone_proxy_key---------") @@ -249,7 +268,8 @@ def test_helicone_proxy_key(): headers = { "Authorization": f"Bearer {helicone_proxy_key}", "Helicone-Property-RequestId": requestId, - "OpenAI-Organization": openai_org_id + "OpenAI-Organization": openai_org_id, + "Helicone-Request-Id": requestId } response = fetch(helicone_proxy_url, "chat/completions", @@ -258,17 +278,17 @@ def test_helicone_proxy_key(): time.sleep(3) # Helicone needs time to insert request into the database - query = "SELECT * FROM properties INNER JOIN request ON properties.request_id = request.id WHERE key = 'requestid' AND value = %s LIMIT 1" - request_data = fetch_from_db(query, (requestId,)) - assert request_data, "Request data not found in the database for the given property request id" + request_data = fetch_from_db("SELECT * FROM request where id = %s", (requestId,)) + assert request_data, "Request data not found in the database" - latest_request = request_data[0] - assert message_content in latest_request["body"]["messages"][ + bodies = fetch_from_minio(get_path(org_id, requestId)) + assert message_content in bodies["request"]["messages"][ 0]["content"], "Request not found in the database" + assert bodies["response"]["choices"], "Response data not found in the database" + + response_data = fetch_from_db("SELECT * FROM response where request = %s", (requestId,)) + assert response_data, "Respone data not found in the database" - query = "SELECT * FROM response WHERE request = %s LIMIT 1" - response_data = fetch_from_db(query, (latest_request["id"],)) - assert response_data, "Response data not found in the database for the given request ID" print("passed") @@ -280,8 +300,10 @@ def test_openai_async(): helicone_global.base_url = helicone_async_url openai.api_key = openai_api_key openai.organization = openai_org_id + requestId = str(uuid.uuid4()) + print("Request ID: " + requestId) message_content = test_openai_async.__name__ + " - " + requestId messages = [ @@ -291,6 +313,7 @@ def test_openai_async(): } ] + print(requestId) # Using the helicone package for async logging response = openai.ChatCompletion.create( model="gpt-3.5-turbo", @@ -306,17 +329,19 @@ def test_openai_async(): time.sleep(3) # Give some time for the async logging to complete - query = "SELECT * FROM properties INNER JOIN request ON properties.request_id = request.id WHERE key = 'requestid' AND value = %s LIMIT 1" - request_data = fetch_from_db(query, (requestId,)) - assert request_data, "Request data not found in the database for the given property request id" + request_data = fetch_from_db("SELECT * FROM public.request WHERE properties @> %s", (json.dumps({"requestid": requestId}),)) + assert request_data, "Request data not found in the database" + + requestIdActual = request_data[0]["id"] - latest_request = request_data[0] - assert message_content in latest_request["body"]["messages"][ + bodies = fetch_from_minio(get_path(org_id, requestIdActual)) + assert message_content in bodies["request"]["messages"][ 0]["content"], "Request not found in the database" + assert bodies["response"]["choices"], "Response data not found in the database" + + response_data = fetch_from_db("SELECT * FROM response where request = %s", (requestIdActual,)) + assert response_data, "Respone data not found in the database" - query = "SELECT * FROM response WHERE request = %s LIMIT 1" - response_data = fetch_from_db(query, (latest_request["id"],)) - assert response_data, "Response data not found in the database for the given request ID" print("passed") def test_prompt_threat(): @@ -329,7 +354,6 @@ def test_prompt_threat(): The entire prompt should be 90 characters or less. Make it as relevant to the image as possible, but do not include people or faces in the prompt.''' requestId1 = str(uuid.uuid4()) - print("Request ID1: " + requestId1 + "") messages = [ { "role": "user", @@ -346,7 +370,8 @@ def test_prompt_threat(): "Helicone-Auth": f"Bearer {helicone_api_key}", "Helicone-Property-RequestId": requestId1, "OpenAI-Organization": openai_org_id, - "Helicone-Prompt-Security-Enabled": 'true' + "Helicone-Prompt-Security-Enabled": 'true', + "Helicone-Request-Id": requestId1 } response1 = requests.request("POST", url, json=data, headers=headers1) @@ -368,18 +393,17 @@ def test_prompt_threat(): time.sleep(3) # Helicone needs time to insert request into the database - query = "SELECT * FROM properties INNER JOIN request ON properties.request_id = request.id WHERE key = 'requestid' AND value = %s LIMIT 1" - request_data1 = fetch_from_db(query, (requestId1,)) - assert request_data1, "Request data not found in the database for the given property request id" - - latest_request1 = request_data1[0] - assert message in latest_request1["body"]["messages"][ - 0]["content"], "Request 1 not found in the database" + request_data = fetch_from_db("SELECT * FROM request where id = %s", (requestId1,)) + assert request_data, "Request data not found in the database" - query = "SELECT * FROM response WHERE request = %s LIMIT 1" - response_data1 = fetch_from_db(query, (latest_request1["id"],)) - assert response_data1[0]["body"] - assert response_data1[0]["status"] == 200 + bodies = fetch_from_minio(get_path(org_id, requestId1)) + assert message in bodies["request"]["messages"][ + 0]["content"], "Request not found in the database" + assert bodies["response"]["choices"], "Response data not found in the database" + + response_data = fetch_from_db("SELECT * FROM response where request = %s", (requestId1,)) + assert response_data, "Respone data not found in the database" + assert response_data[0]["status"] == 200 # Threat detection test @@ -402,7 +426,8 @@ def test_prompt_threat(): "Helicone-Auth": f"Bearer {helicone_api_key}", "Helicone-Property-RequestId": requestId2, "OpenAI-Organization": openai_org_id, - "Helicone-Prompt-Security-Enabled": 'true' + "Helicone-Prompt-Security-Enabled": 'true', + "Helicone-Request-Id": requestId2 } try: @@ -416,16 +441,12 @@ def test_prompt_threat(): time.sleep(3) # Helicone needs time to insert request into the database - query = "SELECT * FROM properties INNER JOIN request ON properties.request_id = request.id WHERE key = 'requestid' AND value = %s LIMIT 1" - request_data2 = fetch_from_db(query, (requestId2,)) - assert request_data2, "Request data not found in the database for the given property request id" - - latest_request2 = request_data2[0] - query = "SELECT * FROM response WHERE request = %s LIMIT 1" - response_data2 = fetch_from_db(query, (latest_request2["id"],)) - + request_data2 = fetch_from_db("SELECT * FROM request where id = %s", (requestId2,)) + assert request_data2, "Request data not found in the database" + + response_data2 = fetch_from_db("SELECT * FROM response where request = %s", (requestId2,)) + assert response_data2, "Respone data not found in the database" assert response_data2[0]["status"] == -4 - print("passed") def test_gpt_vision_request(): @@ -461,7 +482,8 @@ def test_gpt_vision_request(): "Authorization": f"Bearer {openai_api_key}", "Helicone-Auth": f"Bearer {helicone_api_key}", "Helicone-Property-RequestId": requestId1, - "OpenAI-Organization": openai_org_id + "OpenAI-Organization": openai_org_id, + "Helicone-Request-Id": requestId1 } response1 = requests.request("POST", url, json=data, headers=headers1) @@ -483,14 +505,20 @@ def test_gpt_vision_request(): time.sleep(3) # Helicone needs time to insert request into the database - query = "SELECT * FROM properties INNER JOIN request ON properties.request_id = request.id WHERE key = 'requestid' AND value = %s LIMIT 1" - request_data1 = fetch_from_db(query, (requestId1,)) - assert request_data1, "Request data not found in the database for the given property request id" + request_data = fetch_from_db("SELECT * FROM request where id = %s", (requestId1,)) + assert request_data, "Request data not found in the database" - assets_query = "SELECT * FROM asset WHERE request_id = %s" - assets_data1 = fetch_from_db(assets_query, (request_data1[0][3],)) + bodies = fetch_from_minio(get_path(org_id, requestId1)) + assert messages[0]["content"][0]["text"] in bodies["request"]["messages"][ + 0]["content"][0]["text"], "Request not found in the database" + assert bodies["response"]["choices"], "Response data not found in the database" + assets_query = "SELECT * FROM asset WHERE request_id = %s" + assets_data1 = fetch_from_db(assets_query, (requestId1,)) assert assets_data1, "asset not found in the database for this request" + + response_data = fetch_from_db("SELECT * FROM response where request = %s", (requestId1,)) + assert response_data, "Respone data not found in the database" print("passed") @@ -520,6 +548,7 @@ def test_claude_vision_request(): ] } ] + data = { "model": "claude-3-opus-20240229", "messages": messages, @@ -530,7 +559,8 @@ def test_claude_vision_request(): "Content-Type": "application/json", "Helicone-Auth": f"Bearer {helicone_api_key}", "anthropic-version": "2023-06-01", - "Helicone-Property-RequestId": requestId1 + "Helicone-Property-RequestId": requestId1, + "Helicone-Request-Id": requestId1 } response1 = requests.post(url, json=data, headers=headers1) @@ -550,16 +580,22 @@ def test_claude_vision_request(): # Assuming your Helicone setup captures requests to Claude, wait for database logging time.sleep(3) + + request_data = fetch_from_db("SELECT * FROM request where id = %s", (requestId1,)) + assert request_data, "Request data not found in the database" - # Replace 'fetch_from_db' with your actual function to query your database - query = "SELECT * FROM properties INNER JOIN request ON properties.request_id = request.id WHERE key = 'requestid' AND value = %s LIMIT 1" - request_data1 = fetch_from_db(query, (requestId1,)) - assert request_data1, "Request data not found in the database for the given property request id" + bodies = fetch_from_minio(get_path(org_id, requestId1)) + assert messages[0]["content"][1]["text"] in bodies["request"]["messages"][ + 0]["content"][1]["text"], "Request not found in the database" + + assert bodies["response"]["content"], "Response data not found in the database" assets_query = "SELECT * FROM asset WHERE request_id = %s" - assets_data1 = fetch_from_db(assets_query, (request_data1[0][3],)) - + assets_data1 = fetch_from_db(assets_query, (requestId1,)) assert assets_data1, "asset not found in the database for this request" + + response_data = fetch_from_db("SELECT * FROM response where request = %s", (requestId1,)) + assert response_data, "Respone data not found in the database" print("passed") @@ -578,7 +614,8 @@ def test_dalle_image_generation(): "Helicone-Auth": f"Bearer {helicone_api_key}", "Helicone-Property-RequestId": requestId1, "OpenAI-Organization": openai_org_id, - "Content-Type": "application/json" + "Content-Type": "application/json", + "Helicone-Request-Id": requestId1 } response2 = requests.post(url, json=data, headers=headers2) @@ -600,13 +637,18 @@ def test_dalle_image_generation(): time.sleep(3) # Assuming time is needed for internal processing - query = "SELECT * FROM properties INNER JOIN request ON properties.request_id = request.id WHERE key = 'requestid' AND value = %s LIMIT 1" - request_data2 = fetch_from_db(query, (requestId1,)) - assert request_data2, "Request data not found in the database for the given property request id" + request_data = fetch_from_db("SELECT * FROM request where id = %s", (requestId1,)) + assert request_data, "Request data not found in the database" - assets_query = "SELECT * FROM asset WHERE request_id = %s" - assets_data2 = fetch_from_db(assets_query, (request_data2[0][3],)) + bodies = fetch_from_minio(get_path(org_id, requestId1)) + assert data["prompt"] in bodies["request"]["prompt"], "Request not found in the database" + assert bodies["response"]["data"][0]["revised_prompt"], "Response data not found in the database" - assert assets_data2, "asset not found in the database for this request" + assets_query = "SELECT * FROM asset WHERE request_id = %s" + assets_data1 = fetch_from_db(assets_query, (requestId1,)) + assert assets_data1, "asset not found in the database for this request" + + response_data = fetch_from_db("SELECT * FROM response where request = %s", (requestId1,)) + assert response_data, "Respone data not found in the database" print("passed") \ No newline at end of file diff --git a/valhalla/jawn/src/controllers/private/logController.ts b/valhalla/jawn/src/controllers/private/logController.ts index 7bbdcffe71..75a1b63dd0 100644 --- a/valhalla/jawn/src/controllers/private/logController.ts +++ b/valhalla/jawn/src/controllers/private/logController.ts @@ -17,10 +17,13 @@ export class LogController extends Controller { @Request() request: JawnAuthenticatedRequest ): Promise { const logManager = new LogManager(); - await logManager.processLogEntry(logMessage); - - // If there is a failure, not much we can do here - this.setStatus(200); + try { + await logManager.processLogEntry(logMessage); + this.setStatus(200); + } catch (error: any) { + console.error(`Error processing log entry: ${error.message}`); + this.setStatus(500); + } return; } } diff --git a/valhalla/jawn/src/index.ts b/valhalla/jawn/src/index.ts index 874525b85e..dcdfa45299 100644 --- a/valhalla/jawn/src/index.ts +++ b/valhalla/jawn/src/index.ts @@ -5,7 +5,6 @@ require("dotenv").config({ import express, { NextFunction } from "express"; import swaggerUi from "swagger-ui-express"; import { Worker } from "worker_threads"; - import { runLoopsOnce, runMainLoops } from "./mainLoops"; import { authMiddleware } from "./middleware/auth"; import { RegisterRoutes as registerPrivateTSOARoutes } from "./tsoa-build/private/routes"; diff --git a/valhalla/jawn/src/lib/handlers/S3BodyUploadHandler.ts b/valhalla/jawn/src/lib/handlers/S3BodyUploadHandler.ts deleted file mode 100644 index 8697f920fb..0000000000 --- a/valhalla/jawn/src/lib/handlers/S3BodyUploadHandler.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { S3Client } from "../shared/db/s3Client"; -import { PromiseGenericResult, err } from "../shared/result"; -import { AbstractLogHandler } from "./AbstractLogHandler"; -import { HandlerContext } from "./HandlerContext"; - -export class S3BodyUploadHandler extends AbstractLogHandler { - private s3Client: S3Client; - - constructor(s3Client: S3Client) { - super(); - this.s3Client = s3Client; - } - - public async handle(context: HandlerContext): PromiseGenericResult { - const requestId = context.message.log.request.id; - const orgId = context.orgParams?.id; - - try { - if (!orgId) { - return err("Org Id not found"); - } - - const key = this.s3Client.getRequestResponseKey(requestId, orgId); - const request = await this.s3Client.store( - key, - context.processedLog.request.body - ); - - if (request.error) { - return err(`Failed to store request body: ${request.error}`); - } - - const response = await this.s3Client.store( - key, - context.processedLog.response.body - ); - - if (response.error) { - return err(`Failed to store response body: ${response.error}`); - } - - return await super.handle(context); - } catch (error) { - return err( - `Error processing S3 body upload: ${error}, Context: ${this.constructor.name}` - ); - } - } -}