From c828a5dfdf6c4a6caf7230ed879ae688608eb373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B0=E5=9C=A8=E4=BF=AE=E8=A1=8C=E7=9A=84=E5=A4=A7?= =?UTF-8?q?=E8=A1=97=E4=B8=8A?= Date: Fri, 27 Sep 2024 17:31:45 +0800 Subject: [PATCH 001/136] feat(Tools): add feishu tools (#8800) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 黎斌 --- api/core/tools/provider/_position.yaml | 4 + .../builtin/feishu_calendar/_assets/icon.png | Bin 0 -> 5488 bytes .../feishu_calendar/feishu_calendar.py | 7 + .../feishu_calendar/feishu_calendar.yaml | 36 ++ .../tools/add_event_attendees.py | 20 + .../tools/add_event_attendees.yaml | 54 +++ .../feishu_calendar/tools/create_event.py | 26 ++ .../feishu_calendar/tools/create_event.yaml | 119 ++++++ .../feishu_calendar/tools/delete_event.py | 19 + .../feishu_calendar/tools/delete_event.yaml | 38 ++ .../tools/get_primary_calendar.py | 18 + .../tools/get_primary_calendar.yaml | 37 ++ .../feishu_calendar/tools/list_events.py | 21 + .../feishu_calendar/tools/list_events.yaml | 62 +++ .../feishu_calendar/tools/search_events.py | 23 + .../feishu_calendar/tools/search_events.yaml | 100 +++++ .../feishu_calendar/tools/update_event.py | 24 ++ .../feishu_calendar/tools/update_event.yaml | 100 +++++ .../feishu_document/feishu_document.py | 12 +- .../feishu_document/feishu_document.yaml | 8 +- .../tools/create_document.yaml | 9 +- .../tools/get_document_content.py | 4 +- .../tools/get_document_content.yaml | 35 +- .../tools/list_document_blocks.py | 5 +- .../tools/list_document_blocks.yaml | 4 +- .../feishu_document/tools/write_document.py | 2 +- .../feishu_document/tools/write_document.yaml | 30 +- .../builtin/feishu_message/feishu_message.py | 12 +- .../feishu_message/feishu_message.yaml | 8 +- .../feishu_message/tools/get_chat_messages.py | 23 + .../tools/get_chat_messages.yaml | 96 +++++ .../tools/get_thread_messages.py | 21 + .../tools/get_thread_messages.yaml | 72 ++++ .../tools/send_bot_message.yaml | 114 +++-- .../tools/send_webhook_message.yaml | 46 +- .../feishu_spreadsheet/_assets/icon.png | Bin 0 -> 5417 bytes .../feishu_spreadsheet/feishu_spreadsheet.py | 7 + .../feishu_spreadsheet.yaml | 36 ++ .../feishu_spreadsheet/tools/add_cols.py | 22 + .../feishu_spreadsheet/tools/add_cols.yaml | 72 ++++ .../feishu_spreadsheet/tools/add_rows.py | 22 + .../feishu_spreadsheet/tools/add_rows.yaml | 72 ++++ .../tools/create_spreadsheet.py | 19 + .../tools/create_spreadsheet.yaml | 35 ++ .../tools/get_spreadsheet.py | 19 + .../tools/get_spreadsheet.yaml | 49 +++ .../tools/list_spreadsheet_sheets.py | 18 + .../tools/list_spreadsheet_sheets.yaml | 23 + .../feishu_spreadsheet/tools/read_cols.py | 23 + .../feishu_spreadsheet/tools/read_cols.yaml | 97 +++++ .../feishu_spreadsheet/tools/read_rows.py | 23 + .../feishu_spreadsheet/tools/read_rows.yaml | 97 +++++ .../feishu_spreadsheet/tools/read_table.py | 23 + .../feishu_spreadsheet/tools/read_table.yaml | 122 ++++++ .../builtin/feishu_task/_assets/icon.png | Bin 0 -> 3917 bytes .../builtin/feishu_task/feishu_task.py | 7 + .../builtin/feishu_task/feishu_task.yaml | 36 ++ .../builtin/feishu_task/tools/add_members.py | 20 + .../feishu_task/tools/add_members.yaml | 58 +++ .../builtin/feishu_task/tools/create_task.py | 22 + .../feishu_task/tools/create_task.yaml | 74 ++++ .../builtin/feishu_task/tools/delete_task.py | 18 + .../feishu_task/tools/delete_task.yaml | 24 ++ .../builtin/feishu_task/tools/update_task.py | 23 + .../feishu_task/tools/update_task.yaml | 89 ++++ .../builtin/feishu_wiki/_assets/icon.png | Bin 0 -> 4252 bytes .../builtin/feishu_wiki/feishu_wiki.py | 7 + .../builtin/feishu_wiki/feishu_wiki.yaml | 36 ++ .../feishu_wiki/tools/get_wiki_nodes.py | 21 + .../feishu_wiki/tools/get_wiki_nodes.yaml | 63 +++ api/core/tools/utils/feishu_api_utils.py | 401 +++++++++++++++++- 71 files changed, 2755 insertions(+), 132 deletions(-) create mode 100644 api/core/tools/provider/builtin/feishu_calendar/_assets/icon.png create mode 100644 api/core/tools/provider/builtin/feishu_calendar/feishu_calendar.py create mode 100644 api/core/tools/provider/builtin/feishu_calendar/feishu_calendar.yaml create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/add_event_attendees.py create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/add_event_attendees.yaml create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/create_event.py create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/create_event.yaml create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/delete_event.py create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/delete_event.yaml create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/get_primary_calendar.py create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/get_primary_calendar.yaml create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/list_events.py create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/list_events.yaml create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/search_events.py create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/search_events.yaml create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/update_event.py create mode 100644 api/core/tools/provider/builtin/feishu_calendar/tools/update_event.yaml create mode 100644 api/core/tools/provider/builtin/feishu_message/tools/get_chat_messages.py create mode 100644 api/core/tools/provider/builtin/feishu_message/tools/get_chat_messages.yaml create mode 100644 api/core/tools/provider/builtin/feishu_message/tools/get_thread_messages.py create mode 100644 api/core/tools/provider/builtin/feishu_message/tools/get_thread_messages.yaml create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/_assets/icon.png create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/feishu_spreadsheet.py create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/feishu_spreadsheet.yaml create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_cols.py create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_cols.yaml create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_rows.py create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_rows.yaml create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/create_spreadsheet.py create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/create_spreadsheet.yaml create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/get_spreadsheet.py create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/get_spreadsheet.yaml create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/list_spreadsheet_sheets.py create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/list_spreadsheet_sheets.yaml create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_cols.py create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_cols.yaml create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_rows.py create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_rows.yaml create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_table.py create mode 100644 api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_table.yaml create mode 100644 api/core/tools/provider/builtin/feishu_task/_assets/icon.png create mode 100644 api/core/tools/provider/builtin/feishu_task/feishu_task.py create mode 100644 api/core/tools/provider/builtin/feishu_task/feishu_task.yaml create mode 100644 api/core/tools/provider/builtin/feishu_task/tools/add_members.py create mode 100644 api/core/tools/provider/builtin/feishu_task/tools/add_members.yaml create mode 100644 api/core/tools/provider/builtin/feishu_task/tools/create_task.py create mode 100644 api/core/tools/provider/builtin/feishu_task/tools/create_task.yaml create mode 100644 api/core/tools/provider/builtin/feishu_task/tools/delete_task.py create mode 100644 api/core/tools/provider/builtin/feishu_task/tools/delete_task.yaml create mode 100644 api/core/tools/provider/builtin/feishu_task/tools/update_task.py create mode 100644 api/core/tools/provider/builtin/feishu_task/tools/update_task.yaml create mode 100644 api/core/tools/provider/builtin/feishu_wiki/_assets/icon.png create mode 100644 api/core/tools/provider/builtin/feishu_wiki/feishu_wiki.py create mode 100644 api/core/tools/provider/builtin/feishu_wiki/feishu_wiki.yaml create mode 100644 api/core/tools/provider/builtin/feishu_wiki/tools/get_wiki_nodes.py create mode 100644 api/core/tools/provider/builtin/feishu_wiki/tools/get_wiki_nodes.yaml diff --git a/api/core/tools/provider/_position.yaml b/api/core/tools/provider/_position.yaml index 40c3356116..e0a8e7511e 100644 --- a/api/core/tools/provider/_position.yaml +++ b/api/core/tools/provider/_position.yaml @@ -34,5 +34,9 @@ - feishu_base - feishu_document - feishu_message +- feishu_wiki +- feishu_task +- feishu_calendar +- feishu_spreadsheet - slack - tianditu diff --git a/api/core/tools/provider/builtin/feishu_calendar/_assets/icon.png b/api/core/tools/provider/builtin/feishu_calendar/_assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2a934747a98c6680065941bcd31d2400da1eaf23 GIT binary patch literal 5488 zcmd^@S6CClyT+3cB}hx?J%AJ?fE0mHMQMV8&_R?YO?nelY7hlNk>0Cxkg60F3{fc} zH9!DCT0jJ80tr>&_S<*on|*iYn;+KLNRROn&m{l=z^H#)+mzb= z`Og8lNIh#4qnG3;S|irW=|=l}|xX42D3f ziFX7+o4)i%ZwLZ_Wy~1N7x0X<1J061*y29gfDyJ2fUTeVMQPHq7@KLU>F~{ov1emn zTTR^lX{pNZoq%B_m`)+II}6z;t*n3|MoU1jS;dIL*?`4jeJEOe)(8nc{{SYk($W#)H9s-F>-9L)q>vds%qH zkcrltA7vCoxnI4*96v@UvWzE-7Cx7P{&@x%&*6D0Sj%Vv92rJtf5apSYHAh%#><`< z2e{f;;;o92hA{8!WL}P&cvjHhvd7BO#hQoR;KbjEOqS{00syPkr2de>038=`YCj_O zPd5aDqo-cUk32YjA+$q>s&#{_U4>P|VUB0oV{Y#n(#1N^fI)(I^SU~-b7vfzi7wtM z^w6|?o(Z6K3k;+Kp}J2e-ZCfW^Q6Q6wEFUk_k^MfZ-zo4F__Xr;-SE%Op=u@zWCtx zh*)#))OFs6a3XAAOzW2 zaQQ(p)m{RktgoK`-$50pJaB2=3&M;Z< z9qKSBQXoHQsl&j0SDWDz3kDNys17>(|0S{QY(fc-ee#?BF<;wCO^An-3EEzIBkWv} zKsIk^KKf7o0v7 zo)OJwp1u-Fzm8t+m$NYP78%(2mN{nOOaPn7rk52RKXip9_VJ&iy2 z(`YX=^0A&q8oV%!9lT#qgwn1%Cj_27!_4MD;@oHK;g{)Qou*`7VPiE&kMQBhO8^r17_RKNU12a>1wxuj`0t0s!bY)4s! zD?#4%fVSZ!q_)Gvm~T(j8fp+Ga=%Bt#I3m-oc&6^U8Hr;PRv-1eVCti15c z82eYGwqp7}`)hNLUtR=Dj$X5rBizuen46llf69Agt=t;*q;xz|RhMGh9D57TaiOlK zW54w4=tz9_xY_l<09!q@*Q*o7el@U{4iA>_x$Ur8rgLtd1}wROt^d})#PqKdN^EzJ z7h0^03z&m4`l2JG1D0xSRrOoZb~{KblW?80uK9ILNkR>xjR`b&#oVou@Cmm6V#ukF4sbg!;3bqq=X%cB7Tqeui z9NUQemDNQ#3o>0InrU5C`{tK$c6a^jxOY*iE@dc1HVm6dXZbe&l(yRQe9rZ8#aZZ^ zw6z&J(neQ_c6Wlb6zOxXR{3k(gvGzbShj_u7a8vdgN?)Gg|#jWL%d$hipGw#^159) zqu^pbdyA};j?!MfU@>0yNb)JcavNAAk|JC>{Yv@aK_w@vn<`L0BfkXk49muLbB}i?kf}5yCmO@z)g%j_r`dtUNCy{`O2m4Bp};pnCLqyyd=Jo}x_XVBrx^@8}}67`{sD|1|051pQ4fgjz{ z37jS;^1aQzysFD%sxq~W{vU)KfX}hm6@2}C7_E=!#mXw}$z_AVTN^$9LQ=ct=!sU( zuSqmPdWU6%TT(Rkiv}7Jk>bHrt%5g1z{g|ItEvD= z&CY);`g;{Wtx^Mmwlh#Ghh;4r7i%m$_j#>HO{r3ue5tQ-+PnW|wV65V(kEG?>=#a5 zZ^@jEZ+%y9ROh%3mK@ueb=Cg;(Tdg~{7CX>JD=m-e2)k&u!ziJnD5%qZZyAg8W|eHJ=)BJ@en|8qf1zrNdV9JR(N58HEGA z5spvQ>TQu~9oAo>J*ex}I>_7SGSXdv6HEDxX!>EArh?9@3GhfiC31nXHaY5>MU~w% zJ5PZibWvcY>CH680FGhbf8?IUW7<~$VM8QrKLtS?;$d$sO-<8GI6&twn^qBJ8P zRT?$m=--sZ5OJr+$~${ zo&TPY0`_c{1}^{~`_y`&Y(#fLb{N_PA7+LHiH48nhxfhLK&boooRx_b0f2XmTO7U+ z^HPYDdWf4Tcl zsw9+!RONFo0O@N-Ml)v9E%!g&DM}xV?9?Hi{}_9;)_7uN=Km`){jBTj&u=n3AP)WZ z_pmAPdJbrcinuatr-OGK-a0dmu9%We3Gw)<1`iotEL<8s*QJJjZLOhW7OUqFPC=3~ zx}>Li@^{PPLqu^hr#@b3T$Lv#jr=%A0kBt^b8g!<+GZ#)1v#UG7S4^+J3pvXVwU;n zVU=vQrF8D-(d!cmnU-E~ovcUM*s2<}qG!f;MP3FIi0uL7T-PNFY&OiE`r?be5iJRKDTVtwq<2%6lC6V8e-6cGm?YS${34;8=(N+NdW}0mjFw;&v{V8oR>uqO1c-?Anj4^3)C*f zT#==b66e{+N-En+9>_wbg@5Q&h8MJipzxr3eZ7aiqN>h$_8<^0BCi&X^Vp6zq=z;c zexUaXRdJ`}V5T~6SHQ!Z!Pmb#Y)hpVr?|o!ll_&+k-8mGi*DtKHRJ>S>1BO{J8&Zz z>Dr6)#$})#Ze9R00L8&!MJ*v=kbi2KcJk_{w_UFm9|vowb@b1n$i6R<<1Tbk~~DSqDm?*#!Y znZI?X0(UB$X(t!Ti4K-o$1D)@KR?Ih3x9j81xU9{!mnNO+S~0e7;=`|Sh>Msh<06W zY=1LH$!%s{U2t*>R6U%7`uRK>P->BL*D-(UX4}_@mhuTrCO?b7zShW?ES9TOyJ&t@ zqLVDkKKb|c?(*`8kr}0o>6}hqj}FNDD+CLqc1dbx;Cn{QiVvUu`NZsE(d^6$m$43c z1;E~ZRzNM;DuqO9s|)6Ch5hORd)-w80tY~CvhF?h^FHerJ$H+JSi+yG!nv9c7mxck zk~Yb@WdGxDV`i)&r`3Np1>%clUC8-6PM_k#lM9(0D=ndZV)qgAUQS~M!yV)-)CgoO zVcpw%O<;p@iUM?Iu1c#9oRH`*yta{8z^&l~Da4s6eH>3UJId>QHDdTdMz=NLIN2`M zIw8LojX0Ds`}uI=U_|jHkbRoV@j*$`E|gs{=^K~lTXr*`85*9+^dpmZtSu$hjL6Au z-QcE)Pk#F-E!LCB35vn+!ekooGu87X3g(_(LT_=Q|8iB?3;i!p8{KXr%L12MoUo>d zdamz=FNS;v0Bv5PJBn>ta~?hdAfMqYL;O&`%Lc2S0pm?dxY*oUxJnc4qcTk)hh?%8 zi|2*s{kj_+=dtGKE{2Ex2vqB9ah1sPUq4AP7?%*R#GgGr(S!J`{xMTT*y93;o#3P4 zbi@T_;J_nB$P<^B)MEH{WW}UD=lQOf#ll?1*=B`NK*TU7#99mi^$UC%1cS4vUu-!x zBHIV)Y~(kklJf(kp8S-$#gLY@^T-w>Q-y-P|*7Qy_VPhFZNW+)qF9L zU+U-9f2zC$pYe{z4}%GR2Hr-R95YC{S0J|8cHP{n4?5CwN4PlxKI6E}9k_dgfE#o? zhu1zHOgbx=3V>|BhR{85bhdhfYKm}y?Qb^lqqqf@a({}yhHT>bZ()T#Q z<9k;)CH$`B>K52hH*p_Ph-a5xP?3p2C9Eo&3P`Sv$Cum^q7s%g_wIF3>Q6Y(B3x}u z-3PvM=J5~F2Y?Rb>LC(rAn5<11lz*q+0{n*B&mUIrvVMm)e;^z(~*3Y=mSCMC7`Ro zj`C+-)G|Bl&zESzdfdZ~8u^FJpjS|b%4Kyu(v;zU?nJ|NLg`UH1rToohOL|U0zhDr z-HtL(F%@VCFXk#ejH4$Qnz@Y%fI&j|T8_pI6@&KwC^iL?2vHBy*eJOw&kqC_)q$%4 zhcJPRI5QM}oVIk?fFM9uMTHSzVkJ5AJ1Q(YDRCw!JeTgBavDV{ppfl}{^*$E@5h3gQ z7ZH`L$n)OW5Wg>M2`^*0L%BHZ9}ft8&$7>PkJKuMZRL`Q88-@2Mk2H@nWTFPt5S+F zLsHzguCWJ@m*dt_$Y?9MPR9%2ZivX+A@%WHx}bu}?mB6wufL%mOccc8b=|TB+Q{GA zZhnp!1zYQl3})ZmWtz2Umtudiq(x~`fywQMn0h!I_(C6z^7u&~X}5H%u_J;?jT1)h z)JcCcc(qkZcuVYIsjsrR4uv(klxqC5pVaib0cm-rseQuh8gxy%x4l-Ld@rBX+@0j! zff+|)Lp1?l9x4YU$o~%vPtYMYop$Ob0Hh25UxJ56k@&OI*n~FT87e{r=<671H{5b~ F_Fv-s=P3XH literal 0 HcmV?d00001 diff --git a/api/core/tools/provider/builtin/feishu_calendar/feishu_calendar.py b/api/core/tools/provider/builtin/feishu_calendar/feishu_calendar.py new file mode 100644 index 0000000000..a46a9fa9e8 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/feishu_calendar.py @@ -0,0 +1,7 @@ +from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController +from core.tools.utils.feishu_api_utils import auth + + +class FeishuCalendarProvider(BuiltinToolProviderController): + def _validate_credentials(self, credentials: dict) -> None: + auth(credentials) diff --git a/api/core/tools/provider/builtin/feishu_calendar/feishu_calendar.yaml b/api/core/tools/provider/builtin/feishu_calendar/feishu_calendar.yaml new file mode 100644 index 0000000000..db5bab5c10 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/feishu_calendar.yaml @@ -0,0 +1,36 @@ +identity: + author: Doug Lea + name: feishu_calendar + label: + en_US: Feishu Calendar + zh_Hans: 飞书日历 + description: + en_US: | + Feishu calendar, requires the following permissions: calendar:calendar:read、calendar:calendar、contact:user.id:readonly. + zh_Hans: | + 飞书日历,需要开通以下权限: calendar:calendar:read、calendar:calendar、contact:user.id:readonly。 + icon: icon.png + tags: + - social + - productivity +credentials_for_provider: + app_id: + type: text-input + required: true + label: + en_US: APP ID + placeholder: + en_US: Please input your feishu app id + zh_Hans: 请输入你的飞书 app id + help: + en_US: Get your app_id and app_secret from Feishu + zh_Hans: 从飞书获取您的 app_id 和 app_secret + url: https://open.larkoffice.com/app + app_secret: + type: secret-input + required: true + label: + en_US: APP Secret + placeholder: + en_US: Please input your app secret + zh_Hans: 请输入你的飞书 app secret diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/add_event_attendees.py b/api/core/tools/provider/builtin/feishu_calendar/tools/add_event_attendees.py new file mode 100644 index 0000000000..8f83aea5ab --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/add_event_attendees.py @@ -0,0 +1,20 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class AddEventAttendeesTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + event_id = tool_parameters.get("event_id") + attendee_phone_or_email = tool_parameters.get("attendee_phone_or_email") + need_notification = tool_parameters.get("need_notification", True) + + res = client.add_event_attendees(event_id, attendee_phone_or_email, need_notification) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/add_event_attendees.yaml b/api/core/tools/provider/builtin/feishu_calendar/tools/add_event_attendees.yaml new file mode 100644 index 0000000000..b7744499b0 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/add_event_attendees.yaml @@ -0,0 +1,54 @@ +identity: + name: add_event_attendees + author: Doug Lea + label: + en_US: Add Event Attendees + zh_Hans: 添加日程参会人 +description: + human: + en_US: Add Event Attendees + zh_Hans: 添加日程参会人 + llm: A tool for adding attendees to events in Feishu. (在飞书中添加日程参会人) +parameters: + - name: event_id + type: string + required: true + label: + en_US: Event ID + zh_Hans: 日程 ID + human_description: + en_US: | + The ID of the event, which will be returned when the event is created. For example: fb2a6406-26d6-4c8d-a487-6f0246c94d2f_0. + zh_Hans: | + 创建日程时会返回日程 ID。例如: fb2a6406-26d6-4c8d-a487-6f0246c94d2f_0。 + llm_description: | + 日程 ID,创建日程时会返回日程 ID。例如: fb2a6406-26d6-4c8d-a487-6f0246c94d2f_0。 + form: llm + + - name: need_notification + type: boolean + required: false + default: true + label: + en_US: Need Notification + zh_Hans: 是否需要通知 + human_description: + en_US: | + Whether to send a Bot notification to attendees. true: send, false: do not send. + zh_Hans: | + 是否给参与人发送 Bot 通知,true: 发送,false: 不发送。 + llm_description: | + 是否给参与人发送 Bot 通知,true: 发送,false: 不发送。 + form: form + + - name: attendee_phone_or_email + type: string + required: true + label: + en_US: Attendee Phone or Email + zh_Hans: 参会人电话或邮箱 + human_description: + en_US: The list of attendee emails or phone numbers, separated by commas. + zh_Hans: 日程参会人邮箱或者手机号列表,使用逗号分隔。 + llm_description: 日程参会人邮箱或者手机号列表,使用逗号分隔。 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/create_event.py b/api/core/tools/provider/builtin/feishu_calendar/tools/create_event.py new file mode 100644 index 0000000000..8820bebdbe --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/create_event.py @@ -0,0 +1,26 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class CreateEventTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + summary = tool_parameters.get("summary") + description = tool_parameters.get("description") + start_time = tool_parameters.get("start_time") + end_time = tool_parameters.get("end_time") + attendee_ability = tool_parameters.get("attendee_ability") + need_notification = tool_parameters.get("need_notification", True) + auto_record = tool_parameters.get("auto_record", False) + + res = client.create_event( + summary, description, start_time, end_time, attendee_ability, need_notification, auto_record + ) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/create_event.yaml b/api/core/tools/provider/builtin/feishu_calendar/tools/create_event.yaml new file mode 100644 index 0000000000..f0784221ce --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/create_event.yaml @@ -0,0 +1,119 @@ +identity: + name: create_event + author: Doug Lea + label: + en_US: Create Event + zh_Hans: 创建日程 +description: + human: + en_US: Create Event + zh_Hans: 创建日程 + llm: A tool for creating events in Feishu.(创建飞书日程) +parameters: + - name: summary + type: string + required: false + label: + en_US: Summary + zh_Hans: 日程标题 + human_description: + en_US: The title of the event. If not filled, the event title will display (No Subject). + zh_Hans: 日程标题,若不填则日程标题显示 (无主题)。 + llm_description: 日程标题,若不填则日程标题显示 (无主题)。 + form: llm + + - name: description + type: string + required: false + label: + en_US: Description + zh_Hans: 日程描述 + human_description: + en_US: The description of the event. + zh_Hans: 日程描述。 + llm_description: 日程描述。 + form: llm + + - name: need_notification + type: boolean + required: false + default: true + label: + en_US: Need Notification + zh_Hans: 是否发送通知 + human_description: + en_US: | + Whether to send a bot message when the event is created, true: send, false: do not send. + zh_Hans: 创建日程时是否发送 bot 消息,true:发送,false:不发送。 + llm_description: 创建日程时是否发送 bot 消息,true:发送,false:不发送。 + form: form + + - name: start_time + type: string + required: true + label: + en_US: Start Time + zh_Hans: 开始时间 + human_description: + en_US: | + The start time of the event, format: 2006-01-02 15:04:05. + zh_Hans: 日程开始时间,格式:2006-01-02 15:04:05。 + llm_description: 日程开始时间,格式:2006-01-02 15:04:05。 + form: llm + + - name: end_time + type: string + required: true + label: + en_US: End Time + zh_Hans: 结束时间 + human_description: + en_US: | + The end time of the event, format: 2006-01-02 15:04:05. + zh_Hans: 日程结束时间,格式:2006-01-02 15:04:05。 + llm_description: 日程结束时间,格式:2006-01-02 15:04:05。 + form: llm + + - name: attendee_ability + type: select + required: false + options: + - value: none + label: + en_US: none + zh_Hans: 无 + - value: can_see_others + label: + en_US: can_see_others + zh_Hans: 可以查看参与人列表 + - value: can_invite_others + label: + en_US: can_invite_others + zh_Hans: 可以邀请其它参与人 + - value: can_modify_event + label: + en_US: can_modify_event + zh_Hans: 可以编辑日程 + default: "none" + label: + en_US: attendee_ability + zh_Hans: 参会人权限 + human_description: + en_US: Attendee ability, optional values are none, can_see_others, can_invite_others, can_modify_event, with a default value of none. + zh_Hans: 参会人权限,可选值有无、可以查看参与人列表、可以邀请其它参与人、可以编辑日程,默认值为无。 + llm_description: 参会人权限,可选值有无、可以查看参与人列表、可以邀请其它参与人、可以编辑日程,默认值为无。 + form: form + + - name: auto_record + type: boolean + required: false + default: false + label: + en_US: Auto Record + zh_Hans: 自动录制 + human_description: + en_US: | + Whether to enable automatic recording, true: enabled, automatically record when the meeting starts; false: not enabled. + zh_Hans: 是否开启自动录制,true:开启,会议开始后自动录制;false:不开启。 + llm_description: 是否开启自动录制,true:开启,会议开始后自动录制;false:不开启。 + form: form diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/delete_event.py b/api/core/tools/provider/builtin/feishu_calendar/tools/delete_event.py new file mode 100644 index 0000000000..144889692f --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/delete_event.py @@ -0,0 +1,19 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class DeleteEventTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + event_id = tool_parameters.get("event_id") + need_notification = tool_parameters.get("need_notification", True) + + res = client.delete_event(event_id, need_notification) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/delete_event.yaml b/api/core/tools/provider/builtin/feishu_calendar/tools/delete_event.yaml new file mode 100644 index 0000000000..54fdb04acc --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/delete_event.yaml @@ -0,0 +1,38 @@ +identity: + name: delete_event + author: Doug Lea + label: + en_US: Delete Event + zh_Hans: 删除日程 +description: + human: + en_US: Delete Event + zh_Hans: 删除日程 + llm: A tool for deleting events in Feishu.(在飞书中删除日程) +parameters: + - name: event_id + type: string + required: true + label: + en_US: Event ID + zh_Hans: 日程 ID + human_description: + en_US: | + The ID of the event, for example: e8b9791c-39ae-4908-8ad8-66b13159b9fb_0. + zh_Hans: 日程 ID,例如:e8b9791c-39ae-4908-8ad8-66b13159b9fb_0。 + llm_description: 日程 ID,例如:e8b9791c-39ae-4908-8ad8-66b13159b9fb_0。 + form: llm + + - name: need_notification + type: boolean + required: false + default: true + label: + en_US: Need Notification + zh_Hans: 是否需要通知 + human_description: + en_US: | + Indicates whether to send bot notifications to event participants upon deletion. true: send, false: do not send. + zh_Hans: 删除日程是否给日程参与人发送 bot 通知,true:发送,false:不发送。 + llm_description: 删除日程是否给日程参与人发送 bot 通知,true:发送,false:不发送。 + form: form diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/get_primary_calendar.py b/api/core/tools/provider/builtin/feishu_calendar/tools/get_primary_calendar.py new file mode 100644 index 0000000000..a2cd5a8b17 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/get_primary_calendar.py @@ -0,0 +1,18 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class GetPrimaryCalendarTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + user_id_type = tool_parameters.get("user_id_type", "open_id") + + res = client.get_primary_calendar(user_id_type) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/get_primary_calendar.yaml b/api/core/tools/provider/builtin/feishu_calendar/tools/get_primary_calendar.yaml new file mode 100644 index 0000000000..3440c85d4a --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/get_primary_calendar.yaml @@ -0,0 +1,37 @@ +identity: + name: get_primary_calendar + author: Doug Lea + label: + en_US: Get Primary Calendar + zh_Hans: 查询主日历信息 +description: + human: + en_US: Get Primary Calendar + zh_Hans: 查询主日历信息 + llm: A tool for querying primary calendar information in Feishu.(在飞书中查询主日历信息) +parameters: + - name: user_id_type + type: select + required: false + options: + - value: open_id + label: + en_US: open_id + zh_Hans: open_id + - value: union_id + label: + en_US: union_id + zh_Hans: union_id + - value: user_id + label: + en_US: user_id + zh_Hans: user_id + default: "open_id" + label: + en_US: user_id_type + zh_Hans: 用户 ID 类型 + human_description: + en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id. + zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 + llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 + form: form diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/list_events.py b/api/core/tools/provider/builtin/feishu_calendar/tools/list_events.py new file mode 100644 index 0000000000..8815b4c9c8 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/list_events.py @@ -0,0 +1,21 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class ListEventsTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + start_time = tool_parameters.get("start_time") + end_time = tool_parameters.get("end_time") + page_token = tool_parameters.get("page_token") + page_size = tool_parameters.get("page_size") + + res = client.list_events(start_time, end_time, page_token, page_size) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/list_events.yaml b/api/core/tools/provider/builtin/feishu_calendar/tools/list_events.yaml new file mode 100644 index 0000000000..f4a5bfe6ba --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/list_events.yaml @@ -0,0 +1,62 @@ +identity: + name: list_events + author: Doug Lea + label: + en_US: List Events + zh_Hans: 获取日程列表 +description: + human: + en_US: List Events + zh_Hans: 获取日程列表 + llm: A tool for listing events in Feishu.(在飞书中获取日程列表) +parameters: + - name: start_time + type: string + required: false + label: + en_US: Start Time + zh_Hans: 开始时间 + human_description: + en_US: | + The start time, defaults to 0:00 of the current day if not provided, format: 2006-01-02 15:04:05. + zh_Hans: 开始时间,不传值时默认当天 0 点时间,格式为:2006-01-02 15:04:05。 + llm_description: 开始时间,不传值时默认当天 0 点时间,格式为:2006-01-02 15:04:05。 + form: llm + + - name: end_time + type: string + required: false + label: + en_US: End Time + zh_Hans: 结束时间 + human_description: + en_US: | + The end time, defaults to 23:59 of the current day if not provided, format: 2006-01-02 15:04:05. + zh_Hans: 结束时间,不传值时默认当天 23:59 分时间,格式为:2006-01-02 15:04:05。 + llm_description: 结束时间,不传值时默认当天 23:59 分时间,格式为:2006-01-02 15:04:05。 + form: llm + + - name: page_size + type: number + required: false + default: 50 + label: + en_US: Page Size + zh_Hans: 分页大小 + human_description: + en_US: The page size, i.e., the number of data entries returned in a single request. The default value is 50, and the value range is [50,1000]. + zh_Hans: 分页大小,即单次请求所返回的数据条目数。默认值为 50,取值范围为 [50,1000]。 + llm_description: 分页大小,即单次请求所返回的数据条目数。默认值为 50,取值范围为 [50,1000]。 + form: llm + + - name: page_token + type: string + required: false + label: + en_US: Page Token + zh_Hans: 分页标记 + human_description: + en_US: The pagination token. Leave it blank for the first request, indicating to start traversing from the beginning; when the pagination query result has more items, a new page_token will be returned simultaneously, which can be used to obtain the query result in the next traversal. + zh_Hans: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。 + llm_description: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/search_events.py b/api/core/tools/provider/builtin/feishu_calendar/tools/search_events.py new file mode 100644 index 0000000000..dc365205a4 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/search_events.py @@ -0,0 +1,23 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class SearchEventsTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + query = tool_parameters.get("query") + start_time = tool_parameters.get("start_time") + end_time = tool_parameters.get("end_time") + page_token = tool_parameters.get("page_token") + user_id_type = tool_parameters.get("user_id_type", "open_id") + page_size = tool_parameters.get("page_size", 20) + + res = client.search_events(query, start_time, end_time, page_token, user_id_type, page_size) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/search_events.yaml b/api/core/tools/provider/builtin/feishu_calendar/tools/search_events.yaml new file mode 100644 index 0000000000..e92a282091 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/search_events.yaml @@ -0,0 +1,100 @@ +identity: + name: search_events + author: Doug Lea + label: + en_US: Search Events + zh_Hans: 搜索日程 +description: + human: + en_US: Search Events + zh_Hans: 搜索日程 + llm: A tool for searching events in Feishu.(在飞书中搜索日程) +parameters: + - name: user_id_type + type: select + required: false + options: + - value: open_id + label: + en_US: open_id + zh_Hans: open_id + - value: union_id + label: + en_US: union_id + zh_Hans: union_id + - value: user_id + label: + en_US: user_id + zh_Hans: user_id + default: "open_id" + label: + en_US: user_id_type + zh_Hans: 用户 ID 类型 + human_description: + en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id. + zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 + llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 + form: form + + - name: query + type: string + required: true + label: + en_US: Query + zh_Hans: 搜索关键字 + human_description: + en_US: The search keyword used for fuzzy searching event names, with a maximum input of 200 characters. + zh_Hans: 用于模糊查询日程名称的搜索关键字,最大输入 200 字符。 + llm_description: 用于模糊查询日程名称的搜索关键字,最大输入 200 字符。 + form: llm + + - name: start_time + type: string + required: false + label: + en_US: Start Time + zh_Hans: 开始时间 + human_description: + en_US: | + The start time, defaults to 0:00 of the current day if not provided, format: 2006-01-02 15:04:05. + zh_Hans: 开始时间,不传值时默认当天 0 点时间,格式为:2006-01-02 15:04:05。 + llm_description: 开始时间,不传值时默认当天 0 点时间,格式为:2006-01-02 15:04:05。 + form: llm + + - name: end_time + type: string + required: false + label: + en_US: End Time + zh_Hans: 结束时间 + human_description: + en_US: | + The end time, defaults to 23:59 of the current day if not provided, format: 2006-01-02 15:04:05. + zh_Hans: 结束时间,不传值时默认当天 23:59 分时间,格式为:2006-01-02 15:04:05。 + llm_description: 结束时间,不传值时默认当天 23:59 分时间,格式为:2006-01-02 15:04:05。 + form: llm + + - name: page_size + type: number + required: false + default: 20 + label: + en_US: Page Size + zh_Hans: 分页大小 + human_description: + en_US: The page size, i.e., the number of data entries returned in a single request. The default value is 20, and the value range is [10,100]. + zh_Hans: 分页大小,即单次请求所返回的数据条目数。默认值为 20,取值范围为 [10,100]。 + llm_description: 分页大小,即单次请求所返回的数据条目数。默认值为 20,取值范围为 [10,100]。 + form: llm + + - name: page_token + type: string + required: false + label: + en_US: Page Token + zh_Hans: 分页标记 + human_description: + en_US: The pagination token. Leave it blank for the first request, indicating to start traversing from the beginning; when the pagination query result has more items, a new page_token will be returned simultaneously, which can be used to obtain the query result in the next traversal. + zh_Hans: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。 + llm_description: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/update_event.py b/api/core/tools/provider/builtin/feishu_calendar/tools/update_event.py new file mode 100644 index 0000000000..85bcb1d3f6 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/update_event.py @@ -0,0 +1,24 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class UpdateEventTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + event_id = tool_parameters.get("event_id") + summary = tool_parameters.get("summary") + description = tool_parameters.get("description") + need_notification = tool_parameters.get("need_notification", True) + start_time = tool_parameters.get("start_time") + end_time = tool_parameters.get("end_time") + auto_record = tool_parameters.get("auto_record", False) + + res = client.update_event(event_id, summary, description, need_notification, start_time, end_time, auto_record) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_calendar/tools/update_event.yaml b/api/core/tools/provider/builtin/feishu_calendar/tools/update_event.yaml new file mode 100644 index 0000000000..4d60dbf8c8 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_calendar/tools/update_event.yaml @@ -0,0 +1,100 @@ +identity: + name: update_event + author: Doug Lea + label: + en_US: Update Event + zh_Hans: 更新日程 +description: + human: + en_US: Update Event + zh_Hans: 更新日程 + llm: A tool for updating events in Feishu.(更新飞书中的日程) +parameters: + - name: event_id + type: string + required: true + label: + en_US: Event ID + zh_Hans: 日程 ID + human_description: + en_US: | + The ID of the event, for example: e8b9791c-39ae-4908-8ad8-66b13159b9fb_0. + zh_Hans: 日程 ID,例如:e8b9791c-39ae-4908-8ad8-66b13159b9fb_0。 + llm_description: 日程 ID,例如:e8b9791c-39ae-4908-8ad8-66b13159b9fb_0。 + form: llm + + - name: summary + type: string + required: false + label: + en_US: Summary + zh_Hans: 日程标题 + human_description: + en_US: The title of the event. + zh_Hans: 日程标题。 + llm_description: 日程标题。 + form: llm + + - name: description + type: string + required: false + label: + en_US: Description + zh_Hans: 日程描述 + human_description: + en_US: The description of the event. + zh_Hans: 日程描述。 + llm_description: 日程描述。 + form: llm + + - name: need_notification + type: boolean + required: false + label: + en_US: Need Notification + zh_Hans: 是否发送通知 + human_description: + en_US: | + Whether to send a bot message when the event is updated, true: send, false: do not send. + zh_Hans: 更新日程时是否发送 bot 消息,true:发送,false:不发送。 + llm_description: 更新日程时是否发送 bot 消息,true:发送,false:不发送。 + form: form + + - name: start_time + type: string + required: false + label: + en_US: Start Time + zh_Hans: 开始时间 + human_description: + en_US: | + The start time of the event, format: 2006-01-02 15:04:05. + zh_Hans: 日程开始时间,格式:2006-01-02 15:04:05。 + llm_description: 日程开始时间,格式:2006-01-02 15:04:05。 + form: llm + + - name: end_time + type: string + required: false + label: + en_US: End Time + zh_Hans: 结束时间 + human_description: + en_US: | + The end time of the event, format: 2006-01-02 15:04:05. + zh_Hans: 日程结束时间,格式:2006-01-02 15:04:05。 + llm_description: 日程结束时间,格式:2006-01-02 15:04:05。 + form: llm + + - name: auto_record + type: boolean + required: false + label: + en_US: Auto Record + zh_Hans: 自动录制 + human_description: + en_US: | + Whether to enable automatic recording, true: enabled, automatically record when the meeting starts; false: not enabled. + zh_Hans: 是否开启自动录制,true:开启,会议开始后自动录制;false:不开启。 + llm_description: 是否开启自动录制,true:开启,会议开始后自动录制;false:不开启。 + form: form diff --git a/api/core/tools/provider/builtin/feishu_document/feishu_document.py b/api/core/tools/provider/builtin/feishu_document/feishu_document.py index b0a1e393eb..217ae52082 100644 --- a/api/core/tools/provider/builtin/feishu_document/feishu_document.py +++ b/api/core/tools/provider/builtin/feishu_document/feishu_document.py @@ -1,15 +1,7 @@ -from core.tools.errors import ToolProviderCredentialValidationError from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController -from core.tools.utils.feishu_api_utils import FeishuRequest +from core.tools.utils.feishu_api_utils import auth class FeishuDocumentProvider(BuiltinToolProviderController): def _validate_credentials(self, credentials: dict) -> None: - app_id = credentials.get("app_id") - app_secret = credentials.get("app_secret") - if not app_id or not app_secret: - raise ToolProviderCredentialValidationError("app_id and app_secret is required") - try: - assert FeishuRequest(app_id, app_secret).tenant_access_token is not None - except Exception as e: - raise ToolProviderCredentialValidationError(str(e)) + auth(credentials) diff --git a/api/core/tools/provider/builtin/feishu_document/feishu_document.yaml b/api/core/tools/provider/builtin/feishu_document/feishu_document.yaml index 8eaa6b2704..8f9afa6149 100644 --- a/api/core/tools/provider/builtin/feishu_document/feishu_document.yaml +++ b/api/core/tools/provider/builtin/feishu_document/feishu_document.yaml @@ -5,8 +5,10 @@ identity: en_US: Lark Cloud Document zh_Hans: 飞书云文档 description: - en_US: Lark Cloud Document - zh_Hans: 飞书云文档 + en_US: | + Lark cloud document, requires the following permissions: docx:document、drive:drive、docs:document.content:read. + zh_Hans: | + 飞书云文档,需要开通以下权限: docx:document、drive:drive、docs:document.content:read。 icon: icon.svg tags: - social @@ -23,7 +25,7 @@ credentials_for_provider: help: en_US: Get your app_id and app_secret from Feishu zh_Hans: 从飞书获取您的 app_id 和 app_secret - url: https://open.feishu.cn + url: https://open.larkoffice.com/app app_secret: type: secret-input required: true diff --git a/api/core/tools/provider/builtin/feishu_document/tools/create_document.yaml b/api/core/tools/provider/builtin/feishu_document/tools/create_document.yaml index ddf2729f0e..85382e9d8e 100644 --- a/api/core/tools/provider/builtin/feishu_document/tools/create_document.yaml +++ b/api/core/tools/provider/builtin/feishu_document/tools/create_document.yaml @@ -7,7 +7,7 @@ identity: description: human: en_US: Create Lark document - zh_Hans: 创建飞书文档,支持创建空文档和带内容的文档,支持 markdown 语法创建。 + zh_Hans: 创建飞书文档,支持创建空文档和带内容的文档,支持 markdown 语法创建。应用需要开启机器人能力(https://open.feishu.cn/document/faq/trouble-shooting/how-to-enable-bot-ability)。 llm: A tool for creating Feishu documents. parameters: - name: title @@ -41,7 +41,8 @@ parameters: en_US: folder_token zh_Hans: 文档所在文件夹的 Token human_description: - en_US: The token of the folder where the document is located. If it is not passed or is empty, it means the root directory. - zh_Hans: 文档所在文件夹的 Token,不传或传空表示根目录。 - llm_description: 文档所在文件夹的 Token,不传或传空表示根目录。 + en_US: | + The token of the folder where the document is located. If it is not passed or is empty, it means the root directory. For Example: https://svi136aogf123.feishu.cn/drive/folder/JgR9fiG9AlPt8EdsSNpcGjIInbf + zh_Hans: 文档所在文件夹的 Token,不传或传空表示根目录。例如:https://svi136aogf123.feishu.cn/drive/folder/JgR9fiG9AlPt8EdsSNpcGjIInbf。 + llm_description: 文档所在文件夹的 Token,不传或传空表示根目录。例如:https://svi136aogf123.feishu.cn/drive/folder/JgR9fiG9AlPt8EdsSNpcGjIInbf。 form: llm diff --git a/api/core/tools/provider/builtin/feishu_document/tools/get_document_content.py b/api/core/tools/provider/builtin/feishu_document/tools/get_document_content.py index c94a5f70ed..e67a017fac 100644 --- a/api/core/tools/provider/builtin/feishu_document/tools/get_document_content.py +++ b/api/core/tools/provider/builtin/feishu_document/tools/get_document_content.py @@ -12,8 +12,8 @@ class GetDocumentRawContentTool(BuiltinTool): client = FeishuRequest(app_id, app_secret) document_id = tool_parameters.get("document_id") - mode = tool_parameters.get("mode") - lang = tool_parameters.get("lang", 0) + mode = tool_parameters.get("mode", "markdown") + lang = tool_parameters.get("lang", "0") res = client.get_document_content(document_id, mode, lang) return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_document/tools/get_document_content.yaml b/api/core/tools/provider/builtin/feishu_document/tools/get_document_content.yaml index 51eda73a60..15e827cde9 100644 --- a/api/core/tools/provider/builtin/feishu_document/tools/get_document_content.yaml +++ b/api/core/tools/provider/builtin/feishu_document/tools/get_document_content.yaml @@ -23,8 +23,18 @@ parameters: form: llm - name: mode - type: string + type: select required: false + options: + - value: text + label: + en_US: text + zh_Hans: text + - value: markdown + label: + en_US: markdown + zh_Hans: markdown + default: "markdown" label: en_US: mode zh_Hans: 文档返回格式 @@ -32,18 +42,29 @@ parameters: en_US: Format of the document return, optional values are text, markdown, can be empty, default is markdown. zh_Hans: 文档返回格式,可选值有 text、markdown,可以为空,默认值为 markdown。 llm_description: 文档返回格式,可选值有 text、markdown,可以为空,默认值为 markdown。 - form: llm + form: form - name: lang - type: number + type: select required: false - default: 0 + options: + - value: "0" + label: + en_US: User's default name + zh_Hans: 用户的默认名称 + - value: "1" + label: + en_US: User's English name + zh_Hans: 用户的英文名称 + default: "0" label: en_US: lang zh_Hans: 指定@用户的语言 human_description: en_US: | Specifies the language for MentionUser, optional values are [0, 1]. 0: User's default name, 1: User's English name, default is 0. - zh_Hans: 指定返回的 MentionUser,即 @用户 的语言,可选值有 [0,1]。0:该用户的默认名称,1:该用户的英文名称,默认值为 0。 - llm_description: 指定返回的 MentionUser,即 @用户 的语言,可选值有 [0,1]。0:该用户的默认名称,1:该用户的英文名称,默认值为 0。 - form: llm + zh_Hans: | + 指定返回的 MentionUser,即@用户的语言,可选值有 [0,1]。0: 该用户的默认名称,1: 该用户的英文名称,默认值为 0。 + llm_description: | + 指定返回的 MentionUser,即@用户的语言,可选值有 [0,1]。0: 该用户的默认名称,1: 该用户的英文名称,默认值为 0。 + form: form diff --git a/api/core/tools/provider/builtin/feishu_document/tools/list_document_blocks.py b/api/core/tools/provider/builtin/feishu_document/tools/list_document_blocks.py index 572a7abf28..dd57c6870d 100644 --- a/api/core/tools/provider/builtin/feishu_document/tools/list_document_blocks.py +++ b/api/core/tools/provider/builtin/feishu_document/tools/list_document_blocks.py @@ -12,8 +12,9 @@ class ListDocumentBlockTool(BuiltinTool): client = FeishuRequest(app_id, app_secret) document_id = tool_parameters.get("document_id") - page_size = tool_parameters.get("page_size", 500) page_token = tool_parameters.get("page_token", "") + user_id_type = tool_parameters.get("user_id_type", "open_id") + page_size = tool_parameters.get("page_size", 500) - res = client.list_document_blocks(document_id, page_token, page_size) + res = client.list_document_blocks(document_id, page_token, user_id_type, page_size) return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_document/tools/list_document_blocks.yaml b/api/core/tools/provider/builtin/feishu_document/tools/list_document_blocks.yaml index 019ac98390..5b8ef7d53c 100644 --- a/api/core/tools/provider/builtin/feishu_document/tools/list_document_blocks.yaml +++ b/api/core/tools/provider/builtin/feishu_document/tools/list_document_blocks.yaml @@ -46,12 +46,12 @@ parameters: en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id. zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 - form: llm + form: form - name: page_size type: number required: false - default: "500" + default: 500 label: en_US: page_size zh_Hans: 分页大小 diff --git a/api/core/tools/provider/builtin/feishu_document/tools/write_document.py b/api/core/tools/provider/builtin/feishu_document/tools/write_document.py index 6061250e48..59f08f53dc 100644 --- a/api/core/tools/provider/builtin/feishu_document/tools/write_document.py +++ b/api/core/tools/provider/builtin/feishu_document/tools/write_document.py @@ -13,7 +13,7 @@ class CreateDocumentTool(BuiltinTool): document_id = tool_parameters.get("document_id") content = tool_parameters.get("content") - position = tool_parameters.get("position") + position = tool_parameters.get("position", "end") res = client.write_document(document_id, content, position) return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_document/tools/write_document.yaml b/api/core/tools/provider/builtin/feishu_document/tools/write_document.yaml index 4282e3dcf3..de70f4e772 100644 --- a/api/core/tools/provider/builtin/feishu_document/tools/write_document.yaml +++ b/api/core/tools/provider/builtin/feishu_document/tools/write_document.yaml @@ -35,25 +35,23 @@ parameters: form: llm - name: position - type: string + type: select required: false - label: - en_US: position - zh_Hans: 添加位置 - human_description: - en_US: | - Enumeration values: start or end. Use 'start' to add content at the beginning of the document, and 'end' to add content at the end. The default value is 'end'. - zh_Hans: 枚举值:start 或 end。使用 'start' 在文档开头添加内容,使用 'end' 在文档结尾添加内容,默认值为 'end'。 - llm_description: | - 枚举值 start、end,start: 在文档开头添加内容;end: 在文档结尾添加内容,默认值为 end。 - form: llm options: - value: start label: - en_US: start - zh_Hans: 在文档开头添加内容 + en_US: document start + zh_Hans: 文档开始 - value: end label: - en_US: end - zh_Hans: 在文档结尾添加内容 - default: start + en_US: document end + zh_Hans: 文档结束 + default: "end" + label: + en_US: position + zh_Hans: 内容添加位置 + human_description: + en_US: Content insertion position, optional values are start, end. 'start' means adding content at the beginning of the document; 'end' means adding content at the end of the document. The default value is end. + zh_Hans: 内容添加位置,可选值有 start、end。start 表示在文档开头添加内容;end 表示在文档结尾添加内容,默认值为 end。 + llm_description: 内容添加位置,可选值有 start、end。start 表示在文档开头添加内容;end 表示在文档结尾添加内容,默认值为 end。 + form: form diff --git a/api/core/tools/provider/builtin/feishu_message/feishu_message.py b/api/core/tools/provider/builtin/feishu_message/feishu_message.py index 7b3adb9293..a3b5473769 100644 --- a/api/core/tools/provider/builtin/feishu_message/feishu_message.py +++ b/api/core/tools/provider/builtin/feishu_message/feishu_message.py @@ -1,15 +1,7 @@ -from core.tools.errors import ToolProviderCredentialValidationError from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController -from core.tools.utils.feishu_api_utils import FeishuRequest +from core.tools.utils.feishu_api_utils import auth class FeishuMessageProvider(BuiltinToolProviderController): def _validate_credentials(self, credentials: dict) -> None: - app_id = credentials.get("app_id") - app_secret = credentials.get("app_secret") - if not app_id or not app_secret: - raise ToolProviderCredentialValidationError("app_id and app_secret is required") - try: - assert FeishuRequest(app_id, app_secret).tenant_access_token is not None - except Exception as e: - raise ToolProviderCredentialValidationError(str(e)) + auth(credentials) diff --git a/api/core/tools/provider/builtin/feishu_message/feishu_message.yaml b/api/core/tools/provider/builtin/feishu_message/feishu_message.yaml index 1bd8953ddd..56683ec168 100644 --- a/api/core/tools/provider/builtin/feishu_message/feishu_message.yaml +++ b/api/core/tools/provider/builtin/feishu_message/feishu_message.yaml @@ -5,8 +5,10 @@ identity: en_US: Lark Message zh_Hans: 飞书消息 description: - en_US: Lark Message - zh_Hans: 飞书消息 + en_US: | + Lark message, requires the following permissions: im:message、im:message.group_msg. + zh_Hans: | + 飞书消息,需要开通以下权限: im:message、im:message.group_msg。 icon: icon.svg tags: - social @@ -23,7 +25,7 @@ credentials_for_provider: help: en_US: Get your app_id and app_secret from Feishu zh_Hans: 从飞书获取您的 app_id 和 app_secret - url: https://open.feishu.cn + url: https://open.larkoffice.com/app app_secret: type: secret-input required: true diff --git a/api/core/tools/provider/builtin/feishu_message/tools/get_chat_messages.py b/api/core/tools/provider/builtin/feishu_message/tools/get_chat_messages.py new file mode 100644 index 0000000000..7eb29230b2 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_message/tools/get_chat_messages.py @@ -0,0 +1,23 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class GetChatMessagesTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + container_id = tool_parameters.get("container_id") + start_time = tool_parameters.get("start_time") + end_time = tool_parameters.get("end_time") + page_token = tool_parameters.get("page_token") + sort_type = tool_parameters.get("sort_type", "ByCreateTimeAsc") + page_size = tool_parameters.get("page_size", 20) + + res = client.get_chat_messages(container_id, start_time, end_time, page_token, sort_type, page_size) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_message/tools/get_chat_messages.yaml b/api/core/tools/provider/builtin/feishu_message/tools/get_chat_messages.yaml new file mode 100644 index 0000000000..153c8c80e5 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_message/tools/get_chat_messages.yaml @@ -0,0 +1,96 @@ +identity: + name: get_chat_messages + author: Doug Lea + label: + en_US: Get Chat Messages + zh_Hans: 获取指定单聊、群聊的消息历史 +description: + human: + en_US: Get Chat Messages + zh_Hans: 获取指定单聊、群聊的消息历史 + llm: A tool for getting chat messages from specific one-on-one chats or group chats.(获取指定单聊、群聊的消息历史) +parameters: + - name: container_id + type: string + required: true + label: + en_US: Container Id + zh_Hans: 群聊或单聊的 ID + human_description: + en_US: The ID of the group chat or single chat. Refer to the group ID description for how to obtain it. https://open.feishu.cn/document/server-docs/group/chat/chat-id-description + zh_Hans: 群聊或单聊的 ID,获取方式参见群 ID 说明。https://open.feishu.cn/document/server-docs/group/chat/chat-id-description + llm_description: 群聊或单聊的 ID,获取方式参见群 ID 说明。https://open.feishu.cn/document/server-docs/group/chat/chat-id-description + form: llm + + - name: start_time + type: string + required: false + label: + en_US: Start Time + zh_Hans: 起始时间 + human_description: + en_US: The start time for querying historical messages, formatted as "2006-01-02 15:04:05". + zh_Hans: 待查询历史信息的起始时间,格式为 "2006-01-02 15:04:05"。 + llm_description: 待查询历史信息的起始时间,格式为 "2006-01-02 15:04:05"。 + form: llm + + - name: end_time + type: string + required: false + label: + en_US: End Time + zh_Hans: 结束时间 + human_description: + en_US: The end time for querying historical messages, formatted as "2006-01-02 15:04:05". + zh_Hans: 待查询历史信息的结束时间,格式为 "2006-01-02 15:04:05"。 + llm_description: 待查询历史信息的结束时间,格式为 "2006-01-02 15:04:05"。 + form: llm + + - name: sort_type + type: select + required: false + options: + - value: ByCreateTimeAsc + label: + en_US: ByCreateTimeAsc + zh_Hans: ByCreateTimeAsc + - value: ByCreateTimeDesc + label: + en_US: ByCreateTimeDesc + zh_Hans: ByCreateTimeDesc + default: "ByCreateTimeAsc" + label: + en_US: Sort Type + zh_Hans: 排序方式 + human_description: + en_US: | + The message sorting method. Optional values are ByCreateTimeAsc: sorted in ascending order by message creation time; ByCreateTimeDesc: sorted in descending order by message creation time. The default value is ByCreateTimeAsc. Note: When using page_token for pagination requests, the sorting method (sort_type) is consistent with the first request and cannot be changed midway. + zh_Hans: | + 消息排序方式,可选值有 ByCreateTimeAsc:按消息创建时间升序排列;ByCreateTimeDesc:按消息创建时间降序排列。默认值为:ByCreateTimeAsc。注意:使用 page_token 分页请求时,排序方式(sort_type)均与第一次请求一致,不支持中途改换排序方式。 + llm_description: 消息排序方式,可选值有 ByCreateTimeAsc:按消息创建时间升序排列;ByCreateTimeDesc:按消息创建时间降序排列。默认值为:ByCreateTimeAsc。注意:使用 page_token 分页请求时,排序方式(sort_type)均与第一次请求一致,不支持中途改换排序方式。 + form: form + + - name: page_size + type: number + required: false + default: 20 + label: + en_US: Page Size + zh_Hans: 分页大小 + human_description: + en_US: The page size, i.e., the number of data entries returned in a single request. The default value is 20, and the value range is [1,50]. + zh_Hans: 分页大小,即单次请求所返回的数据条目数。默认值为 20,取值范围为 [1,50]。 + llm_description: 分页大小,即单次请求所返回的数据条目数。默认值为 20,取值范围为 [1,50]。 + form: llm + + - name: page_token + type: string + required: false + label: + en_US: Page Token + zh_Hans: 分页标记 + human_description: + en_US: The pagination token. Leave it blank for the first request, indicating to start traversing from the beginning; when the pagination query result has more items, a new page_token will be returned simultaneously, which can be used to obtain the query result in the next traversal. + zh_Hans: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。 + llm_description: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_message/tools/get_thread_messages.py b/api/core/tools/provider/builtin/feishu_message/tools/get_thread_messages.py new file mode 100644 index 0000000000..3b14f46e00 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_message/tools/get_thread_messages.py @@ -0,0 +1,21 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class GetChatMessagesTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + container_id = tool_parameters.get("container_id") + page_token = tool_parameters.get("page_token") + sort_type = tool_parameters.get("sort_type", "ByCreateTimeAsc") + page_size = tool_parameters.get("page_size", 20) + + res = client.get_thread_messages(container_id, page_token, sort_type, page_size) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_message/tools/get_thread_messages.yaml b/api/core/tools/provider/builtin/feishu_message/tools/get_thread_messages.yaml new file mode 100644 index 0000000000..8d5fed9d0b --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_message/tools/get_thread_messages.yaml @@ -0,0 +1,72 @@ +identity: + name: get_thread_messages + author: Doug Lea + label: + en_US: Get Thread Messages + zh_Hans: 获取指定话题的消息历史 +description: + human: + en_US: Get Thread Messages + zh_Hans: 获取指定话题的消息历史 + llm: A tool for getting chat messages from specific threads.(获取指定话题的消息历史) +parameters: + - name: container_id + type: string + required: true + label: + en_US: Thread Id + zh_Hans: 话题 ID + human_description: + en_US: The ID of the thread. Refer to the thread overview on how to obtain the thread_id. https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/thread-introduction + zh_Hans: 话题 ID,获取方式参见话题概述的如何获取 thread_id 章节。https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/thread-introduction + llm_description: 话题 ID,获取方式参见话题概述的如何获取 thread_id 章节。https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/thread-introduction + form: llm + + - name: sort_type + type: select + required: false + options: + - value: ByCreateTimeAsc + label: + en_US: ByCreateTimeAsc + zh_Hans: ByCreateTimeAsc + - value: ByCreateTimeDesc + label: + en_US: ByCreateTimeDesc + zh_Hans: ByCreateTimeDesc + default: "ByCreateTimeAsc" + label: + en_US: Sort Type + zh_Hans: 排序方式 + human_description: + en_US: | + The message sorting method. Optional values are ByCreateTimeAsc: sorted in ascending order by message creation time; ByCreateTimeDesc: sorted in descending order by message creation time. The default value is ByCreateTimeAsc. Note: When using page_token for pagination requests, the sorting method (sort_type) is consistent with the first request and cannot be changed midway. + zh_Hans: | + 消息排序方式,可选值有 ByCreateTimeAsc:按消息创建时间升序排列;ByCreateTimeDesc:按消息创建时间降序排列。默认值为:ByCreateTimeAsc。注意:使用 page_token 分页请求时,排序方式(sort_type)均与第一次请求一致,不支持中途改换排序方式。 + llm_description: 消息排序方式,可选值有 ByCreateTimeAsc:按消息创建时间升序排列;ByCreateTimeDesc:按消息创建时间降序排列。默认值为:ByCreateTimeAsc。注意:使用 page_token 分页请求时,排序方式(sort_type)均与第一次请求一致,不支持中途改换排序方式。 + form: form + + - name: page_size + type: number + required: false + default: 20 + label: + en_US: Page Size + zh_Hans: 分页大小 + human_description: + en_US: The page size, i.e., the number of data entries returned in a single request. The default value is 20, and the value range is [1,50]. + zh_Hans: 分页大小,即单次请求所返回的数据条目数。默认值为 20,取值范围为 [1,50]。 + llm_description: 分页大小,即单次请求所返回的数据条目数。默认值为 20,取值范围为 [1,50]。 + form: llm + + - name: page_token + type: string + required: false + label: + en_US: Page Token + zh_Hans: 分页标记 + human_description: + en_US: The pagination token. Leave it blank for the first request, indicating to start traversing from the beginning; when the pagination query result has more items, a new page_token will be returned simultaneously, which can be used to obtain the query result in the next traversal. + zh_Hans: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。 + llm_description: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_message/tools/send_bot_message.yaml b/api/core/tools/provider/builtin/feishu_message/tools/send_bot_message.yaml index 6e398b18ab..4f7f65a8a7 100644 --- a/api/core/tools/provider/builtin/feishu_message/tools/send_bot_message.yaml +++ b/api/core/tools/provider/builtin/feishu_message/tools/send_bot_message.yaml @@ -10,53 +10,53 @@ description: zh_Hans: 发送飞书应用消息 llm: A tool for sending Feishu application messages. parameters: + - name: receive_id + type: string + required: true + label: + en_US: receive_id + zh_Hans: 消息接收者的 ID + human_description: + en_US: The ID of the message receiver, the ID type is consistent with the value of the query parameter receive_id_type. + zh_Hans: 消息接收者的 ID,ID 类型与查询参数 receive_id_type 的取值一致。 + llm_description: 消息接收者的 ID,ID 类型与查询参数 receive_id_type 的取值一致。 + form: llm + - name: receive_id_type type: select required: true options: - value: open_id label: - en_US: open id - zh_Hans: open id + en_US: open_id + zh_Hans: open_id - value: union_id label: - en_US: union id - zh_Hans: union id + en_US: union_id + zh_Hans: union_id - value: user_id label: - en_US: user id - zh_Hans: user id + en_US: user_id + zh_Hans: user_id - value: email label: en_US: email zh_Hans: email - value: chat_id label: - en_US: chat id - zh_Hans: chat id + en_US: chat_id + zh_Hans: chat_id label: - en_US: User ID Type - zh_Hans: 用户 ID 类型 + en_US: receive_id_type + zh_Hans: 消息接收者的 ID 类型 human_description: - en_US: User ID Type - zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id、email、chat_id。 - llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id、email、chat_id。 - form: llm - - - name: receive_id - type: string - required: true - label: - en_US: Receive Id - zh_Hans: 消息接收者的 ID - human_description: - en_US: The ID of the message receiver. The ID type should correspond to the query parameter receive_id_type. - zh_Hans: 消息接收者的 ID,ID 类型应与查询参数 receive_id_type 对应。 - llm_description: 消息接收者的 ID,ID 类型应与查询参数 receive_id_type 对应。 - form: llm + en_US: The ID type of the message receiver, optional values are open_id, union_id, user_id, email, chat_id, with a default value of open_id. + zh_Hans: 消息接收者的 ID 类型,可选值有 open_id、union_id、user_id、email、chat_id,默认值为 open_id。 + llm_description: 消息接收者的 ID 类型,可选值有 open_id、union_id、user_id、email、chat_id,默认值为 open_id。 + form: form - name: msg_type - type: string + type: select required: true options: - value: text @@ -65,27 +65,61 @@ parameters: zh_Hans: 文本 - value: interactive label: - en_US: message card - zh_Hans: 消息卡片 + en_US: interactive + zh_Hans: 卡片 + - value: post + label: + en_US: post + zh_Hans: 富文本 + - value: image + label: + en_US: image + zh_Hans: 图片 + - value: file + label: + en_US: file + zh_Hans: 文件 + - value: audio + label: + en_US: audio + zh_Hans: 语音 + - value: media + label: + en_US: media + zh_Hans: 视频 + - value: sticker + label: + en_US: sticker + zh_Hans: 表情包 + - value: share_chat + label: + en_US: share_chat + zh_Hans: 分享群名片 + - value: share_user + label: + en_US: share_user + zh_Hans: 分享个人名片 + - value: system + label: + en_US: system + zh_Hans: 系统消息 label: - en_US: Message type + en_US: msg_type zh_Hans: 消息类型 human_description: - en_US: Message type, optional values are, text (text), interactive (message card). - zh_Hans: 消息类型,可选值有:text(文本)、interactive(消息卡片)。 - llm_description: 消息类型,可选值有:text(文本)、interactive(消息卡片)。 - form: llm + en_US: Message type. Optional values are text, post, image, file, audio, media, sticker, interactive, share_chat, share_user, system. For detailed introduction of different message types, refer to the message content(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json). + zh_Hans: 消息类型。可选值有:text、post、image、file、audio、media、sticker、interactive、share_chat、share_user、system。不同消息类型的详细介绍,参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。 + llm_description: 消息类型。可选值有:text、post、image、file、audio、media、sticker、interactive、share_chat、share_user、system。不同消息类型的详细介绍,参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。 + form: form - name: content type: string required: true label: - en_US: Message content + en_US: content zh_Hans: 消息内容 human_description: - en_US: Message content - zh_Hans: | - 消息内容,JSON 结构序列化后的字符串。不同 msg_type 对应不同内容, - 具体格式说明参考:https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json - llm_description: 消息内容,JSON 结构序列化后的字符串。不同 msg_type 对应不同内容。 + en_US: Message content, a JSON structure serialized string. The value of this parameter corresponds to msg_type. For example, if msg_type is text, this parameter needs to pass in text type content. To understand the format and usage limitations of different message types, refer to the message content(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json). + zh_Hans: 消息内容,JSON 结构序列化后的字符串。该参数的取值与 msg_type 对应,例如 msg_type 取值为 text,则该参数需要传入文本类型的内容。了解不同类型的消息内容格式、使用限制,可参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。 + llm_description: 消息内容,JSON 结构序列化后的字符串。该参数的取值与 msg_type 对应,例如 msg_type 取值为 text,则该参数需要传入文本类型的内容。了解不同类型的消息内容格式、使用限制,可参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。 form: llm diff --git a/api/core/tools/provider/builtin/feishu_message/tools/send_webhook_message.yaml b/api/core/tools/provider/builtin/feishu_message/tools/send_webhook_message.yaml index 8b39ce4874..eeeae8b29c 100644 --- a/api/core/tools/provider/builtin/feishu_message/tools/send_webhook_message.yaml +++ b/api/core/tools/provider/builtin/feishu_message/tools/send_webhook_message.yaml @@ -15,15 +15,18 @@ parameters: required: true label: en_US: webhook - zh_Hans: webhook 的地址 + zh_Hans: webhook human_description: - en_US: The address of the webhook - zh_Hans: webhook 的地址 - llm_description: webhook 的地址 + en_US: | + The address of the webhook, the format of the webhook address corresponding to the bot is as follows: https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxxx. For details, please refer to: Feishu Custom Bot Usage Guide(https://open.larkoffice.com/document/client-docs/bot-v3/add-custom-bot) + zh_Hans: | + webhook 的地址,机器人对应的 webhook 地址格式如下: https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxxx,详情可参考: 飞书自定义机器人使用指南(https://open.larkoffice.com/document/client-docs/bot-v3/add-custom-bot) + llm_description: | + webhook 的地址,机器人对应的 webhook 地址格式如下: https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxxx,详情可参考: 飞书自定义机器人使用指南(https://open.larkoffice.com/document/client-docs/bot-v3/add-custom-bot) form: llm - name: msg_type - type: string + type: select required: true options: - value: text @@ -32,27 +35,34 @@ parameters: zh_Hans: 文本 - value: interactive label: - en_US: message card - zh_Hans: 消息卡片 + en_US: interactive + zh_Hans: 卡片 + - value: image + label: + en_US: image + zh_Hans: 图片 + - value: share_chat + label: + en_US: share_chat + zh_Hans: 分享群名片 label: - en_US: Message type + en_US: msg_type zh_Hans: 消息类型 human_description: - en_US: Message type, optional values are, text (text), interactive (message card). - zh_Hans: 消息类型,可选值有:text(文本)、interactive(消息卡片)。 - llm_description: 消息类型,可选值有:text(文本)、interactive(消息卡片)。 - form: llm + en_US: Message type. Optional values are text, image, interactive, share_chat. For detailed introduction of different message types, refer to the message content(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json). + zh_Hans: 消息类型。可选值有:text、image、interactive、share_chat。不同消息类型的详细介绍,参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。 + llm_description: 消息类型。可选值有:text、image、interactive、share_chat。不同消息类型的详细介绍,参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。 + form: form + - name: content type: string required: true label: - en_US: Message content + en_US: content zh_Hans: 消息内容 human_description: - en_US: Message content - zh_Hans: | - 消息内容,JSON 结构序列化后的字符串。不同 msg_type 对应不同内容, - 具体格式说明参考:https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json - llm_description: 消息内容,JSON 结构序列化后的字符串。不同 msg_type 对应不同内容。 + en_US: Message content, a JSON structure serialized string. The value of this parameter corresponds to msg_type. For example, if msg_type is text, this parameter needs to pass in text type content. To understand the format and usage limitations of different message types, refer to the message content(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json). + zh_Hans: 消息内容,JSON 结构序列化后的字符串。该参数的取值与 msg_type 对应,例如 msg_type 取值为 text,则该参数需要传入文本类型的内容。了解不同类型的消息内容格式、使用限制,可参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。 + llm_description: 消息内容,JSON 结构序列化后的字符串。该参数的取值与 msg_type 对应,例如 msg_type 取值为 text,则该参数需要传入文本类型的内容。了解不同类型的消息内容格式、使用限制,可参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。 form: llm diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/_assets/icon.png b/api/core/tools/provider/builtin/feishu_spreadsheet/_assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..258b361261d4e3366251613141efaf200cd492db GIT binary patch literal 5417 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 e^8bzLQ2*ztuUWBv%zNP5C*%^w(uiz`yZ None: + auth(credentials) diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/feishu_spreadsheet.yaml b/api/core/tools/provider/builtin/feishu_spreadsheet/feishu_spreadsheet.yaml new file mode 100644 index 0000000000..29e448d730 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/feishu_spreadsheet.yaml @@ -0,0 +1,36 @@ +identity: + author: Doug Lea + name: feishu_spreadsheet + label: + en_US: Feishu Spreadsheet + zh_Hans: 飞书电子表格 + description: + en_US: | + Feishu Spreadsheet, requires the following permissions: sheets:spreadsheet. + zh_Hans: | + 飞书电子表格,需要开通以下权限: sheets:spreadsheet。 + icon: icon.png + tags: + - social + - productivity +credentials_for_provider: + app_id: + type: text-input + required: true + label: + en_US: APP ID + placeholder: + en_US: Please input your feishu app id + zh_Hans: 请输入你的飞书 app id + help: + en_US: Get your app_id and app_secret from Feishu + zh_Hans: 从飞书获取您的 app_id 和 app_secret + url: https://open.larkoffice.com/app + app_secret: + type: secret-input + required: true + label: + en_US: APP Secret + placeholder: + en_US: Please input your app secret + zh_Hans: 请输入你的飞书 app secret diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_cols.py b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_cols.py new file mode 100644 index 0000000000..44d062f9bd --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_cols.py @@ -0,0 +1,22 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class AddColsTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + spreadsheet_token = tool_parameters.get("spreadsheet_token") + sheet_id = tool_parameters.get("sheet_id") + sheet_name = tool_parameters.get("sheet_name") + length = tool_parameters.get("length") + values = tool_parameters.get("values") + + res = client.add_cols(spreadsheet_token, sheet_id, sheet_name, length, values) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_cols.yaml b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_cols.yaml new file mode 100644 index 0000000000..ef457f8e00 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_cols.yaml @@ -0,0 +1,72 @@ +identity: + name: add_cols + author: Doug Lea + label: + en_US: Add Cols + zh_Hans: 新增多列至工作表最后 +description: + human: + en_US: Add Cols + zh_Hans: 新增多列至工作表最后 + llm: A tool for adding multiple columns to the end of a spreadsheet. (新增多列至工作表最后) +parameters: + - name: spreadsheet_token + type: string + required: true + label: + en_US: spreadsheet_token + zh_Hans: 电子表格 token + human_description: + en_US: Spreadsheet token, supports input of spreadsheet URL. + zh_Hans: 电子表格 token,支持输入电子表格 url。 + llm_description: 电子表格 token,支持输入电子表格 url。 + form: llm + + - name: sheet_id + type: string + required: false + label: + en_US: sheet_id + zh_Hans: 工作表 ID + human_description: + en_US: Sheet ID, either sheet_id or sheet_name must be filled. + zh_Hans: 工作表 ID,与 sheet_name 二者其一必填。 + llm_description: 工作表 ID,与 sheet_name 二者其一必填。 + form: llm + + - name: sheet_name + type: string + required: false + label: + en_US: sheet_name + zh_Hans: 工作表名称 + human_description: + en_US: Sheet name, either sheet_id or sheet_name must be filled. + zh_Hans: 工作表名称,与 sheet_id 二者其一必填。 + llm_description: 工作表名称,与 sheet_id 二者其一必填。 + form: llm + + - name: length + type: number + required: true + label: + en_US: length + zh_Hans: 要增加的列数 + human_description: + en_US: Number of columns to add, range (0-5000]. + zh_Hans: 要增加的列数,范围(0-5000]。 + llm_description: 要增加的列数,范围(0-5000]。 + form: llm + + - name: values + type: string + required: false + label: + en_US: values + zh_Hans: 新增列的单元格内容 + human_description: + en_US: | + Content of the new columns, array of objects in string format, each array represents a row of table data, format like: [ [ "ID","Name","Age" ],[ 1,"Zhang San",10 ],[ 2,"Li Si",11 ] ]. + zh_Hans: 新增列的单元格内容,数组对象字符串,每个数组一行表格数据,格式:[["编号","姓名","年龄"],[1,"张三",10],[2,"李四",11]]。 + llm_description: 新增列的单元格内容,数组对象字符串,每个数组一行表格数据,格式:[["编号","姓名","年龄"],[1,"张三",10],[2,"李四",11]]。 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_rows.py b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_rows.py new file mode 100644 index 0000000000..3a85b7b46c --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_rows.py @@ -0,0 +1,22 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class AddRowsTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + spreadsheet_token = tool_parameters.get("spreadsheet_token") + sheet_id = tool_parameters.get("sheet_id") + sheet_name = tool_parameters.get("sheet_name") + length = tool_parameters.get("length") + values = tool_parameters.get("values") + + res = client.add_rows(spreadsheet_token, sheet_id, sheet_name, length, values) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_rows.yaml b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_rows.yaml new file mode 100644 index 0000000000..37653325ae --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_rows.yaml @@ -0,0 +1,72 @@ +identity: + name: add_rows + author: Doug Lea + label: + en_US: Add Rows + zh_Hans: 新增多行至工作表最后 +description: + human: + en_US: Add Rows + zh_Hans: 新增多行至工作表最后 + llm: A tool for adding multiple rows to the end of a spreadsheet. (新增多行至工作表最后) +parameters: + - name: spreadsheet_token + type: string + required: true + label: + en_US: spreadsheet_token + zh_Hans: 电子表格 token + human_description: + en_US: Spreadsheet token, supports input of spreadsheet URL. + zh_Hans: 电子表格 token,支持输入电子表格 url。 + llm_description: 电子表格 token,支持输入电子表格 url。 + form: llm + + - name: sheet_id + type: string + required: false + label: + en_US: sheet_id + zh_Hans: 工作表 ID + human_description: + en_US: Sheet ID, either sheet_id or sheet_name must be filled. + zh_Hans: 工作表 ID,与 sheet_name 二者其一必填。 + llm_description: 工作表 ID,与 sheet_name 二者其一必填。 + form: llm + + - name: sheet_name + type: string + required: false + label: + en_US: sheet_name + zh_Hans: 工作表名称 + human_description: + en_US: Sheet name, either sheet_id or sheet_name must be filled. + zh_Hans: 工作表名称,与 sheet_id 二者其一必填。 + llm_description: 工作表名称,与 sheet_id 二者其一必填。 + form: llm + + - name: length + type: number + required: true + label: + en_US: length + zh_Hans: 要增加行数 + human_description: + en_US: Number of rows to add, range (0-5000]. + zh_Hans: 要增加行数,范围(0-5000]。 + llm_description: 要增加行数,范围(0-5000]。 + form: llm + + - name: values + type: string + required: false + label: + en_US: values + zh_Hans: 新增行的表格内容 + human_description: + en_US: | + Content of the new rows, array of objects in string format, each array represents a row of table data, format like: [ [ "ID","Name","Age" ],[ 1,"Zhang San",10 ],[ 2,"Li Si",11 ] ]. + zh_Hans: 新增行的表格内容,数组对象字符串,每个数组一行表格数据,格式,如:[["编号","姓名","年龄"],[1,"张三",10],[2,"李四",11]]。 + llm_description: 新增行的表格内容,数组对象字符串,每个数组一行表格数据,格式,如:[["编号","姓名","年龄"],[1,"张三",10],[2,"李四",11]]。 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/create_spreadsheet.py b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/create_spreadsheet.py new file mode 100644 index 0000000000..647364fab0 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/create_spreadsheet.py @@ -0,0 +1,19 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class CreateSpreadsheetTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + title = tool_parameters.get("title") + folder_token = tool_parameters.get("folder_token") + + res = client.create_spreadsheet(title, folder_token) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/create_spreadsheet.yaml b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/create_spreadsheet.yaml new file mode 100644 index 0000000000..931310e631 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/create_spreadsheet.yaml @@ -0,0 +1,35 @@ +identity: + name: create_spreadsheet + author: Doug Lea + label: + en_US: Create Spreadsheet + zh_Hans: 创建电子表格 +description: + human: + en_US: Create Spreadsheet + zh_Hans: 创建电子表格 + llm: A tool for creating spreadsheets. (创建电子表格) +parameters: + - name: title + type: string + required: false + label: + en_US: Spreadsheet Title + zh_Hans: 电子表格标题 + human_description: + en_US: The title of the spreadsheet + zh_Hans: 电子表格的标题 + llm_description: 电子表格的标题 + form: llm + + - name: folder_token + type: string + required: false + label: + en_US: Folder Token + zh_Hans: 文件夹 token + human_description: + en_US: The token of the folder, supports folder URL input, e.g., https://bytedance.larkoffice.com/drive/folder/CxHEf4DCSlNkL2dUTCJcPRgentg + zh_Hans: 文件夹 token,支持文件夹 URL 输入,如:https://bytedance.larkoffice.com/drive/folder/CxHEf4DCSlNkL2dUTCJcPRgentg + llm_description: 文件夹 token,支持文件夹 URL 输入,如:https://bytedance.larkoffice.com/drive/folder/CxHEf4DCSlNkL2dUTCJcPRgentg + form: llm diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/get_spreadsheet.py b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/get_spreadsheet.py new file mode 100644 index 0000000000..dda8c59daf --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/get_spreadsheet.py @@ -0,0 +1,19 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class GetSpreadsheetTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + spreadsheet_token = tool_parameters.get("spreadsheet_token") + user_id_type = tool_parameters.get("user_id_type", "open_id") + + res = client.get_spreadsheet(spreadsheet_token, user_id_type) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/get_spreadsheet.yaml b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/get_spreadsheet.yaml new file mode 100644 index 0000000000..c519938617 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/get_spreadsheet.yaml @@ -0,0 +1,49 @@ +identity: + name: get_spreadsheet + author: Doug Lea + label: + en_US: Get Spreadsheet + zh_Hans: 获取电子表格信息 +description: + human: + en_US: Get Spreadsheet + zh_Hans: 获取电子表格信息 + llm: A tool for getting information from spreadsheets. (获取电子表格信息) +parameters: + - name: spreadsheet_token + type: string + required: true + label: + en_US: Spreadsheet Token + zh_Hans: 电子表格 token + human_description: + en_US: Spreadsheet token, supports input of spreadsheet URL. + zh_Hans: 电子表格 token,支持输入电子表格 URL。 + llm_description: 电子表格 token,支持输入电子表格 URL。 + form: llm + + - name: user_id_type + type: select + required: false + options: + - value: open_id + label: + en_US: open_id + zh_Hans: open_id + - value: union_id + label: + en_US: union_id + zh_Hans: union_id + - value: user_id + label: + en_US: user_id + zh_Hans: user_id + default: "open_id" + label: + en_US: user_id_type + zh_Hans: 用户 ID 类型 + human_description: + en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id. + zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 + llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 + form: form diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/list_spreadsheet_sheets.py b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/list_spreadsheet_sheets.py new file mode 100644 index 0000000000..98497791c0 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/list_spreadsheet_sheets.py @@ -0,0 +1,18 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class ListSpreadsheetSheetsTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + spreadsheet_token = tool_parameters.get("spreadsheet_token") + + res = client.list_spreadsheet_sheets(spreadsheet_token) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/list_spreadsheet_sheets.yaml b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/list_spreadsheet_sheets.yaml new file mode 100644 index 0000000000..c6a7ef45d4 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/list_spreadsheet_sheets.yaml @@ -0,0 +1,23 @@ +identity: + name: list_spreadsheet_sheets + author: Doug Lea + label: + en_US: List Spreadsheet Sheets + zh_Hans: 列出电子表格所有工作表 +description: + human: + en_US: List Spreadsheet Sheets + zh_Hans: 列出电子表格所有工作表 + llm: A tool for listing all sheets in a spreadsheet. (列出电子表格所有工作表) +parameters: + - name: spreadsheet_token + type: string + required: true + label: + en_US: Spreadsheet Token + zh_Hans: 电子表格 token + human_description: + en_US: Spreadsheet token, supports input of spreadsheet URL. + zh_Hans: 电子表格 token,支持输入电子表格 URL。 + llm_description: 电子表格 token,支持输入电子表格 URL。 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_cols.py b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_cols.py new file mode 100644 index 0000000000..ebe3f619d0 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_cols.py @@ -0,0 +1,23 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class ReadColsTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + spreadsheet_token = tool_parameters.get("spreadsheet_token") + sheet_id = tool_parameters.get("sheet_id") + sheet_name = tool_parameters.get("sheet_name") + start_col = tool_parameters.get("start_col") + num_cols = tool_parameters.get("num_cols") + user_id_type = tool_parameters.get("user_id_type", "open_id") + + res = client.read_cols(spreadsheet_token, sheet_id, sheet_name, start_col, num_cols, user_id_type) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_cols.yaml b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_cols.yaml new file mode 100644 index 0000000000..3273857b70 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_cols.yaml @@ -0,0 +1,97 @@ +identity: + name: read_cols + author: Doug Lea + label: + en_US: Read Cols + zh_Hans: 读取工作表列数据 +description: + human: + en_US: Read Cols + zh_Hans: 读取工作表列数据 + llm: A tool for reading column data from a spreadsheet. (读取工作表列数据) +parameters: + - name: spreadsheet_token + type: string + required: true + label: + en_US: spreadsheet_token + zh_Hans: 电子表格 token + human_description: + en_US: Spreadsheet token, supports input of spreadsheet URL. + zh_Hans: 电子表格 token,支持输入电子表格 url。 + llm_description: 电子表格 token,支持输入电子表格 url。 + form: llm + + - name: sheet_id + type: string + required: false + label: + en_US: sheet_id + zh_Hans: 工作表 ID + human_description: + en_US: Sheet ID, either sheet_id or sheet_name must be filled. + zh_Hans: 工作表 ID,与 sheet_name 二者其一必填。 + llm_description: 工作表 ID,与 sheet_name 二者其一必填。 + form: llm + + - name: sheet_name + type: string + required: false + label: + en_US: sheet_name + zh_Hans: 工作表名称 + human_description: + en_US: Sheet name, either sheet_id or sheet_name must be filled. + zh_Hans: 工作表名称,与 sheet_id 二者其一必填。 + llm_description: 工作表名称,与 sheet_id 二者其一必填。 + form: llm + + - name: user_id_type + type: select + required: false + options: + - value: open_id + label: + en_US: open_id + zh_Hans: open_id + - value: union_id + label: + en_US: union_id + zh_Hans: union_id + - value: user_id + label: + en_US: user_id + zh_Hans: user_id + default: "open_id" + label: + en_US: user_id_type + zh_Hans: 用户 ID 类型 + human_description: + en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id. + zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 + llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 + form: form + + - name: start_col + type: number + required: false + label: + en_US: start_col + zh_Hans: 起始列号 + human_description: + en_US: Starting column number, starting from 1. + zh_Hans: 起始列号,从 1 开始。 + llm_description: 起始列号,从 1 开始。 + form: llm + + - name: num_cols + type: number + required: true + label: + en_US: num_cols + zh_Hans: 读取列数 + human_description: + en_US: Number of columns to read. + zh_Hans: 读取列数 + llm_description: 读取列数 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_rows.py b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_rows.py new file mode 100644 index 0000000000..86b91b104b --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_rows.py @@ -0,0 +1,23 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class ReadRowsTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + spreadsheet_token = tool_parameters.get("spreadsheet_token") + sheet_id = tool_parameters.get("sheet_id") + sheet_name = tool_parameters.get("sheet_name") + start_row = tool_parameters.get("start_row") + num_rows = tool_parameters.get("num_rows") + user_id_type = tool_parameters.get("user_id_type", "open_id") + + res = client.read_rows(spreadsheet_token, sheet_id, sheet_name, start_row, num_rows, user_id_type) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_rows.yaml b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_rows.yaml new file mode 100644 index 0000000000..3e9206e8ef --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_rows.yaml @@ -0,0 +1,97 @@ +identity: + name: read_rows + author: Doug Lea + label: + en_US: Read Rows + zh_Hans: 读取工作表行数据 +description: + human: + en_US: Read Rows + zh_Hans: 读取工作表行数据 + llm: A tool for reading row data from a spreadsheet. (读取工作表行数据) +parameters: + - name: spreadsheet_token + type: string + required: true + label: + en_US: spreadsheet_token + zh_Hans: 电子表格 token + human_description: + en_US: Spreadsheet token, supports input of spreadsheet URL. + zh_Hans: 电子表格 token,支持输入电子表格 url。 + llm_description: 电子表格 token,支持输入电子表格 url。 + form: llm + + - name: sheet_id + type: string + required: false + label: + en_US: sheet_id + zh_Hans: 工作表 ID + human_description: + en_US: Sheet ID, either sheet_id or sheet_name must be filled. + zh_Hans: 工作表 ID,与 sheet_name 二者其一必填。 + llm_description: 工作表 ID,与 sheet_name 二者其一必填。 + form: llm + + - name: sheet_name + type: string + required: false + label: + en_US: sheet_name + zh_Hans: 工作表名称 + human_description: + en_US: Sheet name, either sheet_id or sheet_name must be filled. + zh_Hans: 工作表名称,与 sheet_id 二者其一必填。 + llm_description: 工作表名称,与 sheet_id 二者其一必填。 + form: llm + + - name: user_id_type + type: select + required: false + options: + - value: open_id + label: + en_US: open_id + zh_Hans: open_id + - value: union_id + label: + en_US: union_id + zh_Hans: union_id + - value: user_id + label: + en_US: user_id + zh_Hans: user_id + default: "open_id" + label: + en_US: user_id_type + zh_Hans: 用户 ID 类型 + human_description: + en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id. + zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 + llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 + form: form + + - name: start_row + type: number + required: false + label: + en_US: start_row + zh_Hans: 起始行号 + human_description: + en_US: Starting row number, starting from 1. + zh_Hans: 起始行号,从 1 开始。 + llm_description: 起始行号,从 1 开始。 + form: llm + + - name: num_rows + type: number + required: true + label: + en_US: num_rows + zh_Hans: 读取行数 + human_description: + en_US: Number of rows to read. + zh_Hans: 读取行数 + llm_description: 读取行数 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_table.py b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_table.py new file mode 100644 index 0000000000..ddd607d878 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_table.py @@ -0,0 +1,23 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class ReadTableTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + spreadsheet_token = tool_parameters.get("spreadsheet_token") + sheet_id = tool_parameters.get("sheet_id") + sheet_name = tool_parameters.get("sheet_name") + num_range = tool_parameters.get("num_range") + query = tool_parameters.get("query") + user_id_type = tool_parameters.get("user_id_type", "open_id") + + res = client.read_table(spreadsheet_token, sheet_id, sheet_name, num_range, query, user_id_type) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_table.yaml b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_table.yaml new file mode 100644 index 0000000000..e3dc80e1eb --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_table.yaml @@ -0,0 +1,122 @@ +identity: + name: read_table + author: Doug Lea + label: + en_US: Read Table + zh_Hans: 自定义读取电子表格行列数据 +description: + human: + en_US: Read Table + zh_Hans: 自定义读取电子表格行列数据 + llm: A tool for custom reading of row and column data from a spreadsheet. (自定义读取电子表格行列数据) +parameters: + - name: spreadsheet_token + type: string + required: true + label: + en_US: spreadsheet_token + zh_Hans: 电子表格 token + human_description: + en_US: Spreadsheet token, supports input of spreadsheet URL. + zh_Hans: 电子表格 token,支持输入电子表格 url。 + llm_description: 电子表格 token,支持输入电子表格 url。 + form: llm + + - name: sheet_id + type: string + required: false + label: + en_US: sheet_id + zh_Hans: 工作表 ID + human_description: + en_US: Sheet ID, either sheet_id or sheet_name must be filled. + zh_Hans: 工作表 ID,与 sheet_name 二者其一必填。 + llm_description: 工作表 ID,与 sheet_name 二者其一必填。 + form: llm + + - name: sheet_name + type: string + required: false + label: + en_US: sheet_name + zh_Hans: 工作表名称 + human_description: + en_US: Sheet name, either sheet_id or sheet_name must be filled. + zh_Hans: 工作表名称,与 sheet_id 二者其一必填。 + llm_description: 工作表名称,与 sheet_id 二者其一必填。 + form: llm + + - name: user_id_type + type: select + required: false + options: + - value: open_id + label: + en_US: open_id + zh_Hans: open_id + - value: union_id + label: + en_US: union_id + zh_Hans: union_id + - value: user_id + label: + en_US: user_id + zh_Hans: user_id + default: "open_id" + label: + en_US: user_id_type + zh_Hans: 用户 ID 类型 + human_description: + en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id. + zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 + llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。 + form: form + + - name: start_row + type: number + required: false + label: + en_US: start_row + zh_Hans: 起始行号 + human_description: + en_US: Starting row number, starting from 1. + zh_Hans: 起始行号,从 1 开始。 + llm_description: 起始行号,从 1 开始。 + form: llm + + - name: num_rows + type: number + required: false + label: + en_US: num_rows + zh_Hans: 读取行数 + human_description: + en_US: Number of rows to read. + zh_Hans: 读取行数 + llm_description: 读取行数 + form: llm + + - name: range + type: string + required: false + label: + en_US: range + zh_Hans: 取数范围 + human_description: + en_US: | + Data range, format like: A1:B2, can be empty when query=all. + zh_Hans: 取数范围,格式如:A1:B2,query=all 时可为空。 + llm_description: 取数范围,格式如:A1:B2,query=all 时可为空。 + form: llm + + - name: query + type: string + required: false + label: + en_US: query + zh_Hans: 查询 + human_description: + en_US: Pass "all" to query all data in the table, but no more than 100 columns. + zh_Hans: 传 all,表示查询表格所有数据,但最多查询 100 列数据。 + llm_description: 传 all,表示查询表格所有数据,但最多查询 100 列数据。 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_task/_assets/icon.png b/api/core/tools/provider/builtin/feishu_task/_assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3485be0d0fbd85444995dca78b51634899807537 GIT binary patch literal 3917 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 literal 0 HcmV?d00001 diff --git a/api/core/tools/provider/builtin/feishu_task/feishu_task.py b/api/core/tools/provider/builtin/feishu_task/feishu_task.py new file mode 100644 index 0000000000..6df05968d8 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_task/feishu_task.py @@ -0,0 +1,7 @@ +from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController +from core.tools.utils.feishu_api_utils import auth + + +class FeishuTaskProvider(BuiltinToolProviderController): + def _validate_credentials(self, credentials: dict) -> None: + auth(credentials) diff --git a/api/core/tools/provider/builtin/feishu_task/feishu_task.yaml b/api/core/tools/provider/builtin/feishu_task/feishu_task.yaml new file mode 100644 index 0000000000..88736f79a0 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_task/feishu_task.yaml @@ -0,0 +1,36 @@ +identity: + author: Doug Lea + name: feishu_task + label: + en_US: Feishu Task + zh_Hans: 飞书任务 + description: + en_US: | + Feishu Task, requires the following permissions: task:task:write、contact:user.id:readonly. + zh_Hans: | + 飞书任务,需要开通以下权限: task:task:write、contact:user.id:readonly。 + icon: icon.png + tags: + - social + - productivity +credentials_for_provider: + app_id: + type: text-input + required: true + label: + en_US: APP ID + placeholder: + en_US: Please input your feishu app id + zh_Hans: 请输入你的飞书 app id + help: + en_US: Get your app_id and app_secret from Feishu + zh_Hans: 从飞书获取您的 app_id 和 app_secret + url: https://open.larkoffice.com/app + app_secret: + type: secret-input + required: true + label: + en_US: APP Secret + placeholder: + en_US: Please input your app secret + zh_Hans: 请输入你的飞书 app secret diff --git a/api/core/tools/provider/builtin/feishu_task/tools/add_members.py b/api/core/tools/provider/builtin/feishu_task/tools/add_members.py new file mode 100644 index 0000000000..e58ed22e0f --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_task/tools/add_members.py @@ -0,0 +1,20 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class AddMembersTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + task_guid = tool_parameters.get("task_guid") + member_phone_or_email = tool_parameters.get("member_phone_or_email") + member_role = tool_parameters.get("member_role", "follower") + + res = client.add_members(task_guid, member_phone_or_email, member_role) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_task/tools/add_members.yaml b/api/core/tools/provider/builtin/feishu_task/tools/add_members.yaml new file mode 100644 index 0000000000..063c0f7f04 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_task/tools/add_members.yaml @@ -0,0 +1,58 @@ +identity: + name: add_members + author: Doug Lea + label: + en_US: Add Members + zh_Hans: 添加任务成员 +description: + human: + en_US: Add Members + zh_Hans: 添加任务成员 + llm: A tool for adding members to a Feishu task.(添加任务成员) +parameters: + - name: task_guid + type: string + required: true + label: + en_US: Task GUID + zh_Hans: 任务 GUID + human_description: + en_US: | + The GUID of the task to be added, supports passing either the Task ID or the Task link URL. Example of Task ID: 8b5425ec-9f2a-43bd-a3ab-01912f50282b; Example of Task link URL: https://applink.feishu-pre.net/client/todo/detail?guid=8c6bf822-e4da-449a-b82a-dc44020f9be9&suite_entity_num=t21587362 + zh_Hans: 要添加的任务的 GUID,支持传任务 ID 和任务链接 URL。任务 ID 示例:8b5425ec-9f2a-43bd-a3ab-01912f50282b;任务链接 URL 示例:https://applink.feishu-pre.net/client/todo/detail?guid=8c6bf822-e4da-449a-b82a-dc44020f9be9&suite_entity_num=t21587362 + llm_description: 要添加的任务的 GUID,支持传任务 ID 和任务链接 URL。任务 ID 示例:8b5425ec-9f2a-43bd-a3ab-01912f50282b;任务链接 URL 示例:https://applink.feishu-pre.net/client/todo/detail?guid=8c6bf822-e4da-449a-b82a-dc44020f9be9&suite_entity_num=t21587362 + form: llm + + - name: member_phone_or_email + type: string + required: true + label: + en_US: Task Member Phone Or Email + zh_Hans: 任务成员的电话或邮箱 + human_description: + en_US: A list of member emails or phone numbers, separated by commas. + zh_Hans: 任务成员邮箱或者手机号列表,使用逗号分隔。 + llm_description: 任务成员邮箱或者手机号列表,使用逗号分隔。 + form: llm + + - name: member_role + type: select + required: true + options: + - value: assignee + label: + en_US: assignee + zh_Hans: 负责人 + - value: follower + label: + en_US: follower + zh_Hans: 关注人 + default: "follower" + label: + en_US: member_role + zh_Hans: 成员的角色 + human_description: + en_US: Member role, optional values are "assignee" (responsible person) and "follower" (observer), with a default value of "assignee". + zh_Hans: 成员的角色,可选值有 "assignee"(负责人)和 "follower"(关注人),默认值为 "assignee"。 + llm_description: 成员的角色,可选值有 "assignee"(负责人)和 "follower"(关注人),默认值为 "assignee"。 + form: form diff --git a/api/core/tools/provider/builtin/feishu_task/tools/create_task.py b/api/core/tools/provider/builtin/feishu_task/tools/create_task.py new file mode 100644 index 0000000000..96cdcd71f6 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_task/tools/create_task.py @@ -0,0 +1,22 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class CreateTaskTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + summary = tool_parameters.get("summary") + start_time = tool_parameters.get("start_time") + end_time = tool_parameters.get("end_time") + completed_time = tool_parameters.get("completed_time") + description = tool_parameters.get("description") + + res = client.create_task(summary, start_time, end_time, completed_time, description) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_task/tools/create_task.yaml b/api/core/tools/provider/builtin/feishu_task/tools/create_task.yaml new file mode 100644 index 0000000000..7eb4af168b --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_task/tools/create_task.yaml @@ -0,0 +1,74 @@ +identity: + name: create_task + author: Doug Lea + label: + en_US: Create Task + zh_Hans: 创建飞书任务 +description: + human: + en_US: Create Feishu Task + zh_Hans: 创建飞书任务 + llm: A tool for creating tasks in Feishu.(创建飞书任务) +parameters: + - name: summary + type: string + required: true + label: + en_US: Task Title + zh_Hans: 任务标题 + human_description: + en_US: The title of the task. + zh_Hans: 任务标题 + llm_description: 任务标题 + form: llm + + - name: description + type: string + required: false + label: + en_US: Task Description + zh_Hans: 任务备注 + human_description: + en_US: The description or notes for the task. + zh_Hans: 任务备注 + llm_description: 任务备注 + form: llm + + - name: start_time + type: string + required: false + label: + en_US: Start Time + zh_Hans: 任务开始时间 + human_description: + en_US: | + The start time of the task, in the format: 2006-01-02 15:04:05 + zh_Hans: 任务开始时间,格式为:2006-01-02 15:04:05 + llm_description: 任务开始时间,格式为:2006-01-02 15:04:05 + form: llm + + - name: end_time + type: string + required: false + label: + en_US: End Time + zh_Hans: 任务结束时间 + human_description: + en_US: | + The end time of the task, in the format: 2006-01-02 15:04:05 + zh_Hans: 任务结束时间,格式为:2006-01-02 15:04:05 + llm_description: 任务结束时间,格式为:2006-01-02 15:04:05 + form: llm + + - name: completed_time + type: string + required: false + label: + en_US: Completed Time + zh_Hans: 任务完成时间 + human_description: + en_US: | + The completion time of the task, in the format: 2006-01-02 15:04:05. Leave empty to create an incomplete task; fill in a specific time to create a completed task. + zh_Hans: 任务完成时间,格式为:2006-01-02 15:04:05,不填写表示创建一个未完成任务;填写一个具体的时间表示创建一个已完成任务。 + llm_description: 任务完成时间,格式为:2006-01-02 15:04:05,不填写表示创建一个未完成任务;填写一个具体的时间表示创建一个已完成任务。 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_task/tools/delete_task.py b/api/core/tools/provider/builtin/feishu_task/tools/delete_task.py new file mode 100644 index 0000000000..dee036fee5 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_task/tools/delete_task.py @@ -0,0 +1,18 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class UpdateTaskTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + task_guid = tool_parameters.get("task_guid") + + res = client.delete_task(task_guid) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_task/tools/delete_task.yaml b/api/core/tools/provider/builtin/feishu_task/tools/delete_task.yaml new file mode 100644 index 0000000000..d3f9741367 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_task/tools/delete_task.yaml @@ -0,0 +1,24 @@ +identity: + name: delete_task + author: Doug Lea + label: + en_US: Delete Task + zh_Hans: 删除飞书任务 +description: + human: + en_US: Delete Task + zh_Hans: 删除飞书任务 + llm: A tool for deleting tasks in Feishu.(删除飞书任务) +parameters: + - name: task_guid + type: string + required: true + label: + en_US: Task GUID + zh_Hans: 任务 GUID + human_description: + en_US: | + The GUID of the task to be deleted, supports passing either the Task ID or the Task link URL. Example of Task ID: 8b5425ec-9f2a-43bd-a3ab-01912f50282b; Example of Task link URL: https://applink.feishu-pre.net/client/todo/detail?guid=8c6bf822-e4da-449a-b82a-dc44020f9be9&suite_entity_num=t21587362 + zh_Hans: 要删除的任务的 GUID,支持传任务 ID 和任务链接 URL。任务 ID 示例:8b5425ec-9f2a-43bd-a3ab-01912f50282b;任务链接 URL 示例:https://applink.feishu-pre.net/client/todo/detail?guid=8c6bf822-e4da-449a-b82a-dc44020f9be9&suite_entity_num=t21587362 + llm_description: 要删除的任务的 GUID,支持传任务 ID 和任务链接 URL。任务 ID 示例:8b5425ec-9f2a-43bd-a3ab-01912f50282b;任务链接 URL 示例:https://applink.feishu-pre.net/client/todo/detail?guid=8c6bf822-e4da-449a-b82a-dc44020f9be9&suite_entity_num=t21587362 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_task/tools/update_task.py b/api/core/tools/provider/builtin/feishu_task/tools/update_task.py new file mode 100644 index 0000000000..4a48cd283a --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_task/tools/update_task.py @@ -0,0 +1,23 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class UpdateTaskTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + task_guid = tool_parameters.get("task_guid") + summary = tool_parameters.get("summary") + start_time = tool_parameters.get("start_time") + end_time = tool_parameters.get("end_time") + completed_time = tool_parameters.get("completed_time") + description = tool_parameters.get("description") + + res = client.update_task(task_guid, summary, start_time, end_time, completed_time, description) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_task/tools/update_task.yaml b/api/core/tools/provider/builtin/feishu_task/tools/update_task.yaml new file mode 100644 index 0000000000..83c9bcb1c4 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_task/tools/update_task.yaml @@ -0,0 +1,89 @@ +identity: + name: update_task + author: Doug Lea + label: + en_US: Update Task + zh_Hans: 更新飞书任务 +description: + human: + en_US: Update Feishu Task + zh_Hans: 更新飞书任务 + llm: A tool for updating tasks in Feishu.(更新飞书任务) +parameters: + - name: task_guid + type: string + required: true + label: + en_US: Task GUID + zh_Hans: 任务 GUID + human_description: + en_US: | + The task ID, supports inputting either the Task ID or the Task link URL. Example of Task ID: 42cad8a0-f8c8-4344-9be2-d1d7e8e91b64; Example of Task link URL: https://applink.feishu-pre.net/client/todo/detail?guid=42cad8a0-f8c8-4344-9be2-d1d7e8e91b64&suite_entity_num=t21700217 + zh_Hans: | + 任务ID,支持传入任务 ID 和任务链接 URL。任务 ID 示例: 42cad8a0-f8c8-4344-9be2-d1d7e8e91b64;任务链接 URL 示例: https://applink.feishu-pre.net/client/todo/detail?guid=42cad8a0-f8c8-4344-9be2-d1d7e8e91b64&suite_entity_num=t21700217 + llm_description: | + 任务ID,支持传入任务 ID 和任务链接 URL。任务 ID 示例: 42cad8a0-f8c8-4344-9be2-d1d7e8e91b64;任务链接 URL 示例: https://applink.feishu-pre.net/client/todo/detail?guid=42cad8a0-f8c8-4344-9be2-d1d7e8e91b64&suite_entity_num=t21700217 + form: llm + + - name: summary + type: string + required: true + label: + en_US: Task Title + zh_Hans: 任务标题 + human_description: + en_US: The title of the task. + zh_Hans: 任务标题 + llm_description: 任务标题 + form: llm + + - name: description + type: string + required: false + label: + en_US: Task Description + zh_Hans: 任务备注 + human_description: + en_US: The description or notes for the task. + zh_Hans: 任务备注 + llm_description: 任务备注 + form: llm + + - name: start_time + type: string + required: false + label: + en_US: Start Time + zh_Hans: 任务开始时间 + human_description: + en_US: | + The start time of the task, in the format: 2006-01-02 15:04:05 + zh_Hans: 任务开始时间,格式为:2006-01-02 15:04:05 + llm_description: 任务开始时间,格式为:2006-01-02 15:04:05 + form: llm + + - name: end_time + type: string + required: false + label: + en_US: End Time + zh_Hans: 任务结束时间 + human_description: + en_US: | + The end time of the task, in the format: 2006-01-02 15:04:05 + zh_Hans: 任务结束时间,格式为:2006-01-02 15:04:05 + llm_description: 任务结束时间,格式为:2006-01-02 15:04:05 + form: llm + + - name: completed_time + type: string + required: false + label: + en_US: Completed Time + zh_Hans: 任务完成时间 + human_description: + en_US: | + The completion time of the task, in the format: 2006-01-02 15:04:05 + zh_Hans: 任务完成时间,格式为:2006-01-02 15:04:05 + llm_description: 任务完成时间,格式为:2006-01-02 15:04:05 + form: llm diff --git a/api/core/tools/provider/builtin/feishu_wiki/_assets/icon.png b/api/core/tools/provider/builtin/feishu_wiki/_assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..878672c9ae5a511f246d3211863ec786596481eb GIT binary patch literal 4252 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 literal 0 HcmV?d00001 diff --git a/api/core/tools/provider/builtin/feishu_wiki/feishu_wiki.py b/api/core/tools/provider/builtin/feishu_wiki/feishu_wiki.py new file mode 100644 index 0000000000..6c5fccb1a3 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_wiki/feishu_wiki.py @@ -0,0 +1,7 @@ +from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController +from core.tools.utils.feishu_api_utils import auth + + +class FeishuWikiProvider(BuiltinToolProviderController): + def _validate_credentials(self, credentials: dict) -> None: + auth(credentials) diff --git a/api/core/tools/provider/builtin/feishu_wiki/feishu_wiki.yaml b/api/core/tools/provider/builtin/feishu_wiki/feishu_wiki.yaml new file mode 100644 index 0000000000..1fb5f71cbc --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_wiki/feishu_wiki.yaml @@ -0,0 +1,36 @@ +identity: + author: Doug Lea + name: feishu_wiki + label: + en_US: Feishu Wiki + zh_Hans: 飞书知识库 + description: + en_US: | + Feishu Wiki, requires the following permissions: wiki:wiki:readonly. + zh_Hans: | + 飞书知识库,需要开通以下权限: wiki:wiki:readonly。 + icon: icon.png + tags: + - social + - productivity +credentials_for_provider: + app_id: + type: text-input + required: true + label: + en_US: APP ID + placeholder: + en_US: Please input your feishu app id + zh_Hans: 请输入你的飞书 app id + help: + en_US: Get your app_id and app_secret from Feishu + zh_Hans: 从飞书获取您的 app_id 和 app_secret + url: https://open.larkoffice.com/app + app_secret: + type: secret-input + required: true + label: + en_US: APP Secret + placeholder: + en_US: Please input your app secret + zh_Hans: 请输入你的飞书 app secret diff --git a/api/core/tools/provider/builtin/feishu_wiki/tools/get_wiki_nodes.py b/api/core/tools/provider/builtin/feishu_wiki/tools/get_wiki_nodes.py new file mode 100644 index 0000000000..374b4c9a7d --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_wiki/tools/get_wiki_nodes.py @@ -0,0 +1,21 @@ +from typing import Any + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool +from core.tools.utils.feishu_api_utils import FeishuRequest + + +class GetWikiNodesTool(BuiltinTool): + def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: + app_id = self.runtime.credentials.get("app_id") + app_secret = self.runtime.credentials.get("app_secret") + client = FeishuRequest(app_id, app_secret) + + space_id = tool_parameters.get("space_id") + parent_node_token = tool_parameters.get("parent_node_token") + page_token = tool_parameters.get("page_token") + page_size = tool_parameters.get("page_size") + + res = client.get_wiki_nodes(space_id, parent_node_token, page_token, page_size) + + return self.create_json_message(res) diff --git a/api/core/tools/provider/builtin/feishu_wiki/tools/get_wiki_nodes.yaml b/api/core/tools/provider/builtin/feishu_wiki/tools/get_wiki_nodes.yaml new file mode 100644 index 0000000000..7d6ac3c824 --- /dev/null +++ b/api/core/tools/provider/builtin/feishu_wiki/tools/get_wiki_nodes.yaml @@ -0,0 +1,63 @@ +identity: + name: get_wiki_nodes + author: Doug Lea + label: + en_US: Get Wiki Nodes + zh_Hans: 获取知识空间子节点列表 +description: + human: + en_US: | + Get the list of child nodes in Wiki, make sure the app/bot is a member of the wiki space. See How to add an app as a wiki base administrator (member). https://open.feishu.cn/document/server-docs/docs/wiki-v2/wiki-qa + zh_Hans: | + 获取知识库全部子节点列表,请确保应用/机器人为知识空间成员。参阅如何将应用添加为知识库管理员(成员)。https://open.feishu.cn/document/server-docs/docs/wiki-v2/wiki-qa + llm: A tool for getting all sub-nodes of a knowledge base.(获取知识空间子节点列表) +parameters: + - name: space_id + type: string + required: true + label: + en_US: Space Id + zh_Hans: 知识空间 ID + human_description: + en_US: | + The ID of the knowledge space. Supports space link URL, for example: https://svi136aogf123.feishu.cn/wiki/settings/7166950623940706332 + zh_Hans: 知识空间 ID,支持空间链接 URL,例如:https://svi136aogf123.feishu.cn/wiki/settings/7166950623940706332 + llm_description: 知识空间 ID,支持空间链接 URL,例如:https://svi136aogf123.feishu.cn/wiki/settings/7166950623940706332 + form: llm + + - name: page_size + type: number + required: false + default: 10 + label: + en_US: Page Size + zh_Hans: 分页大小 + human_description: + en_US: The size of each page, with a maximum value of 50. + zh_Hans: 分页大小,最大值 50。 + llm_description: 分页大小,最大值 50。 + form: llm + + - name: page_token + type: string + required: false + label: + en_US: Page Token + zh_Hans: 分页标记 + human_description: + en_US: The pagination token. Leave empty for the first request to start from the beginning; if the paginated query result has more items, a new page_token will be returned, which can be used to get the next set of results. + zh_Hans: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。 + llm_description: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。 + form: llm + + - name: parent_node_token + type: string + required: false + label: + en_US: Parent Node Token + zh_Hans: 父节点 token + human_description: + en_US: The token of the parent node. + zh_Hans: 父节点 token + llm_description: 父节点 token + form: llm diff --git a/api/core/tools/utils/feishu_api_utils.py b/api/core/tools/utils/feishu_api_utils.py index ffdb06498f..ce1fd7dc19 100644 --- a/api/core/tools/utils/feishu_api_utils.py +++ b/api/core/tools/utils/feishu_api_utils.py @@ -1,9 +1,23 @@ import httpx +from core.tools.errors import ToolProviderCredentialValidationError from extensions.ext_redis import redis_client +def auth(credentials): + app_id = credentials.get("app_id") + app_secret = credentials.get("app_secret") + if not app_id or not app_secret: + raise ToolProviderCredentialValidationError("app_id and app_secret is required") + try: + assert FeishuRequest(app_id, app_secret).tenant_access_token is not None + except Exception as e: + raise ToolProviderCredentialValidationError(str(e)) + + class FeishuRequest: + API_BASE_URL = "https://lark-plugin-api.solutionsuite.cn/lark-plugin" + def __init__(self, app_id: str, app_secret: str): self.app_id = app_id self.app_secret = app_secret @@ -42,7 +56,7 @@ class FeishuRequest: "expire": 7200 } """ - url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/access_token/get_tenant_access_token" + url = f"{self.API_BASE_URL}/access_token/get_tenant_access_token" payload = {"app_id": app_id, "app_secret": app_secret} res = self._send_request(url, require_token=False, payload=payload) return res @@ -63,7 +77,7 @@ class FeishuRequest: "msg": "创建飞书文档成功,请查看" } """ - url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/document/create_document" + url = f"{self.API_BASE_URL}/document/create_document" payload = { "title": title, "content": content, @@ -72,13 +86,13 @@ class FeishuRequest: res = self._send_request(url, payload=payload) return res.get("data") - def write_document(self, document_id: str, content: str, position: str = "start") -> dict: - url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/document/write_document" + def write_document(self, document_id: str, content: str, position: str = "end") -> dict: + url = f"{self.API_BASE_URL}/document/write_document" payload = {"document_id": document_id, "content": content, "position": position} res = self._send_request(url, payload=payload) return res - def get_document_content(self, document_id: str, mode: str, lang: int = 0) -> dict: + def get_document_content(self, document_id: str, mode: str = "markdown", lang: str = "0") -> dict: """ API url: https://open.larkoffice.com/document/server-docs/docs/docs/docx-v1/document/raw_content Example Response: @@ -95,45 +109,404 @@ class FeishuRequest: "mode": mode, "lang": lang, } - url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/document/get_document_content" - res = self._send_request(url, method="get", params=params) + url = f"{self.API_BASE_URL}/document/get_document_content" + res = self._send_request(url, method="GET", params=params) return res.get("data").get("content") - def list_document_blocks(self, document_id: str, page_token: str, page_size: int = 500) -> dict: + def list_document_blocks( + self, document_id: str, page_token: str, user_id_type: str = "open_id", page_size: int = 500 + ) -> dict: """ API url: https://open.larkoffice.com/document/server-docs/docs/docs/docx-v1/document/list """ - url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/document/list_document_blocks" params = { + "user_id_type": user_id_type, "document_id": document_id, "page_size": page_size, "page_token": page_token, } - res = self._send_request(url, method="get", params=params) + url = f"{self.API_BASE_URL}/document/list_document_blocks" + res = self._send_request(url, method="GET", params=params) return res.get("data") def send_bot_message(self, receive_id_type: str, receive_id: str, msg_type: str, content: str) -> dict: """ API url: https://open.larkoffice.com/document/server-docs/im-v1/message/create """ - url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/message/send_bot_message" + url = f"{self.API_BASE_URL}/message/send_bot_message" params = { "receive_id_type": receive_id_type, } payload = { "receive_id": receive_id, "msg_type": msg_type, - "content": content, + "content": content.strip('"').replace(r"\"", '"').replace(r"\\", "\\"), } res = self._send_request(url, params=params, payload=payload) return res.get("data") def send_webhook_message(self, webhook: str, msg_type: str, content: str) -> dict: - url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/message/send_webhook_message" + url = f"{self.API_BASE_URL}/message/send_webhook_message" payload = { "webhook": webhook, "msg_type": msg_type, - "content": content, + "content": content.strip('"').replace(r"\"", '"').replace(r"\\", "\\"), } res = self._send_request(url, require_token=False, payload=payload) return res + + def get_chat_messages( + self, + container_id: str, + start_time: str, + end_time: str, + page_token: str, + sort_type: str = "ByCreateTimeAsc", + page_size: int = 20, + ) -> dict: + """ + API url: https://open.larkoffice.com/document/server-docs/im-v1/message/list + """ + url = f"{self.API_BASE_URL}/message/get_chat_messages" + params = { + "container_id": container_id, + "start_time": start_time, + "end_time": end_time, + "sort_type": sort_type, + "page_token": page_token, + "page_size": page_size, + } + res = self._send_request(url, method="GET", params=params) + return res.get("data") + + def get_thread_messages( + self, container_id: str, page_token: str, sort_type: str = "ByCreateTimeAsc", page_size: int = 20 + ) -> dict: + """ + API url: https://open.larkoffice.com/document/server-docs/im-v1/message/list + """ + url = f"{self.API_BASE_URL}/message/get_thread_messages" + params = { + "container_id": container_id, + "sort_type": sort_type, + "page_token": page_token, + "page_size": page_size, + } + res = self._send_request(url, method="GET", params=params) + return res.get("data") + + def create_task(self, summary: str, start_time: str, end_time: str, completed_time: str, description: str) -> dict: + # 创建任务 + url = f"{self.API_BASE_URL}/task/create_task" + payload = { + "summary": summary, + "start_time": start_time, + "end_time": end_time, + "completed_at": completed_time, + "description": description, + } + res = self._send_request(url, payload=payload) + return res.get("data") + + def update_task( + self, task_guid: str, summary: str, start_time: str, end_time: str, completed_time: str, description: str + ) -> dict: + # 更新任务 + url = f"{self.API_BASE_URL}/task/update_task" + payload = { + "task_guid": task_guid, + "summary": summary, + "start_time": start_time, + "end_time": end_time, + "completed_time": completed_time, + "description": description, + } + res = self._send_request(url, method="PATCH", payload=payload) + return res.get("data") + + def delete_task(self, task_guid: str) -> dict: + # 删除任务 + url = f"{self.API_BASE_URL}/task/delete_task" + payload = { + "task_guid": task_guid, + } + res = self._send_request(url, method="DELETE", payload=payload) + return res + + def add_members(self, task_guid: str, member_phone_or_email: str, member_role: str) -> dict: + # 删除任务 + url = f"{self.API_BASE_URL}/task/add_members" + payload = { + "task_guid": task_guid, + "member_phone_or_email": member_phone_or_email, + "member_role": member_role, + } + res = self._send_request(url, payload=payload) + return res + + def get_wiki_nodes(self, space_id: str, parent_node_token: str, page_token: str, page_size: int = 20) -> dict: + # 获取知识库全部子节点列表 + url = f"{self.API_BASE_URL}/wiki/get_wiki_nodes" + payload = { + "space_id": space_id, + "parent_node_token": parent_node_token, + "page_token": page_token, + "page_size": page_size, + } + res = self._send_request(url, payload=payload) + return res.get("data") + + def get_primary_calendar(self, user_id_type: str = "open_id") -> dict: + url = f"{self.API_BASE_URL}/calendar/get_primary_calendar" + params = { + "user_id_type": user_id_type, + } + res = self._send_request(url, method="GET", params=params) + return res.get("data") + + def create_event( + self, + summary: str, + description: str, + start_time: str, + end_time: str, + attendee_ability: str, + need_notification: bool = True, + auto_record: bool = False, + ) -> dict: + url = f"{self.API_BASE_URL}/calendar/create_event" + payload = { + "summary": summary, + "description": description, + "need_notification": need_notification, + "start_time": start_time, + "end_time": end_time, + "auto_record": auto_record, + "attendee_ability": attendee_ability, + } + res = self._send_request(url, payload=payload) + return res.get("data") + + def update_event( + self, + event_id: str, + summary: str, + description: str, + need_notification: bool, + start_time: str, + end_time: str, + auto_record: bool, + ) -> dict: + url = f"{self.API_BASE_URL}/calendar/update_event/{event_id}" + payload = {} + if summary: + payload["summary"] = summary + if description: + payload["description"] = description + if start_time: + payload["start_time"] = start_time + if end_time: + payload["end_time"] = end_time + if need_notification: + payload["need_notification"] = need_notification + if auto_record: + payload["auto_record"] = auto_record + res = self._send_request(url, method="PATCH", payload=payload) + return res + + def delete_event(self, event_id: str, need_notification: bool = True) -> dict: + url = f"{self.API_BASE_URL}/calendar/delete_event/{event_id}" + params = { + "need_notification": need_notification, + } + res = self._send_request(url, method="DELETE", params=params) + return res + + def list_events(self, start_time: str, end_time: str, page_token: str, page_size: int = 50) -> dict: + url = f"{self.API_BASE_URL}/calendar/list_events" + params = { + "start_time": start_time, + "end_time": end_time, + "page_token": page_token, + "page_size": page_size, + } + res = self._send_request(url, method="GET", params=params) + return res.get("data") + + def search_events( + self, + query: str, + start_time: str, + end_time: str, + page_token: str, + user_id_type: str = "open_id", + page_size: int = 20, + ) -> dict: + url = f"{self.API_BASE_URL}/calendar/search_events" + payload = { + "query": query, + "start_time": start_time, + "end_time": end_time, + "page_token": page_token, + "user_id_type": user_id_type, + "page_size": page_size, + } + res = self._send_request(url, payload=payload) + return res.get("data") + + def add_event_attendees(self, event_id: str, attendee_phone_or_email: str, need_notification: bool = True) -> dict: + # 参加日程参会人 + url = f"{self.API_BASE_URL}/calendar/add_event_attendees" + payload = { + "event_id": event_id, + "attendee_phone_or_email": attendee_phone_or_email, + "need_notification": need_notification, + } + res = self._send_request(url, payload=payload) + return res.get("data") + + def create_spreadsheet( + self, + title: str, + folder_token: str, + ) -> dict: + # 创建电子表格 + url = f"{self.API_BASE_URL}/spreadsheet/create_spreadsheet" + payload = { + "title": title, + "folder_token": folder_token, + } + res = self._send_request(url, payload=payload) + return res.get("data") + + def get_spreadsheet( + self, + spreadsheet_token: str, + user_id_type: str = "open_id", + ) -> dict: + # 获取电子表格信息 + url = f"{self.API_BASE_URL}/spreadsheet/get_spreadsheet" + params = { + "spreadsheet_token": spreadsheet_token, + "user_id_type": user_id_type, + } + res = self._send_request(url, method="GET", params=params) + return res.get("data") + + def list_spreadsheet_sheets( + self, + spreadsheet_token: str, + ) -> dict: + # 列出电子表格的所有工作表 + url = f"{self.API_BASE_URL}/spreadsheet/list_spreadsheet_sheets" + params = { + "spreadsheet_token": spreadsheet_token, + } + res = self._send_request(url, method="GET", params=params) + return res.get("data") + + def add_rows( + self, + spreadsheet_token: str, + sheet_id: str, + sheet_name: str, + length: int, + values: str, + ) -> dict: + # 增加行,在工作表最后添加 + url = f"{self.API_BASE_URL}/spreadsheet/add_rows" + payload = { + "spreadsheet_token": spreadsheet_token, + "sheet_id": sheet_id, + "sheet_name": sheet_name, + "length": length, + "values": values, + } + res = self._send_request(url, payload=payload) + return res.get("data") + + def add_cols( + self, + spreadsheet_token: str, + sheet_id: str, + sheet_name: str, + length: int, + values: str, + ) -> dict: + # 增加列,在工作表最后添加 + url = f"{self.API_BASE_URL}/spreadsheet/add_cols" + payload = { + "spreadsheet_token": spreadsheet_token, + "sheet_id": sheet_id, + "sheet_name": sheet_name, + "length": length, + "values": values, + } + res = self._send_request(url, payload=payload) + return res.get("data") + + def read_rows( + self, + spreadsheet_token: str, + sheet_id: str, + sheet_name: str, + start_row: int, + num_rows: int, + user_id_type: str = "open_id", + ) -> dict: + # 读取工作表行数据 + url = f"{self.API_BASE_URL}/spreadsheet/read_rows" + params = { + "spreadsheet_token": spreadsheet_token, + "sheet_id": sheet_id, + "sheet_name": sheet_name, + "start_row": start_row, + "num_rows": num_rows, + "user_id_type": user_id_type, + } + res = self._send_request(url, method="GET", params=params) + return res.get("data") + + def read_cols( + self, + spreadsheet_token: str, + sheet_id: str, + sheet_name: str, + start_col: int, + num_cols: int, + user_id_type: str = "open_id", + ) -> dict: + # 读取工作表列数据 + url = f"{self.API_BASE_URL}/spreadsheet/read_cols" + params = { + "spreadsheet_token": spreadsheet_token, + "sheet_id": sheet_id, + "sheet_name": sheet_name, + "start_col": start_col, + "num_cols": num_cols, + "user_id_type": user_id_type, + } + res = self._send_request(url, method="GET", params=params) + return res.get("data") + + def read_table( + self, + spreadsheet_token: str, + sheet_id: str, + sheet_name: str, + num_range: str, + query: str, + user_id_type: str = "open_id", + ) -> dict: + # 自定义读取行列数据 + url = f"{self.API_BASE_URL}/spreadsheet/read_table" + params = { + "spreadsheet_token": spreadsheet_token, + "sheet_id": sheet_id, + "sheet_name": sheet_name, + "range": num_range, + "query": query, + "user_id_type": user_id_type, + } + res = self._send_request(url, method="GET", params=params) + return res.get("data") From 55e6123db93ae7fbda06596d6cd0a163747e6559 Mon Sep 17 00:00:00 2001 From: zhuhao <37029601+hwzhuhao@users.noreply.github.com> Date: Fri, 27 Sep 2024 18:16:20 +0800 Subject: [PATCH 002/136] feat: add min-connection and max-connection for pgvector (#8841) --- api/.env.example | 2 ++ api/configs/middleware/vdb/pgvector_config.py | 10 ++++++++++ api/core/rag/datasource/vdb/pgvector/pgvector.py | 14 ++++++++++++-- .../vdb/pgvector/test_pgvector.py | 2 ++ docker/.env.example | 2 ++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/api/.env.example b/api/.env.example index a3db406aea..7e5c636ff8 100644 --- a/api/.env.example +++ b/api/.env.example @@ -162,6 +162,8 @@ PGVECTOR_PORT=5433 PGVECTOR_USER=postgres PGVECTOR_PASSWORD=postgres PGVECTOR_DATABASE=postgres +PGVECTOR_MIN_CONNECTION=1 +PGVECTOR_MAX_CONNECTION=5 # Tidb Vector configuration TIDB_VECTOR_HOST=xxx.eu-central-1.xxx.aws.tidbcloud.com diff --git a/api/configs/middleware/vdb/pgvector_config.py b/api/configs/middleware/vdb/pgvector_config.py index 395dcaa420..85f5dca7e2 100644 --- a/api/configs/middleware/vdb/pgvector_config.py +++ b/api/configs/middleware/vdb/pgvector_config.py @@ -33,3 +33,13 @@ class PGVectorConfig(BaseSettings): description="Name of the PostgreSQL database to connect to", default=None, ) + + PGVECTOR_MIN_CONNECTION: PositiveInt = Field( + description="Min connection of the PostgreSQL database", + default=1, + ) + + PGVECTOR_MAX_CONNECTION: PositiveInt = Field( + description="Max connection of the PostgreSQL database", + default=5, + ) diff --git a/api/core/rag/datasource/vdb/pgvector/pgvector.py b/api/core/rag/datasource/vdb/pgvector/pgvector.py index 79879d4f63..d90707ebcd 100644 --- a/api/core/rag/datasource/vdb/pgvector/pgvector.py +++ b/api/core/rag/datasource/vdb/pgvector/pgvector.py @@ -23,6 +23,8 @@ class PGVectorConfig(BaseModel): user: str password: str database: str + min_connection: int + max_connection: int @model_validator(mode="before") @classmethod @@ -37,6 +39,12 @@ class PGVectorConfig(BaseModel): raise ValueError("config PGVECTOR_PASSWORD is required") if not values["database"]: raise ValueError("config PGVECTOR_DATABASE is required") + if not values["min_connection"]: + raise ValueError("config PGVECTOR_MIN_CONNECTION is required") + if not values["max_connection"]: + raise ValueError("config PGVECTOR_MAX_CONNECTION is required") + if values["min_connection"] > values["max_connection"]: + raise ValueError("config PGVECTOR_MIN_CONNECTION should less than PGVECTOR_MAX_CONNECTION") return values @@ -61,8 +69,8 @@ class PGVector(BaseVector): def _create_connection_pool(self, config: PGVectorConfig): return psycopg2.pool.SimpleConnectionPool( - 1, - 5, + config.min_connection, + config.max_connection, host=config.host, port=config.port, user=config.user, @@ -213,5 +221,7 @@ class PGVectorFactory(AbstractVectorFactory): user=dify_config.PGVECTOR_USER, password=dify_config.PGVECTOR_PASSWORD, database=dify_config.PGVECTOR_DATABASE, + min_connection=dify_config.PGVECTOR_MIN_CONNECTION, + max_connection=dify_config.PGVECTOR_MAX_CONNECTION, ), ) diff --git a/api/tests/integration_tests/vdb/pgvector/test_pgvector.py b/api/tests/integration_tests/vdb/pgvector/test_pgvector.py index c5a986b747..72efdc2780 100644 --- a/api/tests/integration_tests/vdb/pgvector/test_pgvector.py +++ b/api/tests/integration_tests/vdb/pgvector/test_pgvector.py @@ -18,6 +18,8 @@ class PGVectorTest(AbstractVectorTest): user="postgres", password="difyai123456", database="dify", + min_connection=1, + max_connection=5, ), ) diff --git a/docker/.env.example b/docker/.env.example index d43c3edc7e..eb05f7aa4f 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -391,6 +391,8 @@ PGVECTOR_PORT=5432 PGVECTOR_USER=postgres PGVECTOR_PASSWORD=difyai123456 PGVECTOR_DATABASE=dify +PGVECTOR_MIN_CONNECTION=1 +PGVECTOR_MAX_CONNECTION=5 # pgvecto-rs configurations, only available when VECTOR_STORE is `pgvecto-rs` PGVECTO_RS_HOST=pgvecto-rs From 27e33fb15c01befb47d02afe257746778b1164ed Mon Sep 17 00:00:00 2001 From: ice yao Date: Sat, 28 Sep 2024 10:54:04 +0800 Subject: [PATCH 003/136] chore: fix wrong VectorType match case (#8857) --- api/controllers/console/datasets/datasets.py | 3 ++- api/core/rag/datasource/vdb/tencent/tencent_vector.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/api/controllers/console/datasets/datasets.py b/api/controllers/console/datasets/datasets.py index 2c4e5ac607..5a763b3457 100644 --- a/api/controllers/console/datasets/datasets.py +++ b/api/controllers/console/datasets/datasets.py @@ -563,10 +563,10 @@ class DatasetRetrievalSettingApi(Resource): case ( VectorType.MILVUS | VectorType.RELYT - | VectorType.PGVECTOR | VectorType.TIDB_VECTOR | VectorType.CHROMA | VectorType.TENCENT + | VectorType.PGVECTO_RS ): return {"retrieval_method": [RetrievalMethod.SEMANTIC_SEARCH.value]} case ( @@ -577,6 +577,7 @@ class DatasetRetrievalSettingApi(Resource): | VectorType.MYSCALE | VectorType.ORACLE | VectorType.ELASTICSEARCH + | VectorType.PGVECTOR ): return { "retrieval_method": [ diff --git a/api/core/rag/datasource/vdb/tencent/tencent_vector.py b/api/core/rag/datasource/vdb/tencent/tencent_vector.py index faa373017b..39e3a7f6cf 100644 --- a/api/core/rag/datasource/vdb/tencent/tencent_vector.py +++ b/api/core/rag/datasource/vdb/tencent/tencent_vector.py @@ -56,7 +56,7 @@ class TencentVector(BaseVector): return self._client.create_database(database_name=self._client_config.database) def get_type(self) -> str: - return "tencent" + return VectorType.TENCENT def to_index_struct(self) -> dict: return {"type": self.get_type(), "vector_store": {"class_prefix": self._collection_name}} From a2e2f8a8c98e188dd3d0a4669b4775260756a106 Mon Sep 17 00:00:00 2001 From: Kevin9703 <51311316+Kevin9703@users.noreply.github.com> Date: Sat, 28 Sep 2024 10:54:50 +0800 Subject: [PATCH 004/136] =?UTF-8?q?fix(workflow/nodes/knowledge-retrieval/?= =?UTF-8?q?use-config):=20Preserve=20rerankin=E2=80=A6=20(#8842)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/workflow/nodes/knowledge-retrieval/use-config.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/app/components/workflow/nodes/knowledge-retrieval/use-config.ts b/web/app/components/workflow/nodes/knowledge-retrieval/use-config.ts index 994bf4f205..6d856003d4 100644 --- a/web/app/components/workflow/nodes/knowledge-retrieval/use-config.ts +++ b/web/app/components/workflow/nodes/knowledge-retrieval/use-config.ts @@ -136,6 +136,8 @@ const useConfig = (id: string, payload: KnowledgeRetrievalNodeType) => { top_k: multipleRetrievalConfig?.top_k || DATASET_DEFAULT.top_k, score_threshold: multipleRetrievalConfig?.score_threshold, reranking_model: multipleRetrievalConfig?.reranking_model, + reranking_mode: multipleRetrievalConfig?.reranking_mode, + weights: multipleRetrievalConfig?.weights, } }) setInputs(newInput) From 6cd22f3bca2509c19f7b4dcfca4b4785b139d677 Mon Sep 17 00:00:00 2001 From: zhuhao <37029601+hwzhuhao@users.noreply.github.com> Date: Sat, 28 Sep 2024 15:01:27 +0800 Subject: [PATCH 005/136] fix: update qwen2.5-coder-7b model name (#8861) --- .../model_providers/tongyi/llm/qwen2.5-coder-7b-instruct.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/core/model_runtime/model_providers/tongyi/llm/qwen2.5-coder-7b-instruct.yaml b/api/core/model_runtime/model_providers/tongyi/llm/qwen2.5-coder-7b-instruct.yaml index fdcd3d4275..7ebeec3953 100644 --- a/api/core/model_runtime/model_providers/tongyi/llm/qwen2.5-coder-7b-instruct.yaml +++ b/api/core/model_runtime/model_providers/tongyi/llm/qwen2.5-coder-7b-instruct.yaml @@ -1,7 +1,7 @@ # for more details, please refer to https://help.aliyun.com/zh/model-studio/getting-started/models -model: qwen2.5-7b-instruct +model: qwen2.5-coder-7b-instruct label: - en_US: qwen2.5-7b-instruct + en_US: qwen2.5-coder-7b-instruct model_type: llm features: - agent-thought From 49af18fbd6549e1ce756544529158a5ca8a7c338 Mon Sep 17 00:00:00 2001 From: takatost Date: Sat, 28 Sep 2024 15:54:26 +0800 Subject: [PATCH 006/136] fix: customize model credentials were invalid despite the provider credentials being active (#8864) --- api/core/entities/provider_configuration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/core/entities/provider_configuration.py b/api/core/entities/provider_configuration.py index 4797b69b85..807f09598c 100644 --- a/api/core/entities/provider_configuration.py +++ b/api/core/entities/provider_configuration.py @@ -119,7 +119,7 @@ class ProviderConfiguration(BaseModel): credentials = model_configuration.credentials break - if self.custom_configuration.provider: + if not credentials and self.custom_configuration.provider: credentials = self.custom_configuration.provider.credentials return credentials From 61c89a9168e54f79be54866a1e88171da533f91a Mon Sep 17 00:00:00 2001 From: zhuhao <37029601+hwzhuhao@users.noreply.github.com> Date: Sat, 28 Sep 2024 16:31:02 +0800 Subject: [PATCH 007/136] feat: add internlm2.5-20b and qwen2.5-coder-7b model (#8862) --- .../siliconflow/llm/_position.yaml | 16 +--- .../siliconflow/llm/internlm2_5-20b-chat.yaml | 30 ++++++++ .../llm/qwen2.5-coder-7b-instruct.yaml | 74 +++++++++++++++++++ .../llm/qwen2.5-math-72b-instruct.yaml | 74 +++++++++++++++++++ 4 files changed, 181 insertions(+), 13 deletions(-) create mode 100644 api/core/model_runtime/model_providers/siliconflow/llm/internlm2_5-20b-chat.yaml create mode 100644 api/core/model_runtime/model_providers/siliconflow/llm/qwen2.5-coder-7b-instruct.yaml create mode 100644 api/core/model_runtime/model_providers/siliconflow/llm/qwen2.5-math-72b-instruct.yaml diff --git a/api/core/model_runtime/model_providers/siliconflow/llm/_position.yaml b/api/core/model_runtime/model_providers/siliconflow/llm/_position.yaml index a3e5d0981f..8d1df82140 100644 --- a/api/core/model_runtime/model_providers/siliconflow/llm/_position.yaml +++ b/api/core/model_runtime/model_providers/siliconflow/llm/_position.yaml @@ -1,18 +1,17 @@ - Qwen/Qwen2.5-72B-Instruct -- Qwen/Qwen2.5-Math-72B-Instruct - Qwen/Qwen2.5-32B-Instruct - Qwen/Qwen2.5-14B-Instruct - Qwen/Qwen2.5-7B-Instruct - Qwen/Qwen2.5-Coder-7B-Instruct -- deepseek-ai/DeepSeek-V2.5 +- Qwen/Qwen2.5-Math-72B-Instruct - Qwen/Qwen2-72B-Instruct - Qwen/Qwen2-57B-A14B-Instruct - Qwen/Qwen2-7B-Instruct - Qwen/Qwen2-1.5B-Instruct +- deepseek-ai/DeepSeek-V2.5 - deepseek-ai/DeepSeek-V2-Chat - deepseek-ai/DeepSeek-Coder-V2-Instruct - THUDM/glm-4-9b-chat -- THUDM/chatglm3-6b - 01-ai/Yi-1.5-34B-Chat-16K - 01-ai/Yi-1.5-9B-Chat-16K - 01-ai/Yi-1.5-6B-Chat @@ -26,13 +25,4 @@ - google/gemma-2-27b-it - google/gemma-2-9b-it - mistralai/Mistral-7B-Instruct-v0.2 -- Pro/Qwen/Qwen2-7B-Instruct -- Pro/Qwen/Qwen2-1.5B-Instruct -- Pro/THUDM/glm-4-9b-chat -- Pro/THUDM/chatglm3-6b -- Pro/01-ai/Yi-1.5-9B-Chat-16K -- Pro/01-ai/Yi-1.5-6B-Chat -- Pro/internlm/internlm2_5-7b-chat -- Pro/meta-llama/Meta-Llama-3.1-8B-Instruct -- Pro/meta-llama/Meta-Llama-3-8B-Instruct -- Pro/google/gemma-2-9b-it +- mistralai/Mixtral-8x7B-Instruct-v0.1 diff --git a/api/core/model_runtime/model_providers/siliconflow/llm/internlm2_5-20b-chat.yaml b/api/core/model_runtime/model_providers/siliconflow/llm/internlm2_5-20b-chat.yaml new file mode 100644 index 0000000000..d9663582e5 --- /dev/null +++ b/api/core/model_runtime/model_providers/siliconflow/llm/internlm2_5-20b-chat.yaml @@ -0,0 +1,30 @@ +model: internlm/internlm2_5-20b-chat +label: + en_US: internlm/internlm2_5-20b-chat +model_type: llm +features: + - agent-thought +model_properties: + mode: chat + context_size: 32768 +parameter_rules: + - name: temperature + use_template: temperature + - name: max_tokens + use_template: max_tokens + type: int + default: 512 + min: 1 + max: 4096 + help: + zh_Hans: 指定生成结果长度的上限。如果生成结果截断,可以调大该参数。 + en_US: Specifies the upper limit on the length of generated results. If the generated results are truncated, you can increase this parameter. + - name: top_p + use_template: top_p + - name: frequency_penalty + use_template: frequency_penalty +pricing: + input: '1' + output: '1' + unit: '0.000001' + currency: RMB diff --git a/api/core/model_runtime/model_providers/siliconflow/llm/qwen2.5-coder-7b-instruct.yaml b/api/core/model_runtime/model_providers/siliconflow/llm/qwen2.5-coder-7b-instruct.yaml new file mode 100644 index 0000000000..76526200cc --- /dev/null +++ b/api/core/model_runtime/model_providers/siliconflow/llm/qwen2.5-coder-7b-instruct.yaml @@ -0,0 +1,74 @@ +model: Qwen/Qwen2.5-Coder-7B-Instruct +label: + en_US: Qwen/Qwen2.5-Coder-7B-Instruct +model_type: llm +features: + - agent-thought +model_properties: + mode: chat + context_size: 131072 +parameter_rules: + - name: temperature + use_template: temperature + type: float + default: 0.3 + min: 0.0 + max: 2.0 + help: + zh_Hans: 用于控制随机性和多样性的程度。具体来说,temperature值控制了生成文本时对每个候选词的概率分布进行平滑的程度。较高的temperature值会降低概率分布的峰值,使得更多的低概率词被选择,生成结果更加多样化;而较低的temperature值则会增强概率分布的峰值,使得高概率词更容易被选择,生成结果更加确定。 + en_US: Used to control the degree of randomness and diversity. Specifically, the temperature value controls the degree to which the probability distribution of each candidate word is smoothed when generating text. A higher temperature value will reduce the peak value of the probability distribution, allowing more low-probability words to be selected, and the generated results will be more diverse; while a lower temperature value will enhance the peak value of the probability distribution, making it easier for high-probability words to be selected. , the generated results are more certain. + - name: max_tokens + use_template: max_tokens + type: int + default: 8192 + min: 1 + max: 8192 + help: + zh_Hans: 用于指定模型在生成内容时token的最大数量,它定义了生成的上限,但不保证每次都会生成到这个数量。 + en_US: It is used to specify the maximum number of tokens when the model generates content. It defines the upper limit of generation, but does not guarantee that this number will be generated every time. + - name: top_p + use_template: top_p + type: float + default: 0.8 + min: 0.1 + max: 0.9 + help: + zh_Hans: 生成过程中核采样方法概率阈值,例如,取值为0.8时,仅保留概率加起来大于等于0.8的最可能token的最小集合作为候选集。取值范围为(0,1.0),取值越大,生成的随机性越高;取值越低,生成的确定性越高。 + en_US: The probability threshold of the kernel sampling method during the generation process. For example, when the value is 0.8, only the smallest set of the most likely tokens with a sum of probabilities greater than or equal to 0.8 is retained as the candidate set. The value range is (0,1.0). The larger the value, the higher the randomness generated; the lower the value, the higher the certainty generated. + - name: top_k + type: int + min: 0 + max: 99 + label: + zh_Hans: 取样数量 + en_US: Top k + help: + zh_Hans: 生成时,采样候选集的大小。例如,取值为50时,仅将单次生成中得分最高的50个token组成随机采样的候选集。取值越大,生成的随机性越高;取值越小,生成的确定性越高。 + en_US: The size of the sample candidate set when generated. For example, when the value is 50, only the 50 highest-scoring tokens in a single generation form a randomly sampled candidate set. The larger the value, the higher the randomness generated; the smaller the value, the higher the certainty generated. + - name: seed + required: false + type: int + default: 1234 + label: + zh_Hans: 随机种子 + en_US: Random seed + help: + zh_Hans: 生成时使用的随机数种子,用户控制模型生成内容的随机性。支持无符号64位整数,默认值为 1234。在使用seed时,模型将尽可能生成相同或相似的结果,但目前不保证每次生成的结果完全相同。 + en_US: The random number seed used when generating, the user controls the randomness of the content generated by the model. Supports unsigned 64-bit integers, default value is 1234. When using seed, the model will try its best to generate the same or similar results, but there is currently no guarantee that the results will be exactly the same every time. + - name: repetition_penalty + required: false + type: float + default: 1.1 + label: + zh_Hans: 重复惩罚 + en_US: Repetition penalty + help: + zh_Hans: 用于控制模型生成时的重复度。提高repetition_penalty时可以降低模型生成的重复度。1.0表示不做惩罚。 + en_US: Used to control the repeatability when generating models. Increasing repetition_penalty can reduce the duplication of model generation. 1.0 means no punishment. + - name: response_format + use_template: response_format +pricing: + input: '0' + output: '0' + unit: '0.000001' + currency: RMB diff --git a/api/core/model_runtime/model_providers/siliconflow/llm/qwen2.5-math-72b-instruct.yaml b/api/core/model_runtime/model_providers/siliconflow/llm/qwen2.5-math-72b-instruct.yaml new file mode 100644 index 0000000000..90afa0cfd5 --- /dev/null +++ b/api/core/model_runtime/model_providers/siliconflow/llm/qwen2.5-math-72b-instruct.yaml @@ -0,0 +1,74 @@ +model: Qwen/Qwen2.5-Math-72B-Instruct +label: + en_US: Qwen/Qwen2.5-Math-72B-Instruct +model_type: llm +features: + - agent-thought +model_properties: + mode: chat + context_size: 4096 +parameter_rules: + - name: temperature + use_template: temperature + type: float + default: 0.3 + min: 0.0 + max: 2.0 + help: + zh_Hans: 用于控制随机性和多样性的程度。具体来说,temperature值控制了生成文本时对每个候选词的概率分布进行平滑的程度。较高的temperature值会降低概率分布的峰值,使得更多的低概率词被选择,生成结果更加多样化;而较低的temperature值则会增强概率分布的峰值,使得高概率词更容易被选择,生成结果更加确定。 + en_US: Used to control the degree of randomness and diversity. Specifically, the temperature value controls the degree to which the probability distribution of each candidate word is smoothed when generating text. A higher temperature value will reduce the peak value of the probability distribution, allowing more low-probability words to be selected, and the generated results will be more diverse; while a lower temperature value will enhance the peak value of the probability distribution, making it easier for high-probability words to be selected. , the generated results are more certain. + - name: max_tokens + use_template: max_tokens + type: int + default: 2000 + min: 1 + max: 2000 + help: + zh_Hans: 用于指定模型在生成内容时token的最大数量,它定义了生成的上限,但不保证每次都会生成到这个数量。 + en_US: It is used to specify the maximum number of tokens when the model generates content. It defines the upper limit of generation, but does not guarantee that this number will be generated every time. + - name: top_p + use_template: top_p + type: float + default: 0.8 + min: 0.1 + max: 0.9 + help: + zh_Hans: 生成过程中核采样方法概率阈值,例如,取值为0.8时,仅保留概率加起来大于等于0.8的最可能token的最小集合作为候选集。取值范围为(0,1.0),取值越大,生成的随机性越高;取值越低,生成的确定性越高。 + en_US: The probability threshold of the kernel sampling method during the generation process. For example, when the value is 0.8, only the smallest set of the most likely tokens with a sum of probabilities greater than or equal to 0.8 is retained as the candidate set. The value range is (0,1.0). The larger the value, the higher the randomness generated; the lower the value, the higher the certainty generated. + - name: top_k + type: int + min: 0 + max: 99 + label: + zh_Hans: 取样数量 + en_US: Top k + help: + zh_Hans: 生成时,采样候选集的大小。例如,取值为50时,仅将单次生成中得分最高的50个token组成随机采样的候选集。取值越大,生成的随机性越高;取值越小,生成的确定性越高。 + en_US: The size of the sample candidate set when generated. For example, when the value is 50, only the 50 highest-scoring tokens in a single generation form a randomly sampled candidate set. The larger the value, the higher the randomness generated; the smaller the value, the higher the certainty generated. + - name: seed + required: false + type: int + default: 1234 + label: + zh_Hans: 随机种子 + en_US: Random seed + help: + zh_Hans: 生成时使用的随机数种子,用户控制模型生成内容的随机性。支持无符号64位整数,默认值为 1234。在使用seed时,模型将尽可能生成相同或相似的结果,但目前不保证每次生成的结果完全相同。 + en_US: The random number seed used when generating, the user controls the randomness of the content generated by the model. Supports unsigned 64-bit integers, default value is 1234. When using seed, the model will try its best to generate the same or similar results, but there is currently no guarantee that the results will be exactly the same every time. + - name: repetition_penalty + required: false + type: float + default: 1.1 + label: + zh_Hans: 重复惩罚 + en_US: Repetition penalty + help: + zh_Hans: 用于控制模型生成时的重复度。提高repetition_penalty时可以降低模型生成的重复度。1.0表示不做惩罚。 + en_US: Used to control the repeatability when generating models. Increasing repetition_penalty can reduce the duplication of model generation. 1.0 means no punishment. + - name: response_format + use_template: response_format +pricing: + input: '4.13' + output: '4.13' + unit: '0.000001' + currency: RMB From 850492dafaa8ef801a332d5a787cc9818c7b6072 Mon Sep 17 00:00:00 2001 From: zhuhao <37029601+hwzhuhao@users.noreply.github.com> Date: Sat, 28 Sep 2024 21:40:27 +0800 Subject: [PATCH 008/136] feat: deprecate gte-Qwen2-7B-instruct embedding model (#8866) --- .../perfxcloud/llm/_position.yaml | 21 +++++++++---------- .../perfxcloud/text_embedding/_position.yaml | 4 ++++ .../text_embedding/gte-Qwen2-7B-instruct.yaml | 1 + 3 files changed, 15 insertions(+), 11 deletions(-) create mode 100644 api/core/model_runtime/model_providers/perfxcloud/text_embedding/_position.yaml diff --git a/api/core/model_runtime/model_providers/perfxcloud/llm/_position.yaml b/api/core/model_runtime/model_providers/perfxcloud/llm/_position.yaml index 37bf400f1e..c6930e54f5 100644 --- a/api/core/model_runtime/model_providers/perfxcloud/llm/_position.yaml +++ b/api/core/model_runtime/model_providers/perfxcloud/llm/_position.yaml @@ -1,24 +1,23 @@ - Qwen2.5-72B-Instruct - Qwen2.5-7B-Instruct +- Qwen2-72B-Instruct +- Qwen2-72B-Instruct-AWQ-int4 +- Qwen2-72B-Instruct-GPTQ-Int4 +- Qwen2-7B-Instruct +- Qwen2-7B +- Qwen1.5-110B-Chat-GPTQ-Int4 +- Qwen1.5-72B-Chat-GPTQ-Int4 +- Qwen1.5-7B +- Qwen-14B-Chat-Int4 - Yi-Coder-1.5B-Chat - Yi-Coder-9B-Chat -- Qwen2-72B-Instruct-AWQ-int4 - Yi-1_5-9B-Chat-16K -- Qwen2-7B-Instruct - Reflection-Llama-3.1-70B -- Qwen2-72B-Instruct - Meta-Llama-3.1-8B-Instruct - - Meta-Llama-3.1-405B-Instruct-AWQ-INT4 - Meta-Llama-3-70B-Instruct-GPTQ-Int4 -- chatglm3-6b - Meta-Llama-3-8B-Instruct - Llama3-Chinese_v2 - deepseek-v2-lite-chat -- Qwen2-72B-Instruct-GPTQ-Int4 -- Qwen2-7B -- Qwen-14B-Chat-Int4 -- Qwen1.5-72B-Chat-GPTQ-Int4 -- Qwen1.5-7B -- Qwen1.5-110B-Chat-GPTQ-Int4 - deepseek-v2-chat +- chatglm3-6b diff --git a/api/core/model_runtime/model_providers/perfxcloud/text_embedding/_position.yaml b/api/core/model_runtime/model_providers/perfxcloud/text_embedding/_position.yaml new file mode 100644 index 0000000000..99163d4293 --- /dev/null +++ b/api/core/model_runtime/model_providers/perfxcloud/text_embedding/_position.yaml @@ -0,0 +1,4 @@ +- gte-Qwen2-7B-instruct +- BAAI/bge-large-en-v1.5 +- BAAI/bge-large-zh-v1.5 +- BAAI/bge-m3 diff --git a/api/core/model_runtime/model_providers/perfxcloud/text_embedding/gte-Qwen2-7B-instruct.yaml b/api/core/model_runtime/model_providers/perfxcloud/text_embedding/gte-Qwen2-7B-instruct.yaml index 03db0d8bce..161d5ea9a2 100644 --- a/api/core/model_runtime/model_providers/perfxcloud/text_embedding/gte-Qwen2-7B-instruct.yaml +++ b/api/core/model_runtime/model_providers/perfxcloud/text_embedding/gte-Qwen2-7B-instruct.yaml @@ -2,3 +2,4 @@ model: gte-Qwen2-7B-instruct model_type: text-embedding model_properties: context_size: 2048 +deprecated: true From f97607370a2dae9eff8bfeece505b417d232df76 Mon Sep 17 00:00:00 2001 From: zhuhao <37029601+hwzhuhao@users.noreply.github.com> Date: Sat, 28 Sep 2024 21:41:02 +0800 Subject: [PATCH 009/136] refactor: update Callback to an abstract class (#8868) --- api/core/model_runtime/callbacks/base_callback.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/api/core/model_runtime/callbacks/base_callback.py b/api/core/model_runtime/callbacks/base_callback.py index 92da53c9a4..6bd9325785 100644 --- a/api/core/model_runtime/callbacks/base_callback.py +++ b/api/core/model_runtime/callbacks/base_callback.py @@ -1,3 +1,4 @@ +from abc import ABC, abstractmethod from typing import Optional from core.model_runtime.entities.llm_entities import LLMResult, LLMResultChunk @@ -13,7 +14,7 @@ _TEXT_COLOR_MAPPING = { } -class Callback: +class Callback(ABC): """ Base class for callbacks. Only for LLM. @@ -21,6 +22,7 @@ class Callback: raise_error: bool = False + @abstractmethod def on_before_invoke( self, llm_instance: AIModel, @@ -48,6 +50,7 @@ class Callback: """ raise NotImplementedError() + @abstractmethod def on_new_chunk( self, llm_instance: AIModel, @@ -77,6 +80,7 @@ class Callback: """ raise NotImplementedError() + @abstractmethod def on_after_invoke( self, llm_instance: AIModel, @@ -106,6 +110,7 @@ class Callback: """ raise NotImplementedError() + @abstractmethod def on_invoke_error( self, llm_instance: AIModel, From 74f58f29f9a3070152b0bb097eb2bebb9f9cd19e Mon Sep 17 00:00:00 2001 From: Bowen Liang Date: Sun, 29 Sep 2024 00:29:59 +0800 Subject: [PATCH 010/136] chore: bump ruff to 0.6.8 for fixing violation in SIM910 (#8869) --- .../zhipuai/zhipuai_sdk/core/_utils/_utils.py | 2 +- .../rag/datasource/keyword/jieba/jieba.py | 2 +- .../event_handlers/create_document_index.py | 2 +- api/poetry.lock | 40 +++++++++---------- api/pyproject.toml | 2 +- .../integration_tests/tools/__mock/http.py | 2 +- .../workflow/nodes/__mock/http.py | 4 +- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/api/core/model_runtime/model_providers/zhipuai/zhipuai_sdk/core/_utils/_utils.py b/api/core/model_runtime/model_providers/zhipuai/zhipuai_sdk/core/_utils/_utils.py index ce5e7786aa..3a7b234ab0 100644 --- a/api/core/model_runtime/model_providers/zhipuai/zhipuai_sdk/core/_utils/_utils.py +++ b/api/core/model_runtime/model_providers/zhipuai/zhipuai_sdk/core/_utils/_utils.py @@ -248,7 +248,7 @@ def required_args(*variants: Sequence[str]) -> Callable[[CallableT], CallableT]: @functools.wraps(func) def wrapper(*args: object, **kwargs: object) -> object: given_params: set[str] = set() - for i, _ in enumerate(args): + for i in range(len(args)): try: given_params.add(positional[i]) except IndexError: diff --git a/api/core/rag/datasource/keyword/jieba/jieba.py b/api/core/rag/datasource/keyword/jieba/jieba.py index 3073100746..a0153c1e58 100644 --- a/api/core/rag/datasource/keyword/jieba/jieba.py +++ b/api/core/rag/datasource/keyword/jieba/jieba.py @@ -45,7 +45,7 @@ class Jieba(BaseKeyword): keyword_table_handler = JiebaKeywordTableHandler() keyword_table = self._get_dataset_keyword_table() - keywords_list = kwargs.get("keywords_list", None) + keywords_list = kwargs.get("keywords_list") for i in range(len(texts)): text = texts[i] if keywords_list: diff --git a/api/events/event_handlers/create_document_index.py b/api/events/event_handlers/create_document_index.py index 54f6a76e16..5af45e1e50 100644 --- a/api/events/event_handlers/create_document_index.py +++ b/api/events/event_handlers/create_document_index.py @@ -14,7 +14,7 @@ from models.dataset import Document @document_index_created.connect def handle(sender, **kwargs): dataset_id = sender - document_ids = kwargs.get("document_ids", None) + document_ids = kwargs.get("document_ids") documents = [] start_at = time.perf_counter() for document_id in document_ids: diff --git a/api/poetry.lock b/api/poetry.lock index bce21fb547..85c68cd75f 100644 --- a/api/poetry.lock +++ b/api/poetry.lock @@ -8074,29 +8074,29 @@ pyasn1 = ">=0.1.3" [[package]] name = "ruff" -version = "0.6.5" +version = "0.6.8" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.6.5-py3-none-linux_armv6l.whl", hash = "sha256:7e4e308f16e07c95fc7753fc1aaac690a323b2bb9f4ec5e844a97bb7fbebd748"}, - {file = "ruff-0.6.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:932cd69eefe4daf8c7d92bd6689f7e8182571cb934ea720af218929da7bd7d69"}, - {file = "ruff-0.6.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3a8d42d11fff8d3143ff4da41742a98f8f233bf8890e9fe23077826818f8d680"}, - {file = "ruff-0.6.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a50af6e828ee692fb10ff2dfe53f05caecf077f4210fae9677e06a808275754f"}, - {file = "ruff-0.6.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:794ada3400a0d0b89e3015f1a7e01f4c97320ac665b7bc3ade24b50b54cb2972"}, - {file = "ruff-0.6.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:381413ec47f71ce1d1c614f7779d88886f406f1fd53d289c77e4e533dc6ea200"}, - {file = "ruff-0.6.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:52e75a82bbc9b42e63c08d22ad0ac525117e72aee9729a069d7c4f235fc4d276"}, - {file = "ruff-0.6.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09c72a833fd3551135ceddcba5ebdb68ff89225d30758027280968c9acdc7810"}, - {file = "ruff-0.6.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:800c50371bdcb99b3c1551d5691e14d16d6f07063a518770254227f7f6e8c178"}, - {file = "ruff-0.6.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e25ddd9cd63ba1f3bd51c1f09903904a6adf8429df34f17d728a8fa11174253"}, - {file = "ruff-0.6.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7291e64d7129f24d1b0c947ec3ec4c0076e958d1475c61202497c6aced35dd19"}, - {file = "ruff-0.6.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9ad7dfbd138d09d9a7e6931e6a7e797651ce29becd688be8a0d4d5f8177b4b0c"}, - {file = "ruff-0.6.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:005256d977021790cc52aa23d78f06bb5090dc0bfbd42de46d49c201533982ae"}, - {file = "ruff-0.6.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:482c1e6bfeb615eafc5899127b805d28e387bd87db38b2c0c41d271f5e58d8cc"}, - {file = "ruff-0.6.5-py3-none-win32.whl", hash = "sha256:cf4d3fa53644137f6a4a27a2b397381d16454a1566ae5335855c187fbf67e4f5"}, - {file = "ruff-0.6.5-py3-none-win_amd64.whl", hash = "sha256:3e42a57b58e3612051a636bc1ac4e6b838679530235520e8f095f7c44f706ff9"}, - {file = "ruff-0.6.5-py3-none-win_arm64.whl", hash = "sha256:51935067740773afdf97493ba9b8231279e9beef0f2a8079188c4776c25688e0"}, - {file = "ruff-0.6.5.tar.gz", hash = "sha256:4d32d87fab433c0cf285c3683dd4dae63be05fd7a1d65b3f5bf7cdd05a6b96fb"}, + {file = "ruff-0.6.8-py3-none-linux_armv6l.whl", hash = "sha256:77944bca110ff0a43b768f05a529fecd0706aac7bcce36d7f1eeb4cbfca5f0f2"}, + {file = "ruff-0.6.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:27b87e1801e786cd6ede4ada3faa5e254ce774de835e6723fd94551464c56b8c"}, + {file = "ruff-0.6.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:cd48f945da2a6334f1793d7f701725a76ba93bf3d73c36f6b21fb04d5338dcf5"}, + {file = "ruff-0.6.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:677e03c00f37c66cea033274295a983c7c546edea5043d0c798833adf4cf4c6f"}, + {file = "ruff-0.6.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9f1476236b3eacfacfc0f66aa9e6cd39f2a624cb73ea99189556015f27c0bdeb"}, + {file = "ruff-0.6.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f5a2f17c7d32991169195d52a04c95b256378bbf0de8cb98478351eb70d526f"}, + {file = "ruff-0.6.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5fd0d4b7b1457c49e435ee1e437900ced9b35cb8dc5178921dfb7d98d65a08d0"}, + {file = "ruff-0.6.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8034b19b993e9601f2ddf2c517451e17a6ab5cdb1c13fdff50c1442a7171d87"}, + {file = "ruff-0.6.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6cfb227b932ba8ef6e56c9f875d987973cd5e35bc5d05f5abf045af78ad8e098"}, + {file = "ruff-0.6.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ef0411eccfc3909269fed47c61ffebdcb84a04504bafa6b6df9b85c27e813b0"}, + {file = "ruff-0.6.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:007dee844738c3d2e6c24ab5bc7d43c99ba3e1943bd2d95d598582e9c1b27750"}, + {file = "ruff-0.6.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ce60058d3cdd8490e5e5471ef086b3f1e90ab872b548814e35930e21d848c9ce"}, + {file = "ruff-0.6.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1085c455d1b3fdb8021ad534379c60353b81ba079712bce7a900e834859182fa"}, + {file = "ruff-0.6.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:70edf6a93b19481affd287d696d9e311388d808671bc209fb8907b46a8c3af44"}, + {file = "ruff-0.6.8-py3-none-win32.whl", hash = "sha256:792213f7be25316f9b46b854df80a77e0da87ec66691e8f012f887b4a671ab5a"}, + {file = "ruff-0.6.8-py3-none-win_amd64.whl", hash = "sha256:ec0517dc0f37cad14a5319ba7bba6e7e339d03fbf967a6d69b0907d61be7a263"}, + {file = "ruff-0.6.8-py3-none-win_arm64.whl", hash = "sha256:8d3bb2e3fbb9875172119021a13eed38849e762499e3cfde9588e4b4d70968dc"}, + {file = "ruff-0.6.8.tar.gz", hash = "sha256:a5bf44b1aa0adaf6d9d20f86162b34f7c593bfedabc51239953e446aefc8ce18"}, ] [[package]] @@ -10501,4 +10501,4 @@ cffi = ["cffi (>=1.11)"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.13" -content-hash = "69b42bb1ff033f14e199fee8335356275099421d72bbd7037b7a991ea65cae08" +content-hash = "c4580c22e2b220c8c80dbc3f765060a09e14874ed29b690c13a533bf0365e789" diff --git a/api/pyproject.toml b/api/pyproject.toml index f004865d5f..64b35621b2 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -286,4 +286,4 @@ optional = true [tool.poetry.group.lint.dependencies] dotenv-linter = "~0.5.0" -ruff = "~0.6.5" +ruff = "~0.6.8" diff --git a/api/tests/integration_tests/tools/__mock/http.py b/api/tests/integration_tests/tools/__mock/http.py index d3c1f3101c..42cf87e317 100644 --- a/api/tests/integration_tests/tools/__mock/http.py +++ b/api/tests/integration_tests/tools/__mock/http.py @@ -17,7 +17,7 @@ class MockedHttp: request = httpx.Request( method, url, params=kwargs.get("params"), headers=kwargs.get("headers"), cookies=kwargs.get("cookies") ) - data = kwargs.get("data", None) + data = kwargs.get("data") resp = json.dumps(data).encode("utf-8") if data else b"OK" response = httpx.Response( status_code=200, diff --git a/api/tests/integration_tests/workflow/nodes/__mock/http.py b/api/tests/integration_tests/workflow/nodes/__mock/http.py index f1ab23b002..ec013183b7 100644 --- a/api/tests/integration_tests/workflow/nodes/__mock/http.py +++ b/api/tests/integration_tests/workflow/nodes/__mock/http.py @@ -22,8 +22,8 @@ class MockedHttp: return response # get data, files - data = kwargs.get("data", None) - files = kwargs.get("files", None) + data = kwargs.get("data") + files = kwargs.get("files") if data is not None: resp = dumps(data).encode("utf-8") elif files is not None: From 4ec977eabafefc3859ef04425ec669ce87b5483e Mon Sep 17 00:00:00 2001 From: -LAN- Date: Sun, 29 Sep 2024 16:12:42 +0800 Subject: [PATCH 011/136] fix(workflow): update tagging logic in GitHub Actions (#8882) --- .github/workflows/build-push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-push.yml b/.github/workflows/build-push.yml index 407bd47d9b..6daaaf5791 100644 --- a/.github/workflows/build-push.yml +++ b/.github/workflows/build-push.yml @@ -125,7 +125,7 @@ jobs: with: images: ${{ env[matrix.image_name_env] }} tags: | - type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }} + type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') && !contains(github.ref, '-') }} type=ref,event=branch type=sha,enable=true,priority=100,prefix=,suffix=,format=long type=raw,value=${{ github.ref_name }},enable=${{ startsWith(github.ref, 'refs/tags/') }} From e4ed916baadb10ffd22ec1772e56b4fcefa1b57f Mon Sep 17 00:00:00 2001 From: longzhihun <38651850@qq.com> Date: Sun, 29 Sep 2024 16:12:56 +0800 Subject: [PATCH 012/136] Add Jamba and Llama3.2 model support (#8878) --- .../bedrock/llm/_position.yaml | 6 ++++ .../llm/ai21.jamba-1-5-large-v1.0.yaml | 26 ++++++++++++++++ .../bedrock/llm/ai21.jamba-1-5-mini-v1.0.yaml | 26 ++++++++++++++++ .../model_providers/bedrock/llm/llm.py | 2 ++ .../us.meta.llama3-2-11b-instruct-v1.0.yaml | 29 +++++++++++++++++ .../us.meta.llama3-2-1b-instruct-v1.0.yaml | 26 ++++++++++++++++ .../us.meta.llama3-2-3b-instruct-v1.0.yaml | 26 ++++++++++++++++ .../us.meta.llama3-2-90b-instruct-v1.0.yaml | 31 +++++++++++++++++++ 8 files changed, 172 insertions(+) create mode 100644 api/core/model_runtime/model_providers/bedrock/llm/ai21.jamba-1-5-large-v1.0.yaml create mode 100644 api/core/model_runtime/model_providers/bedrock/llm/ai21.jamba-1-5-mini-v1.0.yaml create mode 100644 api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-11b-instruct-v1.0.yaml create mode 100644 api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-1b-instruct-v1.0.yaml create mode 100644 api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-3b-instruct-v1.0.yaml create mode 100644 api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-90b-instruct-v1.0.yaml diff --git a/api/core/model_runtime/model_providers/bedrock/llm/_position.yaml b/api/core/model_runtime/model_providers/bedrock/llm/_position.yaml index 86c8061dee..47e2b020fd 100644 --- a/api/core/model_runtime/model_providers/bedrock/llm/_position.yaml +++ b/api/core/model_runtime/model_providers/bedrock/llm/_position.yaml @@ -6,6 +6,8 @@ - anthropic.claude-v2:1 - anthropic.claude-3-sonnet-v1:0 - anthropic.claude-3-haiku-v1:0 +- ai21.jamba-1-5-large-v1:0 +- ai21.jamba-1-5-mini-v1:0 - cohere.command-light-text-v14 - cohere.command-text-v14 - cohere.command-r-plus-v1.0 @@ -15,6 +17,10 @@ - meta.llama3-1-405b-instruct-v1:0 - meta.llama3-8b-instruct-v1:0 - meta.llama3-70b-instruct-v1:0 +- us.meta.llama3-2-1b-instruct-v1:0 +- us.meta.llama3-2-3b-instruct-v1:0 +- us.meta.llama3-2-11b-instruct-v1:0 +- us.meta.llama3-2-90b-instruct-v1:0 - meta.llama2-13b-chat-v1 - meta.llama2-70b-chat-v1 - mistral.mistral-large-2407-v1:0 diff --git a/api/core/model_runtime/model_providers/bedrock/llm/ai21.jamba-1-5-large-v1.0.yaml b/api/core/model_runtime/model_providers/bedrock/llm/ai21.jamba-1-5-large-v1.0.yaml new file mode 100644 index 0000000000..276c7312ce --- /dev/null +++ b/api/core/model_runtime/model_providers/bedrock/llm/ai21.jamba-1-5-large-v1.0.yaml @@ -0,0 +1,26 @@ +model: ai21.jamba-1-5-large-v1:0 +label: + en_US: Jamba 1.5 Large +model_type: llm +model_properties: + mode: completion + context_size: 256000 +parameter_rules: + - name: temperature + use_template: temperature + default: 1 + min: 0.0 + max: 2.0 + - name: top_p + use_template: top_p + - name: max_gen_len + use_template: max_tokens + required: true + default: 4096 + min: 1 + max: 4096 +pricing: + input: '0.002' + output: '0.008' + unit: '0.001' + currency: USD diff --git a/api/core/model_runtime/model_providers/bedrock/llm/ai21.jamba-1-5-mini-v1.0.yaml b/api/core/model_runtime/model_providers/bedrock/llm/ai21.jamba-1-5-mini-v1.0.yaml new file mode 100644 index 0000000000..3461d8ab71 --- /dev/null +++ b/api/core/model_runtime/model_providers/bedrock/llm/ai21.jamba-1-5-mini-v1.0.yaml @@ -0,0 +1,26 @@ +model: ai21.jamba-1-5-mini-v1:0 +label: + en_US: Jamba 1.5 Mini +model_type: llm +model_properties: + mode: completion + context_size: 256000 +parameter_rules: + - name: temperature + use_template: temperature + default: 1 + min: 0.0 + max: 2.0 + - name: top_p + use_template: top_p + - name: max_gen_len + use_template: max_tokens + required: true + default: 4096 + min: 1 + max: 4096 +pricing: + input: '0.0002' + output: '0.0004' + unit: '0.001' + currency: USD diff --git a/api/core/model_runtime/model_providers/bedrock/llm/llm.py b/api/core/model_runtime/model_providers/bedrock/llm/llm.py index 77bab0c294..d1961784f2 100644 --- a/api/core/model_runtime/model_providers/bedrock/llm/llm.py +++ b/api/core/model_runtime/model_providers/bedrock/llm/llm.py @@ -63,6 +63,7 @@ class BedrockLargeLanguageModel(LargeLanguageModel): {"prefix": "us.anthropic.claude-3", "support_system_prompts": True, "support_tool_use": True}, {"prefix": "eu.anthropic.claude-3", "support_system_prompts": True, "support_tool_use": True}, {"prefix": "anthropic.claude-3", "support_system_prompts": True, "support_tool_use": True}, + {"prefix": "us.meta.llama3-2", "support_system_prompts": True, "support_tool_use": True}, {"prefix": "meta.llama", "support_system_prompts": True, "support_tool_use": False}, {"prefix": "mistral.mistral-7b-instruct", "support_system_prompts": False, "support_tool_use": False}, {"prefix": "mistral.mixtral-8x7b-instruct", "support_system_prompts": False, "support_tool_use": False}, @@ -70,6 +71,7 @@ class BedrockLargeLanguageModel(LargeLanguageModel): {"prefix": "mistral.mistral-small", "support_system_prompts": True, "support_tool_use": True}, {"prefix": "cohere.command-r", "support_system_prompts": True, "support_tool_use": True}, {"prefix": "amazon.titan", "support_system_prompts": False, "support_tool_use": False}, + {"prefix": "ai21.jamba-1-5", "support_system_prompts": True, "support_tool_use": False}, ] @staticmethod diff --git a/api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-11b-instruct-v1.0.yaml b/api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-11b-instruct-v1.0.yaml new file mode 100644 index 0000000000..029f428776 --- /dev/null +++ b/api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-11b-instruct-v1.0.yaml @@ -0,0 +1,29 @@ +model: us.meta.llama3-2-11b-instruct-v1:0 +label: + en_US: US Meta Llama 3.2 11B Instruct +model_type: llm +features: + - vision + - tool-call +model_properties: + mode: completion + context_size: 128000 +parameter_rules: + - name: temperature + use_template: temperature + default: 0.5 + min: 0.0 + max: 1 + - name: top_p + use_template: top_p + - name: max_gen_len + use_template: max_tokens + required: true + default: 512 + min: 1 + max: 2048 +pricing: + input: '0.00035' + output: '0.00035' + unit: '0.001' + currency: USD diff --git a/api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-1b-instruct-v1.0.yaml b/api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-1b-instruct-v1.0.yaml new file mode 100644 index 0000000000..51c8474e54 --- /dev/null +++ b/api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-1b-instruct-v1.0.yaml @@ -0,0 +1,26 @@ +model: us.meta.llama3-2-1b-instruct-v1:0 +label: + en_US: US Meta Llama 3.2 1B Instruct +model_type: llm +model_properties: + mode: completion + context_size: 128000 +parameter_rules: + - name: temperature + use_template: temperature + default: 0.5 + min: 0.0 + max: 1 + - name: top_p + use_template: top_p + - name: max_gen_len + use_template: max_tokens + required: true + default: 512 + min: 1 + max: 2048 +pricing: + input: '0.0001' + output: '0.0001' + unit: '0.001' + currency: USD diff --git a/api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-3b-instruct-v1.0.yaml b/api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-3b-instruct-v1.0.yaml new file mode 100644 index 0000000000..472cc7403e --- /dev/null +++ b/api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-3b-instruct-v1.0.yaml @@ -0,0 +1,26 @@ +model: us.meta.llama3-2-3b-instruct-v1:0 +label: + en_US: US Meta Llama 3.2 3B Instruct +model_type: llm +model_properties: + mode: completion + context_size: 128000 +parameter_rules: + - name: temperature + use_template: temperature + default: 0.5 + min: 0.0 + max: 1 + - name: top_p + use_template: top_p + - name: max_gen_len + use_template: max_tokens + required: true + default: 512 + min: 1 + max: 2048 +pricing: + input: '0.00015' + output: '0.00015' + unit: '0.001' + currency: USD diff --git a/api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-90b-instruct-v1.0.yaml b/api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-90b-instruct-v1.0.yaml new file mode 100644 index 0000000000..cecd0236ca --- /dev/null +++ b/api/core/model_runtime/model_providers/bedrock/llm/us.meta.llama3-2-90b-instruct-v1.0.yaml @@ -0,0 +1,31 @@ +model: us.meta.llama3-2-90b-instruct-v1:0 +label: + en_US: US Meta Llama 3.2 90B Instruct +model_type: llm +features: + - tool-call +model_properties: + mode: completion + context_size: 128000 +parameter_rules: + - name: temperature + use_template: temperature + default: 0.5 + min: 0.0 + max: 1 + - name: top_p + use_template: top_p + default: 0.9 + min: 0 + max: 1 + - name: max_gen_len + use_template: max_tokens + required: true + default: 512 + min: 1 + max: 2048 +pricing: + input: '0.002' + output: '0.002' + unit: '0.001' + currency: USD From c531b4a911f34357e2beeff77bdc5e1ecb4333de Mon Sep 17 00:00:00 2001 From: chenxu9741 Date: Sun, 29 Sep 2024 16:13:20 +0800 Subject: [PATCH 013/136] =?UTF-8?q?fix:=20#8843=20event:=20tts=5Fmessage?= =?UTF-8?q?=5Fend=20always=20return=20in=20api=20streaming=20resp=E2=80=A6?= =?UTF-8?q?=20(#8846)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/core/app/apps/advanced_chat/generate_task_pipeline.py | 3 ++- api/core/app/apps/workflow/generate_task_pipeline.py | 3 ++- .../app/task_pipeline/easy_ui_based_generate_task_pipeline.py | 3 ++- .../model_providers/zhipuai/zhipuai_sdk/core/_base_models.py | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/api/core/app/apps/advanced_chat/generate_task_pipeline.py b/api/core/app/apps/advanced_chat/generate_task_pipeline.py index 94206a1b1c..897b6fd063 100644 --- a/api/core/app/apps/advanced_chat/generate_task_pipeline.py +++ b/api/core/app/apps/advanced_chat/generate_task_pipeline.py @@ -231,7 +231,8 @@ class AdvancedChatAppGenerateTaskPipeline(BasedGenerateTaskPipeline, WorkflowCyc except Exception as e: logger.error(e) break - yield MessageAudioEndStreamResponse(audio="", task_id=task_id) + if tts_publisher: + yield MessageAudioEndStreamResponse(audio="", task_id=task_id) def _process_stream_response( self, diff --git a/api/core/app/apps/workflow/generate_task_pipeline.py b/api/core/app/apps/workflow/generate_task_pipeline.py index 93edf8e0e8..798847a507 100644 --- a/api/core/app/apps/workflow/generate_task_pipeline.py +++ b/api/core/app/apps/workflow/generate_task_pipeline.py @@ -212,7 +212,8 @@ class WorkflowAppGenerateTaskPipeline(BasedGenerateTaskPipeline, WorkflowCycleMa except Exception as e: logger.error(e) break - yield MessageAudioEndStreamResponse(audio="", task_id=task_id) + if tts_publisher: + yield MessageAudioEndStreamResponse(audio="", task_id=task_id) def _process_stream_response( self, diff --git a/api/core/app/task_pipeline/easy_ui_based_generate_task_pipeline.py b/api/core/app/task_pipeline/easy_ui_based_generate_task_pipeline.py index 8f834b6458..917649f34e 100644 --- a/api/core/app/task_pipeline/easy_ui_based_generate_task_pipeline.py +++ b/api/core/app/task_pipeline/easy_ui_based_generate_task_pipeline.py @@ -248,7 +248,8 @@ class EasyUIBasedGenerateTaskPipeline(BasedGenerateTaskPipeline, MessageCycleMan else: start_listener_time = time.time() yield MessageAudioStreamResponse(audio=audio.audio, task_id=task_id) - yield MessageAudioEndStreamResponse(audio="", task_id=task_id) + if publisher: + yield MessageAudioEndStreamResponse(audio="", task_id=task_id) def _process_stream_response( self, publisher: AppGeneratorTTSPublisher, trace_manager: Optional[TraceQueueManager] = None diff --git a/api/core/model_runtime/model_providers/zhipuai/zhipuai_sdk/core/_base_models.py b/api/core/model_runtime/model_providers/zhipuai/zhipuai_sdk/core/_base_models.py index 6d8ba700b7..69b1d3a83d 100644 --- a/api/core/model_runtime/model_providers/zhipuai/zhipuai_sdk/core/_base_models.py +++ b/api/core/model_runtime/model_providers/zhipuai/zhipuai_sdk/core/_base_models.py @@ -48,7 +48,7 @@ from ._utils import ( ) if TYPE_CHECKING: - from pydantic_core.core_schema import LiteralSchema, ModelField, ModelFieldsSchema + from pydantic_core.core_schema import ModelField __all__ = ["BaseModel", "GenericModel"] _BaseModelT = TypeVar("_BaseModelT", bound="BaseModel") From 42dfde65468ec8b945eb086d88441baf1fc22e2d Mon Sep 17 00:00:00 2001 From: zhuhao <37029601+hwzhuhao@users.noreply.github.com> Date: Sun, 29 Sep 2024 16:16:56 +0800 Subject: [PATCH 014/136] docs: add english versions for the files customizable_model_scale_out and predefined_model_scale_out (#8871) --- .../en_US/customizable_model_scale_out.md | 310 ++++++++++++++++++ .../docs/en_US/images/index/image-1.png | Bin 0 -> 235102 bytes .../docs/en_US/images/index/image-2.png | Bin 0 -> 210087 bytes .../docs/en_US/images/index/image-3.png | Bin 0 -> 44778 bytes .../docs/en_US/images/index/image.png | Bin 0 -> 267979 bytes .../docs/en_US/predefined_model_scale_out.md | 173 ++++++++++ .../docs/en_US/provider_scale_out.md | 2 +- .../docs/zh_Hans/provider_scale_out.md | 2 +- 8 files changed, 485 insertions(+), 2 deletions(-) create mode 100644 api/core/model_runtime/docs/en_US/customizable_model_scale_out.md create mode 100644 api/core/model_runtime/docs/en_US/images/index/image-1.png create mode 100644 api/core/model_runtime/docs/en_US/images/index/image-2.png create mode 100644 api/core/model_runtime/docs/en_US/images/index/image-3.png create mode 100644 api/core/model_runtime/docs/en_US/images/index/image.png create mode 100644 api/core/model_runtime/docs/en_US/predefined_model_scale_out.md diff --git a/api/core/model_runtime/docs/en_US/customizable_model_scale_out.md b/api/core/model_runtime/docs/en_US/customizable_model_scale_out.md new file mode 100644 index 0000000000..f5b806ade6 --- /dev/null +++ b/api/core/model_runtime/docs/en_US/customizable_model_scale_out.md @@ -0,0 +1,310 @@ +## Custom Integration of Pre-defined Models + +### Introduction + +After completing the vendors integration, the next step is to connect the vendor's models. To illustrate the entire connection process, we will use Xinference as an example to demonstrate a complete vendor integration. + +It is important to note that for custom models, each model connection requires a complete vendor credential. + +Unlike pre-defined models, a custom vendor integration always includes the following two parameters, which do not need to be defined in the vendor YAML file. + +![](images/index/image-3.png) + +As mentioned earlier, vendors do not need to implement validate_provider_credential. The runtime will automatically call the corresponding model layer's validate_credentials to validate the credentials based on the model type and name selected by the user. + +### Writing the Vendor YAML + +First, we need to identify the types of models supported by the vendor we are integrating. + +Currently supported model types are as follows: + +- `llm` Text Generation Models + +- `text_embedding` Text Embedding Models + +- `rerank` Rerank Models + +- `speech2text` Speech-to-Text + +- `tts` Text-to-Speech + +- `moderation` Moderation + +Xinference supports LLM, Text Embedding, and Rerank. So we will start by writing xinference.yaml. + +```yaml +provider: xinference #Define the vendor identifier +label: # Vendor display name, supports both en_US (English) and zh_Hans (Simplified Chinese). If zh_Hans is not set, it will use en_US by default. + en_US: Xorbits Inference +icon_small: # Small icon, refer to other vendors' icons stored in the _assets directory within the vendor implementation directory; follows the same language policy as the label + en_US: icon_s_en.svg +icon_large: # Large icon + en_US: icon_l_en.svg +help: # Help information + title: + en_US: How to deploy Xinference + zh_Hans: 如何部署 Xinference + url: + en_US: https://github.com/xorbitsai/inference +supported_model_types: # Supported model types. Xinference supports LLM, Text Embedding, and Rerank +- llm +- text-embedding +- rerank +configurate_methods: # Since Xinference is a locally deployed vendor with no predefined models, users need to deploy whatever models they need according to Xinference documentation. Thus, it only supports custom models. +- customizable-model +provider_credential_schema: + credential_form_schemas: +``` + + +Then, we need to determine what credentials are required to define a model in Xinference. + +- Since it supports three different types of models, we need to specify the model_type to denote the model type. Here is how we can define it: + +```yaml +provider_credential_schema: + credential_form_schemas: + - variable: model_type + type: select + label: + en_US: Model type + zh_Hans: 模型类型 + required: true + options: + - value: text-generation + label: + en_US: Language Model + zh_Hans: 语言模型 + - value: embeddings + label: + en_US: Text Embedding + - value: reranking + label: + en_US: Rerank +``` + +- Next, each model has its own model_name, so we need to define that here: + +```yaml + - variable: model_name + type: text-input + label: + en_US: Model name + zh_Hans: 模型名称 + required: true + placeholder: + zh_Hans: 填写模型名称 + en_US: Input model name +``` + +- Specify the Xinference local deployment address: + +```yaml + - variable: server_url + label: + zh_Hans: 服务器URL + en_US: Server url + type: text-input + required: true + placeholder: + zh_Hans: 在此输入Xinference的服务器地址,如 https://example.com/xxx + en_US: Enter the url of your Xinference, for example https://example.com/xxx +``` + +- Each model has a unique model_uid, so we also need to define that here: + +```yaml + - variable: model_uid + label: + zh_Hans: 模型UID + en_US: Model uid + type: text-input + required: true + placeholder: + zh_Hans: 在此输入您的Model UID + en_US: Enter the model uid +``` + +Now, we have completed the basic definition of the vendor. + +### Writing the Model Code + +Next, let's take the `llm` type as an example and write `xinference.llm.llm.py`. + +In `llm.py`, create a Xinference LLM class, we name it `XinferenceAILargeLanguageModel` (this can be arbitrary), inheriting from the `__base.large_language_model.LargeLanguageModel` base class, and implement the following methods: + +- LLM Invocation + +Implement the core method for LLM invocation, supporting both stream and synchronous responses. + +```python +def _invoke(self, model: str, credentials: dict, + prompt_messages: list[PromptMessage], model_parameters: dict, + tools: Optional[list[PromptMessageTool]] = None, stop: Optional[list[str]] = None, + stream: bool = True, user: Optional[str] = None) \ + -> Union[LLMResult, Generator]: + """ + Invoke large language model + + :param model: model name + :param credentials: model credentials + :param prompt_messages: prompt messages + :param model_parameters: model parameters + :param tools: tools for tool usage + :param stop: stop words + :param stream: is the response a stream + :param user: unique user id + :return: full response or stream response chunk generator result + """ +``` + +When implementing, ensure to use two functions to return data separately for synchronous and stream responses. This is important because Python treats functions containing the `yield` keyword as generator functions, mandating them to return `Generator` types. Here’s an example (note that the example uses simplified parameters; in real implementation, use the parameter list as defined above): + +```python +def _invoke(self, stream: bool, **kwargs) \ + -> Union[LLMResult, Generator]: + if stream: + return self._handle_stream_response(**kwargs) + return self._handle_sync_response(**kwargs) + +def _handle_stream_response(self, **kwargs) -> Generator: + for chunk in response: + yield chunk +def _handle_sync_response(self, **kwargs) -> LLMResult: + return LLMResult(**response) +``` + +- Pre-compute Input Tokens + +If the model does not provide an interface for pre-computing tokens, you can return 0 directly. + +```python +def get_num_tokens(self, model: str, credentials: dict, prompt_messages: list[PromptMessage],tools: Optional[list[PromptMessageTool]] = None) -> int: + """ + Get number of tokens for given prompt messages + + :param model: model name + :param credentials: model credentials + :param prompt_messages: prompt messages + :param tools: tools for tool usage + :return: token count + """ +``` + + +Sometimes, you might not want to return 0 directly. In such cases, you can use `self._get_num_tokens_by_gpt2(text: str)` to get pre-computed tokens. This method is provided by the `AIModel` base class, and it uses GPT2's Tokenizer for calculation. However, it should be noted that this is only a substitute and may not be fully accurate. + +- Model Credentials Validation + +Similar to vendor credentials validation, this method validates individual model credentials. + +```python +def validate_credentials(self, model: str, credentials: dict) -> None: + """ + Validate model credentials + + :param model: model name + :param credentials: model credentials + :return: None + """ +``` + +- Model Parameter Schema + +Unlike custom types, since the YAML file does not define which parameters a model supports, we need to dynamically generate the model parameter schema. + +For instance, Xinference supports `max_tokens`, `temperature`, and `top_p` parameters. + +However, some vendors may support different parameters for different models. For example, the `OpenLLM` vendor supports `top_k`, but not all models provided by this vendor support `top_k`. Let's say model A supports `top_k` but model B does not. In such cases, we need to dynamically generate the model parameter schema, as illustrated below: + +```python + def get_customizable_model_schema(self, model: str, credentials: dict) -> AIModelEntity | None: + """ + used to define customizable model schema + """ + rules = [ + ParameterRule( + name='temperature', type=ParameterType.FLOAT, + use_template='temperature', + label=I18nObject( + zh_Hans='温度', en_US='Temperature' + ) + ), + ParameterRule( + name='top_p', type=ParameterType.FLOAT, + use_template='top_p', + label=I18nObject( + zh_Hans='Top P', en_US='Top P' + ) + ), + ParameterRule( + name='max_tokens', type=ParameterType.INT, + use_template='max_tokens', + min=1, + default=512, + label=I18nObject( + zh_Hans='最大生成长度', en_US='Max Tokens' + ) + ) + ] + + # if model is A, add top_k to rules + if model == 'A': + rules.append( + ParameterRule( + name='top_k', type=ParameterType.INT, + use_template='top_k', + min=1, + default=50, + label=I18nObject( + zh_Hans='Top K', en_US='Top K' + ) + ) + ) + + """ + some NOT IMPORTANT code here + """ + + entity = AIModelEntity( + model=model, + label=I18nObject( + en_US=model + ), + fetch_from=FetchFrom.CUSTOMIZABLE_MODEL, + model_type=model_type, + model_properties={ + ModelPropertyKey.MODE: ModelType.LLM, + }, + parameter_rules=rules + ) + + return entity +``` + +- Exception Error Mapping + +When a model invocation error occurs, it should be mapped to the runtime's specified `InvokeError` type, enabling Dify to handle different errors appropriately. + +Runtime Errors: + +- `InvokeConnectionError` Connection error during invocation +- `InvokeServerUnavailableError` Service provider unavailable +- `InvokeRateLimitError` Rate limit reached +- `InvokeAuthorizationError` Authorization failure +- `InvokeBadRequestError` Invalid request parameters + +```python + @property + def _invoke_error_mapping(self) -> dict[type[InvokeError], list[type[Exception]]]: + """ + Map model invoke error to unified error + The key is the error type thrown to the caller + The value is the error type thrown by the model, + which needs to be converted into a unified error type for the caller. + + :return: Invoke error mapping + """ +``` + +For interface method details, see: [Interfaces](./interfaces.md). For specific implementations, refer to: [llm.py](https://github.com/langgenius/dify-runtime/blob/main/lib/model_providers/anthropic/llm/llm.py). \ No newline at end of file diff --git a/api/core/model_runtime/docs/en_US/images/index/image-1.png b/api/core/model_runtime/docs/en_US/images/index/image-1.png new file mode 100644 index 0000000000000000000000000000000000000000..b158d44b29dcc2a8fa6d6d349ef8d7fb9f7d4cdd GIT binary patch literal 235102 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

@X9M|S}m8FsNi-XPvc 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 literal 0 HcmV?d00001 diff --git a/api/core/model_runtime/docs/en_US/images/index/image-2.png b/api/core/model_runtime/docs/en_US/images/index/image-2.png new file mode 100644 index 0000000000000000000000000000000000000000..c70cd3da5eea19e6e3613126ba7b42ea33e699ee GIT binary patch literal 210087 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

Grwv=!9*TatX45e$TwCGb>WAQ! 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

`)W3@@#pAC_@dQ|x)(+$>?YRnT6W-0g|M?>kwf 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%0D#vZg}-nl%E54~{*dp()))xdr`+9mv{fwj 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 literal 0 HcmV?d00001 diff --git a/api/core/model_runtime/docs/en_US/images/index/image-3.png b/api/core/model_runtime/docs/en_US/images/index/image-3.png new file mode 100644 index 0000000000000000000000000000000000000000..bf0b9a7f47fddfcb7969e4ea05e9d07b800fd8d9 GIT binary patch literal 44778 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 TKZ9(JEn7^^o1e=wba?PDUY&?8 literal 0 HcmV?d00001 diff --git a/api/core/model_runtime/docs/en_US/images/index/image.png b/api/core/model_runtime/docs/en_US/images/index/image.png new file mode 100644 index 0000000000000000000000000000000000000000..eb63d107e1c385495f3ecf7a751582099873c0c5 GIT binary patch literal 267979 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 h3*@_&N(iHYy(NxrwrA!9 Union[LLMResult, Generator]: + """ + Invoke large language model + + :param model: model name + :param credentials: model credentials + :param prompt_messages: prompt messages + :param model_parameters: model parameters + :param tools: tools for tool calling + :param stop: stop words + :param stream: is stream response + :param user: unique user id + :return: full response or stream response chunk generator result + """ +``` + +Ensure to use two functions for returning data, one for synchronous returns and the other for streaming returns, because Python identifies functions containing the `yield` keyword as generator functions, fixing the return type to `Generator`. Thus, synchronous and streaming returns need to be implemented separately, as shown below (note that the example uses simplified parameters, for actual implementation follow the above parameter list): + +```python + def _invoke(self, stream: bool, **kwargs) \ + -> Union[LLMResult, Generator]: + if stream: + return self._handle_stream_response(**kwargs) + return self._handle_sync_response(**kwargs) + + def _handle_stream_response(self, **kwargs) -> Generator: + for chunk in response: + yield chunk + def _handle_sync_response(self, **kwargs) -> LLMResult: + return LLMResult(**response) +``` + +- Pre-compute Input Tokens + +If the model does not provide an interface to precompute tokens, return 0 directly. + +```python + def get_num_tokens(self, model: str, credentials: dict, prompt_messages: list[PromptMessage], + tools: Optional[list[PromptMessageTool]] = None) -> int: + """ + Get number of tokens for given prompt messages + + :param model: model name + :param credentials: model credentials + :param prompt_messages: prompt messages + :param tools: tools for tool calling + :return: + """ +``` + +- Validate Model Credentials + +Similar to vendor credential validation, but specific to a single model. + +```python + def validate_credentials(self, model: str, credentials: dict) -> None: + """ + Validate model credentials + + :param model: model name + :param credentials: model credentials + :return: + """ +``` + +- Map Invoke Errors + +When a model call fails, map it to a specific `InvokeError` type as required by Runtime, allowing Dify to handle different errors accordingly. + +Runtime Errors: + +- `InvokeConnectionError` Connection error + +- `InvokeServerUnavailableError` Service provider unavailable +- `InvokeRateLimitError` Rate limit reached +- `InvokeAuthorizationError` Authorization failed +- `InvokeBadRequestError` Parameter error + +```python + @property + def _invoke_error_mapping(self) -> dict[type[InvokeError], list[type[Exception]]]: + """ + Map model invoke error to unified error + The key is the error type thrown to the caller + The value is the error type thrown by the model, + which needs to be converted into a unified error type for the caller. + + :return: Invoke error mapping + """ +``` + +For interface method explanations, see: [Interfaces](./interfaces.md). For detailed implementation, refer to: [llm.py](https://github.com/langgenius/dify-runtime/blob/main/lib/model_providers/anthropic/llm/llm.py). \ No newline at end of file diff --git a/api/core/model_runtime/docs/en_US/provider_scale_out.md b/api/core/model_runtime/docs/en_US/provider_scale_out.md index ba356c5cab..07be5811d3 100644 --- a/api/core/model_runtime/docs/en_US/provider_scale_out.md +++ b/api/core/model_runtime/docs/en_US/provider_scale_out.md @@ -58,7 +58,7 @@ provider_credential_schema: # Provider credential rules, as Anthropic only supp en_US: Enter your API URL ``` -You can also refer to the YAML configuration information under other provider directories in `model_providers`. The complete YAML rules are available at: [Schema](schema.md#Provider). +You can also refer to the YAML configuration information under other provider directories in `model_providers`. The complete YAML rules are available at: [Schema](schema.md#provider). ### Implementing Provider Code diff --git a/api/core/model_runtime/docs/zh_Hans/provider_scale_out.md b/api/core/model_runtime/docs/zh_Hans/provider_scale_out.md index b34544c789..78aad8876f 100644 --- a/api/core/model_runtime/docs/zh_Hans/provider_scale_out.md +++ b/api/core/model_runtime/docs/zh_Hans/provider_scale_out.md @@ -117,7 +117,7 @@ model_credential_schema: en_US: Enter your API Base ``` -也可以参考 `model_providers` 目录下其他供应商目录下的 YAML 配置信息,完整的 YAML 规则见:[Schema](schema.md#Provider)。 +也可以参考 `model_providers` 目录下其他供应商目录下的 YAML 配置信息,完整的 YAML 规则见:[Schema](schema.md#provider)。 #### 实现供应商代码 From fb49413a41fd22828fe306aadd2e2fea2648f6ec Mon Sep 17 00:00:00 2001 From: zhuhao <37029601+hwzhuhao@users.noreply.github.com> Date: Sun, 29 Sep 2024 16:55:59 +0800 Subject: [PATCH 015/136] feat: add voyage ai as a new model provider (#8747) --- .../model_providers/_position.yaml | 1 + .../model_providers/voyage/__init__.py | 0 .../voyage/_assets/icon_l_en.svg | 21 +++ .../voyage/_assets/icon_s_en.svg | 8 + .../model_providers/voyage/rerank/__init__.py | 0 .../voyage/rerank/rerank-1.yaml | 4 + .../voyage/rerank/rerank-lite-1.yaml | 4 + .../model_providers/voyage/rerank/rerank.py | 123 +++++++++++++ .../voyage/text_embedding/__init__.py | 0 .../voyage/text_embedding/text_embedding.py | 172 ++++++++++++++++++ .../voyage/text_embedding/voyage-3-lite.yaml | 8 + .../voyage/text_embedding/voyage-3.yaml | 8 + .../model_providers/voyage/voyage.py | 28 +++ .../model_providers/voyage/voyage.yaml | 31 ++++ api/pyproject.toml | 1 + .../model_runtime/voyage/__init__.py | 0 .../model_runtime/voyage/test_provider.py | 25 +++ .../model_runtime/voyage/test_rerank.py | 92 ++++++++++ .../voyage/test_text_embedding.py | 70 +++++++ dev/pytest/pytest_model_runtime.sh | 3 +- 20 files changed, 598 insertions(+), 1 deletion(-) create mode 100644 api/core/model_runtime/model_providers/voyage/__init__.py create mode 100644 api/core/model_runtime/model_providers/voyage/_assets/icon_l_en.svg create mode 100644 api/core/model_runtime/model_providers/voyage/_assets/icon_s_en.svg create mode 100644 api/core/model_runtime/model_providers/voyage/rerank/__init__.py create mode 100644 api/core/model_runtime/model_providers/voyage/rerank/rerank-1.yaml create mode 100644 api/core/model_runtime/model_providers/voyage/rerank/rerank-lite-1.yaml create mode 100644 api/core/model_runtime/model_providers/voyage/rerank/rerank.py create mode 100644 api/core/model_runtime/model_providers/voyage/text_embedding/__init__.py create mode 100644 api/core/model_runtime/model_providers/voyage/text_embedding/text_embedding.py create mode 100644 api/core/model_runtime/model_providers/voyage/text_embedding/voyage-3-lite.yaml create mode 100644 api/core/model_runtime/model_providers/voyage/text_embedding/voyage-3.yaml create mode 100644 api/core/model_runtime/model_providers/voyage/voyage.py create mode 100644 api/core/model_runtime/model_providers/voyage/voyage.yaml create mode 100644 api/tests/integration_tests/model_runtime/voyage/__init__.py create mode 100644 api/tests/integration_tests/model_runtime/voyage/test_provider.py create mode 100644 api/tests/integration_tests/model_runtime/voyage/test_rerank.py create mode 100644 api/tests/integration_tests/model_runtime/voyage/test_text_embedding.py diff --git a/api/core/model_runtime/model_providers/_position.yaml b/api/core/model_runtime/model_providers/_position.yaml index 80db22ea84..89fccef659 100644 --- a/api/core/model_runtime/model_providers/_position.yaml +++ b/api/core/model_runtime/model_providers/_position.yaml @@ -40,3 +40,4 @@ - fireworks - mixedbread - nomic +- voyage diff --git a/api/core/model_runtime/model_providers/voyage/__init__.py b/api/core/model_runtime/model_providers/voyage/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/api/core/model_runtime/model_providers/voyage/_assets/icon_l_en.svg b/api/core/model_runtime/model_providers/voyage/_assets/icon_l_en.svg new file mode 100644 index 0000000000..a961f5e435 --- /dev/null +++ b/api/core/model_runtime/model_providers/voyage/_assets/icon_l_en.svg @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/api/core/model_runtime/model_providers/voyage/_assets/icon_s_en.svg b/api/core/model_runtime/model_providers/voyage/_assets/icon_s_en.svg new file mode 100644 index 0000000000..2c4e121dd7 --- /dev/null +++ b/api/core/model_runtime/model_providers/voyage/_assets/icon_s_en.svg @@ -0,0 +1,8 @@ + + + voyage + + + + + \ No newline at end of file diff --git a/api/core/model_runtime/model_providers/voyage/rerank/__init__.py b/api/core/model_runtime/model_providers/voyage/rerank/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/api/core/model_runtime/model_providers/voyage/rerank/rerank-1.yaml b/api/core/model_runtime/model_providers/voyage/rerank/rerank-1.yaml new file mode 100644 index 0000000000..9c894eda85 --- /dev/null +++ b/api/core/model_runtime/model_providers/voyage/rerank/rerank-1.yaml @@ -0,0 +1,4 @@ +model: rerank-1 +model_type: rerank +model_properties: + context_size: 8000 diff --git a/api/core/model_runtime/model_providers/voyage/rerank/rerank-lite-1.yaml b/api/core/model_runtime/model_providers/voyage/rerank/rerank-lite-1.yaml new file mode 100644 index 0000000000..b052d6f000 --- /dev/null +++ b/api/core/model_runtime/model_providers/voyage/rerank/rerank-lite-1.yaml @@ -0,0 +1,4 @@ +model: rerank-lite-1 +model_type: rerank +model_properties: + context_size: 4000 diff --git a/api/core/model_runtime/model_providers/voyage/rerank/rerank.py b/api/core/model_runtime/model_providers/voyage/rerank/rerank.py new file mode 100644 index 0000000000..33fdebbb45 --- /dev/null +++ b/api/core/model_runtime/model_providers/voyage/rerank/rerank.py @@ -0,0 +1,123 @@ +from typing import Optional + +import httpx + +from core.model_runtime.entities.common_entities import I18nObject +from core.model_runtime.entities.model_entities import AIModelEntity, FetchFrom, ModelPropertyKey, ModelType +from core.model_runtime.entities.rerank_entities import RerankDocument, RerankResult +from core.model_runtime.errors.invoke import ( + InvokeAuthorizationError, + InvokeBadRequestError, + InvokeConnectionError, + InvokeError, + InvokeRateLimitError, + InvokeServerUnavailableError, +) +from core.model_runtime.errors.validate import CredentialsValidateFailedError +from core.model_runtime.model_providers.__base.rerank_model import RerankModel + + +class VoyageRerankModel(RerankModel): + """ + Model class for Voyage rerank model. + """ + + def _invoke( + self, + model: str, + credentials: dict, + query: str, + docs: list[str], + score_threshold: Optional[float] = None, + top_n: Optional[int] = None, + user: Optional[str] = None, + ) -> RerankResult: + """ + Invoke rerank model + :param model: model name + :param credentials: model credentials + :param query: search query + :param docs: docs for reranking + :param score_threshold: score threshold + :param top_n: top n documents to return + :param user: unique user id + :return: rerank result + """ + if len(docs) == 0: + return RerankResult(model=model, docs=[]) + + base_url = credentials.get("base_url", "https://api.voyageai.com/v1") + base_url = base_url.removesuffix("/") + + try: + response = httpx.post( + base_url + "/rerank", + json={"model": model, "query": query, "documents": docs, "top_k": top_n, "return_documents": True}, + headers={"Authorization": f"Bearer {credentials.get('api_key')}", "Content-Type": "application/json"}, + ) + response.raise_for_status() + results = response.json() + + rerank_documents = [] + for result in results["data"]: + rerank_document = RerankDocument( + index=result["index"], + text=result["document"], + score=result["relevance_score"], + ) + if score_threshold is None or result["relevance_score"] >= score_threshold: + rerank_documents.append(rerank_document) + + return RerankResult(model=model, docs=rerank_documents) + except httpx.HTTPStatusError as e: + raise InvokeServerUnavailableError(str(e)) + + def validate_credentials(self, model: str, credentials: dict) -> None: + """ + Validate model credentials + :param model: model name + :param credentials: model credentials + :return: + """ + try: + self._invoke( + model=model, + credentials=credentials, + query="What is the capital of the United States?", + docs=[ + "Carson City is the capital city of the American state of Nevada. At the 2010 United States " + "Census, Carson City had a population of 55,274.", + "The Commonwealth of the Northern Mariana Islands is a group of islands in the Pacific Ocean that " + "are a political division controlled by the United States. Its capital is Saipan.", + ], + score_threshold=0.8, + ) + except Exception as ex: + raise CredentialsValidateFailedError(str(ex)) + + @property + def _invoke_error_mapping(self) -> dict[type[InvokeError], list[type[Exception]]]: + """ + Map model invoke error to unified error + """ + return { + InvokeConnectionError: [httpx.ConnectError], + InvokeServerUnavailableError: [httpx.RemoteProtocolError], + InvokeRateLimitError: [], + InvokeAuthorizationError: [httpx.HTTPStatusError], + InvokeBadRequestError: [httpx.RequestError], + } + + def get_customizable_model_schema(self, model: str, credentials: dict) -> AIModelEntity: + """ + generate custom model entities from credentials + """ + entity = AIModelEntity( + model=model, + label=I18nObject(en_US=model), + model_type=ModelType.RERANK, + fetch_from=FetchFrom.CUSTOMIZABLE_MODEL, + model_properties={ModelPropertyKey.CONTEXT_SIZE: int(credentials.get("context_size", "8000"))}, + ) + + return entity diff --git a/api/core/model_runtime/model_providers/voyage/text_embedding/__init__.py b/api/core/model_runtime/model_providers/voyage/text_embedding/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/api/core/model_runtime/model_providers/voyage/text_embedding/text_embedding.py b/api/core/model_runtime/model_providers/voyage/text_embedding/text_embedding.py new file mode 100644 index 0000000000..a8a4d3c15b --- /dev/null +++ b/api/core/model_runtime/model_providers/voyage/text_embedding/text_embedding.py @@ -0,0 +1,172 @@ +import time +from json import JSONDecodeError, dumps +from typing import Optional + +import requests + +from core.embedding.embedding_constant import EmbeddingInputType +from core.model_runtime.entities.common_entities import I18nObject +from core.model_runtime.entities.model_entities import AIModelEntity, FetchFrom, ModelPropertyKey, ModelType, PriceType +from core.model_runtime.entities.text_embedding_entities import EmbeddingUsage, TextEmbeddingResult +from core.model_runtime.errors.invoke import ( + InvokeAuthorizationError, + InvokeBadRequestError, + InvokeConnectionError, + InvokeError, + InvokeRateLimitError, + InvokeServerUnavailableError, +) +from core.model_runtime.errors.validate import CredentialsValidateFailedError +from core.model_runtime.model_providers.__base.text_embedding_model import TextEmbeddingModel + + +class VoyageTextEmbeddingModel(TextEmbeddingModel): + """ + Model class for Voyage text embedding model. + """ + + api_base: str = "https://api.voyageai.com/v1" + + def _invoke( + self, + model: str, + credentials: dict, + texts: list[str], + user: Optional[str] = None, + input_type: EmbeddingInputType = EmbeddingInputType.DOCUMENT, + ) -> TextEmbeddingResult: + """ + Invoke text embedding model + + :param model: model name + :param credentials: model credentials + :param texts: texts to embed + :param user: unique user id + :param input_type: input type + :return: embeddings result + """ + api_key = credentials["api_key"] + if not api_key: + raise CredentialsValidateFailedError("api_key is required") + + base_url = credentials.get("base_url", self.api_base) + base_url = base_url.removesuffix("/") + + url = base_url + "/embeddings" + headers = {"Authorization": "Bearer " + api_key, "Content-Type": "application/json"} + voyage_input_type = "null" + if input_type is not None: + voyage_input_type = input_type.value + data = {"model": model, "input": texts, "input_type": voyage_input_type} + + try: + response = requests.post(url, headers=headers, data=dumps(data)) + except Exception as e: + raise InvokeConnectionError(str(e)) + + if response.status_code != 200: + try: + resp = response.json() + msg = resp["detail"] + if response.status_code == 401: + raise InvokeAuthorizationError(msg) + elif response.status_code == 429: + raise InvokeRateLimitError(msg) + elif response.status_code == 500: + raise InvokeServerUnavailableError(msg) + else: + raise InvokeBadRequestError(msg) + except JSONDecodeError as e: + raise InvokeServerUnavailableError( + f"Failed to convert response to json: {e} with text: {response.text}" + ) + + try: + resp = response.json() + embeddings = resp["data"] + usage = resp["usage"] + except Exception as e: + raise InvokeServerUnavailableError(f"Failed to convert response to json: {e} with text: {response.text}") + + usage = self._calc_response_usage(model=model, credentials=credentials, tokens=usage["total_tokens"]) + + result = TextEmbeddingResult( + model=model, embeddings=[[float(data) for data in x["embedding"]] for x in embeddings], usage=usage + ) + + return result + + def get_num_tokens(self, model: str, credentials: dict, texts: list[str]) -> int: + """ + Get number of tokens for given prompt messages + + :param model: model name + :param credentials: model credentials + :param texts: texts to embed + :return: + """ + return sum(self._get_num_tokens_by_gpt2(text) for text in texts) + + def validate_credentials(self, model: str, credentials: dict) -> None: + """ + Validate model credentials + + :param model: model name + :param credentials: model credentials + :return: + """ + try: + self._invoke(model=model, credentials=credentials, texts=["ping"]) + except Exception as e: + raise CredentialsValidateFailedError(f"Credentials validation failed: {e}") + + @property + def _invoke_error_mapping(self) -> dict[type[InvokeError], list[type[Exception]]]: + return { + InvokeConnectionError: [InvokeConnectionError], + InvokeServerUnavailableError: [InvokeServerUnavailableError], + InvokeRateLimitError: [InvokeRateLimitError], + InvokeAuthorizationError: [InvokeAuthorizationError], + InvokeBadRequestError: [KeyError, InvokeBadRequestError], + } + + def _calc_response_usage(self, model: str, credentials: dict, tokens: int) -> EmbeddingUsage: + """ + Calculate response usage + + :param model: model name + :param credentials: model credentials + :param tokens: input tokens + :return: usage + """ + # get input price info + input_price_info = self.get_price( + model=model, credentials=credentials, price_type=PriceType.INPUT, tokens=tokens + ) + + # transform usage + usage = EmbeddingUsage( + tokens=tokens, + total_tokens=tokens, + unit_price=input_price_info.unit_price, + price_unit=input_price_info.unit, + total_price=input_price_info.total_amount, + currency=input_price_info.currency, + latency=time.perf_counter() - self.started_at, + ) + + return usage + + def get_customizable_model_schema(self, model: str, credentials: dict) -> AIModelEntity: + """ + generate custom model entities from credentials + """ + entity = AIModelEntity( + model=model, + label=I18nObject(en_US=model), + model_type=ModelType.TEXT_EMBEDDING, + fetch_from=FetchFrom.CUSTOMIZABLE_MODEL, + model_properties={ModelPropertyKey.CONTEXT_SIZE: int(credentials.get("context_size"))}, + ) + + return entity diff --git a/api/core/model_runtime/model_providers/voyage/text_embedding/voyage-3-lite.yaml b/api/core/model_runtime/model_providers/voyage/text_embedding/voyage-3-lite.yaml new file mode 100644 index 0000000000..a06bb7639f --- /dev/null +++ b/api/core/model_runtime/model_providers/voyage/text_embedding/voyage-3-lite.yaml @@ -0,0 +1,8 @@ +model: voyage-3-lite +model_type: text-embedding +model_properties: + context_size: 32000 +pricing: + input: '0.00002' + unit: '0.001' + currency: USD diff --git a/api/core/model_runtime/model_providers/voyage/text_embedding/voyage-3.yaml b/api/core/model_runtime/model_providers/voyage/text_embedding/voyage-3.yaml new file mode 100644 index 0000000000..117afbcaf3 --- /dev/null +++ b/api/core/model_runtime/model_providers/voyage/text_embedding/voyage-3.yaml @@ -0,0 +1,8 @@ +model: voyage-3 +model_type: text-embedding +model_properties: + context_size: 32000 +pricing: + input: '0.00006' + unit: '0.001' + currency: USD diff --git a/api/core/model_runtime/model_providers/voyage/voyage.py b/api/core/model_runtime/model_providers/voyage/voyage.py new file mode 100644 index 0000000000..3e33b45e11 --- /dev/null +++ b/api/core/model_runtime/model_providers/voyage/voyage.py @@ -0,0 +1,28 @@ +import logging + +from core.model_runtime.entities.model_entities import ModelType +from core.model_runtime.errors.validate import CredentialsValidateFailedError +from core.model_runtime.model_providers.__base.model_provider import ModelProvider + +logger = logging.getLogger(__name__) + + +class VoyageProvider(ModelProvider): + def validate_provider_credentials(self, credentials: dict) -> None: + """ + Validate provider credentials + if validate failed, raise exception + + :param credentials: provider credentials, credentials form defined in `provider_credential_schema`. + """ + try: + model_instance = self.get_model_instance(ModelType.TEXT_EMBEDDING) + + # Use `voyage-3` model for validate, + # no matter what model you pass in, text completion model or chat model + model_instance.validate_credentials(model="voyage-3", credentials=credentials) + except CredentialsValidateFailedError as ex: + raise ex + except Exception as ex: + logger.exception(f"{self.get_provider_schema().provider} credentials validate failed") + raise ex diff --git a/api/core/model_runtime/model_providers/voyage/voyage.yaml b/api/core/model_runtime/model_providers/voyage/voyage.yaml new file mode 100644 index 0000000000..c64707800e --- /dev/null +++ b/api/core/model_runtime/model_providers/voyage/voyage.yaml @@ -0,0 +1,31 @@ +provider: voyage +label: + en_US: Voyage +description: + en_US: Embedding and Rerank Model Supported +icon_small: + en_US: icon_s_en.svg +icon_large: + en_US: icon_l_en.svg +background: "#EFFDFD" +help: + title: + en_US: Get your API key from Voyage AI + zh_Hans: 从 Voyage 获取 API Key + url: + en_US: https://dash.voyageai.com/ +supported_model_types: + - text-embedding + - rerank +configurate_methods: + - predefined-model +provider_credential_schema: + credential_form_schemas: + - variable: api_key + label: + en_US: API Key + type: secret-input + required: true + placeholder: + zh_Hans: 在此输入您的 API Key + en_US: Enter your API Key diff --git a/api/pyproject.toml b/api/pyproject.toml index 64b35621b2..e737761f3b 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -123,6 +123,7 @@ FIRECRAWL_API_KEY = "fc-" TEI_EMBEDDING_SERVER_URL = "http://a.abc.com:11451" TEI_RERANK_SERVER_URL = "http://a.abc.com:11451" MIXEDBREAD_API_KEY = "mk-aaaaaaaaaaaaaaaaaaaa" +VOYAGE_API_KEY = "va-aaaaaaaaaaaaaaaaaaaa" [tool.poetry] name = "dify-api" diff --git a/api/tests/integration_tests/model_runtime/voyage/__init__.py b/api/tests/integration_tests/model_runtime/voyage/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/api/tests/integration_tests/model_runtime/voyage/test_provider.py b/api/tests/integration_tests/model_runtime/voyage/test_provider.py new file mode 100644 index 0000000000..08978c88a9 --- /dev/null +++ b/api/tests/integration_tests/model_runtime/voyage/test_provider.py @@ -0,0 +1,25 @@ +import os +from unittest.mock import Mock, patch + +import pytest + +from core.model_runtime.errors.validate import CredentialsValidateFailedError +from core.model_runtime.model_providers.voyage.voyage import VoyageProvider + + +def test_validate_provider_credentials(): + provider = VoyageProvider() + + with pytest.raises(CredentialsValidateFailedError): + provider.validate_provider_credentials(credentials={"api_key": "hahahaha"}) + with patch("requests.post") as mock_post: + mock_response = Mock() + mock_response.json.return_value = { + "object": "list", + "data": [{"object": "embedding", "embedding": [0.23333 for _ in range(1024)], "index": 0}], + "model": "voyage-3", + "usage": {"total_tokens": 1}, + } + mock_response.status_code = 200 + mock_post.return_value = mock_response + provider.validate_provider_credentials(credentials={"api_key": os.environ.get("VOYAGE_API_KEY")}) diff --git a/api/tests/integration_tests/model_runtime/voyage/test_rerank.py b/api/tests/integration_tests/model_runtime/voyage/test_rerank.py new file mode 100644 index 0000000000..e97a9e4c81 --- /dev/null +++ b/api/tests/integration_tests/model_runtime/voyage/test_rerank.py @@ -0,0 +1,92 @@ +import os +from unittest.mock import Mock, patch + +import pytest + +from core.model_runtime.entities.rerank_entities import RerankResult +from core.model_runtime.errors.validate import CredentialsValidateFailedError +from core.model_runtime.model_providers.voyage.rerank.rerank import VoyageRerankModel + + +def test_validate_credentials(): + model = VoyageRerankModel() + + with pytest.raises(CredentialsValidateFailedError): + model.validate_credentials( + model="rerank-lite-1", + credentials={"api_key": "invalid_key"}, + ) + with patch("httpx.post") as mock_post: + mock_response = Mock() + mock_response.json.return_value = { + "object": "list", + "data": [ + { + "relevance_score": 0.546875, + "index": 0, + "document": "Carson City is the capital city of the American state of Nevada. At the 2010 United " + "States Census, Carson City had a population of 55,274.", + }, + { + "relevance_score": 0.4765625, + "index": 1, + "document": "The Commonwealth of the Northern Mariana Islands is a group of islands in the " + "Pacific Ocean that are a political division controlled by the United States. Its " + "capital is Saipan.", + }, + ], + "model": "rerank-lite-1", + "usage": {"total_tokens": 96}, + } + mock_response.status_code = 200 + mock_post.return_value = mock_response + model.validate_credentials( + model="rerank-lite-1", + credentials={ + "api_key": os.environ.get("VOYAGE_API_KEY"), + }, + ) + + +def test_invoke_model(): + model = VoyageRerankModel() + with patch("httpx.post") as mock_post: + mock_response = Mock() + mock_response.json.return_value = { + "object": "list", + "data": [ + { + "relevance_score": 0.84375, + "index": 0, + "document": "Kasumi is a girl name of Japanese origin meaning mist.", + }, + { + "relevance_score": 0.4765625, + "index": 1, + "document": "Her music is a kawaii bass, a mix of future bass, pop, and kawaii music and she " + "leads a team named PopiParty.", + }, + ], + "model": "rerank-lite-1", + "usage": {"total_tokens": 59}, + } + mock_response.status_code = 200 + mock_post.return_value = mock_response + result = model.invoke( + model="rerank-lite-1", + credentials={ + "api_key": os.environ.get("VOYAGE_API_KEY"), + }, + query="Who is Kasumi?", + docs=[ + "Kasumi is a girl name of Japanese origin meaning mist.", + "Her music is a kawaii bass, a mix of future bass, pop, and kawaii music and she leads a team named " + "PopiParty.", + ], + score_threshold=0.5, + ) + + assert isinstance(result, RerankResult) + assert len(result.docs) == 1 + assert result.docs[0].index == 0 + assert result.docs[0].score >= 0.5 diff --git a/api/tests/integration_tests/model_runtime/voyage/test_text_embedding.py b/api/tests/integration_tests/model_runtime/voyage/test_text_embedding.py new file mode 100644 index 0000000000..75719672a9 --- /dev/null +++ b/api/tests/integration_tests/model_runtime/voyage/test_text_embedding.py @@ -0,0 +1,70 @@ +import os +from unittest.mock import Mock, patch + +import pytest + +from core.model_runtime.entities.text_embedding_entities import TextEmbeddingResult +from core.model_runtime.errors.validate import CredentialsValidateFailedError +from core.model_runtime.model_providers.voyage.text_embedding.text_embedding import VoyageTextEmbeddingModel + + +def test_validate_credentials(): + model = VoyageTextEmbeddingModel() + + with pytest.raises(CredentialsValidateFailedError): + model.validate_credentials(model="voyage-3", credentials={"api_key": "invalid_key"}) + with patch("requests.post") as mock_post: + mock_response = Mock() + mock_response.json.return_value = { + "object": "list", + "data": [{"object": "embedding", "embedding": [0.23333 for _ in range(1024)], "index": 0}], + "model": "voyage-3", + "usage": {"total_tokens": 1}, + } + mock_response.status_code = 200 + mock_post.return_value = mock_response + model.validate_credentials(model="voyage-3", credentials={"api_key": os.environ.get("VOYAGE_API_KEY")}) + + +def test_invoke_model(): + model = VoyageTextEmbeddingModel() + + with patch("requests.post") as mock_post: + mock_response = Mock() + mock_response.json.return_value = { + "object": "list", + "data": [ + {"object": "embedding", "embedding": [0.23333 for _ in range(1024)], "index": 0}, + {"object": "embedding", "embedding": [0.23333 for _ in range(1024)], "index": 1}, + ], + "model": "voyage-3", + "usage": {"total_tokens": 2}, + } + mock_response.status_code = 200 + mock_post.return_value = mock_response + result = model.invoke( + model="voyage-3", + credentials={ + "api_key": os.environ.get("VOYAGE_API_KEY"), + }, + texts=["hello", "world"], + user="abc-123", + ) + + assert isinstance(result, TextEmbeddingResult) + assert len(result.embeddings) == 2 + assert result.usage.total_tokens == 2 + + +def test_get_num_tokens(): + model = VoyageTextEmbeddingModel() + + num_tokens = model.get_num_tokens( + model="voyage-3", + credentials={ + "api_key": os.environ.get("VOYAGE_API_KEY"), + }, + texts=["ping"], + ) + + assert num_tokens == 1 diff --git a/dev/pytest/pytest_model_runtime.sh b/dev/pytest/pytest_model_runtime.sh index b60ff64fdc..63891eb9f8 100755 --- a/dev/pytest/pytest_model_runtime.sh +++ b/dev/pytest/pytest_model_runtime.sh @@ -9,4 +9,5 @@ pytest api/tests/integration_tests/model_runtime/anthropic \ api/tests/integration_tests/model_runtime/upstage \ api/tests/integration_tests/model_runtime/fireworks \ api/tests/integration_tests/model_runtime/nomic \ - api/tests/integration_tests/model_runtime/mixedbread + api/tests/integration_tests/model_runtime/mixedbread \ + api/tests/integration_tests/model_runtime/voyage \ No newline at end of file From 369e1e6f58814929c7a236a482189f2ff4605570 Mon Sep 17 00:00:00 2001 From: Zhaofeng Miao <522856232@qq.com> Date: Mon, 30 Sep 2024 09:57:19 +0800 Subject: [PATCH 016/136] feat(website-crawl): add jina reader as additional alternative for website crawling (#8761) --- api/controllers/console/datasets/website.py | 6 +- api/core/rag/extractor/extract_processor.py | 10 + .../rag/extractor/jina_reader_extractor.py | 35 +++ api/services/auth/api_key_auth_factory.py | 3 + api/services/auth/jina.py | 44 ++++ api/services/website_service.py | 100 ++++++++ .../datasets/create/assets/jina.png | Bin 0 -> 2773 bytes web/app/components/datasets/create/index.tsx | 12 +- .../datasets/create/step-one/index.tsx | 11 +- .../datasets/create/step-two/index.tsx | 11 +- .../base/checkbox-with-label.tsx | 11 + .../crawled-result-item.tsx | 0 .../{firecrawl => base}/crawled-result.tsx | 2 +- .../website/{firecrawl => base}/crawling.tsx | 0 .../{firecrawl => }/base/error-message.tsx | 0 .../website/{firecrawl => }/base/field.tsx | 0 .../website/{firecrawl => }/base/input.tsx | 0 .../{firecrawl => base}/mock-crawl-result.ts | 0 .../{firecrawl => }/base/options-wrap.tsx | 0 .../{firecrawl => }/base/url-input.tsx | 0 .../create/website/firecrawl/index.tsx | 10 +- .../create/website/firecrawl/options.tsx | 4 +- .../datasets/create/website/index.module.css | 6 + .../datasets/create/website/index.tsx | 100 ++++++-- .../create/website/jina-reader/header.tsx | 42 ++++ .../create/website/jina-reader/index.tsx | 232 ++++++++++++++++++ .../create/website/jina-reader/options.tsx | 59 +++++ .../datasets/create/website/no-data.tsx | 45 +++- .../config-firecrawl-modal.tsx | 2 +- .../config-jina-reader-modal.tsx | 140 +++++++++++ .../data-source-website/index.tsx | 51 ++-- .../data-source-page/index.tsx | 4 +- .../data-source-page/panel/index.tsx | 5 +- web/i18n/en-US/dataset-creation.ts | 15 +- web/i18n/zh-Hans/dataset-creation.ts | 15 +- web/models/common.ts | 1 + web/models/datasets.ts | 1 + web/service/datasets.ts | 25 +- 38 files changed, 927 insertions(+), 75 deletions(-) create mode 100644 api/core/rag/extractor/jina_reader_extractor.py create mode 100644 api/services/auth/jina.py create mode 100644 web/app/components/datasets/create/assets/jina.png rename web/app/components/datasets/create/website/{firecrawl => }/base/checkbox-with-label.tsx (72%) rename web/app/components/datasets/create/website/{firecrawl => base}/crawled-result-item.tsx (100%) rename web/app/components/datasets/create/website/{firecrawl => base}/crawled-result.tsx (97%) rename web/app/components/datasets/create/website/{firecrawl => base}/crawling.tsx (100%) rename web/app/components/datasets/create/website/{firecrawl => }/base/error-message.tsx (100%) rename web/app/components/datasets/create/website/{firecrawl => }/base/field.tsx (100%) rename web/app/components/datasets/create/website/{firecrawl => }/base/input.tsx (100%) rename web/app/components/datasets/create/website/{firecrawl => base}/mock-crawl-result.ts (100%) rename web/app/components/datasets/create/website/{firecrawl => }/base/options-wrap.tsx (100%) rename web/app/components/datasets/create/website/{firecrawl => }/base/url-input.tsx (100%) create mode 100644 web/app/components/datasets/create/website/index.module.css create mode 100644 web/app/components/datasets/create/website/jina-reader/header.tsx create mode 100644 web/app/components/datasets/create/website/jina-reader/index.tsx create mode 100644 web/app/components/datasets/create/website/jina-reader/options.tsx create mode 100644 web/app/components/header/account-setting/data-source-page/data-source-website/config-jina-reader-modal.tsx diff --git a/api/controllers/console/datasets/website.py b/api/controllers/console/datasets/website.py index cb54f1aacb..e80ce17c68 100644 --- a/api/controllers/console/datasets/website.py +++ b/api/controllers/console/datasets/website.py @@ -14,7 +14,9 @@ class WebsiteCrawlApi(Resource): @account_initialization_required def post(self): parser = reqparse.RequestParser() - parser.add_argument("provider", type=str, choices=["firecrawl"], required=True, nullable=True, location="json") + parser.add_argument( + "provider", type=str, choices=["firecrawl", "jinareader"], required=True, nullable=True, location="json" + ) parser.add_argument("url", type=str, required=True, nullable=True, location="json") parser.add_argument("options", type=dict, required=True, nullable=True, location="json") args = parser.parse_args() @@ -33,7 +35,7 @@ class WebsiteCrawlStatusApi(Resource): @account_initialization_required def get(self, job_id: str): parser = reqparse.RequestParser() - parser.add_argument("provider", type=str, choices=["firecrawl"], required=True, location="args") + parser.add_argument("provider", type=str, choices=["firecrawl", "jinareader"], required=True, location="args") args = parser.parse_args() # get crawl status try: diff --git a/api/core/rag/extractor/extract_processor.py b/api/core/rag/extractor/extract_processor.py index 0ffc89b214..9048138511 100644 --- a/api/core/rag/extractor/extract_processor.py +++ b/api/core/rag/extractor/extract_processor.py @@ -12,6 +12,7 @@ from core.rag.extractor.entity.extract_setting import ExtractSetting from core.rag.extractor.excel_extractor import ExcelExtractor from core.rag.extractor.firecrawl.firecrawl_web_extractor import FirecrawlWebExtractor from core.rag.extractor.html_extractor import HtmlExtractor +from core.rag.extractor.jina_reader_extractor import JinaReaderWebExtractor from core.rag.extractor.markdown_extractor import MarkdownExtractor from core.rag.extractor.notion_extractor import NotionExtractor from core.rag.extractor.pdf_extractor import PdfExtractor @@ -171,6 +172,15 @@ class ExtractProcessor: only_main_content=extract_setting.website_info.only_main_content, ) return extractor.extract() + elif extract_setting.website_info.provider == "jinareader": + extractor = JinaReaderWebExtractor( + url=extract_setting.website_info.url, + job_id=extract_setting.website_info.job_id, + tenant_id=extract_setting.website_info.tenant_id, + mode=extract_setting.website_info.mode, + only_main_content=extract_setting.website_info.only_main_content, + ) + return extractor.extract() else: raise ValueError(f"Unsupported website provider: {extract_setting.website_info.provider}") else: diff --git a/api/core/rag/extractor/jina_reader_extractor.py b/api/core/rag/extractor/jina_reader_extractor.py new file mode 100644 index 0000000000..5b780af126 --- /dev/null +++ b/api/core/rag/extractor/jina_reader_extractor.py @@ -0,0 +1,35 @@ +from core.rag.extractor.extractor_base import BaseExtractor +from core.rag.models.document import Document +from services.website_service import WebsiteService + + +class JinaReaderWebExtractor(BaseExtractor): + """ + Crawl and scrape websites and return content in clean llm-ready markdown. + """ + + def __init__(self, url: str, job_id: str, tenant_id: str, mode: str = "crawl", only_main_content: bool = False): + """Initialize with url, api_key, base_url and mode.""" + self._url = url + self.job_id = job_id + self.tenant_id = tenant_id + self.mode = mode + self.only_main_content = only_main_content + + def extract(self) -> list[Document]: + """Extract content from the URL.""" + documents = [] + if self.mode == "crawl": + crawl_data = WebsiteService.get_crawl_url_data(self.job_id, "jinareader", self._url, self.tenant_id) + if crawl_data is None: + return [] + document = Document( + page_content=crawl_data.get("content", ""), + metadata={ + "source_url": crawl_data.get("url"), + "description": crawl_data.get("description"), + "title": crawl_data.get("title"), + }, + ) + documents.append(document) + return documents diff --git a/api/services/auth/api_key_auth_factory.py b/api/services/auth/api_key_auth_factory.py index ae5b953b47..36387e9c2e 100644 --- a/api/services/auth/api_key_auth_factory.py +++ b/api/services/auth/api_key_auth_factory.py @@ -1,10 +1,13 @@ from services.auth.firecrawl import FirecrawlAuth +from services.auth.jina import JinaAuth class ApiKeyAuthFactory: def __init__(self, provider: str, credentials: dict): if provider == "firecrawl": self.auth = FirecrawlAuth(credentials) + elif provider == "jinareader": + self.auth = JinaAuth(credentials) else: raise ValueError("Invalid provider") diff --git a/api/services/auth/jina.py b/api/services/auth/jina.py new file mode 100644 index 0000000000..de898a1f94 --- /dev/null +++ b/api/services/auth/jina.py @@ -0,0 +1,44 @@ +import json + +import requests + +from services.auth.api_key_auth_base import ApiKeyAuthBase + + +class JinaAuth(ApiKeyAuthBase): + def __init__(self, credentials: dict): + super().__init__(credentials) + auth_type = credentials.get("auth_type") + if auth_type != "bearer": + raise ValueError("Invalid auth type, Jina Reader auth type must be Bearer") + self.api_key = credentials.get("config").get("api_key", None) + + if not self.api_key: + raise ValueError("No API key provided") + + def validate_credentials(self): + headers = self._prepare_headers() + options = { + "url": "https://example.com", + } + response = self._post_request("https://r.jina.ai", options, headers) + if response.status_code == 200: + return True + else: + self._handle_error(response) + + def _prepare_headers(self): + return {"Content-Type": "application/json", "Authorization": f"Bearer {self.api_key}"} + + def _post_request(self, url, data, headers): + return requests.post(url, headers=headers, json=data) + + def _handle_error(self, response): + if response.status_code in {402, 409, 500}: + error_message = response.json().get("error", "Unknown error occurred") + raise Exception(f"Failed to authorize. Status code: {response.status_code}. Error: {error_message}") + else: + if response.text: + error_message = json.loads(response.text).get("error", "Unknown error occurred") + raise Exception(f"Failed to authorize. Status code: {response.status_code}. Error: {error_message}") + raise Exception(f"Unexpected error occurred while trying to authorize. Status code: {response.status_code}") diff --git a/api/services/website_service.py b/api/services/website_service.py index fea605cf30..be01815720 100644 --- a/api/services/website_service.py +++ b/api/services/website_service.py @@ -1,6 +1,7 @@ import datetime import json +import requests from flask_login import current_user from core.helper import encrypter @@ -65,6 +66,35 @@ class WebsiteService: time = str(datetime.datetime.now().timestamp()) redis_client.setex(website_crawl_time_cache_key, 3600, time) return {"status": "active", "job_id": job_id} + elif provider == "jinareader": + api_key = encrypter.decrypt_token( + tenant_id=current_user.current_tenant_id, token=credentials.get("config").get("api_key") + ) + crawl_sub_pages = options.get("crawl_sub_pages", False) + if not crawl_sub_pages: + response = requests.get( + f"https://r.jina.ai/{url}", + headers={"Accept": "application/json", "Authorization": f"Bearer {api_key}"}, + ) + if response.json().get("code") != 200: + raise ValueError("Failed to crawl") + return {"status": "active", "data": response.json().get("data")} + else: + response = requests.post( + "https://adaptivecrawl-kir3wx7b3a-uc.a.run.app", + json={ + "url": url, + "maxPages": options.get("limit", 1), + "useSitemap": options.get("use_sitemap", True), + }, + headers={ + "Content-Type": "application/json", + "Authorization": f"Bearer {api_key}", + }, + ) + if response.json().get("code") != 200: + raise ValueError("Failed to crawl") + return {"status": "active", "job_id": response.json().get("data", {}).get("taskId")} else: raise ValueError("Invalid provider") @@ -93,6 +123,42 @@ class WebsiteService: time_consuming = abs(end_time - float(start_time)) crawl_status_data["time_consuming"] = f"{time_consuming:.2f}" redis_client.delete(website_crawl_time_cache_key) + elif provider == "jinareader": + api_key = encrypter.decrypt_token( + tenant_id=current_user.current_tenant_id, token=credentials.get("config").get("api_key") + ) + response = requests.post( + "https://adaptivecrawlstatus-kir3wx7b3a-uc.a.run.app", + headers={"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}, + json={"taskId": job_id}, + ) + data = response.json().get("data", {}) + crawl_status_data = { + "status": data.get("status", "active"), + "job_id": job_id, + "total": len(data.get("urls", [])), + "current": len(data.get("processed", [])) + len(data.get("failed", [])), + "data": [], + "time_consuming": data.get("duration", 0) / 1000, + } + + if crawl_status_data["status"] == "completed": + response = requests.post( + "https://adaptivecrawlstatus-kir3wx7b3a-uc.a.run.app", + headers={"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}, + json={"taskId": job_id, "urls": list(data.get("processed", {}).keys())}, + ) + data = response.json().get("data", {}) + formatted_data = [ + { + "title": item.get("data", {}).get("title"), + "source_url": item.get("data", {}).get("url"), + "description": item.get("data", {}).get("description"), + "markdown": item.get("data", {}).get("content"), + } + for item in data.get("processed", {}).values() + ] + crawl_status_data["data"] = formatted_data else: raise ValueError("Invalid provider") return crawl_status_data @@ -119,6 +185,40 @@ class WebsiteService: if item.get("source_url") == url: return item return None + elif provider == "jinareader": + file_key = "website_files/" + job_id + ".txt" + if storage.exists(file_key): + data = storage.load_once(file_key) + if data: + data = json.loads(data.decode("utf-8")) + elif not job_id: + response = requests.get( + f"https://r.jina.ai/{url}", + headers={"Accept": "application/json", "Authorization": f"Bearer {api_key}"}, + ) + if response.json().get("code") != 200: + raise ValueError("Failed to crawl") + return response.json().get("data") + else: + api_key = encrypter.decrypt_token(tenant_id=tenant_id, token=credentials.get("config").get("api_key")) + response = requests.post( + "https://adaptivecrawlstatus-kir3wx7b3a-uc.a.run.app", + headers={"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}, + json={"taskId": job_id}, + ) + data = response.json().get("data", {}) + if data.get("status") != "completed": + raise ValueError("Crawl job is not completed") + + response = requests.post( + "https://adaptivecrawlstatus-kir3wx7b3a-uc.a.run.app", + headers={"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}, + json={"taskId": job_id, "urls": list(data.get("processed", {}).keys())}, + ) + data = response.json().get("data", {}) + for item in data.get("processed", {}).values(): + if item.get("data", {}).get("url") == url: + return item.get("data", {}) else: raise ValueError("Invalid provider") diff --git a/web/app/components/datasets/create/assets/jina.png b/web/app/components/datasets/create/assets/jina.png new file mode 100644 index 0000000000000000000000000000000000000000..b4beeafdfb127115d0e29ad3728654310dfc389a GIT binary patch literal 2773 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 { @@ -51,7 +52,8 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => { const updateFileList = (preparedFiles: FileItem[]) => { setFiles(preparedFiles) } - const [fireCrawlJobId, setFireCrawlJobId] = useState('') + const [websiteCrawlProvider, setWebsiteCrawlProvider] = useState(DataSourceProvider.fireCrawl) + const [websiteCrawlJobId, setWebsiteCrawlJobId] = useState('') const updateFile = (fileItem: FileItem, progress: number, list: FileItem[]) => { const targetIndex = list.findIndex(file => file.fileID === fileItem.fileID) @@ -137,7 +139,8 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => { onStepChange={nextStep} websitePages={websitePages} updateWebsitePages={setWebsitePages} - onFireCrawlJobIdChange={setFireCrawlJobId} + onWebsiteCrawlProviderChange={setWebsiteCrawlProvider} + onWebsiteCrawlJobIdChange={setWebsiteCrawlJobId} crawlOptions={crawlOptions} onCrawlOptionsChange={setCrawlOptions} /> @@ -151,7 +154,8 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => { files={fileList.map(file => file.file)} notionPages={notionPages} websitePages={websitePages} - fireCrawlJobId={fireCrawlJobId} + websiteCrawlProvider={websiteCrawlProvider} + websiteCrawlJobId={websiteCrawlJobId} onStepChange={changeStep} updateIndexingTypeCache={updateIndexingTypeCache} updateResultCache={updateResultCache} diff --git a/web/app/components/datasets/create/step-one/index.tsx b/web/app/components/datasets/create/step-one/index.tsx index c2d77f4cec..643932e9ae 100644 --- a/web/app/components/datasets/create/step-one/index.tsx +++ b/web/app/components/datasets/create/step-one/index.tsx @@ -10,7 +10,7 @@ import WebsitePreview from '../website/preview' import s from './index.module.css' import cn from '@/utils/classnames' import type { CrawlOptions, CrawlResultItem, FileItem } from '@/models/datasets' -import type { NotionPage } from '@/models/common' +import type { DataSourceProvider, NotionPage } from '@/models/common' import { DataSourceType } from '@/models/datasets' import Button from '@/app/components/base/button' import { NotionPageSelector } from '@/app/components/base/notion-page-selector' @@ -33,7 +33,8 @@ type IStepOneProps = { changeType: (type: DataSourceType) => void websitePages?: CrawlResultItem[] updateWebsitePages: (value: CrawlResultItem[]) => void - onFireCrawlJobIdChange: (jobId: string) => void + onWebsiteCrawlProviderChange: (provider: DataSourceProvider) => void + onWebsiteCrawlJobIdChange: (jobId: string) => void crawlOptions: CrawlOptions onCrawlOptionsChange: (payload: CrawlOptions) => void } @@ -69,7 +70,8 @@ const StepOne = ({ updateNotionPages, websitePages = [], updateWebsitePages, - onFireCrawlJobIdChange, + onWebsiteCrawlProviderChange, + onWebsiteCrawlJobIdChange, crawlOptions, onCrawlOptionsChange, }: IStepOneProps) => { @@ -229,7 +231,8 @@ const StepOne = ({ onPreview={setCurrentWebsite} checkedCrawlResult={websitePages} onCheckedCrawlResultChange={updateWebsitePages} - onJobIdChange={onFireCrawlJobIdChange} + onCrawlProviderChange={onWebsiteCrawlProviderChange} + onJobIdChange={onWebsiteCrawlJobIdChange} crawlOptions={crawlOptions} onCrawlOptionsChange={onCrawlOptionsChange} /> diff --git a/web/app/components/datasets/create/step-two/index.tsx b/web/app/components/datasets/create/step-two/index.tsx index f4fc58ee2a..ee01652de8 100644 --- a/web/app/components/datasets/create/step-two/index.tsx +++ b/web/app/components/datasets/create/step-two/index.tsx @@ -33,6 +33,7 @@ import { ensureRerankModelSelected, isReRankModelSelected } from '@/app/componen import Toast from '@/app/components/base/toast' import { formatNumber } from '@/utils/format' import type { NotionPage } from '@/models/common' +import { DataSourceProvider } from '@/models/common' import { DataSourceType, DocForm } from '@/models/datasets' import NotionIcon from '@/app/components/base/notion-icon' import Switch from '@/app/components/base/switch' @@ -63,7 +64,8 @@ type StepTwoProps = { notionPages?: NotionPage[] websitePages?: CrawlResultItem[] crawlOptions?: CrawlOptions - fireCrawlJobId?: string + websiteCrawlProvider?: DataSourceProvider + websiteCrawlJobId?: string onStepChange?: (delta: number) => void updateIndexingTypeCache?: (type: string) => void updateResultCache?: (res: createDocumentResponse) => void @@ -94,7 +96,8 @@ const StepTwo = ({ notionPages = [], websitePages = [], crawlOptions, - fireCrawlJobId = '', + websiteCrawlProvider = DataSourceProvider.fireCrawl, + websiteCrawlJobId = '', onStepChange, updateIndexingTypeCache, updateResultCache, @@ -260,8 +263,8 @@ const StepTwo = ({ const getWebsiteInfo = () => { return { - provider: 'firecrawl', - job_id: fireCrawlJobId, + provider: websiteCrawlProvider, + job_id: websiteCrawlJobId, urls: websitePages.map(page => page.source_url), only_main_content: crawlOptions?.only_main_content, } diff --git a/web/app/components/datasets/create/website/firecrawl/base/checkbox-with-label.tsx b/web/app/components/datasets/create/website/base/checkbox-with-label.tsx similarity index 72% rename from web/app/components/datasets/create/website/firecrawl/base/checkbox-with-label.tsx rename to web/app/components/datasets/create/website/base/checkbox-with-label.tsx index 5c574ebe3e..25d40fe076 100644 --- a/web/app/components/datasets/create/website/firecrawl/base/checkbox-with-label.tsx +++ b/web/app/components/datasets/create/website/base/checkbox-with-label.tsx @@ -3,6 +3,7 @@ import type { FC } from 'react' import React from 'react' import cn from '@/utils/classnames' import Checkbox from '@/app/components/base/checkbox' +import Tooltip from '@/app/components/base/tooltip' type Props = { className?: string @@ -10,6 +11,7 @@ type Props = { onChange: (isChecked: boolean) => void label: string labelClassName?: string + tooltip?: string } const CheckboxWithLabel: FC = ({ @@ -18,11 +20,20 @@ const CheckboxWithLabel: FC = ({ onChange, label, labelClassName, + tooltip, }) => { return (

+ {tooltip && ( + {tooltip} + } + triggerClassName='ml-0.5 w-4 h-4' + /> + )} ) } diff --git a/web/app/components/datasets/create/website/firecrawl/crawled-result-item.tsx b/web/app/components/datasets/create/website/base/crawled-result-item.tsx similarity index 100% rename from web/app/components/datasets/create/website/firecrawl/crawled-result-item.tsx rename to web/app/components/datasets/create/website/base/crawled-result-item.tsx diff --git a/web/app/components/datasets/create/website/firecrawl/crawled-result.tsx b/web/app/components/datasets/create/website/base/crawled-result.tsx similarity index 97% rename from web/app/components/datasets/create/website/firecrawl/crawled-result.tsx rename to web/app/components/datasets/create/website/base/crawled-result.tsx index 2bd51e4d73..d5c8d1b80a 100644 --- a/web/app/components/datasets/create/website/firecrawl/crawled-result.tsx +++ b/web/app/components/datasets/create/website/base/crawled-result.tsx @@ -2,7 +2,7 @@ import type { FC } from 'react' import React, { useCallback } from 'react' import { useTranslation } from 'react-i18next' -import CheckboxWithLabel from './base/checkbox-with-label' +import CheckboxWithLabel from './checkbox-with-label' import CrawledResultItem from './crawled-result-item' import cn from '@/utils/classnames' import type { CrawlResultItem } from '@/models/datasets' diff --git a/web/app/components/datasets/create/website/firecrawl/crawling.tsx b/web/app/components/datasets/create/website/base/crawling.tsx similarity index 100% rename from web/app/components/datasets/create/website/firecrawl/crawling.tsx rename to web/app/components/datasets/create/website/base/crawling.tsx diff --git a/web/app/components/datasets/create/website/firecrawl/base/error-message.tsx b/web/app/components/datasets/create/website/base/error-message.tsx similarity index 100% rename from web/app/components/datasets/create/website/firecrawl/base/error-message.tsx rename to web/app/components/datasets/create/website/base/error-message.tsx diff --git a/web/app/components/datasets/create/website/firecrawl/base/field.tsx b/web/app/components/datasets/create/website/base/field.tsx similarity index 100% rename from web/app/components/datasets/create/website/firecrawl/base/field.tsx rename to web/app/components/datasets/create/website/base/field.tsx diff --git a/web/app/components/datasets/create/website/firecrawl/base/input.tsx b/web/app/components/datasets/create/website/base/input.tsx similarity index 100% rename from web/app/components/datasets/create/website/firecrawl/base/input.tsx rename to web/app/components/datasets/create/website/base/input.tsx diff --git a/web/app/components/datasets/create/website/firecrawl/mock-crawl-result.ts b/web/app/components/datasets/create/website/base/mock-crawl-result.ts similarity index 100% rename from web/app/components/datasets/create/website/firecrawl/mock-crawl-result.ts rename to web/app/components/datasets/create/website/base/mock-crawl-result.ts diff --git a/web/app/components/datasets/create/website/firecrawl/base/options-wrap.tsx b/web/app/components/datasets/create/website/base/options-wrap.tsx similarity index 100% rename from web/app/components/datasets/create/website/firecrawl/base/options-wrap.tsx rename to web/app/components/datasets/create/website/base/options-wrap.tsx diff --git a/web/app/components/datasets/create/website/firecrawl/base/url-input.tsx b/web/app/components/datasets/create/website/base/url-input.tsx similarity index 100% rename from web/app/components/datasets/create/website/firecrawl/base/url-input.tsx rename to web/app/components/datasets/create/website/base/url-input.tsx diff --git a/web/app/components/datasets/create/website/firecrawl/index.tsx b/web/app/components/datasets/create/website/firecrawl/index.tsx index de4f8bb129..aa4dffc174 100644 --- a/web/app/components/datasets/create/website/firecrawl/index.tsx +++ b/web/app/components/datasets/create/website/firecrawl/index.tsx @@ -2,13 +2,13 @@ import type { FC } from 'react' import React, { useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' +import UrlInput from '../base/url-input' +import OptionsWrap from '../base/options-wrap' +import CrawledResult from '../base/crawled-result' +import Crawling from '../base/crawling' +import ErrorMessage from '../base/error-message' import Header from './header' -import UrlInput from './base/url-input' -import OptionsWrap from './base/options-wrap' import Options from './options' -import CrawledResult from './crawled-result' -import Crawling from './crawling' -import ErrorMessage from './base/error-message' import cn from '@/utils/classnames' import { useModalContext } from '@/context/modal-context' import type { CrawlOptions, CrawlResultItem } from '@/models/datasets' diff --git a/web/app/components/datasets/create/website/firecrawl/options.tsx b/web/app/components/datasets/create/website/firecrawl/options.tsx index 20cc4f073f..8cc2c6757c 100644 --- a/web/app/components/datasets/create/website/firecrawl/options.tsx +++ b/web/app/components/datasets/create/website/firecrawl/options.tsx @@ -2,8 +2,8 @@ import type { FC } from 'react' import React, { useCallback } from 'react' import { useTranslation } from 'react-i18next' -import CheckboxWithLabel from './base/checkbox-with-label' -import Field from './base/field' +import CheckboxWithLabel from '../base/checkbox-with-label' +import Field from '../base/field' import cn from '@/utils/classnames' import type { CrawlOptions } from '@/models/datasets' diff --git a/web/app/components/datasets/create/website/index.module.css b/web/app/components/datasets/create/website/index.module.css new file mode 100644 index 0000000000..abaab4bea4 --- /dev/null +++ b/web/app/components/datasets/create/website/index.module.css @@ -0,0 +1,6 @@ +.jinaLogo { + @apply w-4 h-4 bg-center bg-no-repeat inline-block; + background-color: #F5FAFF; + background-image: url(../assets/jina.png); + background-size: 16px; +} diff --git a/web/app/components/datasets/create/website/index.tsx b/web/app/components/datasets/create/website/index.tsx index e06fbb4a12..58b7f5f2fd 100644 --- a/web/app/components/datasets/create/website/index.tsx +++ b/web/app/components/datasets/create/website/index.tsx @@ -1,8 +1,12 @@ 'use client' import type { FC } from 'react' import React, { useCallback, useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import s from './index.module.css' import NoData from './no-data' import Firecrawl from './firecrawl' +import JinaReader from './jina-reader' +import cn from '@/utils/classnames' import { useModalContext } from '@/context/modal-context' import type { CrawlOptions, CrawlResultItem } from '@/models/datasets' import { fetchDataSources } from '@/service/datasets' @@ -12,6 +16,7 @@ type Props = { onPreview: (payload: CrawlResultItem) => void checkedCrawlResult: CrawlResultItem[] onCheckedCrawlResultChange: (payload: CrawlResultItem[]) => void + onCrawlProviderChange: (provider: DataSourceProvider) => void onJobIdChange: (jobId: string) => void crawlOptions: CrawlOptions onCrawlOptionsChange: (payload: CrawlOptions) => void @@ -21,17 +26,32 @@ const Website: FC = ({ onPreview, checkedCrawlResult, onCheckedCrawlResultChange, + onCrawlProviderChange, onJobIdChange, crawlOptions, onCrawlOptionsChange, }) => { + const { t } = useTranslation() const { setShowAccountSettingModal } = useModalContext() const [isLoaded, setIsLoaded] = useState(false) - const [isSetFirecrawlApiKey, setIsSetFirecrawlApiKey] = useState(false) + const [selectedProvider, setSelectedProvider] = useState(DataSourceProvider.jinaReader) + const [sources, setSources] = useState([]) + + useEffect(() => { + onCrawlProviderChange(selectedProvider) + }, [selectedProvider, onCrawlProviderChange]) + const checkSetApiKey = useCallback(async () => { const res = await fetchDataSources() as any - const isFirecrawlSet = res.sources.some((item: DataSourceItem) => item.provider === DataSourceProvider.fireCrawl) - setIsSetFirecrawlApiKey(isFirecrawlSet) + setSources(res.sources) + + // If users have configured one of the providers, select it. + const availableProviders = res.sources.filter((item: DataSourceItem) => + [DataSourceProvider.jinaReader, DataSourceProvider.fireCrawl].includes(item.provider), + ) + + if (availableProviders.length > 0) + setSelectedProvider(availableProviders[0].provider) }, []) useEffect(() => { @@ -52,20 +72,66 @@ const Website: FC = ({ return (
- {isSetFirecrawlApiKey - ? ( - - ) - : ( - - )} +
+
+ {t('datasetCreation.stepOne.website.chooseProvider')} +
+
+ + +
+
+ + { + selectedProvider === DataSourceProvider.fireCrawl + ? sources.find(source => source.provider === DataSourceProvider.fireCrawl) + ? ( + + ) + : ( + + ) + : sources.find(source => source.provider === DataSourceProvider.jinaReader) + ? ( + + ) + : ( + + ) + }
) } diff --git a/web/app/components/datasets/create/website/jina-reader/header.tsx b/web/app/components/datasets/create/website/jina-reader/header.tsx new file mode 100644 index 0000000000..85014a30ee --- /dev/null +++ b/web/app/components/datasets/create/website/jina-reader/header.tsx @@ -0,0 +1,42 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import { useTranslation } from 'react-i18next' +import { Settings01 } from '@/app/components/base/icons/src/vender/line/general' +import { BookOpen01 } from '@/app/components/base/icons/src/vender/line/education' + +const I18N_PREFIX = 'datasetCreation.stepOne.website' + +type Props = { + onSetting: () => void +} + +const Header: FC = ({ + onSetting, +}) => { + const { t } = useTranslation() + + return ( +
+ ) +} +export default React.memo(Header) diff --git a/web/app/components/datasets/create/website/jina-reader/index.tsx b/web/app/components/datasets/create/website/jina-reader/index.tsx new file mode 100644 index 0000000000..51d77d7121 --- /dev/null +++ b/web/app/components/datasets/create/website/jina-reader/index.tsx @@ -0,0 +1,232 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback, useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import UrlInput from '../base/url-input' +import OptionsWrap from '../base/options-wrap' +import CrawledResult from '../base/crawled-result' +import Crawling from '../base/crawling' +import ErrorMessage from '../base/error-message' +import Header from './header' +import Options from './options' +import cn from '@/utils/classnames' +import { useModalContext } from '@/context/modal-context' +import Toast from '@/app/components/base/toast' +import { checkJinaReaderTaskStatus, createJinaReaderTask } from '@/service/datasets' +import { sleep } from '@/utils' +import type { CrawlOptions, CrawlResultItem } from '@/models/datasets' + +const ERROR_I18N_PREFIX = 'common.errorMsg' +const I18N_PREFIX = 'datasetCreation.stepOne.website' + +type Props = { + onPreview: (payload: CrawlResultItem) => void + checkedCrawlResult: CrawlResultItem[] + onCheckedCrawlResultChange: (payload: CrawlResultItem[]) => void + onJobIdChange: (jobId: string) => void + crawlOptions: CrawlOptions + onCrawlOptionsChange: (payload: CrawlOptions) => void +} + +enum Step { + init = 'init', + running = 'running', + finished = 'finished', +} + +const JinaReader: FC = ({ + onPreview, + checkedCrawlResult, + onCheckedCrawlResultChange, + onJobIdChange, + crawlOptions, + onCrawlOptionsChange, +}) => { + const { t } = useTranslation() + const [step, setStep] = useState(Step.init) + const [controlFoldOptions, setControlFoldOptions] = useState(0) + useEffect(() => { + if (step !== Step.init) + setControlFoldOptions(Date.now()) + }, [step]) + const { setShowAccountSettingModal } = useModalContext() + const handleSetting = useCallback(() => { + setShowAccountSettingModal({ + payload: 'data-source', + }) + }, [setShowAccountSettingModal]) + + const checkValid = useCallback((url: string) => { + let errorMsg = '' + if (!url) { + errorMsg = t(`${ERROR_I18N_PREFIX}.fieldRequired`, { + field: 'url', + }) + } + + if (!errorMsg && !((url.startsWith('http://') || url.startsWith('https://')))) + errorMsg = t(`${ERROR_I18N_PREFIX}.urlError`) + + if (!errorMsg && (crawlOptions.limit === null || crawlOptions.limit === undefined || crawlOptions.limit === '')) { + errorMsg = t(`${ERROR_I18N_PREFIX}.fieldRequired`, { + field: t(`${I18N_PREFIX}.limit`), + }) + } + + return { + isValid: !errorMsg, + errorMsg, + } + }, [crawlOptions, t]) + + const isInit = step === Step.init + const isCrawlFinished = step === Step.finished + const isRunning = step === Step.running + const [crawlResult, setCrawlResult] = useState<{ + current: number + total: number + data: CrawlResultItem[] + time_consuming: number | string + } | undefined>(undefined) + const [crawlErrorMessage, setCrawlErrorMessage] = useState('') + const showError = isCrawlFinished && crawlErrorMessage + + const waitForCrawlFinished = useCallback(async (jobId: string) => { + try { + const res = await checkJinaReaderTaskStatus(jobId) as any + console.log('res', res) + if (res.status === 'completed') { + return { + isError: false, + data: { + ...res, + total: Math.min(res.total, parseFloat(crawlOptions.limit as string)), + }, + } + } + if (res.status === 'failed' || !res.status) { + return { + isError: true, + errorMessage: res.message, + data: { + data: [], + }, + } + } + // update the progress + setCrawlResult({ + ...res, + total: Math.min(res.total, parseFloat(crawlOptions.limit as string)), + }) + onCheckedCrawlResultChange(res.data || []) // default select the crawl result + await sleep(2500) + return await waitForCrawlFinished(jobId) + } + catch (e: any) { + const errorBody = await e.json() + return { + isError: true, + errorMessage: errorBody.message, + data: { + data: [], + }, + } + } + }, [crawlOptions.limit]) + + const handleRun = useCallback(async (url: string) => { + const { isValid, errorMsg } = checkValid(url) + if (!isValid) { + Toast.notify({ + message: errorMsg!, + type: 'error', + }) + return + } + setStep(Step.running) + try { + const startTime = Date.now() + const res = await createJinaReaderTask({ + url, + options: crawlOptions, + }) as any + + if (res.data) { + const data = { + current: 1, + total: 1, + data: [{ + title: res.data.title, + markdown: res.data.content, + description: res.data.description, + source_url: res.data.url, + }], + time_consuming: (Date.now() - startTime) / 1000, + } + setCrawlResult(data) + onCheckedCrawlResultChange(data.data || []) + setCrawlErrorMessage('') + } + else if (res.job_id) { + const jobId = res.job_id + onJobIdChange(jobId) + const { isError, data, errorMessage } = await waitForCrawlFinished(jobId) + if (isError) { + setCrawlErrorMessage(errorMessage || t(`${I18N_PREFIX}.unknownError`)) + } + else { + setCrawlResult(data) + onCheckedCrawlResultChange(data.data || []) // default select the crawl result + setCrawlErrorMessage('') + } + } + } + catch (e) { + setCrawlErrorMessage(t(`${I18N_PREFIX}.unknownError`)!) + console.log(e) + } + finally { + setStep(Step.finished) + } + }, [checkValid, crawlOptions, onJobIdChange, t, waitForCrawlFinished]) + + return ( +
+
+
+ + + + + + {!isInit && ( +
+ {isRunning + && } + {showError && ( + + )} + {isCrawlFinished && !showError + && + } +
+ )} +
+
+ ) +} +export default React.memo(JinaReader) diff --git a/web/app/components/datasets/create/website/jina-reader/options.tsx b/web/app/components/datasets/create/website/jina-reader/options.tsx new file mode 100644 index 0000000000..52cfaa8b3b --- /dev/null +++ b/web/app/components/datasets/create/website/jina-reader/options.tsx @@ -0,0 +1,59 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback } from 'react' +import { useTranslation } from 'react-i18next' +import CheckboxWithLabel from '../base/checkbox-with-label' +import Field from '../base/field' +import cn from '@/utils/classnames' +import type { CrawlOptions } from '@/models/datasets' + +const I18N_PREFIX = 'datasetCreation.stepOne.website' + +type Props = { + className?: string + payload: CrawlOptions + onChange: (payload: CrawlOptions) => void +} + +const Options: FC = ({ + className = '', + payload, + onChange, +}) => { + const { t } = useTranslation() + + const handleChange = useCallback((key: keyof CrawlOptions) => { + return (value: any) => { + onChange({ + ...payload, + [key]: value, + }) + } + }, [payload, onChange]) + return ( +
+ + +
+ +
+
+ ) +} +export default React.memo(Options) diff --git a/web/app/components/datasets/create/website/no-data.tsx b/web/app/components/datasets/create/website/no-data.tsx index 13e5ee7dfb..8a508a48c6 100644 --- a/web/app/components/datasets/create/website/no-data.tsx +++ b/web/app/components/datasets/create/website/no-data.tsx @@ -2,35 +2,56 @@ import type { FC } from 'react' import React from 'react' import { useTranslation } from 'react-i18next' +import s from './index.module.css' import { Icon3Dots } from '@/app/components/base/icons/src/vender/line/others' import Button from '@/app/components/base/button' +import { DataSourceProvider } from '@/models/common' const I18N_PREFIX = 'datasetCreation.stepOne.website' type Props = { onConfig: () => void + provider: DataSourceProvider } const NoData: FC = ({ onConfig, + provider, }) => { const { t } = useTranslation() + const providerConfig = { + [DataSourceProvider.jinaReader]: { + emoji: , + title: t(`${I18N_PREFIX}.jinaReaderNotConfigured`), + description: t(`${I18N_PREFIX}.jinaReaderNotConfiguredDescription`), + }, + [DataSourceProvider.fireCrawl]: { + emoji: '🔥', + title: t(`${I18N_PREFIX}.fireCrawlNotConfigured`), + description: t(`${I18N_PREFIX}.fireCrawlNotConfiguredDescription`), + }, + } + + const currentProvider = providerConfig[provider] + return ( -
-
- 🔥 -
-
- {t(`${I18N_PREFIX}.fireCrawlNotConfigured`)} -
- {t(`${I18N_PREFIX}.fireCrawlNotConfiguredDescription`)} + <> +
+
+ {currentProvider.emoji}
+
+ {currentProvider.title} +
+ {currentProvider.description} +
+
+
- -
+ ) } export default React.memo(NoData) diff --git a/web/app/components/header/account-setting/data-source-page/data-source-website/config-firecrawl-modal.tsx b/web/app/components/header/account-setting/data-source-page/data-source-website/config-firecrawl-modal.tsx index d68fc79b0d..a4a8b9b637 100644 --- a/web/app/components/header/account-setting/data-source-page/data-source-website/config-firecrawl-modal.tsx +++ b/web/app/components/header/account-setting/data-source-page/data-source-website/config-firecrawl-modal.tsx @@ -9,7 +9,7 @@ import { import { Lock01 } from '@/app/components/base/icons/src/vender/solid/security' import Button from '@/app/components/base/button' import type { FirecrawlConfig } from '@/models/common' -import Field from '@/app/components/datasets/create/website/firecrawl/base/field' +import Field from '@/app/components/datasets/create/website/base/field' import Toast from '@/app/components/base/toast' import { createDataSourceApiKeyBinding } from '@/service/datasets' import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/general' diff --git a/web/app/components/header/account-setting/data-source-page/data-source-website/config-jina-reader-modal.tsx b/web/app/components/header/account-setting/data-source-page/data-source-website/config-jina-reader-modal.tsx new file mode 100644 index 0000000000..c6d6ad0256 --- /dev/null +++ b/web/app/components/header/account-setting/data-source-page/data-source-website/config-jina-reader-modal.tsx @@ -0,0 +1,140 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { + PortalToFollowElem, + PortalToFollowElemContent, +} from '@/app/components/base/portal-to-follow-elem' +import { Lock01 } from '@/app/components/base/icons/src/vender/solid/security' +import Button from '@/app/components/base/button' +import { DataSourceProvider } from '@/models/common' +import Field from '@/app/components/datasets/create/website/base/field' +import Toast from '@/app/components/base/toast' +import { createDataSourceApiKeyBinding } from '@/service/datasets' +import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/general' +type Props = { + onCancel: () => void + onSaved: () => void +} + +const I18N_PREFIX = 'datasetCreation.jinaReader' + +const ConfigJinaReaderModal: FC = ({ + onCancel, + onSaved, +}) => { + const { t } = useTranslation() + const [isSaving, setIsSaving] = useState(false) + const [apiKey, setApiKey] = useState('') + + const handleSave = useCallback(async () => { + if (isSaving) + return + let errorMsg = '' + if (!errorMsg) { + if (!apiKey) { + errorMsg = t('common.errorMsg.fieldRequired', { + field: 'API Key', + }) + } + } + + if (errorMsg) { + Toast.notify({ + type: 'error', + message: errorMsg, + }) + return + } + const postData = { + category: 'website', + provider: DataSourceProvider.jinaReader, + credentials: { + auth_type: 'bearer', + config: { + api_key: apiKey, + }, + }, + } + try { + setIsSaving(true) + await createDataSourceApiKeyBinding(postData) + Toast.notify({ + type: 'success', + message: t('common.api.success'), + }) + } + finally { + setIsSaving(false) + } + + onSaved() + }, [apiKey, onSaved, t, isSaving]) + + return ( + + +
+
+
+
+
{t(`${I18N_PREFIX}.configJinaReader`)}
+
+ +
+ setApiKey(value as string)} + placeholder={t(`${I18N_PREFIX}.apiKeyPlaceholder`)!} + /> +
+
+ + {t(`${I18N_PREFIX}.getApiKeyLinkText`)} + + +
+ + +
+ +
+
+
+
+ + {t('common.modelProvider.encrypted.front')} + + PKCS1_OAEP + + {t('common.modelProvider.encrypted.back')} +
+
+
+
+
+
+ ) +} +export default React.memo(ConfigJinaReaderModal) diff --git a/web/app/components/header/account-setting/data-source-page/data-source-website/index.tsx b/web/app/components/header/account-setting/data-source-page/data-source-website/index.tsx index 21f7660ef1..628510c5dd 100644 --- a/web/app/components/header/account-setting/data-source-page/data-source-website/index.tsx +++ b/web/app/components/header/account-setting/data-source-page/data-source-website/index.tsx @@ -2,11 +2,12 @@ import type { FC } from 'react' import React, { useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { useBoolean } from 'ahooks' import Panel from '../panel' import { DataSourceType } from '../panel/types' import ConfigFirecrawlModal from './config-firecrawl-modal' +import ConfigJinaReaderModal from './config-jina-reader-modal' import cn from '@/utils/classnames' +import s from '@/app/components/datasets/create/website/index.module.css' import { fetchDataSources, removeDataSourceApiKeyBinding } from '@/service/datasets' import type { @@ -19,9 +20,11 @@ import { } from '@/models/common' import Toast from '@/app/components/base/toast' -type Props = {} +type Props = { + provider: DataSourceProvider +} -const DataSourceWebsite: FC = () => { +const DataSourceWebsite: FC = ({ provider }) => { const { t } = useTranslation() const { isCurrentWorkspaceManager } = useAppContext() const [sources, setSources] = useState([]) @@ -36,22 +39,26 @@ const DataSourceWebsite: FC = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []) - const [isShowConfig, { - setTrue: showConfig, - setFalse: hideConfig, - }] = useBoolean(false) + const [configTarget, setConfigTarget] = useState(null) + const showConfig = useCallback((provider: DataSourceProvider) => { + setConfigTarget(provider) + }, [setConfigTarget]) + + const hideConfig = useCallback(() => { + setConfigTarget(null) + }, [setConfigTarget]) const handleAdded = useCallback(() => { checkSetApiKey() hideConfig() }, [checkSetApiKey, hideConfig]) - const getIdByProvider = (provider: string): string | undefined => { + const getIdByProvider = (provider: DataSourceProvider): string | undefined => { const source = sources.find(item => item.provider === provider) return source?.id } - const handleRemove = useCallback((provider: string) => { + const handleRemove = useCallback((provider: DataSourceProvider) => { return async () => { const dataSourceId = getIdByProvider(provider) if (dataSourceId) { @@ -69,22 +76,34 @@ const DataSourceWebsite: FC = () => { <> 0} - onConfigure={showConfig} + provider={provider} + isConfigured={sources.find(item => item.provider === provider) !== undefined} + onConfigure={() => showConfig(provider)} readOnly={!isCurrentWorkspaceManager} - configuredList={sources.map(item => ({ + configuredList={sources.filter(item => item.provider === provider).map(item => ({ id: item.id, logo: ({ className }: { className: string }) => ( -
🔥
+ item.provider === DataSourceProvider.fireCrawl + ? ( +
🔥
+ ) + : ( +
+ +
+ ) ), - name: 'Firecrawl', + name: item.provider === DataSourceProvider.fireCrawl ? 'Firecrawl' : 'Jina Reader', isActive: true, }))} - onRemove={handleRemove(DataSourceProvider.fireCrawl)} + onRemove={handleRemove(provider)} /> - {isShowConfig && ( + {configTarget === DataSourceProvider.fireCrawl && ( )} + {configTarget === DataSourceProvider.jinaReader && ( + + )} ) diff --git a/web/app/components/header/account-setting/data-source-page/index.tsx b/web/app/components/header/account-setting/data-source-page/index.tsx index ede83152b2..c3da977ca4 100644 --- a/web/app/components/header/account-setting/data-source-page/index.tsx +++ b/web/app/components/header/account-setting/data-source-page/index.tsx @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next' import DataSourceNotion from './data-source-notion' import DataSourceWebsite from './data-source-website' import { fetchDataSource } from '@/service/common' +import { DataSourceProvider } from '@/models/common' export default function DataSourcePage() { const { t } = useTranslation() @@ -13,7 +14,8 @@ export default function DataSourcePage() {
{t('common.dataSource.add')}
- + +
) } diff --git a/web/app/components/header/account-setting/data-source-page/panel/index.tsx b/web/app/components/header/account-setting/data-source-page/panel/index.tsx index 988aedcaf7..4a810020b4 100644 --- a/web/app/components/header/account-setting/data-source-page/panel/index.tsx +++ b/web/app/components/header/account-setting/data-source-page/panel/index.tsx @@ -8,10 +8,12 @@ import ConfigItem from './config-item' import s from './style.module.css' import { DataSourceType } from './types' +import { DataSourceProvider } from '@/models/common' import cn from '@/utils/classnames' type Props = { type: DataSourceType + provider: DataSourceProvider isConfigured: boolean onConfigure: () => void readOnly: boolean @@ -25,6 +27,7 @@ type Props = { const Panel: FC = ({ type, + provider, isConfigured, onConfigure, readOnly, @@ -46,7 +49,7 @@ const Panel: FC = ({
{t(`common.dataSource.${type}.title`)}
{isWebsite && (
- {t('common.dataSource.website.with')} 🔥 Firecrawl + {t('common.dataSource.website.with')} { provider === DataSourceProvider.fireCrawl ? '🔥 Firecrawl' : 'Jina Reader'}
)}
diff --git a/web/i18n/en-US/dataset-creation.ts b/web/i18n/en-US/dataset-creation.ts index 32f9d596ca..1849b12757 100644 --- a/web/i18n/en-US/dataset-creation.ts +++ b/web/i18n/en-US/dataset-creation.ts @@ -16,6 +16,11 @@ const translation = { apiKeyPlaceholder: 'API key from firecrawl.dev', getApiKeyLinkText: 'Get your API key from firecrawl.dev', }, + jinaReader: { + configJinaReader: 'Configure Jina Reader', + apiKeyPlaceholder: 'API key from jina.ai', + getApiKeyLinkText: 'Get your free API key at jina.ai', + }, stepOne: { filePreview: 'File Preview', pagePreview: 'Page Preview', @@ -56,13 +61,21 @@ const translation = { failed: 'Creation failed', }, website: { + chooseProvider: 'Select a provider', fireCrawlNotConfigured: 'Firecrawl is not configured', fireCrawlNotConfiguredDescription: 'Configure Firecrawl with API key to use it.', + jinaReaderNotConfigured: 'Jina Reader is not configured', + jinaReaderNotConfiguredDescription: 'Set up Jina Reader by entering your free API key for access.', configure: 'Configure', run: 'Run', firecrawlTitle: 'Extract web content with 🔥Firecrawl', firecrawlDoc: 'Firecrawl docs', firecrawlDocLink: 'https://docs.dify.ai/guides/knowledge-base/sync-from-website', + jinaReaderTitle: 'Convert the entire site to Markdown', + jinaReaderDoc: 'Learn more about Jina Reader', + jinaReaderDocLink: 'https://jina.ai/reader', + useSitemap: 'Use sitemap', + useSitemapTooltip: 'Follow the sitemap to crawl the site. If not, Jina Reader will crawl iteratively based on page relevance, yielding fewer but higher-quality pages.', options: 'Options', crawlSubPage: 'Crawl sub-pages', limit: 'Limit', @@ -70,7 +83,7 @@ const translation = { excludePaths: 'Exclude paths', includeOnlyPaths: 'Include only paths', extractOnlyMainContent: 'Extract only main content (no headers, navs, footers, etc.)', - exceptionErrorTitle: 'An exception occurred while running Firecrawl job:', + exceptionErrorTitle: 'An exception occurred while running crawling job:', unknownError: 'Unknown error', totalPageScraped: 'Total pages scraped:', selectAll: 'Select All', diff --git a/web/i18n/zh-Hans/dataset-creation.ts b/web/i18n/zh-Hans/dataset-creation.ts index 78f5170791..4f6786a191 100644 --- a/web/i18n/zh-Hans/dataset-creation.ts +++ b/web/i18n/zh-Hans/dataset-creation.ts @@ -16,6 +16,11 @@ const translation = { apiKeyPlaceholder: '从 firecrawl.dev 获取 API Key', getApiKeyLinkText: '从 firecrawl.dev 获取您的 API Key', }, + jinaReader: { + configJinaReader: '配置 Jina Reader', + apiKeyPlaceholder: '从 jina.ai 获取 API Key', + getApiKeyLinkText: '从 jina.ai 获取您的免费 API Key', + }, stepOne: { filePreview: '文件预览', pagePreview: '页面预览', @@ -56,13 +61,21 @@ const translation = { failed: '创建失败', }, website: { + chooseProvider: '选择工具', fireCrawlNotConfigured: 'Firecrawl 未配置', fireCrawlNotConfiguredDescription: '请配置 Firecrawl 的 API 密钥以使用它。', + jinaReaderNotConfigured: 'Jina Reader 未配置', + jinaReaderNotConfiguredDescription: '请配置 Jina Reader 的免费 API 密钥以访问它。', configure: '配置', run: '运行', firecrawlTitle: '使用 🔥Firecrawl 提取网页内容', firecrawlDoc: 'Firecrawl 文档', firecrawlDocLink: 'https://docs.dify.ai/v/zh-hans/guides/knowledge-base/sync-from-website', + jinaReaderTitle: '将整个站点内容转换为 Markdown 格式', + jinaReaderDoc: '了解更多关于 Jina Reader', + jinaReaderDocLink: 'https://jina.ai/reader', + useSitemap: '使用 sitemap', + useSitemapTooltip: '根据 sitemap 爬取站点。否则,Jina Reader 将基于页面相关性迭代爬取,抓取较少的页面,但质量更高。', options: '选项', crawlSubPage: '爬取子页面', limit: '限制数量', @@ -70,7 +83,7 @@ const translation = { excludePaths: '排除路径', includeOnlyPaths: '仅包含路径', extractOnlyMainContent: '仅提取主要内容(无标题、导航、页脚等)', - exceptionErrorTitle: '运行 Firecrawl 时发生异常:', + exceptionErrorTitle: '运行时发生异常:', unknownError: '未知错误', totalPageScraped: '抓取页面总数:', selectAll: '全选', diff --git a/web/models/common.ts b/web/models/common.ts index 78f09bee09..204e89ed9b 100644 --- a/web/models/common.ts +++ b/web/models/common.ts @@ -177,6 +177,7 @@ export enum DataSourceCategory { } export enum DataSourceProvider { fireCrawl = 'firecrawl', + jinaReader = 'jinareader', } export type FirecrawlConfig = { diff --git a/web/models/datasets.ts b/web/models/datasets.ts index 23d1fe6136..9358f6fcb9 100644 --- a/web/models/datasets.ts +++ b/web/models/datasets.ts @@ -49,6 +49,7 @@ export type CrawlOptions = { excludes: string limit: number | string max_depth: number | string + use_sitemap: boolean } export type CrawlResultItem = { diff --git a/web/service/datasets.ts b/web/service/datasets.ts index 4ca269a7d6..689ac7c403 100644 --- a/web/service/datasets.ts +++ b/web/service/datasets.ts @@ -23,7 +23,7 @@ import type { SegmentsResponse, createDocumentResponse, } from '@/models/datasets' -import type { CommonResponse, DataSourceNotionWorkspace } from '@/models/common' +import { type CommonResponse, type DataSourceNotionWorkspace, DataSourceProvider } from '@/models/common' import type { ApiKeysListResponse, CreateApiKeyResponse, @@ -253,7 +253,7 @@ export const createFirecrawlTask: Fetcher> = return post('website/crawl', { body: { ...body, - provider: 'firecrawl', + provider: DataSourceProvider.fireCrawl, }, }) } @@ -261,7 +261,26 @@ export const createFirecrawlTask: Fetcher> = export const checkFirecrawlTaskStatus: Fetcher = (jobId: string) => { return get(`website/crawl/status/${jobId}`, { params: { - provider: 'firecrawl', + provider: DataSourceProvider.fireCrawl, + }, + }, { + silent: true, + }) +} + +export const createJinaReaderTask: Fetcher> = (body) => { + return post('website/crawl', { + body: { + ...body, + provider: DataSourceProvider.jinaReader, + }, + }) +} + +export const checkJinaReaderTaskStatus: Fetcher = (jobId: string) => { + return get(`website/crawl/status/${jobId}`, { + params: { + provider: 'jinareader', }, }, { silent: true, From 3af65b2f452ae765cde4916507350b8c59ea2aea Mon Sep 17 00:00:00 2001 From: -LAN- Date: Mon, 30 Sep 2024 11:12:26 +0800 Subject: [PATCH 017/136] feat(api): add version comparison logic (#8902) --- api/controllers/console/version.py | 49 +++++++++++++++++-- .../controllers/test_compare_versions.py | 38 ++++++++++++++ 2 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 api/tests/unit_tests/controllers/test_compare_versions.py diff --git a/api/controllers/console/version.py b/api/controllers/console/version.py index 76adbfe6a9..deda1a0d02 100644 --- a/api/controllers/console/version.py +++ b/api/controllers/console/version.py @@ -38,11 +38,52 @@ class VersionApi(Resource): return result content = json.loads(response.content) - result["version"] = content["version"] - result["release_date"] = content["releaseDate"] - result["release_notes"] = content["releaseNotes"] - result["can_auto_update"] = content["canAutoUpdate"] + if _has_new_version(latest_version=content["version"], current_version=f"{args.get('current_version')}"): + result["version"] = content["version"] + result["release_date"] = content["releaseDate"] + result["release_notes"] = content["releaseNotes"] + result["can_auto_update"] = content["canAutoUpdate"] return result +def _has_new_version(*, latest_version: str, current_version: str) -> bool: + def parse_version(version: str) -> tuple: + # Split version into parts and pre-release suffix if any + parts = version.split("-") + version_parts = parts[0].split(".") + pre_release = parts[1] if len(parts) > 1 else None + + # Validate version format + if len(version_parts) != 3: + raise ValueError(f"Invalid version format: {version}") + + try: + # Convert version parts to integers + major, minor, patch = map(int, version_parts) + return (major, minor, patch, pre_release) + except ValueError: + raise ValueError(f"Invalid version format: {version}") + + latest = parse_version(latest_version) + current = parse_version(current_version) + + # Compare major, minor, and patch versions + for latest_part, current_part in zip(latest[:3], current[:3]): + if latest_part > current_part: + return True + elif latest_part < current_part: + return False + + # If versions are equal, check pre-release suffixes + if latest[3] is None and current[3] is not None: + return True + elif latest[3] is not None and current[3] is None: + return False + elif latest[3] is not None and current[3] is not None: + # Simple string comparison for pre-release versions + return latest[3] > current[3] + + return False + + api.add_resource(VersionApi, "/version") diff --git a/api/tests/unit_tests/controllers/test_compare_versions.py b/api/tests/unit_tests/controllers/test_compare_versions.py new file mode 100644 index 0000000000..87902b6d44 --- /dev/null +++ b/api/tests/unit_tests/controllers/test_compare_versions.py @@ -0,0 +1,38 @@ +import pytest + +from controllers.console.version import _has_new_version + + +@pytest.mark.parametrize( + ("latest_version", "current_version", "expected"), + [ + ("1.0.1", "1.0.0", True), + ("1.1.0", "1.0.0", True), + ("2.0.0", "1.9.9", True), + ("1.0.0", "1.0.0", False), + ("1.0.0", "1.0.1", False), + ("1.0.0", "2.0.0", False), + ("1.0.1", "1.0.0-beta", True), + ("1.0.0", "1.0.0-alpha", True), + ("1.0.0-beta", "1.0.0-alpha", True), + ("1.0.0", "1.0.0-rc1", True), + ("1.0.0", "0.9.9", True), + ("1.0.0", "1.0.0-dev", True), + ], +) +def test_has_new_version(latest_version, current_version, expected): + assert _has_new_version(latest_version=latest_version, current_version=current_version) == expected + + +def test_has_new_version_invalid_input(): + with pytest.raises(ValueError): + _has_new_version(latest_version="1.0", current_version="1.0.0") + + with pytest.raises(ValueError): + _has_new_version(latest_version="1.0.0", current_version="1.0") + + with pytest.raises(ValueError): + _has_new_version(latest_version="invalid", current_version="1.0.0") + + with pytest.raises(ValueError): + _has_new_version(latest_version="1.0.0", current_version="invalid") From ada9d408ac66bc8775d0a2c72568c43666946b1a Mon Sep 17 00:00:00 2001 From: -LAN- Date: Mon, 30 Sep 2024 12:48:58 +0800 Subject: [PATCH 018/136] refactor(api/variables): VariableError as a ValueError. (#8554) --- api/core/app/segments/exc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/core/app/segments/exc.py b/api/core/app/segments/exc.py index d15d6d500f..5cf67c3bac 100644 --- a/api/core/app/segments/exc.py +++ b/api/core/app/segments/exc.py @@ -1,2 +1,2 @@ -class VariableError(Exception): +class VariableError(ValueError): pass From 503561f464c50a9a8469614603407f8accfd025f Mon Sep 17 00:00:00 2001 From: zhuhao <37029601+hwzhuhao@users.noreply.github.com> Date: Mon, 30 Sep 2024 12:52:18 +0800 Subject: [PATCH 019/136] fix: fix the data validation consistency issue in keyword content review (#8908) --- api/core/moderation/keywords/keywords.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/api/core/moderation/keywords/keywords.py b/api/core/moderation/keywords/keywords.py index dc6a7ec564..4846da8f93 100644 --- a/api/core/moderation/keywords/keywords.py +++ b/api/core/moderation/keywords/keywords.py @@ -18,8 +18,12 @@ class KeywordsModeration(Moderation): if not config.get("keywords"): raise ValueError("keywords is required") - if len(config.get("keywords")) > 1000: - raise ValueError("keywords length must be less than 1000") + if len(config.get("keywords")) > 10000: + raise ValueError("keywords length must be less than 10000") + + keywords_row_len = config["keywords"].split("\n") + if len(keywords_row_len) > 100: + raise ValueError("the number of rows for the keywords must be less than 100") def moderation_for_inputs(self, inputs: dict, query: str = "") -> ModerationInputsResult: flagged = False From 77aef9ff1db220dfbab5da6e48061051b98b7cbd Mon Sep 17 00:00:00 2001 From: zhuhao <37029601+hwzhuhao@users.noreply.github.com> Date: Mon, 30 Sep 2024 12:55:01 +0800 Subject: [PATCH 020/136] refactor: optimize the calculation of rerank threshold and the logic for forbidden characters in model_uid (#8879) --- .../model_providers/xinference/llm/llm.py | 3 ++- .../model_providers/xinference/rerank/rerank.py | 8 +++----- .../xinference/speech2text/speech2text.py | 3 ++- .../xinference/text_embedding/text_embedding.py | 4 ++-- .../model_providers/xinference/tts/tts.py | 4 ++-- .../model_providers/xinference/xinference_helper.py | 13 +++++++++++++ 6 files changed, 24 insertions(+), 11 deletions(-) diff --git a/api/core/model_runtime/model_providers/xinference/llm/llm.py b/api/core/model_runtime/model_providers/xinference/llm/llm.py index 286640079b..0c9d08679a 100644 --- a/api/core/model_runtime/model_providers/xinference/llm/llm.py +++ b/api/core/model_runtime/model_providers/xinference/llm/llm.py @@ -59,6 +59,7 @@ from core.model_runtime.model_providers.__base.large_language_model import Large from core.model_runtime.model_providers.xinference.xinference_helper import ( XinferenceHelper, XinferenceModelExtraParameter, + validate_model_uid, ) from core.model_runtime.utils import helper @@ -114,7 +115,7 @@ class XinferenceAILargeLanguageModel(LargeLanguageModel): } """ try: - if "/" in credentials["model_uid"] or "?" in credentials["model_uid"] or "#" in credentials["model_uid"]: + if not validate_model_uid(credentials): raise CredentialsValidateFailedError("model_uid should not contain /, ?, or #") extra_param = XinferenceHelper.get_xinference_extra_parameter( diff --git a/api/core/model_runtime/model_providers/xinference/rerank/rerank.py b/api/core/model_runtime/model_providers/xinference/rerank/rerank.py index 8f18bc42d2..6368cd76dc 100644 --- a/api/core/model_runtime/model_providers/xinference/rerank/rerank.py +++ b/api/core/model_runtime/model_providers/xinference/rerank/rerank.py @@ -15,6 +15,7 @@ from core.model_runtime.errors.invoke import ( ) from core.model_runtime.errors.validate import CredentialsValidateFailedError from core.model_runtime.model_providers.__base.rerank_model import RerankModel +from core.model_runtime.model_providers.xinference.xinference_helper import validate_model_uid class XinferenceRerankModel(RerankModel): @@ -77,10 +78,7 @@ class XinferenceRerankModel(RerankModel): ) # score threshold check - if score_threshold is not None: - if result["relevance_score"] >= score_threshold: - rerank_documents.append(rerank_document) - else: + if score_threshold is None or result["relevance_score"] >= score_threshold: rerank_documents.append(rerank_document) return RerankResult(model=model, docs=rerank_documents) @@ -94,7 +92,7 @@ class XinferenceRerankModel(RerankModel): :return: """ try: - if "/" in credentials["model_uid"] or "?" in credentials["model_uid"] or "#" in credentials["model_uid"]: + if not validate_model_uid(credentials): raise CredentialsValidateFailedError("model_uid should not contain /, ?, or #") credentials["server_url"] = credentials["server_url"].removesuffix("/") diff --git a/api/core/model_runtime/model_providers/xinference/speech2text/speech2text.py b/api/core/model_runtime/model_providers/xinference/speech2text/speech2text.py index a6c5b8a0a5..c5ad383911 100644 --- a/api/core/model_runtime/model_providers/xinference/speech2text/speech2text.py +++ b/api/core/model_runtime/model_providers/xinference/speech2text/speech2text.py @@ -14,6 +14,7 @@ from core.model_runtime.errors.invoke import ( ) from core.model_runtime.errors.validate import CredentialsValidateFailedError from core.model_runtime.model_providers.__base.speech2text_model import Speech2TextModel +from core.model_runtime.model_providers.xinference.xinference_helper import validate_model_uid class XinferenceSpeech2TextModel(Speech2TextModel): @@ -42,7 +43,7 @@ class XinferenceSpeech2TextModel(Speech2TextModel): :return: """ try: - if "/" in credentials["model_uid"] or "?" in credentials["model_uid"] or "#" in credentials["model_uid"]: + if not validate_model_uid(credentials): raise CredentialsValidateFailedError("model_uid should not contain /, ?, or #") credentials["server_url"] = credentials["server_url"].removesuffix("/") diff --git a/api/core/model_runtime/model_providers/xinference/text_embedding/text_embedding.py b/api/core/model_runtime/model_providers/xinference/text_embedding/text_embedding.py index 1627239132..ddc21b365c 100644 --- a/api/core/model_runtime/model_providers/xinference/text_embedding/text_embedding.py +++ b/api/core/model_runtime/model_providers/xinference/text_embedding/text_embedding.py @@ -17,7 +17,7 @@ from core.model_runtime.errors.invoke import ( ) from core.model_runtime.errors.validate import CredentialsValidateFailedError from core.model_runtime.model_providers.__base.text_embedding_model import TextEmbeddingModel -from core.model_runtime.model_providers.xinference.xinference_helper import XinferenceHelper +from core.model_runtime.model_providers.xinference.xinference_helper import XinferenceHelper, validate_model_uid class XinferenceTextEmbeddingModel(TextEmbeddingModel): @@ -110,7 +110,7 @@ class XinferenceTextEmbeddingModel(TextEmbeddingModel): :return: """ try: - if "/" in credentials["model_uid"] or "?" in credentials["model_uid"] or "#" in credentials["model_uid"]: + if not validate_model_uid(credentials): raise CredentialsValidateFailedError("model_uid should not contain /, ?, or #") server_url = credentials["server_url"] diff --git a/api/core/model_runtime/model_providers/xinference/tts/tts.py b/api/core/model_runtime/model_providers/xinference/tts/tts.py index 81dbe397d2..6290e8551d 100644 --- a/api/core/model_runtime/model_providers/xinference/tts/tts.py +++ b/api/core/model_runtime/model_providers/xinference/tts/tts.py @@ -15,7 +15,7 @@ from core.model_runtime.errors.invoke import ( ) from core.model_runtime.errors.validate import CredentialsValidateFailedError from core.model_runtime.model_providers.__base.tts_model import TTSModel -from core.model_runtime.model_providers.xinference.xinference_helper import XinferenceHelper +from core.model_runtime.model_providers.xinference.xinference_helper import XinferenceHelper, validate_model_uid class XinferenceText2SpeechModel(TTSModel): @@ -70,7 +70,7 @@ class XinferenceText2SpeechModel(TTSModel): :return: """ try: - if "/" in credentials["model_uid"] or "?" in credentials["model_uid"] or "#" in credentials["model_uid"]: + if not validate_model_uid(credentials): raise CredentialsValidateFailedError("model_uid should not contain /, ?, or #") credentials["server_url"] = credentials["server_url"].removesuffix("/") diff --git a/api/core/model_runtime/model_providers/xinference/xinference_helper.py b/api/core/model_runtime/model_providers/xinference/xinference_helper.py index 619ee1492a..baa3ccbe8a 100644 --- a/api/core/model_runtime/model_providers/xinference/xinference_helper.py +++ b/api/core/model_runtime/model_providers/xinference/xinference_helper.py @@ -132,3 +132,16 @@ class XinferenceHelper: context_length=context_length, model_family=model_family, ) + + +def validate_model_uid(credentials: dict) -> bool: + """ + Validate the model_uid within the credentials dictionary to ensure it does not + contain forbidden characters ("/", "?", "#"). + + param credentials: model credentials + :return: True if the model_uid does not contain forbidden characters ("/", "?", "#"), else False. + """ + forbidden_characters = ["/", "?", "#"] + model_uid = credentials.get("model_uid", "") + return not any(char in forbidden_characters for char in model_uid) From 9d221a5e19f8613fa1a47984649378b22a0fd66e Mon Sep 17 00:00:00 2001 From: Jyong <76649700+JohnJyong@users.noreply.github.com> Date: Mon, 30 Sep 2024 15:38:43 +0800 Subject: [PATCH 021/136] external knowledge api (#8913) Co-authored-by: Yi --- api/controllers/console/__init__.py | 11 +- api/controllers/console/datasets/datasets.py | 54 +- api/controllers/console/datasets/external.py | 239 +++ .../console/datasets/hit_testing.py | 2 + .../service_api/dataset/dataset.py | 27 +- .../index_tool_callback_handler.py | 2 +- api/core/rag/datasource/retrieval_service.py | 14 + api/core/rag/entities/context_entities.py | 10 + api/core/rag/models/document.py | 2 + api/core/rag/rerank/rerank_model.py | 17 +- api/core/rag/retrieval/dataset_retrieval.py | 298 ++-- .../knowledge_retrieval_node.py | 44 +- api/fields/dataset_fields.py | 13 + api/fields/external_dataset_fields.py | 11 + ...-6af6a521a53e_update_retrieval_resource.py | 48 + ...434-33f5fac87f29_external_knowledge_api.py | 73 + ...fca025d3b60f_add_dataset_retrival_model.py | 2 +- api/models/dataset.py | 106 ++ api/models/model.py | 6 +- api/poetry.lock | 1524 +++++++++-------- api/pyproject.toml | 1 + api/schedule/clean_unused_messages_task.py | 92 + api/services/dataset_service.py | 191 ++- .../external_knowledge_entities.py | 26 + api/services/external_knowledge_service.py | 274 +++ api/services/hit_testing_service.py | 68 +- api/tasks/external_document_indexing_task.py | 93 + .../[datasetId]/layout.tsx | 26 +- web/app/(commonLayout)/datasets/Container.tsx | 20 +- .../(commonLayout)/datasets/DatasetCard.tsx | 29 +- .../datasets/NewDatasetCard.tsx | 27 +- .../(commonLayout)/datasets/connect/page.tsx | 8 + web/app/(commonLayout)/datasets/layout.tsx | 14 + web/app/(commonLayout)/datasets/page.tsx | 4 +- web/app/(commonLayout)/datasets/store.ts | 11 + web/app/components/app-sidebar/basic.tsx | 7 +- web/app/components/app-sidebar/index.tsx | 4 +- .../dataset-config/card-item/item.tsx | 10 +- .../params-config/config-content.tsx | 20 +- .../dataset-config/params-config/index.tsx | 15 +- .../dataset-config/select-dataset/index.tsx | 7 +- .../dataset-config/settings-modal/index.tsx | 148 +- .../components/base/corner-label/index.tsx | 21 + .../solid/development/api-connection-mod.svg | 5 + .../assets/vender/solid/shapes/corner.svg | 3 + .../solid/development/ApiConnectionMod.json | 38 + .../solid/development/ApiConnectionMod.tsx | 16 + .../src/vender/solid/development/index.ts | 1 + .../icons/src/vender/solid/shapes/Corner.json | 27 + .../icons/src/vender/solid/shapes/Corner.tsx | 16 + .../icons/src/vender/solid/shapes/index.ts | 1 + web/app/components/base/modal/index.css | 2 +- web/app/components/base/param-item/index.tsx | 1 + web/app/components/base/select/index.tsx | 2 +- .../detail/completed/SegmentCard.tsx | 20 +- .../datasets/external-api/declarations.ts | 16 + .../external-api/external-api-modal/Form.tsx | 90 + .../external-api/external-api-modal/index.tsx | 218 +++ .../external-api/external-api-panel/index.tsx | 90 + .../external-knowledge-api-card/index.tsx | 151 ++ .../connector/index.tsx | 36 + .../create/ExternalApiSelect.tsx | 110 ++ .../create/ExternalApiSelection.tsx | 96 ++ .../create/InfoPanel.tsx | 33 + .../create/KnowledgeBaseInfo.tsx | 65 + .../create/RetrievalSettings.tsx | 67 + .../create/declarations.ts | 12 + .../external-knowledge-base/create/index.tsx | 128 ++ .../datasets/hit-testing/hit-detail.tsx | 10 +- .../components/datasets/hit-testing/index.tsx | 111 +- .../modify-external-retrieval-modal.tsx | 71 + .../datasets/hit-testing/textarea.tsx | 91 +- .../datasets/rename-modal/index.tsx | 15 +- .../datasets/settings/form/index.tsx | 122 +- .../components/header/dataset-nav/index.tsx | 2 +- .../components/dataset-item.tsx | 58 +- .../nodes/knowledge-retrieval/use-config.ts | 10 +- .../nodes/knowledge-retrieval/utils.ts | 31 +- web/context/external-api-panel-context.tsx | 28 + .../external-knowledge-api-context.tsx | 46 + web/context/modal-context.tsx | 39 + web/i18n/en-US/dataset-hit-testing.ts | 4 +- web/i18n/en-US/dataset-settings.ts | 11 +- web/i18n/en-US/dataset.ts | 74 + web/i18n/zh-Hans/dataset-hit-testing.ts | 4 +- web/i18n/zh-Hans/dataset-settings.ts | 6 +- web/i18n/zh-Hans/dataset.ts | 74 + web/i18n/zh-Hant/dataset-hit-testing.ts | 1 + web/models/datasets.ts | 81 + web/service/datasets.ts | 42 +- 90 files changed, 4623 insertions(+), 1171 deletions(-) create mode 100644 api/controllers/console/datasets/external.py create mode 100644 api/core/rag/entities/context_entities.py create mode 100644 api/fields/external_dataset_fields.py create mode 100644 api/migrations/versions/2024_09_24_0922-6af6a521a53e_update_retrieval_resource.py create mode 100644 api/migrations/versions/2024_09_25_0434-33f5fac87f29_external_knowledge_api.py create mode 100644 api/schedule/clean_unused_messages_task.py create mode 100644 api/services/entities/external_knowledge_entities/external_knowledge_entities.py create mode 100644 api/services/external_knowledge_service.py create mode 100644 api/tasks/external_document_indexing_task.py create mode 100644 web/app/(commonLayout)/datasets/connect/page.tsx create mode 100644 web/app/(commonLayout)/datasets/layout.tsx create mode 100644 web/app/(commonLayout)/datasets/store.ts create mode 100644 web/app/components/base/corner-label/index.tsx create mode 100644 web/app/components/base/icons/assets/vender/solid/development/api-connection-mod.svg create mode 100644 web/app/components/base/icons/assets/vender/solid/shapes/corner.svg create mode 100644 web/app/components/base/icons/src/vender/solid/development/ApiConnectionMod.json create mode 100644 web/app/components/base/icons/src/vender/solid/development/ApiConnectionMod.tsx create mode 100644 web/app/components/base/icons/src/vender/solid/shapes/Corner.json create mode 100644 web/app/components/base/icons/src/vender/solid/shapes/Corner.tsx create mode 100644 web/app/components/datasets/external-api/declarations.ts create mode 100644 web/app/components/datasets/external-api/external-api-modal/Form.tsx create mode 100644 web/app/components/datasets/external-api/external-api-modal/index.tsx create mode 100644 web/app/components/datasets/external-api/external-api-panel/index.tsx create mode 100644 web/app/components/datasets/external-api/external-knowledge-api-card/index.tsx create mode 100644 web/app/components/datasets/external-knowledge-base/connector/index.tsx create mode 100644 web/app/components/datasets/external-knowledge-base/create/ExternalApiSelect.tsx create mode 100644 web/app/components/datasets/external-knowledge-base/create/ExternalApiSelection.tsx create mode 100644 web/app/components/datasets/external-knowledge-base/create/InfoPanel.tsx create mode 100644 web/app/components/datasets/external-knowledge-base/create/KnowledgeBaseInfo.tsx create mode 100644 web/app/components/datasets/external-knowledge-base/create/RetrievalSettings.tsx create mode 100644 web/app/components/datasets/external-knowledge-base/create/declarations.ts create mode 100644 web/app/components/datasets/external-knowledge-base/create/index.tsx create mode 100644 web/app/components/datasets/hit-testing/modify-external-retrieval-modal.tsx create mode 100644 web/context/external-api-panel-context.tsx create mode 100644 web/context/external-knowledge-api-context.tsx diff --git a/api/controllers/console/__init__.py b/api/controllers/console/__init__.py index eb7c1464d3..c7282fcf14 100644 --- a/api/controllers/console/__init__.py +++ b/api/controllers/console/__init__.py @@ -37,7 +37,16 @@ from .auth import activate, data_source_bearer_auth, data_source_oauth, forgot_p from .billing import billing # Import datasets controllers -from .datasets import data_source, datasets, datasets_document, datasets_segments, file, hit_testing, website +from .datasets import ( + data_source, + datasets, + datasets_document, + datasets_segments, + external, + file, + hit_testing, + website, +) # Import explore controllers from .explore import ( diff --git a/api/controllers/console/datasets/datasets.py b/api/controllers/console/datasets/datasets.py index 5a763b3457..9561fd8b70 100644 --- a/api/controllers/console/datasets/datasets.py +++ b/api/controllers/console/datasets/datasets.py @@ -49,7 +49,7 @@ class DatasetListApi(Resource): page = request.args.get("page", default=1, type=int) limit = request.args.get("limit", default=20, type=int) ids = request.args.getlist("ids") - provider = request.args.get("provider", default="vendor") + # provider = request.args.get("provider", default="vendor") search = request.args.get("keyword", default=None, type=str) tag_ids = request.args.getlist("tag_ids") @@ -57,7 +57,7 @@ class DatasetListApi(Resource): datasets, total = DatasetService.get_datasets_by_ids(ids, current_user.current_tenant_id) else: datasets, total = DatasetService.get_datasets( - page, limit, provider, current_user.current_tenant_id, current_user, search, tag_ids + page, limit, current_user.current_tenant_id, current_user, search, tag_ids ) # check embedding setting @@ -110,6 +110,26 @@ class DatasetListApi(Resource): nullable=True, help="Invalid indexing technique.", ) + parser.add_argument( + "external_knowledge_api_id", + type=str, + nullable=True, + required=False, + ) + parser.add_argument( + "provider", + type=str, + nullable=True, + choices=Dataset.PROVIDER_LIST, + required=False, + default="vendor", + ) + parser.add_argument( + "external_knowledge_id", + type=str, + nullable=True, + required=False, + ) args = parser.parse_args() # The role of the current user in the ta table must be admin, owner, or editor, or dataset_operator @@ -123,6 +143,9 @@ class DatasetListApi(Resource): indexing_technique=args["indexing_technique"], account=current_user, permission=DatasetPermissionEnum.ONLY_ME, + provider=args["provider"], + external_knowledge_api_id=args["external_knowledge_api_id"], + external_knowledge_id=args["external_knowledge_id"], ) except services.errors.dataset.DatasetNameDuplicateError: raise DatasetNameDuplicateError() @@ -211,6 +234,33 @@ class DatasetApi(Resource): ) parser.add_argument("retrieval_model", type=dict, location="json", help="Invalid retrieval model.") parser.add_argument("partial_member_list", type=list, location="json", help="Invalid parent user list.") + + parser.add_argument( + "external_retrieval_model", + type=dict, + required=False, + nullable=True, + location="json", + help="Invalid external retrieval model.", + ) + + parser.add_argument( + "external_knowledge_id", + type=str, + required=False, + nullable=True, + location="json", + help="Invalid external knowledge id.", + ) + + parser.add_argument( + "external_knowledge_api_id", + type=str, + required=False, + nullable=True, + location="json", + help="Invalid external knowledge api id.", + ) args = parser.parse_args() data = request.get_json() diff --git a/api/controllers/console/datasets/external.py b/api/controllers/console/datasets/external.py new file mode 100644 index 0000000000..dcef979360 --- /dev/null +++ b/api/controllers/console/datasets/external.py @@ -0,0 +1,239 @@ +from flask import request +from flask_login import current_user +from flask_restful import Resource, marshal, reqparse +from werkzeug.exceptions import Forbidden, InternalServerError, NotFound + +import services +from controllers.console import api +from controllers.console.datasets.error import DatasetNameDuplicateError +from controllers.console.setup import setup_required +from controllers.console.wraps import account_initialization_required +from fields.dataset_fields import dataset_detail_fields +from libs.login import login_required +from services.dataset_service import DatasetService +from services.external_knowledge_service import ExternalDatasetService +from services.hit_testing_service import HitTestingService + + +def _validate_name(name): + if not name or len(name) < 1 or len(name) > 100: + raise ValueError("Name must be between 1 to 100 characters.") + return name + + +def _validate_description_length(description): + if description and len(description) > 400: + raise ValueError("Description cannot exceed 400 characters.") + return description + + +class ExternalApiTemplateListApi(Resource): + @setup_required + @login_required + @account_initialization_required + def get(self): + page = request.args.get("page", default=1, type=int) + limit = request.args.get("limit", default=20, type=int) + search = request.args.get("keyword", default=None, type=str) + + external_knowledge_apis, total = ExternalDatasetService.get_external_knowledge_apis( + page, limit, current_user.current_tenant_id, search + ) + response = { + "data": [item.to_dict() for item in external_knowledge_apis], + "has_more": len(external_knowledge_apis) == limit, + "limit": limit, + "total": total, + "page": page, + } + return response, 200 + + @setup_required + @login_required + @account_initialization_required + def post(self): + parser = reqparse.RequestParser() + parser.add_argument( + "name", + nullable=False, + required=True, + help="Name is required. Name must be between 1 to 100 characters.", + type=_validate_name, + ) + parser.add_argument( + "settings", + type=dict, + location="json", + nullable=False, + required=True, + ) + args = parser.parse_args() + + ExternalDatasetService.validate_api_list(args["settings"]) + + # The role of the current user in the ta table must be admin, owner, or editor, or dataset_operator + if not current_user.is_dataset_editor: + raise Forbidden() + + try: + external_knowledge_api = ExternalDatasetService.create_external_knowledge_api( + tenant_id=current_user.current_tenant_id, user_id=current_user.id, args=args + ) + except services.errors.dataset.DatasetNameDuplicateError: + raise DatasetNameDuplicateError() + + return external_knowledge_api.to_dict(), 201 + + +class ExternalApiTemplateApi(Resource): + @setup_required + @login_required + @account_initialization_required + def get(self, external_knowledge_api_id): + external_knowledge_api_id = str(external_knowledge_api_id) + external_knowledge_api = ExternalDatasetService.get_external_knowledge_api(external_knowledge_api_id) + if external_knowledge_api is None: + raise NotFound("API template not found.") + + return external_knowledge_api.to_dict(), 200 + + @setup_required + @login_required + @account_initialization_required + def patch(self, external_knowledge_api_id): + external_knowledge_api_id = str(external_knowledge_api_id) + + parser = reqparse.RequestParser() + parser.add_argument( + "name", + nullable=False, + required=True, + help="type is required. Name must be between 1 to 100 characters.", + type=_validate_name, + ) + parser.add_argument( + "settings", + type=dict, + location="json", + nullable=False, + required=True, + ) + args = parser.parse_args() + ExternalDatasetService.validate_api_list(args["settings"]) + + external_knowledge_api = ExternalDatasetService.update_external_knowledge_api( + tenant_id=current_user.current_tenant_id, + user_id=current_user.id, + external_knowledge_api_id=external_knowledge_api_id, + args=args, + ) + + return external_knowledge_api.to_dict(), 200 + + @setup_required + @login_required + @account_initialization_required + def delete(self, external_knowledge_api_id): + external_knowledge_api_id = str(external_knowledge_api_id) + + # The role of the current user in the ta table must be admin, owner, or editor + if not current_user.is_editor or current_user.is_dataset_operator: + raise Forbidden() + + ExternalDatasetService.delete_external_knowledge_api(current_user.current_tenant_id, external_knowledge_api_id) + return {"result": "success"}, 200 + + +class ExternalApiUseCheckApi(Resource): + @setup_required + @login_required + @account_initialization_required + def get(self, external_knowledge_api_id): + external_knowledge_api_id = str(external_knowledge_api_id) + + external_knowledge_api_is_using, count = ExternalDatasetService.external_knowledge_api_use_check( + external_knowledge_api_id + ) + return {"is_using": external_knowledge_api_is_using, "count": count}, 200 + + +class ExternalDatasetCreateApi(Resource): + @setup_required + @login_required + @account_initialization_required + def post(self): + # The role of the current user in the ta table must be admin, owner, or editor + if not current_user.is_editor: + raise Forbidden() + + parser = reqparse.RequestParser() + parser.add_argument("external_knowledge_api_id", type=str, required=True, nullable=False, location="json") + parser.add_argument("external_knowledge_id", type=str, required=True, nullable=False, location="json") + parser.add_argument( + "name", + nullable=False, + required=True, + help="name is required. Name must be between 1 to 100 characters.", + type=_validate_name, + ) + parser.add_argument("description", type=str, required=False, nullable=True, location="json") + parser.add_argument("external_retrieval_model", type=dict, required=False, location="json") + + args = parser.parse_args() + + # The role of the current user in the ta table must be admin, owner, or editor, or dataset_operator + if not current_user.is_dataset_editor: + raise Forbidden() + + try: + dataset = ExternalDatasetService.create_external_dataset( + tenant_id=current_user.current_tenant_id, + user_id=current_user.id, + args=args, + ) + except services.errors.dataset.DatasetNameDuplicateError: + raise DatasetNameDuplicateError() + + return marshal(dataset, dataset_detail_fields), 201 + + +class ExternalKnowledgeHitTestingApi(Resource): + @setup_required + @login_required + @account_initialization_required + def post(self, dataset_id): + dataset_id_str = str(dataset_id) + dataset = DatasetService.get_dataset(dataset_id_str) + if dataset is None: + raise NotFound("Dataset not found.") + + try: + DatasetService.check_dataset_permission(dataset, current_user) + except services.errors.account.NoPermissionError as e: + raise Forbidden(str(e)) + + parser = reqparse.RequestParser() + parser.add_argument("query", type=str, location="json") + parser.add_argument("external_retrieval_model", type=dict, required=False, location="json") + args = parser.parse_args() + + HitTestingService.hit_testing_args_check(args) + + try: + response = HitTestingService.external_retrieve( + dataset=dataset, + query=args["query"], + account=current_user, + external_retrieval_model=args["external_retrieval_model"], + ) + + return response + except Exception as e: + raise InternalServerError(str(e)) + + +api.add_resource(ExternalKnowledgeHitTestingApi, "/datasets//external-hit-testing") +api.add_resource(ExternalDatasetCreateApi, "/datasets/external") +api.add_resource(ExternalApiTemplateListApi, "/datasets/external-knowledge-api") +api.add_resource(ExternalApiTemplateApi, "/datasets/external-knowledge-api/") +api.add_resource(ExternalApiUseCheckApi, "/datasets/external-knowledge-api//use-check") diff --git a/api/controllers/console/datasets/hit_testing.py b/api/controllers/console/datasets/hit_testing.py index 0b4a7be986..6e6d8c0bd7 100644 --- a/api/controllers/console/datasets/hit_testing.py +++ b/api/controllers/console/datasets/hit_testing.py @@ -47,6 +47,7 @@ class HitTestingApi(Resource): parser = reqparse.RequestParser() parser.add_argument("query", type=str, location="json") parser.add_argument("retrieval_model", type=dict, required=False, location="json") + parser.add_argument("external_retrieval_model", type=dict, required=False, location="json") args = parser.parse_args() HitTestingService.hit_testing_args_check(args) @@ -57,6 +58,7 @@ class HitTestingApi(Resource): query=args["query"], account=current_user, retrieval_model=args["retrieval_model"], + external_retrieval_model=args["external_retrieval_model"], limit=10, ) diff --git a/api/controllers/service_api/dataset/dataset.py b/api/controllers/service_api/dataset/dataset.py index c2c0672a03..f076cff6c8 100644 --- a/api/controllers/service_api/dataset/dataset.py +++ b/api/controllers/service_api/dataset/dataset.py @@ -28,11 +28,11 @@ class DatasetListApi(DatasetApiResource): page = request.args.get("page", default=1, type=int) limit = request.args.get("limit", default=20, type=int) - provider = request.args.get("provider", default="vendor") + # provider = request.args.get("provider", default="vendor") search = request.args.get("keyword", default=None, type=str) tag_ids = request.args.getlist("tag_ids") - datasets, total = DatasetService.get_datasets(page, limit, provider, tenant_id, current_user, search, tag_ids) + datasets, total = DatasetService.get_datasets(page, limit, tenant_id, current_user, search, tag_ids) # check embedding setting provider_manager = ProviderManager() configurations = provider_manager.get_configurations(tenant_id=current_user.current_tenant_id) @@ -82,6 +82,26 @@ class DatasetListApi(DatasetApiResource): required=False, nullable=False, ) + parser.add_argument( + "external_knowledge_api_id", + type=str, + nullable=True, + required=False, + default="_validate_name", + ) + parser.add_argument( + "provider", + type=str, + nullable=True, + required=False, + default="vendor", + ) + parser.add_argument( + "external_knowledge_id", + type=str, + nullable=True, + required=False, + ) args = parser.parse_args() try: @@ -91,6 +111,9 @@ class DatasetListApi(DatasetApiResource): indexing_technique=args["indexing_technique"], account=current_user, permission=args["permission"], + provider=args["provider"], + external_knowledge_api_id=args["external_knowledge_api_id"], + external_knowledge_id=args["external_knowledge_id"], ) except services.errors.dataset.DatasetNameDuplicateError: raise DatasetNameDuplicateError() diff --git a/api/core/callback_handler/index_tool_callback_handler.py b/api/core/callback_handler/index_tool_callback_handler.py index 7cf472d984..23dc092895 100644 --- a/api/core/callback_handler/index_tool_callback_handler.py +++ b/api/core/callback_handler/index_tool_callback_handler.py @@ -59,7 +59,7 @@ class DatasetIndexToolCallbackHandler: for item in resource: dataset_retriever_resource = DatasetRetrieverResource( message_id=self._message_id, - position=item.get("position"), + position=item.get("position") or 0, dataset_id=item.get("dataset_id"), dataset_name=item.get("dataset_name"), document_id=item.get("document_id"), diff --git a/api/core/rag/datasource/retrieval_service.py b/api/core/rag/datasource/retrieval_service.py index afac1bf300..d3fd0c672a 100644 --- a/api/core/rag/datasource/retrieval_service.py +++ b/api/core/rag/datasource/retrieval_service.py @@ -10,6 +10,7 @@ from core.rag.rerank.constants.rerank_mode import RerankMode from core.rag.retrieval.retrieval_methods import RetrievalMethod from extensions.ext_database import db from models.dataset import Dataset +from services.external_knowledge_service import ExternalDatasetService default_retrieval_model = { "search_method": RetrievalMethod.SEMANTIC_SEARCH.value, @@ -34,6 +35,9 @@ class RetrievalService: weights: Optional[dict] = None, ): dataset = db.session.query(Dataset).filter(Dataset.id == dataset_id).first() + if not dataset: + return [] + if not dataset or dataset.available_document_count == 0 or dataset.available_segment_count == 0: return [] all_documents = [] @@ -108,6 +112,16 @@ class RetrievalService: ) return all_documents + @classmethod + def external_retrieve(cls, dataset_id: str, query: str, external_retrieval_model: Optional[dict] = None): + dataset = db.session.query(Dataset).filter(Dataset.id == dataset_id).first() + if not dataset: + return [] + all_documents = ExternalDatasetService.fetch_external_knowledge_retrieval( + dataset.tenant_id, dataset_id, query, external_retrieval_model + ) + return all_documents + @classmethod def keyword_search( cls, flask_app: Flask, dataset_id: str, query: str, top_k: int, all_documents: list, exceptions: list diff --git a/api/core/rag/entities/context_entities.py b/api/core/rag/entities/context_entities.py new file mode 100644 index 0000000000..dde3beccf6 --- /dev/null +++ b/api/core/rag/entities/context_entities.py @@ -0,0 +1,10 @@ +from pydantic import BaseModel + + +class DocumentContext(BaseModel): + """ + Model class for document context. + """ + + content: str + score: float diff --git a/api/core/rag/models/document.py b/api/core/rag/models/document.py index 0ff1fdb81c..1e9aaa24f0 100644 --- a/api/core/rag/models/document.py +++ b/api/core/rag/models/document.py @@ -17,6 +17,8 @@ class Document(BaseModel): """ metadata: Optional[dict] = Field(default_factory=dict) + provider: Optional[str] = "dify" + class BaseDocumentTransformer(ABC): """Abstract base class for document transformation systems. diff --git a/api/core/rag/rerank/rerank_model.py b/api/core/rag/rerank/rerank_model.py index 6356ff87ab..27f86aed34 100644 --- a/api/core/rag/rerank/rerank_model.py +++ b/api/core/rag/rerank/rerank_model.py @@ -28,11 +28,16 @@ class RerankModelRunner: docs = [] doc_id = [] unique_documents = [] - for document in documents: + dify_documents = [item for item in documents if item.provider == "dify"] + external_documents = [item for item in documents if item.provider == "external"] + for document in dify_documents: if document.metadata["doc_id"] not in doc_id: doc_id.append(document.metadata["doc_id"]) docs.append(document.page_content) unique_documents.append(document) + for document in external_documents: + docs.append(document.page_content) + unique_documents.append(document) documents = unique_documents @@ -46,14 +51,10 @@ class RerankModelRunner: # format document rerank_document = Document( page_content=result.text, - metadata={ - "doc_id": documents[result.index].metadata["doc_id"], - "doc_hash": documents[result.index].metadata["doc_hash"], - "document_id": documents[result.index].metadata["document_id"], - "dataset_id": documents[result.index].metadata["dataset_id"], - "score": result.score, - }, + metadata=documents[result.index].metadata, + provider=documents[result.index].provider, ) + rerank_document.metadata["score"] = result.score rerank_documents.append(rerank_document) return rerank_documents diff --git a/api/core/rag/retrieval/dataset_retrieval.py b/api/core/rag/retrieval/dataset_retrieval.py index 4603957d68..ae61ba7112 100644 --- a/api/core/rag/retrieval/dataset_retrieval.py +++ b/api/core/rag/retrieval/dataset_retrieval.py @@ -20,6 +20,7 @@ from core.ops.utils import measure_time from core.rag.data_post_processor.data_post_processor import DataPostProcessor from core.rag.datasource.keyword.jieba.jieba_keyword_table_handler import JiebaKeywordTableHandler from core.rag.datasource.retrieval_service import RetrievalService +from core.rag.entities.context_entities import DocumentContext from core.rag.models.document import Document from core.rag.retrieval.retrieval_methods import RetrievalMethod from core.rag.retrieval.router.multi_dataset_function_call_router import FunctionCallMultiDatasetRouter @@ -30,6 +31,7 @@ from core.tools.tool.dataset_retriever.dataset_retriever_tool import DatasetRetr from extensions.ext_database import db from models.dataset import Dataset, DatasetQuery, DocumentSegment from models.dataset import Document as DatasetDocument +from services.external_knowledge_service import ExternalDatasetService default_retrieval_model = { "search_method": RetrievalMethod.SEMANTIC_SEARCH.value, @@ -110,7 +112,7 @@ class DatasetRetrieval: continue # pass if dataset is not available - if dataset and dataset.available_document_count == 0: + if dataset and dataset.available_document_count == 0 and dataset.provider != "external": continue available_datasets.append(dataset) @@ -146,69 +148,93 @@ class DatasetRetrieval: message_id, ) - document_score_list = {} - for item in all_documents: - if item.metadata.get("score"): - document_score_list[item.metadata["doc_id"]] = item.metadata["score"] - + dify_documents = [item for item in all_documents if item.provider == "dify"] + external_documents = [item for item in all_documents if item.provider == "external"] document_context_list = [] - index_node_ids = [document.metadata["doc_id"] for document in all_documents] - segments = DocumentSegment.query.filter( - DocumentSegment.dataset_id.in_(dataset_ids), - DocumentSegment.completed_at.isnot(None), - DocumentSegment.status == "completed", - DocumentSegment.enabled == True, - DocumentSegment.index_node_id.in_(index_node_ids), - ).all() + retrieval_resource_list = [] + # deal with external documents + for item in external_documents: + document_context_list.append(DocumentContext(content=item.page_content, score=item.metadata.get("score"))) + source = { + "dataset_id": item.metadata.get("dataset_id"), + "dataset_name": item.metadata.get("dataset_name"), + "document_name": item.metadata.get("title"), + "data_source_type": "external", + "retriever_from": invoke_from.to_source(), + "score": item.metadata.get("score"), + "content": item.page_content, + } + retrieval_resource_list.append(source) + document_score_list = {} + # deal with dify documents + if dify_documents: + for item in dify_documents: + if item.metadata.get("score"): + document_score_list[item.metadata["doc_id"]] = item.metadata["score"] - if segments: - index_node_id_to_position = {id: position for position, id in enumerate(index_node_ids)} - sorted_segments = sorted( - segments, key=lambda segment: index_node_id_to_position.get(segment.index_node_id, float("inf")) - ) - for segment in sorted_segments: - if segment.answer: - document_context_list.append(f"question:{segment.get_sign_content()} answer:{segment.answer}") - else: - document_context_list.append(segment.get_sign_content()) - if show_retrieve_source: - context_list = [] - resource_number = 1 + index_node_ids = [document.metadata["doc_id"] for document in dify_documents] + segments = DocumentSegment.query.filter( + DocumentSegment.dataset_id.in_(dataset_ids), + DocumentSegment.status == "completed", + DocumentSegment.enabled == True, + DocumentSegment.index_node_id.in_(index_node_ids), + ).all() + + if segments: + index_node_id_to_position = {id: position for position, id in enumerate(index_node_ids)} + sorted_segments = sorted( + segments, key=lambda segment: index_node_id_to_position.get(segment.index_node_id, float("inf")) + ) for segment in sorted_segments: - dataset = Dataset.query.filter_by(id=segment.dataset_id).first() - document = DatasetDocument.query.filter( - DatasetDocument.id == segment.document_id, - DatasetDocument.enabled == True, - DatasetDocument.archived == False, - ).first() - if dataset and document: - source = { - "position": resource_number, - "dataset_id": dataset.id, - "dataset_name": dataset.name, - "document_id": document.id, - "document_name": document.name, - "data_source_type": document.data_source_type, - "segment_id": segment.id, - "retriever_from": invoke_from.to_source(), - "score": document_score_list.get(segment.index_node_id, None), - } + if segment.answer: + document_context_list.append( + DocumentContext( + content=f"question:{segment.get_sign_content()} answer:{segment.answer}", + score=document_score_list.get(segment.index_node_id, None), + ) + ) + else: + document_context_list.append( + DocumentContext( + content=segment.get_sign_content(), + score=document_score_list.get(segment.index_node_id, None), + ) + ) + if show_retrieve_source: + for segment in sorted_segments: + dataset = Dataset.query.filter_by(id=segment.dataset_id).first() + document = DatasetDocument.query.filter( + DatasetDocument.id == segment.document_id, + DatasetDocument.enabled == True, + DatasetDocument.archived == False, + ).first() + if dataset and document: + source = { + "dataset_id": dataset.id, + "dataset_name": dataset.name, + "document_id": document.id, + "document_name": document.name, + "data_source_type": document.data_source_type, + "segment_id": segment.id, + "retriever_from": invoke_from.to_source(), + "score": document_score_list.get(segment.index_node_id, None), + } - if invoke_from.to_source() == "dev": - source["hit_count"] = segment.hit_count - source["word_count"] = segment.word_count - source["segment_position"] = segment.position - source["index_node_hash"] = segment.index_node_hash - if segment.answer: - source["content"] = f"question:{segment.content} \nanswer:{segment.answer}" - else: - source["content"] = segment.content - context_list.append(source) - resource_number += 1 - if hit_callback: - hit_callback.return_retriever_resource_info(context_list) - - return str("\n".join(document_context_list)) + if invoke_from.to_source() == "dev": + source["hit_count"] = segment.hit_count + source["word_count"] = segment.word_count + source["segment_position"] = segment.position + source["index_node_hash"] = segment.index_node_hash + if segment.answer: + source["content"] = f"question:{segment.content} \nanswer:{segment.answer}" + else: + source["content"] = segment.content + retrieval_resource_list.append(source) + if hit_callback and retrieval_resource_list: + hit_callback.return_retriever_resource_info(retrieval_resource_list) + if document_context_list: + document_context_list = sorted(document_context_list, key=lambda x: x.score, reverse=True) + return str("\n".join([document_context.content for document_context in document_context_list])) return "" def single_retrieve( @@ -256,36 +282,58 @@ class DatasetRetrieval: # get retrieval model config dataset = db.session.query(Dataset).filter(Dataset.id == dataset_id).first() if dataset: - retrieval_model_config = dataset.retrieval_model or default_retrieval_model - - # get top k - top_k = retrieval_model_config["top_k"] - # get retrieval method - if dataset.indexing_technique == "economy": - retrieval_method = "keyword_search" - else: - retrieval_method = retrieval_model_config["search_method"] - # get reranking model - reranking_model = ( - retrieval_model_config["reranking_model"] if retrieval_model_config["reranking_enable"] else None - ) - # get score threshold - score_threshold = 0.0 - score_threshold_enabled = retrieval_model_config.get("score_threshold_enabled") - if score_threshold_enabled: - score_threshold = retrieval_model_config.get("score_threshold") - - with measure_time() as timer: - results = RetrievalService.retrieve( - retrieval_method=retrieval_method, - dataset_id=dataset.id, + results = [] + if dataset.provider == "external": + external_documents = ExternalDatasetService.fetch_external_knowledge_retrieval( + tenant_id=dataset.tenant_id, + dataset_id=dataset_id, query=query, - top_k=top_k, - score_threshold=score_threshold, - reranking_model=reranking_model, - reranking_mode=retrieval_model_config.get("reranking_mode", "reranking_model"), - weights=retrieval_model_config.get("weights", None), + external_retrieval_parameters=dataset.retrieval_model, ) + for external_document in external_documents: + document = Document( + page_content=external_document.get("content"), + metadata=external_document.get("metadata"), + provider="external", + ) + document.metadata["score"] = external_document.get("score") + document.metadata["title"] = external_document.get("title") + document.metadata["dataset_id"] = dataset_id + document.metadata["dataset_name"] = dataset.name + results.append(document) + else: + retrieval_model_config = dataset.retrieval_model or default_retrieval_model + + # get top k + top_k = retrieval_model_config["top_k"] + # get retrieval method + if dataset.indexing_technique == "economy": + retrieval_method = "keyword_search" + else: + retrieval_method = retrieval_model_config["search_method"] + # get reranking model + reranking_model = ( + retrieval_model_config["reranking_model"] + if retrieval_model_config["reranking_enable"] + else None + ) + # get score threshold + score_threshold = 0.0 + score_threshold_enabled = retrieval_model_config.get("score_threshold_enabled") + if score_threshold_enabled: + score_threshold = retrieval_model_config.get("score_threshold") + + with measure_time() as timer: + results = RetrievalService.retrieve( + retrieval_method=retrieval_method, + dataset_id=dataset.id, + query=query, + top_k=top_k, + score_threshold=score_threshold, + reranking_model=reranking_model, + reranking_mode=retrieval_model_config.get("reranking_mode", "reranking_model"), + weights=retrieval_model_config.get("weights", None), + ) self._on_query(query, [dataset_id], app_id, user_from, user_id) if results: @@ -356,7 +404,8 @@ class DatasetRetrieval: self, documents: list[Document], message_id: Optional[str] = None, timer: Optional[dict] = None ) -> None: """Handle retrieval end.""" - for document in documents: + dify_documents = [document for document in documents if document.provider == "dify"] + for document in dify_documents: query = db.session.query(DocumentSegment).filter( DocumentSegment.index_node_id == document.metadata["doc_id"] ) @@ -409,35 +458,54 @@ class DatasetRetrieval: if not dataset: return [] - # get retrieval model , if the model is not setting , using default - retrieval_model = dataset.retrieval_model or default_retrieval_model - - if dataset.indexing_technique == "economy": - # use keyword table query - documents = RetrievalService.retrieve( - retrieval_method="keyword_search", dataset_id=dataset.id, query=query, top_k=top_k + if dataset.provider == "external": + external_documents = ExternalDatasetService.fetch_external_knowledge_retrieval( + tenant_id=dataset.tenant_id, + dataset_id=dataset_id, + query=query, + external_retrieval_parameters=dataset.retrieval_model, ) - if documents: - all_documents.extend(documents) - else: - if top_k > 0: - # retrieval source - documents = RetrievalService.retrieve( - retrieval_method=retrieval_model["search_method"], - dataset_id=dataset.id, - query=query, - top_k=retrieval_model.get("top_k") or 2, - score_threshold=retrieval_model.get("score_threshold", 0.0) - if retrieval_model["score_threshold_enabled"] - else 0.0, - reranking_model=retrieval_model.get("reranking_model", None) - if retrieval_model["reranking_enable"] - else None, - reranking_mode=retrieval_model.get("reranking_mode") or "reranking_model", - weights=retrieval_model.get("weights", None), + for external_document in external_documents: + document = Document( + page_content=external_document.get("content"), + metadata=external_document.get("metadata"), + provider="external", ) + document.metadata["score"] = external_document.get("score") + document.metadata["title"] = external_document.get("title") + document.metadata["dataset_id"] = dataset_id + document.metadata["dataset_name"] = dataset.name + all_documents.append(document) + else: + # get retrieval model , if the model is not setting , using default + retrieval_model = dataset.retrieval_model or default_retrieval_model - all_documents.extend(documents) + if dataset.indexing_technique == "economy": + # use keyword table query + documents = RetrievalService.retrieve( + retrieval_method="keyword_search", dataset_id=dataset.id, query=query, top_k=top_k + ) + if documents: + all_documents.extend(documents) + else: + if top_k > 0: + # retrieval source + documents = RetrievalService.retrieve( + retrieval_method=retrieval_model["search_method"], + dataset_id=dataset.id, + query=query, + top_k=retrieval_model.get("top_k") or 2, + score_threshold=retrieval_model.get("score_threshold", 0.0) + if retrieval_model["score_threshold_enabled"] + else 0.0, + reranking_model=retrieval_model.get("reranking_model", None) + if retrieval_model["reranking_enable"] + else None, + reranking_mode=retrieval_model.get("reranking_mode") or "reranking_model", + weights=retrieval_model.get("weights", None), + ) + + all_documents.extend(documents) def to_dataset_retriever_tool( self, diff --git a/api/core/workflow/nodes/knowledge_retrieval/knowledge_retrieval_node.py b/api/core/workflow/nodes/knowledge_retrieval/knowledge_retrieval_node.py index af55688a52..c08dc143a6 100644 --- a/api/core/workflow/nodes/knowledge_retrieval/knowledge_retrieval_node.py +++ b/api/core/workflow/nodes/knowledge_retrieval/knowledge_retrieval_node.py @@ -156,16 +156,34 @@ class KnowledgeRetrievalNode(BaseNode): weights, node_data.multiple_retrieval_config.reranking_enable, ) - - context_list = [] - if all_documents: + dify_documents = [item for item in all_documents if item.provider == "dify"] + external_documents = [item for item in all_documents if item.provider == "external"] + retrieval_resource_list = [] + # deal with external documents + for item in external_documents: + source = { + "metadata": { + "_source": "knowledge", + "dataset_id": item.metadata.get("dataset_id"), + "dataset_name": item.metadata.get("dataset_name"), + "document_name": item.metadata.get("title"), + "data_source_type": "external", + "retriever_from": "workflow", + "score": item.metadata.get("score"), + }, + "title": item.metadata.get("title"), + "content": item.page_content, + } + retrieval_resource_list.append(source) + document_score_list = {} + # deal with dify documents + if dify_documents: document_score_list = {} - page_number_list = {} - for item in all_documents: + for item in dify_documents: if item.metadata.get("score"): document_score_list[item.metadata["doc_id"]] = item.metadata["score"] - index_node_ids = [document.metadata["doc_id"] for document in all_documents] + index_node_ids = [document.metadata["doc_id"] for document in dify_documents] segments = DocumentSegment.query.filter( DocumentSegment.dataset_id.in_(dataset_ids), DocumentSegment.completed_at.isnot(None), @@ -186,13 +204,10 @@ class KnowledgeRetrievalNode(BaseNode): Document.enabled == True, Document.archived == False, ).first() - - resource_number = 1 if dataset and document: source = { "metadata": { "_source": "knowledge", - "position": resource_number, "dataset_id": dataset.id, "dataset_name": dataset.name, "document_id": document.id, @@ -212,9 +227,14 @@ class KnowledgeRetrievalNode(BaseNode): source["content"] = f"question:{segment.get_sign_content()} \nanswer:{segment.answer}" else: source["content"] = segment.get_sign_content() - context_list.append(source) - resource_number += 1 - return context_list + retrieval_resource_list.append(source) + if retrieval_resource_list: + retrieval_resource_list = sorted(retrieval_resource_list, key=lambda x: x.get("score"), reverse=True) + position = 1 + for item in retrieval_resource_list: + item["metadata"]["position"] = position + position += 1 + return retrieval_resource_list @classmethod def _extract_variable_selector_to_variable_mapping( diff --git a/api/fields/dataset_fields.py b/api/fields/dataset_fields.py index 9cf8da7acd..b32423f10c 100644 --- a/api/fields/dataset_fields.py +++ b/api/fields/dataset_fields.py @@ -38,9 +38,20 @@ dataset_retrieval_model_fields = { "score_threshold_enabled": fields.Boolean, "score_threshold": fields.Float, } +external_retrieval_model_fields = { + "top_k": fields.Integer, + "score_threshold": fields.Float, +} tag_fields = {"id": fields.String, "name": fields.String, "type": fields.String} +external_knowledge_info_fields = { + "external_knowledge_id": fields.String, + "external_knowledge_api_id": fields.String, + "external_knowledge_api_name": fields.String, + "external_knowledge_api_endpoint": fields.String, +} + dataset_detail_fields = { "id": fields.String, "name": fields.String, @@ -61,6 +72,8 @@ dataset_detail_fields = { "embedding_available": fields.Boolean, "retrieval_model_dict": fields.Nested(dataset_retrieval_model_fields), "tags": fields.List(fields.Nested(tag_fields)), + "external_knowledge_info": fields.Nested(external_knowledge_info_fields), + "external_retrieval_model": fields.Nested(external_retrieval_model_fields, allow_null=True), } dataset_query_detail_fields = { diff --git a/api/fields/external_dataset_fields.py b/api/fields/external_dataset_fields.py new file mode 100644 index 0000000000..2281460fe2 --- /dev/null +++ b/api/fields/external_dataset_fields.py @@ -0,0 +1,11 @@ +from flask_restful import fields + +from libs.helper import TimestampField + +external_knowledge_api_query_detail_fields = { + "id": fields.String, + "name": fields.String, + "setting": fields.String, + "created_by": fields.String, + "created_at": TimestampField, +} diff --git a/api/migrations/versions/2024_09_24_0922-6af6a521a53e_update_retrieval_resource.py b/api/migrations/versions/2024_09_24_0922-6af6a521a53e_update_retrieval_resource.py new file mode 100644 index 0000000000..5337b340db --- /dev/null +++ b/api/migrations/versions/2024_09_24_0922-6af6a521a53e_update_retrieval_resource.py @@ -0,0 +1,48 @@ +"""update-retrieval-resource + +Revision ID: 6af6a521a53e +Revises: ec3df697ebbb +Create Date: 2024-09-24 09:22:43.570120 + +""" +from alembic import op +import models as models +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '6af6a521a53e' +down_revision = 'd57ba9ebb251' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('dataset_retriever_resources', schema=None) as batch_op: + batch_op.alter_column('document_id', + existing_type=sa.UUID(), + nullable=True) + batch_op.alter_column('data_source_type', + existing_type=sa.TEXT(), + nullable=True) + batch_op.alter_column('segment_id', + existing_type=sa.UUID(), + nullable=True) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('dataset_retriever_resources', schema=None) as batch_op: + batch_op.alter_column('segment_id', + existing_type=sa.UUID(), + nullable=False) + batch_op.alter_column('data_source_type', + existing_type=sa.TEXT(), + nullable=False) + batch_op.alter_column('document_id', + existing_type=sa.UUID(), + nullable=False) + + # ### end Alembic commands ### diff --git a/api/migrations/versions/2024_09_25_0434-33f5fac87f29_external_knowledge_api.py b/api/migrations/versions/2024_09_25_0434-33f5fac87f29_external_knowledge_api.py new file mode 100644 index 0000000000..3cb76e72c1 --- /dev/null +++ b/api/migrations/versions/2024_09_25_0434-33f5fac87f29_external_knowledge_api.py @@ -0,0 +1,73 @@ +"""external_knowledge_api + +Revision ID: 33f5fac87f29 +Revises: 6af6a521a53e +Create Date: 2024-09-25 04:34:57.249436 + +""" +from alembic import op +import models as models +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '33f5fac87f29' +down_revision = '6af6a521a53e' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('external_knowledge_apis', + sa.Column('id', models.types.StringUUID(), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('name', sa.String(length=255), nullable=False), + sa.Column('description', sa.String(length=255), nullable=False), + sa.Column('tenant_id', models.types.StringUUID(), nullable=False), + sa.Column('settings', sa.Text(), nullable=True), + sa.Column('created_by', models.types.StringUUID(), nullable=False), + sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP(0)'), nullable=False), + sa.Column('updated_by', models.types.StringUUID(), nullable=True), + sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP(0)'), nullable=False), + sa.PrimaryKeyConstraint('id', name='external_knowledge_apis_pkey') + ) + with op.batch_alter_table('external_knowledge_apis', schema=None) as batch_op: + batch_op.create_index('external_knowledge_apis_name_idx', ['name'], unique=False) + batch_op.create_index('external_knowledge_apis_tenant_idx', ['tenant_id'], unique=False) + + op.create_table('external_knowledge_bindings', + sa.Column('id', models.types.StringUUID(), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('tenant_id', models.types.StringUUID(), nullable=False), + sa.Column('external_knowledge_api_id', models.types.StringUUID(), nullable=False), + sa.Column('dataset_id', models.types.StringUUID(), nullable=False), + sa.Column('external_knowledge_id', sa.Text(), nullable=False), + sa.Column('created_by', models.types.StringUUID(), nullable=False), + sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP(0)'), nullable=False), + sa.Column('updated_by', models.types.StringUUID(), nullable=True), + sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP(0)'), nullable=False), + sa.PrimaryKeyConstraint('id', name='external_knowledge_bindings_pkey') + ) + with op.batch_alter_table('external_knowledge_bindings', schema=None) as batch_op: + batch_op.create_index('external_knowledge_bindings_dataset_idx', ['dataset_id'], unique=False) + batch_op.create_index('external_knowledge_bindings_external_knowledge_api_idx', ['external_knowledge_api_id'], unique=False) + batch_op.create_index('external_knowledge_bindings_external_knowledge_idx', ['external_knowledge_id'], unique=False) + batch_op.create_index('external_knowledge_bindings_tenant_idx', ['tenant_id'], unique=False) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('external_knowledge_bindings', schema=None) as batch_op: + batch_op.drop_index('external_knowledge_bindings_tenant_idx') + batch_op.drop_index('external_knowledge_bindings_external_knowledge_idx') + batch_op.drop_index('external_knowledge_bindings_external_knowledge_api_idx') + batch_op.drop_index('external_knowledge_bindings_dataset_idx') + + op.drop_table('external_knowledge_bindings') + with op.batch_alter_table('external_knowledge_apis', schema=None) as batch_op: + batch_op.drop_index('external_knowledge_apis_tenant_idx') + batch_op.drop_index('external_knowledge_apis_name_idx') + + op.drop_table('external_knowledge_apis') + # ### end Alembic commands ### diff --git a/api/migrations/versions/fca025d3b60f_add_dataset_retrival_model.py b/api/migrations/versions/fca025d3b60f_add_dataset_retrival_model.py index 1f8250c3eb..52495be60a 100644 --- a/api/migrations/versions/fca025d3b60f_add_dataset_retrival_model.py +++ b/api/migrations/versions/fca025d3b60f_add_dataset_retrival_model.py @@ -1,4 +1,4 @@ -"""add-dataset-retrival-model +"""add-dataset-retrieval-model Revision ID: fca025d3b60f Revises: b3a09c049e8e diff --git a/api/models/dataset.py b/api/models/dataset.py index a2d2a3454d..4224ee5e9c 100644 --- a/api/models/dataset.py +++ b/api/models/dataset.py @@ -38,6 +38,7 @@ class Dataset(db.Model): ) INDEXING_TECHNIQUE_LIST = ["high_quality", "economy", None] + PROVIDER_LIST = ["vendor", "external", None] id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()")) tenant_id = db.Column(StringUUID, nullable=False) @@ -71,6 +72,14 @@ class Dataset(db.Model): def index_struct_dict(self): return json.loads(self.index_struct) if self.index_struct else None + @property + def external_retrieval_model(self): + default_retrieval_model = { + "top_k": 2, + "score_threshold": 0.0, + } + return self.retrieval_model or default_retrieval_model + @property def created_by_account(self): return db.session.get(Account, self.created_by) @@ -162,6 +171,29 @@ class Dataset(db.Model): return tags or [] + @property + def external_knowledge_info(self): + if self.provider != "external": + return None + external_knowledge_binding = ( + db.session.query(ExternalKnowledgeBindings).filter(ExternalKnowledgeBindings.dataset_id == self.id).first() + ) + if not external_knowledge_binding: + return None + external_knowledge_api = ( + db.session.query(ExternalKnowledgeApis) + .filter(ExternalKnowledgeApis.id == external_knowledge_binding.external_knowledge_api_id) + .first() + ) + if not external_knowledge_api: + return None + return { + "external_knowledge_id": external_knowledge_binding.external_knowledge_id, + "external_knowledge_api_id": external_knowledge_api.id, + "external_knowledge_api_name": external_knowledge_api.name, + "external_knowledge_api_endpoint": json.loads(external_knowledge_api.settings).get("endpoint", ""), + } + @staticmethod def gen_collection_name_by_id(dataset_id: str) -> str: normalized_dataset_id = dataset_id.replace("-", "_") @@ -687,3 +719,77 @@ class DatasetPermission(db.Model): tenant_id = db.Column(StringUUID, nullable=False) has_permission = db.Column(db.Boolean, nullable=False, server_default=db.text("true")) created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)")) + + +class ExternalKnowledgeApis(db.Model): + __tablename__ = "external_knowledge_apis" + __table_args__ = ( + db.PrimaryKeyConstraint("id", name="external_knowledge_apis_pkey"), + db.Index("external_knowledge_apis_tenant_idx", "tenant_id"), + db.Index("external_knowledge_apis_name_idx", "name"), + ) + + id = db.Column(StringUUID, nullable=False, server_default=db.text("uuid_generate_v4()")) + name = db.Column(db.String(255), nullable=False) + description = db.Column(db.String(255), nullable=False) + tenant_id = db.Column(StringUUID, nullable=False) + settings = db.Column(db.Text, nullable=True) + created_by = db.Column(StringUUID, nullable=False) + created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)")) + updated_by = db.Column(StringUUID, nullable=True) + updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)")) + + def to_dict(self): + return { + "id": self.id, + "tenant_id": self.tenant_id, + "name": self.name, + "description": self.description, + "settings": self.settings_dict, + "dataset_bindings": self.dataset_bindings, + "created_by": self.created_by, + "created_at": self.created_at.isoformat(), + } + + @property + def settings_dict(self): + try: + return json.loads(self.settings) if self.settings else None + except JSONDecodeError: + return None + + @property + def dataset_bindings(self): + external_knowledge_bindings = ( + db.session.query(ExternalKnowledgeBindings) + .filter(ExternalKnowledgeBindings.external_knowledge_api_id == self.id) + .all() + ) + dataset_ids = [binding.dataset_id for binding in external_knowledge_bindings] + datasets = db.session.query(Dataset).filter(Dataset.id.in_(dataset_ids)).all() + dataset_bindings = [] + for dataset in datasets: + dataset_bindings.append({"id": dataset.id, "name": dataset.name}) + + return dataset_bindings + + +class ExternalKnowledgeBindings(db.Model): + __tablename__ = "external_knowledge_bindings" + __table_args__ = ( + db.PrimaryKeyConstraint("id", name="external_knowledge_bindings_pkey"), + db.Index("external_knowledge_bindings_tenant_idx", "tenant_id"), + db.Index("external_knowledge_bindings_dataset_idx", "dataset_id"), + db.Index("external_knowledge_bindings_external_knowledge_idx", "external_knowledge_id"), + db.Index("external_knowledge_bindings_external_knowledge_api_idx", "external_knowledge_api_id"), + ) + + id = db.Column(StringUUID, nullable=False, server_default=db.text("uuid_generate_v4()")) + tenant_id = db.Column(StringUUID, nullable=False) + external_knowledge_api_id = db.Column(StringUUID, nullable=False) + dataset_id = db.Column(StringUUID, nullable=False) + external_knowledge_id = db.Column(db.Text, nullable=False) + created_by = db.Column(StringUUID, nullable=False) + created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)")) + updated_by = db.Column(StringUUID, nullable=True) + updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP(0)")) diff --git a/api/models/model.py b/api/models/model.py index 53940a5a16..0ac9334321 100644 --- a/api/models/model.py +++ b/api/models/model.py @@ -1423,10 +1423,10 @@ class DatasetRetrieverResource(db.Model): position = db.Column(db.Integer, nullable=False) dataset_id = db.Column(StringUUID, nullable=False) dataset_name = db.Column(db.Text, nullable=False) - document_id = db.Column(StringUUID, nullable=False) + document_id = db.Column(StringUUID, nullable=True) document_name = db.Column(db.Text, nullable=False) - data_source_type = db.Column(db.Text, nullable=False) - segment_id = db.Column(StringUUID, nullable=False) + data_source_type = db.Column(db.Text, nullable=True) + segment_id = db.Column(StringUUID, nullable=True) score = db.Column(db.Float, nullable=True) content = db.Column(db.Text, nullable=False) hit_count = db.Column(db.Integer, nullable=True) diff --git a/api/poetry.lock b/api/poetry.lock index 85c68cd75f..4fb8d54f11 100644 --- a/api/poetry.lock +++ b/api/poetry.lock @@ -2,13 +2,13 @@ [[package]] name = "aiohappyeyeballs" -version = "2.4.0" +version = "2.4.2" description = "Happy Eyeballs for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "aiohappyeyeballs-2.4.0-py3-none-any.whl", hash = "sha256:7ce92076e249169a13c2f49320d1967425eaf1f407522d707d59cac7628d62bd"}, - {file = "aiohappyeyeballs-2.4.0.tar.gz", hash = "sha256:55a1714f084e63d49639800f95716da97a1f173d46a16dfcfda0016abb93b6b2"}, + {file = "aiohappyeyeballs-2.4.2-py3-none-any.whl", hash = "sha256:8522691d9a154ba1145b157d6d5c15e5c692527ce6a53c5e5f9876977f6dab2f"}, + {file = "aiohappyeyeballs-2.4.2.tar.gz", hash = "sha256:4ca893e6c5c1f5bf3888b04cb5a3bee24995398efef6e0b9f747b5e89d84fd74"}, ] [[package]] @@ -153,13 +153,13 @@ frozenlist = ">=1.1.0" [[package]] name = "alembic" -version = "1.13.2" +version = "1.13.3" description = "A database migration tool for SQLAlchemy." optional = false python-versions = ">=3.8" files = [ - {file = "alembic-1.13.2-py3-none-any.whl", hash = "sha256:6b8733129a6224a9a711e17c99b08462dbf7cc9670ba8f2e2ae9af860ceb1953"}, - {file = "alembic-1.13.2.tar.gz", hash = "sha256:1ff0ae32975f4fd96028c39ed9bb3c867fe3af956bd7bb37343b54c9fe7445ef"}, + {file = "alembic-1.13.3-py3-none-any.whl", hash = "sha256:908e905976d15235fae59c9ac42c4c5b75cfcefe3d27c0fbf7ae15a37715d80e"}, + {file = "alembic-1.13.3.tar.gz", hash = "sha256:203503117415561e203aa14541740643a611f641517f0209fcae63e9fa09f1a2"}, ] [package.dependencies] @@ -293,13 +293,13 @@ alibabacloud-tea = "*" [[package]] name = "alibabacloud-tea" -version = "0.3.9" +version = "0.3.10" description = "The tea module of alibabaCloud Python SDK." optional = false python-versions = ">=3.6" files = [ - {file = "alibabacloud-tea-0.3.9.tar.gz", hash = "sha256:a9689770003fa9313d1995812f9fe36a2be315e5cdfc8d58de0d96808219ced9"}, - {file = "alibabacloud_tea-0.3.9-py3-none-any.whl", hash = "sha256:402fd2a92e6729f228d8c0300b182f80019edce19d83afa497aeb15fd7947f9a"}, + {file = "alibabacloud-tea-0.3.10.tar.gz", hash = "sha256:bcf972416af5d8b5e671078c2ec20296dbc792e85e68acd685730a0a016afd2a"}, + {file = "alibabacloud_tea-0.3.10-py3-none-any.whl", hash = "sha256:9136f302a3baea8a1528f500bf5d47c3727b827a09b5c14b283ca53578e30082"}, ] [package.dependencies] @@ -321,17 +321,17 @@ alibabacloud-tea = ">=0.0.1" [[package]] name = "alibabacloud-tea-openapi" -version = "0.3.11" +version = "0.3.12" description = "Alibaba Cloud openapi SDK Library for Python" optional = false python-versions = ">=3.6" files = [ - {file = "alibabacloud_tea_openapi-0.3.11.tar.gz", hash = "sha256:3f5cace1b1aeb8a64587574097403cfd066b86ee4c3c9abde587f9abfcad38de"}, + {file = "alibabacloud_tea_openapi-0.3.12.tar.gz", hash = "sha256:2e14809f357438e62c1ef4976a7655110dd54a75bbfa7d905fa3798355cfd974"}, ] [package.dependencies] -alibabacloud_credentials = ">=0.3.1,<1.0.0" -alibabacloud_gateway_spi = ">=0.0.1,<1.0.0" +alibabacloud_credentials = ">=0.3.5,<1.0.0" +alibabacloud_gateway_spi = ">=0.0.2,<1.0.0" alibabacloud_openapi_util = ">=0.2.1,<1.0.0" alibabacloud_tea_util = ">=0.3.13,<1.0.0" alibabacloud_tea_xml = ">=0.0.2,<1.0.0" @@ -455,13 +455,13 @@ vertex = ["google-auth (>=2,<3)"] [[package]] name = "anyio" -version = "4.4.0" +version = "4.6.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, - {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, + {file = "anyio-4.6.0-py3-none-any.whl", hash = "sha256:c7d2e9d63e31599eeb636c8c5c03a7e108d73b345f064f1c19fdc87b79036a9a"}, + {file = "anyio-4.6.0.tar.gz", hash = "sha256:137b4559cbb034c477165047febb6ff83f390fc3b20bf181c1fc0a728cb8beeb"}, ] [package.dependencies] @@ -471,9 +471,9 @@ sniffio = ">=1.1" typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} [package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (>=0.23)"] +doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.21.0b1)"] +trio = ["trio (>=0.26.1)"] [[package]] name = "arxiv" @@ -698,23 +698,23 @@ msrest = ">=0.6.21" [[package]] name = "azure-storage-file-share" -version = "12.17.0" +version = "12.18.0" description = "Microsoft Azure Azure File Share Storage Client Library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "azure-storage-file-share-12.17.0.tar.gz", hash = "sha256:f7b2c6cfc1b7cb80097a53b1ed2efa9e545b49a291430d369cdb49fafbc841d6"}, - {file = "azure_storage_file_share-12.17.0-py3-none-any.whl", hash = "sha256:c4652759a9d529bf08881bb53275bf38774bb643746b849d27c47118f9cf923d"}, + {file = "azure_storage_file_share-12.18.0-py3-none-any.whl", hash = "sha256:23ca35206a0cb8af0decd9d1363d0ad8ab31584a5e55cfc64528d7192ff748a9"}, + {file = "azure_storage_file_share-12.18.0.tar.gz", hash = "sha256:0a81daee5e13598accde3c73b1aeccc6edfdcec5e957bf40150c0622fb95dc76"}, ] [package.dependencies] -azure-core = ">=1.28.0" +azure-core = ">=1.30.0" cryptography = ">=2.1.4" isodate = ">=0.6.1" typing-extensions = ">=4.6.0" [package.extras] -aio = ["azure-core[aio] (>=1.28.0)"] +aio = ["azure-core[aio] (>=1.30.0)"] [[package]] name = "backoff" @@ -787,13 +787,13 @@ lxml = ["lxml"] [[package]] name = "billiard" -version = "4.2.0" +version = "4.2.1" description = "Python multiprocessing fork with improvements and bugfixes" optional = false python-versions = ">=3.7" files = [ - {file = "billiard-4.2.0-py3-none-any.whl", hash = "sha256:07aa978b308f334ff8282bd4a746e681b3513db5c9a514cbdd810cbbdc19714d"}, - {file = "billiard-4.2.0.tar.gz", hash = "sha256:9a3c3184cb275aa17a732f93f65b20c525d3d9f253722d26a82194803ade5a2c"}, + {file = "billiard-4.2.1-py3-none-any.whl", hash = "sha256:40b59a4ac8806ba2c2369ea98d876bc6108b051c227baffd928c644d15d8f3cb"}, + {file = "billiard-4.2.1.tar.gz", hash = "sha256:12b641b0c539073fc8d3f5b8b7be998956665c4233c7c1fcd66a7e677c4fb36f"}, ] [[package]] @@ -828,13 +828,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.35.19" +version = "1.35.29" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" files = [ - {file = "botocore-1.35.19-py3-none-any.whl", hash = "sha256:c83f7f0cacfe7c19b109b363ebfa8736e570d24922f16ed371681f58ebab44a9"}, - {file = "botocore-1.35.19.tar.gz", hash = "sha256:42d6d8db7250cbd7899f786f9861e02cab17dc238f64d6acb976098ed9809625"}, + {file = "botocore-1.35.29-py3-none-any.whl", hash = "sha256:f8e3ae0d84214eff3fb69cb4dc51cea6c43d3bde82027a94d00c52b941d6c3d5"}, + {file = "botocore-1.35.29.tar.gz", hash = "sha256:4ed28ab03675bb008a290c452c5ddd7aaa5d4e3fa1912aadbdf93057ee84362b"}, ] [package.dependencies] @@ -2077,13 +2077,13 @@ tokenizer = ["tiktoken"] [[package]] name = "dataclass-wizard" -version = "0.22.3" +version = "0.23.0" description = "Marshal dataclasses to/from JSON. Use field properties with initial values. Construct a dataclass schema with JSON input." optional = false python-versions = "*" files = [ - {file = "dataclass-wizard-0.22.3.tar.gz", hash = "sha256:4c46591782265058f1148cfd1f54a3a91221e63986fdd04c9d59f4ced61f4424"}, - {file = "dataclass_wizard-0.22.3-py2.py3-none-any.whl", hash = "sha256:63751203e54b9b9349212cc185331da73c1adc99c51312575eb73bb5c00c1962"}, + {file = "dataclass-wizard-0.23.0.tar.gz", hash = "sha256:da29ec19846d46a1eef0692ba7c59c8a86ecd3a9eaddc0511cfc7485ad6d9c50"}, + {file = "dataclass_wizard-0.23.0-py2.py3-none-any.whl", hash = "sha256:50207dec6d36494421366b49b7a9ba6a4d831e2650c0af25cb4c057103d4a97c"}, ] [package.extras] @@ -2164,13 +2164,13 @@ dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] [[package]] name = "dill" -version = "0.3.8" +version = "0.3.9" description = "serialize all of Python" optional = false python-versions = ">=3.8" files = [ - {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"}, - {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"}, + {file = "dill-0.3.9-py3-none-any.whl", hash = "sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a"}, + {file = "dill-0.3.9.tar.gz", hash = "sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c"}, ] [package.extras] @@ -2241,78 +2241,94 @@ typing_extensions = ">=4.0,<5.0" [[package]] name = "duckdb" -version = "1.1.0" +version = "1.1.1" description = "DuckDB in-process database" optional = false python-versions = ">=3.7.0" files = [ - {file = "duckdb-1.1.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:5e4cbc408e6e41146dea89b9044dae7356e353db0c96b183e5583ee02bc6ae5d"}, - {file = "duckdb-1.1.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:6370ae27ec8167ccfbefb94f58ad9fdc7bac142399960549d6d367f233189868"}, - {file = "duckdb-1.1.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:4e1c3414f7fd01f4810dc8b335deffc91933a159282d65fef11c1286bc0ded04"}, - {file = "duckdb-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6bc2a58689adf5520303c5f68b065b9f980bd31f1366c541b8c7490abaf55cd"}, - {file = "duckdb-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d02be208d2885ca085d4c852b911493b8cdac9d6eae893259da32bd72a437c25"}, - {file = "duckdb-1.1.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:655df442ceebfc6f3fd6c8766e04b60d44dddedfa90275d794f9fab2d3180879"}, - {file = "duckdb-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6e183729bb64be7798ccbfda6283ebf423c869268c25af2b56929e48f763be2f"}, - {file = "duckdb-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:61fb838da51e07ceb0222c4406b059b90e10efcc453c19a3650b73c0112138c4"}, - {file = "duckdb-1.1.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:7807e2f0d3344668e433f0dc1f54bfaddd410589611393e9a7ed56f8dec9514f"}, - {file = "duckdb-1.1.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:3da30b7b466f710d52caa1fdc3ef0bf4176ad7f115953cd9f8b0fbf0f723778f"}, - {file = "duckdb-1.1.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:b9b6a77ef0183f561b1fc2945fcc762a71570ffd33fea4e3a855d413ed596fe4"}, - {file = "duckdb-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16243e66a9fd0e64ee265f2634d137adc6593f54ddf3ef55cb8a29e1decf6e54"}, - {file = "duckdb-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42b910a149e00f40a1766dc74fa309d4255b912a5d2fdcc387287658048650f6"}, - {file = "duckdb-1.1.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:47849d546dc4238c0f20e95fe53b621aa5b08684e68fff91fd84a7092be91a17"}, - {file = "duckdb-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11ec967b67159361ceade34095796a8d19368ea5c30cad988f44896b082b0816"}, - {file = "duckdb-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:510b5885ed6c267b9c0e1e7c6138fdffc2dd6f934a5a95b76da85da127213338"}, - {file = "duckdb-1.1.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:657bc7ac64d5faf069a782ae73afac51ef30ae2e5d0e09ce6a09d03db84ab35e"}, - {file = "duckdb-1.1.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:89f3de8cba57d19b41cd3c47dd06d979bd2a2ffead115480e37afbe72b02896d"}, - {file = "duckdb-1.1.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:f6486323ab20656d22ffa8f3c6e109dde30d0b327b7c831f22ebcfe747f97fb0"}, - {file = "duckdb-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78a4510f82431ee3f14db689fe8727a4a9062c8f2fbb3bcfe3bfad3c1a198004"}, - {file = "duckdb-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64bf2a6e23840d662bd2ac09206a9bd4fa657418884d69e5c352d4456dc70b3c"}, - {file = "duckdb-1.1.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23fc9aa0af74e3803ed90c8d98280fd5bcac8c940592bf6288e8fd60fb051d00"}, - {file = "duckdb-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1f3aea31341ce400640dd522e4399b941f66df17e39884f446638fe958d6117c"}, - {file = "duckdb-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:3db4ab31c20de4edaef152930836b38e7662cd71370748fdf2c38ba9cf854dc4"}, - {file = "duckdb-1.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3b6b4fe1edfe35f64f403a9f0ab75258cee35abd964356893ee37424174b7e4"}, - {file = "duckdb-1.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad02f50d5a2020822d1638fc1a9bcf082056f11d2e15ccfc1c1ed4d0f85a3be"}, - {file = "duckdb-1.1.0-cp37-cp37m-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb66e9e7391801928ea134dcab12d2e4c97f2ce0391c603a3e480bbb15830bc8"}, - {file = "duckdb-1.1.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:069fb7bca459e31edb32a61f0eea95d7a8a766bef7b8318072563abf8e939593"}, - {file = "duckdb-1.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e39f9b7b62e64e10d421ff04480290a70129c38067d1a4f600e9212b10542c5a"}, - {file = "duckdb-1.1.0-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:55ef98bcc7ba745752607f1b926e8d9b7ce32c42c423bbad10c44820aefe23a7"}, - {file = "duckdb-1.1.0-cp38-cp38-macosx_12_0_universal2.whl", hash = "sha256:e2a08175e43b865c1e9611efd18cacd29ddd69093de442b1ebdf312071df7719"}, - {file = "duckdb-1.1.0-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:0e3644b1f034012d82b9baa12a7ea306fe71dc6623731b28c753c4a617ff9499"}, - {file = "duckdb-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:211a33c1ddb5cc609f75eb43772b0b03b45d2fa89bec107e4715267ca907806a"}, - {file = "duckdb-1.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e74b6f8a5145abbf7e6c1a2a61f0adbcd493c19b358f524ec9a3cebdf362abb"}, - {file = "duckdb-1.1.0-cp38-cp38-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:58f1633dd2c5af5088ae2d119418e200855d0699d84f2fae9d46d30f404bcead"}, - {file = "duckdb-1.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d18caea926b1e301c29b140418fca697aad728129e269b4f82c2795a184549e1"}, - {file = "duckdb-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:cd9fb1408942411ad360f8414bc3fbf0091c396ca903d947a10f2e31324d5cbd"}, - {file = "duckdb-1.1.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bd11bc899cebf5ff936d1276a2dfb7b7db08aba3bcc42924afeafc2163bddb43"}, - {file = "duckdb-1.1.0-cp39-cp39-macosx_12_0_universal2.whl", hash = "sha256:53825a63193c582a78c152ea53de8d145744ddbeea18f452625a82ebc33eb14a"}, - {file = "duckdb-1.1.0-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:29dc18087de47563b3859a6b98bbed96e1c96ce5db829646dc3b16a916997e7d"}, - {file = "duckdb-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecb19319883564237a7a03a104dbe7f445e73519bb67108fcab3d19b6b91fe30"}, - {file = "duckdb-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aac2fcabe2d5072c252d0b3087365f431de812d8199705089fb073e4d039d19c"}, - {file = "duckdb-1.1.0-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d89eaaa5df8a57e7d2bc1f4c46493bb1fee319a00155f2015810ad2ace6570ae"}, - {file = "duckdb-1.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d86a6926313913cd2cc7e08816d3e7f72ba340adf2959279b1a80058be6526d9"}, - {file = "duckdb-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:d8333f3e85fa2a0f1c222b752c2bd42ea875235ff88492f7bcbb6867d0f644eb"}, - {file = "duckdb-1.1.0.tar.gz", hash = "sha256:b4d4c12b1f98732151bd31377753e0da1a20f6423016d2d097d2e31953ec7c23"}, + {file = "duckdb-1.1.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:e310610b692d30aa7f1f40d7878b26978a5b191f23fa8fa082bd17092c67c2fd"}, + {file = "duckdb-1.1.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:7acc97c3cc995850a4fa59dfa6ce713d7ea187c9696632161aa09d898f001a2b"}, + {file = "duckdb-1.1.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:c0a09d78daea0de7ddf3d6d1113e80ceed8c15537e93f8efaad53024ffbde245"}, + {file = "duckdb-1.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50c3b1667b0c73cb076b1b1f8fa0fd88fcef5c2bbb2b9acdef79e2eae429c248"}, + {file = "duckdb-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1499a9b159d4675ea46786b7ebdbabd8287c62b6b116ccfd529112318d47184e"}, + {file = "duckdb-1.1.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:876deda2ce97f4a9005a9ac862f0ebee9e5956d51d589a24955802ca91726d49"}, + {file = "duckdb-1.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:40be901b38c709076f699b0c2f42a0c5663a496647eba350530e3a77f46a239b"}, + {file = "duckdb-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:5cb7642c5b21b8165b60029c274fc931c7c29cae3124b9a95ed73d050dd23584"}, + {file = "duckdb-1.1.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:959716b65cf1c94fc117ac9c9692eea0bd64ae53bc8ab6538d459087b474dbeb"}, + {file = "duckdb-1.1.1-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:6ff3c52ce0f8d25478155eb01de043ad0a25badbd10e684a2cd74363f1b86cde"}, + {file = "duckdb-1.1.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:430294cf11ce866d3b726cf4530462316e20b773fed3cf2de3cf63eb89650da6"}, + {file = "duckdb-1.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc9d48f772fafeea52568a0568cd11314cd79a10214069f3700dbcb31ebdf511"}, + {file = "duckdb-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:572095739024d9a5aa2dd8336c289af6a624c203004213e49b7e2469275e940f"}, + {file = "duckdb-1.1.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:660d9baf637b9a15e1ba74bbe02d3b4a20d82e8cbbd7d0712e0d59e3e9d6efea"}, + {file = "duckdb-1.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b91973605c8a30a38c4381a27895e7768cb3caa6700b2534ab76cc6b72cac390"}, + {file = "duckdb-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:f57c9e070cecf42d379145a75f325ec57fb1d410d6ff6592b5a28c2ff2b5792c"}, + {file = "duckdb-1.1.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:926a99b81c50b9a4a43ca26dcb781f934d35e773d22913548396601ab8d44c12"}, + {file = "duckdb-1.1.1-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:55a2632d27b5a965f1d9fc74b03383e80a3f8e3dc9596807dfb02c8db08cfcb7"}, + {file = "duckdb-1.1.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:8d8174fe47caf48d830dc477a45cedc8c970722df09dc1456bddc760ff6ccf68"}, + {file = "duckdb-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ad84023399002222fa8d5264a8dc2083053027910df728da92cabb07494a489"}, + {file = "duckdb-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c8adbc8b37444424c72043288f1521c860555a4f151ee4b744e6125f5d05729"}, + {file = "duckdb-1.1.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:550524c1b423eeb7ca0fdf1c2e6d29e723d7ec7cfab3050b9feb55a620ae927f"}, + {file = "duckdb-1.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4064243e4d3f445975b78773677de0ccbe924f9c7058a7c2cfedb24bba2ba939"}, + {file = "duckdb-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:4f64516dc62dd0fcbb9785c5bc7532a4fca3e6016bbcc92a2b235aa972c631f6"}, + {file = "duckdb-1.1.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:4bf75a64c927470b6618496adcfbf0f316ef09d46a44cfe8e38b78e9ff40c8a0"}, + {file = "duckdb-1.1.1-cp313-cp313-macosx_12_0_universal2.whl", hash = "sha256:5c8cd6fd7107299b9a243836cd8163e4c08d6228f18cbee4ed9f535f53300096"}, + {file = "duckdb-1.1.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:fc81c02b4d73533a438a9bbae19499531d85b752233c905facc4df41bbde043c"}, + {file = "duckdb-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baff4014caf6553b624a296e4db2926602670bd9be6e0fc75f3e970b085631b0"}, + {file = "duckdb-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e21b75a9a60f10b5b5033138c317d929018c92f355fadae5949b310a9179e0a7"}, + {file = "duckdb-1.1.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8220f039c5ea06dc126232464ab9b77197f80ae53d4611b0a41f73c54f6f3931"}, + {file = "duckdb-1.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:07384414ceae585d4106a7dc154331ae42f45390ed675ec81e3d01f2252a6b01"}, + {file = "duckdb-1.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:82776b3999e71a962db0bdc3f0258407ef41453f63eb47c33da29b644f8eb530"}, + {file = "duckdb-1.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35d4323655be4053fb90d47e85222c93fd56aea0e8ab0ac44bd8f7249ba85697"}, + {file = "duckdb-1.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:990d0799e0f543a4369413dc6caf7782cbbab49955c08c28ac56d5dab5ccef11"}, + {file = "duckdb-1.1.1-cp37-cp37m-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5ef3ba36b317abe000f502702eaaefdd8c3651a25aa0ad409f9487b286e2fb28"}, + {file = "duckdb-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2c6e513a572967cd2bab0f20ce265f8eaf95ea7b554eecf1c233717c38569abc"}, + {file = "duckdb-1.1.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:567471cb964a0e54a7874c578e81af7b6ab474676ae6469ae1c33c2353f76fb1"}, + {file = "duckdb-1.1.1-cp38-cp38-macosx_12_0_universal2.whl", hash = "sha256:a41d8eb4dc538d17660b78f2f4ecd0ba29666a396453bb71d6f4972bf2b3959e"}, + {file = "duckdb-1.1.1-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:31be0b9bc1909fb60abda7cd30615fe0224d1e451160d79e8e0313d6205417b0"}, + {file = "duckdb-1.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:541fb49da108e080d4f2984d2fdabaee36d65967a33642f8bce03373b29952f0"}, + {file = "duckdb-1.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1c54f836dac5eddbe369fa654811e979bb07688638a52d1c006172feb5b75a5"}, + {file = "duckdb-1.1.1-cp38-cp38-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:afb97970ee72e554b507c6f2e40b356bdbf8fc1f466e7c4d1797183eb66c0809"}, + {file = "duckdb-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:a2cdcb68247f02017a35a0b617ceb1d36a02a7c0588d7e2ed91c9a4e9f14c3f6"}, + {file = "duckdb-1.1.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:36d71969cb98d10dc2391d8755921258d197995cc8c69e6c82fc377c2f71940a"}, + {file = "duckdb-1.1.1-cp39-cp39-macosx_12_0_universal2.whl", hash = "sha256:3693f464409379a21aff4e35b5f67eb6c96fc402649d9ffddbda4ee9ee9ba9b6"}, + {file = "duckdb-1.1.1-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:06ca7f4ca785cc86e9f9aa23d16b67b82dc454b14c396b2e0ff4c09698c7838e"}, + {file = "duckdb-1.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ed92f3229bf70897a742e7648f648aa8b0c81a7489072aec5515c5635f3303c"}, + {file = "duckdb-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a80ebf52c03f81265b67720abc06a5c7770d08df82b30cabbe266012bd526229"}, + {file = "duckdb-1.1.1-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:402a42b992227ebb371a48681ce71b6d1c0661385454b269e6aa379f77a8a83a"}, + {file = "duckdb-1.1.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a182d3cbf2e352aaddf392887331bbac460c473cbd55c65d6b6121ef7b43f174"}, + {file = "duckdb-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:fafc7d1ec4401787597a5f983d4ef8a9b0638f31e1674a458c57383911166f27"}, + {file = "duckdb-1.1.1.tar.gz", hash = "sha256:74fb07c1334a73e0ead1b0a03646d349921dac655762d916c8e45194c8218d30"}, ] [[package]] name = "duckduckgo-search" -version = "6.2.12" +version = "6.2.13" description = "Search for words, documents, images, news, maps and text translation using the DuckDuckGo.com search engine." optional = false python-versions = ">=3.8" files = [ - {file = "duckduckgo_search-6.2.12-py3-none-any.whl", hash = "sha256:0d379c1f845b632a41553efb13d571788f19ad289229e641a27b5710d92097a6"}, - {file = "duckduckgo_search-6.2.12.tar.gz", hash = "sha256:04f9f1459763668d268344c7a32d943173d0e060dad53a5c2df4b4d3ca9a74cf"}, + {file = "duckduckgo_search-6.2.13-py3-none-any.whl", hash = "sha256:a6618fb2744fa1d081b1bf2e47ef8051de993276a15c20f4e879a150726472de"}, + {file = "duckduckgo_search-6.2.13.tar.gz", hash = "sha256:f89a9782f0f47d18c01a761c83453d0aef7a4335d1b6466fc47709652d5ca791"}, ] [package.dependencies] click = ">=8.1.7" -primp = ">=0.6.2" +primp = ">=0.6.3" [package.extras] dev = ["mypy (>=1.11.1)", "pytest (>=8.3.1)", "pytest-asyncio (>=0.23.8)", "ruff (>=0.6.1)"] lxml = ["lxml (>=5.2.2)"] +[[package]] +name = "durationpy" +version = "0.7" +description = "Module for converting between datetime.timedelta and Go's Duration strings." +optional = false +python-versions = "*" +files = [ + {file = "durationpy-0.7.tar.gz", hash = "sha256:8447c43df4f1a0b434e70c15a38d77f5c9bd17284bfc1ff1d430f233d5083732"}, +] + [[package]] name = "elastic-transport" version = "8.15.0" @@ -2356,18 +2372,15 @@ vectorstore-mmr = ["numpy (>=1)", "simsimd (>=3)"] [[package]] name = "emoji" -version = "2.12.1" +version = "2.13.2" description = "Emoji for Python" optional = false python-versions = ">=3.7" files = [ - {file = "emoji-2.12.1-py3-none-any.whl", hash = "sha256:a00d62173bdadc2510967a381810101624a2f0986145b8da0cffa42e29430235"}, - {file = "emoji-2.12.1.tar.gz", hash = "sha256:4aa0488817691aa58d83764b6c209f8a27c0b3ab3f89d1b8dceca1a62e4973eb"}, + {file = "emoji-2.13.2-py3-none-any.whl", hash = "sha256:ef6f2ee63b245e934c763b1a9a0637713955aa3d9e322432e036bb60559de4d6"}, + {file = "emoji-2.13.2.tar.gz", hash = "sha256:f95d10d96c5f21299ed2c4b32511611ba890b8c07f5f2bf5b04d5d3eee91fd19"}, ] -[package.dependencies] -typing-extensions = ">=4.7.0" - [package.extras] dev = ["coverage", "pytest (>=7.4.4)"] @@ -2432,13 +2445,13 @@ test = ["pytest (>=6)"] [[package]] name = "fastapi" -version = "0.114.2" +version = "0.115.0" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi-0.114.2-py3-none-any.whl", hash = "sha256:44474a22913057b1acb973ab90f4b671ba5200482e7622816d79105dcece1ac5"}, - {file = "fastapi-0.114.2.tar.gz", hash = "sha256:0adb148b62edb09e8c6eeefa3ea934e8f276dabc038c5a82989ea6346050c3da"}, + {file = "fastapi-0.115.0-py3-none-any.whl", hash = "sha256:17ea427674467486e997206a5ab25760f6b09e069f099b96f5b55a32fb6f1631"}, + {file = "fastapi-0.115.0.tar.gz", hash = "sha256:f93b4ca3529a8ebc6fc3fcf710e5efa8de3df9b41570958abf1d97d843138004"}, ] [package.dependencies] @@ -2527,18 +2540,18 @@ sgmllib3k = "*" [[package]] name = "filelock" -version = "3.16.0" +version = "3.16.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.16.0-py3-none-any.whl", hash = "sha256:f6ed4c963184f4c84dd5557ce8fece759a3724b37b80c6c4f20a2f63a4dc6609"}, - {file = "filelock-3.16.0.tar.gz", hash = "sha256:81de9eb8453c769b63369f87f11131a7ab04e367f8d97ad39dc230daa07e3bec"}, + {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, + {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, ] [package.extras] -docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.1.1)", "pytest (>=8.3.2)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.3)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] typing = ["typing-extensions (>=4.12.2)"] [[package]] @@ -2701,53 +2714,59 @@ files = [ [[package]] name = "fonttools" -version = "4.53.1" +version = "4.54.1" description = "Tools to manipulate font files" optional = false python-versions = ">=3.8" files = [ - {file = "fonttools-4.53.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0679a30b59d74b6242909945429dbddb08496935b82f91ea9bf6ad240ec23397"}, - {file = "fonttools-4.53.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8bf06b94694251861ba7fdeea15c8ec0967f84c3d4143ae9daf42bbc7717fe3"}, - {file = "fonttools-4.53.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b96cd370a61f4d083c9c0053bf634279b094308d52fdc2dd9a22d8372fdd590d"}, - {file = "fonttools-4.53.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1c7c5aa18dd3b17995898b4a9b5929d69ef6ae2af5b96d585ff4005033d82f0"}, - {file = "fonttools-4.53.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e013aae589c1c12505da64a7d8d023e584987e51e62006e1bb30d72f26522c41"}, - {file = "fonttools-4.53.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9efd176f874cb6402e607e4cc9b4a9cd584d82fc34a4b0c811970b32ba62501f"}, - {file = "fonttools-4.53.1-cp310-cp310-win32.whl", hash = "sha256:c8696544c964500aa9439efb6761947393b70b17ef4e82d73277413f291260a4"}, - {file = "fonttools-4.53.1-cp310-cp310-win_amd64.whl", hash = "sha256:8959a59de5af6d2bec27489e98ef25a397cfa1774b375d5787509c06659b3671"}, - {file = "fonttools-4.53.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1"}, - {file = "fonttools-4.53.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923"}, - {file = "fonttools-4.53.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719"}, - {file = "fonttools-4.53.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3"}, - {file = "fonttools-4.53.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6e08f572625a1ee682115223eabebc4c6a2035a6917eac6f60350aba297ccadb"}, - {file = "fonttools-4.53.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b21952c092ffd827504de7e66b62aba26fdb5f9d1e435c52477e6486e9d128b2"}, - {file = "fonttools-4.53.1-cp311-cp311-win32.whl", hash = "sha256:9dfdae43b7996af46ff9da520998a32b105c7f098aeea06b2226b30e74fbba88"}, - {file = "fonttools-4.53.1-cp311-cp311-win_amd64.whl", hash = "sha256:d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02"}, - {file = "fonttools-4.53.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d92d3c2a1b39631a6131c2fa25b5406855f97969b068e7e08413325bc0afba58"}, - {file = "fonttools-4.53.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3b3c8ebafbee8d9002bd8f1195d09ed2bd9ff134ddec37ee8f6a6375e6a4f0e8"}, - {file = "fonttools-4.53.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32f029c095ad66c425b0ee85553d0dc326d45d7059dbc227330fc29b43e8ba60"}, - {file = "fonttools-4.53.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f5e6c3510b79ea27bb1ebfcc67048cde9ec67afa87c7dd7efa5c700491ac7f"}, - {file = "fonttools-4.53.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f677ce218976496a587ab17140da141557beb91d2a5c1a14212c994093f2eae2"}, - {file = "fonttools-4.53.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9e6ceba2a01b448e36754983d376064730690401da1dd104ddb543519470a15f"}, - {file = "fonttools-4.53.1-cp312-cp312-win32.whl", hash = "sha256:791b31ebbc05197d7aa096bbc7bd76d591f05905d2fd908bf103af4488e60670"}, - {file = "fonttools-4.53.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ed170b5e17da0264b9f6fae86073be3db15fa1bd74061c8331022bca6d09bab"}, - {file = "fonttools-4.53.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c818c058404eb2bba05e728d38049438afd649e3c409796723dfc17cd3f08749"}, - {file = "fonttools-4.53.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:651390c3b26b0c7d1f4407cad281ee7a5a85a31a110cbac5269de72a51551ba2"}, - {file = "fonttools-4.53.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e54f1bba2f655924c1138bbc7fa91abd61f45c68bd65ab5ed985942712864bbb"}, - {file = "fonttools-4.53.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9cd19cf4fe0595ebdd1d4915882b9440c3a6d30b008f3cc7587c1da7b95be5f"}, - {file = "fonttools-4.53.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2af40ae9cdcb204fc1d8f26b190aa16534fcd4f0df756268df674a270eab575d"}, - {file = "fonttools-4.53.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:35250099b0cfb32d799fb5d6c651220a642fe2e3c7d2560490e6f1d3f9ae9169"}, - {file = "fonttools-4.53.1-cp38-cp38-win32.whl", hash = "sha256:f08df60fbd8d289152079a65da4e66a447efc1d5d5a4d3f299cdd39e3b2e4a7d"}, - {file = "fonttools-4.53.1-cp38-cp38-win_amd64.whl", hash = "sha256:7b6b35e52ddc8fb0db562133894e6ef5b4e54e1283dff606fda3eed938c36fc8"}, - {file = "fonttools-4.53.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75a157d8d26c06e64ace9df037ee93a4938a4606a38cb7ffaf6635e60e253b7a"}, - {file = "fonttools-4.53.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4824c198f714ab5559c5be10fd1adf876712aa7989882a4ec887bf1ef3e00e31"}, - {file = "fonttools-4.53.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:becc5d7cb89c7b7afa8321b6bb3dbee0eec2b57855c90b3e9bf5fb816671fa7c"}, - {file = "fonttools-4.53.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84ec3fb43befb54be490147b4a922b5314e16372a643004f182babee9f9c3407"}, - {file = "fonttools-4.53.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:73379d3ffdeecb376640cd8ed03e9d2d0e568c9d1a4e9b16504a834ebadc2dfb"}, - {file = "fonttools-4.53.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:02569e9a810f9d11f4ae82c391ebc6fb5730d95a0657d24d754ed7763fb2d122"}, - {file = "fonttools-4.53.1-cp39-cp39-win32.whl", hash = "sha256:aae7bd54187e8bf7fd69f8ab87b2885253d3575163ad4d669a262fe97f0136cb"}, - {file = "fonttools-4.53.1-cp39-cp39-win_amd64.whl", hash = "sha256:e5b708073ea3d684235648786f5f6153a48dc8762cdfe5563c57e80787c29fbb"}, - {file = "fonttools-4.53.1-py3-none-any.whl", hash = "sha256:f1f8758a2ad110bd6432203a344269f445a2907dc24ef6bccfd0ac4e14e0d71d"}, - {file = "fonttools-4.53.1.tar.gz", hash = "sha256:e128778a8e9bc11159ce5447f76766cefbd876f44bd79aff030287254e4752c4"}, + {file = "fonttools-4.54.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ed7ee041ff7b34cc62f07545e55e1468808691dddfd315d51dd82a6b37ddef2"}, + {file = "fonttools-4.54.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41bb0b250c8132b2fcac148e2e9198e62ff06f3cc472065dff839327945c5882"}, + {file = "fonttools-4.54.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7965af9b67dd546e52afcf2e38641b5be956d68c425bef2158e95af11d229f10"}, + {file = "fonttools-4.54.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:278913a168f90d53378c20c23b80f4e599dca62fbffae4cc620c8eed476b723e"}, + {file = "fonttools-4.54.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0e88e3018ac809b9662615072dcd6b84dca4c2d991c6d66e1970a112503bba7e"}, + {file = "fonttools-4.54.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4aa4817f0031206e637d1e685251ac61be64d1adef111060df84fdcbc6ab6c44"}, + {file = "fonttools-4.54.1-cp310-cp310-win32.whl", hash = "sha256:7e3b7d44e18c085fd8c16dcc6f1ad6c61b71ff463636fcb13df7b1b818bd0c02"}, + {file = "fonttools-4.54.1-cp310-cp310-win_amd64.whl", hash = "sha256:dd9cc95b8d6e27d01e1e1f1fae8559ef3c02c76317da650a19047f249acd519d"}, + {file = "fonttools-4.54.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5419771b64248484299fa77689d4f3aeed643ea6630b2ea750eeab219588ba20"}, + {file = "fonttools-4.54.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:301540e89cf4ce89d462eb23a89464fef50915255ece765d10eee8b2bf9d75b2"}, + {file = "fonttools-4.54.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ae5091547e74e7efecc3cbf8e75200bc92daaeb88e5433c5e3e95ea8ce5aa7"}, + {file = "fonttools-4.54.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82834962b3d7c5ca98cb56001c33cf20eb110ecf442725dc5fdf36d16ed1ab07"}, + {file = "fonttools-4.54.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d26732ae002cc3d2ecab04897bb02ae3f11f06dd7575d1df46acd2f7c012a8d8"}, + {file = "fonttools-4.54.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:58974b4987b2a71ee08ade1e7f47f410c367cdfc5a94fabd599c88165f56213a"}, + {file = "fonttools-4.54.1-cp311-cp311-win32.whl", hash = "sha256:ab774fa225238986218a463f3fe151e04d8c25d7de09df7f0f5fce27b1243dbc"}, + {file = "fonttools-4.54.1-cp311-cp311-win_amd64.whl", hash = "sha256:07e005dc454eee1cc60105d6a29593459a06321c21897f769a281ff2d08939f6"}, + {file = "fonttools-4.54.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:54471032f7cb5fca694b5f1a0aaeba4af6e10ae989df408e0216f7fd6cdc405d"}, + {file = "fonttools-4.54.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fa92cb248e573daab8d032919623cc309c005086d743afb014c836636166f08"}, + {file = "fonttools-4.54.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a911591200114969befa7f2cb74ac148bce5a91df5645443371aba6d222e263"}, + {file = "fonttools-4.54.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93d458c8a6a354dc8b48fc78d66d2a8a90b941f7fec30e94c7ad9982b1fa6bab"}, + {file = "fonttools-4.54.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5eb2474a7c5be8a5331146758debb2669bf5635c021aee00fd7c353558fc659d"}, + {file = "fonttools-4.54.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9c563351ddc230725c4bdf7d9e1e92cbe6ae8553942bd1fb2b2ff0884e8b714"}, + {file = "fonttools-4.54.1-cp312-cp312-win32.whl", hash = "sha256:fdb062893fd6d47b527d39346e0c5578b7957dcea6d6a3b6794569370013d9ac"}, + {file = "fonttools-4.54.1-cp312-cp312-win_amd64.whl", hash = "sha256:e4564cf40cebcb53f3dc825e85910bf54835e8a8b6880d59e5159f0f325e637e"}, + {file = "fonttools-4.54.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6e37561751b017cf5c40fce0d90fd9e8274716de327ec4ffb0df957160be3bff"}, + {file = "fonttools-4.54.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:357cacb988a18aace66e5e55fe1247f2ee706e01debc4b1a20d77400354cddeb"}, + {file = "fonttools-4.54.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e953cc0bddc2beaf3a3c3b5dd9ab7554677da72dfaf46951e193c9653e515a"}, + {file = "fonttools-4.54.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:58d29b9a294573d8319f16f2f79e42428ba9b6480442fa1836e4eb89c4d9d61c"}, + {file = "fonttools-4.54.1-cp313-cp313-win32.whl", hash = "sha256:9ef1b167e22709b46bf8168368b7b5d3efeaaa746c6d39661c1b4405b6352e58"}, + {file = "fonttools-4.54.1-cp313-cp313-win_amd64.whl", hash = "sha256:262705b1663f18c04250bd1242b0515d3bbae177bee7752be67c979b7d47f43d"}, + {file = "fonttools-4.54.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ed2f80ca07025551636c555dec2b755dd005e2ea8fbeb99fc5cdff319b70b23b"}, + {file = "fonttools-4.54.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9dc080e5a1c3b2656caff2ac2633d009b3a9ff7b5e93d0452f40cd76d3da3b3c"}, + {file = "fonttools-4.54.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d152d1be65652fc65e695e5619e0aa0982295a95a9b29b52b85775243c06556"}, + {file = "fonttools-4.54.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8583e563df41fdecef31b793b4dd3af8a9caa03397be648945ad32717a92885b"}, + {file = "fonttools-4.54.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0d1d353ef198c422515a3e974a1e8d5b304cd54a4c2eebcae708e37cd9eeffb1"}, + {file = "fonttools-4.54.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:fda582236fee135d4daeca056c8c88ec5f6f6d88a004a79b84a02547c8f57386"}, + {file = "fonttools-4.54.1-cp38-cp38-win32.whl", hash = "sha256:e7d82b9e56716ed32574ee106cabca80992e6bbdcf25a88d97d21f73a0aae664"}, + {file = "fonttools-4.54.1-cp38-cp38-win_amd64.whl", hash = "sha256:ada215fd079e23e060157aab12eba0d66704316547f334eee9ff26f8c0d7b8ab"}, + {file = "fonttools-4.54.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f5b8a096e649768c2f4233f947cf9737f8dbf8728b90e2771e2497c6e3d21d13"}, + {file = "fonttools-4.54.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e10d2e0a12e18f4e2dd031e1bf7c3d7017be5c8dbe524d07706179f355c5dac"}, + {file = "fonttools-4.54.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31c32d7d4b0958600eac75eaf524b7b7cb68d3a8c196635252b7a2c30d80e986"}, + {file = "fonttools-4.54.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c39287f5c8f4a0c5a55daf9eaf9ccd223ea59eed3f6d467133cc727d7b943a55"}, + {file = "fonttools-4.54.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a7a310c6e0471602fe3bf8efaf193d396ea561486aeaa7adc1f132e02d30c4b9"}, + {file = "fonttools-4.54.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d3b659d1029946f4ff9b6183984578041b520ce0f8fb7078bb37ec7445806b33"}, + {file = "fonttools-4.54.1-cp39-cp39-win32.whl", hash = "sha256:e96bc94c8cda58f577277d4a71f51c8e2129b8b36fd05adece6320dd3d57de8a"}, + {file = "fonttools-4.54.1-cp39-cp39-win_amd64.whl", hash = "sha256:e8a4b261c1ef91e7188a30571be6ad98d1c6d9fa2427244c545e2fa0a2494dd7"}, + {file = "fonttools-4.54.1-py3-none-any.whl", hash = "sha256:37cddd62d83dc4f72f7c3f3c2bcf2697e89a30efb152079896544a93907733bd"}, + {file = "fonttools-4.54.1.tar.gz", hash = "sha256:957f669d4922f92c171ba01bef7f29410668db09f6c02111e22b2bce446f3285"}, ] [package.extras] @@ -3211,30 +3230,30 @@ xai = ["tensorflow (>=2.3.0,<3.0.0dev)"] [[package]] name = "google-cloud-bigquery" -version = "3.25.0" +version = "3.26.0" description = "Google BigQuery API client library" optional = false python-versions = ">=3.7" files = [ - {file = "google-cloud-bigquery-3.25.0.tar.gz", hash = "sha256:5b2aff3205a854481117436836ae1403f11f2594e6810a98886afd57eda28509"}, - {file = "google_cloud_bigquery-3.25.0-py2.py3-none-any.whl", hash = "sha256:7f0c371bc74d2a7fb74dacbc00ac0f90c8c2bec2289b51dd6685a275873b1ce9"}, + {file = "google_cloud_bigquery-3.26.0-py2.py3-none-any.whl", hash = "sha256:e0e9ad28afa67a18696e624cbccab284bf2c0a3f6eeb9eeb0426c69b943793a8"}, + {file = "google_cloud_bigquery-3.26.0.tar.gz", hash = "sha256:edbdc788beea659e04c0af7fe4dcd6d9155344b98951a0d5055bd2f15da4ba23"}, ] [package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} +google-api-core = {version = ">=2.11.1,<3.0.0dev", extras = ["grpc"]} google-auth = ">=2.14.1,<3.0.0dev" -google-cloud-core = ">=1.6.0,<3.0.0dev" -google-resumable-media = ">=0.6.0,<3.0dev" +google-cloud-core = ">=2.4.1,<3.0.0dev" +google-resumable-media = ">=2.0.0,<3.0dev" packaging = ">=20.0.0" -python-dateutil = ">=2.7.2,<3.0dev" +python-dateutil = ">=2.7.3,<3.0dev" requests = ">=2.21.0,<3.0.0dev" [package.extras] -all = ["Shapely (>=1.8.4,<3.0.0dev)", "db-dtypes (>=0.3.0,<2.0.0dev)", "geopandas (>=0.9.0,<1.0dev)", "google-cloud-bigquery-storage (>=2.6.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "importlib-metadata (>=1.0.0)", "ipykernel (>=6.0.0)", "ipython (>=7.23.1,!=8.1.0)", "ipywidgets (>=7.7.0)", "opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)", "pandas (>=1.1.0)", "proto-plus (>=1.15.0,<2.0.0dev)", "protobuf (>=3.19.5,!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0dev)", "pyarrow (>=3.0.0)", "tqdm (>=4.7.4,<5.0.0dev)"] -bigquery-v2 = ["proto-plus (>=1.15.0,<2.0.0dev)", "protobuf (>=3.19.5,!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0dev)"] +all = ["Shapely (>=1.8.4,<3.0.0dev)", "bigquery-magics (>=0.1.0)", "db-dtypes (>=0.3.0,<2.0.0dev)", "geopandas (>=0.9.0,<1.0dev)", "google-cloud-bigquery-storage (>=2.6.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "importlib-metadata (>=1.0.0)", "ipykernel (>=6.0.0)", "ipywidgets (>=7.7.0)", "opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)", "pandas (>=1.1.0)", "proto-plus (>=1.22.3,<2.0.0dev)", "protobuf (>=3.20.2,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0dev)", "pyarrow (>=3.0.0)", "tqdm (>=4.7.4,<5.0.0dev)"] +bigquery-v2 = ["proto-plus (>=1.22.3,<2.0.0dev)", "protobuf (>=3.20.2,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0dev)"] bqstorage = ["google-cloud-bigquery-storage (>=2.6.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "pyarrow (>=3.0.0)"] geopandas = ["Shapely (>=1.8.4,<3.0.0dev)", "geopandas (>=0.9.0,<1.0dev)"] -ipython = ["ipykernel (>=6.0.0)", "ipython (>=7.23.1,!=8.1.0)"] +ipython = ["bigquery-magics (>=0.1.0)"] ipywidgets = ["ipykernel (>=6.0.0)", "ipywidgets (>=7.7.0)"] opentelemetry = ["opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)"] pandas = ["db-dtypes (>=0.3.0,<2.0.0dev)", "importlib-metadata (>=1.0.0)", "pandas (>=1.1.0)", "pyarrow (>=3.0.0)"] @@ -3413,77 +3432,84 @@ grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] [[package]] name = "greenlet" -version = "3.1.0" +version = "3.1.1" description = "Lightweight in-process concurrent programming" optional = false python-versions = ">=3.7" files = [ - {file = "greenlet-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a814dc3100e8a046ff48faeaa909e80cdb358411a3d6dd5293158425c684eda8"}, - {file = "greenlet-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a771dc64fa44ebe58d65768d869fcfb9060169d203446c1d446e844b62bdfdca"}, - {file = "greenlet-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0e49a65d25d7350cca2da15aac31b6f67a43d867448babf997fe83c7505f57bc"}, - {file = "greenlet-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2cd8518eade968bc52262d8c46727cfc0826ff4d552cf0430b8d65aaf50bb91d"}, - {file = "greenlet-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76dc19e660baea5c38e949455c1181bc018893f25372d10ffe24b3ed7341fb25"}, - {file = "greenlet-3.1.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c0a5b1c22c82831f56f2f7ad9bbe4948879762fe0d59833a4a71f16e5fa0f682"}, - {file = "greenlet-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2651dfb006f391bcb240635079a68a261b227a10a08af6349cba834a2141efa1"}, - {file = "greenlet-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3e7e6ef1737a819819b1163116ad4b48d06cfdd40352d813bb14436024fcda99"}, - {file = "greenlet-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:ffb08f2a1e59d38c7b8b9ac8083c9c8b9875f0955b1e9b9b9a965607a51f8e54"}, - {file = "greenlet-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9730929375021ec90f6447bff4f7f5508faef1c02f399a1953870cdb78e0c345"}, - {file = "greenlet-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:713d450cf8e61854de9420fb7eea8ad228df4e27e7d4ed465de98c955d2b3fa6"}, - {file = "greenlet-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c3446937be153718250fe421da548f973124189f18fe4575a0510b5c928f0cc"}, - {file = "greenlet-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ddc7bcedeb47187be74208bc652d63d6b20cb24f4e596bd356092d8000da6d6"}, - {file = "greenlet-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44151d7b81b9391ed759a2f2865bbe623ef00d648fed59363be2bbbd5154656f"}, - {file = "greenlet-3.1.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cea1cca3be76c9483282dc7760ea1cc08a6ecec1f0b6ca0a94ea0d17432da19"}, - {file = "greenlet-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:619935a44f414274a2c08c9e74611965650b730eb4efe4b2270f91df5e4adf9a"}, - {file = "greenlet-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:221169d31cada333a0c7fd087b957c8f431c1dba202c3a58cf5a3583ed973e9b"}, - {file = "greenlet-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:01059afb9b178606b4b6e92c3e710ea1635597c3537e44da69f4531e111dd5e9"}, - {file = "greenlet-3.1.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:24fc216ec7c8be9becba8b64a98a78f9cd057fd2dc75ae952ca94ed8a893bf27"}, - {file = "greenlet-3.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d07c28b85b350564bdff9f51c1c5007dfb2f389385d1bc23288de51134ca303"}, - {file = "greenlet-3.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:243a223c96a4246f8a30ea470c440fe9db1f5e444941ee3c3cd79df119b8eebf"}, - {file = "greenlet-3.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26811df4dc81271033a7836bc20d12cd30938e6bd2e9437f56fa03da81b0f8fc"}, - {file = "greenlet-3.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9d86401550b09a55410f32ceb5fe7efcd998bd2dad9e82521713cb148a4a15f"}, - {file = "greenlet-3.1.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:26d9c1c4f1748ccac0bae1dbb465fb1a795a75aba8af8ca871503019f4285e2a"}, - {file = "greenlet-3.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:cd468ec62257bb4544989402b19d795d2305eccb06cde5da0eb739b63dc04665"}, - {file = "greenlet-3.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a53dfe8f82b715319e9953330fa5c8708b610d48b5c59f1316337302af5c0811"}, - {file = "greenlet-3.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:28fe80a3eb673b2d5cc3b12eea468a5e5f4603c26aa34d88bf61bba82ceb2f9b"}, - {file = "greenlet-3.1.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:76b3e3976d2a452cba7aa9e453498ac72240d43030fdc6d538a72b87eaff52fd"}, - {file = "greenlet-3.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:655b21ffd37a96b1e78cc48bf254f5ea4b5b85efaf9e9e2a526b3c9309d660ca"}, - {file = "greenlet-3.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6f4c2027689093775fd58ca2388d58789009116844432d920e9147f91acbe64"}, - {file = "greenlet-3.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:76e5064fd8e94c3f74d9fd69b02d99e3cdb8fc286ed49a1f10b256e59d0d3a0b"}, - {file = "greenlet-3.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a4bf607f690f7987ab3291406e012cd8591a4f77aa54f29b890f9c331e84989"}, - {file = "greenlet-3.1.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:037d9ac99540ace9424cb9ea89f0accfaff4316f149520b4ae293eebc5bded17"}, - {file = "greenlet-3.1.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:90b5bbf05fe3d3ef697103850c2ce3374558f6fe40fd57c9fac1bf14903f50a5"}, - {file = "greenlet-3.1.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:726377bd60081172685c0ff46afbc600d064f01053190e4450857483c4d44484"}, - {file = "greenlet-3.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:d46d5069e2eeda111d6f71970e341f4bd9aeeee92074e649ae263b834286ecc0"}, - {file = "greenlet-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81eeec4403a7d7684b5812a8aaa626fa23b7d0848edb3a28d2eb3220daddcbd0"}, - {file = "greenlet-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a3dae7492d16e85ea6045fd11cb8e782b63eac8c8d520c3a92c02ac4573b0a6"}, - {file = "greenlet-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b5ea3664eed571779403858d7cd0a9b0ebf50d57d2cdeafc7748e09ef8cd81a"}, - {file = "greenlet-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22f4e26400f7f48faef2d69c20dc055a1f3043d330923f9abe08ea0aecc44df"}, - {file = "greenlet-3.1.0-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13ff8c8e54a10472ce3b2a2da007f915175192f18e6495bad50486e87c7f6637"}, - {file = "greenlet-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f9671e7282d8c6fcabc32c0fb8d7c0ea8894ae85cee89c9aadc2d7129e1a9954"}, - {file = "greenlet-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:184258372ae9e1e9bddce6f187967f2e08ecd16906557c4320e3ba88a93438c3"}, - {file = "greenlet-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:a0409bc18a9f85321399c29baf93545152d74a49d92f2f55302f122007cfda00"}, - {file = "greenlet-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9eb4a1d7399b9f3c7ac68ae6baa6be5f9195d1d08c9ddc45ad559aa6b556bce6"}, - {file = "greenlet-3.1.0-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:a8870983af660798dc1b529e1fd6f1cefd94e45135a32e58bd70edd694540f33"}, - {file = "greenlet-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfcfb73aed40f550a57ea904629bdaf2e562c68fa1164fa4588e752af6efdc3f"}, - {file = "greenlet-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f9482c2ed414781c0af0b35d9d575226da6b728bd1a720668fa05837184965b7"}, - {file = "greenlet-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d58ec349e0c2c0bc6669bf2cd4982d2f93bf067860d23a0ea1fe677b0f0b1e09"}, - {file = "greenlet-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd65695a8df1233309b701dec2539cc4b11e97d4fcc0f4185b4a12ce54db0491"}, - {file = "greenlet-3.1.0-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:665b21e95bc0fce5cab03b2e1d90ba9c66c510f1bb5fdc864f3a377d0f553f6b"}, - {file = "greenlet-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d3c59a06c2c28a81a026ff11fbf012081ea34fb9b7052f2ed0366e14896f0a1d"}, - {file = "greenlet-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415b9494ff6240b09af06b91a375731febe0090218e2898d2b85f9b92abcda0"}, - {file = "greenlet-3.1.0-cp38-cp38-win32.whl", hash = "sha256:1544b8dd090b494c55e60c4ff46e238be44fdc472d2589e943c241e0169bcea2"}, - {file = "greenlet-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:7f346d24d74c00b6730440f5eb8ec3fe5774ca8d1c9574e8e57c8671bb51b910"}, - {file = "greenlet-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:db1b3ccb93488328c74e97ff888604a8b95ae4f35f4f56677ca57a4fc3a4220b"}, - {file = "greenlet-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44cd313629ded43bb3b98737bba2f3e2c2c8679b55ea29ed73daea6b755fe8e7"}, - {file = "greenlet-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fad7a051e07f64e297e6e8399b4d6a3bdcad3d7297409e9a06ef8cbccff4f501"}, - {file = "greenlet-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3967dcc1cd2ea61b08b0b276659242cbce5caca39e7cbc02408222fb9e6ff39"}, - {file = "greenlet-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d45b75b0f3fd8d99f62eb7908cfa6d727b7ed190737dec7fe46d993da550b81a"}, - {file = "greenlet-3.1.0-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2d004db911ed7b6218ec5c5bfe4cf70ae8aa2223dffbb5b3c69e342bb253cb28"}, - {file = "greenlet-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9505a0c8579899057cbefd4ec34d865ab99852baf1ff33a9481eb3924e2da0b"}, - {file = "greenlet-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fd6e94593f6f9714dbad1aaba734b5ec04593374fa6638df61592055868f8b8"}, - {file = "greenlet-3.1.0-cp39-cp39-win32.whl", hash = "sha256:d0dd943282231480aad5f50f89bdf26690c995e8ff555f26d8a5b9887b559bcc"}, - {file = "greenlet-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:ac0adfdb3a21dc2a24ed728b61e72440d297d0fd3a577389df566651fcd08f97"}, - {file = "greenlet-3.1.0.tar.gz", hash = "sha256:b395121e9bbe8d02a750886f108d540abe66075e61e22f7353d9acb0b81be0f0"}, + {file = "greenlet-3.1.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563"}, + {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83"}, + {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0"}, + {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120"}, + {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc"}, + {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617"}, + {file = "greenlet-3.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7"}, + {file = "greenlet-3.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6"}, + {file = "greenlet-3.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80"}, + {file = "greenlet-3.1.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70"}, + {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159"}, + {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e"}, + {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1"}, + {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383"}, + {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a"}, + {file = "greenlet-3.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511"}, + {file = "greenlet-3.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395"}, + {file = "greenlet-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39"}, + {file = "greenlet-3.1.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d"}, + {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79"}, + {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa"}, + {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441"}, + {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36"}, + {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9"}, + {file = "greenlet-3.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0"}, + {file = "greenlet-3.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942"}, + {file = "greenlet-3.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01"}, + {file = "greenlet-3.1.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1"}, + {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff"}, + {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a"}, + {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e"}, + {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4"}, + {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e"}, + {file = "greenlet-3.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1"}, + {file = "greenlet-3.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c"}, + {file = "greenlet-3.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761"}, + {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011"}, + {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13"}, + {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475"}, + {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b"}, + {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822"}, + {file = "greenlet-3.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01"}, + {file = "greenlet-3.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6"}, + {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291"}, + {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981"}, + {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803"}, + {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc"}, + {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de"}, + {file = "greenlet-3.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa"}, + {file = "greenlet-3.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af"}, + {file = "greenlet-3.1.1-cp37-cp37m-win32.whl", hash = "sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798"}, + {file = "greenlet-3.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef"}, + {file = "greenlet-3.1.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9"}, + {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111"}, + {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81"}, + {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba"}, + {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8"}, + {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1"}, + {file = "greenlet-3.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd"}, + {file = "greenlet-3.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7"}, + {file = "greenlet-3.1.1-cp38-cp38-win32.whl", hash = "sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef"}, + {file = "greenlet-3.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d"}, + {file = "greenlet-3.1.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3"}, + {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42"}, + {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f"}, + {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437"}, + {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145"}, + {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c"}, + {file = "greenlet-3.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e"}, + {file = "greenlet-3.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e"}, + {file = "greenlet-3.1.1-cp39-cp39-win32.whl", hash = "sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c"}, + {file = "greenlet-3.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22"}, + {file = "greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467"}, ] [package.extras] @@ -3508,61 +3534,70 @@ protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4 [[package]] name = "grpcio" -version = "1.66.1" +version = "1.66.2" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.8" files = [ - {file = "grpcio-1.66.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:4877ba180591acdf127afe21ec1c7ff8a5ecf0fe2600f0d3c50e8c4a1cbc6492"}, - {file = "grpcio-1.66.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:3750c5a00bd644c75f4507f77a804d0189d97a107eb1481945a0cf3af3e7a5ac"}, - {file = "grpcio-1.66.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:a013c5fbb12bfb5f927444b477a26f1080755a931d5d362e6a9a720ca7dbae60"}, - {file = "grpcio-1.66.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b1b24c23d51a1e8790b25514157d43f0a4dce1ac12b3f0b8e9f66a5e2c4c132f"}, - {file = "grpcio-1.66.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7ffb8ea674d68de4cac6f57d2498fef477cef582f1fa849e9f844863af50083"}, - {file = "grpcio-1.66.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:307b1d538140f19ccbd3aed7a93d8f71103c5d525f3c96f8616111614b14bf2a"}, - {file = "grpcio-1.66.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1c17ebcec157cfb8dd445890a03e20caf6209a5bd4ac5b040ae9dbc59eef091d"}, - {file = "grpcio-1.66.1-cp310-cp310-win32.whl", hash = "sha256:ef82d361ed5849d34cf09105d00b94b6728d289d6b9235513cb2fcc79f7c432c"}, - {file = "grpcio-1.66.1-cp310-cp310-win_amd64.whl", hash = "sha256:292a846b92cdcd40ecca46e694997dd6b9be6c4c01a94a0dfb3fcb75d20da858"}, - {file = "grpcio-1.66.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:c30aeceeaff11cd5ddbc348f37c58bcb96da8d5aa93fed78ab329de5f37a0d7a"}, - {file = "grpcio-1.66.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8a1e224ce6f740dbb6b24c58f885422deebd7eb724aff0671a847f8951857c26"}, - {file = "grpcio-1.66.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:a66fe4dc35d2330c185cfbb42959f57ad36f257e0cc4557d11d9f0a3f14311df"}, - {file = "grpcio-1.66.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e3ba04659e4fce609de2658fe4dbf7d6ed21987a94460f5f92df7579fd5d0e22"}, - {file = "grpcio-1.66.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4573608e23f7e091acfbe3e84ac2045680b69751d8d67685ffa193a4429fedb1"}, - {file = "grpcio-1.66.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7e06aa1f764ec8265b19d8f00140b8c4b6ca179a6dc67aa9413867c47e1fb04e"}, - {file = "grpcio-1.66.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3885f037eb11f1cacc41f207b705f38a44b69478086f40608959bf5ad85826dd"}, - {file = "grpcio-1.66.1-cp311-cp311-win32.whl", hash = "sha256:97ae7edd3f3f91480e48ede5d3e7d431ad6005bfdbd65c1b56913799ec79e791"}, - {file = "grpcio-1.66.1-cp311-cp311-win_amd64.whl", hash = "sha256:cfd349de4158d797db2bd82d2020554a121674e98fbe6b15328456b3bf2495bb"}, - {file = "grpcio-1.66.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:a92c4f58c01c77205df6ff999faa008540475c39b835277fb8883b11cada127a"}, - {file = "grpcio-1.66.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:fdb14bad0835914f325349ed34a51940bc2ad965142eb3090081593c6e347be9"}, - {file = "grpcio-1.66.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:f03a5884c56256e08fd9e262e11b5cfacf1af96e2ce78dc095d2c41ccae2c80d"}, - {file = "grpcio-1.66.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ca2559692d8e7e245d456877a85ee41525f3ed425aa97eb7a70fc9a79df91a0"}, - {file = "grpcio-1.66.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84ca1be089fb4446490dd1135828bd42a7c7f8421e74fa581611f7afdf7ab761"}, - {file = "grpcio-1.66.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:d639c939ad7c440c7b2819a28d559179a4508783f7e5b991166f8d7a34b52815"}, - {file = "grpcio-1.66.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b9feb4e5ec8dc2d15709f4d5fc367794d69277f5d680baf1910fc9915c633524"}, - {file = "grpcio-1.66.1-cp312-cp312-win32.whl", hash = "sha256:7101db1bd4cd9b880294dec41a93fcdce465bdbb602cd8dc5bd2d6362b618759"}, - {file = "grpcio-1.66.1-cp312-cp312-win_amd64.whl", hash = "sha256:b0aa03d240b5539648d996cc60438f128c7f46050989e35b25f5c18286c86734"}, - {file = "grpcio-1.66.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:ecfe735e7a59e5a98208447293ff8580e9db1e890e232b8b292dc8bd15afc0d2"}, - {file = "grpcio-1.66.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:4825a3aa5648010842e1c9d35a082187746aa0cdbf1b7a2a930595a94fb10fce"}, - {file = "grpcio-1.66.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:f517fd7259fe823ef3bd21e508b653d5492e706e9f0ef82c16ce3347a8a5620c"}, - {file = "grpcio-1.66.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1fe60d0772831d96d263b53d83fb9a3d050a94b0e94b6d004a5ad111faa5b5b"}, - {file = "grpcio-1.66.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31a049daa428f928f21090403e5d18ea02670e3d5d172581670be006100db9ef"}, - {file = "grpcio-1.66.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6f914386e52cbdeb5d2a7ce3bf1fdfacbe9d818dd81b6099a05b741aaf3848bb"}, - {file = "grpcio-1.66.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bff2096bdba686019fb32d2dde45b95981f0d1490e054400f70fc9a8af34b49d"}, - {file = "grpcio-1.66.1-cp38-cp38-win32.whl", hash = "sha256:aa8ba945c96e73de29d25331b26f3e416e0c0f621e984a3ebdb2d0d0b596a3b3"}, - {file = "grpcio-1.66.1-cp38-cp38-win_amd64.whl", hash = "sha256:161d5c535c2bdf61b95080e7f0f017a1dfcb812bf54093e71e5562b16225b4ce"}, - {file = "grpcio-1.66.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:d0cd7050397b3609ea51727b1811e663ffda8bda39c6a5bb69525ef12414b503"}, - {file = "grpcio-1.66.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0e6c9b42ded5d02b6b1fea3a25f036a2236eeb75d0579bfd43c0018c88bf0a3e"}, - {file = "grpcio-1.66.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:c9f80f9fad93a8cf71c7f161778ba47fd730d13a343a46258065c4deb4b550c0"}, - {file = "grpcio-1.66.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dd67ed9da78e5121efc5c510f0122a972216808d6de70953a740560c572eb44"}, - {file = "grpcio-1.66.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48b0d92d45ce3be2084b92fb5bae2f64c208fea8ceed7fccf6a7b524d3c4942e"}, - {file = "grpcio-1.66.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:4d813316d1a752be6f5c4360c49f55b06d4fe212d7df03253dfdae90c8a402bb"}, - {file = "grpcio-1.66.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9c9bebc6627873ec27a70fc800f6083a13c70b23a5564788754b9ee52c5aef6c"}, - {file = "grpcio-1.66.1-cp39-cp39-win32.whl", hash = "sha256:30a1c2cf9390c894c90bbc70147f2372130ad189cffef161f0432d0157973f45"}, - {file = "grpcio-1.66.1-cp39-cp39-win_amd64.whl", hash = "sha256:17663598aadbedc3cacd7bbde432f541c8e07d2496564e22b214b22c7523dac8"}, - {file = "grpcio-1.66.1.tar.gz", hash = "sha256:35334f9c9745add3e357e3372756fd32d925bd52c41da97f4dfdafbde0bf0ee2"}, + {file = "grpcio-1.66.2-cp310-cp310-linux_armv7l.whl", hash = "sha256:fe96281713168a3270878255983d2cb1a97e034325c8c2c25169a69289d3ecfa"}, + {file = "grpcio-1.66.2-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:73fc8f8b9b5c4a03e802b3cd0c18b2b06b410d3c1dcbef989fdeb943bd44aff7"}, + {file = "grpcio-1.66.2-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:03b0b307ba26fae695e067b94cbb014e27390f8bc5ac7a3a39b7723fed085604"}, + {file = "grpcio-1.66.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d69ce1f324dc2d71e40c9261d3fdbe7d4c9d60f332069ff9b2a4d8a257c7b2b"}, + {file = "grpcio-1.66.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05bc2ceadc2529ab0b227b1310d249d95d9001cd106aa4d31e8871ad3c428d73"}, + {file = "grpcio-1.66.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8ac475e8da31484efa25abb774674d837b343afb78bb3bcdef10f81a93e3d6bf"}, + {file = "grpcio-1.66.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0be4e0490c28da5377283861bed2941d1d20ec017ca397a5df4394d1c31a9b50"}, + {file = "grpcio-1.66.2-cp310-cp310-win32.whl", hash = "sha256:4e504572433f4e72b12394977679161d495c4c9581ba34a88d843eaf0f2fbd39"}, + {file = "grpcio-1.66.2-cp310-cp310-win_amd64.whl", hash = "sha256:2018b053aa15782db2541ca01a7edb56a0bf18c77efed975392583725974b249"}, + {file = "grpcio-1.66.2-cp311-cp311-linux_armv7l.whl", hash = "sha256:2335c58560a9e92ac58ff2bc5649952f9b37d0735608242973c7a8b94a6437d8"}, + {file = "grpcio-1.66.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:45a3d462826f4868b442a6b8fdbe8b87b45eb4f5b5308168c156b21eca43f61c"}, + {file = "grpcio-1.66.2-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:a9539f01cb04950fd4b5ab458e64a15f84c2acc273670072abe49a3f29bbad54"}, + {file = "grpcio-1.66.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce89f5876662f146d4c1f695dda29d4433a5d01c8681fbd2539afff535da14d4"}, + {file = "grpcio-1.66.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d25a14af966438cddf498b2e338f88d1c9706f3493b1d73b93f695c99c5f0e2a"}, + {file = "grpcio-1.66.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6001e575b8bbd89eee11960bb640b6da6ae110cf08113a075f1e2051cc596cae"}, + {file = "grpcio-1.66.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4ea1d062c9230278793820146c95d038dc0f468cbdd172eec3363e42ff1c7d01"}, + {file = "grpcio-1.66.2-cp311-cp311-win32.whl", hash = "sha256:38b68498ff579a3b1ee8f93a05eb48dc2595795f2f62716e797dc24774c1aaa8"}, + {file = "grpcio-1.66.2-cp311-cp311-win_amd64.whl", hash = "sha256:6851de821249340bdb100df5eacfecfc4e6075fa85c6df7ee0eb213170ec8e5d"}, + {file = "grpcio-1.66.2-cp312-cp312-linux_armv7l.whl", hash = "sha256:802d84fd3d50614170649853d121baaaa305de7b65b3e01759247e768d691ddf"}, + {file = "grpcio-1.66.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:80fd702ba7e432994df208f27514280b4b5c6843e12a48759c9255679ad38db8"}, + {file = "grpcio-1.66.2-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:12fda97ffae55e6526825daf25ad0fa37483685952b5d0f910d6405c87e3adb6"}, + {file = "grpcio-1.66.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:950da58d7d80abd0ea68757769c9db0a95b31163e53e5bb60438d263f4bed7b7"}, + {file = "grpcio-1.66.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e636ce23273683b00410f1971d209bf3689238cf5538d960adc3cdfe80dd0dbd"}, + {file = "grpcio-1.66.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a917d26e0fe980b0ac7bfcc1a3c4ad6a9a4612c911d33efb55ed7833c749b0ee"}, + {file = "grpcio-1.66.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49f0ca7ae850f59f828a723a9064cadbed90f1ece179d375966546499b8a2c9c"}, + {file = "grpcio-1.66.2-cp312-cp312-win32.whl", hash = "sha256:31fd163105464797a72d901a06472860845ac157389e10f12631025b3e4d0453"}, + {file = "grpcio-1.66.2-cp312-cp312-win_amd64.whl", hash = "sha256:ff1f7882e56c40b0d33c4922c15dfa30612f05fb785074a012f7cda74d1c3679"}, + {file = "grpcio-1.66.2-cp313-cp313-linux_armv7l.whl", hash = "sha256:3b00efc473b20d8bf83e0e1ae661b98951ca56111feb9b9611df8efc4fe5d55d"}, + {file = "grpcio-1.66.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1caa38fb22a8578ab8393da99d4b8641e3a80abc8fd52646f1ecc92bcb8dee34"}, + {file = "grpcio-1.66.2-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:c408f5ef75cfffa113cacd8b0c0e3611cbfd47701ca3cdc090594109b9fcbaed"}, + {file = "grpcio-1.66.2-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c806852deaedee9ce8280fe98955c9103f62912a5b2d5ee7e3eaa284a6d8d8e7"}, + {file = "grpcio-1.66.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f145cc21836c332c67baa6fc81099d1d27e266401565bf481948010d6ea32d46"}, + {file = "grpcio-1.66.2-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:73e3b425c1e155730273f73e419de3074aa5c5e936771ee0e4af0814631fb30a"}, + {file = "grpcio-1.66.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:9c509a4f78114cbc5f0740eb3d7a74985fd2eff022971bc9bc31f8bc93e66a3b"}, + {file = "grpcio-1.66.2-cp313-cp313-win32.whl", hash = "sha256:20657d6b8cfed7db5e11b62ff7dfe2e12064ea78e93f1434d61888834bc86d75"}, + {file = "grpcio-1.66.2-cp313-cp313-win_amd64.whl", hash = "sha256:fb70487c95786e345af5e854ffec8cb8cc781bcc5df7930c4fbb7feaa72e1cdf"}, + {file = "grpcio-1.66.2-cp38-cp38-linux_armv7l.whl", hash = "sha256:a18e20d8321c6400185b4263e27982488cb5cdd62da69147087a76a24ef4e7e3"}, + {file = "grpcio-1.66.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:02697eb4a5cbe5a9639f57323b4c37bcb3ab2d48cec5da3dc2f13334d72790dd"}, + {file = "grpcio-1.66.2-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:99a641995a6bc4287a6315989ee591ff58507aa1cbe4c2e70d88411c4dcc0839"}, + {file = "grpcio-1.66.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ed71e81782966ffead60268bbda31ea3f725ebf8aa73634d5dda44f2cf3fb9c"}, + {file = "grpcio-1.66.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbd27c24a4cc5e195a7f56cfd9312e366d5d61b86e36d46bbe538457ea6eb8dd"}, + {file = "grpcio-1.66.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d9a9724a156c8ec6a379869b23ba3323b7ea3600851c91489b871e375f710bc8"}, + {file = "grpcio-1.66.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d8d4732cc5052e92cea2f78b233c2e2a52998ac40cd651f40e398893ad0d06ec"}, + {file = "grpcio-1.66.2-cp38-cp38-win32.whl", hash = "sha256:7b2c86457145ce14c38e5bf6bdc19ef88e66c5fee2c3d83285c5aef026ba93b3"}, + {file = "grpcio-1.66.2-cp38-cp38-win_amd64.whl", hash = "sha256:e88264caad6d8d00e7913996030bac8ad5f26b7411495848cc218bd3a9040b6c"}, + {file = "grpcio-1.66.2-cp39-cp39-linux_armv7l.whl", hash = "sha256:c400ba5675b67025c8a9f48aa846f12a39cf0c44df5cd060e23fda5b30e9359d"}, + {file = "grpcio-1.66.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:66a0cd8ba6512b401d7ed46bb03f4ee455839957f28b8d61e7708056a806ba6a"}, + {file = "grpcio-1.66.2-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:06de8ec0bd71be123eec15b0e0d457474931c2c407869b6c349bd9bed4adbac3"}, + {file = "grpcio-1.66.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb57870449dfcfac428afbb5a877829fcb0d6db9d9baa1148705739e9083880e"}, + {file = "grpcio-1.66.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b672abf90a964bfde2d0ecbce30f2329a47498ba75ce6f4da35a2f4532b7acbc"}, + {file = "grpcio-1.66.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ad2efdbe90c73b0434cbe64ed372e12414ad03c06262279b104a029d1889d13e"}, + {file = "grpcio-1.66.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9c3a99c519f4638e700e9e3f83952e27e2ea10873eecd7935823dab0c1c9250e"}, + {file = "grpcio-1.66.2-cp39-cp39-win32.whl", hash = "sha256:78fa51ebc2d9242c0fc5db0feecc57a9943303b46664ad89921f5079e2e4ada7"}, + {file = "grpcio-1.66.2-cp39-cp39-win_amd64.whl", hash = "sha256:728bdf36a186e7f51da73be7f8d09457a03061be848718d0edf000e709418987"}, + {file = "grpcio-1.66.2.tar.gz", hash = "sha256:563588c587b75c34b928bc428548e5b00ea38c46972181a4d8b75ba7e3f24231"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.66.1)"] +protobuf = ["grpcio-tools (>=1.66.2)"] [[package]] name = "grpcio-status" @@ -3993,13 +4028,13 @@ files = [ [[package]] name = "idna" -version = "3.9" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" files = [ - {file = "idna-3.9-py3-none-any.whl", hash = "sha256:69297d5da0cc9281c77efffb4e730254dd45943f45bbfb461de5991713989b1e"}, - {file = "idna-3.9.tar.gz", hash = "sha256:e5c5dafde284f26e9e0f28f6ea2d6400abd5ca099864a67f576f3981c6476124"}, + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] [package.extras] @@ -4341,17 +4376,18 @@ files = [ [[package]] name = "kombu" -version = "5.4.1" +version = "5.4.2" description = "Messaging library for Python." optional = false python-versions = ">=3.8" files = [ - {file = "kombu-5.4.1-py3-none-any.whl", hash = "sha256:621d365f234e4c089596f3a2510f1ade07026efc28caca426161d8f458786cab"}, - {file = "kombu-5.4.1.tar.gz", hash = "sha256:1c05178826dab811f8cab5b0a154d42a7a33d8bcdde9fa3d7b4582e43c3c03db"}, + {file = "kombu-5.4.2-py3-none-any.whl", hash = "sha256:14212f5ccf022fc0a70453bb025a1dcc32782a588c49ea866884047d66e14763"}, + {file = "kombu-5.4.2.tar.gz", hash = "sha256:eef572dd2fd9fc614b37580e3caeafdd5af46c1eff31e7fba89138cdb406f2cf"}, ] [package.dependencies] amqp = ">=5.1.1,<6.0.0" +tzdata = {version = "*", markers = "python_version >= \"3.9\""} vine = "5.1.0" [package.extras] @@ -4373,17 +4409,18 @@ zookeeper = ["kazoo (>=2.8.0)"] [[package]] name = "kubernetes" -version = "30.1.0" +version = "31.0.0" description = "Kubernetes python client" optional = false python-versions = ">=3.6" files = [ - {file = "kubernetes-30.1.0-py2.py3-none-any.whl", hash = "sha256:e212e8b7579031dd2e512168b617373bc1e03888d41ac4e04039240a292d478d"}, - {file = "kubernetes-30.1.0.tar.gz", hash = "sha256:41e4c77af9f28e7a6c314e3bd06a8c6229ddd787cad684e0ab9f69b498e98ebc"}, + {file = "kubernetes-31.0.0-py2.py3-none-any.whl", hash = "sha256:bf141e2d380c8520eada8b351f4e319ffee9636328c137aa432bc486ca1200e1"}, + {file = "kubernetes-31.0.0.tar.gz", hash = "sha256:28945de906c8c259c1ebe62703b56a03b714049372196f854105afe4e6d014c0"}, ] [package.dependencies] certifi = ">=14.05.14" +durationpy = ">=0.7" google-auth = ">=1.0.1" oauthlib = ">=3.2.2" python-dateutil = ">=2.5.3" @@ -4413,13 +4450,13 @@ six = "*" [[package]] name = "langfuse" -version = "2.48.1" +version = "2.51.2" description = "A client library for accessing langfuse" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langfuse-2.48.1-py3-none-any.whl", hash = "sha256:8661070b6d94ba1d7da92c054f3110b6ecf4489d6e8204a4080f934f3f49ebf2"}, - {file = "langfuse-2.48.1.tar.gz", hash = "sha256:b8117d90babec6be1bc3303b42e0b71848531eae44118e6e0123d03e7961d0fc"}, + {file = "langfuse-2.51.2-py3-none-any.whl", hash = "sha256:7aab94a9452cda4587a2cd4917e455da1afd7f8a2696688742130e2f2d23ca59"}, + {file = "langfuse-2.51.2.tar.gz", hash = "sha256:0982b108ab4c02947f682e442b0796b7a73825d31eeace1771575f6454b8f79a"}, ] [package.dependencies] @@ -4438,13 +4475,13 @@ openai = ["openai (>=0.27.8)"] [[package]] name = "langsmith" -version = "0.1.120" +version = "0.1.129" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langsmith-0.1.120-py3-none-any.whl", hash = "sha256:54d2785e301646c0988e0a69ebe4d976488c87b41928b358cb153b6ddd8db62b"}, - {file = "langsmith-0.1.120.tar.gz", hash = "sha256:25499ca187b41bd89d784b272b97a8d76f60e0e21bdf20336e8a2aa6a9b23ac9"}, + {file = "langsmith-0.1.129-py3-none-any.whl", hash = "sha256:31393fbbb17d6be5b99b9b22d530450094fab23c6c37281a6a6efb2143d05347"}, + {file = "langsmith-0.1.129.tar.gz", hash = "sha256:6c3ba66471bef41b9f87da247cc0b493268b3f54656f73648a256a205261b6a0"}, ] [package.dependencies] @@ -4948,95 +4985,116 @@ tqdm = "*" [[package]] name = "mmh3" -version = "4.1.0" +version = "5.0.1" description = "Python extension for MurmurHash (MurmurHash3), a set of fast and robust hash functions." optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:be5ac76a8b0cd8095784e51e4c1c9c318c19edcd1709a06eb14979c8d850c31a"}, - {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98a49121afdfab67cd80e912b36404139d7deceb6773a83620137aaa0da5714c"}, - {file = "mmh3-4.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5259ac0535874366e7d1a5423ef746e0d36a9e3c14509ce6511614bdc5a7ef5b"}, - {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5950827ca0453a2be357696da509ab39646044e3fa15cad364eb65d78797437"}, - {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1dd0f652ae99585b9dd26de458e5f08571522f0402155809fd1dc8852a613a39"}, - {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99d25548070942fab1e4a6f04d1626d67e66d0b81ed6571ecfca511f3edf07e6"}, - {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53db8d9bad3cb66c8f35cbc894f336273f63489ce4ac416634932e3cbe79eb5b"}, - {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75da0f615eb55295a437264cc0b736753f830b09d102aa4c2a7d719bc445ec05"}, - {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b926b07fd678ea84b3a2afc1fa22ce50aeb627839c44382f3d0291e945621e1a"}, - {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c5b053334f9b0af8559d6da9dc72cef0a65b325ebb3e630c680012323c950bb6"}, - {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:5bf33dc43cd6de2cb86e0aa73a1cc6530f557854bbbe5d59f41ef6de2e353d7b"}, - {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fa7eacd2b830727ba3dd65a365bed8a5c992ecd0c8348cf39a05cc77d22f4970"}, - {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:42dfd6742b9e3eec599f85270617debfa0bbb913c545bb980c8a4fa7b2d047da"}, - {file = "mmh3-4.1.0-cp310-cp310-win32.whl", hash = "sha256:2974ad343f0d39dcc88e93ee6afa96cedc35a9883bc067febd7ff736e207fa47"}, - {file = "mmh3-4.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:74699a8984ded645c1a24d6078351a056f5a5f1fe5838870412a68ac5e28d865"}, - {file = "mmh3-4.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:f0dc874cedc23d46fc488a987faa6ad08ffa79e44fb08e3cd4d4cf2877c00a00"}, - {file = "mmh3-4.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3280a463855b0eae64b681cd5b9ddd9464b73f81151e87bb7c91a811d25619e6"}, - {file = "mmh3-4.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:97ac57c6c3301769e757d444fa7c973ceb002cb66534b39cbab5e38de61cd896"}, - {file = "mmh3-4.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a7b6502cdb4dbd880244818ab363c8770a48cdccecf6d729ade0241b736b5ec0"}, - {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52ba2da04671a9621580ddabf72f06f0e72c1c9c3b7b608849b58b11080d8f14"}, - {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a5fef4c4ecc782e6e43fbeab09cff1bac82c998a1773d3a5ee6a3605cde343e"}, - {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5135358a7e00991f73b88cdc8eda5203bf9de22120d10a834c5761dbeb07dd13"}, - {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cff9ae76a54f7c6fe0167c9c4028c12c1f6de52d68a31d11b6790bb2ae685560"}, - {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f02576a4d106d7830ca90278868bf0983554dd69183b7bbe09f2fcd51cf54f"}, - {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:073d57425a23721730d3ff5485e2da489dd3c90b04e86243dd7211f889898106"}, - {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:71e32ddec7f573a1a0feb8d2cf2af474c50ec21e7a8263026e8d3b4b629805db"}, - {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7cbb20b29d57e76a58b40fd8b13a9130db495a12d678d651b459bf61c0714cea"}, - {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:a42ad267e131d7847076bb7e31050f6c4378cd38e8f1bf7a0edd32f30224d5c9"}, - {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4a013979fc9390abadc445ea2527426a0e7a4495c19b74589204f9b71bcaafeb"}, - {file = "mmh3-4.1.0-cp311-cp311-win32.whl", hash = "sha256:1d3b1cdad7c71b7b88966301789a478af142bddcb3a2bee563f7a7d40519a00f"}, - {file = "mmh3-4.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0dc6dc32eb03727467da8e17deffe004fbb65e8b5ee2b502d36250d7a3f4e2ec"}, - {file = "mmh3-4.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:9ae3a5c1b32dda121c7dc26f9597ef7b01b4c56a98319a7fe86c35b8bc459ae6"}, - {file = "mmh3-4.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0033d60c7939168ef65ddc396611077a7268bde024f2c23bdc283a19123f9e9c"}, - {file = "mmh3-4.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d6af3e2287644b2b08b5924ed3a88c97b87b44ad08e79ca9f93d3470a54a41c5"}, - {file = "mmh3-4.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d82eb4defa245e02bb0b0dc4f1e7ee284f8d212633389c91f7fba99ba993f0a2"}, - {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba245e94b8d54765e14c2d7b6214e832557e7856d5183bc522e17884cab2f45d"}, - {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb04e2feeabaad6231e89cd43b3d01a4403579aa792c9ab6fdeef45cc58d4ec0"}, - {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e3b1a27def545ce11e36158ba5d5390cdbc300cfe456a942cc89d649cf7e3b2"}, - {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce0ab79ff736d7044e5e9b3bfe73958a55f79a4ae672e6213e92492ad5e734d5"}, - {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b02268be6e0a8eeb8a924d7db85f28e47344f35c438c1e149878bb1c47b1cd3"}, - {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:deb887f5fcdaf57cf646b1e062d56b06ef2f23421c80885fce18b37143cba828"}, - {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99dd564e9e2b512eb117bd0cbf0f79a50c45d961c2a02402787d581cec5448d5"}, - {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:08373082dfaa38fe97aa78753d1efd21a1969e51079056ff552e687764eafdfe"}, - {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:54b9c6a2ea571b714e4fe28d3e4e2db37abfd03c787a58074ea21ee9a8fd1740"}, - {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a7b1edf24c69e3513f879722b97ca85e52f9032f24a52284746877f6a7304086"}, - {file = "mmh3-4.1.0-cp312-cp312-win32.whl", hash = "sha256:411da64b951f635e1e2284b71d81a5a83580cea24994b328f8910d40bed67276"}, - {file = "mmh3-4.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:bebc3ecb6ba18292e3d40c8712482b4477abd6981c2ebf0e60869bd90f8ac3a9"}, - {file = "mmh3-4.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:168473dd608ade6a8d2ba069600b35199a9af837d96177d3088ca91f2b3798e3"}, - {file = "mmh3-4.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:372f4b7e1dcde175507640679a2a8790185bb71f3640fc28a4690f73da986a3b"}, - {file = "mmh3-4.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:438584b97f6fe13e944faf590c90fc127682b57ae969f73334040d9fa1c7ffa5"}, - {file = "mmh3-4.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6e27931b232fc676675fac8641c6ec6b596daa64d82170e8597f5a5b8bdcd3b6"}, - {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:571a92bad859d7b0330e47cfd1850b76c39b615a8d8e7aa5853c1f971fd0c4b1"}, - {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a69d6afe3190fa08f9e3a58e5145549f71f1f3fff27bd0800313426929c7068"}, - {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:afb127be0be946b7630220908dbea0cee0d9d3c583fa9114a07156f98566dc28"}, - {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:940d86522f36348ef1a494cbf7248ab3f4a1638b84b59e6c9e90408bd11ad729"}, - {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3dcccc4935686619a8e3d1f7b6e97e3bd89a4a796247930ee97d35ea1a39341"}, - {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01bb9b90d61854dfc2407c5e5192bfb47222d74f29d140cb2dd2a69f2353f7cc"}, - {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bcb1b8b951a2c0b0fb8a5426c62a22557e2ffc52539e0a7cc46eb667b5d606a9"}, - {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6477a05d5e5ab3168e82e8b106e316210ac954134f46ec529356607900aea82a"}, - {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:da5892287e5bea6977364b15712a2573c16d134bc5fdcdd4cf460006cf849278"}, - {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:99180d7fd2327a6fffbaff270f760576839dc6ee66d045fa3a450f3490fda7f5"}, - {file = "mmh3-4.1.0-cp38-cp38-win32.whl", hash = "sha256:9b0d4f3949913a9f9a8fb1bb4cc6ecd52879730aab5ff8c5a3d8f5b593594b73"}, - {file = "mmh3-4.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:598c352da1d945108aee0c3c3cfdd0e9b3edef74108f53b49d481d3990402169"}, - {file = "mmh3-4.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:475d6d1445dd080f18f0f766277e1237fa2914e5fe3307a3b2a3044f30892103"}, - {file = "mmh3-4.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5ca07c41e6a2880991431ac717c2a049056fff497651a76e26fc22224e8b5732"}, - {file = "mmh3-4.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ebe052fef4bbe30c0548d12ee46d09f1b69035ca5208a7075e55adfe091be44"}, - {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaefd42e85afb70f2b855a011f7b4d8a3c7e19c3f2681fa13118e4d8627378c5"}, - {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0ae43caae5a47afe1b63a1ae3f0986dde54b5fb2d6c29786adbfb8edc9edfb"}, - {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6218666f74c8c013c221e7f5f8a693ac9cf68e5ac9a03f2373b32d77c48904de"}, - {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac59294a536ba447b5037f62d8367d7d93b696f80671c2c45645fa9f1109413c"}, - {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086844830fcd1e5c84fec7017ea1ee8491487cfc877847d96f86f68881569d2e"}, - {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e42b38fad664f56f77f6fbca22d08450f2464baa68acdbf24841bf900eb98e87"}, - {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d08b790a63a9a1cde3b5d7d733ed97d4eb884bfbc92f075a091652d6bfd7709a"}, - {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:73ea4cc55e8aea28c86799ecacebca09e5f86500414870a8abaedfcbaf74d288"}, - {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:f90938ff137130e47bcec8dc1f4ceb02f10178c766e2ef58a9f657ff1f62d124"}, - {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:aa1f13e94b8631c8cd53259250556edcf1de71738936b60febba95750d9632bd"}, - {file = "mmh3-4.1.0-cp39-cp39-win32.whl", hash = "sha256:a3b680b471c181490cf82da2142029edb4298e1bdfcb67c76922dedef789868d"}, - {file = "mmh3-4.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:fefef92e9c544a8dbc08f77a8d1b6d48006a750c4375bbcd5ff8199d761e263b"}, - {file = "mmh3-4.1.0-cp39-cp39-win_arm64.whl", hash = "sha256:8e2c1f6a2b41723a4f82bd5a762a777836d29d664fc0095f17910bea0adfd4a6"}, - {file = "mmh3-4.1.0.tar.gz", hash = "sha256:a1cf25348b9acd229dda464a094d6170f47d2850a1fcb762a3b6172d2ce6ca4a"}, + {file = "mmh3-5.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f0a4b4bf05778ed77d820d6e7d0e9bd6beb0c01af10e1ce9233f5d2f814fcafa"}, + {file = "mmh3-5.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac7a391039aeab95810c2d020b69a94eb6b4b37d4e2374831e92db3a0cdf71c6"}, + {file = "mmh3-5.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3a2583b5521ca49756d8d8bceba80627a9cc295f255dcab4e3df7ccc2f09679a"}, + {file = "mmh3-5.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:081a8423fe53c1ac94f87165f3e4c500125d343410c1a0c5f1703e898a3ef038"}, + {file = "mmh3-5.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8b4d72713799755dc8954a7d36d5c20a6c8de7b233c82404d122c7c7c1707cc"}, + {file = "mmh3-5.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:389a6fd51efc76d3182d36ec306448559c1244f11227d2bb771bdd0e6cc91321"}, + {file = "mmh3-5.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:39f4128edaa074bff721b1d31a72508cba4d2887ee7867f22082e1fe9d4edea0"}, + {file = "mmh3-5.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d5d23a94d91aabba3386b3769048d5f4210fdfef80393fece2f34ba5a7b466c"}, + {file = "mmh3-5.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:16347d038361f8b8f24fd2b7ef378c9b68ddee9f7706e46269b6e0d322814713"}, + {file = "mmh3-5.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6e299408565af7d61f2d20a5ffdd77cf2ed902460fe4e6726839d59ba4b72316"}, + {file = "mmh3-5.0.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:42050af21ddfc5445ee5a66e73a8fc758c71790305e3ee9e4a85a8e69e810f94"}, + {file = "mmh3-5.0.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2ae9b1f5ef27ec54659920f0404b7ceb39966e28867c461bfe83a05e8d18ddb0"}, + {file = "mmh3-5.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:50c2495a02045f3047d71d4ae9cdd7a15efc0bcbb7ff17a18346834a8e2d1d19"}, + {file = "mmh3-5.0.1-cp310-cp310-win32.whl", hash = "sha256:c028fa77cddf351ca13b4a56d43c1775652cde0764cadb39120b68f02a23ecf6"}, + {file = "mmh3-5.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:c5e741e421ec14400c4aae30890515c201f518403bdef29ae1e00d375bb4bbb5"}, + {file = "mmh3-5.0.1-cp310-cp310-win_arm64.whl", hash = "sha256:b17156d56fabc73dbf41bca677ceb6faed435cc8544f6566d72ea77d8a17e9d0"}, + {file = "mmh3-5.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a6d5a9b1b923f1643559ba1fc0bf7a5076c90cbb558878d3bf3641ce458f25d"}, + {file = "mmh3-5.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3349b968be555f7334bbcce839da98f50e1e80b1c615d8e2aa847ea4a964a012"}, + {file = "mmh3-5.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1bd3c94b110e55db02ab9b605029f48a2f7f677c6e58c09d44e42402d438b7e1"}, + {file = "mmh3-5.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d47ba84d48608f79adbb10bb09986b6dc33eeda5c2d1bd75d00820081b73bde9"}, + {file = "mmh3-5.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c0217987a8b8525c8d9170f66d036dec4ab45cfbd53d47e8d76125791ceb155e"}, + {file = "mmh3-5.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2797063a34e78d1b61639a98b0edec1c856fa86ab80c7ec859f1796d10ba429"}, + {file = "mmh3-5.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8bba16340adcbd47853a2fbe5afdb397549e8f2e79324ff1dced69a3f8afe7c3"}, + {file = "mmh3-5.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:282797957c9f60b51b9d768a602c25f579420cc9af46feb77d457a27823d270a"}, + {file = "mmh3-5.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e4fb670c29e63f954f9e7a2cdcd57b36a854c2538f579ef62681ccbaa1de2b69"}, + {file = "mmh3-5.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ee7d85438dc6aff328e19ab052086a3c29e8a9b632998a49e5c4b0034e9e8d6"}, + {file = "mmh3-5.0.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b7fb5db231f3092444bc13901e6a8d299667126b00636ffbad4a7b45e1051e2f"}, + {file = "mmh3-5.0.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c100dd441703da5ec136b1d9003ed4a041d8a1136234c9acd887499796df6ad8"}, + {file = "mmh3-5.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:71f3b765138260fd7a7a2dba0ea5727dabcd18c1f80323c9cfef97a7e86e01d0"}, + {file = "mmh3-5.0.1-cp311-cp311-win32.whl", hash = "sha256:9a76518336247fd17689ce3ae5b16883fd86a490947d46a0193d47fb913e26e3"}, + {file = "mmh3-5.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:336bc4df2e44271f1c302d289cc3d78bd52d3eed8d306c7e4bff8361a12bf148"}, + {file = "mmh3-5.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:af6522722fbbc5999aa66f7244d0986767a46f1fb05accc5200f75b72428a508"}, + {file = "mmh3-5.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f2730bb263ed9c388e8860438b057a53e3cc701134a6ea140f90443c4c11aa40"}, + {file = "mmh3-5.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6246927bc293f6d56724536400b85fb85f5be26101fa77d5f97dd5e2a4c69bf2"}, + {file = "mmh3-5.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fbca322519a6e6e25b6abf43e940e1667cf8ea12510e07fb4919b48a0cd1c411"}, + {file = "mmh3-5.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eae8c19903ed8a1724ad9e67e86f15d198a7a1271a4f9be83d47e38f312ed672"}, + {file = "mmh3-5.0.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a09fd6cc72c07c0c07c3357714234b646d78052487c4a3bd5f7f6e08408cff60"}, + {file = "mmh3-5.0.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2ff8551fee7ae3b11c5d986b6347ade0dccaadd4670ffdb2b944dee120ffcc84"}, + {file = "mmh3-5.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e39694c73a5a20c8bf36dfd8676ed351e5234d55751ba4f7562d85449b21ef3f"}, + {file = "mmh3-5.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eba6001989a92f72a89c7cf382fda831678bd780707a66b4f8ca90239fdf2123"}, + {file = "mmh3-5.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0771f90c9911811cc606a5c7b7b58f33501c9ee896ed68a6ac22c7d55878ecc0"}, + {file = "mmh3-5.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:09b31ed0c0c0920363e96641fac4efde65b1ab62b8df86293142f35a254e72b4"}, + {file = "mmh3-5.0.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5cf4a8deda0235312db12075331cb417c4ba163770edfe789bde71d08a24b692"}, + {file = "mmh3-5.0.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:41f7090a95185ef20ac018581a99337f0cbc84a2135171ee3290a9c0d9519585"}, + {file = "mmh3-5.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b97b5b368fb7ff22194ec5854f5b12d8de9ab67a0f304728c7f16e5d12135b76"}, + {file = "mmh3-5.0.1-cp312-cp312-win32.whl", hash = "sha256:842516acf04da546f94fad52db125ee619ccbdcada179da51c326a22c4578cb9"}, + {file = "mmh3-5.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:d963be0dbfd9fca209c17172f6110787ebf78934af25e3694fe2ba40e55c1e2b"}, + {file = "mmh3-5.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:a5da292ceeed8ce8e32b68847261a462d30fd7b478c3f55daae841404f433c15"}, + {file = "mmh3-5.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:673e3f1c8d4231d6fb0271484ee34cb7146a6499fc0df80788adb56fd76842da"}, + {file = "mmh3-5.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f795a306bd16a52ad578b663462cc8e95500b3925d64118ae63453485d67282b"}, + {file = "mmh3-5.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5ed57a5e28e502a1d60436cc25c76c3a5ba57545f250f2969af231dc1221e0a5"}, + {file = "mmh3-5.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:632c28e7612e909dbb6cbe2fe496201ada4695b7715584005689c5dc038e59ad"}, + {file = "mmh3-5.0.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53fd6bd525a5985e391c43384672d9d6b317fcb36726447347c7fc75bfed34ec"}, + {file = "mmh3-5.0.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dceacf6b0b961a0e499836af3aa62d60633265607aef551b2a3e3c48cdaa5edd"}, + {file = "mmh3-5.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8f0738d478fdfb5d920f6aff5452c78f2c35b0eff72caa2a97dfe38e82f93da2"}, + {file = "mmh3-5.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e70285e7391ab88b872e5bef632bad16b9d99a6d3ca0590656a4753d55988af"}, + {file = "mmh3-5.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:27e5fc6360aa6b828546a4318da1a7da6bf6e5474ccb053c3a6aa8ef19ff97bd"}, + {file = "mmh3-5.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7989530c3c1e2c17bf5a0ec2bba09fd19819078ba90beedabb1c3885f5040b0d"}, + {file = "mmh3-5.0.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:cdad7bee649950da7ecd3cbbbd12fb81f1161072ecbdb5acfa0018338c5cb9cf"}, + {file = "mmh3-5.0.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e143b8f184c1bb58cecd85ab4a4fd6dc65a2d71aee74157392c3fddac2a4a331"}, + {file = "mmh3-5.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e5eb12e886f3646dd636f16b76eb23fc0c27e8ff3c1ae73d4391e50ef60b40f6"}, + {file = "mmh3-5.0.1-cp313-cp313-win32.whl", hash = "sha256:16e6dddfa98e1c2d021268e72c78951234186deb4df6630e984ac82df63d0a5d"}, + {file = "mmh3-5.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:d3ffb792d70b8c4a2382af3598dad6ae0c5bd9cee5b7ffcc99aa2f5fd2c1bf70"}, + {file = "mmh3-5.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:122fa9ec148383f9124292962bda745f192b47bfd470b2af5fe7bb3982b17896"}, + {file = "mmh3-5.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b12bad8c75e6ff5d67319794fb6a5e8c713826c818d47f850ad08b4aa06960c6"}, + {file = "mmh3-5.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e5bbb066538c1048d542246fc347bb7994bdda29a3aea61c22f9f8b57111ce69"}, + {file = "mmh3-5.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:eee6134273f64e2a106827cc8fd77e70cc7239a285006fc6ab4977d59b015af2"}, + {file = "mmh3-5.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d04d9aa19d48e4c7bbec9cabc2c4dccc6ff3b2402f856d5bf0de03e10f167b5b"}, + {file = "mmh3-5.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79f37da1eed034d06567a69a7988456345c7f29e49192831c3975b464493b16e"}, + {file = "mmh3-5.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:242f77666743337aa828a2bf2da71b6ba79623ee7f93edb11e009f69237c8561"}, + {file = "mmh3-5.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffd943fff690463945f6441a2465555b3146deaadf6a5e88f2590d14c655d71b"}, + {file = "mmh3-5.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:565b15f8d7df43acb791ff5a360795c20bfa68bca8b352509e0fbabd06cc48cd"}, + {file = "mmh3-5.0.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fc6aafb867c2030df98ac7760ff76b500359252867985f357bd387739f3d5287"}, + {file = "mmh3-5.0.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:32898170644d45aa27c974ab0d067809c066205110f5c6d09f47d9ece6978bfe"}, + {file = "mmh3-5.0.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:42865567838d2193eb64e0ef571f678bf361a254fcdef0c5c8e73243217829bd"}, + {file = "mmh3-5.0.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:5ff5c1f301c4a8b6916498969c0fcc7e3dbc56b4bfce5cfe3fe31f3f4609e5ae"}, + {file = "mmh3-5.0.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:be74c2dda8a6f44a504450aa2c3507f8067a159201586fc01dd41ab80efc350f"}, + {file = "mmh3-5.0.1-cp38-cp38-win32.whl", hash = "sha256:5610a842621ff76c04b20b29cf5f809b131f241a19d4937971ba77dc99a7f330"}, + {file = "mmh3-5.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:de15739ac50776fe8aa1ef13f1be46a6ee1fbd45f6d0651084097eb2be0a5aa4"}, + {file = "mmh3-5.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:48e84cf3cc7e8c41bc07de72299a73b92d9e3cde51d97851420055b1484995f7"}, + {file = "mmh3-5.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6dd9dc28c2d168c49928195c2e29b96f9582a5d07bd690a28aede4cc07b0e696"}, + {file = "mmh3-5.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2771a1c56a3d4bdad990309cff5d0a8051f29c8ec752d001f97d6392194ae880"}, + {file = "mmh3-5.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5ff2a8322ba40951a84411550352fba1073ce1c1d1213bb7530f09aed7f8caf"}, + {file = "mmh3-5.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a16bd3ec90682c9e0a343e6bd4c778c09947c8c5395cdb9e5d9b82b2559efbca"}, + {file = "mmh3-5.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d45733a78d68b5b05ff4a823aea51fa664df1d3bf4929b152ff4fd6dea2dd69b"}, + {file = "mmh3-5.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:904285e83cedebc8873b0838ed54c20f7344120be26e2ca5a907ab007a18a7a0"}, + {file = "mmh3-5.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac4aeb1784e43df728034d0ed72e4b2648db1a69fef48fa58e810e13230ae5ff"}, + {file = "mmh3-5.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:cb3d4f751a0b8b4c8d06ef1c085216c8fddcc8b8c8d72445976b5167a40c6d1e"}, + {file = "mmh3-5.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:8021851935600e60c42122ed1176399d7692df338d606195cd599d228a04c1c6"}, + {file = "mmh3-5.0.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:6182d5924a5efc451900f864cbb021d7e8ad5d524816ca17304a0f663bc09bb5"}, + {file = "mmh3-5.0.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:5f30b834552a4f79c92e3d266336fb87fd92ce1d36dc6813d3e151035890abbd"}, + {file = "mmh3-5.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cd4383f35e915e06d077df27e04ffd3be7513ec6a9de2d31f430393f67e192a7"}, + {file = "mmh3-5.0.1-cp39-cp39-win32.whl", hash = "sha256:1455fb6b42665a97db8fc66e89a861e52b567bce27ed054c47877183f86ea6e3"}, + {file = "mmh3-5.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:9e26a0f4eb9855a143f5938a53592fa14c2d3b25801c2106886ab6c173982780"}, + {file = "mmh3-5.0.1-cp39-cp39-win_arm64.whl", hash = "sha256:0d0a35a69abdad7549c4030a714bb4ad07902edb3bbe61e1bbc403ded5d678be"}, + {file = "mmh3-5.0.1.tar.gz", hash = "sha256:7dab080061aeb31a6069a181f27c473a1f67933854e36a3464931f2716508896"}, ] [package.extras] -test = ["mypy (>=1.0)", "pytest (>=7.0.0)"] +benchmark = ["pymmh3 (==0.0.5)", "pyperf (==2.7.0)", "xxhash (==3.5.0)"] +docs = ["myst-parser (==4.0.0)", "shibuya (==2024.8.30)", "sphinx (==8.0.2)", "sphinx-copybutton (==0.5.2)"] +lint = ["black (==24.8.0)", "clang-format (==18.1.8)", "isort (==5.13.2)", "pylint (==3.2.7)"] +plot = ["matplotlib (==3.9.2)", "pandas (==2.2.2)"] +test = ["pytest (==8.3.3)", "pytest-sugar (==1.0.0)"] +type = ["mypy (==1.11.2)"] [[package]] name = "mock" @@ -5539,13 +5597,13 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] [[package]] name = "oci" -version = "2.133.0" +version = "2.135.0" description = "Oracle Cloud Infrastructure Python SDK" optional = false python-versions = "*" files = [ - {file = "oci-2.133.0-py3-none-any.whl", hash = "sha256:9706365481ca538c89b3a15e6b5c246801eccb06be831a7f21c40f2a2ee310a7"}, - {file = "oci-2.133.0.tar.gz", hash = "sha256:800418025bb98f587c65bbf89c6b6d61ef0f2249e0698d73439baf3251640b7f"}, + {file = "oci-2.135.0-py3-none-any.whl", hash = "sha256:c01f1d103ed034fa7ca2bceb297bf00e6f6c456d14a46b35ee9007b25f3ea397"}, + {file = "oci-2.135.0.tar.gz", hash = "sha256:6e28e6595264705d8fd0719045ffc4b23170e7fd2cd76a1c3aa25e4cdaa5883a"}, ] [package.dependencies] @@ -6059,40 +6117,53 @@ files = [ [[package]] name = "pandas" -version = "2.2.2" +version = "2.2.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" files = [ - {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, - {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"}, - {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"}, - {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"}, - {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"}, - {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99"}, - {file = "pandas-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772"}, - {file = "pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288"}, - {file = "pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151"}, - {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b"}, - {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee"}, - {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db"}, - {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"}, - {file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"}, - {file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"}, - {file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"}, - {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"}, - {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"}, - {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"}, - {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"}, - {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"}, - {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"}, - {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"}, - {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"}, - {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"}, - {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"}, - {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57"}, - {file = "pandas-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4"}, - {file = "pandas-2.2.2.tar.gz", hash = "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54"}, + {file = "pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5"}, + {file = "pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348"}, + {file = "pandas-2.2.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed"}, + {file = "pandas-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57"}, + {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42"}, + {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f"}, + {file = "pandas-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645"}, + {file = "pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039"}, + {file = "pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd"}, + {file = "pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698"}, + {file = "pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc"}, + {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3"}, + {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32"}, + {file = "pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5"}, + {file = "pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9"}, + {file = "pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4"}, + {file = "pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3"}, + {file = "pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319"}, + {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8"}, + {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a"}, + {file = "pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13"}, + {file = "pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015"}, + {file = "pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28"}, + {file = "pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0"}, + {file = "pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24"}, + {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659"}, + {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb"}, + {file = "pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d"}, + {file = "pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468"}, + {file = "pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18"}, + {file = "pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2"}, + {file = "pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4"}, + {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d"}, + {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a"}, + {file = "pandas-2.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39"}, + {file = "pandas-2.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5dbca4c1acd72e8eeef4753eeca07de9b1db4f398669d5994086f788a5d7cc30"}, + {file = "pandas-2.2.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8cd6d7cc958a3910f934ea8dbdf17b2364827bb4dafc38ce6eef6bb3d65ff09c"}, + {file = "pandas-2.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c"}, + {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31d0ced62d4ea3e231a9f228366919a5ea0b07440d9d4dac345376fd8e1477ea"}, + {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761"}, + {file = "pandas-2.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e"}, + {file = "pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667"}, ] [package.dependencies] @@ -6300,13 +6371,13 @@ xmp = ["defusedxml"] [[package]] name = "platformdirs" -version = "4.3.3" +version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.3.3-py3-none-any.whl", hash = "sha256:50a5450e2e84f44539718293cbb1da0a0885c9d14adf21b77bae4e66fc99d9b5"}, - {file = "platformdirs-4.3.3.tar.gz", hash = "sha256:d4e0b7d8ec176b341fb03cb11ca12d0276faa8c485f9cd218f613840463fc2c0"}, + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, ] [package.extras] @@ -6376,13 +6447,13 @@ tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "p [[package]] name = "posthog" -version = "3.6.5" +version = "3.6.6" description = "Integrate PostHog into any python application." optional = false python-versions = "*" files = [ - {file = "posthog-3.6.5-py2.py3-none-any.whl", hash = "sha256:f8b7c573826b061a1d22c9495169c38ebe83a1df2729f49c7129a9c23a02acf6"}, - {file = "posthog-3.6.5.tar.gz", hash = "sha256:7fd3ca809e15476c35f75d18cd6bba31395daf0a17b75242965c469fb6292510"}, + {file = "posthog-3.6.6-py2.py3-none-any.whl", hash = "sha256:38834fd7f0732582a20d4eb4674c8d5c088e464d14d1b3f8c176e389aecaa4ef"}, + {file = "posthog-3.6.6.tar.gz", hash = "sha256:1e04783293117109189ad7048f3eedbe21caff0e39bee5e2d47a93dd790fefac"}, ] [package.dependencies] @@ -6399,44 +6470,44 @@ test = ["coverage", "django", "flake8", "freezegun (==0.3.15)", "mock (>=2.0.0)" [[package]] name = "pox" -version = "0.3.4" +version = "0.3.5" description = "utilities for filesystem exploration and automated builds" optional = false python-versions = ">=3.8" files = [ - {file = "pox-0.3.4-py3-none-any.whl", hash = "sha256:651b8ae8a7b341b7bfd267f67f63106daeb9805f1ac11f323d5280d2da93fdb6"}, - {file = "pox-0.3.4.tar.gz", hash = "sha256:16e6eca84f1bec3828210b06b052adf04cf2ab20c22fd6fbef5f78320c9a6fed"}, + {file = "pox-0.3.5-py3-none-any.whl", hash = "sha256:9e82bcc9e578b43e80a99cad80f0d8f44f4d424f0ee4ee8d4db27260a6aa365a"}, + {file = "pox-0.3.5.tar.gz", hash = "sha256:8120ee4c94e950e6e0483e050a4f0e56076e590ba0a9add19524c254bd23c2d1"}, ] [[package]] name = "ppft" -version = "1.7.6.8" +version = "1.7.6.9" description = "distributed and parallel Python" optional = false python-versions = ">=3.8" files = [ - {file = "ppft-1.7.6.8-py3-none-any.whl", hash = "sha256:de2dd4b1b080923dd9627fbdea52649fd741c752fce4f3cf37e26f785df23d9b"}, - {file = "ppft-1.7.6.8.tar.gz", hash = "sha256:76a429a7d7b74c4d743f6dba8351e58d62b6432ed65df9fe204790160dab996d"}, + {file = "ppft-1.7.6.9-py3-none-any.whl", hash = "sha256:dab36548db5ca3055067fbe6b1a17db5fee29f3c366c579a9a27cebb52ed96f0"}, + {file = "ppft-1.7.6.9.tar.gz", hash = "sha256:73161c67474ea9d81d04bcdad166d399cff3f084d5d2dc21ebdd46c075bbc265"}, ] [package.extras] -dill = ["dill (>=0.3.8)"] +dill = ["dill (>=0.3.9)"] [[package]] name = "primp" -version = "0.6.2" +version = "0.6.3" description = "HTTP client that can impersonate web browsers, mimicking their headers and `TLS/JA3/JA4/HTTP2` fingerprints" optional = false python-versions = ">=3.8" files = [ - {file = "primp-0.6.2-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:4a35d441462a55d9a9525bf170e2ffd2fcb3db6039b23e802859fa22c18cdd51"}, - {file = "primp-0.6.2-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:f67ccade95bdbca3cf9b96b93aa53f9617d85ddbf988da4e9c523aa785fd2d54"}, - {file = "primp-0.6.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8074b93befaf36567e4cf3d4a1a8cd6ab9cc6e4dd4ff710650678daa405aee71"}, - {file = "primp-0.6.2-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:7d3e2a3f8c6262e9b883651b79c4ff2b7677a76f47293a139f541c9ea333ce3b"}, - {file = "primp-0.6.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:a460ea389371c6d04839b4b50b5805d99da8ebe281a2e8b534d27377c6d44f0e"}, - {file = "primp-0.6.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5b6b27e89d3c05c811aff0e4fde7a36d6957b15b3112f4ce28b6b99e8ca1e725"}, - {file = "primp-0.6.2-cp38-abi3-win_amd64.whl", hash = "sha256:1006a40a85f88a4c5222094813a1ebc01f85a63e9a33d2c443288c0720bed321"}, - {file = "primp-0.6.2.tar.gz", hash = "sha256:5a96a6b65195a8a989157e67d23bd171c49be238654e02bdf1b1fda36cbcc068"}, + {file = "primp-0.6.3-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bdbe6a7cdaaf5c9ed863432a941f4a75bd4c6ff626cbc8d32fc232793c70ba06"}, + {file = "primp-0.6.3-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:eeb53eb987bdcbcd85740633470255cab887d921df713ffa12a36a13366c9cdb"}, + {file = "primp-0.6.3-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78da53d3c92a8e3f05bd3286ac76c291f1b6fe5e08ea63b7ba92b0f9141800bb"}, + {file = "primp-0.6.3-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:86337b44deecdac752bd8112909987fc9fa9b894f30191c80a164dc8f895da53"}, + {file = "primp-0.6.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d3cd9a22b97f3eae42b2a5fb99f00480daf4cd6d9b139e05b0ffb03f7cc037f3"}, + {file = "primp-0.6.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7732bec917e2d3c48a31cdb92e1250f4ad6203a1aa4f802bd9abd84f2286a1e0"}, + {file = "primp-0.6.3-cp38-abi3-win_amd64.whl", hash = "sha256:1e4113c34b86c676ae321af185f03a372caef3ee009f1682c2d62e30ec87348c"}, + {file = "primp-0.6.3.tar.gz", hash = "sha256:17d30ebe26864defad5232dbbe1372e80483940012356e1f68846bb182282039"}, ] [package.extras] @@ -6444,13 +6515,13 @@ dev = ["certifi", "pytest (>=8.1.1)"] [[package]] name = "prompt-toolkit" -version = "3.0.47" +version = "3.0.48" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.47-py3-none-any.whl", hash = "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10"}, - {file = "prompt_toolkit-3.0.47.tar.gz", hash = "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360"}, + {file = "prompt_toolkit-3.0.48-py3-none-any.whl", hash = "sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e"}, + {file = "prompt_toolkit-3.0.48.tar.gz", hash = "sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90"}, ] [package.dependencies] @@ -6475,22 +6546,22 @@ testing = ["google-api-core (>=1.31.5)"] [[package]] name = "protobuf" -version = "4.25.4" +version = "4.25.5" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "protobuf-4.25.4-cp310-abi3-win32.whl", hash = "sha256:db9fd45183e1a67722cafa5c1da3e85c6492a5383f127c86c4c4aa4845867dc4"}, - {file = "protobuf-4.25.4-cp310-abi3-win_amd64.whl", hash = "sha256:ba3d8504116a921af46499471c63a85260c1a5fc23333154a427a310e015d26d"}, - {file = "protobuf-4.25.4-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:eecd41bfc0e4b1bd3fa7909ed93dd14dd5567b98c941d6c1ad08fdcab3d6884b"}, - {file = "protobuf-4.25.4-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:4c8a70fdcb995dcf6c8966cfa3a29101916f7225e9afe3ced4395359955d3835"}, - {file = "protobuf-4.25.4-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:3319e073562e2515c6ddc643eb92ce20809f5d8f10fead3332f71c63be6a7040"}, - {file = "protobuf-4.25.4-cp38-cp38-win32.whl", hash = "sha256:7e372cbbda66a63ebca18f8ffaa6948455dfecc4e9c1029312f6c2edcd86c4e1"}, - {file = "protobuf-4.25.4-cp38-cp38-win_amd64.whl", hash = "sha256:051e97ce9fa6067a4546e75cb14f90cf0232dcb3e3d508c448b8d0e4265b61c1"}, - {file = "protobuf-4.25.4-cp39-cp39-win32.whl", hash = "sha256:90bf6fd378494eb698805bbbe7afe6c5d12c8e17fca817a646cd6a1818c696ca"}, - {file = "protobuf-4.25.4-cp39-cp39-win_amd64.whl", hash = "sha256:ac79a48d6b99dfed2729ccccee547b34a1d3d63289c71cef056653a846a2240f"}, - {file = "protobuf-4.25.4-py3-none-any.whl", hash = "sha256:bfbebc1c8e4793cfd58589acfb8a1026be0003e852b9da7db5a4285bde996978"}, - {file = "protobuf-4.25.4.tar.gz", hash = "sha256:0dc4a62cc4052a036ee2204d26fe4d835c62827c855c8a03f29fe6da146b380d"}, + {file = "protobuf-4.25.5-cp310-abi3-win32.whl", hash = "sha256:5e61fd921603f58d2f5acb2806a929b4675f8874ff5f330b7d6f7e2e784bbcd8"}, + {file = "protobuf-4.25.5-cp310-abi3-win_amd64.whl", hash = "sha256:4be0571adcbe712b282a330c6e89eae24281344429ae95c6d85e79e84780f5ea"}, + {file = "protobuf-4.25.5-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:b2fde3d805354df675ea4c7c6338c1aecd254dfc9925e88c6d31a2bcb97eb173"}, + {file = "protobuf-4.25.5-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:919ad92d9b0310070f8356c24b855c98df2b8bd207ebc1c0c6fcc9ab1e007f3d"}, + {file = "protobuf-4.25.5-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:fe14e16c22be926d3abfcb500e60cab068baf10b542b8c858fa27e098123e331"}, + {file = "protobuf-4.25.5-cp38-cp38-win32.whl", hash = "sha256:98d8d8aa50de6a2747efd9cceba361c9034050ecce3e09136f90de37ddba66e1"}, + {file = "protobuf-4.25.5-cp38-cp38-win_amd64.whl", hash = "sha256:b0234dd5a03049e4ddd94b93400b67803c823cfc405689688f59b34e0742381a"}, + {file = "protobuf-4.25.5-cp39-cp39-win32.whl", hash = "sha256:abe32aad8561aa7cc94fc7ba4fdef646e576983edb94a73381b03c53728a626f"}, + {file = "protobuf-4.25.5-cp39-cp39-win_amd64.whl", hash = "sha256:7a183f592dc80aa7c8da7ad9e55091c4ffc9497b3054452d629bb85fa27c2a45"}, + {file = "protobuf-4.25.5-py3-none-any.whl", hash = "sha256:0aebecb809cae990f8129ada5ca273d9d670b76d9bfc9b1809f0a9c02b7dbf41"}, + {file = "protobuf-4.25.5.tar.gz", hash = "sha256:7f8249476b4a9473645db7f8ab42b02fe1488cbe5fb72fddd445e0665afd8584"}, ] [[package]] @@ -6644,19 +6715,6 @@ files = [ {file = "pyarrow-17.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:392bc9feabc647338e6c89267635e111d71edad5fcffba204425a7c8d13610d7"}, {file = "pyarrow-17.0.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:af5ff82a04b2171415f1410cff7ebb79861afc5dae50be73ce06d6e870615204"}, {file = "pyarrow-17.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:edca18eaca89cd6382dfbcff3dd2d87633433043650c07375d095cd3517561d8"}, - {file = "pyarrow-17.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c7916bff914ac5d4a8fe25b7a25e432ff921e72f6f2b7547d1e325c1ad9d155"}, - {file = "pyarrow-17.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f553ca691b9e94b202ff741bdd40f6ccb70cdd5fbf65c187af132f1317de6145"}, - {file = "pyarrow-17.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:0cdb0e627c86c373205a2f94a510ac4376fdc523f8bb36beab2e7f204416163c"}, - {file = "pyarrow-17.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:d7d192305d9d8bc9082d10f361fc70a73590a4c65cf31c3e6926cd72b76bc35c"}, - {file = "pyarrow-17.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:02dae06ce212d8b3244dd3e7d12d9c4d3046945a5933d28026598e9dbbda1fca"}, - {file = "pyarrow-17.0.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:13d7a460b412f31e4c0efa1148e1d29bdf18ad1411eb6757d38f8fbdcc8645fb"}, - {file = "pyarrow-17.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b564a51fbccfab5a04a80453e5ac6c9954a9c5ef2890d1bcf63741909c3f8df"}, - {file = "pyarrow-17.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32503827abbc5aadedfa235f5ece8c4f8f8b0a3cf01066bc8d29de7539532687"}, - {file = "pyarrow-17.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a155acc7f154b9ffcc85497509bcd0d43efb80d6f733b0dc3bb14e281f131c8b"}, - {file = "pyarrow-17.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:dec8d129254d0188a49f8a1fc99e0560dc1b85f60af729f47de4046015f9b0a5"}, - {file = "pyarrow-17.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:a48ddf5c3c6a6c505904545c25a4ae13646ae1f8ba703c4df4a1bfe4f4006bda"}, - {file = "pyarrow-17.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:42bf93249a083aca230ba7e2786c5f673507fa97bbd9725a1e2754715151a204"}, - {file = "pyarrow-17.0.0.tar.gz", hash = "sha256:4beca9521ed2c0921c1023e68d097d0299b62c362639ea315572a58f3f50fd28"}, ] [package.dependencies] @@ -6957,13 +7015,13 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] name = "pymilvus" -version = "2.4.6" +version = "2.4.7" description = "Python Sdk for Milvus" optional = false python-versions = ">=3.8" files = [ - {file = "pymilvus-2.4.6-py3-none-any.whl", hash = "sha256:b4c43472edc313b845d313be50610e19054e6954b2c5c3b515565c596c2d3d97"}, - {file = "pymilvus-2.4.6.tar.gz", hash = "sha256:6ac3eb91c92cc01bbe444fe83f895f02d7b2546d96ac67998630bf31ac074d66"}, + {file = "pymilvus-2.4.7-py3-none-any.whl", hash = "sha256:1e5d377bd40fa7eb459d3958dbd96201758f5cf997d41eb3d2d169d0b7fa462e"}, + {file = "pymilvus-2.4.7.tar.gz", hash = "sha256:9ef460b940782a42e1b7b8ae0da03d8cc02d9d80044d13f4b689a7c935ec7aa7"}, ] [package.dependencies] @@ -7082,28 +7140,28 @@ files = [ [[package]] name = "pyproject-hooks" -version = "1.1.0" +version = "1.2.0" description = "Wrappers to call pyproject.toml-based build backend hooks." optional = false python-versions = ">=3.7" files = [ - {file = "pyproject_hooks-1.1.0-py3-none-any.whl", hash = "sha256:7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2"}, - {file = "pyproject_hooks-1.1.0.tar.gz", hash = "sha256:4b37730834edbd6bd37f26ece6b44802fb1c1ee2ece0e54ddff8bfc06db86965"}, + {file = "pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913"}, + {file = "pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8"}, ] [[package]] name = "pyreadline3" -version = "3.5.2" +version = "3.5.4" description = "A python implementation of GNU readline." optional = false python-versions = ">=3.8" files = [ - {file = "pyreadline3-3.5.2-py3-none-any.whl", hash = "sha256:a87d56791e2965b2b187e2ea33dcf664600842c997c0623c95cf8ef07db83de9"}, - {file = "pyreadline3-3.5.2.tar.gz", hash = "sha256:ba82292e52c5a3bb256b291af0c40b457c1e8699cac9a873abbcaac8aef3a1bb"}, + {file = "pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6"}, + {file = "pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7"}, ] [package.extras] -dev = ["build", "flake8", "pytest", "twine"] +dev = ["build", "flake8", "mypy", "pytest", "twine"] [[package]] name = "pytest" @@ -7149,21 +7207,21 @@ histogram = ["pygal", "pygaljs"] [[package]] name = "pytest-env" -version = "1.1.4" +version = "1.1.5" description = "pytest plugin that allows you to add environment variables." optional = false python-versions = ">=3.8" files = [ - {file = "pytest_env-1.1.4-py3-none-any.whl", hash = "sha256:a4212056d4d440febef311a98fdca56c31256d58fb453d103cba4e8a532b721d"}, - {file = "pytest_env-1.1.4.tar.gz", hash = "sha256:86653658da8f11c6844975db955746c458a9c09f1e64957603161e2ff93f5133"}, + {file = "pytest_env-1.1.5-py3-none-any.whl", hash = "sha256:ce90cf8772878515c24b31cd97c7fa1f4481cd68d588419fd45f10ecaee6bc30"}, + {file = "pytest_env-1.1.5.tar.gz", hash = "sha256:91209840aa0e43385073ac464a554ad2947cc2fd663a9debf88d03b01e0cc1cf"}, ] [package.dependencies] -pytest = ">=8.3.2" +pytest = ">=8.3.3" tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} [package.extras] -test = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "pytest-mock (>=3.14)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "pytest-mock (>=3.14)"] [[package]] name = "pytest-mock" @@ -7550,123 +7608,103 @@ dev = ["pytest"] [[package]] name = "rapidfuzz" -version = "3.9.7" +version = "3.10.0" description = "rapid fuzzy string matching" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "rapidfuzz-3.9.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ccf68e30b80e903f2309f90a438dbd640dd98e878eeb5ad361a288051ee5b75c"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:696a79018ef989bf1c9abd9005841cee18005ccad4748bad8a4c274c47b6241a"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4eebf6c93af0ae866c22b403a84747580bb5c10f0d7b51c82a87f25405d4dcb"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e9125377fa3d21a8abd4fbdbcf1c27be73e8b1850f0b61b5b711364bf3b59db"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c12d180b17a22d107c8747de9c68d0b9c1d15dcda5445ff9bf9f4ccfb67c3e16"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1318d42610c26dcd68bd3279a1bf9e3605377260867c9a8ed22eafc1bd93a7c"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd5fa6e3c6e0333051c1f3a49f0807b3366f4131c8d6ac8c3e05fd0d0ce3755c"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fcf79b686962d7bec458a0babc904cb4fa319808805e036b9d5a531ee6b9b835"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8b01153c7466d0bad48fba77a303d5a768e66f24b763853469f47220b3de4661"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:94baaeea0b4f8632a6da69348b1e741043eba18d4e3088d674d3f76586b6223d"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6c5b32875646cb7f60c193ade99b2e4b124f19583492115293cd00f6fb198b17"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:110b6294396bc0a447648627479c9320f095c2034c0537f687592e0f58622638"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-win32.whl", hash = "sha256:3445a35c4c8d288f2b2011eb61bce1227c633ce85a3154e727170f37c0266bb2"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-win_amd64.whl", hash = "sha256:0d1415a732ee75e74a90af12020b77a0b396b36c60afae1bde3208a78cd2c9fc"}, - {file = "rapidfuzz-3.9.7-cp310-cp310-win_arm64.whl", hash = "sha256:836f4d88b8bd0fff2ebe815dcaab8aa6c8d07d1d566a7e21dd137cf6fe11ed5b"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d098ce6162eb5e48fceb0745455bc950af059df6113eec83e916c129fca11408"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:048d55d36c02c6685a2b2741688503c3d15149694506655b6169dcfd3b6c2585"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c33211cfff9aec425bb1bfedaf94afcf337063aa273754f22779d6dadebef4c2"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6d9db2fa4e9be171e9bb31cf2d2575574774966b43f5b951062bb2e67885852"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4e049d5ad61448c9a020d1061eba20944c4887d720c4069724beb6ea1692507"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cfa74aac64c85898b93d9c80bb935a96bf64985e28d4ee0f1a3d1f3bf11a5106"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:965693c2e9efd425b0f059f5be50ef830129f82892fa1858e220e424d9d0160f"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8501000a5eb8037c4b56857724797fe5a8b01853c363de91c8d0d0ad56bef319"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d92c552c6b7577402afdd547dcf5d31ea6c8ae31ad03f78226e055cfa37f3c6"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1ee2086f490cb501d86b7e386c1eb4e3a0ccbb0c99067089efaa8c79012c8952"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1de91e7fd7f525e10ea79a6e62c559d1b0278ec097ad83d9da378b6fab65a265"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a4da514d13f4433e16960a17f05b67e0af30ac771719c9a9fb877e5004f74477"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-win32.whl", hash = "sha256:a40184c67db8252593ec518e17fb8a6e86d7259dc9f2d6c0bf4ff4db8cf1ad4b"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-win_amd64.whl", hash = "sha256:c4f28f1930b09a2c300357d8465b388cecb7e8b2f454a5d5425561710b7fd07f"}, - {file = "rapidfuzz-3.9.7-cp311-cp311-win_arm64.whl", hash = "sha256:675b75412a943bb83f1f53e2e54fd18c80ef15ed642dc6eb0382d1949419d904"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1ef6a1a8f0b12f8722f595f15c62950c9a02d5abc64742561299ffd49f6c6944"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:32532af1d70c6ec02ea5ac7ee2766dfff7c8ae8c761abfe8da9e527314e634e8"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae1a38bade755aa9dd95a81cda949e1bf9cd92b79341ccc5e2189c9e7bdfc5ec"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d73ee2df41224c87336448d279b5b6a3a75f36e41dd3dcf538c0c9cce36360d8"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be3a1fc3e2ab3bdf93dc0c83c00acca8afd2a80602297d96cf4a0ba028333cdf"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:603f48f621272a448ff58bb556feb4371252a02156593303391f5c3281dfaeac"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:268f8e1ca50fc61c0736f3fe9d47891424adf62d96ed30196f30f4bd8216b41f"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f8bf3f0d02935751d8660abda6044821a861f6229f7d359f98bcdcc7e66c39b"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b997ff3b39d4cee9fb025d6c46b0a24bd67595ce5a5b652a97fb3a9d60beb651"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ca66676c8ef6557f9b81c5b2b519097817a7c776a6599b8d6fcc3e16edd216fe"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:35d3044cb635ca6b1b2b7b67b3597bd19f34f1753b129eb6d2ae04cf98cd3945"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5a93c9e60904cb76e7aefef67afffb8b37c4894f81415ed513db090f29d01101"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-win32.whl", hash = "sha256:579d107102c0725f7c79b4e79f16d3cf4d7c9208f29c66b064fa1fd4641d5155"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-win_amd64.whl", hash = "sha256:953b3780765c8846866faf891ee4290f6a41a6dacf4fbcd3926f78c9de412ca6"}, - {file = "rapidfuzz-3.9.7-cp312-cp312-win_arm64.whl", hash = "sha256:7c20c1474b068c4bd45bf2fd0ad548df284f74e9a14a68b06746c56e3aa8eb70"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fde81b1da9a947f931711febe2e2bee694e891f6d3e6aa6bc02c1884702aea19"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:47e92c155a14f44511ea8ebcc6bc1535a1fe8d0a7d67ad3cc47ba61606df7bcf"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8772b745668260c5c4d069c678bbaa68812e6c69830f3771eaad521af7bc17f8"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:578302828dd97ee2ba507d2f71d62164e28d2fc7bc73aad0d2d1d2afc021a5d5"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc3e6081069eea61593f1d6839029da53d00c8c9b205c5534853eaa3f031085c"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0b1c2d504eddf97bc0f2eba422c8915576dbf025062ceaca2d68aecd66324ad9"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb76e5a21034f0307c51c5a2fc08856f698c53a4c593b17d291f7d6e9d09ca3"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d4ba2318ef670ce505f42881a5d2af70f948124646947341a3c6ccb33cd70369"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:057bb03f39e285047d7e9412e01ecf31bb2d42b9466a5409d715d587460dd59b"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a8feac9006d5c9758438906f093befffc4290de75663dbb2098461df7c7d28dd"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:95b8292383e717e10455f2c917df45032b611141e43d1adf70f71b1566136b11"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e9fbf659537d246086d0297628b3795dc3e4a384101ecc01e5791c827b8d7345"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-win32.whl", hash = "sha256:1dc516ac6d32027be2b0196bedf6d977ac26debd09ca182376322ad620460feb"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-win_amd64.whl", hash = "sha256:b4f86e09d3064dca0b014cd48688964036a904a2d28048f00c8f4640796d06a8"}, - {file = "rapidfuzz-3.9.7-cp313-cp313-win_arm64.whl", hash = "sha256:19c64d8ddb2940b42a4567b23f1681af77f50a5ff6c9b8e85daba079c210716e"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fbda3dd68d8b28ccb20ffb6f756fefd9b5ba570a772bedd7643ed441f5793308"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2379e0b2578ad3ac7004f223251550f08bca873ff76c169b09410ec562ad78d8"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d1eff95362f993b0276fd3839aee48625b09aac8938bb0c23b40d219cba5dc5"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd9360e30041690912525a210e48a897b49b230768cc8af1c702e5395690464f"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a93cd834b3c315ab437f0565ee3a2f42dd33768dc885ccbabf9710b131cf70d2"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ff196996240db7075f62c7bc4506f40a3c80cd4ae3ab0e79ac6892283a90859"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:948dcee7aaa1cd14358b2a7ef08bf0be42bf89049c3a906669874a715fc2c937"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d95751f505a301af1aaf086c19f34536056d6c8efa91b2240de532a3db57b543"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:90db86fa196eecf96cb6db09f1083912ea945c50c57188039392d810d0b784e1"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:3171653212218a162540a3c8eb8ae7d3dcc8548540b69eaecaf3b47c14d89c90"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:36dd6e820379c37a1ffefc8a52b648758e867cd9d78ee5b5dc0c9a6a10145378"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:7b702de95666a1f7d5c6b47eacadfe2d2794af3742d63d2134767d13e5d1c713"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-win32.whl", hash = "sha256:9030e7238c0df51aed5c9c5ed8eee2bdd47a2ae788e562c1454af2851c3d1906"}, - {file = "rapidfuzz-3.9.7-cp38-cp38-win_amd64.whl", hash = "sha256:f847fb0fbfb72482b1c05c59cbb275c58a55b73708a7f77a83f8035ee3c86497"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:97f2ce529d2a70a60c290f6ab269a2bbf1d3b47b9724dccc84339b85f7afb044"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e2957fdad10bb83b1982b02deb3604a3f6911a5e545f518b59c741086f92d152"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d5262383634626eb45c536017204b8163a03bc43bda880cf1bdd7885db9a163"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:364587827d7cbd41afa0782adc2d2d19e3f07d355b0750a02a8e33ad27a9c368"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecc24af7f905f3d6efb371a01680116ffea8d64e266618fb9ad1602a9b4f7934"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dc86aa6b29d174713c5f4caac35ffb7f232e3e649113e8d13812b35ab078228"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3dcfbe7266e74a707173a12a7b355a531f2dcfbdb32f09468e664330da14874"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b23806fbdd6b510ba9ac93bb72d503066263b0fba44b71b835be9f063a84025f"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:5551d68264c1bb6943f542da83a4dc8940ede52c5847ef158698799cc28d14f5"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:13d8675a1fa7e2b19650ca7ef9a6ec01391d4bb12ab9e0793e8eb024538b4a34"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9b6a5de507b9be6de688dae40143b656f7a93b10995fb8bd90deb555e7875c60"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:111a20a3c090cf244d9406e60500b6c34b2375ba3a5009e2b38fd806fe38e337"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-win32.whl", hash = "sha256:22589c0b8ccc6c391ce7f776c93a8c92c96ab8d34e1a19f1bd2b12a235332632"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-win_amd64.whl", hash = "sha256:6f83221db5755b8f34222e40607d87f1176a8d5d4dbda4a55a0f0b67d588a69c"}, - {file = "rapidfuzz-3.9.7-cp39-cp39-win_arm64.whl", hash = "sha256:3665b92e788578c3bb334bd5b5fa7ee1a84bafd68be438e3110861d1578c63a0"}, - {file = "rapidfuzz-3.9.7-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:d7df9c2194c7ec930b33c991c55dbd0c10951bd25800c0b7a7b571994ebbced5"}, - {file = "rapidfuzz-3.9.7-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:68bd888eafd07b09585dcc8bc2716c5ecdb7eed62827470664d25588982b2873"}, - {file = "rapidfuzz-3.9.7-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1230e0f9026851a6a432beaa0ce575dda7b39fe689b576f99a0704fbb81fc9c"}, - {file = "rapidfuzz-3.9.7-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3b36e1c61b796ae1777f3e9e11fd39898b09d351c9384baf6e3b7e6191d8ced"}, - {file = "rapidfuzz-3.9.7-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9dba13d86806fcf3fe9c9919f58575e0090eadfb89c058bde02bcc7ab24e4548"}, - {file = "rapidfuzz-3.9.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1f1a33e84056b7892c721d84475d3bde49a145126bc4c6efe0d6d0d59cb31c29"}, - {file = "rapidfuzz-3.9.7-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3492c7a42b7fa9f0051d7fcce9893e95ed91c97c9ec7fb64346f3e070dd318ed"}, - {file = "rapidfuzz-3.9.7-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:ece45eb2af8b00f90d10f7419322e8804bd42fb1129026f9bfe712c37508b514"}, - {file = "rapidfuzz-3.9.7-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcd14cf4876f04b488f6e54a7abd3e9b31db5f5a6aba0ce90659917aaa8c088"}, - {file = "rapidfuzz-3.9.7-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:521c58c72ed8a612b25cda378ff10dee17e6deb4ee99a070b723519a345527b9"}, - {file = "rapidfuzz-3.9.7-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18669bb6cdf7d40738526d37e550df09ba065b5a7560f3d802287988b6cb63cf"}, - {file = "rapidfuzz-3.9.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7abe2dbae81120a64bb4f8d3fcafe9122f328c9f86d7f327f174187a5af4ed86"}, - {file = "rapidfuzz-3.9.7-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a3c0783910911f4f24655826d007c9f4360f08107410952c01ee3df98c713eb2"}, - {file = "rapidfuzz-3.9.7-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:03126f9a040ff21d2a110610bfd6b93b79377ce8b4121edcb791d61b7df6eec5"}, - {file = "rapidfuzz-3.9.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:591908240f4085e2ade5b685c6e8346e2ed44932cffeaac2fb32ddac95b55c7f"}, - {file = "rapidfuzz-3.9.7-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9012d86c6397edbc9da4ac0132de7f8ee9d6ce857f4194d5684c4ddbcdd1c5c"}, - {file = "rapidfuzz-3.9.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df596ddd3db38aa513d4c0995611267b3946e7cbe5a8761b50e9306dfec720ee"}, - {file = "rapidfuzz-3.9.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3ed5adb752f4308fcc8f4fb6f8eb7aa4082f9d12676fda0a74fa5564242a8107"}, - {file = "rapidfuzz-3.9.7.tar.gz", hash = "sha256:f1c7296534c1afb6f495aa95871f14ccdc197c6db42965854e483100df313030"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:884453860de029380dded8f3c1918af2d8eb5adf8010261645c7e5c88c2b5428"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:718c9bd369288aca5fa929df6dbf66fdbe9768d90940a940c0b5cdc96ade4309"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a68e3724b7dab761c01816aaa64b0903734d999d5589daf97c14ef5cc0629a8e"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1af60988d47534246d9525f77288fdd9de652608a4842815d9018570b959acc6"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3084161fc3e963056232ef8d937449a2943852e07101f5a136c8f3cfa4119217"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6cd67d3d017296d98ff505529104299f78433e4b8af31b55003d901a62bbebe9"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b11a127ac590fc991e8a02c2d7e1ac86e8141c92f78546f18b5c904064a0552c"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:aadce42147fc09dcef1afa892485311e824c050352e1aa6e47f56b9b27af4cf0"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b54853c2371bf0e38d67da379519deb6fbe70055efb32f6607081641af3dc752"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ce19887268e90ee81a3957eef5e46a70ecc000713796639f83828b950343f49e"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:f39a2a5ded23b9b9194ec45740dce57177b80f86c6d8eba953d3ff1a25c97766"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0ec338d5f4ad8d9339a88a08db5c23e7f7a52c2b2a10510c48a0cef1fb3f0ddc"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-win32.whl", hash = "sha256:56fd15ea8f4c948864fa5ebd9261c67cf7b89a1c517a0caef4df75446a7af18c"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:43dfc5e733808962a822ff6d9c29f3039a3cfb3620706f5953e17cfe4496724c"}, + {file = "rapidfuzz-3.10.0-cp310-cp310-win_arm64.whl", hash = "sha256:ae7966f205b5a7fde93b44ca8fed37c1c8539328d7f179b1197de34eceaceb5f"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bb0013795b40db5cf361e6f21ee7cda09627cf294977149b50e217d7fe9a2f03"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:69ef5b363afff7150a1fbe788007e307b9802a2eb6ad92ed51ab94e6ad2674c6"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c582c46b1bb0b19f1a5f4c1312f1b640c21d78c371a6615c34025b16ee56369b"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:288f6f6e7410cacb115fb851f3f18bf0e4231eb3f6cb5bd1cec0e7b25c4d039d"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9e29a13d2fd9be3e7d8c26c7ef4ba60b5bc7efbc9dbdf24454c7e9ebba31768"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea2da0459b951ee461bd4e02b8904890bd1c4263999d291c5cd01e6620177ad4"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:457827ba82261aa2ae6ac06a46d0043ab12ba7216b82d87ae1434ec0f29736d6"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5d350864269d56f51ab81ab750c9259ae5cad3152c0680baef143dcec92206a1"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a9b8f51e08c3f983d857c3889930af9ddecc768453822076683664772d87e374"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7f3a6aa6e70fc27e4ff5c479f13cc9fc26a56347610f5f8b50396a0d344c5f55"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:803f255f10d63420979b1909ef976e7d30dec42025c9b067fc1d2040cc365a7e"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2026651761bf83a0f31495cc0f70840d5c0d54388f41316e3f9cb51bd85e49a5"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-win32.whl", hash = "sha256:4df75b3ebbb8cfdb9bf8b213b168620b88fd92d0c16a8bc9f9234630b282db59"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f9f0bbfb6787b97c51516f3ccf97737d504db5d239ad44527673b81f598b84ab"}, + {file = "rapidfuzz-3.10.0-cp311-cp311-win_arm64.whl", hash = "sha256:10fdad800441b9c97d471a937ba7d42625f1b530db05e572f1cb7d401d95c893"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7dc87073ba3a40dd65591a2100aa71602107443bf10770579ff9c8a3242edb94"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a425a0a868cf8e9c6e93e1cda4b758cdfd314bb9a4fc916c5742c934e3613480"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86d5d1d75e61df060c1e56596b6b0a4422a929dff19cc3dbfd5eee762c86b61"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34f213d59219a9c3ca14e94a825f585811a68ac56b4118b4dc388b5b14afc108"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96ad46f5f56f70fab2be9e5f3165a21be58d633b90bf6e67fc52a856695e4bcf"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9178277f72d144a6c7704d7ae7fa15b7b86f0f0796f0e1049c7b4ef748a662ef"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76a35e9e19a7c883c422ffa378e9a04bc98cb3b29648c5831596401298ee51e6"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8a6405d34c394c65e4f73a1d300c001f304f08e529d2ed6413b46ee3037956eb"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bd393683129f446a75d8634306aed7e377627098a1286ff3af2a4f1736742820"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b0445fa9880ead81f5a7d0efc0b9c977a947d8052c43519aceeaf56eabaf6843"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:c50bc308fa29767ed8f53a8d33b7633a9e14718ced038ed89d41b886e301da32"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e89605afebbd2d4b045bccfdc12a14b16fe8ccbae05f64b4b4c64a97dad1c891"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-win32.whl", hash = "sha256:2db9187f3acf3cd33424ecdbaad75414c298ecd1513470df7bda885dcb68cc15"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:50e3d0c72ea15391ba9531ead7f2068a67c5b18a6a365fef3127583aaadd1725"}, + {file = "rapidfuzz-3.10.0-cp312-cp312-win_arm64.whl", hash = "sha256:9eac95b4278bd53115903d89118a2c908398ee8bdfd977ae844f1bd2b02b917c"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fe5231e8afd069c742ac5b4f96344a0fe4aff52df8e53ef87faebf77f827822c"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:886882367dbc985f5736356105798f2ae6e794e671fc605476cbe2e73838a9bb"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b33e13e537e3afd1627d421a142a12bbbe601543558a391a6fae593356842f6e"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:094c26116d55bf9c53abd840d08422f20da78ec4c4723e5024322321caedca48"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:545fc04f2d592e4350f59deb0818886c1b444ffba3bec535b4fbb97191aaf769"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:916a6abf3632e592b937c3d04c00a6efadd8fd30539cdcd4e6e4d92be7ca5d90"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb6ec40cef63b1922083d33bfef2f91fc0b0bc07b5b09bfee0b0f1717d558292"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c77a7330dd15c7eb5fd3631dc646fc96327f98db8181138766bd14d3e905f0ba"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:949b5e9eeaa4ecb4c7e9c2a4689dddce60929dd1ff9c76a889cdbabe8bbf2171"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b5363932a5aab67010ae1a6205c567d1ef256fb333bc23c27582481606be480c"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:5dd6eec15b13329abe66cc241b484002ecb0e17d694491c944a22410a6a9e5e2"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79e7f98525b60b3c14524e0a4e1fedf7654657b6e02eb25f1be897ab097706f3"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-win32.whl", hash = "sha256:d29d1b9857c65f8cb3a29270732e1591b9bacf89de9d13fa764f79f07d8f1fd2"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:fa9720e56663cc3649d62b4b5f3145e94b8f5611e8a8e1b46507777249d46aad"}, + {file = "rapidfuzz-3.10.0-cp313-cp313-win_arm64.whl", hash = "sha256:eda4c661e68dddd56c8fbfe1ca35e40dd2afd973f7ebb1605f4d151edc63dff8"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cffbc50e0767396ed483900900dd58ce4351bc0d40e64bced8694bd41864cc71"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c038b9939da3035afb6cb2f465f18163e8f070aba0482923ecff9443def67178"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca366c2e2a54e2f663f4529b189fdeb6e14d419b1c78b754ec1744f3c01070d4"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c4c82b1689b23b1b5e6a603164ed2be41b6f6de292a698b98ba2381e889eb9d"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98f6ebe28831a482981ecfeedc8237047878424ad0c1add2c7f366ba44a20452"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4bd1a7676ee2a4c8e2f7f2550bece994f9f89e58afb96088964145a83af7408b"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec9139baa3f85b65adc700eafa03ed04995ca8533dd56c924f0e458ffec044ab"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:26de93e6495078b6af4c4d93a42ca067b16cc0e95699526c82ab7d1025b4d3bf"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f3a0bda83c18195c361b5500377d0767749f128564ca95b42c8849fd475bb327"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:63e4c175cbce8c3adc22dca5e6154588ae673f6c55374d156f3dac732c88d7de"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4dd3d8443970eaa02ab5ae45ce584b061f2799cd9f7e875190e2617440c1f9d4"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e5ddb2388610799fc46abe389600625058f2a73867e63e20107c5ad5ffa57c47"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-win32.whl", hash = "sha256:2e9be5d05cd960914024412b5406fb75a82f8562f45912ff86255acbfdbfb78e"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:47aca565a39c9a6067927871973ca827023e8b65ba6c5747f4c228c8d7ddc04f"}, + {file = "rapidfuzz-3.10.0-cp39-cp39-win_arm64.whl", hash = "sha256:b0732343cdc4273b5921268026dd7266f75466eb21873cb7635a200d9d9c3fac"}, + {file = "rapidfuzz-3.10.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f744b5eb1469bf92dd143d36570d2bdbbdc88fe5cb0b5405e53dd34f479cbd8a"}, + {file = "rapidfuzz-3.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b67cc21a14327a0eb0f47bc3d7e59ec08031c7c55220ece672f9476e7a8068d3"}, + {file = "rapidfuzz-3.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fe5783676f0afba4a522c80b15e99dbf4e393c149ab610308a8ef1f04c6bcc8"}, + {file = "rapidfuzz-3.10.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4688862f957c8629d557d084f20b2d803f8738b6c4066802a0b1cc472e088d9"}, + {file = "rapidfuzz-3.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20bd153aacc244e4c907d772c703fea82754c4db14f8aa64d75ff81b7b8ab92d"}, + {file = "rapidfuzz-3.10.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:50484d563f8bfa723c74c944b0bb15b9e054db9c889348c8c307abcbee75ab92"}, + {file = "rapidfuzz-3.10.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5897242d455461f2c5b82d7397b29341fd11e85bf3608a522177071044784ee8"}, + {file = "rapidfuzz-3.10.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:116c71a81e046ba56551d8ab68067ca7034d94b617545316d460a452c5c3c289"}, + {file = "rapidfuzz-3.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0a547e4350d1fa32624d3eab51eff8cf329f4cae110b4ea0402486b1da8be40"}, + {file = "rapidfuzz-3.10.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:399b9b79ccfcf50ca3bad7692bc098bb8eade88d7d5e15773b7f866c91156d0c"}, + {file = "rapidfuzz-3.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7947a425d1be3e744707ee58c6cb318b93a56e08f080722dcc0347e0b7a1bb9a"}, + {file = "rapidfuzz-3.10.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:94c48b4a2a4b1d22246f48e2b11cae01ec7d23f0c9123f8bb822839ad79d0a88"}, + {file = "rapidfuzz-3.10.0.tar.gz", hash = "sha256:6b62af27e65bb39276a66533655a2fa3c60a487b03935721c45b7809527979be"}, ] [package.extras] -full = ["numpy"] +all = ["numpy"] [[package]] name = "readabilipy" @@ -8293,13 +8331,13 @@ test = ["accelerate (>=0.24.1,<=0.27.0)", "apache-airflow (==2.9.3)", "apache-ai [[package]] name = "sagemaker-core" -version = "1.0.4" +version = "1.0.9" description = "An python package for sagemaker core functionalities" optional = false python-versions = ">=3.8" files = [ - {file = "sagemaker_core-1.0.4-py3-none-any.whl", hash = "sha256:bf71d988dbda03a3cd1557524f2fab4f19d89e54bd38fc7f05bbbcf580715f95"}, - {file = "sagemaker_core-1.0.4.tar.gz", hash = "sha256:203f4eb9d0d2a0e6ba80d79ba8c28b8ea27c94d04f6d9ff01c2fd55b95615c78"}, + {file = "sagemaker_core-1.0.9-py3-none-any.whl", hash = "sha256:7a22c46cf93594f8d44e3523d4ba98407911f3530af68a8ffdde5082d3b26fa3"}, + {file = "sagemaker_core-1.0.9.tar.gz", hash = "sha256:664115faf797412553fb81b97a4777e78e51dfd4454c32edb2c8371bf203c535"}, ] [package.dependencies] @@ -8473,18 +8511,18 @@ tornado = ["tornado (>=5)"] [[package]] name = "setuptools" -version = "74.1.2" +version = "75.1.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-74.1.2-py3-none-any.whl", hash = "sha256:5f4c08aa4d3ebcb57a50c33b1b07e94315d7fc7230f7115e47fc99776c8ce308"}, - {file = "setuptools-74.1.2.tar.gz", hash = "sha256:95b40ed940a1c67eb70fc099094bd6e99c6ee7c23aa2306f4d2697ba7916f9c6"}, + {file = "setuptools-75.1.0-py3-none-any.whl", hash = "sha256:35ab7fd3bcd95e6b7fd704e4a1539513edad446c097797f2985e0e4b960772f2"}, + {file = "setuptools-75.1.0.tar.gz", hash = "sha256:d59a21b17a275fb872a9c3dae73963160ae079f1049ed956880cd7c09b120538"}, ] [package.extras] check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] -core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] @@ -8644,60 +8682,60 @@ files = [ [[package]] name = "sqlalchemy" -version = "2.0.34" +version = "2.0.35" description = "Database Abstraction Library" optional = false python-versions = ">=3.7" files = [ - {file = "SQLAlchemy-2.0.34-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:95d0b2cf8791ab5fb9e3aa3d9a79a0d5d51f55b6357eecf532a120ba3b5524db"}, - {file = "SQLAlchemy-2.0.34-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:243f92596f4fd4c8bd30ab8e8dd5965afe226363d75cab2468f2c707f64cd83b"}, - {file = "SQLAlchemy-2.0.34-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ea54f7300553af0a2a7235e9b85f4204e1fc21848f917a3213b0e0818de9a24"}, - {file = "SQLAlchemy-2.0.34-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:173f5f122d2e1bff8fbd9f7811b7942bead1f5e9f371cdf9e670b327e6703ebd"}, - {file = "SQLAlchemy-2.0.34-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:196958cde924a00488e3e83ff917be3b73cd4ed8352bbc0f2989333176d1c54d"}, - {file = "SQLAlchemy-2.0.34-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd90c221ed4e60ac9d476db967f436cfcecbd4ef744537c0f2d5291439848768"}, - {file = "SQLAlchemy-2.0.34-cp310-cp310-win32.whl", hash = "sha256:3166dfff2d16fe9be3241ee60ece6fcb01cf8e74dd7c5e0b64f8e19fab44911b"}, - {file = "SQLAlchemy-2.0.34-cp310-cp310-win_amd64.whl", hash = "sha256:6831a78bbd3c40f909b3e5233f87341f12d0b34a58f14115c9e94b4cdaf726d3"}, - {file = "SQLAlchemy-2.0.34-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7db3db284a0edaebe87f8f6642c2b2c27ed85c3e70064b84d1c9e4ec06d5d84"}, - {file = "SQLAlchemy-2.0.34-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:430093fce0efc7941d911d34f75a70084f12f6ca5c15d19595c18753edb7c33b"}, - {file = "SQLAlchemy-2.0.34-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79cb400c360c7c210097b147c16a9e4c14688a6402445ac848f296ade6283bbc"}, - {file = "SQLAlchemy-2.0.34-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb1b30f31a36c7f3fee848391ff77eebdd3af5750bf95fbf9b8b5323edfdb4ec"}, - {file = "SQLAlchemy-2.0.34-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fddde2368e777ea2a4891a3fb4341e910a056be0bb15303bf1b92f073b80c02"}, - {file = "SQLAlchemy-2.0.34-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:80bd73ea335203b125cf1d8e50fef06be709619eb6ab9e7b891ea34b5baa2287"}, - {file = "SQLAlchemy-2.0.34-cp311-cp311-win32.whl", hash = "sha256:6daeb8382d0df526372abd9cb795c992e18eed25ef2c43afe518c73f8cccb721"}, - {file = "SQLAlchemy-2.0.34-cp311-cp311-win_amd64.whl", hash = "sha256:5bc08e75ed11693ecb648b7a0a4ed80da6d10845e44be0c98c03f2f880b68ff4"}, - {file = "SQLAlchemy-2.0.34-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:53e68b091492c8ed2bd0141e00ad3089bcc6bf0e6ec4142ad6505b4afe64163e"}, - {file = "SQLAlchemy-2.0.34-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bcd18441a49499bf5528deaa9dee1f5c01ca491fc2791b13604e8f972877f812"}, - {file = "SQLAlchemy-2.0.34-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:165bbe0b376541092bf49542bd9827b048357f4623486096fc9aaa6d4e7c59a2"}, - {file = "SQLAlchemy-2.0.34-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3330415cd387d2b88600e8e26b510d0370db9b7eaf984354a43e19c40df2e2b"}, - {file = "SQLAlchemy-2.0.34-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:97b850f73f8abbffb66ccbab6e55a195a0eb655e5dc74624d15cff4bfb35bd74"}, - {file = "SQLAlchemy-2.0.34-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee4c6917857fd6121ed84f56d1dc78eb1d0e87f845ab5a568aba73e78adf83"}, - {file = "SQLAlchemy-2.0.34-cp312-cp312-win32.whl", hash = "sha256:fbb034f565ecbe6c530dff948239377ba859420d146d5f62f0271407ffb8c580"}, - {file = "SQLAlchemy-2.0.34-cp312-cp312-win_amd64.whl", hash = "sha256:707c8f44931a4facd4149b52b75b80544a8d824162602b8cd2fe788207307f9a"}, - {file = "SQLAlchemy-2.0.34-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:24af3dc43568f3780b7e1e57c49b41d98b2d940c1fd2e62d65d3928b6f95f021"}, - {file = "SQLAlchemy-2.0.34-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e60ed6ef0a35c6b76b7640fe452d0e47acc832ccbb8475de549a5cc5f90c2c06"}, - {file = "SQLAlchemy-2.0.34-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:413c85cd0177c23e32dee6898c67a5f49296640041d98fddb2c40888fe4daa2e"}, - {file = "SQLAlchemy-2.0.34-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:25691f4adfb9d5e796fd48bf1432272f95f4bbe5f89c475a788f31232ea6afba"}, - {file = "SQLAlchemy-2.0.34-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:526ce723265643dbc4c7efb54f56648cc30e7abe20f387d763364b3ce7506c82"}, - {file = "SQLAlchemy-2.0.34-cp37-cp37m-win32.whl", hash = "sha256:13be2cc683b76977a700948411a94c67ad8faf542fa7da2a4b167f2244781cf3"}, - {file = "SQLAlchemy-2.0.34-cp37-cp37m-win_amd64.whl", hash = "sha256:e54ef33ea80d464c3dcfe881eb00ad5921b60f8115ea1a30d781653edc2fd6a2"}, - {file = "SQLAlchemy-2.0.34-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:43f28005141165edd11fbbf1541c920bd29e167b8bbc1fb410d4fe2269c1667a"}, - {file = "SQLAlchemy-2.0.34-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b68094b165a9e930aedef90725a8fcfafe9ef95370cbb54abc0464062dbf808f"}, - {file = "SQLAlchemy-2.0.34-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a1e03db964e9d32f112bae36f0cc1dcd1988d096cfd75d6a588a3c3def9ab2b"}, - {file = "SQLAlchemy-2.0.34-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:203d46bddeaa7982f9c3cc693e5bc93db476ab5de9d4b4640d5c99ff219bee8c"}, - {file = "SQLAlchemy-2.0.34-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ae92bebca3b1e6bd203494e5ef919a60fb6dfe4d9a47ed2453211d3bd451b9f5"}, - {file = "SQLAlchemy-2.0.34-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9661268415f450c95f72f0ac1217cc6f10256f860eed85c2ae32e75b60278ad8"}, - {file = "SQLAlchemy-2.0.34-cp38-cp38-win32.whl", hash = "sha256:895184dfef8708e15f7516bd930bda7e50ead069280d2ce09ba11781b630a434"}, - {file = "SQLAlchemy-2.0.34-cp38-cp38-win_amd64.whl", hash = "sha256:6e7cde3a2221aa89247944cafb1b26616380e30c63e37ed19ff0bba5e968688d"}, - {file = "SQLAlchemy-2.0.34-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dbcdf987f3aceef9763b6d7b1fd3e4ee210ddd26cac421d78b3c206d07b2700b"}, - {file = "SQLAlchemy-2.0.34-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ce119fc4ce0d64124d37f66a6f2a584fddc3c5001755f8a49f1ca0a177ef9796"}, - {file = "SQLAlchemy-2.0.34-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a17d8fac6df9835d8e2b4c5523666e7051d0897a93756518a1fe101c7f47f2f0"}, - {file = "SQLAlchemy-2.0.34-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ebc11c54c6ecdd07bb4efbfa1554538982f5432dfb8456958b6d46b9f834bb7"}, - {file = "SQLAlchemy-2.0.34-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e6965346fc1491a566e019a4a1d3dfc081ce7ac1a736536367ca305da6472a8"}, - {file = "SQLAlchemy-2.0.34-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:220574e78ad986aea8e81ac68821e47ea9202b7e44f251b7ed8c66d9ae3f4278"}, - {file = "SQLAlchemy-2.0.34-cp39-cp39-win32.whl", hash = "sha256:b75b00083e7fe6621ce13cfce9d4469c4774e55e8e9d38c305b37f13cf1e874c"}, - {file = "SQLAlchemy-2.0.34-cp39-cp39-win_amd64.whl", hash = "sha256:c29d03e0adf3cc1a8c3ec62d176824972ae29b67a66cbb18daff3062acc6faa8"}, - {file = "SQLAlchemy-2.0.34-py3-none-any.whl", hash = "sha256:7286c353ee6475613d8beff83167374006c6b3e3f0e6491bfe8ca610eb1dec0f"}, - {file = "sqlalchemy-2.0.34.tar.gz", hash = "sha256:10d8f36990dd929690666679b0f42235c159a7051534adb135728ee52828dd22"}, + {file = "SQLAlchemy-2.0.35-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:67219632be22f14750f0d1c70e62f204ba69d28f62fd6432ba05ab295853de9b"}, + {file = "SQLAlchemy-2.0.35-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4668bd8faf7e5b71c0319407b608f278f279668f358857dbfd10ef1954ac9f90"}, + {file = "SQLAlchemy-2.0.35-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb8bea573863762bbf45d1e13f87c2d2fd32cee2dbd50d050f83f87429c9e1ea"}, + {file = "SQLAlchemy-2.0.35-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f552023710d4b93d8fb29a91fadf97de89c5926c6bd758897875435f2a939f33"}, + {file = "SQLAlchemy-2.0.35-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:016b2e665f778f13d3c438651dd4de244214b527a275e0acf1d44c05bc6026a9"}, + {file = "SQLAlchemy-2.0.35-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7befc148de64b6060937231cbff8d01ccf0bfd75aa26383ffdf8d82b12ec04ff"}, + {file = "SQLAlchemy-2.0.35-cp310-cp310-win32.whl", hash = "sha256:22b83aed390e3099584b839b93f80a0f4a95ee7f48270c97c90acd40ee646f0b"}, + {file = "SQLAlchemy-2.0.35-cp310-cp310-win_amd64.whl", hash = "sha256:a29762cd3d116585278ffb2e5b8cc311fb095ea278b96feef28d0b423154858e"}, + {file = "SQLAlchemy-2.0.35-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e21f66748ab725ade40fa7af8ec8b5019c68ab00b929f6643e1b1af461eddb60"}, + {file = "SQLAlchemy-2.0.35-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8a6219108a15fc6d24de499d0d515c7235c617b2540d97116b663dade1a54d62"}, + {file = "SQLAlchemy-2.0.35-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:042622a5306c23b972192283f4e22372da3b8ddf5f7aac1cc5d9c9b222ab3ff6"}, + {file = "SQLAlchemy-2.0.35-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:627dee0c280eea91aed87b20a1f849e9ae2fe719d52cbf847c0e0ea34464b3f7"}, + {file = "SQLAlchemy-2.0.35-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4fdcd72a789c1c31ed242fd8c1bcd9ea186a98ee8e5408a50e610edfef980d71"}, + {file = "SQLAlchemy-2.0.35-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:89b64cd8898a3a6f642db4eb7b26d1b28a497d4022eccd7717ca066823e9fb01"}, + {file = "SQLAlchemy-2.0.35-cp311-cp311-win32.whl", hash = "sha256:6a93c5a0dfe8d34951e8a6f499a9479ffb9258123551fa007fc708ae2ac2bc5e"}, + {file = "SQLAlchemy-2.0.35-cp311-cp311-win_amd64.whl", hash = "sha256:c68fe3fcde03920c46697585620135b4ecfdfc1ed23e75cc2c2ae9f8502c10b8"}, + {file = "SQLAlchemy-2.0.35-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:eb60b026d8ad0c97917cb81d3662d0b39b8ff1335e3fabb24984c6acd0c900a2"}, + {file = "SQLAlchemy-2.0.35-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6921ee01caf375363be5e9ae70d08ce7ca9d7e0e8983183080211a062d299468"}, + {file = "SQLAlchemy-2.0.35-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8cdf1a0dbe5ced887a9b127da4ffd7354e9c1a3b9bb330dce84df6b70ccb3a8d"}, + {file = "SQLAlchemy-2.0.35-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93a71c8601e823236ac0e5d087e4f397874a421017b3318fd92c0b14acf2b6db"}, + {file = "SQLAlchemy-2.0.35-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e04b622bb8a88f10e439084486f2f6349bf4d50605ac3e445869c7ea5cf0fa8c"}, + {file = "SQLAlchemy-2.0.35-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1b56961e2d31389aaadf4906d453859f35302b4eb818d34a26fab72596076bb8"}, + {file = "SQLAlchemy-2.0.35-cp312-cp312-win32.whl", hash = "sha256:0f9f3f9a3763b9c4deb8c5d09c4cc52ffe49f9876af41cc1b2ad0138878453cf"}, + {file = "SQLAlchemy-2.0.35-cp312-cp312-win_amd64.whl", hash = "sha256:25b0f63e7fcc2a6290cb5f7f5b4fc4047843504983a28856ce9b35d8f7de03cc"}, + {file = "SQLAlchemy-2.0.35-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f021d334f2ca692523aaf7bbf7592ceff70c8594fad853416a81d66b35e3abf9"}, + {file = "SQLAlchemy-2.0.35-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05c3f58cf91683102f2f0265c0db3bd3892e9eedabe059720492dbaa4f922da1"}, + {file = "SQLAlchemy-2.0.35-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:032d979ce77a6c2432653322ba4cbeabf5a6837f704d16fa38b5a05d8e21fa00"}, + {file = "SQLAlchemy-2.0.35-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:2e795c2f7d7249b75bb5f479b432a51b59041580d20599d4e112b5f2046437a3"}, + {file = "SQLAlchemy-2.0.35-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:cc32b2990fc34380ec2f6195f33a76b6cdaa9eecf09f0c9404b74fc120aef36f"}, + {file = "SQLAlchemy-2.0.35-cp37-cp37m-win32.whl", hash = "sha256:9509c4123491d0e63fb5e16199e09f8e262066e58903e84615c301dde8fa2e87"}, + {file = "SQLAlchemy-2.0.35-cp37-cp37m-win_amd64.whl", hash = "sha256:3655af10ebcc0f1e4e06c5900bb33e080d6a1fa4228f502121f28a3b1753cde5"}, + {file = "SQLAlchemy-2.0.35-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4c31943b61ed8fdd63dfd12ccc919f2bf95eefca133767db6fbbd15da62078ec"}, + {file = "SQLAlchemy-2.0.35-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a62dd5d7cc8626a3634208df458c5fe4f21200d96a74d122c83bc2015b333bc1"}, + {file = "SQLAlchemy-2.0.35-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0630774b0977804fba4b6bbea6852ab56c14965a2b0c7fc7282c5f7d90a1ae72"}, + {file = "SQLAlchemy-2.0.35-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d625eddf7efeba2abfd9c014a22c0f6b3796e0ffb48f5d5ab106568ef01ff5a"}, + {file = "SQLAlchemy-2.0.35-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ada603db10bb865bbe591939de854faf2c60f43c9b763e90f653224138f910d9"}, + {file = "SQLAlchemy-2.0.35-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c41411e192f8d3ea39ea70e0fae48762cd11a2244e03751a98bd3c0ca9a4e936"}, + {file = "SQLAlchemy-2.0.35-cp38-cp38-win32.whl", hash = "sha256:d299797d75cd747e7797b1b41817111406b8b10a4f88b6e8fe5b5e59598b43b0"}, + {file = "SQLAlchemy-2.0.35-cp38-cp38-win_amd64.whl", hash = "sha256:0375a141e1c0878103eb3d719eb6d5aa444b490c96f3fedab8471c7f6ffe70ee"}, + {file = "SQLAlchemy-2.0.35-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ccae5de2a0140d8be6838c331604f91d6fafd0735dbdcee1ac78fc8fbaba76b4"}, + {file = "SQLAlchemy-2.0.35-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2a275a806f73e849e1c309ac11108ea1a14cd7058577aba962cd7190e27c9e3c"}, + {file = "SQLAlchemy-2.0.35-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:732e026240cdd1c1b2e3ac515c7a23820430ed94292ce33806a95869c46bd139"}, + {file = "SQLAlchemy-2.0.35-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:890da8cd1941fa3dab28c5bac3b9da8502e7e366f895b3b8e500896f12f94d11"}, + {file = "SQLAlchemy-2.0.35-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c0d8326269dbf944b9201911b0d9f3dc524d64779a07518199a58384c3d37a44"}, + {file = "SQLAlchemy-2.0.35-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b76d63495b0508ab9fc23f8152bac63205d2a704cd009a2b0722f4c8e0cba8e0"}, + {file = "SQLAlchemy-2.0.35-cp39-cp39-win32.whl", hash = "sha256:69683e02e8a9de37f17985905a5eca18ad651bf592314b4d3d799029797d0eb3"}, + {file = "SQLAlchemy-2.0.35-cp39-cp39-win_amd64.whl", hash = "sha256:aee110e4ef3c528f3abbc3c2018c121e708938adeeff9006428dd7c8555e9b3f"}, + {file = "SQLAlchemy-2.0.35-py3-none-any.whl", hash = "sha256:2ab3f0336c0387662ce6221ad30ab3a5e6499aab01b9790879b6578fd9b8faa1"}, + {file = "sqlalchemy-2.0.35.tar.gz", hash = "sha256:e11d7ea4d24f0a262bccf9a7cd6284c976c5369dac21db237cff59586045ab9f"}, ] [package.dependencies] @@ -8746,13 +8784,13 @@ doc = ["sphinx"] [[package]] name = "starlette" -version = "0.38.5" +version = "0.38.6" description = "The little ASGI library that shines." optional = false python-versions = ">=3.8" files = [ - {file = "starlette-0.38.5-py3-none-any.whl", hash = "sha256:632f420a9d13e3ee2a6f18f437b0a9f1faecb0bc42e1942aa2ea0e379a4c4206"}, - {file = "starlette-0.38.5.tar.gz", hash = "sha256:04a92830a9b6eb1442c766199d62260c3d4dc9c4f9188360626b1e0273cb7077"}, + {file = "starlette-0.38.6-py3-none-any.whl", hash = "sha256:4517a1409e2e73ee4951214ba012052b9e16f60e90d73cfb06192c19203bbb05"}, + {file = "starlette-0.38.6.tar.gz", hash = "sha256:863a1588f5574e70a821dadefb41e4881ea451a47a3cd1b4df359d4ffefe5ead"}, ] [package.dependencies] @@ -8777,13 +8815,13 @@ python-dateutil = ">=2.6.0" [[package]] name = "sympy" -version = "1.13.2" +version = "1.13.3" description = "Computer algebra system (CAS) in Python" optional = false python-versions = ">=3.8" files = [ - {file = "sympy-1.13.2-py3-none-any.whl", hash = "sha256:c51d75517712f1aed280d4ce58506a4a88d635d6b5dd48b39102a7ae1f3fcfe9"}, - {file = "sympy-1.13.2.tar.gz", hash = "sha256:401449d84d07be9d0c7a46a64bd54fe097667d5e7181bfe67ec777be9e01cb13"}, + {file = "sympy-1.13.3-py3-none-any.whl", hash = "sha256:54612cf55a62755ee71824ce692986f23c88ffa77207b30c1368eda4a7060f73"}, + {file = "sympy-1.13.3.tar.gz", hash = "sha256:b27fd2c6530e0ab39e275fc9b683895367e51d5da91baa8d3d64db2565fec4d9"}, ] [package.dependencies] @@ -8849,13 +8887,13 @@ test = ["pytest", "tornado (>=4.5)", "typeguard"] [[package]] name = "tencentcloud-sdk-python-common" -version = "3.0.1231" +version = "3.0.1243" description = "Tencent Cloud Common SDK for Python" optional = false python-versions = "*" files = [ - {file = "tencentcloud-sdk-python-common-3.0.1231.tar.gz", hash = "sha256:22aa281ca2eac511e1615b2953da7c4a0bec87cf93a05a7a15dbb61b23a215ee"}, - {file = "tencentcloud_sdk_python_common-3.0.1231-py2.py3-none-any.whl", hash = "sha256:bd0f7c4df4b156ec35c8731afa1f498043c7e1cd5d2feb595ee441fdb45a061e"}, + {file = "tencentcloud-sdk-python-common-3.0.1243.tar.gz", hash = "sha256:4008126b5506543ddc33ea53ef25abe19b4fa025006ec7751b3d5b3c046438b6"}, + {file = "tencentcloud_sdk_python_common-3.0.1243-py2.py3-none-any.whl", hash = "sha256:ed5d2040627aeed2df1fe5f9d65b9987ef842222d79fb13136cc5866aa5ac50c"}, ] [package.dependencies] @@ -8863,17 +8901,17 @@ requests = ">=2.16.0" [[package]] name = "tencentcloud-sdk-python-hunyuan" -version = "3.0.1231" +version = "3.0.1243" description = "Tencent Cloud Hunyuan SDK for Python" optional = false python-versions = "*" files = [ - {file = "tencentcloud-sdk-python-hunyuan-3.0.1231.tar.gz", hash = "sha256:6da12f418f14305b3a6b7bb29b6d95bf4038a6b66b81c0e03b8dafc4f6df99ca"}, - {file = "tencentcloud_sdk_python_hunyuan-3.0.1231-py2.py3-none-any.whl", hash = "sha256:21ba28f69c34c15e20900be3f2c06376fcaf7e58265f939833c55631f2348792"}, + {file = "tencentcloud-sdk-python-hunyuan-3.0.1243.tar.gz", hash = "sha256:2caad419f24106574f05faf69d162060689e03452832fda890a28eb8814199bc"}, + {file = "tencentcloud_sdk_python_hunyuan-3.0.1243-py2.py3-none-any.whl", hash = "sha256:b5a5c0dfa8b6de68c2c8747bf34b880c7fd2a1cbd59efc372e076260228ce231"}, ] [package.dependencies] -tencentcloud-sdk-python-common = "3.0.1231" +tencentcloud-sdk-python-common = "3.0.1243" [[package]] name = "threadpoolctl" @@ -9316,13 +9354,13 @@ typing-extensions = ">=3.7.4" [[package]] name = "tzdata" -version = "2024.1" +version = "2024.2" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" files = [ - {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, - {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, + {file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"}, + {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"}, ] [[package]] @@ -9542,13 +9580,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvicorn" -version = "0.30.6" +version = "0.31.0" description = "The lightning-fast ASGI server." optional = false python-versions = ">=3.8" files = [ - {file = "uvicorn-0.30.6-py3-none-any.whl", hash = "sha256:65fd46fe3fda5bdc1b03b94eb634923ff18cd35b2f084813ea79d1f103f711b5"}, - {file = "uvicorn-0.30.6.tar.gz", hash = "sha256:4b15decdda1e72be08209e860a1e10e92439ad5b97cf44cc945fcbee66fc5788"}, + {file = "uvicorn-0.31.0-py3-none-any.whl", hash = "sha256:cac7be4dd4d891c363cd942160a7b02e69150dcbc7a36be04d5f4af4b17c8ced"}, + {file = "uvicorn-0.31.0.tar.gz", hash = "sha256:13bc21373d103859f68fe739608e2eb054a816dea79189bc3ca08ea89a275906"}, ] [package.dependencies] @@ -9685,12 +9723,12 @@ files = [ [[package]] name = "volcengine-python-sdk" -version = "1.0.101" +version = "1.0.103" description = "Volcengine SDK for Python" optional = false python-versions = "*" files = [ - {file = "volcengine-python-sdk-1.0.101.tar.gz", hash = "sha256:1b76e71a6dcf3d5be1b2c058e7d281359e6cca2cc920ffe2567d3115beea1d02"}, + {file = "volcengine-python-sdk-1.0.103.tar.gz", hash = "sha256:49fa8572802724972e1cb47a7e692b184b055f41b09099358c1a0fad1d146af5"}, ] [package.dependencies] @@ -9860,97 +9898,97 @@ test = ["websockets"] [[package]] name = "websockets" -version = "13.0.1" +version = "13.1" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false python-versions = ">=3.8" files = [ - {file = "websockets-13.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1841c9082a3ba4a05ea824cf6d99570a6a2d8849ef0db16e9c826acb28089e8f"}, - {file = "websockets-13.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c5870b4a11b77e4caa3937142b650fbbc0914a3e07a0cf3131f35c0587489c1c"}, - {file = "websockets-13.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f1d3d1f2eb79fe7b0fb02e599b2bf76a7619c79300fc55f0b5e2d382881d4f7f"}, - {file = "websockets-13.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15c7d62ee071fa94a2fc52c2b472fed4af258d43f9030479d9c4a2de885fd543"}, - {file = "websockets-13.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6724b554b70d6195ba19650fef5759ef11346f946c07dbbe390e039bcaa7cc3d"}, - {file = "websockets-13.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56a952fa2ae57a42ba7951e6b2605e08a24801a4931b5644dfc68939e041bc7f"}, - {file = "websockets-13.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:17118647c0ea14796364299e942c330d72acc4b248e07e639d34b75067b3cdd8"}, - {file = "websockets-13.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64a11aae1de4c178fa653b07d90f2fb1a2ed31919a5ea2361a38760192e1858b"}, - {file = "websockets-13.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0617fd0b1d14309c7eab6ba5deae8a7179959861846cbc5cb528a7531c249448"}, - {file = "websockets-13.0.1-cp310-cp310-win32.whl", hash = "sha256:11f9976ecbc530248cf162e359a92f37b7b282de88d1d194f2167b5e7ad80ce3"}, - {file = "websockets-13.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:c3c493d0e5141ec055a7d6809a28ac2b88d5b878bb22df8c621ebe79a61123d0"}, - {file = "websockets-13.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:699ba9dd6a926f82a277063603fc8d586b89f4cb128efc353b749b641fcddda7"}, - {file = "websockets-13.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cf2fae6d85e5dc384bf846f8243ddaa9197f3a1a70044f59399af001fd1f51d4"}, - {file = "websockets-13.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:52aed6ef21a0f1a2a5e310fb5c42d7555e9c5855476bbd7173c3aa3d8a0302f2"}, - {file = "websockets-13.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8eb2b9a318542153674c6e377eb8cb9ca0fc011c04475110d3477862f15d29f0"}, - {file = "websockets-13.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5df891c86fe68b2c38da55b7aea7095beca105933c697d719f3f45f4220a5e0e"}, - {file = "websockets-13.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fac2d146ff30d9dd2fcf917e5d147db037a5c573f0446c564f16f1f94cf87462"}, - {file = "websockets-13.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b8ac5b46fd798bbbf2ac6620e0437c36a202b08e1f827832c4bf050da081b501"}, - {file = "websockets-13.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:46af561eba6f9b0848b2c9d2427086cabadf14e0abdd9fde9d72d447df268418"}, - {file = "websockets-13.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b5a06d7f60bc2fc378a333978470dfc4e1415ee52f5f0fce4f7853eb10c1e9df"}, - {file = "websockets-13.0.1-cp311-cp311-win32.whl", hash = "sha256:556e70e4f69be1082e6ef26dcb70efcd08d1850f5d6c5f4f2bcb4e397e68f01f"}, - {file = "websockets-13.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:67494e95d6565bf395476e9d040037ff69c8b3fa356a886b21d8422ad86ae075"}, - {file = "websockets-13.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f9c9e258e3d5efe199ec23903f5da0eeaad58cf6fccb3547b74fd4750e5ac47a"}, - {file = "websockets-13.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6b41a1b3b561f1cba8321fb32987552a024a8f67f0d05f06fcf29f0090a1b956"}, - {file = "websockets-13.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f73e676a46b0fe9426612ce8caeca54c9073191a77c3e9d5c94697aef99296af"}, - {file = "websockets-13.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f613289f4a94142f914aafad6c6c87903de78eae1e140fa769a7385fb232fdf"}, - {file = "websockets-13.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f52504023b1480d458adf496dc1c9e9811df4ba4752f0bc1f89ae92f4f07d0c"}, - {file = "websockets-13.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:139add0f98206cb74109faf3611b7783ceafc928529c62b389917a037d4cfdf4"}, - {file = "websockets-13.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:47236c13be337ef36546004ce8c5580f4b1150d9538b27bf8a5ad8edf23ccfab"}, - {file = "websockets-13.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c44ca9ade59b2e376612df34e837013e2b273e6c92d7ed6636d0556b6f4db93d"}, - {file = "websockets-13.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9bbc525f4be3e51b89b2a700f5746c2a6907d2e2ef4513a8daafc98198b92237"}, - {file = "websockets-13.0.1-cp312-cp312-win32.whl", hash = "sha256:3624fd8664f2577cf8de996db3250662e259bfbc870dd8ebdcf5d7c6ac0b5185"}, - {file = "websockets-13.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0513c727fb8adffa6d9bf4a4463b2bade0186cbd8c3604ae5540fae18a90cb99"}, - {file = "websockets-13.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1ee4cc030a4bdab482a37462dbf3ffb7e09334d01dd37d1063be1136a0d825fa"}, - {file = "websockets-13.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dbb0b697cc0655719522406c059eae233abaa3243821cfdfab1215d02ac10231"}, - {file = "websockets-13.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:acbebec8cb3d4df6e2488fbf34702cbc37fc39ac7abf9449392cefb3305562e9"}, - {file = "websockets-13.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63848cdb6fcc0bf09d4a155464c46c64ffdb5807ede4fb251da2c2692559ce75"}, - {file = "websockets-13.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:872afa52a9f4c414d6955c365b6588bc4401272c629ff8321a55f44e3f62b553"}, - {file = "websockets-13.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05e70fec7c54aad4d71eae8e8cab50525e899791fc389ec6f77b95312e4e9920"}, - {file = "websockets-13.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e82db3756ccb66266504f5a3de05ac6b32f287faacff72462612120074103329"}, - {file = "websockets-13.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4e85f46ce287f5c52438bb3703d86162263afccf034a5ef13dbe4318e98d86e7"}, - {file = "websockets-13.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f3fea72e4e6edb983908f0db373ae0732b275628901d909c382aae3b592589f2"}, - {file = "websockets-13.0.1-cp313-cp313-win32.whl", hash = "sha256:254ecf35572fca01a9f789a1d0f543898e222f7b69ecd7d5381d8d8047627bdb"}, - {file = "websockets-13.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:ca48914cdd9f2ccd94deab5bcb5ac98025a5ddce98881e5cce762854a5de330b"}, - {file = "websockets-13.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b74593e9acf18ea5469c3edaa6b27fa7ecf97b30e9dabd5a94c4c940637ab96e"}, - {file = "websockets-13.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:132511bfd42e77d152c919147078460c88a795af16b50e42a0bd14f0ad71ddd2"}, - {file = "websockets-13.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:165bedf13556f985a2aa064309baa01462aa79bf6112fbd068ae38993a0e1f1b"}, - {file = "websockets-13.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e801ca2f448850685417d723ec70298feff3ce4ff687c6f20922c7474b4746ae"}, - {file = "websockets-13.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30d3a1f041360f029765d8704eae606781e673e8918e6b2c792e0775de51352f"}, - {file = "websockets-13.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67648f5e50231b5a7f6d83b32f9c525e319f0ddc841be0de64f24928cd75a603"}, - {file = "websockets-13.0.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:4f0426d51c8f0926a4879390f53c7f5a855e42d68df95fff6032c82c888b5f36"}, - {file = "websockets-13.0.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ef48e4137e8799998a343706531e656fdec6797b80efd029117edacb74b0a10a"}, - {file = "websockets-13.0.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:249aab278810bee585cd0d4de2f08cfd67eed4fc75bde623be163798ed4db2eb"}, - {file = "websockets-13.0.1-cp38-cp38-win32.whl", hash = "sha256:06c0a667e466fcb56a0886d924b5f29a7f0886199102f0a0e1c60a02a3751cb4"}, - {file = "websockets-13.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1f3cf6d6ec1142412d4535adabc6bd72a63f5f148c43fe559f06298bc21953c9"}, - {file = "websockets-13.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1fa082ea38d5de51dd409434edc27c0dcbd5fed2b09b9be982deb6f0508d25bc"}, - {file = "websockets-13.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4a365bcb7be554e6e1f9f3ed64016e67e2fa03d7b027a33e436aecf194febb63"}, - {file = "websockets-13.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:10a0dc7242215d794fb1918f69c6bb235f1f627aaf19e77f05336d147fce7c37"}, - {file = "websockets-13.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59197afd478545b1f73367620407b0083303569c5f2d043afe5363676f2697c9"}, - {file = "websockets-13.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d20516990d8ad557b5abeb48127b8b779b0b7e6771a265fa3e91767596d7d97"}, - {file = "websockets-13.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1a2e272d067030048e1fe41aa1ec8cfbbaabce733b3d634304fa2b19e5c897f"}, - {file = "websockets-13.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ad327ac80ba7ee61da85383ca8822ff808ab5ada0e4a030d66703cc025b021c4"}, - {file = "websockets-13.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:518f90e6dd089d34eaade01101fd8a990921c3ba18ebbe9b0165b46ebff947f0"}, - {file = "websockets-13.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:68264802399aed6fe9652e89761031acc734fc4c653137a5911c2bfa995d6d6d"}, - {file = "websockets-13.0.1-cp39-cp39-win32.whl", hash = "sha256:a5dc0c42ded1557cc7c3f0240b24129aefbad88af4f09346164349391dea8e58"}, - {file = "websockets-13.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b448a0690ef43db5ef31b3a0d9aea79043882b4632cfc3eaab20105edecf6097"}, - {file = "websockets-13.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:faef9ec6354fe4f9a2c0bbb52fb1ff852effc897e2a4501e25eb3a47cb0a4f89"}, - {file = "websockets-13.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:03d3f9ba172e0a53e37fa4e636b86cc60c3ab2cfee4935e66ed1d7acaa4625ad"}, - {file = "websockets-13.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d450f5a7a35662a9b91a64aefa852f0c0308ee256122f5218a42f1d13577d71e"}, - {file = "websockets-13.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f55b36d17ac50aa8a171b771e15fbe1561217510c8768af3d546f56c7576cdc"}, - {file = "websockets-13.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14b9c006cac63772b31abbcd3e3abb6228233eec966bf062e89e7fa7ae0b7333"}, - {file = "websockets-13.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b79915a1179a91f6c5f04ece1e592e2e8a6bd245a0e45d12fd56b2b59e559a32"}, - {file = "websockets-13.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f40de079779acbcdbb6ed4c65af9f018f8b77c5ec4e17a4b737c05c2db554491"}, - {file = "websockets-13.0.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:80e4ba642fc87fa532bac07e5ed7e19d56940b6af6a8c61d4429be48718a380f"}, - {file = "websockets-13.0.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a02b0161c43cc9e0232711eff846569fad6ec836a7acab16b3cf97b2344c060"}, - {file = "websockets-13.0.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6aa74a45d4cdc028561a7d6ab3272c8b3018e23723100b12e58be9dfa5a24491"}, - {file = "websockets-13.0.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00fd961943b6c10ee6f0b1130753e50ac5dcd906130dcd77b0003c3ab797d026"}, - {file = "websockets-13.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d93572720d781331fb10d3da9ca1067817d84ad1e7c31466e9f5e59965618096"}, - {file = "websockets-13.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:71e6e5a3a3728886caee9ab8752e8113670936a193284be9d6ad2176a137f376"}, - {file = "websockets-13.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c4a6343e3b0714e80da0b0893543bf9a5b5fa71b846ae640e56e9abc6fbc4c83"}, - {file = "websockets-13.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a678532018e435396e37422a95e3ab87f75028ac79570ad11f5bf23cd2a7d8c"}, - {file = "websockets-13.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6716c087e4aa0b9260c4e579bb82e068f84faddb9bfba9906cb87726fa2e870"}, - {file = "websockets-13.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e33505534f3f673270dd67f81e73550b11de5b538c56fe04435d63c02c3f26b5"}, - {file = "websockets-13.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:acab3539a027a85d568c2573291e864333ec9d912675107d6efceb7e2be5d980"}, - {file = "websockets-13.0.1-py3-none-any.whl", hash = "sha256:b80f0c51681c517604152eb6a572f5a9378f877763231fddb883ba2f968e8817"}, - {file = "websockets-13.0.1.tar.gz", hash = "sha256:4d6ece65099411cfd9a48d13701d7438d9c34f479046b34c50ff60bb8834e43e"}, + {file = "websockets-13.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee"}, + {file = "websockets-13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7"}, + {file = "websockets-13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6"}, + {file = "websockets-13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676df3fe46956fbb0437d8800cd5f2b6d41143b6e7e842e60554398432cf29b"}, + {file = "websockets-13.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7affedeb43a70351bb811dadf49493c9cfd1ed94c9c70095fd177e9cc1541fa"}, + {file = "websockets-13.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1971e62d2caa443e57588e1d82d15f663b29ff9dfe7446d9964a4b6f12c1e700"}, + {file = "websockets-13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5f2e75431f8dc4a47f31565a6e1355fb4f2ecaa99d6b89737527ea917066e26c"}, + {file = "websockets-13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58cf7e75dbf7e566088b07e36ea2e3e2bd5676e22216e4cad108d4df4a7402a0"}, + {file = "websockets-13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c90d6dec6be2c7d03378a574de87af9b1efea77d0c52a8301dd831ece938452f"}, + {file = "websockets-13.1-cp310-cp310-win32.whl", hash = "sha256:730f42125ccb14602f455155084f978bd9e8e57e89b569b4d7f0f0c17a448ffe"}, + {file = "websockets-13.1-cp310-cp310-win_amd64.whl", hash = "sha256:5993260f483d05a9737073be197371940c01b257cc45ae3f1d5d7adb371b266a"}, + {file = "websockets-13.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19"}, + {file = "websockets-13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5"}, + {file = "websockets-13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd"}, + {file = "websockets-13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02"}, + {file = "websockets-13.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7"}, + {file = "websockets-13.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87c6e35319b46b99e168eb98472d6c7d8634ee37750d7693656dc766395df096"}, + {file = "websockets-13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084"}, + {file = "websockets-13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3"}, + {file = "websockets-13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9"}, + {file = "websockets-13.1-cp311-cp311-win32.whl", hash = "sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f"}, + {file = "websockets-13.1-cp311-cp311-win_amd64.whl", hash = "sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557"}, + {file = "websockets-13.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc"}, + {file = "websockets-13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49"}, + {file = "websockets-13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd"}, + {file = "websockets-13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0"}, + {file = "websockets-13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6"}, + {file = "websockets-13.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9"}, + {file = "websockets-13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68"}, + {file = "websockets-13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14"}, + {file = "websockets-13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf"}, + {file = "websockets-13.1-cp312-cp312-win32.whl", hash = "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c"}, + {file = "websockets-13.1-cp312-cp312-win_amd64.whl", hash = "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3"}, + {file = "websockets-13.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6"}, + {file = "websockets-13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708"}, + {file = "websockets-13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418"}, + {file = "websockets-13.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a"}, + {file = "websockets-13.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f"}, + {file = "websockets-13.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91a0fa841646320ec0d3accdff5b757b06e2e5c86ba32af2e0815c96c7a603c5"}, + {file = "websockets-13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135"}, + {file = "websockets-13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2"}, + {file = "websockets-13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6"}, + {file = "websockets-13.1-cp313-cp313-win32.whl", hash = "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d"}, + {file = "websockets-13.1-cp313-cp313-win_amd64.whl", hash = "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2"}, + {file = "websockets-13.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c7934fd0e920e70468e676fe7f1b7261c1efa0d6c037c6722278ca0228ad9d0d"}, + {file = "websockets-13.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:149e622dc48c10ccc3d2760e5f36753db9cacf3ad7bc7bbbfd7d9c819e286f23"}, + {file = "websockets-13.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a569eb1b05d72f9bce2ebd28a1ce2054311b66677fcd46cf36204ad23acead8c"}, + {file = "websockets-13.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95df24ca1e1bd93bbca51d94dd049a984609687cb2fb08a7f2c56ac84e9816ea"}, + {file = "websockets-13.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8dbb1bf0c0a4ae8b40bdc9be7f644e2f3fb4e8a9aca7145bfa510d4a374eeb7"}, + {file = "websockets-13.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:035233b7531fb92a76beefcbf479504db8c72eb3bff41da55aecce3a0f729e54"}, + {file = "websockets-13.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e4450fc83a3df53dec45922b576e91e94f5578d06436871dce3a6be38e40f5db"}, + {file = "websockets-13.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:463e1c6ec853202dd3657f156123d6b4dad0c546ea2e2e38be2b3f7c5b8e7295"}, + {file = "websockets-13.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6d6855bbe70119872c05107e38fbc7f96b1d8cb047d95c2c50869a46c65a8e96"}, + {file = "websockets-13.1-cp38-cp38-win32.whl", hash = "sha256:204e5107f43095012b00f1451374693267adbb832d29966a01ecc4ce1db26faf"}, + {file = "websockets-13.1-cp38-cp38-win_amd64.whl", hash = "sha256:485307243237328c022bc908b90e4457d0daa8b5cf4b3723fd3c4a8012fce4c6"}, + {file = "websockets-13.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d"}, + {file = "websockets-13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7"}, + {file = "websockets-13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a"}, + {file = "websockets-13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:586a356928692c1fed0eca68b4d1c2cbbd1ca2acf2ac7e7ebd3b9052582deefa"}, + {file = "websockets-13.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7bd6abf1e070a6b72bfeb71049d6ad286852e285f146682bf30d0296f5fbadfa"}, + {file = "websockets-13.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2aad13a200e5934f5a6767492fb07151e1de1d6079c003ab31e1823733ae79"}, + {file = "websockets-13.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:df01aea34b6e9e33572c35cd16bae5a47785e7d5c8cb2b54b2acdb9678315a17"}, + {file = "websockets-13.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e54affdeb21026329fb0744ad187cf812f7d3c2aa702a5edb562b325191fcab6"}, + {file = "websockets-13.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9ef8aa8bdbac47f4968a5d66462a2a0935d044bf35c0e5a8af152d58516dbeb5"}, + {file = "websockets-13.1-cp39-cp39-win32.whl", hash = "sha256:deeb929efe52bed518f6eb2ddc00cc496366a14c726005726ad62c2dd9017a3c"}, + {file = "websockets-13.1-cp39-cp39-win_amd64.whl", hash = "sha256:7c65ffa900e7cc958cd088b9a9157a8141c991f8c53d11087e6fb7277a03f81d"}, + {file = "websockets-13.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5dd6da9bec02735931fccec99d97c29f47cc61f644264eb995ad6c0c27667238"}, + {file = "websockets-13.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:2510c09d8e8df777177ee3d40cd35450dc169a81e747455cc4197e63f7e7bfe5"}, + {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1c3cf67185543730888b20682fb186fc8d0fa6f07ccc3ef4390831ab4b388d9"}, + {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcc03c8b72267e97b49149e4863d57c2d77f13fae12066622dc78fe322490fe6"}, + {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:004280a140f220c812e65f36944a9ca92d766b6cc4560be652a0a3883a79ed8a"}, + {file = "websockets-13.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e2620453c075abeb0daa949a292e19f56de518988e079c36478bacf9546ced23"}, + {file = "websockets-13.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9156c45750b37337f7b0b00e6248991a047be4aa44554c9886fe6bdd605aab3b"}, + {file = "websockets-13.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:80c421e07973a89fbdd93e6f2003c17d20b69010458d3a8e37fb47874bd67d51"}, + {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82d0ba76371769d6a4e56f7e83bb8e81846d17a6190971e38b5de108bde9b0d7"}, + {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9875a0143f07d74dc5e1ded1c4581f0d9f7ab86c78994e2ed9e95050073c94d"}, + {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a11e38ad8922c7961447f35c7b17bffa15de4d17c70abd07bfbe12d6faa3e027"}, + {file = "websockets-13.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4059f790b6ae8768471cddb65d3c4fe4792b0ab48e154c9f0a04cefaabcd5978"}, + {file = "websockets-13.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:25c35bf84bf7c7369d247f0b8cfa157f989862c49104c5cf85cb5436a641d93e"}, + {file = "websockets-13.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:83f91d8a9bb404b8c2c41a707ac7f7f75b9442a0a876df295de27251a856ad09"}, + {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a43cfdcddd07f4ca2b1afb459824dd3c6d53a51410636a2c7fc97b9a8cf4842"}, + {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48a2ef1381632a2f0cb4efeff34efa97901c9fbc118e01951ad7cfc10601a9bb"}, + {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459bf774c754c35dbb487360b12c5727adab887f1622b8aed5755880a21c4a20"}, + {file = "websockets-13.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:95858ca14a9f6fa8413d29e0a585b31b278388aa775b8a81fa24830123874678"}, + {file = "websockets-13.1-py3-none-any.whl", hash = "sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f"}, + {file = "websockets-13.1.tar.gz", hash = "sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878"}, ] [[package]] @@ -10501,4 +10539,4 @@ cffi = ["cffi (>=1.11)"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.13" -content-hash = "c4580c22e2b220c8c80dbc3f765060a09e14874ed29b690c13a533bf0365e789" +content-hash = "74a22b763f5f6f1414e843f1a508ff48210d32f9523b696e5dd443489deaad46" diff --git a/api/pyproject.toml b/api/pyproject.toml index e737761f3b..fe9e64907b 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -221,6 +221,7 @@ volcengine-python-sdk = {extras = ["ark"], version = "^1.0.98"} oci = "^2.133.0" tos = "^2.7.1" nomic = "^3.1.2" +validators = "0.21.0" [tool.poetry.group.indriect.dependencies] kaleido = "0.2.1" rank-bm25 = "~0.2.2" diff --git a/api/schedule/clean_unused_messages_task.py b/api/schedule/clean_unused_messages_task.py new file mode 100644 index 0000000000..85e6a58a0e --- /dev/null +++ b/api/schedule/clean_unused_messages_task.py @@ -0,0 +1,92 @@ +import datetime +import time + +import click +from sqlalchemy import func +from werkzeug.exceptions import NotFound + +import app +from configs import dify_config +from core.rag.index_processor.index_processor_factory import IndexProcessorFactory +from extensions.ext_database import db +from models.dataset import Dataset, DatasetQuery, Document + + +@app.celery.task(queue="dataset") +def clean_unused_message_task(): + click.echo(click.style("Start clean unused messages .", fg="green")) + clean_days = int(dify_config.CLEAN_DAY_SETTING) + start_at = time.perf_counter() + thirty_days_ago = datetime.datetime.now() - datetime.timedelta(days=clean_days) + page = 1 + while True: + try: + # Subquery for counting new documents + document_subquery_new = ( + db.session.query(Document.dataset_id, func.count(Document.id).label("document_count")) + .filter( + Document.indexing_status == "completed", + Document.enabled == True, + Document.archived == False, + Document.updated_at > thirty_days_ago, + ) + .group_by(Document.dataset_id) + .subquery() + ) + + # Subquery for counting old documents + document_subquery_old = ( + db.session.query(Document.dataset_id, func.count(Document.id).label("document_count")) + .filter( + Document.indexing_status == "completed", + Document.enabled == True, + Document.archived == False, + Document.updated_at < thirty_days_ago, + ) + .group_by(Document.dataset_id) + .subquery() + ) + + # Main query with join and filter + datasets = ( + db.session.query(Dataset) + .outerjoin(document_subquery_new, Dataset.id == document_subquery_new.c.dataset_id) + .outerjoin(document_subquery_old, Dataset.id == document_subquery_old.c.dataset_id) + .filter( + Dataset.created_at < thirty_days_ago, + func.coalesce(document_subquery_new.c.document_count, 0) == 0, + func.coalesce(document_subquery_old.c.document_count, 0) > 0, + ) + .order_by(Dataset.created_at.desc()) + .paginate(page=page, per_page=50) + ) + + except NotFound: + break + if datasets.items is None or len(datasets.items) == 0: + break + page += 1 + for dataset in datasets: + dataset_query = ( + db.session.query(DatasetQuery) + .filter(DatasetQuery.created_at > thirty_days_ago, DatasetQuery.dataset_id == dataset.id) + .all() + ) + if not dataset_query or len(dataset_query) == 0: + try: + # remove index + index_processor = IndexProcessorFactory(dataset.doc_form).init_index_processor() + index_processor.clean(dataset, None) + + # update document + update_params = {Document.enabled: False} + + Document.query.filter_by(dataset_id=dataset.id).update(update_params) + db.session.commit() + click.echo(click.style("Cleaned unused dataset {} from db success!".format(dataset.id), fg="green")) + except Exception as e: + click.echo( + click.style("clean dataset index error: {} {}".format(e.__class__.__name__, str(e)), fg="red") + ) + end_at = time.perf_counter() + click.echo(click.style("Cleaned unused dataset from db success latency: {}".format(end_at - start_at), fg="green")) diff --git a/api/services/dataset_service.py b/api/services/dataset_service.py index e96f06ed40..c165def6d5 100644 --- a/api/services/dataset_service.py +++ b/api/services/dataset_service.py @@ -32,6 +32,7 @@ from models.dataset import ( DatasetQuery, Document, DocumentSegment, + ExternalKnowledgeBindings, ) from models.model import UploadFile from models.source import DataSourceOauthBinding @@ -39,6 +40,7 @@ from services.errors.account import NoPermissionError from services.errors.dataset import DatasetNameDuplicateError from services.errors.document import DocumentIndexingError from services.errors.file import FileNotExistsError +from services.external_knowledge_service import ExternalDatasetService from services.feature_service import FeatureModel, FeatureService from services.tag_service import TagService from services.vector_service import VectorService @@ -56,10 +58,8 @@ from tasks.sync_website_document_indexing_task import sync_website_document_inde class DatasetService: @staticmethod - def get_datasets(page, per_page, provider="vendor", tenant_id=None, user=None, search=None, tag_ids=None): - query = Dataset.query.filter(Dataset.provider == provider, Dataset.tenant_id == tenant_id).order_by( - Dataset.created_at.desc() - ) + def get_datasets(page, per_page, tenant_id=None, user=None, search=None, tag_ids=None): + query = Dataset.query.filter(Dataset.tenant_id == tenant_id).order_by(Dataset.created_at.desc()) if user: # get permitted dataset ids @@ -137,7 +137,14 @@ class DatasetService: @staticmethod def create_empty_dataset( - tenant_id: str, name: str, indexing_technique: Optional[str], account: Account, permission: Optional[str] = None + tenant_id: str, + name: str, + indexing_technique: Optional[str], + account: Account, + permission: Optional[str] = None, + provider: str = "vendor", + external_knowledge_api_id: Optional[str] = None, + external_knowledge_id: Optional[str] = None, ): # check if dataset name already exists if Dataset.query.filter_by(name=name, tenant_id=tenant_id).first(): @@ -156,12 +163,28 @@ class DatasetService: dataset.embedding_model_provider = embedding_model.provider if embedding_model else None dataset.embedding_model = embedding_model.model if embedding_model else None dataset.permission = permission or DatasetPermissionEnum.ONLY_ME + dataset.provider = provider db.session.add(dataset) + db.session.flush() + + if provider == "external" and external_knowledge_api_id: + external_knowledge_api = ExternalDatasetService.get_external_knowledge_api(external_knowledge_api_id) + if not external_knowledge_api: + raise ValueError("External API template not found.") + external_knowledge_binding = ExternalKnowledgeBindings( + tenant_id=tenant_id, + dataset_id=dataset.id, + external_knowledge_api_id=external_knowledge_api_id, + external_knowledge_id=external_knowledge_id, + created_by=account.id, + ) + db.session.add(external_knowledge_binding) + db.session.commit() return dataset @staticmethod - def get_dataset(dataset_id): + def get_dataset(dataset_id) -> Dataset: return Dataset.query.filter_by(id=dataset_id).first() @staticmethod @@ -202,81 +225,103 @@ class DatasetService: @staticmethod def update_dataset(dataset_id, data, user): - data.pop("partial_member_list", None) - filtered_data = {k: v for k, v in data.items() if v is not None or k == "description"} dataset = DatasetService.get_dataset(dataset_id) + DatasetService.check_dataset_permission(dataset, user) - action = None - if dataset.indexing_technique != data["indexing_technique"]: - # if update indexing_technique - if data["indexing_technique"] == "economy": - action = "remove" - filtered_data["embedding_model"] = None - filtered_data["embedding_model_provider"] = None - filtered_data["collection_binding_id"] = None - elif data["indexing_technique"] == "high_quality": - action = "add" - # get embedding model setting - try: - model_manager = ModelManager() - embedding_model = model_manager.get_model_instance( - tenant_id=current_user.current_tenant_id, - provider=data["embedding_model_provider"], - model_type=ModelType.TEXT_EMBEDDING, - model=data["embedding_model"], - ) - filtered_data["embedding_model"] = embedding_model.model - filtered_data["embedding_model_provider"] = embedding_model.provider - dataset_collection_binding = DatasetCollectionBindingService.get_dataset_collection_binding( - embedding_model.provider, embedding_model.model - ) - filtered_data["collection_binding_id"] = dataset_collection_binding.id - except LLMBadRequestError: - raise ValueError( - "No Embedding Model available. Please configure a valid provider " - "in the Settings -> Model Provider." - ) - except ProviderTokenNotInitError as ex: - raise ValueError(ex.description) - else: + if dataset.provider == "external": + dataset.retrieval_model = data.get("external_retrieval_model", None) + dataset.name = data.get("name", dataset.name) + dataset.description = data.get("description", "") + external_knowledge_id = data.get("external_knowledge_id", None) + db.session.add(dataset) + if not external_knowledge_id: + raise ValueError("External knowledge id is required.") + external_knowledge_api_id = data.get("external_knowledge_api_id", None) + if not external_knowledge_api_id: + raise ValueError("External knowledge api id is required.") + external_knowledge_binding = ExternalKnowledgeBindings.query.filter_by(dataset_id=dataset_id).first() if ( - data["embedding_model_provider"] != dataset.embedding_model_provider - or data["embedding_model"] != dataset.embedding_model + external_knowledge_binding.external_knowledge_id != external_knowledge_id + or external_knowledge_binding.external_knowledge_api_id != external_knowledge_api_id ): - action = "update" - try: - model_manager = ModelManager() - embedding_model = model_manager.get_model_instance( - tenant_id=current_user.current_tenant_id, - provider=data["embedding_model_provider"], - model_type=ModelType.TEXT_EMBEDDING, - model=data["embedding_model"], - ) - filtered_data["embedding_model"] = embedding_model.model - filtered_data["embedding_model_provider"] = embedding_model.provider - dataset_collection_binding = DatasetCollectionBindingService.get_dataset_collection_binding( - embedding_model.provider, embedding_model.model - ) - filtered_data["collection_binding_id"] = dataset_collection_binding.id - except LLMBadRequestError: - raise ValueError( - "No Embedding Model available. Please configure a valid provider " - "in the Settings -> Model Provider." - ) - except ProviderTokenNotInitError as ex: - raise ValueError(ex.description) + external_knowledge_binding.external_knowledge_id = external_knowledge_id + external_knowledge_binding.external_knowledge_api_id = external_knowledge_api_id + db.session.add(external_knowledge_binding) + db.session.commit() + else: + data.pop("partial_member_list", None) + filtered_data = {k: v for k, v in data.items() if v is not None or k == "description"} + action = None + if dataset.indexing_technique != data["indexing_technique"]: + # if update indexing_technique + if data["indexing_technique"] == "economy": + action = "remove" + filtered_data["embedding_model"] = None + filtered_data["embedding_model_provider"] = None + filtered_data["collection_binding_id"] = None + elif data["indexing_technique"] == "high_quality": + action = "add" + # get embedding model setting + try: + model_manager = ModelManager() + embedding_model = model_manager.get_model_instance( + tenant_id=current_user.current_tenant_id, + provider=data["embedding_model_provider"], + model_type=ModelType.TEXT_EMBEDDING, + model=data["embedding_model"], + ) + filtered_data["embedding_model"] = embedding_model.model + filtered_data["embedding_model_provider"] = embedding_model.provider + dataset_collection_binding = DatasetCollectionBindingService.get_dataset_collection_binding( + embedding_model.provider, embedding_model.model + ) + filtered_data["collection_binding_id"] = dataset_collection_binding.id + except LLMBadRequestError: + raise ValueError( + "No Embedding Model available. Please configure a valid provider " + "in the Settings -> Model Provider." + ) + except ProviderTokenNotInitError as ex: + raise ValueError(ex.description) + else: + if ( + data["embedding_model_provider"] != dataset.embedding_model_provider + or data["embedding_model"] != dataset.embedding_model + ): + action = "update" + try: + model_manager = ModelManager() + embedding_model = model_manager.get_model_instance( + tenant_id=current_user.current_tenant_id, + provider=data["embedding_model_provider"], + model_type=ModelType.TEXT_EMBEDDING, + model=data["embedding_model"], + ) + filtered_data["embedding_model"] = embedding_model.model + filtered_data["embedding_model_provider"] = embedding_model.provider + dataset_collection_binding = DatasetCollectionBindingService.get_dataset_collection_binding( + embedding_model.provider, embedding_model.model + ) + filtered_data["collection_binding_id"] = dataset_collection_binding.id + except LLMBadRequestError: + raise ValueError( + "No Embedding Model available. Please configure a valid provider " + "in the Settings -> Model Provider." + ) + except ProviderTokenNotInitError as ex: + raise ValueError(ex.description) - filtered_data["updated_by"] = user.id - filtered_data["updated_at"] = datetime.datetime.now() + filtered_data["updated_by"] = user.id + filtered_data["updated_at"] = datetime.datetime.now() - # update Retrieval model - filtered_data["retrieval_model"] = data["retrieval_model"] + # update Retrieval model + filtered_data["retrieval_model"] = data["retrieval_model"] - dataset.query.filter_by(id=dataset_id).update(filtered_data) + dataset.query.filter_by(id=dataset_id).update(filtered_data) - db.session.commit() - if action: - deal_dataset_vector_index_task.delay(dataset_id, action) + db.session.commit() + if action: + deal_dataset_vector_index_task.delay(dataset_id, action) return dataset @staticmethod diff --git a/api/services/entities/external_knowledge_entities/external_knowledge_entities.py b/api/services/entities/external_knowledge_entities/external_knowledge_entities.py new file mode 100644 index 0000000000..4545f385eb --- /dev/null +++ b/api/services/entities/external_knowledge_entities/external_knowledge_entities.py @@ -0,0 +1,26 @@ +from typing import Literal, Optional, Union + +from pydantic import BaseModel + + +class AuthorizationConfig(BaseModel): + type: Literal[None, "basic", "bearer", "custom"] + api_key: Union[None, str] = None + header: Union[None, str] = None + + +class Authorization(BaseModel): + type: Literal["no-auth", "api-key"] + config: Optional[AuthorizationConfig] = None + + +class ProcessStatusSetting(BaseModel): + request_method: str + url: str + + +class ExternalKnowledgeApiSetting(BaseModel): + url: str + request_method: str + headers: Optional[dict] = None + params: Optional[dict] = None diff --git a/api/services/external_knowledge_service.py b/api/services/external_knowledge_service.py new file mode 100644 index 0000000000..4efdf8d7db --- /dev/null +++ b/api/services/external_knowledge_service.py @@ -0,0 +1,274 @@ +import json +from copy import deepcopy +from datetime import datetime, timezone +from typing import Any, Optional, Union + +import httpx +import validators + +# from tasks.external_document_indexing_task import external_document_indexing_task +from core.helper import ssrf_proxy +from extensions.ext_database import db +from models.dataset import ( + Dataset, + ExternalKnowledgeApis, + ExternalKnowledgeBindings, +) +from services.entities.external_knowledge_entities.external_knowledge_entities import ( + Authorization, + ExternalKnowledgeApiSetting, +) +from services.errors.dataset import DatasetNameDuplicateError + + +class ExternalDatasetService: + @staticmethod + def get_external_knowledge_apis(page, per_page, tenant_id, search=None) -> tuple[list[ExternalKnowledgeApis], int]: + query = ExternalKnowledgeApis.query.filter(ExternalKnowledgeApis.tenant_id == tenant_id).order_by( + ExternalKnowledgeApis.created_at.desc() + ) + if search: + query = query.filter(ExternalKnowledgeApis.name.ilike(f"%{search}%")) + + external_knowledge_apis = query.paginate(page=page, per_page=per_page, max_per_page=100, error_out=False) + + return external_knowledge_apis.items, external_knowledge_apis.total + + @classmethod + def validate_api_list(cls, api_settings: dict): + if not api_settings: + raise ValueError("api list is empty") + if "endpoint" not in api_settings and not api_settings["endpoint"]: + raise ValueError("endpoint is required") + if "api_key" not in api_settings and not api_settings["api_key"]: + raise ValueError("api_key is required") + + @staticmethod + def create_external_knowledge_api(tenant_id: str, user_id: str, args: dict) -> ExternalKnowledgeApis: + ExternalDatasetService.check_endpoint_and_api_key(args.get("settings")) + external_knowledge_api = ExternalKnowledgeApis( + tenant_id=tenant_id, + created_by=user_id, + updated_by=user_id, + name=args.get("name"), + description=args.get("description", ""), + settings=json.dumps(args.get("settings"), ensure_ascii=False), + ) + + db.session.add(external_knowledge_api) + db.session.commit() + return external_knowledge_api + + @staticmethod + def check_endpoint_and_api_key(settings: dict): + if "endpoint" not in settings or not settings["endpoint"]: + raise ValueError("endpoint is required") + if "api_key" not in settings or not settings["api_key"]: + raise ValueError("api_key is required") + + endpoint = f"{settings['endpoint']}/retrieval" + api_key = settings["api_key"] + if not validators.url(endpoint): + raise ValueError(f"invalid endpoint: {endpoint}") + try: + response = httpx.post(endpoint, headers={"Authorization": f"Bearer {api_key}"}) + except Exception as e: + raise ValueError(f"failed to connect to the endpoint: {endpoint}") + if response.status_code == 502: + raise ValueError(f"Bad Gateway: failed to connect to the endpoint: {endpoint}") + if response.status_code == 404: + raise ValueError(f"Not Found: failed to connect to the endpoint: {endpoint}") + if response.status_code == 403: + raise ValueError(f"Forbidden: Authorization failed with api_key: {api_key}") + + @staticmethod + def get_external_knowledge_api(external_knowledge_api_id: str) -> ExternalKnowledgeApis: + return ExternalKnowledgeApis.query.filter_by(id=external_knowledge_api_id).first() + + @staticmethod + def update_external_knowledge_api(tenant_id, user_id, external_knowledge_api_id, args) -> ExternalKnowledgeApis: + external_knowledge_api = ExternalKnowledgeApis.query.filter_by( + id=external_knowledge_api_id, tenant_id=tenant_id + ).first() + if external_knowledge_api is None: + raise ValueError("api template not found") + + external_knowledge_api.name = args.get("name") + external_knowledge_api.description = args.get("description", "") + external_knowledge_api.settings = json.dumps(args.get("settings"), ensure_ascii=False) + external_knowledge_api.updated_by = user_id + external_knowledge_api.updated_at = datetime.now(timezone.utc).replace(tzinfo=None) + db.session.commit() + + return external_knowledge_api + + @staticmethod + def delete_external_knowledge_api(tenant_id: str, external_knowledge_api_id: str): + external_knowledge_api = ExternalKnowledgeApis.query.filter_by( + id=external_knowledge_api_id, tenant_id=tenant_id + ).first() + if external_knowledge_api is None: + raise ValueError("api template not found") + + db.session.delete(external_knowledge_api) + db.session.commit() + + @staticmethod + def external_knowledge_api_use_check(external_knowledge_api_id: str) -> tuple[bool, int]: + count = ExternalKnowledgeBindings.query.filter_by(external_knowledge_api_id=external_knowledge_api_id).count() + if count > 0: + return True, count + return False, 0 + + @staticmethod + def get_external_knowledge_binding_with_dataset_id(tenant_id: str, dataset_id: str) -> ExternalKnowledgeBindings: + external_knowledge_binding = ExternalKnowledgeBindings.query.filter_by( + dataset_id=dataset_id, tenant_id=tenant_id + ).first() + if not external_knowledge_binding: + raise ValueError("external knowledge binding not found") + return external_knowledge_binding + + @staticmethod + def document_create_args_validate(tenant_id: str, external_knowledge_api_id: str, process_parameter: dict): + external_knowledge_api = ExternalKnowledgeApis.query.filter_by( + id=external_knowledge_api_id, tenant_id=tenant_id + ).first() + if external_knowledge_api is None: + raise ValueError("api template not found") + settings = json.loads(external_knowledge_api.settings) + for setting in settings: + custom_parameters = setting.get("document_process_setting") + if custom_parameters: + for parameter in custom_parameters: + if parameter.get("required", False) and not process_parameter.get(parameter.get("name")): + raise ValueError(f'{parameter.get("name")} is required') + + @staticmethod + def process_external_api( + settings: ExternalKnowledgeApiSetting, files: Union[None, dict[str, Any]] + ) -> httpx.Response: + """ + do http request depending on api bundle + """ + + kwargs = { + "url": settings.url, + "headers": settings.headers, + "follow_redirects": True, + } + + response = getattr(ssrf_proxy, settings.request_method)(data=json.dumps(settings.params), files=files, **kwargs) + + return response + + @staticmethod + def assembling_headers(authorization: Authorization, headers: Optional[dict] = None) -> dict[str, Any]: + authorization = deepcopy(authorization) + if headers: + headers = deepcopy(headers) + else: + headers = {} + if authorization.type == "api-key": + if authorization.config is None: + raise ValueError("authorization config is required") + + if authorization.config.api_key is None: + raise ValueError("api_key is required") + + if not authorization.config.header: + authorization.config.header = "Authorization" + + if authorization.config.type == "bearer": + headers[authorization.config.header] = f"Bearer {authorization.config.api_key}" + elif authorization.config.type == "basic": + headers[authorization.config.header] = f"Basic {authorization.config.api_key}" + elif authorization.config.type == "custom": + headers[authorization.config.header] = authorization.config.api_key + + return headers + + @staticmethod + def get_external_knowledge_api_settings(settings: dict) -> ExternalKnowledgeApiSetting: + return ExternalKnowledgeApiSetting.parse_obj(settings) + + @staticmethod + def create_external_dataset(tenant_id: str, user_id: str, args: dict) -> Dataset: + # check if dataset name already exists + if Dataset.query.filter_by(name=args.get("name"), tenant_id=tenant_id).first(): + raise DatasetNameDuplicateError(f"Dataset with name {args.get('name')} already exists.") + external_knowledge_api = ExternalKnowledgeApis.query.filter_by( + id=args.get("external_knowledge_api_id"), tenant_id=tenant_id + ).first() + + if external_knowledge_api is None: + raise ValueError("api template not found") + + dataset = Dataset( + tenant_id=tenant_id, + name=args.get("name"), + description=args.get("description", ""), + provider="external", + retrieval_model=args.get("external_retrieval_model"), + created_by=user_id, + ) + + db.session.add(dataset) + db.session.flush() + + external_knowledge_binding = ExternalKnowledgeBindings( + tenant_id=tenant_id, + dataset_id=dataset.id, + external_knowledge_api_id=args.get("external_knowledge_api_id"), + external_knowledge_id=args.get("external_knowledge_id"), + created_by=user_id, + ) + db.session.add(external_knowledge_binding) + + db.session.commit() + + return dataset + + @staticmethod + def fetch_external_knowledge_retrieval( + tenant_id: str, dataset_id: str, query: str, external_retrieval_parameters: dict + ) -> list: + external_knowledge_binding = ExternalKnowledgeBindings.query.filter_by( + dataset_id=dataset_id, tenant_id=tenant_id + ).first() + if not external_knowledge_binding: + raise ValueError("external knowledge binding not found") + + external_knowledge_api = ExternalKnowledgeApis.query.filter_by( + id=external_knowledge_binding.external_knowledge_api_id + ).first() + if not external_knowledge_api: + raise ValueError("external api template not found") + + settings = json.loads(external_knowledge_api.settings) + headers = {"Content-Type": "application/json"} + if settings.get("api_key"): + headers["Authorization"] = f"Bearer {settings.get('api_key')}" + score_threshold_enabled = external_retrieval_parameters.get("score_threshold_enabled") or False + score_threshold = external_retrieval_parameters.get("score_threshold", 0.0) if score_threshold_enabled else 0.0 + request_params = { + "retrieval_setting": { + "top_k": external_retrieval_parameters.get("top_k"), + "score_threshold": score_threshold, + }, + "query": query, + "knowledge_id": external_knowledge_binding.external_knowledge_id, + } + + external_knowledge_api_setting = { + "url": f"{settings.get('endpoint')}/retrieval", + "request_method": "post", + "headers": headers, + "params": request_params, + } + response = ExternalDatasetService.process_external_api( + ExternalKnowledgeApiSetting(**external_knowledge_api_setting), None + ) + if response.status_code == 200: + return response.json().get("records", []) + return [] diff --git a/api/services/hit_testing_service.py b/api/services/hit_testing_service.py index 3dafafd5b4..7957b4dc82 100644 --- a/api/services/hit_testing_service.py +++ b/api/services/hit_testing_service.py @@ -19,7 +19,15 @@ default_retrieval_model = { class HitTestingService: @classmethod - def retrieve(cls, dataset: Dataset, query: str, account: Account, retrieval_model: dict, limit: int = 10) -> dict: + def retrieve( + cls, + dataset: Dataset, + query: str, + account: Account, + retrieval_model: dict, + external_retrieval_model: dict, + limit: int = 10, + ) -> dict: if dataset.available_document_count == 0 or dataset.available_segment_count == 0: return { "query": { @@ -62,10 +70,44 @@ class HitTestingService: return cls.compact_retrieve_response(dataset, query, all_documents) + @classmethod + def external_retrieve( + cls, + dataset: Dataset, + query: str, + account: Account, + external_retrieval_model: dict, + ) -> dict: + if dataset.provider != "external": + return { + "query": {"content": query}, + "records": [], + } + + start = time.perf_counter() + + all_documents = RetrievalService.external_retrieve( + dataset_id=dataset.id, + query=cls.escape_query_for_search(query), + external_retrieval_model=external_retrieval_model, + ) + + end = time.perf_counter() + logging.debug(f"External knowledge hit testing retrieve in {end - start:0.4f} seconds") + + dataset_query = DatasetQuery( + dataset_id=dataset.id, content=query, source="hit_testing", created_by_role="account", created_by=account.id + ) + + db.session.add(dataset_query) + db.session.commit() + + return cls.compact_external_retrieve_response(dataset, query, all_documents) + @classmethod def compact_retrieve_response(cls, dataset: Dataset, query: str, documents: list[Document]): - i = 0 records = [] + for document in documents: index_node_id = document.metadata["doc_id"] @@ -81,7 +123,6 @@ class HitTestingService: ) if not segment: - i += 1 continue record = { @@ -91,8 +132,6 @@ class HitTestingService: records.append(record) - i += 1 - return { "query": { "content": query, @@ -100,6 +139,25 @@ class HitTestingService: "records": records, } + @classmethod + def compact_external_retrieve_response(cls, dataset: Dataset, query: str, documents: list): + records = [] + if dataset.provider == "external": + for document in documents: + record = { + "content": document.get("content", None), + "title": document.get("title", None), + "score": document.get("score", None), + "metadata": document.get("metadata", None), + } + records.append(record) + return { + "query": { + "content": query, + }, + "records": records, + } + @classmethod def hit_testing_args_check(cls, args): query = args["query"] diff --git a/api/tasks/external_document_indexing_task.py b/api/tasks/external_document_indexing_task.py new file mode 100644 index 0000000000..6fc719ae8d --- /dev/null +++ b/api/tasks/external_document_indexing_task.py @@ -0,0 +1,93 @@ +import json +import logging +import time + +import click +from celery import shared_task + +from core.indexing_runner import DocumentIsPausedException +from extensions.ext_database import db +from extensions.ext_storage import storage +from models.dataset import Dataset, ExternalKnowledgeApis +from models.model import UploadFile +from services.external_knowledge_service import ExternalDatasetService + + +@shared_task(queue="dataset") +def external_document_indexing_task( + dataset_id: str, external_knowledge_api_id: str, data_source: dict, process_parameter: dict +): + """ + Async process document + :param dataset_id: + :param external_knowledge_api_id: + :param data_source: + :param process_parameter: + Usage: external_document_indexing_task.delay(dataset_id, document_id) + """ + start_at = time.perf_counter() + + dataset = db.session.query(Dataset).filter(Dataset.id == dataset_id).first() + if not dataset: + logging.info( + click.style("Processed external dataset: {} failed, dataset not exit.".format(dataset_id), fg="red") + ) + return + + # get external api template + external_knowledge_api = ( + db.session.query(ExternalKnowledgeApis) + .filter( + ExternalKnowledgeApis.id == external_knowledge_api_id, ExternalKnowledgeApis.tenant_id == dataset.tenant_id + ) + .first() + ) + + if not external_knowledge_api: + logging.info( + click.style( + "Processed external dataset: {} failed, api template: {} not exit.".format( + dataset_id, external_knowledge_api_id + ), + fg="red", + ) + ) + return + files = {} + if data_source["type"] == "upload_file": + upload_file_list = data_source["info_list"]["file_info_list"]["file_ids"] + for file_id in upload_file_list: + file = ( + db.session.query(UploadFile) + .filter(UploadFile.tenant_id == dataset.tenant_id, UploadFile.id == file_id) + .first() + ) + if file: + files[file.id] = (file.name, storage.load_once(file.key), file.mime_type) + try: + settings = ExternalDatasetService.get_external_knowledge_api_settings( + json.loads(external_knowledge_api.settings) + ) + # assemble headers + headers = ExternalDatasetService.assembling_headers(settings.authorization, settings.headers) + + # do http request + response = ExternalDatasetService.process_external_api(settings, headers, process_parameter, files) + job_id = response.json().get("job_id") + if job_id: + # save job_id to dataset + dataset.job_id = job_id + db.session.commit() + + end_at = time.perf_counter() + logging.info( + click.style( + "Processed external dataset: {} successful, latency: {}".format(dataset.id, end_at - start_at), + fg="green", + ) + ) + except DocumentIsPausedException as ex: + logging.info(click.style(str(ex), fg="yellow")) + + except Exception: + pass diff --git a/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout.tsx b/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout.tsx index e691cc05f6..a58027bcd1 100644 --- a/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout.tsx +++ b/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout.tsx @@ -1,6 +1,6 @@ 'use client' import type { FC, SVGProps } from 'react' -import React, { useEffect } from 'react' +import React, { useEffect, useMemo } from 'react' import { usePathname } from 'next/navigation' import useSWR from 'swr' import { useTranslation } from 'react-i18next' @@ -203,12 +203,23 @@ const DatasetDetailLayout: FC = (props) => { datasetId, }, apiParams => fetchDatasetRelatedApps(apiParams.datasetId)) - const navigation = [ - { name: t('common.datasetMenus.documents'), href: `/datasets/${datasetId}/documents`, icon: DocumentTextIcon, selectedIcon: DocumentTextSolidIcon }, - { name: t('common.datasetMenus.hitTesting'), href: `/datasets/${datasetId}/hitTesting`, icon: TargetIcon, selectedIcon: TargetSolidIcon }, - // { name: 'api & webhook', href: `/datasets/${datasetId}/api`, icon: CommandLineIcon, selectedIcon: CommandLineSolidIcon }, - { name: t('common.datasetMenus.settings'), href: `/datasets/${datasetId}/settings`, icon: Cog8ToothIcon, selectedIcon: Cog8ToothSolidIcon }, - ] + const navigation = useMemo(() => { + const baseNavigation = [ + { name: t('common.datasetMenus.hitTesting'), href: `/datasets/${datasetId}/hitTesting`, icon: TargetIcon, selectedIcon: TargetSolidIcon }, + // { name: 'api & webhook', href: `/datasets/${datasetId}/api`, icon: CommandLineIcon, selectedIcon: CommandLineSolidIcon }, + { name: t('common.datasetMenus.settings'), href: `/datasets/${datasetId}/settings`, icon: Cog8ToothIcon, selectedIcon: Cog8ToothSolidIcon }, + ] + + if (datasetRes?.provider !== 'external') { + baseNavigation.unshift({ + name: t('common.datasetMenus.documents'), + href: `/datasets/${datasetId}/documents`, + icon: DocumentTextIcon, + selectedIcon: DocumentTextSolidIcon, + }) + } + return baseNavigation + }, [datasetRes?.provider, datasetId, t]) useEffect(() => { if (datasetRes) @@ -233,6 +244,7 @@ const DatasetDetailLayout: FC = (props) => { icon={datasetRes?.icon || 'https://static.dify.ai/images/dataset-default-icon.png'} icon_background={datasetRes?.icon_background || '#F5F5F5'} desc={datasetRes?.description || '--'} + isExternal={datasetRes?.provider === 'external'} navigation={navigation} extraInfo={!isCurrentWorkspaceDatasetOperator ? mode => : undefined} iconType={datasetRes?.data_source_type === DataSourceType.NOTION ? 'notion' : 'dataset'} diff --git a/web/app/(commonLayout)/datasets/Container.tsx b/web/app/(commonLayout)/datasets/Container.tsx index f532ca416f..e350a85354 100644 --- a/web/app/(commonLayout)/datasets/Container.tsx +++ b/web/app/(commonLayout)/datasets/Container.tsx @@ -8,6 +8,7 @@ import { useDebounceFn } from 'ahooks' import useSWR from 'swr' // Components +import ExternalAPIPanel from '../../components/datasets/external-api/external-api-panel' import Datasets from './Datasets' import DatasetFooter from './DatasetFooter' import ApiServer from './ApiServer' @@ -16,6 +17,8 @@ import TabSliderNew from '@/app/components/base/tab-slider-new' import SearchInput from '@/app/components/base/search-input' import TagManagementModal from '@/app/components/base/tag-management' import TagFilter from '@/app/components/base/tag-management/filter' +import Button from '@/app/components/base/button' +import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/development' // Services import { fetchDatasetApiBaseUrl } from '@/service/datasets' @@ -24,12 +27,14 @@ import { fetchDatasetApiBaseUrl } from '@/service/datasets' import { useTabSearchParams } from '@/hooks/use-tab-searchparams' import { useStore as useTagStore } from '@/app/components/base/tag-management/store' import { useAppContext } from '@/context/app-context' +import { useExternalApiPanel } from '@/context/external-api-panel-context' const Container = () => { const { t } = useTranslation() const router = useRouter() const { currentWorkspace } = useAppContext() const showTagManagementModal = useTagStore(s => s.showTagManagementModal) + const { showExternalApiPanel, setShowExternalApiPanel } = useExternalApiPanel() const options = useMemo(() => { return [ @@ -66,7 +71,7 @@ const Container = () => { useEffect(() => { if (currentWorkspace.role === 'normal') return router.replace('/apps') - }, [currentWorkspace]) + }, [currentWorkspace, router]) return (
@@ -80,11 +85,18 @@ const Container = () => {
+
+
)} {activeTab === 'api' && data && }
- {activeTab === 'dataset' && ( <> @@ -94,10 +106,10 @@ const Container = () => { )} )} - {activeTab === 'api' && data && } -
+ {showExternalApiPanel && setShowExternalApiPanel(false)} />} +
) } diff --git a/web/app/(commonLayout)/datasets/DatasetCard.tsx b/web/app/(commonLayout)/datasets/DatasetCard.tsx index f66c6bccf4..e8ccddbcb7 100644 --- a/web/app/(commonLayout)/datasets/DatasetCard.tsx +++ b/web/app/(commonLayout)/datasets/DatasetCard.tsx @@ -18,6 +18,7 @@ import Divider from '@/app/components/base/divider' import RenameDatasetModal from '@/app/components/datasets/rename-modal' import type { Tag } from '@/app/components/base/tag-management/constant' import TagSelector from '@/app/components/base/tag-management/selector' +import CornerLabel from '@/app/components/base/corner-label' import { useAppContext } from '@/context/app-context' export type DatasetCardProps = { @@ -32,6 +33,7 @@ const DatasetCard = ({ const { t } = useTranslation() const { notify } = useContext(ToastContext) const { push } = useRouter() + const EXTERNAL_PROVIDER = 'external' as const const { isCurrentWorkspaceDatasetOperator } = useAppContext() const [tags, setTags] = useState(dataset.tags) @@ -39,6 +41,7 @@ const DatasetCard = ({ const [showRenameModal, setShowRenameModal] = useState(false) const [showConfirmDelete, setShowConfirmDelete] = useState(false) const [confirmMessage, setConfirmMessage] = useState('') + const isExternalProvider = (provider: string): boolean => provider === EXTERNAL_PROVIDER const detectIsUsedByApp = useCallback(async () => { try { const { is_using: isUsedByApp } = await checkIsUsedInApp(dataset.id) @@ -108,13 +111,16 @@ const DatasetCard = ({ return ( <>
{ e.preventDefault() - push(`/datasets/${dataset.id}/documents`) + isExternalProvider(dataset.provider) + ? push(`/datasets/${dataset.id}/hitTesting`) + : push(`/datasets/${dataset.id}/documents`) }} > + {isExternalProvider(dataset.provider) && }
- {dataset.document_count}{t('dataset.documentCount')} - · - {Math.round(dataset.word_count / 1000)}{t('dataset.wordCount')} - · - {dataset.app_count}{t('dataset.appCount')} + {dataset.provider === 'external' + ? <> + {dataset.app_count}{t('dataset.appCount')} + + : <> + {dataset.document_count}{t('dataset.documentCount')} + · + {Math.round(dataset.word_count / 1000)}{t('dataset.wordCount')} + · + {dataset.app_count}{t('dataset.appCount')} + + }
diff --git a/web/app/(commonLayout)/datasets/NewDatasetCard.tsx b/web/app/(commonLayout)/datasets/NewDatasetCard.tsx index f76efa5769..5dd244ad41 100644 --- a/web/app/(commonLayout)/datasets/NewDatasetCard.tsx +++ b/web/app/(commonLayout)/datasets/NewDatasetCard.tsx @@ -4,21 +4,32 @@ import { forwardRef } from 'react' import { useTranslation } from 'react-i18next' import { RiAddLine, + RiArrowRightLine, } from '@remixicon/react' const CreateAppCard = forwardRef((_, ref) => { const { t } = useTranslation() return ( - -
- ) }) diff --git a/web/app/(commonLayout)/datasets/connect/page.tsx b/web/app/(commonLayout)/datasets/connect/page.tsx new file mode 100644 index 0000000000..724c506a7f --- /dev/null +++ b/web/app/(commonLayout)/datasets/connect/page.tsx @@ -0,0 +1,8 @@ +import React from 'react' +import ExternalKnowledgeBaseConnector from '@/app/components/datasets/external-knowledge-base/connector' + +const ExternalKnowledgeBaseCreation = () => { + return +} + +export default ExternalKnowledgeBaseCreation diff --git a/web/app/(commonLayout)/datasets/layout.tsx b/web/app/(commonLayout)/datasets/layout.tsx new file mode 100644 index 0000000000..aecb537aa6 --- /dev/null +++ b/web/app/(commonLayout)/datasets/layout.tsx @@ -0,0 +1,14 @@ +'use client' + +import { ExternalApiPanelProvider } from '@/context/external-api-panel-context' +import { ExternalKnowledgeApiProvider } from '@/context/external-knowledge-api-context' + +export default function DatasetsLayout({ children }: { children: React.ReactNode }) { + return ( + + + {children} + + + ) +} diff --git a/web/app/(commonLayout)/datasets/page.tsx b/web/app/(commonLayout)/datasets/page.tsx index 5aa11aa275..096a1b8979 100644 --- a/web/app/(commonLayout)/datasets/page.tsx +++ b/web/app/(commonLayout)/datasets/page.tsx @@ -1,9 +1,7 @@ import Container from './Container' const AppList = async () => { - return ( - - ) + return } export const metadata = { diff --git a/web/app/(commonLayout)/datasets/store.ts b/web/app/(commonLayout)/datasets/store.ts new file mode 100644 index 0000000000..40b7b15594 --- /dev/null +++ b/web/app/(commonLayout)/datasets/store.ts @@ -0,0 +1,11 @@ +import { create } from 'zustand' + +type DatasetStore = { + showExternalApiPanel: boolean + setShowExternalApiPanel: (show: boolean) => void +} + +export const useDatasetStore = create(set => ({ + showExternalApiPanel: false, + setShowExternalApiPanel: show => set({ showExternalApiPanel: show }), +})) diff --git a/web/app/components/app-sidebar/basic.tsx b/web/app/components/app-sidebar/basic.tsx index c939cb7bb3..51fc10721e 100644 --- a/web/app/components/app-sidebar/basic.tsx +++ b/web/app/components/app-sidebar/basic.tsx @@ -1,4 +1,5 @@ import React from 'react' +import { useTranslation } from 'react-i18next' import AppIcon from '../base/app-icon' import Tooltip from '@/app/components/base/tooltip' @@ -6,6 +7,7 @@ export type IAppBasicProps = { iconType?: 'app' | 'api' | 'dataset' | 'webapp' | 'notion' icon?: string icon_background?: string | null + isExternal?: boolean name: string type: string | React.ReactNode hoverTip?: string @@ -52,7 +54,9 @@ const ICON_MAP = { notion: , } -export default function AppBasic({ icon, icon_background, name, type, hoverTip, textStyle, mode = 'expand', iconType = 'app' }: IAppBasicProps) { +export default function AppBasic({ icon, icon_background, name, isExternal, type, hoverTip, textStyle, mode = 'expand', iconType = 'app' }: IAppBasicProps) { + const { t } = useTranslation() + return (
{icon && icon_background && iconType === 'app' && ( @@ -83,6 +87,7 @@ export default function AppBasic({ icon, icon_background, name, type, hoverTip, }
{type}
+
{isExternal ? t('dataset.externalTag') : ''}
}
) diff --git a/web/app/components/app-sidebar/index.tsx b/web/app/components/app-sidebar/index.tsx index 5d5d407dc0..5ee063ad64 100644 --- a/web/app/components/app-sidebar/index.tsx +++ b/web/app/components/app-sidebar/index.tsx @@ -15,6 +15,7 @@ export type IAppDetailNavProps = { iconType?: 'app' | 'dataset' | 'notion' title: string desc: string + isExternal?: boolean icon: string icon_background: string navigation: Array<{ @@ -26,7 +27,7 @@ export type IAppDetailNavProps = { extraInfo?: (modeState: string) => React.ReactNode } -const AppDetailNav = ({ title, desc, icon, icon_background, navigation, extraInfo, iconType = 'app' }: IAppDetailNavProps) => { +const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigation, extraInfo, iconType = 'app' }: IAppDetailNavProps) => { const { appSidebarExpand, setAppSiderbarExpand } = useAppStore(useShallow(state => ({ appSidebarExpand: state.appSidebarExpand, setAppSiderbarExpand: state.setAppSiderbarExpand, @@ -70,6 +71,7 @@ const AppDetailNav = ({ title, desc, icon, icon_background, navigation, extraInf icon_background={icon_background} name={title} type={desc} + isExternal={isExternal} /> )} diff --git a/web/app/components/app/configuration/dataset-config/card-item/item.tsx b/web/app/components/app/configuration/dataset-config/card-item/item.tsx index 184a598e10..9c5e6fa785 100644 --- a/web/app/components/app/configuration/dataset-config/card-item/item.tsx +++ b/web/app/components/app/configuration/dataset-config/card-item/item.tsx @@ -5,6 +5,7 @@ import { RiDeleteBinLine, RiEditLine, } from '@remixicon/react' +import { useTranslation } from 'react-i18next' import SettingsModal from '../settings-modal' import type { DataSet } from '@/models/datasets' import { DataSourceType } from '@/models/datasets' @@ -33,6 +34,7 @@ const Item: FC = ({ const isMobile = media === MediaType.mobile const [showSettingsModal, setShowSettingsModal] = useState(false) const { formatIndexingTechniqueAndMethod } = useKnowledge() + const { t } = useTranslation() const handleSave = (newDataset: DataSet) => { onSave(newDataset) @@ -65,9 +67,11 @@ const Item: FC = ({
{config.name}
- + {config.provider === 'external' + ? + : }
diff --git a/web/app/components/app/configuration/dataset-config/params-config/config-content.tsx b/web/app/components/app/configuration/dataset-config/params-config/config-content.tsx index 91cae54bb8..f99496b14f 100644 --- a/web/app/components/app/configuration/dataset-config/params-config/config-content.tsx +++ b/web/app/components/app/configuration/dataset-config/params-config/config-content.tsx @@ -174,6 +174,20 @@ const ConfigContent: FC = ({
) } + { + selectedDatasetsMode.mixtureInternalAndExternal && ( +
+ {t('dataset.mixtureInternalAndExternalTip')} +
+ ) + } + { + selectedDatasetsMode.allExternal && ( +
+ {t('dataset.allExternalTip')} +
+ ) + } { selectedDatasetsMode.mixtureHighQualityAndEconomic && ( @@ -229,15 +243,15 @@ const ConfigContent: FC = ({ /> ) } -
{t('common.modelProvider.rerankModel.key')}
+
{t('common.modelProvider.rerankModel.key')}
{t('common.modelProvider.rerankModel.tip')} } - popupClassName='ml-0.5' - triggerClassName='ml-0.5 w-3.5 h-3.5' + popupClassName='ml-1' + triggerClassName='ml-1 w-4 h-4' />
diff --git a/web/app/components/app/configuration/dataset-config/params-config/index.tsx b/web/app/components/app/configuration/dataset-config/params-config/index.tsx index 656cbfea65..2d3df0b039 100644 --- a/web/app/components/app/configuration/dataset-config/params-config/index.tsx +++ b/web/app/components/app/configuration/dataset-config/params-config/index.tsx @@ -39,13 +39,26 @@ const ParamsConfig = ({ useEffect(() => { const { allEconomic, + allHighQuality, + allHighQualityFullTextSearch, + allHighQualityVectorSearch, + allExternal, + mixtureHighQualityAndEconomic, + inconsistentEmbeddingModel, + mixtureInternalAndExternal, } = getSelectedDatasetsMode(selectedDatasets) const { datasets, retrieval_model, score_threshold_enabled, ...restConfigs } = datasetConfigs let rerankEnable = restConfigs.reranking_enable - if (allEconomic && !restConfigs.reranking_model?.reranking_provider_name && rerankEnable === undefined) + if ((allEconomic && !restConfigs.reranking_model?.reranking_provider_name && rerankEnable === undefined) || allExternal) rerankEnable = false + if (allEconomic || allHighQuality || allHighQualityFullTextSearch || allHighQualityVectorSearch || (allExternal && selectedDatasets.length === 1)) + setRerankSettingModalOpen(false) + + if (mixtureHighQualityAndEconomic || inconsistentEmbeddingModel || mixtureInternalAndExternal || (allExternal && selectedDatasets.length > 1)) + setRerankSettingModalOpen(true) + setTempDataSetConfigs({ ...getMultipleRetrievalConfig({ top_k: restConfigs.top_k, diff --git a/web/app/components/app/configuration/dataset-config/select-dataset/index.tsx b/web/app/components/app/configuration/dataset-config/select-dataset/index.tsx index 4493755ba0..0d94e599b4 100644 --- a/web/app/components/app/configuration/dataset-config/select-dataset/index.tsx +++ b/web/app/components/app/configuration/dataset-config/select-dataset/index.tsx @@ -47,7 +47,7 @@ const SelectDataSet: FC = ({ const { data, has_more } = await fetchDatasets({ url: '/datasets', params: { page } }) setPage(getPage() + 1) setIsNoMore(!has_more) - const newList = [...(datasets || []), ...data.filter(item => item.indexing_technique)] + const newList = [...(datasets || []), ...data.filter(item => item.indexing_technique || item.provider === 'external')] setDataSets(newList) setLoaded(true) if (!selected.find(item => !item.name)) @@ -145,6 +145,11 @@ const SelectDataSet: FC = ({ /> ) } + { + item.provider === 'external' && ( + + ) + }
))} diff --git a/web/app/components/app/configuration/dataset-config/settings-modal/index.tsx b/web/app/components/app/configuration/dataset-config/settings-modal/index.tsx index e538c347d9..7b3b4abc0f 100644 --- a/web/app/components/app/configuration/dataset-config/settings-modal/index.tsx +++ b/web/app/components/app/configuration/dataset-config/settings-modal/index.tsx @@ -5,8 +5,10 @@ import { useTranslation } from 'react-i18next' import { isEqual } from 'lodash-es' import { RiCloseLine } from '@remixicon/react' import { BookOpenIcon } from '@heroicons/react/24/outline' +import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/development' import cn from '@/utils/classnames' import IndexMethodRadio from '@/app/components/datasets/settings/index-method-radio' +import Divider from '@/app/components/base/divider' import Button from '@/app/components/base/button' import type { DataSet } from '@/models/datasets' import { useToastContext } from '@/app/components/base/toast' @@ -14,6 +16,7 @@ import { updateDatasetSetting } from '@/service/datasets' import { useAppContext } from '@/context/app-context' import { useModalContext } from '@/context/modal-context' import type { RetrievalConfig } from '@/types/app' +import RetrievalSettings from '@/app/components/datasets/external-knowledge-base/create/RetrievalSettings' import RetrievalMethodConfig from '@/app/components/datasets/common/retrieval-method-config' import EconomicalRetrievalMethodConfig from '@/app/components/datasets/common/economical-retrieval-method-config' import { ensureRerankModelSelected, isReRankModelSelected } from '@/app/components/datasets/common/check-rerank-model' @@ -56,6 +59,9 @@ const SettingsModal: FC = ({ const { t } = useTranslation() const { notify } = useToastContext() const ref = useRef(null) + const [topK, setTopK] = useState(currentDataset?.external_retrieval_model.top_k ?? 2) + const [scoreThreshold, setScoreThreshold] = useState(currentDataset?.external_retrieval_model.score_threshold ?? 0.5) + const [scoreThresholdEnabled, setScoreThresholdEnabled] = useState(currentDataset?.external_retrieval_model.score_threshold_enabled ?? false) const { setShowAccountSettingModal } = useModalContext() const [loading, setLoading] = useState(false) @@ -73,6 +79,15 @@ const SettingsModal: FC = ({ const [isHideChangedTip, setIsHideChangedTip] = useState(false) const isRetrievalChanged = !isEqual(retrievalConfig, localeCurrentDataset?.retrieval_model_dict) || indexMethod !== localeCurrentDataset?.indexing_technique + const handleSettingsChange = (data: { top_k?: number; score_threshold?: number; score_threshold_enabled?: boolean }) => { + if (data.top_k !== undefined) + setTopK(data.top_k) + if (data.score_threshold !== undefined) + setScoreThreshold(data.score_threshold) + if (data.score_threshold_enabled !== undefined) + setScoreThresholdEnabled(data.score_threshold_enabled) + } + const handleSave = async () => { if (loading) return @@ -107,10 +122,17 @@ const SettingsModal: FC = ({ description, permission, indexing_technique: indexMethod, + external_retrieval_model: { + top_k: topK, + score_threshold: scoreThreshold, + score_threshold_enabled: scoreThresholdEnabled, + }, retrieval_model: { ...postRetrievalConfig, score_threshold: postRetrievalConfig.score_threshold_enabled ? postRetrievalConfig.score_threshold : 0, }, + external_knowledge_id: currentDataset!.external_knowledge_info.external_knowledge_id, + external_knowledge_api_id: currentDataset!.external_knowledge_info.external_knowledge_api_id, embedding_model: localeCurrentDataset.embedding_model, embedding_model_provider: localeCurrentDataset.embedding_model_provider, }, @@ -178,7 +200,7 @@ const SettingsModal: FC = ({ }}>
- {t('datasetSettings.form.name')} +
{t('datasetSettings.form.name')}
= ({
- {t('datasetSettings.form.desc')} +
{t('datasetSettings.form.desc')}

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®^aQ5#KOZ7pfex#L4ou3P%--2~N$WQyBD=d{3 zPC7W~%0dwml#H8p1@M`=M6Me|pVjHYaJ@m9)g(L?A4Wn6LnGFtb)s;VldHbtElN&k zP!*%7Dg!w|>5hFOij(EUFc!XHjnkkTa&a9Ad-V_I^{&oLkwKqzU}qfRtKqEOcvxP< z#oudv?iK(}zP3Jzy*PC7a~BW%Mn$UNdN*T=VN zhHIBxj|>wr^1%E@-EwKcNgqfZrQpnW=sxfGd9UVlDSVBJ~NO z1D;1)pr`JNKHEEikNmVY{LK$bDfwzSasAp(sJY9O=`#2dlzw%r)_#BOIfCNJjYw$s zYjF_s0_99h$F0(!`iH2)rP5_ZH39dsq{h~!`I*JE<&uU9tCUvcR>|@0&O>o9sWK zUA5wq!Wss}3?JXBg@X$hc3{%`ODJMw)oQ*!z^_^cyKRCgRjLZ#GNLHS*N1uvW{s~$ zp5$MU=iCTQv*tgx(OR|&^~+SI%&bJu)H$sL^#xyB8{xk_Shn!MV~IHBeYkg|&@lTQ zVPGpttG6k#*kyKiw>0IR+6jJnmk(6Epq-5jmf=>xTAjmdUXOi@y5=9|ml$r_KL>A3 zabK$*ON!r=ZBtrJYM*W_6umPoxu_S!-0D?PS&DyMy!rV_$oxSZ1_5FYg@^!6fRq(8 z>HM)dT6U|_mK7F5MYi2*6}v85T-+vBevE$L`tm`&0i_EQcxV}h)qd?OU~X^v3Hg3? z((f2SF1_N!VequKtwQH1XPq|Zpx8>Q$*Kqb*B!2 zlrOMWsd%BFG&5Krw%T@tk%DRE7$CA4QC42u{0Pp~Cx;GeJkR{p#Em^+@)8+!pla=G zd5kuojB|;8v=^;NRj9Pt{E%%sJ6)imFPaKr3