diff --git a/.gitignore b/.gitignore index c1e69543e..a4d2733b7 100644 --- a/.gitignore +++ b/.gitignore @@ -79,3 +79,5 @@ paulgraham.py supabase/seed-airwallex.sql airwallexpayouts.py application.log +backend/celerybeat-schedule.db + diff --git a/Pipfile b/Pipfile index 091a4d72a..d006103fc 100644 --- a/Pipfile +++ b/Pipfile @@ -47,8 +47,12 @@ watchdog = "*" langchain-community = "*" langchain-openai = "*" pydantic-settings = "*" -unstructured = {extras = ["all-docs"], version = "*"} langfuse = "*" +pandasai = "*" +colorlog = "*" +psycopg2-binary = "*" +psycopg2 = "*" +unstructured = {extras = ["all-docs"], version = "*"} [dev-packages] black = "*" diff --git a/Pipfile.lock b/Pipfile.lock index c438fe314..cc0d09907 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "7b0a7a1d9a850c686e65ee17aecfe4de8b84e92c7b4b155dcda21e64a75257d4" + "sha256": "c655d8a43b0a0a2d3460e7707c2059601ec2bf2830d20a6ed7cf45f07d7d844b" }, "pipfile-spec": 6, "requires": { @@ -136,6 +136,14 @@ "markers": "python_version >= '3.8'", "version": "==4.2.0" }, + "astor": { + "hashes": [ + "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5", + "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.8.1" + }, "async-generator": { "hashes": [ "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b", @@ -251,21 +259,21 @@ }, "boto3": { "hashes": [ - "sha256:9fd66f22a4cdd63165a7a19186fff9b6e3d742e83498ea3f3231bab6ae4bf0f3", - "sha256:ae1a974c728c076a49392a695102124f650f45361c654bb7c0bef1bb644c52d5" + "sha256:2ed136f9cf79e783e12424db23e970d1c50e65a8d7a9077efa71cbf8496fb7a3", + "sha256:5069b2c647c73c8428378e88b32bd23f568001f897a6f01179fae25de72a7ca6" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.34.41" + "version": "==1.34.42" }, "botocore": { "hashes": [ - "sha256:3a6943c75a0d292ab6e008bce58ee6503776969479f991f5ad03a5d877af29ae", - "sha256:9b5827332da766da487e5a5b14b36e02528be9f2e899f909577afb7001eb441d" + "sha256:93755c3ede4bd9f6180b3118f6b607acca8b633fd2668226794a543ce79a2434", + "sha256:cf4fad50d09686f03e44418fcae9dd24369658daa556357cedc0790cfcd6fdac" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.34.41" + "version": "==1.34.42" }, "bytecode": { "hashes": [ @@ -510,6 +518,15 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==15.0.1" }, + "colorlog": { + "hashes": [ + "sha256:3e3e079a41feb5a1b64f978b5ea4f46040a94f11f0e8bbb8261e3dbbeca64d44", + "sha256:4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33" + ], + "index": "pypi", + "markers": "python_version >= '3.6'", + "version": "==6.8.2" + }, "contourpy": { "hashes": [ "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8", @@ -640,70 +657,70 @@ }, "ddtrace": { "hashes": [ - "sha256:0239709913f4f7a008a4e4ebd9f7810640bdb73ca68308804cbf884d510cf240", - "sha256:0abc759f5e4d6fcc59dbb7de300a8550005071aef41b29ceda37a9cf8a45bd2e", - "sha256:0cc2b7e45ae870dd9d2beb172d36810893a94bb1a605ba3a8e746f3e9bc88a55", - "sha256:0def60135e371fc2b5ace1f6c6c21073d1723506245c512eb8a8fc0406159a87", - "sha256:1013e6c0026035744f463a3a252b4b810c090974564a5e5dcb047b9d30d5a18b", - "sha256:11252ce5fb68f8c89d7866f001d8f744fa10f07da0a35a57fa261fec1409bb2b", - "sha256:12439445bc6a6cdeca0cb781c4cea37461fc7ab65ea5aeaace76329d5b645e2e", - "sha256:13412381b0eee7079701d8e3ec9b6963f6de405c8ec49d977be65ec5d4e987dc", - "sha256:17d4338961b00aa17590237c07b61c60357fbe6577b02159d6dba496063cc2cc", - "sha256:2352f4ae5140e919aeb5f3c7c19b58333d601f6f1982baeeac4a737b572661cc", - "sha256:2d8a34b41a1672119adca2c6f3b064c6346f5f4499218199697575bf2c0400df", - "sha256:326460202d801d0bb409b42727f2344798e74511febe11091b09b07344ceece2", - "sha256:364d452ccfded04db36a93a253e4e3ab00290ea5416a2c86c3091e06d1a70aff", - "sha256:44d3fb389113f2574160f31c56755687845a95a8bd5fe12208faa7f0e24d0eb4", - "sha256:4650c892236a07f8c6ab1b8cff8d9775b431542e2fc668830e3ecd93c5f55154", - "sha256:4d2941c62d6727f327094c444713c2584d241c0bbc7447f6185dd06b3d1cb1f9", - "sha256:4f7fee39437dc2ae9202ca9d1837bb4f3f07ead29b3a17814f7d0c5d842e2a0a", - "sha256:535ee7a6f9003376597a6a887a2efa0d1ce3109157edbdd0794d4c2fb9c1b754", - "sha256:5639112e22076ce8ba0e06b9a0ebcd9f1fa8bf6116cd17f96aec32e256d9538e", - "sha256:59eb7b545ad1bc1ddc3763b615975f325fd0e08c8889a5cab5f2acc996f0b4b4", - "sha256:5e1b53d509382bd29bcb9441fcac7c3a560c7440376fd9110051b99ab1a38854", - "sha256:61afd60be6af89e1201d652e6d3b499c27b95ea6aeccd3098dbadd736054485f", - "sha256:636a593a09c9e6d97fd206751aa1ff9d6647699a4a661a277cf49c628114778a", - "sha256:64fda6dc32533212630f27bf20f1a76f8831cdd49100f4d94c53a50e56354ac9", - "sha256:658523572f6995f16391e10be005851d52b3558eca07a9ab8c3b1961944a619b", - "sha256:68f86fdfc5720863727914a1e9f63ed681f1c0851e1dc90b53ec7c2d48fc4898", - "sha256:6d5fc1ed9b3a399c39aba211e8070fa94df89bf407076c76dd4565e33f1b0ab7", - "sha256:6e705b29774aba337606fb2f04610cd7f054916d32a1638cb10292978044d39a", - "sha256:752cbc6eb5540d25f5729529dbf07a7c8eb6f6c469c4ed892f3c7c1fb00a20d7", - "sha256:8394841d4d63a3493e43cddd6fd867ed7e653ae8720352b9cf821386e212aad6", - "sha256:918964f98f8fdcca2cbf35f670e4257280707c1b38dc9f49682b1d1faae10ff6", - "sha256:973e63ac6216f4202fc0e3712a9756291dfd244d1d70e12a5f11899166c78112", - "sha256:97be1e5e240fd2e180c393cb3bf835b5375755c766ea0a38b13d71e42daee4a5", - "sha256:986c4bf30d5f4e3690677bf7813ffa7f69ae9b709e8abf54824eb295dfc67b4c", - "sha256:a00afb76df909fb005f784c387eaa83d9b4ee00cb2f60ca82be204af94d7a5da", - "sha256:a2bf77769ee39b61364ade7367cee6803210f1350050b2b4d1a483dcc9918a24", - "sha256:a6188a676a7a68e6fa69daaa16d05e716aaa5eb8761969ffb1b53f97eb2feffd", - "sha256:a76f6f9d1f3a955b8be1d48c8c31ea2b7520e62d5f9e4a2877892ac75d845cdd", - "sha256:a89ef3d48f313f62045c941a07c04ed4729734211c309ffa3df68cce89ad1397", - "sha256:ae72d8ce673f09d269b1e6a5aedba47c073aed8a15f2b333804461bcd7dde4a3", - "sha256:af51e41f79568085ca529f77f8fdbb000dc20f41acd557d906f47ebcc5c70b4f", - "sha256:b0eac508c3f6cd5392bc4093ad82078c56b2025e1761d481f58af198a3d68bd0", - "sha256:b29ed615cb742b35abd8b7a23ec29d8f05ada0e6434a7409cf55f4dabe6b8552", - "sha256:b393ce67f0e13c1dc2da6a142ad698efbb9e977fb3d8d549954007a01860345e", - "sha256:b7fefb1db11c23c7fe02ab798f4a878759d053d015bba5250e2a9404fc247da4", - "sha256:ba68ddca8b0a643e64e15cc39727cec3149671d28e9f5024264face606dd69c9", - "sha256:bffdc0cca791aad249ca6384ebe6988f99a7d8e11bb6b1ff714d16644af29dde", - "sha256:c07fb4de27b7626ff9e4aedc5fdf302a3a69006ca81e6dbce6d16d8ebf7547ce", - "sha256:c4e743d4102e0a76ca27868a7c27d4b8bc037c574f61c1fc263a4bb62c09cb7f", - "sha256:c83eb7a4f5a74d8df13b1195140ec85c982425139c4946a7915926c1e378c574", - "sha256:c84a393448ac50ee4a3cf19e105bcb8bb84381241ac544afae973ea8424d3ef4", - "sha256:cb8be39df72f3e7319eff2dd12517db3742e3effc248061a76fc0f73fccf7edd", - "sha256:cc17be5812c299d2682ee8391035098ced735531badd9e5ccf0925e5fc8c7555", - "sha256:d52b3d3cf48b143c39d2f318bff26a3a70f21102ef1e0245b4512fabbe22f121", - "sha256:dec60168fa1276cc2101ecb3e02422109495c07f2f47a0a77256bbb1a4f154ff", - "sha256:e05f97990479ff7922897a827101ae459420e4d1be21ab79b707d6a9df54afee", - "sha256:e7ebb07c816c62ce170a9e70b15fbe3c87b161316856b67a4058b1969b7694bf", - "sha256:f3fefa78874c9ef11f2b7fb18592b5e2b0072d1ec279d5051fd48df0b3ad2aa0", - "sha256:f6c74a3e1049d87229bb1938ec231b019e1d8b38de0221274f449e6f10171b6c", - "sha256:fbb5dbf725d1919686292ea314434c5cbe560d490b9d6c9851e05a94f9dbd925" + "sha256:03207981d6384b10a7ee85fb4dd1b2613166faf02ae63a67230a47d9ebb925cd", + "sha256:059c21dd3eb58d7ce2def5820af9819aa8c659e30cbec8bbda32f3c49480c513", + "sha256:064dadaa8033fd56f9e8d498c16382f01f65a471c46150b5557106b8a781a379", + "sha256:0b3e79c04702b516ca769fd5589c39e6392a8bc9d5ec9dac544f05ebe0fd06b9", + "sha256:0b57281c435782694fc545e4fd1a0dfefe23142bac2e10e7d59bdf687c497163", + "sha256:1acc84bb9f830659f8304a96c42a7b52f9da0b534e082427f1b72646a5915f23", + "sha256:1e490da9d87a36bde0d5e1b520ca2f4915400c1f413233dee7346d8447afdbf7", + "sha256:1f120a17f2c9bff10496b347cd6592d8fa35a31c3d2715b9eb9fcb2008a5fbad", + "sha256:22ea21aa27801b0b2ff4def039b7f04ac1226685246e726f2010a52c58bc91f0", + "sha256:273e22c1a57a9b5a7e53ae568762e2653e2dde7b5eb56b75aa3be69226dad204", + "sha256:2ac025b79f9f70e8b14b2647930977fbfffafe8557fb18e116be507b1cd1c640", + "sha256:3681e110f336c03e5b989c17d2e3308803467cc42e6be9987d0a6516a17289c1", + "sha256:36ba7745f534f5f811c3ae4ca1e3b1827cdb26fe3e7b7aab81c4b27ffa899e09", + "sha256:3ad54bbdb675b81001372396171a72aa02c36dd203bea6f3d64dbdf50aec4b26", + "sha256:3b5a236513b3027fcf5069bba91e0795c528a16ceb6317398737b0f09864fea6", + "sha256:40f14644b553230c57def0d9febca122b847bf210ea777a924a0ee5e1b4cd92c", + "sha256:42c77dd11a3aa44cc6f7ff0de961a2651c19e048901ec7df32a0cdad45cc41d6", + "sha256:4905e66b133ba1e1e383af7df4978554ce98d753dedbd290f5425bc971df88ad", + "sha256:4c8cf7856ed0038bc6095435109523395bfa5aadaaecf860dd358f299a3d6d58", + "sha256:4e436c9345f61c373f87cc49b2f99dcd3a89c8147c9932f729ed92f5f3a27eab", + "sha256:511b6c7f710f98136584074c886b14e46d08901a85fabcc533d4a9cc1ef2ee85", + "sha256:56b808a15d898d3028b36d6c86d7664a0825e20a446d6c9ab968c22c946a9358", + "sha256:5e6480b089cef377c1ed7cacbd63846ab6a9854198f08be2c70edde00ab91173", + "sha256:6349f429f20dbc30ea81e2ab75a905b819074afdd8c1bb0b391d03c834af34ba", + "sha256:636130d37e1961184a7761bc4116753ba63a738fa4fe3ef9474a1b030539ba58", + "sha256:6714164e19486ef0a671569108b04a07ca7d24155d9743b4b8d703e1a0c1ba52", + "sha256:6849606c45e26211b8a2574eae776d6d2793e9567888c27b5bbb8946bf8921e1", + "sha256:6c1b42a8e5743e11c803948d632a55d46fb00663e17a67fffa05eb600af081dc", + "sha256:6c37fef0710fd20faba2d1b53c5b6de31396f6a1b5fe5635248a9a01b1c7b7ce", + "sha256:6f44cc317d13edd81ed46bb1fe4f3d17342734a231543a5f76c10c671ec827e8", + "sha256:7132d3036ecb3129232cdeb2a7962c0aa39c8d4529478c014dcd75fbca121356", + "sha256:7c49abd723f9fe530d5c57395dc4324fd0bffe97619e835fea82871b0d855f4e", + "sha256:833c7609122a3cb5357d8c78454f64d06b56dd4d4a9446390169c6371a57bfc3", + "sha256:838dd8f11786305f5b5df00a430238711e8887000ca7c077587ca2c582403181", + "sha256:9690dd3509e6d2854f2054fd994b0548fe6c5d20af72b457fd704c7e7120ff03", + "sha256:9dc46a2ac1f2b24a8f802151d5befede387c083e02b78e4b8930447ad9dfad38", + "sha256:9f34eb5074e8915835383c0b8887bab988b054fac2ab3ece0fe35ffaa7b1aff4", + "sha256:a81d054720d6441b258f2fd9212d6b735a76fbb7d90201a1787fbb072d422dd6", + "sha256:ac4225c297256dfaf012eee2e803d87471699b2978a4bd24e188f5a49bcbd08f", + "sha256:ad1e8762814b438bd00bc5000aebfc57d1648fc836f65b3659d37ddff5fccb30", + "sha256:b1ee27f9b863dd24ef3f30bdf0e2dee7d959b49eb6c67ac08c16fb74eb758962", + "sha256:b2a6bd2e957e3c55d039304a09e3566bee85bf112319bb790eacea8d570a0c0a", + "sha256:c2ae27d019c3e3bfb8a731413dd650d6e447dc41979ee4dcad5b77ed8917e5d9", + "sha256:cf070c21e90db2c8bfeb4571dcfecbedec4392afdbcf3196ec772ee476be3852", + "sha256:d06766a7daae9eab8e81583c98eab8ca284027eaaac714e9621deec56e528b3e", + "sha256:d8de058bc65e670661e56f715a47a844e923b9d7ce8eb971d100480ef60b4673", + "sha256:dc4c5cbfa264e3a459b980f1d6dbd03a224c47297714f9f7aa2d763667db1f9d", + "sha256:ddbd82d61a338570e8a2ff3b55ce8af31251959f90fb09e6784fdbb311cdaa21", + "sha256:e3885af6449987e02a9fadd9132e7227825968c803ce9f164aeab01f9d23fbe2", + "sha256:eaf335dc2cf92627d3192134d54b063bc998d2ac4f25ae0fe3e2b36e8af92566", + "sha256:ec14250ce150f6c69de4a94d0da34702397564a6c118c550687adbfbfec4e075", + "sha256:edbf02d7be60cc743b76d8efe0d1953fa2f97d01f805a621f913bdc78c516d64", + "sha256:ee0ecdc9df9113e76d21d6a22c6c572ab1ddb198a498a19416b1e46605234f8d", + "sha256:f1064509f258bee5ae6a4d417c7f4d8ca28664edfdc6b4b978f07801aa7b16c5", + "sha256:f2f21519c0260f4fbaed12996de0e1940739706bfa9f92868e0ef27322c6f9aa", + "sha256:f61ea2d3e608d14ee2f4e3111c559d95db21762756214d05de8b980c1aae9265", + "sha256:fc77de2e3adb2e2b261adbcfe0b1f7288586e1d1ca775555f321e22259cad02a", + "sha256:fd06242bebbeed67e456a43bd678f28f30f98c6634e75e1aaf9c4905833d2f04", + "sha256:fe1e1fe9a2a32402e91184273434cbacf5dc007f2ba97fcd717028f13e99be6d", + "sha256:fe47433f3463434c4ced69652c58a4eef96518ff29a473d9587655ab797d086f" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==2.6.1" + "version": "==2.6.2" }, "deprecated": { "hashes": [ @@ -740,7 +757,7 @@ "sha256:190348041559e21b22a1d65cee485282ca11a6f81d503fddb84d5017e9ed1e49", "sha256:80600258e7ed2f16b9aa1d7c295bd70194109ad5a30fdee0eaeefef1d4c559dd" ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.18.0" }, "effdet": { @@ -1029,11 +1046,11 @@ }, "httpcore": { "hashes": [ - "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7", - "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535" + "sha256:5c0f9546ad17dac4d0772b0808856eb616eb8b48ce94f49ed819fd6982a8a544", + "sha256:9a6a501c3099307d9fd76ac244e08503427679b1e81ceb1d922485e2f2462ad2" ], "markers": "python_version >= '3.8'", - "version": "==1.0.2" + "version": "==1.0.3" }, "httpx": { "hashes": [ @@ -1359,7 +1376,7 @@ "sha256:b40fbe2b65360afe6c0d5bbf37e79469f990779460640edde5b906175c49807e" ], "index": "pypi", - "markers": "python_full_version >= '3.8.1' and python_version < '4.0'", + "markers": "python_version < '4.0' and python_full_version >= '3.8.1'", "version": "==0.1.7" }, "langchain-community": { @@ -1368,7 +1385,7 @@ "sha256:c56c48bc77d24e1fc399a9ee9a637d96e3b2ff952e3a080b5a41820d9d00fb3c" ], "index": "pypi", - "markers": "python_full_version >= '3.8.1' and python_version < '4.0'", + "markers": "python_version < '4.0' and python_full_version >= '3.8.1'", "version": "==0.0.20" }, "langchain-core": { @@ -1376,7 +1393,7 @@ "sha256:34359cc8b6f8c3d45098c54a6a9b35c9f538ef58329cd943a2249d6d7b4e5806", "sha256:d42fac013c39a8b0bcd7e337a4cb6c17c16046c60d768f89df582ad73ec3c5cb" ], - "markers": "python_full_version >= '3.8.1' and python_version < '4.0'", + "markers": "python_version < '4.0' and python_full_version >= '3.8.1'", "version": "==0.1.23" }, "langchain-openai": { @@ -1385,7 +1402,7 @@ "sha256:f5c4ebe46f2c8635c8f0c26cc8df27700aacafea025410e418d5a080039974dd" ], "index": "pypi", - "markers": "python_full_version >= '3.8.1' and python_version < '4.0'", + "markers": "python_version < '4.0' and python_full_version >= '3.8.1'", "version": "==0.0.6" }, "langdetect": { @@ -1397,19 +1414,19 @@ }, "langfuse": { "hashes": [ - "sha256:97dd415f731507c54880aad3b29c4d82ec157fe4e10ddf07fbf4ce334a04c3a0", - "sha256:ffa59c573f075863d04380b02f45d3391337085cf9b71d280dc3106a4368ef1b" + "sha256:2be049382e867681eabf774d60aadad3e6c277841e2c7f06d71190379650c2d9", + "sha256:7bdcf02a74366ef77d5258c2aaae07d11fabde9a90c883f9022ecaf244bfdeca" ], "index": "pypi", - "markers": "python_full_version >= '3.8.1' and python_version < '4.0'", - "version": "==2.13.2" + "markers": "python_version < '4.0' and python_full_version >= '3.8.1'", + "version": "==2.13.3" }, "langsmith": { "hashes": [ "sha256:36c4cc47e5b54be57d038036a30fb19ce6e4c73048cd7a464b8f25b459694d34", "sha256:8903d3811b9fc89eb18f5961c8e6935fbd2d0f119884fbf30dc70b8f8f4121fc" ], - "markers": "python_full_version >= '3.8.1' and python_version < '4.0'", + "markers": "python_version < '4.0' and python_full_version >= '3.8.1'", "version": "==0.0.87" }, "layoutparser": { @@ -1426,12 +1443,12 @@ }, "litellm": { "hashes": [ - "sha256:40d7e1a15ef8337dd0f97419022fb07cab028f20bc34047a62d6ad955594b055", - "sha256:bdc513da4cf9f1432fc050c651b926e5dbc8561fa3feecfa86425de13a025642" + "sha256:0c9e75d50d3a3b5460e6eb0335c1cdf8dbf87cf298ee2e80ca09a235b540a98e", + "sha256:f47c0ae57ebde27b4f994f484e599050899a6643d6d9246dbe4717962c3fef16" ], "index": "pypi", "markers": "python_version not in '2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7' and python_version >= '3.8'", - "version": "==1.23.14" + "version": "==1.23.15" }, "lxml": { "hashes": [ @@ -1600,37 +1617,37 @@ }, "matplotlib": { "hashes": [ - "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1", - "sha256:03f9d160a29e0b65c0790bb07f4f45d6a181b1ac33eb1bb0dd225986450148f0", - "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4", - "sha256:09796f89fb71a0c0e1e2f4bdaf63fb2cefc84446bb963ecdeb40dfee7dfa98c7", - "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630", - "sha256:172f4d0fbac3383d39164c6caafd3255ce6fa58f08fc392513a0b1d3b89c4f89", - "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d", - "sha256:3773002da767f0a9323ba1a9b9b5d00d6257dbd2a93107233167cfb581f64717", - "sha256:46a569130ff53798ea5f50afce7406e91fdc471ca1e0e26ba976a8c734c9427a", - "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627", - "sha256:4e208f46cf6576a7624195aa047cb344a7f802e113bb1a06cfd4bee431de5e31", - "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213", - "sha256:5864bdd7da445e4e5e011b199bb67168cdad10b501750367c496420f2ad00843", - "sha256:5ba9cbd8ac6cf422f3102622b20f8552d601bf8837e49a3afed188d560152788", - "sha256:6f9c6976748a25e8b9be51ea028df49b8e561eed7809146da7a47dbecebab367", - "sha256:7c48d9e221b637c017232e3760ed30b4e8d5dfd081daf327e829bf2a72c731b4", - "sha256:830f00640c965c5b7f6bc32f0d4ce0c36dfe0379f7dd65b07a00c801713ec40a", - "sha256:9a5430836811b7652991939012f43d2808a2db9b64ee240387e8c43e2e5578c8", - "sha256:aa11b3c6928a1e496c1a79917d51d4cd5d04f8a2e75f21df4949eeefdf697f4b", - "sha256:b78e4f2cedf303869b782071b55fdde5987fda3038e9d09e58c91cc261b5ad18", - "sha256:b9576723858a78751d5aacd2497b8aef29ffea6d1c95981505877f7ac28215c6", - "sha256:bddfb1db89bfaa855912261c805bd0e10218923cc262b9159a49c29a7a1c1afa", - "sha256:c7d36c2209d9136cd8e02fab1c0ddc185ce79bc914c45054a9f514e44c787917", - "sha256:d1095fecf99eeb7384dabad4bf44b965f929a5f6079654b681193edf7169ec20", - "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331", - "sha256:d86593ccf546223eb75a39b44c32788e6f6440d13cfc4750c1c15d0fcb850b63", - "sha256:deaed9ad4da0b1aea77fe0aa0cebb9ef611c70b3177be936a95e5d01fa05094f", - "sha256:ef8345b48e95cee45ff25192ed1f4857273117917a4dcd48e3905619bcd9c9b8" + "sha256:04b36ad07eac9740fc76c2aa16edf94e50b297d6eb4c081e3add863de4bb19a7", + "sha256:09074f8057917d17ab52c242fdf4916f30e99959c1908958b1fc6032e2d0f6d4", + "sha256:1c5c8290074ba31a41db1dc332dc2b62def469ff33766cbe325d32a3ee291aea", + "sha256:242489efdb75b690c9c2e70bb5c6550727058c8a614e4c7716f363c27e10bba1", + "sha256:40321634e3a05ed02abf7c7b47a50be50b53ef3eaa3a573847431a545585b407", + "sha256:4c6e00a65d017d26009bac6808f637b75ceade3e1ff91a138576f6b3065eeeba", + "sha256:5184e07c7e1d6d1481862ee361905b7059f7fe065fc837f7c3dc11eeb3f2f900", + "sha256:5745f6d0fb5acfabbb2790318db03809a253096e98c91b9a31969df28ee604aa", + "sha256:5e431a09e6fab4012b01fc155db0ce6dccacdbabe8198197f523a4ef4805eb26", + "sha256:5f557156f7116be3340cdeef7f128fa99b0d5d287d5f41a16e169819dcf22357", + "sha256:6728dde0a3997396b053602dbd907a9bd64ec7d5cf99e728b404083698d3ca01", + "sha256:7b416239e9ae38be54b028abbf9048aff5054a9aba5416bef0bd17f9162ce161", + "sha256:7c42dae72a62f14982f1474f7e5c9959fc4bc70c9de11cc5244c6e766200ba65", + "sha256:813925d08fb86aba139f2d31864928d67511f64e5945ca909ad5bc09a96189bb", + "sha256:83c0653c64b73926730bd9ea14aa0f50f202ba187c307a881673bad4985967b7", + "sha256:83e0f72e2c116ca7e571c57aa29b0fe697d4c6425c4e87c6e994159e0c008635", + "sha256:b3c5f96f57b0369c288bf6f9b5274ba45787f7e0589a34d24bdbaf6d3344632f", + "sha256:b97653d869a71721b639714b42d87cda4cfee0ee74b47c569e4874c7590c55c5", + "sha256:bf5932eee0d428192c40b7eac1399d608f5d995f975cdb9d1e6b48539a5ad8d0", + "sha256:c4af3f7317f8a1009bbb2d0bf23dfaba859eb7dd4ccbd604eba146dccaaaf0a4", + "sha256:cd3a0c2be76f4e7be03d34a14d49ded6acf22ef61f88da600a18a5cd8b3c5f3c", + "sha256:cf60138ccc8004f117ab2a2bad513cc4d122e55864b4fe7adf4db20ca68a078f", + "sha256:d7e7e0993d0758933b1a241a432b42c2db22dfa37d4108342ab4afb9557cbe3e", + "sha256:e7b49ab49a3bea17802df6872f8d44f664ba8f9be0632a60c99b20b6db2165b7", + "sha256:e9764df0e8778f06414b9d281a75235c1e85071f64bb5d71564b97c1306a2afc", + "sha256:ef6c1025a570354297d6c15f7d0f296d95f88bd3850066b7f1e7b4f2f4c13a39", + "sha256:f386cf162b059809ecfac3bcc491a9ea17da69fa35c8ded8ad154cd4b933d5ec", + "sha256:fa93695d5c08544f4a0dfd0965f378e7afc410d8672816aff1e81be1f45dbf2e" ], "markers": "python_version >= '3.9'", - "version": "==3.8.2" + "version": "==3.8.3" }, "mccabe": { "hashes": [ @@ -1999,8 +2016,18 @@ "sha256:f9670b3ac00a387620489dfc1bca66db47a787f4e55911f1293063a78b108df1", "sha256:fbc1b53c0e1fdf16388c33c3cca160f798d38aea2978004dd3f4d3dec56454c9" ], + "markers": "python_version >= '3.9'", "version": "==2.2.0" }, + "pandasai": { + "hashes": [ + "sha256:7cf42308907e38249bc565fa8ccfb9b1a84e4b151c72c3352864c9dc291f2f96", + "sha256:c5fb258870e1936701a3af31114379b9bc1ecc9cf99816ad5c8b523f2c7ddbe9" + ], + "index": "pypi", + "markers": "python_version >= '3.9' and python_version < '4.0'", + "version": "==0.1.0" + }, "pathspec": { "hashes": [ "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", @@ -2241,11 +2268,11 @@ }, "prometheus-client": { "hashes": [ - "sha256:4585b0d1223148c27a225b10dbec5ae9bc4c81a99a3fa80774fa6209935324e1", - "sha256:c88b1e6ecf6b41cd8fb5731c7ae919bf66df6ec6fafa555cd6c0e16ca169ae92" + "sha256:287629d00b147a32dcb2be0b9df905da599b2d82f80377083ec8463309a4bb89", + "sha256:cde524a85bce83ca359cc837f28b8c0db5cac7aa653a588fd7e84ba061c329e7" ], "markers": "python_version >= '3.8'", - "version": "==0.19.0" + "version": "==0.20.0" }, "prompt-toolkit": { "hashes": [ @@ -2272,6 +2299,105 @@ "markers": "python_version >= '3.8'", "version": "==4.25.2" }, + "psycopg2": { + "hashes": [ + "sha256:121081ea2e76729acfb0673ff33755e8703d45e926e416cb59bae3a86c6a4981", + "sha256:38a8dcc6856f569068b47de286b472b7c473ac7977243593a288ebce0dc89516", + "sha256:426f9f29bde126913a20a96ff8ce7d73fd8a216cfb323b1f04da402d452853c3", + "sha256:5e0d98cade4f0e0304d7d6f25bbfbc5bd186e07b38eac65379309c4ca3193efa", + "sha256:7e2dacf8b009a1c1e843b5213a87f7c544b2b042476ed7755be813eaf4e8347a", + "sha256:a7653d00b732afb6fc597e29c50ad28087dcb4fbfb28e86092277a559ae4e693", + "sha256:ade01303ccf7ae12c356a5e10911c9e1c51136003a9a1d92f7aa9d010fb98372", + "sha256:bac58c024c9922c23550af2a581998624d6e02350f4ae9c5f0bc642c633a2d5e", + "sha256:c92811b2d4c9b6ea0285942b2e7cac98a59e166d59c588fe5cfe1eda58e72d59", + "sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156", + "sha256:d735786acc7dd25815e89cc4ad529a43af779db2e25aa7c626de864127e5a024", + "sha256:de80739447af31525feddeb8effd640782cf5998e1a4e9192ebdf829717e3913", + "sha256:ff432630e510709564c01dafdbe996cb552e0b9f3f065eb89bdce5bd31fabf4c" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==2.9.9" + }, + "psycopg2-binary": { + "hashes": [ + "sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9", + "sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77", + "sha256:0c009475ee389757e6e34611d75f6e4f05f0cf5ebb76c6037508318e1a1e0d7e", + "sha256:0ef4854e82c09e84cc63084a9e4ccd6d9b154f1dbdd283efb92ecd0b5e2b8c84", + "sha256:1236ed0952fbd919c100bc839eaa4a39ebc397ed1c08a97fc45fee2a595aa1b3", + "sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2", + "sha256:15208be1c50b99203fe88d15695f22a5bed95ab3f84354c494bcb1d08557df67", + "sha256:1873aade94b74715be2246321c8650cabf5a0d098a95bab81145ffffa4c13876", + "sha256:18d0ef97766055fec15b5de2c06dd8e7654705ce3e5e5eed3b6651a1d2a9a152", + "sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f", + "sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a", + "sha256:246b123cc54bb5361588acc54218c8c9fb73068bf227a4a531d8ed56fa3ca7d6", + "sha256:275ff571376626195ab95a746e6a04c7df8ea34638b99fc11160de91f2fef503", + "sha256:281309265596e388ef483250db3640e5f414168c5a67e9c665cafce9492eda2f", + "sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493", + "sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996", + "sha256:30dcc86377618a4c8f3b72418df92e77be4254d8f89f14b8e8f57d6d43603c0f", + "sha256:31a34c508c003a4347d389a9e6fcc2307cc2150eb516462a7a17512130de109e", + "sha256:323ba25b92454adb36fa425dc5cf6f8f19f78948cbad2e7bc6cdf7b0d7982e59", + "sha256:34eccd14566f8fe14b2b95bb13b11572f7c7d5c36da61caf414d23b91fcc5d94", + "sha256:3a58c98a7e9c021f357348867f537017057c2ed7f77337fd914d0bedb35dace7", + "sha256:3f78fd71c4f43a13d342be74ebbc0666fe1f555b8837eb113cb7416856c79682", + "sha256:4154ad09dac630a0f13f37b583eae260c6aa885d67dfbccb5b02c33f31a6d420", + "sha256:420f9bbf47a02616e8554e825208cb947969451978dceb77f95ad09c37791dae", + "sha256:4686818798f9194d03c9129a4d9a702d9e113a89cb03bffe08c6cf799e053291", + "sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe", + "sha256:60989127da422b74a04345096c10d416c2b41bd7bf2a380eb541059e4e999980", + "sha256:64cf30263844fa208851ebb13b0732ce674d8ec6a0c86a4e160495d299ba3c93", + "sha256:68fc1f1ba168724771e38bee37d940d2865cb0f562380a1fb1ffb428b75cb692", + "sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119", + "sha256:729177eaf0aefca0994ce4cffe96ad3c75e377c7b6f4efa59ebf003b6d398716", + "sha256:72dffbd8b4194858d0941062a9766f8297e8868e1dd07a7b36212aaa90f49472", + "sha256:75723c3c0fbbf34350b46a3199eb50638ab22a0228f93fb472ef4d9becc2382b", + "sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2", + "sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc", + "sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c", + "sha256:804d99b24ad523a1fe18cc707bf741670332f7c7412e9d49cb5eab67e886b9b5", + "sha256:81ff62668af011f9a48787564ab7eded4e9fb17a4a6a74af5ffa6a457400d2ab", + "sha256:8359bf4791968c5a78c56103702000105501adb557f3cf772b2c207284273984", + "sha256:83791a65b51ad6ee6cf0845634859d69a038ea9b03d7b26e703f94c7e93dbcf9", + "sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf", + "sha256:876801744b0dee379e4e3c38b76fc89f88834bb15bf92ee07d94acd06ec890a0", + "sha256:8dbf6d1bc73f1d04ec1734bae3b4fb0ee3cb2a493d35ede9badbeb901fb40f6f", + "sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212", + "sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb", + "sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be", + "sha256:9dba73be7305b399924709b91682299794887cbbd88e38226ed9f6712eabee90", + "sha256:a148c5d507bb9b4f2030a2025c545fccb0e1ef317393eaba42e7eabd28eb6041", + "sha256:a6cdcc3ede532f4a4b96000b6362099591ab4a3e913d70bcbac2b56c872446f7", + "sha256:ac05fb791acf5e1a3e39402641827780fe44d27e72567a000412c648a85ba860", + "sha256:b0605eaed3eb239e87df0d5e3c6489daae3f7388d455d0c0b4df899519c6a38d", + "sha256:b58b4710c7f4161b5e9dcbe73bb7c62d65670a87df7bcce9e1faaad43e715245", + "sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27", + "sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417", + "sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359", + "sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202", + "sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0", + "sha256:c6af2a6d4b7ee9615cbb162b0738f6e1fd1f5c3eda7e5da17861eacf4c717ea7", + "sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba", + "sha256:ca08decd2697fdea0aea364b370b1249d47336aec935f87b8bbfd7da5b2ee9c1", + "sha256:ca49a8119c6cbd77375ae303b0cfd8c11f011abbbd64601167ecca18a87e7cdd", + "sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07", + "sha256:d2997c458c690ec2bc6b0b7ecbafd02b029b7b4283078d3b32a852a7ce3ddd98", + "sha256:d3f82c171b4ccd83bbaf35aa05e44e690113bd4f3b7b6cc54d2219b132f3ae55", + "sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d", + "sha256:ead20f7913a9c1e894aebe47cccf9dc834e1618b7aa96155d2091a626e59c972", + "sha256:ebdc36bea43063116f0486869652cb2ed7032dbc59fbcb4445c4862b5c1ecf7f", + "sha256:ed1184ab8f113e8d660ce49a56390ca181f2981066acc27cf637d5c1e10ce46e", + "sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26", + "sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957", + "sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53", + "sha256:f9b5571d33660d5009a8b3c25dc1db560206e2d2f89d3df1cb32d72c0d117d52" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==2.9.9" + }, "pyasn1": { "hashes": [ "sha256:4439847c58d40b1d0a573d07e3856e95333f1976294494c325775aeca506eb58", @@ -2531,7 +2657,7 @@ "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.2" }, "python-docx": { @@ -3082,7 +3208,7 @@ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, "smmap": { @@ -3533,6 +3659,7 @@ "sha256:019cf52e9e2bfa286e61ffa0d7d336e1645280f9a0f165e697583143fcfe708a", "sha256:f1aa046297a3afba3aa16895e513aca6a93802ef73b7a18080656435c4deb217" ], + "index": "pypi", "markers": "python_version < '3.12' and python_full_version >= '3.9.0'", "version": "==0.12.4" }, @@ -3563,7 +3690,7 @@ "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84", "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e" ], - "markers": "python_version >= '3.10'", + "markers": "python_version >= '3.7'", "version": "==2.0.7" }, "uvicorn": { diff --git a/backend/logger.py b/backend/logger.py index ea144d7cd..0c7cef91f 100644 --- a/backend/logger.py +++ b/backend/logger.py @@ -1,6 +1,10 @@ import logging from logging.handlers import RotatingFileHandler +from colorlog import ( + ColoredFormatter, +) # You need to install this package: pip install colorlog + def get_logger(logger_name, log_level=logging.INFO, log_file="application.log"): logger = logging.getLogger(logger_name) @@ -8,11 +12,24 @@ def get_logger(logger_name, log_level=logging.INFO, log_file="application.log"): logger.propagate = False # Prevent log propagation to avoid double logging formatter = logging.Formatter( - "%(asctime)s [%(levelname)s] %(name)s [%(lineno)d]: %(message)s" + "[%(levelname)s] %(name)s [%(filename)s:%(lineno)d]: %(message)s" + ) + + color_formatter = ColoredFormatter( + "%(log_color)s[%(levelname)s]%(reset)s %(name)s [%(filename)s:%(lineno)d]: %(message)s", + log_colors={ + "DEBUG": "cyan", + "INFO": "green", + "WARNING": "yellow", + "ERROR": "red", + "CRITICAL": "red,bg_white", + }, + reset=True, + style="%", ) console_handler = logging.StreamHandler() - console_handler.setFormatter(formatter) + console_handler.setFormatter(color_formatter) file_handler = RotatingFileHandler( log_file, maxBytes=5000000, backupCount=5 diff --git a/backend/manage_services.sh b/backend/manage_services.sh new file mode 100755 index 000000000..333cfde3d --- /dev/null +++ b/backend/manage_services.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +SESSION_NAME="my_services" + +start_services() { + # Create a new tmux session + tmux new-session -d -s $SESSION_NAME + + # Split the window into panes for each service + tmux split-window -h + tmux split-window -v + tmux select-pane -t 0 + tmux split-window -v + + # Start each service in its pane + tmux send-keys -t $SESSION_NAME:0.0 'echo "Starting backend-core...";pipenv run uvicorn main:app --reload --host 0.0.0.0 --port 5050 --workers 6' C-m + tmux send-keys -t $SESSION_NAME:0.1 'echo "Starting worker...";pipenv run celery -A celery_worker worker -l info' C-m + tmux send-keys -t $SESSION_NAME:0.2 'echo "Starting beat...";pipenv run celery -A celery_worker beat -l info' C-m + tmux send-keys -t $SESSION_NAME:0.3 'echo "Starting flower...";pipenv run celery -A celery_worker flower -l info --port=5555' C-m + + echo "Services started in tmux session '$SESSION_NAME'" + echo "Use 'tmux attach-session -t $SESSION_NAME' to view logs" +} + +stop_services() { + # Kill the tmux session + tmux kill-session -t $SESSION_NAME + echo "Services stopped" +} + +view_logs() { + # Attach to the tmux session to view logs + tmux attach-session -t $SESSION_NAME +} + +if [ "$1" == "start" ]; then + start_services +elif [ "$1" == "stop" ]; then + stop_services +elif [ "$1" == "logs" ]; then + view_logs +else + echo "Usage: $0 {start|stop|logs}" +fi diff --git a/backend/modules/brain/entity/integration_brain.py b/backend/modules/brain/entity/integration_brain.py index 89756d008..b180150b0 100644 --- a/backend/modules/brain/entity/integration_brain.py +++ b/backend/modules/brain/entity/integration_brain.py @@ -12,7 +12,7 @@ class IntegrationDescriptionEntity(BaseModel): class IntegrationEntity(BaseModel): - id: str + id: int user_id: str brain_id: str integration_id: str diff --git a/backend/modules/brain/integrations/GPT4/Brain.py b/backend/modules/brain/integrations/GPT4/Brain.py new file mode 100644 index 000000000..03db2cd1d --- /dev/null +++ b/backend/modules/brain/integrations/GPT4/Brain.py @@ -0,0 +1,62 @@ +import json +from typing import AsyncIterable +from uuid import UUID + +from langchain_community.chat_models import ChatLiteLLM +from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder +from modules.brain.knowledge_brain_qa import KnowledgeBrainQA +from modules.chat.dto.chats import ChatQuestion + + +class GPT4Brain(KnowledgeBrainQA): + """This is the Notion brain class. it is a KnowledgeBrainQA has the data is stored locally. + It is going to call the Data Store internally to get the data. + + Args: + KnowledgeBrainQA (_type_): A brain that store the knowledge internaly + """ + + def __init__( + self, + **kwargs, + ): + super().__init__( + **kwargs, + ) + + def get_chain(self): + + prompt = ChatPromptTemplate.from_messages( + [ + ("system", "You are GPT-4 powered by Quivr. You are an assistant."), + MessagesPlaceholder(variable_name="chat_history"), + ("human", "{question}"), + ] + ) + + chain = prompt | ChatLiteLLM( + model="gpt-4-0125-preview", max_tokens=self.max_tokens + ) + + return chain + + async def generate_stream( + self, chat_id: UUID, question: ChatQuestion, save_answer: bool = True + ) -> AsyncIterable: + conversational_qa_chain = self.get_chain() + transformed_history, streamed_chat_history = ( + self.initialize_streamed_chat_history(chat_id, question) + ) + response_tokens = [] + + async for chunk in conversational_qa_chain.astream( + { + "question": question.question, + "chat_history": transformed_history, + } + ): + response_tokens.append(chunk.content) + streamed_chat_history.assistant = chunk.content + yield f"data: {json.dumps(streamed_chat_history.dict())}" + + self.save_answer(question, response_tokens, streamed_chat_history, save_answer) diff --git a/backend/modules/brain/integrations/GPT4/__init__.py b/backend/modules/brain/integrations/GPT4/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/backend/modules/brain/integrations/SQL/Brain.py b/backend/modules/brain/integrations/SQL/Brain.py new file mode 100644 index 000000000..4354d2d6d --- /dev/null +++ b/backend/modules/brain/integrations/SQL/Brain.py @@ -0,0 +1,100 @@ +import json +from typing import AsyncIterable +from uuid import UUID + +from langchain_community.chat_models import ChatLiteLLM +from langchain_community.utilities import SQLDatabase +from langchain_core.output_parsers import StrOutputParser +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.runnables import RunnablePassthrough +from modules.brain.integrations.SQL.SQL_connector import SQLConnector +from modules.brain.knowledge_brain_qa import KnowledgeBrainQA +from modules.brain.repository.integration_brains import IntegrationBrain +from modules.chat.dto.chats import ChatQuestion + + +class SQLBrain(KnowledgeBrainQA, IntegrationBrain): + """This is the Notion brain class. it is a KnowledgeBrainQA has the data is stored locally. + It is going to call the Data Store internally to get the data. + + Args: + KnowledgeBrainQA (_type_): A brain that store the knowledge internaly + """ + + uri: str = None + db: SQLDatabase = None + sql_connector: SQLConnector = None + + def __init__( + self, + **kwargs, + ): + super().__init__( + **kwargs, + ) + self.sql_connector = SQLConnector(self.brain_id, self.user_id) + + def get_schema(self, _): + return self.db.get_table_info() + + def run_query(self, query): + return self.db.run(query) + + def get_chain(self): + template = """Based on the table schema below, write a SQL query that would answer the user's question: + {schema} + + Question: {question} + SQL Query:""" + prompt = ChatPromptTemplate.from_template(template) + + self.db = SQLDatabase.from_uri(self.sql_connector.credentials["uri"]) + + model = ChatLiteLLM(model=self.model) + + sql_response = ( + RunnablePassthrough.assign(schema=self.get_schema) + | prompt + | model.bind(stop=["\nSQLResult:"]) + | StrOutputParser() + ) + + template = """Based on the table schema below, question, sql query, and sql response, write a natural language response and the query that was used to generate it.: + {schema} + + Question: {question} + SQL Query: {query} + SQL Response: {response}""" + prompt_response = ChatPromptTemplate.from_template(template) + + full_chain = ( + RunnablePassthrough.assign(query=sql_response).assign( + schema=self.get_schema, + response=lambda x: self.db.run(x["query"]), + ) + | prompt_response + | model + ) + + return full_chain + + async def generate_stream( + self, chat_id: UUID, question: ChatQuestion, save_answer: bool = True + ) -> AsyncIterable: + + conversational_qa_chain = self.get_chain() + transformed_history, streamed_chat_history = ( + self.initialize_streamed_chat_history(chat_id, question) + ) + response_tokens = [] + + async for chunk in conversational_qa_chain.astream( + { + "question": question.question, + } + ): + response_tokens.append(chunk.content) + streamed_chat_history.assistant = chunk.content + yield f"data: {json.dumps(streamed_chat_history.dict())}" + + self.save_answer(question, response_tokens, streamed_chat_history, save_answer) diff --git a/backend/modules/brain/integrations/SQL/SQL_connector.py b/backend/modules/brain/integrations/SQL/SQL_connector.py new file mode 100644 index 000000000..4cbc858b0 --- /dev/null +++ b/backend/modules/brain/integrations/SQL/SQL_connector.py @@ -0,0 +1,41 @@ +from logger import get_logger +from modules.brain.entity.integration_brain import IntegrationEntity +from modules.brain.repository.integration_brains import IntegrationBrain +from modules.knowledge.repository.knowledge_interface import KnowledgeInterface +from modules.knowledge.service.knowledge_service import KnowledgeService + +logger = get_logger(__name__) + + +class SQLConnector(IntegrationBrain): + """A class to interact with an SQL database""" + + credentials: dict[str, str] = None + integration_details: IntegrationEntity = None + brain_id: str = None + user_id: str = None + knowledge_service: KnowledgeInterface + + def __init__(self, brain_id: str, user_id: str): + super().__init__() + self.brain_id = brain_id + self.user_id = user_id + self._load_credentials() + self.knowledge_service = KnowledgeService() + + def _load_credentials(self) -> dict[str, str]: + """Load the Notion credentials""" + self.integration_details = self.get_integration_brain( + self.brain_id, self.user_id + ) + if self.credentials is None: + logger.info("Loading Notion credentials") + self.integration_details.credentials = { + "uri": self.integration_details.settings.get("uri", "") + } + self.update_integration_brain( + self.brain_id, self.user_id, self.integration_details + ) + self.credentials = self.integration_details.credentials + else: # pragma: no cover + self.credentials = self.integration_details.credentials diff --git a/backend/modules/brain/integrations/SQL/__init__.py b/backend/modules/brain/integrations/SQL/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/backend/modules/brain/knowledge_brain_qa.py b/backend/modules/brain/knowledge_brain_qa.py index 450aaf751..7eeaa4bbd 100644 --- a/backend/modules/brain/knowledge_brain_qa.py +++ b/backend/modules/brain/knowledge_brain_qa.py @@ -38,7 +38,7 @@ def is_valid_uuid(uuid_to_test, version=4): return str(uuid_obj) == uuid_to_test -def generate_source(result, brain): +def generate_source(source_documents, brain_id): # Initialize an empty list for sources sources_list: List[Sources] = [] @@ -46,27 +46,28 @@ def generate_source(result, brain): generated_urls = {} # Get source documents from the result, default to an empty list if not found - source_documents = result.get("source_documents", []) # If source documents exist if source_documents: logger.info(f"Source documents found: {source_documents}") # Iterate over each document for doc in source_documents: + doc0 = doc[0] + logger.info("Document: %s", doc0) # Check if 'url' is in the document metadata - logger.info(f"Metadata 1: {doc.metadata}") + logger.info(f"Metadata 1: {doc0.metadata}") is_url = ( - "original_file_name" in doc.metadata - and doc.metadata["original_file_name"] is not None - and doc.metadata["original_file_name"].startswith("http") + "original_file_name" in doc0.metadata + and doc0.metadata["original_file_name"] is not None + and doc0.metadata["original_file_name"].startswith("http") ) logger.info(f"Is URL: {is_url}") # Determine the name based on whether it's a URL or a file name = ( - doc.metadata["original_file_name"] + doc0.metadata["original_file_name"] if is_url - else doc.metadata["file_name"] + else doc0.metadata["file_name"] ) # Determine the type based on whether it's a URL or a file @@ -74,9 +75,9 @@ def generate_source(result, brain): # Determine the source URL based on whether it's a URL or a file if is_url: - source_url = doc.metadata["original_file_name"] + source_url = doc0.metadata["original_file_name"] else: - file_path = f"{brain.brain_id}/{doc.metadata['file_name']}" + file_path = f"{brain_id}/{doc0.metadata['file_name']}" # Check if the URL has already been generated if file_path in generated_urls: source_url = generated_urls[file_path] @@ -126,6 +127,7 @@ class KnowledgeBrainQA(BaseModel, QAInterface): streaming: bool = False knowledge_qa: Optional[RAGInterface] = None metadata: Optional[dict] = None + user_id: str = None callbacks: List[AsyncIteratorCallbackHandler] = ( None # pyright: ignore reportPrivateUsage=none @@ -142,6 +144,7 @@ class KnowledgeBrainQA(BaseModel, QAInterface): streaming: bool = False, prompt_id: Optional[UUID] = None, metadata: Optional[dict] = None, + user_id: str = None, **kwargs, ): super().__init__( @@ -161,6 +164,7 @@ class KnowledgeBrainQA(BaseModel, QAInterface): ) self.metadata = metadata self.max_tokens = max_tokens + self.user_id = user_id @property def prompt_to_use(self): @@ -259,14 +263,42 @@ class KnowledgeBrainQA(BaseModel, QAInterface): async def generate_stream( self, chat_id: UUID, question: ChatQuestion, save_answer: bool = True ) -> AsyncIterable: - history = chat_service.get_chat_history(self.chat_id) - conversational_qa_chain = self.knowledge_qa.get_chain() - - transformed_history = format_chat_history(history) - + transformed_history, streamed_chat_history = ( + self.initialize_streamed_chat_history(chat_id, question) + ) response_tokens = [] + sources = [] + async for chunk in conversational_qa_chain.astream( + { + "question": question.question, + "chat_history": transformed_history, + "custom_personality": ( + self.prompt_to_use.content if self.prompt_to_use else None + ), + } + ): + if chunk.get("answer"): + logger.info(f"Chunk: {chunk}") + response_tokens.append(chunk["answer"].content) + streamed_chat_history.assistant = chunk["answer"].content + yield f"data: {json.dumps(streamed_chat_history.dict())}" + if chunk.get("docs"): + sources = chunk["docs"] + + sources_list = generate_source(sources, self.brain_id) + if not streamed_chat_history.metadata: + streamed_chat_history.metadata = {} + # Serialize the sources list + serialized_sources_list = [source.dict() for source in sources_list] + streamed_chat_history.metadata["sources"] = serialized_sources_list + yield f"data: {json.dumps(streamed_chat_history.dict())}" + self.save_answer(question, response_tokens, streamed_chat_history, save_answer) + + def initialize_streamed_chat_history(self, chat_id, question): + history = chat_service.get_chat_history(self.chat_id) + transformed_history = format_chat_history(history) brain = brain_service.get_brain_by_id(self.brain_id) streamed_chat_history = chat_service.update_chat_history( @@ -297,24 +329,11 @@ class KnowledgeBrainQA(BaseModel, QAInterface): } ) - try: - - async for chunk in conversational_qa_chain.astream( - { - "question": question.question, - "chat_history": transformed_history, - "custom_personality": ( - self.prompt_to_use.content if self.prompt_to_use else None - ), - } - ): - response_tokens.append(chunk.content) - streamed_chat_history.assistant = chunk.content - yield f"data: {json.dumps(streamed_chat_history.dict())}" - - except Exception as e: - logger.error("Error generating stream: %s", e) + return transformed_history, streamed_chat_history + def save_answer( + self, question, response_tokens, streamed_chat_history, save_answer + ): assistant = "".join(response_tokens) try: diff --git a/backend/modules/brain/rags/quivr_rag.py b/backend/modules/brain/rags/quivr_rag.py index ca6b6da07..a62e03efe 100644 --- a/backend/modules/brain/rags/quivr_rag.py +++ b/backend/modules/brain/rags/quivr_rag.py @@ -5,14 +5,15 @@ from uuid import UUID from langchain.chains import ConversationalRetrievalChain from langchain.embeddings.ollama import OllamaEmbeddings from langchain.llms.base import BaseLLM +from langchain.memory import ConversationBufferMemory from langchain.prompts import HumanMessagePromptTemplate from langchain.schema import format_document from langchain_community.chat_models import ChatLiteLLM from langchain_core.messages import SystemMessage, get_buffer_string from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate, PromptTemplate -from langchain_core.runnables import RunnableParallel, RunnablePassthrough -from langchain_openai import ChatOpenAI, OpenAIEmbeddings +from langchain_core.runnables import RunnableLambda, RunnablePassthrough +from langchain_openai import OpenAIEmbeddings from llm.utils.get_prompt_to_use import get_prompt_to_use from logger import get_logger from models import BrainSettings # Importing settings related to the 'brain' @@ -57,8 +58,6 @@ ANSWER_PROMPT = ChatPromptTemplate.from_messages( ) -ChatPromptTemplate.from_template(template_answer) - # How we format documents DEFAULT_DOCUMENT_PROMPT = PromptTemplate.from_template( @@ -205,29 +204,49 @@ class QuivrRAG(BaseModel): def get_chain(self): retriever_doc = self.get_retriever() - - _inputs = RunnableParallel( - standalone_question=RunnablePassthrough.assign( - chat_history=lambda x: get_buffer_string(x["chat_history"]) - ) - | CONDENSE_QUESTION_PROMPT - | ChatOpenAI(temperature=0) - | StrOutputParser(), + memory = ConversationBufferMemory( + return_messages=True, output_key="answer", input_key="question" ) + loaded_memory = RunnablePassthrough.assign( + chat_history=RunnableLambda(memory.load_memory_variables) + | itemgetter("history"), + ) + + standalone_question = { + "standalone_question": { + "question": lambda x: x["question"], + "chat_history": lambda x: get_buffer_string(x["chat_history"]), + } + | CONDENSE_QUESTION_PROMPT + | ChatLiteLLM(temperature=0, model=self.model) + | StrOutputParser(), + } + prompt_custom_user = self.prompt_to_use() prompt_to_use = "None" if prompt_custom_user: prompt_to_use = prompt_custom_user.content - logger.info(f"Prompt to use: {prompt_custom_user}") - _context = { - "context": itemgetter("standalone_question") - | retriever_doc - | self._combine_documents, + + # Now we retrieve the documents + retrieved_documents = { + "docs": itemgetter("standalone_question") | retriever_doc, "question": lambda x: x["standalone_question"], "custom_instructions": lambda x: prompt_to_use, } - conversational_qa_chain = _inputs | _context | ANSWER_PROMPT | ChatOpenAI() + final_inputs = { + "context": lambda x: self._combine_documents(x["docs"]), + "question": itemgetter("question"), + "custom_instructions": itemgetter("custom_instructions"), + } - return conversational_qa_chain + # And finally, we do the part that returns the answers + answer = { + "answer": final_inputs + | ANSWER_PROMPT + | ChatLiteLLM(max_tokens=self.max_tokens, model=self.model), + "docs": itemgetter("docs"), + } + + return loaded_memory | standalone_question | retrieved_documents | answer diff --git a/backend/modules/brain/service/brain_service.py b/backend/modules/brain/service/brain_service.py index 0f2475021..876f53631 100644 --- a/backend/modules/brain/service/brain_service.py +++ b/backend/modules/brain/service/brain_service.py @@ -202,8 +202,8 @@ class BrainService: if ( self.integration_description_repository.get_integration_description( brain.integration.integration_id - ).integration_name - == "Notion" + ).integration_name.lower() + == "notion" ): celery.send_task( "NotionConnectorLoad", diff --git a/backend/modules/chat/controller/chat/brainful_chat.py b/backend/modules/chat/controller/chat/brainful_chat.py index e166f84ad..9b75434ca 100644 --- a/backend/modules/chat/controller/chat/brainful_chat.py +++ b/backend/modules/chat/controller/chat/brainful_chat.py @@ -1,7 +1,9 @@ from logger import get_logger from modules.brain.api_brain_qa import APIBrainQA from modules.brain.entity.brain_entity import BrainType, RoleEnum +from modules.brain.integrations.GPT4.Brain import GPT4Brain from modules.brain.integrations.Notion.Brain import NotionBrain +from modules.brain.integrations.SQL.Brain import SQLBrain from modules.brain.knowledge_brain_qa import KnowledgeBrainQA from modules.brain.service.api_brain_definition_service import ApiBrainDefinitionService from modules.brain.service.brain_authorization_service import ( @@ -31,6 +33,13 @@ models_supporting_function_calls = [ "gpt-3.5-turbo", ] + +integration_list = { + "notion": NotionBrain, + "gpt4": GPT4Brain, + "sql": SQLBrain, +} + brain_service = BrainService() @@ -67,6 +76,7 @@ class BrainfulChat(ChatInterface): streaming=streaming, prompt_id=prompt_id, metadata=metadata, + user_id=user_id, ) if brain.brain_type == BrainType.API: @@ -94,8 +104,11 @@ class BrainfulChat(ChatInterface): brain.brain_id, user_id ) - if integration_brain.integration_name == "Notion": - return NotionBrain( + integration_class = integration_list.get( + integration_brain.integration_name.lower() + ) + if integration_class: + return integration_class( chat_id=chat_id, model=model, max_tokens=max_tokens, @@ -105,4 +118,5 @@ class BrainfulChat(ChatInterface): streaming=streaming, prompt_id=prompt_id, metadata=metadata, + user_id=user_id, ) diff --git a/backend/requirements.txt b/backend/requirements.txt index 87d854986..9fe417f66 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -5,6 +5,7 @@ amqp==5.2.0; python_version >= '3.6' annotated-types==0.6.0; python_version >= '3.8' antlr4-python3-runtime==4.9.3 anyio==4.2.0; python_version >= '3.8' +astor==0.8.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' async-generator==1.10; python_version >= '3.5' asyncpg==0.27.0; python_full_version >= '3.7.0' attrs==23.2.0; python_version >= '3.7' @@ -12,8 +13,8 @@ backoff==2.2.1; python_version >= '3.7' and python_version < '4.0' beautifulsoup4==4.12.3; python_full_version >= '3.6.0' billiard==4.2.0; python_version >= '3.7' black==24.2.0; python_version >= '3.8' -boto3==1.34.41; python_version >= '3.8' -botocore==1.34.41; python_version >= '3.8' +boto3==1.34.42; python_version >= '3.8' +botocore==1.34.42; python_version >= '3.8' bytecode==0.15.1; python_version >= '3.8' cattrs==23.2.3; python_version >= '3.8' celery[sqs]==5.3.6; python_version >= '3.8' @@ -27,6 +28,7 @@ click-didyoumean==0.3.0; python_full_version >= '3.6.2' and python_full_version click-plugins==1.1.1 click-repl==0.3.0; python_version >= '3.6' coloredlogs==15.0.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' +colorlog==6.8.2; python_version >= '3.6' contourpy==1.2.0; python_version >= '3.9' cryptography==42.0.2; python_version >= '3.7' cssselect==1.2.0; python_version >= '3.7' @@ -34,12 +36,12 @@ cycler==0.12.1; python_version >= '3.8' dataclasses-json==0.6.4; python_version >= '3.7' and python_version < '4.0' dataclasses-json-speakeasy==0.5.11; python_version >= '3.7' and python_version < '4.0' ddsketch==2.0.4; python_version >= '2.7' -ddtrace==2.6.1; python_version >= '3.7' +ddtrace==2.6.2; python_version >= '3.7' deprecated==1.2.14; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' deprecation==2.1.0 distro==1.9.0; python_version >= '3.6' docx2txt==0.8 -ecdsa==0.18.0; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2' +ecdsa==0.18.0; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3' effdet==0.4.1 emoji==2.10.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' envier==0.5.1; python_version >= '3.7' @@ -61,7 +63,7 @@ gitpython==3.1.36; python_version >= '3.7' gotrue==2.1.0; python_version >= '3.8' and python_version < '4.0' h11==0.14.0; python_version >= '3.7' html5lib==1.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -httpcore==1.0.2; python_version >= '3.8' +httpcore==1.0.3; python_version >= '3.8' httpx==0.25.2; python_version >= '3.8' huggingface-hub==0.20.3; python_full_version >= '3.8.0' humanfriendly==10.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' @@ -80,20 +82,20 @@ jsonpath-python==1.0.6; python_version >= '3.6' jsonpointer==2.4; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6' kiwisolver==1.4.5; python_version >= '3.7' kombu[sqs]==5.3.5; python_version >= '3.8' -langchain==0.1.7; python_full_version >= '3.8.1' and python_version < '4.0' -langchain-community==0.0.20; python_full_version >= '3.8.1' and python_version < '4.0' -langchain-core==0.1.23; python_full_version >= '3.8.1' and python_version < '4.0' -langchain-openai==0.0.6; python_full_version >= '3.8.1' and python_version < '4.0' +langchain==0.1.7; python_version < '4.0' and python_full_version >= '3.8.1' +langchain-community==0.0.20; python_version < '4.0' and python_full_version >= '3.8.1' +langchain-core==0.1.23; python_version < '4.0' and python_full_version >= '3.8.1' +langchain-openai==0.0.6; python_version < '4.0' and python_full_version >= '3.8.1' langdetect==1.0.9 -langfuse==2.13.2; python_full_version >= '3.8.1' and python_version < '4.0' -langsmith==0.0.87; python_full_version >= '3.8.1' and python_version < '4.0' +langfuse==2.13.3; python_version < '4.0' and python_full_version >= '3.8.1' +langsmith==0.0.87; python_version < '4.0' and python_full_version >= '3.8.1' layoutparser[layoutmodels,tesseract]==0.3.4; python_version >= '3.6' -litellm==1.23.14; python_version not in '2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7' and python_version >= '3.8' +litellm==1.23.15; python_version not in '2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7' and python_version >= '3.8' lxml==5.1.0; python_version >= '3.6' markdown==3.5.2 markupsafe==2.1.5; python_version >= '3.7' marshmallow==3.20.2; python_version >= '3.8' -matplotlib==3.8.2; python_version >= '3.9' +matplotlib==3.8.3; python_version >= '3.9' mccabe==0.7.0; python_version >= '3.6' monotonic==1.6 mpmath==1.3.0 @@ -115,7 +117,8 @@ opencv-python==4.9.0.80; python_version >= '3.6' openpyxl==3.1.2 opentelemetry-api==1.22.0; python_version >= '3.7' packaging==23.2; python_version >= '3.7' -pandas==2.2.0 +pandas==2.2.0; python_version >= '3.9' +pandasai==0.1.0; python_version >= '3.9' and python_version < '4.0' pathspec==0.12.1; python_version >= '3.8' pdf2image==1.16.3 pdfminer.six==20221105 @@ -128,9 +131,11 @@ pluggy==1.4.0; python_version >= '3.8' portalocker==2.8.2; python_version >= '3.8' postgrest==0.15.0; python_version >= '3.8' and python_version < '4.0' posthog==3.4.1 -prometheus-client==0.19.0; python_version >= '3.8' +prometheus-client==0.20.0; python_version >= '3.8' prompt-toolkit==3.0.43; python_full_version >= '3.7.0' protobuf==4.25.2; python_version >= '3.8' +psycopg2==2.9.9; python_version >= '3.7' +psycopg2-binary==2.9.9; python_version >= '3.7' pyasn1==0.5.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' pycocotools==2.0.7; python_version >= '3.5' pycodestyle==2.11.1; python_version >= '3.8' @@ -149,7 +154,7 @@ pytesseract==0.3.10; python_version >= '3.7' pytest==8.0.0; python_version >= '3.8' pytest-celery==0.0.0 pytest-mock==3.12.0; python_version >= '3.8' -python-dateutil==2.8.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2' +python-dateutil==2.8.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' python-docx==1.1.0 python-dotenv==1.0.1; python_version >= '3.8' python-iso639==2024.2.7; python_version >= '3.8' @@ -173,7 +178,7 @@ scipy==1.12.0; python_version >= '3.9' sentry-sdk[fastapi]==1.40.4 setuptools==69.1.0; python_version >= '3.8' sgmllib3k==1.0.0 -six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2' +six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' smmap==5.0.1; python_version >= '3.7' sniffio==1.3.0; python_version >= '3.7' soupsieve==2.5; python_version >= '3.8' @@ -203,7 +208,7 @@ unstructured[all-docs]==0.12.4; python_version < '3.12' and python_full_version unstructured-client==0.18.0; python_version >= '3.8' unstructured-inference==0.7.23 unstructured.pytesseract==0.3.12 -urllib3==2.0.7; python_version >= '3.10' +urllib3==2.0.7; python_version >= '3.7' uvicorn==0.22.0; python_version >= '3.7' vine==5.1.0; python_version >= '3.6' watchdog==4.0.0; python_version >= '3.8' diff --git a/docker-compose.redis.yml b/docker-compose.redis.yml new file mode 100644 index 000000000..06074ae2f --- /dev/null +++ b/docker-compose.redis.yml @@ -0,0 +1,9 @@ +version: "3.8" + +services: + redis: + image: redis:latest@sha256:a7cee7c8178ff9b5297cb109e6240f5072cdaaafd775ce6b586c3c704b06458e + container_name: redis + restart: always + ports: + - 6379:6379