Compare commits
1017
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7b2fe1e8b | ||
|
|
fac9459402 | ||
|
|
6cf0e0c242 | ||
|
|
656bd9257d | ||
|
|
38441c930c | ||
|
|
dafdbfa0fd | ||
|
|
a264973366 | ||
|
|
5843b30a13 | ||
|
|
340ae3c52f | ||
|
|
817e16493f | ||
|
|
66cf787755 | ||
|
|
4f3872277c | ||
|
|
9b84086bac | ||
|
|
ce2b2755af | ||
|
|
a91bec033d | ||
|
|
096cc74373 | ||
|
|
34db42ecea | ||
|
|
34e8d2f6bb | ||
|
|
a771d59b1e | ||
|
|
3a00941125 | ||
|
|
8e9ade14df | ||
|
|
a1ec45fdd1 | ||
|
|
9295739dc0 | ||
|
|
4afb16844c | ||
|
|
c4e6ed1aa2 | ||
|
|
95c5848d05 | ||
|
|
8e56096f83 | ||
|
|
c8f51dd6db | ||
|
|
ebbb30de44 | ||
|
|
fe1168d15a | ||
|
|
fd7fded6e5 | ||
|
|
8cffbc6b2a | ||
|
|
fa673f9b4c | ||
|
|
178f1fc5d6 | ||
|
|
0c409e2b9e | ||
|
|
e366e12be0 | ||
|
|
8e0d8fdb3f | ||
|
|
524b19bb3a | ||
|
|
fb2e351c08 | ||
|
|
260fef40c4 | ||
|
|
72818e946d | ||
|
|
e673c64534 | ||
|
|
93bbb2694f | ||
|
|
b038b7aa33 | ||
|
|
02a059bdc6 | ||
|
|
267d9568c6 | ||
|
|
d71eae8f93 | ||
|
|
8bdaab96b1 | ||
|
|
a05fcedd61 | ||
|
|
0db67a2fd3 | ||
|
|
6e56a504fd | ||
|
|
69fa8c9794 | ||
|
|
8dc8650ecb | ||
|
|
40775e27ce | ||
|
|
6fb294202d | ||
|
|
bd409a3caf | ||
|
|
0d0da9a892 | ||
|
|
a7e2f9caf0 | ||
|
|
3d4d60a353 | ||
|
|
75e876b14e | ||
|
|
66fd60bc6f | ||
|
|
c3e7299494 | ||
|
|
8fc576870d | ||
|
|
d4f362164f | ||
|
|
94ca0edb68 | ||
|
|
a0dde6e4da | ||
|
|
17f572f23f | ||
|
|
137746387d | ||
|
|
9b5deaf80a | ||
|
|
1201bef879 | ||
|
|
30a9b8b917 | ||
|
|
77bdc6ffb1 | ||
|
|
a65c99496b | ||
|
|
a8c86b759d | ||
|
|
76081db6e4 | ||
|
|
0606b6f922 | ||
|
|
9ed2a99abf | ||
|
|
8f311b020a | ||
|
|
de6cbc36bb | ||
|
|
0aa984219f | ||
|
|
c9168c19cd | ||
|
|
beca05848c | ||
|
|
2e5acef1b6 | ||
|
|
c4811f921f | ||
|
|
7569346943 | ||
|
|
2919cc9adf | ||
|
|
18883d9faa | ||
|
|
e462ddb805 | ||
|
|
df274416f9 | ||
|
|
b35d9f6c36 | ||
|
|
4c5737fc7f | ||
|
|
7bb1decaf8 | ||
|
|
4bef2eed25 | ||
|
|
0d2a90adf3 | ||
|
|
38a1ea139a | ||
|
|
698eb9671f | ||
|
|
1b857eba29 | ||
|
|
b060b773ef | ||
|
|
ae197fb2ba | ||
|
|
2697454a8e | ||
|
|
2a75258836 | ||
|
|
b50f221327 | ||
|
|
d984eb3648 | ||
|
|
4df8fa0afb | ||
|
|
67b3ee3776 | ||
|
|
8337e3c6ba | ||
|
|
a9b8917e22 | ||
|
|
70698b553e | ||
|
|
b131c5dc73 | ||
|
|
15e2ab9203 | ||
|
|
d5c79e0489 | ||
|
|
884eeebe83 | ||
|
|
9042db301d | ||
|
|
f4f8d6c652 | ||
|
|
20cd3e52d0 | ||
|
|
53fa4ffe73 | ||
|
|
8acd6f2531 | ||
|
|
8d8bbc586e | ||
|
|
df4e1339da | ||
|
|
0183651cd5 | ||
|
|
9f024835aa | ||
|
|
45017f3f35 | ||
|
|
089072432e | ||
|
|
6e600bc0dc | ||
|
|
25995eb735 | ||
|
|
28dc089540 | ||
|
|
8967c4c8f6 | ||
|
|
3969ed6f69 | ||
|
|
56b025ebdd | ||
|
|
aab5566d98 | ||
|
|
a9e44b1fd2 | ||
|
|
bae1bc2e4b | ||
|
|
b9f58d3c1d | ||
|
|
7c7f3958ff | ||
|
|
85da94aac4 | ||
|
|
5350753905 | ||
|
|
e7895cdc53 | ||
|
|
b84d4bdb85 | ||
|
|
66538d8cbd | ||
|
|
4e24e116aa | ||
|
|
3f13c47b9b | ||
|
|
10237c99e4 | ||
|
|
faf936416f | ||
|
|
779f77ccd6 | ||
|
|
758b8bf812 | ||
|
|
c61f51dc5d | ||
|
|
b17e30b1c2 | ||
|
|
0756b09cf5 | ||
|
|
2f16b3600c | ||
|
|
55d2417906 | ||
|
|
49dd5b76f1 | ||
|
|
43429108f5 | ||
|
|
18159b1a4b | ||
|
|
b31da3b195 | ||
|
|
17b7426cc6 | ||
|
|
ba7b9a595b | ||
|
|
7778901630 | ||
|
|
8f7356cc12 | ||
|
|
d49834ee56 | ||
|
|
e4fdf1730e | ||
|
|
f41a619490 | ||
|
|
1607fcfaa7 | ||
|
|
8386abaed1 | ||
|
|
16a1562900 | ||
|
|
9b1869f521 | ||
|
|
3dfcd9ca67 | ||
|
|
74408c4ced | ||
|
|
653917649d | ||
|
|
00f51749a3 | ||
|
|
8d3158a6d5 | ||
|
|
dbaf54c93d | ||
|
|
7762737796 | ||
|
|
133d52deb9 | ||
|
|
0ede136d67 | ||
|
|
8d82d9f7ef | ||
|
|
1532564601 | ||
|
|
24ac4996c0 | ||
|
|
112593119a | ||
|
|
0c100ac0b1 | ||
|
|
45168d0e00 | ||
|
|
dc91b2e3df | ||
|
|
ced6a5c18b | ||
|
|
0b7cdd1e5d | ||
|
|
67de047122 | ||
|
|
4ec14d8d91 | ||
|
|
09516726e9 | ||
|
|
6bfd61a887 | ||
|
|
a436550dff | ||
|
|
f5a3069913 | ||
|
|
cf0c96e0d1 | ||
|
|
978ee93df7 | ||
|
|
f3bf4c7730 | ||
|
|
d2de16fba2 | ||
|
|
90543c458c | ||
|
|
d6e655eaae | ||
|
|
9884466ef0 | ||
|
|
3b4676d8e9 | ||
|
|
3ee9f74cf8 | ||
|
|
1c7573a686 | ||
|
|
2da7cc6928 | ||
|
|
fda802e796 | ||
|
|
5a5beb5b59 | ||
|
|
a0b16e541c | ||
|
|
a67777b8e2 | ||
|
|
eae4c80679 | ||
|
|
ac63b5385a | ||
|
|
f61ceadec5 | ||
|
|
5ff2fbed59 | ||
|
|
d24cf9e56a | ||
|
|
7b9fbccf60 | ||
|
|
0b07c6914a | ||
|
|
f803fb5855 | ||
|
|
cd3c2f6b00 | ||
|
|
587ba27f8c | ||
|
|
1b0acdbe63 | ||
|
|
3e810bc490 | ||
|
|
cc86850ad9 | ||
|
|
fed19db938 | ||
|
|
9175eb455f | ||
|
|
a89287bf20 | ||
|
|
977020f580 | ||
|
|
a2195c813c | ||
|
|
d5a404236a | ||
|
|
202492e5ac | ||
|
|
601e888fde | ||
|
|
4a483a8754 | ||
|
|
a4f367b8ff | ||
|
|
e225a3d33c | ||
|
|
31b6383697 | ||
|
|
e7d6def1e8 | ||
|
|
197c0bb1a3 | ||
|
|
d6953f28d3 | ||
|
|
249f013ca3 | ||
|
|
387a6cfee4 | ||
|
|
81cbf2e713 | ||
|
|
e66c55ba9e | ||
|
|
56044a104c | ||
|
|
c409ab4c3c | ||
|
|
487efcb206 | ||
|
|
4eb7546177 | ||
|
|
4b561aec93 | ||
|
|
34695f02fb | ||
|
|
aa421269c4 | ||
|
|
09cfbe117e | ||
|
|
0ea233edbe | ||
|
|
d69e0a79d4 | ||
|
|
7320ac41af | ||
|
|
08b1f5d7c3 | ||
|
|
61b41ca04b | ||
|
|
8d4f40bc7c | ||
|
|
3e9c7dccc0 | ||
|
|
672b8f14f2 | ||
|
|
513d075ebc | ||
|
|
8d34082246 | ||
|
|
5ed181dd42 | ||
|
|
9d8f9f6f63 | ||
|
|
8e8c39a88c | ||
|
|
41d9fdee50 | ||
|
|
9e37021387 | ||
|
|
bf06be0c75 | ||
|
|
a93a2e2e0c | ||
|
|
02337cbb09 | ||
|
|
c35c0fc6f4 | ||
|
|
1482eb0348 | ||
|
|
cbe7116bb7 | ||
|
|
788550affa | ||
|
|
25949338cb | ||
|
|
958da42f74 | ||
|
|
6e8ea528c2 | ||
|
|
d537efe97a | ||
|
|
0439276866 | ||
|
|
69c8e4ddd1 | ||
|
|
711f7107b4 | ||
|
|
ea4476ac6e | ||
|
|
13dbc7f0ce | ||
|
|
b8ecfd859b | ||
|
|
4daf93ef4f | ||
|
|
90b7ca1df1 | ||
|
|
96f38b2d15 | ||
|
|
8a27e51658 | ||
|
|
8ecec84dcf | ||
|
|
a2b3096159 | ||
|
|
80f1fbba56 | ||
|
|
d8ab611480 | ||
|
|
722ff7795d | ||
|
|
73c2b35dfe | ||
|
|
b99eadecf6 | ||
|
|
843db3dbdf | ||
|
|
3b660f1698 | ||
|
|
a2e30e6aa9 | ||
|
|
9638885a67 | ||
|
|
cd01c890e1 | ||
|
|
552ccb058b | ||
|
|
36180b1001 | ||
|
|
65ed4dc91f | ||
|
|
c709e339b1 | ||
|
|
3cf8416484 | ||
|
|
d2d47d0e0e | ||
|
|
05f97f6e06 | ||
|
|
11dfdb236d | ||
|
|
6df520ebc6 | ||
|
|
a047a98462 | ||
|
|
1df68a546e | ||
|
|
5013ea09d5 | ||
|
|
d92d952e76 | ||
|
|
4af304e6ae | ||
|
|
5c4d1c52ee | ||
|
|
5ee7fc4fde | ||
|
|
b0cf8c00db | ||
|
|
338dd1c714 | ||
|
|
af9ae91934 | ||
|
|
d122daca87 | ||
|
|
ec49da073e | ||
|
|
62846be275 | ||
|
|
6b9cc927c0 | ||
|
|
a577db9ddd | ||
|
|
e5c8743712 | ||
|
|
777cca1a09 | ||
|
|
e3c65c072c | ||
|
|
9b069bd3d4 | ||
|
|
56c53d1f07 | ||
|
|
6146f24932 | ||
|
|
9908a8bf1f | ||
|
|
e33260d2e2 | ||
|
|
5713ee5fce | ||
|
|
129a68bb06 | ||
|
|
aff5ab933b | ||
|
|
4835358f24 | ||
|
|
9b57b4c6c8 | ||
|
|
785dfc5c00 | ||
|
|
12eb236364 | ||
|
|
1cfeb989f7 | ||
|
|
ede65eca4d | ||
|
|
dc53362506 | ||
|
|
74e644be1c | ||
|
|
6e51ce123c | ||
|
|
737321da75 | ||
|
|
72d2f76d24 | ||
|
|
87a36a1fc8 | ||
|
|
c2ded79cb2 | ||
|
|
fb6e5bf4d5 | ||
|
|
6633a92e1a | ||
|
|
44c4d5be72 | ||
|
|
5a67c09b48 | ||
|
|
0614ddde7d | ||
|
|
e5ff06bcb7 | ||
|
|
6b19ba3bb2 | ||
|
|
735b55e61b | ||
|
|
7e53625eae | ||
|
|
5213b0aade | ||
|
|
2b4b6817a3 | ||
|
|
da3e1e9d14 | ||
|
|
e4794e309a | ||
|
|
e6572ef2d7 | ||
|
|
2182533af8 | ||
|
|
d88ac6c238 | ||
|
|
e8751bebfa | ||
|
|
92c1da8dbe | ||
|
|
951aaf5161 | ||
|
|
a420953385 | ||
|
|
b102562614 | ||
|
|
2c2b9e7389 | ||
|
|
513a8655b1 | ||
|
|
d3385a2715 | ||
|
|
ebf9c41adb | ||
|
|
7372776992 | ||
|
|
7f7269d261 | ||
|
|
f2bb0012fd | ||
|
|
33113034ea | ||
|
|
88c29f613f | ||
|
|
f318fa058c | ||
|
|
407bfb8182 | ||
|
|
91845fc9f6 | ||
|
|
f911b1c488 | ||
|
|
7a6fa3655f | ||
|
|
5eb7b4d56a | ||
|
|
5e4bd9fc38 | ||
|
|
f8cba2679e | ||
|
|
e0883302d2 | ||
|
|
a0a1618869 | ||
|
|
be68369983 | ||
|
|
9d0a832e40 | ||
|
|
8031262006 | ||
|
|
751489fa54 | ||
|
|
1e6feadc7e | ||
|
|
2d8497f79b | ||
|
|
61a1aadf9c | ||
|
|
8b832097de | ||
|
|
7e4daf131e | ||
|
|
de3978fdbb | ||
|
|
51f6ab49cf | ||
|
|
2895c3bc8c | ||
|
|
3d5f9b5a1e | ||
|
|
614bc2e075 | ||
|
|
193bcce236 | ||
|
|
a0fd731170 | ||
|
|
2f57d090a1 | ||
|
|
4c5822fb6e | ||
|
|
e90637f67a | ||
|
|
9b0f83f807 | ||
|
|
fc573564b4 | ||
|
|
5596b3b00b | ||
|
|
cb02b1e12e | ||
|
|
736e386f15 | ||
|
|
c152d55f68 | ||
|
|
1a0b6adc2c | ||
|
|
1914dfea77 | ||
|
|
1f986a3abb | ||
|
|
b174f85237 | ||
|
|
2ad9c76093 | ||
|
|
8684b172d2 | ||
|
|
3e54cb26be | ||
|
|
079cc082a3 | ||
|
|
a1bc6b50c5 | ||
|
|
7d28fe8ea5 | ||
|
|
dd50deaa43 | ||
|
|
79a10e9729 | ||
|
|
a5de7b10f3 | ||
|
|
bc4edbfc2b | ||
|
|
75f1355d4c | ||
|
|
1a86e79d4a | ||
|
|
c8a1f923f5 | ||
|
|
df753e84a3 | ||
|
|
3086893ee7 | ||
|
|
242fcf0145 | ||
|
|
de40422205 | ||
|
|
df809ff435 | ||
|
|
75559bcbf9 | ||
|
|
d9b8a938c6 | ||
|
|
e9004a06a5 | ||
|
|
be709d4b84 | ||
|
|
602bc67495 | ||
|
|
e498efce2d | ||
|
|
09dfe80718 | ||
|
|
06b05163f6 | ||
|
|
b80092ea12 | ||
|
|
2eaae6742a | ||
|
|
3f5d1a79c6 | ||
|
|
15c7e0ec2f | ||
|
|
43b0440358 | ||
|
|
9651a208a9 | ||
|
|
7bff65304f | ||
|
|
8a8882ed8d | ||
|
|
9467fe9aa9 | ||
|
|
799db69e4f | ||
|
|
896c200211 | ||
|
|
3badc4423a | ||
|
|
d741527ae4 | ||
|
|
77618823a5 | ||
|
|
dd70aeff24 | ||
|
|
022b7d5dd4 | ||
|
|
11337e51c5 | ||
|
|
7724d010b6 | ||
|
|
124aa9db08 | ||
|
|
20cf075b2d | ||
|
|
bf4a5f6b33 | ||
|
|
03749917f0 | ||
|
|
7d51d6030b | ||
|
|
742b87df5e | ||
|
|
a457faa2bf | ||
|
|
4f50f113dd | ||
|
|
8b529a3ec7 | ||
|
|
84c3ec0ea7 | ||
|
|
c13e8077ba | ||
|
|
9f42892b42 | ||
|
|
27ba5a0bce | ||
|
|
78afba49bf | ||
|
|
a9192bc1c6 | ||
|
|
77f04603b3 | ||
|
|
34ed5e428c | ||
|
|
98cb17e79e | ||
|
|
fce20e483c | ||
|
|
97c4733e79 | ||
|
|
748aa22ee2 | ||
|
|
2ba7ac8bc1 | ||
|
|
7458fde5a5 | ||
|
|
f11bf9153d | ||
|
|
0806b3163a | ||
|
|
45621ba4d7 | ||
|
|
6aecf42b6e | ||
|
|
3b234febf5 | ||
|
|
8642354a2a | ||
|
|
c028e5f889 | ||
|
|
3642dd3a73 | ||
|
|
603b1e9ed4 | ||
|
|
b7c6cba23f | ||
|
|
d430136f65 | ||
|
|
381b3d5016 | ||
|
|
e3f1e143e5 | ||
|
|
9f1cbb2ee7 | ||
|
|
d0ef9e672f | ||
|
|
b5c212f575 | ||
|
|
ff5ab43f9c | ||
|
|
68f947c7e0 | ||
|
|
e98456b025 | ||
|
|
75b332695b | ||
|
|
3e4bb695e4 | ||
|
|
7ba1b37a5a | ||
|
|
2886255c8b | ||
|
|
f7a9564e11 | ||
|
|
c1b0f115d0 | ||
|
|
2203d9a138 | ||
|
|
5adf94bd7d | ||
|
|
5fbf8ee6c6 | ||
|
|
8d9c86ac4c | ||
|
|
946ef4c685 | ||
|
|
c3773bc2d1 | ||
|
|
1b8c8b0a43 | ||
|
|
86d2c1184c | ||
|
|
817aea9f05 | ||
|
|
985c07b25b | ||
|
|
05ac27dfa8 | ||
|
|
bcce53a929 | ||
|
|
58922ba40b | ||
|
|
e6b8b13f2e | ||
|
|
ac675c4443 | ||
|
|
ae6a558662 | ||
|
|
64e44d1709 | ||
|
|
f35ae2355f | ||
|
|
3a857c83e6 | ||
|
|
d9edcb2250 | ||
|
|
d129d7951c | ||
|
|
5c246285da | ||
|
|
19c1722032 | ||
|
|
cd9a58231b | ||
|
|
d85b5b9134 | ||
|
|
8bd74d5abf | ||
|
|
2af2e2be67 | ||
|
|
43a3b827a3 | ||
|
|
3c6de0bf3e | ||
|
|
13a724864d | ||
|
|
baf536eb2b | ||
|
|
5200668336 | ||
|
|
7eeffb16e2 | ||
|
|
300909341e | ||
|
|
277d21cccb | ||
|
|
de184051f0 | ||
|
|
95ee72556f | ||
|
|
f48364914b | ||
|
|
19df70efad | ||
|
|
9813609645 | ||
|
|
975d0a1651 | ||
|
|
3c3571713e | ||
|
|
aa6254a3b4 | ||
|
|
0b05d2939a | ||
|
|
6f33163f88 | ||
|
|
93101b4d9a | ||
|
|
d8222a15ca | ||
|
|
1728513634 | ||
|
|
68fa81ec82 | ||
|
|
c051c89176 | ||
|
|
8b2a63e545 | ||
|
|
fcd470fcac | ||
|
|
fd8fe15d28 | ||
|
|
e80315f504 | ||
|
|
ae9e7acd77 | ||
|
|
149eb38e84 | ||
|
|
d777184fd5 | ||
|
|
1653e5eebe | ||
|
|
1f4826ca01 | ||
|
|
ef700b2688 | ||
|
|
cedc1bada2 | ||
|
|
0c709afe5c | ||
|
|
1c5d07871f | ||
|
|
e11fc8c131 | ||
|
|
2edef89a8d | ||
|
|
cbe7de58ab | ||
|
|
801160c430 | ||
|
|
cb2a814296 | ||
|
|
db78b91ec2 | ||
|
|
25a11c5bb7 | ||
|
|
1f41521c21 | ||
|
|
e686d42262 | ||
|
|
9bca3f8fd7 | ||
|
|
6ef3542c6c | ||
|
|
db299a876e | ||
|
|
737d04361b | ||
|
|
0d2366b432 | ||
|
|
b13345ceb2 | ||
|
|
f15dce9ee3 | ||
|
|
b718e66b26 | ||
|
|
a55a7603dd | ||
|
|
64fa343d16 | ||
|
|
6b02eebe36 | ||
|
|
d0f5318b75 | ||
|
|
5fe0d50cee | ||
|
|
4d7caa3458 | ||
|
|
856466320d | ||
|
|
3bd53556ca | ||
|
|
c74854aec0 | ||
|
|
294128d43a | ||
|
|
3f59a579d7 | ||
|
|
e5cf4ea60e | ||
|
|
768ca2d3f0 | ||
|
|
92e9b1bbb1 | ||
|
|
446932e076 | ||
|
|
0469edcc0c | ||
|
|
3823ae5890 | ||
|
|
14d71fb598 | ||
|
|
a031507443 | ||
|
|
4f5c052dc8 | ||
|
|
90e013554c | ||
|
|
30ea3cb702 | ||
|
|
a5147a382d | ||
|
|
74bf6cd186 | ||
|
|
15ddbb5e6f | ||
|
|
547df0b5fe | ||
|
|
8ae46a8a14 | ||
|
|
9753077661 | ||
|
|
22e7393b9d | ||
|
|
943c676768 | ||
|
|
4ecfe1fec5 | ||
|
|
5fac4f8737 | ||
|
|
a5394fa2ce | ||
|
|
8dc4d122b9 | ||
|
|
0eb482f35b | ||
|
|
bd52937c88 | ||
|
|
d5b321af3f | ||
|
|
f3b46bf7e2 | ||
|
|
2008986f83 | ||
|
|
1a57951d72 | ||
|
|
7655d7f662 | ||
|
|
373857d0f2 | ||
|
|
6719af9ba9 | ||
|
|
19c9091d5b | ||
|
|
84e2071a32 | ||
|
|
b3b9e1dabb | ||
|
|
91a35ded18 | ||
|
|
2d68594a86 | ||
|
|
f3d19f9691 | ||
|
|
94047de8b4 | ||
|
|
1c450e27d3 | ||
|
|
c0ccffa1c3 | ||
|
|
bbc76cb833 | ||
|
|
94f3cf1a4c | ||
|
|
2aa8847b78 | ||
|
|
049e858ef7 | ||
|
|
8e491ace5c | ||
|
|
dcf9d85e8d | ||
|
|
460c0da176 | ||
|
|
295a248561 | ||
|
|
4630f9c746 | ||
|
|
ba66beb487 | ||
|
|
b5cb38641a | ||
|
|
4b37d30c0d | ||
|
|
59ba7917c4 | ||
|
|
8d0ff01a59 | ||
|
|
100fb0c5d6 | ||
|
|
b75cd2514e | ||
|
|
7693ba8797 | ||
|
|
3d6b06696e | ||
|
|
0386061fdf | ||
|
|
3407b4d8dd | ||
|
|
71ff2a8356 | ||
|
|
8b809b8004 | ||
|
|
707a3a0a66 | ||
|
|
b798aa915c | ||
|
|
2db67c4101 | ||
|
|
80b4db08dc | ||
|
|
37cdee5101 | ||
|
|
b5366cba03 | ||
|
|
6cfda369ef | ||
|
|
5a57ed2536 | ||
|
|
13937fc103 | ||
|
|
17cd512284 | ||
|
|
97398ff209 | ||
|
|
2ffb63ff0c | ||
|
|
90bcb241cc | ||
|
|
f4f7cfd45a | ||
|
|
d214c047e9 | ||
|
|
fee8a86880 | ||
|
|
ea883b5e48 | ||
|
|
46296d777c | ||
|
|
79f0e894e9 | ||
|
|
6372183471 | ||
|
|
5963e7d1c5 | ||
|
|
c7618fc377 | ||
|
|
3fc932b041 | ||
|
|
97cdc96f7c | ||
|
|
892fe927c2 | ||
|
|
d51d456d80 | ||
|
|
836376c6c8 | ||
|
|
fa29eadb7a | ||
|
|
0cc0065f8c | ||
|
|
c3eac450ce | ||
|
|
7b738e045e | ||
|
|
3f6c17247f | ||
|
|
0551a9bfcd | ||
|
|
7c149ebf4f | ||
|
|
37b70eb73e | ||
|
|
451ea5308f | ||
|
|
a4d6954d4f | ||
|
|
c786533f22 | ||
|
|
406a625c98 | ||
|
|
171b2bdc20 | ||
|
|
4266ce73cb | ||
|
|
afa920cc94 | ||
|
|
701f116be3 | ||
|
|
5c7ea08bdf | ||
|
|
5e38996222 | ||
|
|
18febeabd1 | ||
|
|
be1500bf7d | ||
|
|
fea549679a | ||
|
|
11e1b569ea | ||
|
|
2bbf96d762 | ||
|
|
70394bae52 | ||
|
|
0c9e112f41 | ||
|
|
607b84d929 | ||
|
|
7a13cd1530 | ||
|
|
9b1afb68eb | ||
|
|
cf9d2965bf | ||
|
|
b1328c193b | ||
|
|
3d222caaae | ||
|
|
77ac6fa356 | ||
|
|
a3b46006a8 | ||
|
|
ea4716d039 | ||
|
|
db9e7a53f8 | ||
|
|
4432e055be | ||
|
|
403c2f436d | ||
|
|
594de43dec | ||
|
|
2e68c3fc11 | ||
|
|
2187f6f62e | ||
|
|
9249c38bf9 | ||
|
|
67e0ba5167 | ||
|
|
9004d8c3cd | ||
|
|
4df424438d | ||
|
|
6e3cd62e31 | ||
|
|
61b4bedc16 | ||
|
|
4e5de036c6 | ||
|
|
8e54b2e3f2 | ||
|
|
d39a51c134 | ||
|
|
6efc3d4913 | ||
|
|
55c31eec31 | ||
|
|
9820dcb201 | ||
|
|
9f29ce9591 | ||
|
|
afb0ff37bd | ||
|
|
67b6f08d89 | ||
|
|
892036bd7d | ||
|
|
d123ddedc8 | ||
|
|
fc243982e5 | ||
|
|
df66cd2205 | ||
|
|
a44d3c3eda | ||
|
|
297b33aa41 | ||
|
|
0d858cc036 | ||
|
|
f067947266 | ||
|
|
9ad6bd78f5 | ||
|
|
b1e220f2d2 | ||
|
|
200dc56c37 | ||
|
|
49992925e2 | ||
|
|
405e99d27f | ||
|
|
90ee7fe201 | ||
|
|
bc90fc885f | ||
|
|
5afa5fb085 | ||
|
|
93e2dc4f5f | ||
|
|
08d2a4279f | ||
|
|
d79b686992 | ||
|
|
1adec7ab51 | ||
|
|
3b029f2387 | ||
|
|
6d6afe8f52 | ||
|
|
e307947dd8 | ||
|
|
04ad1eef79 | ||
|
|
2b475b7916 | ||
|
|
f51f4a5843 | ||
|
|
b5f3bbead2 | ||
|
|
a192ae9314 | ||
|
|
7a07d8c2bc | ||
|
|
17a67e7922 | ||
|
|
328a3e2e6b | ||
|
|
597053c30e | ||
|
|
29bef1e3ab | ||
|
|
e36d62f08c | ||
|
|
50b4c7fa18 | ||
|
|
d86ef15d9a | ||
|
|
fa3eb11b6a | ||
|
|
beff31b003 | ||
|
|
2360fb293b | ||
|
|
1c82e3870a | ||
|
|
49ce9d2200 | ||
|
|
c20c9b53e1 | ||
|
|
89fc90ac80 | ||
|
|
072f5caa06 | ||
|
|
783f7a9b13 | ||
|
|
425e162a91 | ||
|
|
55b5d76e0b | ||
|
|
9693d014ba | ||
|
|
16abcf082c | ||
|
|
173336f256 | ||
|
|
f37316f2a0 | ||
|
|
e044e8efaa | ||
|
|
af99a55552 | ||
|
|
8f3d9d0149 | ||
|
|
344e30bef4 | ||
|
|
45ef4059f0 | ||
|
|
13174aac18 | ||
|
|
74f02363f4 | ||
|
|
10c421a94c | ||
|
|
3162227b54 | ||
|
|
7e647cc6e7 | ||
|
|
ec710d7ffd | ||
|
|
36718c39dc | ||
|
|
fca9753140 | ||
|
|
0529c3d5d2 | ||
|
|
5a27a95f8d | ||
|
|
5ec3a967b5 | ||
|
|
a45ec15a56 | ||
|
|
0164dec438 | ||
|
|
4edaa95cbf | ||
|
|
067e6b5ae7 | ||
|
|
6adb986167 | ||
|
|
cc4ca942c9 | ||
|
|
3202f12cb8 | ||
|
|
6448d71ca6 | ||
|
|
e3a3e07eef | ||
|
|
8a906e2959 | ||
|
|
9839b5cb53 | ||
|
|
430569d486 | ||
|
|
d3dfadbd9b | ||
|
|
e474e02a50 | ||
|
|
54d9cdaabf | ||
|
|
76fe3c1d76 | ||
|
|
261e56e61d | ||
|
|
ede0bb5396 | ||
|
|
186b85cd62 | ||
|
|
eab405af5b | ||
|
|
93999cec56 | ||
|
|
acacc0a4cb | ||
|
|
b2ae7089dc | ||
|
|
d4ab6b294a | ||
|
|
e6d89f6756 | ||
|
|
7ec29bbee7 | ||
|
|
f1d44a4c87 | ||
|
|
466f16eb1d | ||
|
|
04d54c0319 | ||
|
|
0367a2148a | ||
|
|
57e9e229de | ||
|
|
90c8d9d27b | ||
|
|
a30b6acc52 | ||
|
|
0ee7f952ef | ||
|
|
86656de971 | ||
|
|
2e649c3329 | ||
|
|
e868e44025 | ||
|
|
4376813951 | ||
|
|
ccd3e519ea | ||
|
|
c4ca3bd34d | ||
|
|
081baae883 | ||
|
|
a3d4befad4 | ||
|
|
2f13d2775f | ||
|
|
a36a2a1080 | ||
|
|
474c7865d7 | ||
|
|
bd205f63cc | ||
|
|
ac40eb8d87 | ||
|
|
3ea06d286a | ||
|
|
8d6984e286 | ||
|
|
cd773b8cc9 | ||
|
|
9bca69ebfb | ||
|
|
b33da6a09c | ||
|
|
7ae23d5567 | ||
|
|
569315ee3e | ||
|
|
4c7941adef | ||
|
|
93d116a9d0 | ||
|
|
7b2499c292 | ||
|
|
2be2bc5877 | ||
|
|
cfb853efbf | ||
|
|
2691164fc4 | ||
|
|
b113711a86 | ||
|
|
68e9530507 | ||
|
|
0ca23bb840 | ||
|
|
6e3d6c4269 | ||
|
|
c2eaa32036 | ||
|
|
604930db64 | ||
|
|
c3f99779f2 | ||
|
|
0518da1e49 | ||
|
|
6f6f032244 | ||
|
|
0acb2db9b6 | ||
|
|
74d26764f8 | ||
|
|
cf77a89123 | ||
|
|
1b73632f77 | ||
|
|
0a7cbf6fde | ||
|
|
e4701e26c8 | ||
|
|
045156985a | ||
|
|
257e795ca9 | ||
|
|
bafdc510d6 | ||
|
|
1840d05a37 | ||
|
|
6d5618447e | ||
|
|
b2de27b7be | ||
|
|
9c0d44fa09 | ||
|
|
f95eb2df0d | ||
|
|
cbb298ccb6 | ||
|
|
9e6940ed3e | ||
|
|
fbcc769d4e | ||
|
|
65f0378e43 | ||
|
|
f7a90f2660 | ||
|
|
3d825dcb3e | ||
|
|
2094a554f6 | ||
|
|
4837ae4958 | ||
|
|
6da9950b72 | ||
|
|
e8921787b3 | ||
|
|
d2d6904c9b | ||
|
|
510f0593e9 | ||
|
|
7a438f8999 | ||
|
|
113af85c3c | ||
|
|
916bacb60e | ||
|
|
a98b5ca97e | ||
|
|
076fe8ca3a | ||
|
|
b08327cb4b | ||
|
|
f1b868d5d9 | ||
|
|
76ff004ea5 | ||
|
|
df173764d2 | ||
|
|
7fa25934af | ||
|
|
649c3d0732 | ||
|
|
35c56237a0 | ||
|
|
236cc6f526 | ||
|
|
a311f88c99 | ||
|
|
e92bc25216 | ||
|
|
0c06d84e22 | ||
|
|
77c8261fca | ||
|
|
91a2e71fff | ||
|
|
0fb47fed9e | ||
|
|
4519c6ab29 | ||
|
|
32c6431dbc | ||
|
|
925964ac28 | ||
|
|
4d4d3bb965 | ||
|
|
3d526b3a87 | ||
|
|
f91582e060 | ||
|
|
dec60fdd4c | ||
|
|
31930159b8 | ||
|
|
6e2611c86c | ||
|
|
7574107d8c | ||
|
|
58d8b0dd01 | ||
|
|
49f78bacef | ||
|
|
3b190467c1 | ||
|
|
804a090457 | ||
|
|
14cfb310e3 | ||
|
|
f607a334ac | ||
|
|
117b84116e | ||
|
|
171dd5c737 | ||
|
|
b5ed4af25a | ||
|
|
b6c683a1b8 | ||
|
|
5200ec0b9a | ||
|
|
307cbf1d9f | ||
|
|
e7ecdb01a6 | ||
|
|
383bfd7583 | ||
|
|
508ea8bc0a | ||
|
|
077de17cd5 | ||
|
|
f6c07c996b | ||
|
|
7ba0bfffa2 | ||
|
|
9b577fa32c | ||
|
|
94cda3e837 | ||
|
|
f09f91e25a | ||
|
|
235bec6481 | ||
|
|
ee616ee6dd | ||
|
|
5153068a64 | ||
|
|
701e441349 | ||
|
|
5817a035f9 | ||
|
|
ea76f46223 | ||
|
|
0759b29ca2 | ||
|
|
db6074e035 | ||
|
|
6057ba0988 | ||
|
|
2fdcf1756e | ||
|
|
f489736e06 | ||
|
|
15f13209cf | ||
|
|
dbf3b7ad6d | ||
|
|
3341077587 | ||
|
|
e39d7021e0 | ||
|
|
cffaf30760 | ||
|
|
bc60cf0a35 | ||
|
|
9bb9807252 | ||
|
|
8b8fdb48bb | ||
|
|
b4437ccd2b | ||
|
|
65ac4dedcc | ||
|
|
671654da71 | ||
|
|
31490417d1 | ||
|
|
17e8c91267 | ||
|
|
db7dccf349 | ||
|
|
71d3f71e22 | ||
|
|
13a54c3f56 | ||
|
|
d58a1b1359 | ||
|
|
bb87a350ac | ||
|
|
c441a848e7 | ||
|
|
f14a5c7346 | ||
|
|
92219b5aad | ||
|
|
291201db1c | ||
|
|
c8ea6d7bfb | ||
|
|
9c70befaf6 | ||
|
|
fcadb807f6 | ||
|
|
4364775dcb | ||
|
|
2a196e91a6 | ||
|
|
7a0358827a | ||
|
|
62e2deafca | ||
|
|
25b4e68fbb | ||
|
|
c909319413 | ||
|
|
c7ee8ac1c7 | ||
|
|
2386eed703 | ||
|
|
ada558bedc | ||
|
|
6caca3aaf7 | ||
|
|
3d3bc4c512 | ||
|
|
044ed624eb | ||
|
|
4dff0c5dff | ||
|
|
59d8f926c8 | ||
|
|
c6f1900a93 | ||
|
|
d94a9cd864 | ||
|
|
21db8e3be4 | ||
|
|
e05bbec879 | ||
|
|
240e0dfa6f | ||
|
|
ab6a01b476 | ||
|
|
dce01cf002 | ||
|
|
da84ba06c7 | ||
|
|
45ba3ca07b | ||
|
|
56407a910d | ||
|
|
e624c33d51 | ||
|
|
3666462076 | ||
|
|
da0d9aab39 | ||
|
|
ace04b3ef4 | ||
|
|
1a4c2e77c4 | ||
|
|
f3c78fe73d | ||
|
|
a17c0e5bf6 | ||
|
|
20d5fdea2c |
@@ -8,8 +8,6 @@ body:
|
||||
label: Self Checks
|
||||
description: "To make sure we get to you in time, please check the following :)"
|
||||
options:
|
||||
- label: This is only for bug report, if you would like to ask a quesion, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general).
|
||||
required: true
|
||||
- label: I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones.
|
||||
required: true
|
||||
- label: I confirm that I am using English to submit this report (我已阅读并同意 [Language Policy](https://github.com/langgenius/dify/issues/1542)).
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: "\U0001F4E7 Discussions"
|
||||
url: https://github.com/langgenius/dify/discussions/categories/general
|
||||
about: General discussions and request help from the community
|
||||
- name: "\U0001F4DA Dify user documentation"
|
||||
url: https://docs.dify.ai/getting-started/readme
|
||||
about: Documentation for users of Dify
|
||||
- name: "\U0001F4DA Dify dev documentation"
|
||||
url: https://docs.dify.ai/getting-started/install-self-hosted
|
||||
about: Documentation for people interested in developing and contributing for Dify
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
name: "🤝 Help Wanted"
|
||||
description: "Request help from the community [please use English :)]"
|
||||
labels:
|
||||
- help-wanted
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Self Checks
|
||||
description: "To make sure we get to you in time, please check the following :)"
|
||||
options:
|
||||
- label: I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones.
|
||||
required: true
|
||||
- label: I confirm that I am using English to submit this report (我已阅读并同意 [Language Policy](https://github.com/langgenius/dify/issues/1542)).
|
||||
required: true
|
||||
- label: "Pleas do not modify this template :) and fill in all the required fields."
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Provide a description of the help you need
|
||||
placeholder: Briefly describe what you need help with.
|
||||
validations:
|
||||
required: true
|
||||
@@ -12,7 +12,7 @@ Please delete options that are not relevant.
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] This change requires a documentation update, included: [Dify Document](https://github.com/langgenius/dify-docs)
|
||||
- [ ] Improvement, including but not limited to code refactoring, performance optimization, and UI/UX improvement
|
||||
- [ ] Improvement,including but not limited to code refactoring, performance optimization, and UI/UX improvement
|
||||
- [ ] Dependency upgrade
|
||||
|
||||
# How Has This Been Tested?
|
||||
|
||||
@@ -26,7 +26,6 @@ jobs:
|
||||
HUGGINGFACE_TEXT2TEXT_GEN_ENDPOINT_URL: b
|
||||
HUGGINGFACE_EMBEDDINGS_ENDPOINT_URL: c
|
||||
MOCK_SWITCH: true
|
||||
CODE_MAX_STRING_LENGTH: 80000
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@@ -42,11 +41,5 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: pip install -r ./api/requirements.txt
|
||||
|
||||
- name: Run ModelRuntime
|
||||
- name: Run pytest
|
||||
run: pytest api/tests/integration_tests/model_runtime/anthropic api/tests/integration_tests/model_runtime/azure_openai api/tests/integration_tests/model_runtime/openai api/tests/integration_tests/model_runtime/chatglm api/tests/integration_tests/model_runtime/google api/tests/integration_tests/model_runtime/xinference api/tests/integration_tests/model_runtime/huggingface_hub/test_llm.py
|
||||
|
||||
- name: Run Tool
|
||||
run: pytest api/tests/integration_tests/tools/test_all_provider.py
|
||||
|
||||
- name: Run Workflow
|
||||
run: pytest api/tests/integration_tests/workflow
|
||||
@@ -0,0 +1,26 @@
|
||||
name: Run Tool Pytest
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10'
|
||||
cache: 'pip'
|
||||
cache-dependency-path: ./api/requirements.txt
|
||||
|
||||
- name: Install dependencies
|
||||
run: pip install -r ./api/requirements.txt
|
||||
|
||||
- name: Run pytest
|
||||
run: pytest ./api/tests/integration_tests/tools/test_all_provider.py
|
||||
@@ -0,0 +1,31 @@
|
||||
name: Run Pytest
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- deploy/dev
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
MOCK_SWITCH: true
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10'
|
||||
cache: 'pip'
|
||||
cache-dependency-path: ./api/requirements.txt
|
||||
|
||||
- name: Install dependencies
|
||||
run: pip install -r ./api/requirements.txt
|
||||
|
||||
- name: Run pytest
|
||||
run: pytest api/tests/integration_tests/workflow
|
||||
@@ -5,6 +5,7 @@ on:
|
||||
branches:
|
||||
- "main"
|
||||
- "deploy/dev"
|
||||
- "feat/workflow"
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
|
||||
+1
-1
@@ -155,4 +155,4 @@ And that's it! Once your PR is merged, you will be featured as a contributor in
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you ever get stuck or got a burning question while contributing, simply shoot your queries our way via the related GitHub issue, or hop onto our [Discord](https://discord.gg/8Tpq4AcN9c) for a quick chat.
|
||||
If you ever get stuck or got a burning question while contributing, simply shoot your queries our way via the related GitHub issue, or hop onto our [Discord](https://discord.gg/AhzKf7dNgk) for a quick chat.
|
||||
|
||||
+1
-1
@@ -152,4 +152,4 @@ Dify的后端使用Python编写,使用[Flask](https://flask.palletsprojects.co
|
||||
|
||||
## 获取帮助
|
||||
|
||||
如果你在贡献过程中遇到困难或者有任何问题,可以通过相关的 GitHub 问题提出你的疑问,或者加入我们的 [Discord](https://discord.gg/8Tpq4AcN9c) 进行快速交流。
|
||||
如果你在贡献过程中遇到困难或者有任何问题,可以通过相关的 GitHub 问题提出你的疑问,或者加入我们的 [Discord](https://discord.gg/AhzKf7dNgk) 进行快速交流。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[](https://dify.ai)
|
||||
[](https://dify.ai)
|
||||
<p align="center">
|
||||
<a href="./README.md">English</a> |
|
||||
<a href="./README_CN.md">简体中文</a> |
|
||||
@@ -27,7 +27,7 @@
|
||||
</a>
|
||||
</p>
|
||||
|
||||
**Dify** is an open-source LLM app development platform. Dify's intuitive interface combines a RAG pipeline, AI workflow orchestration, agent capabilities, model management, observability features and more, letting you quickly go from prototype to production.
|
||||
**Dify** is an LLM application development platform that has helped built over **100,000** applications. It integrates BaaS and LLMOps, covering the essential tech stack for building generative AI-native applications, including a built-in RAG engine. Dify allows you to **deploy your own version of Assistants API and GPTs, based on any LLMs.**
|
||||
|
||||

|
||||
|
||||
@@ -100,12 +100,10 @@ docker compose up -d
|
||||
|
||||
After running, you can access the Dify dashboard in your browser at [http://localhost/install](http://localhost/install) and start the initialization installation process.
|
||||
|
||||
#### Deploy with Helm Chart
|
||||
### Helm Chart
|
||||
|
||||
[Helm Chart](https://helm.sh/) version, which allows Dify to be deployed on Kubernetes.
|
||||
|
||||
- [Helm Chart by @LeoQuote](https://github.com/douban/charts/tree/master/charts/dify)
|
||||
- [Helm Chart by @BorisPolonsky](https://github.com/BorisPolonsky/dify-helm)
|
||||
Big thanks to @BorisPolonsky for providing us with a [Helm Chart](https://helm.sh/) version, which allows Dify to be deployed on Kubernetes.
|
||||
You can go to https://github.com/BorisPolonsky/dify-helm for deployment information.
|
||||
|
||||
### Configuration
|
||||
|
||||
@@ -122,10 +120,6 @@ For those who'd like to contribute code, see our [Contribution Guide](https://gi
|
||||
|
||||
At the same time, please consider supporting Dify by sharing it on social media and at events and conferences.
|
||||
|
||||
### Projects made by community
|
||||
|
||||
- [Chatbot Chrome Extension by @charli117](https://github.com/langgenius/chatbot-chrome-extension)
|
||||
|
||||
### Contributors
|
||||
|
||||
<a href="https://github.com/langgenius/dify/graphs/contributors">
|
||||
@@ -134,11 +128,11 @@ At the same time, please consider supporting Dify by sharing it on social media
|
||||
|
||||
### Translations
|
||||
|
||||
We are looking for contributors to help with translating Dify to languages other than Mandarin or English. If you are interested in helping, please see the [i18n README](https://github.com/langgenius/dify/blob/main/web/i18n/README.md) for more information, and leave us a comment in the `global-users` channel of our [Discord Community Server](https://discord.gg/8Tpq4AcN9c).
|
||||
We are looking for contributors to help with translating Dify to languages other than Mandarin or English. If you are interested in helping, please see the [i18n README](https://github.com/langgenius/dify/blob/main/web/i18n/README_EN.md) for more information, and leave us a comment in the `global-users` channel of our [Discord Community Server](https://discord.gg/AhzKf7dNgk).
|
||||
|
||||
## Community & Support
|
||||
|
||||
* [Github Discussion](https://github.com/langgenius/dify/discussions). Best for: sharing feedback and checking out our feature roadmap.
|
||||
* [Canny](https://feedback.dify.ai/). Best for: sharing feedback and checking out our feature roadmap.
|
||||
* [GitHub Issues](https://github.com/langgenius/dify/issues). Best for: bugs you encounter using Dify.AI, and feature proposals. See our [Contribution Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md).
|
||||
* [Email Support](mailto:[email protected]?subject=[GitHub]Questions%20About%20Dify). Best for: questions you have about using Dify.AI.
|
||||
* [Discord](https://discord.gg/FngNHpbcY7). Best for: sharing your applications and hanging out with the community.
|
||||
|
||||
+3
-6
@@ -94,12 +94,10 @@ docker compose up -d
|
||||
|
||||
运行后,可以在浏览器上访问 [http://localhost/install](http://localhost/install) 进入 Dify 控制台并开始初始化安装操作。
|
||||
|
||||
#### 使用 Helm Chart 部署
|
||||
### Helm Chart
|
||||
|
||||
使用 [Helm Chart](https://helm.sh/) 版本,可以在 Kubernetes 上部署 Dify。
|
||||
|
||||
- [Helm Chart by @LeoQuote](https://github.com/douban/charts/tree/master/charts/dify)
|
||||
- [Helm Chart by @BorisPolonsky](https://github.com/BorisPolonsky/dify-helm)
|
||||
非常感谢 @BorisPolonsky 为我们提供了一个 [Helm Chart](https://helm.sh/) 版本,可以在 Kubernetes 上部署 Dify。
|
||||
您可以前往 https://github.com/BorisPolonsky/dify-helm 来获取部署信息。
|
||||
|
||||
### 配置
|
||||
|
||||
@@ -114,7 +112,6 @@ docker compose up -d
|
||||
|
||||
我们欢迎您为 Dify 做出贡献,以帮助改善 Dify。包括:提交代码、问题、新想法,或分享您基于 Dify 创建的有趣且有用的 AI 应用程序。同时,我们也欢迎您在不同的活动、会议和社交媒体上分享 Dify。
|
||||
|
||||
- [Github Discussion](https://github.com/langgenius/dify/discussions). 👉:分享您的应用程序并与社区交流。
|
||||
- [GitHub Issues](https://github.com/langgenius/dify/issues)。👉:使用 Dify.AI 时遇到的错误和问题,请参阅[贡献指南](CONTRIBUTING.md)。
|
||||
- [电子邮件支持](mailto:[email protected]?subject=[GitHub]Questions%20About%20Dify)。👉:关于使用 Dify.AI 的问题。
|
||||
- [Discord](https://discord.gg/FngNHpbcY7)。👉:分享您的应用程序并与社区交流。
|
||||
|
||||
@@ -137,15 +137,7 @@ SSRF_PROXY_HTTP_URL=
|
||||
SSRF_PROXY_HTTPS_URL=
|
||||
|
||||
BATCH_UPLOAD_LIMIT=10
|
||||
KEYWORD_DATA_SOURCE_TYPE=database
|
||||
|
||||
# CODE EXECUTION CONFIGURATION
|
||||
CODE_EXECUTION_ENDPOINT=http://127.0.0.1:8194
|
||||
CODE_EXECUTION_API_KEY=dify-sandbox
|
||||
CODE_MAX_NUMBER=9223372036854775807
|
||||
CODE_MIN_NUMBER=-9223372036854775808
|
||||
CODE_MAX_STRING_LENGTH=80000
|
||||
TEMPLATE_TRANSFORM_MAX_LENGTH=80000
|
||||
CODE_MAX_STRING_ARRAY_LENGTH=30
|
||||
CODE_MAX_OBJECT_ARRAY_LENGTH=30
|
||||
CODE_MAX_NUMBER_ARRAY_LENGTH=1000
|
||||
|
||||
Vendored
+2
-2
@@ -6,7 +6,7 @@
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Python: Celery",
|
||||
"type": "debugpy",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"module": "celery",
|
||||
"justMyCode": true,
|
||||
@@ -21,7 +21,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Python: Flask",
|
||||
"type": "debugpy",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"module": "flask",
|
||||
"env": {
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
```bash
|
||||
sed -i "/^SECRET_KEY=/c\SECRET_KEY=$(openssl rand -base64 42)" .env
|
||||
```
|
||||
3.5 If you use Anaconda, create a new environment and activate it
|
||||
3.5 If you use annaconda, create a new environment and activate it
|
||||
```bash
|
||||
conda create --name dify python=3.10
|
||||
conda activate dify
|
||||
|
||||
+13
-22
@@ -109,20 +109,19 @@ def reset_encrypt_key_pair():
|
||||
click.echo(click.style('Sorry, only support SELF_HOSTED mode.', fg='red'))
|
||||
return
|
||||
|
||||
tenants = db.session.query(Tenant).all()
|
||||
for tenant in tenants:
|
||||
if not tenant:
|
||||
click.echo(click.style('Sorry, no workspace found. Please enter /install to initialize.', fg='red'))
|
||||
return
|
||||
tenant = db.session.query(Tenant).first()
|
||||
if not tenant:
|
||||
click.echo(click.style('Sorry, no workspace found. Please enter /install to initialize.', fg='red'))
|
||||
return
|
||||
|
||||
tenant.encrypt_public_key = generate_key_pair(tenant.id)
|
||||
tenant.encrypt_public_key = generate_key_pair(tenant.id)
|
||||
|
||||
db.session.query(Provider).filter(Provider.provider_type == 'custom', Provider.tenant_id == tenant.id).delete()
|
||||
db.session.query(ProviderModel).filter(ProviderModel.tenant_id == tenant.id).delete()
|
||||
db.session.commit()
|
||||
db.session.query(Provider).filter(Provider.provider_type == 'custom').delete()
|
||||
db.session.query(ProviderModel).delete()
|
||||
db.session.commit()
|
||||
|
||||
click.echo(click.style('Congratulations! '
|
||||
'the asymmetric key pair of workspace {} has been reset.'.format(tenant.id), fg='green'))
|
||||
click.echo(click.style('Congratulations! '
|
||||
'the asymmetric key pair of workspace {} has been reset.'.format(tenant.id), fg='green'))
|
||||
|
||||
|
||||
@click.command('vdb-migrate', help='migrate vector db.')
|
||||
@@ -384,17 +383,9 @@ def convert_to_agent_apps():
|
||||
# fetch first 1000 apps
|
||||
sql_query = """SELECT a.id AS id FROM apps a
|
||||
INNER JOIN app_model_configs am ON a.app_model_config_id=am.id
|
||||
WHERE a.mode = 'chat'
|
||||
AND am.agent_mode is not null
|
||||
AND (
|
||||
am.agent_mode like '%"strategy": "function_call"%'
|
||||
OR am.agent_mode like '%"strategy": "react"%'
|
||||
)
|
||||
AND (
|
||||
am.agent_mode like '{"enabled": true%'
|
||||
OR am.agent_mode like '{"max_iteration": %'
|
||||
) ORDER BY a.created_at DESC LIMIT 1000
|
||||
"""
|
||||
WHERE a.mode = 'chat' AND am.agent_mode is not null
|
||||
and (am.agent_mode like '%"strategy": "function_call"%' or am.agent_mode like '%"strategy": "react"%')
|
||||
and am.agent_mode like '{"enabled": true%' ORDER BY a.created_at DESC LIMIT 1000"""
|
||||
|
||||
with db.engine.begin() as conn:
|
||||
rs = conn.execute(db.text(sql_query))
|
||||
|
||||
+2
-8
@@ -22,7 +22,6 @@ DEFAULTS = {
|
||||
'SERVICE_API_URL': 'https://api.dify.ai',
|
||||
'APP_WEB_URL': 'https://udify.app',
|
||||
'FILES_URL': '',
|
||||
'S3_ADDRESS_STYLE': 'auto',
|
||||
'STORAGE_TYPE': 'local',
|
||||
'STORAGE_LOCAL_PATH': 'storage',
|
||||
'CHECK_UPDATE_URL': 'https://updates.dify.ai',
|
||||
@@ -65,9 +64,7 @@ DEFAULTS = {
|
||||
'KEYWORD_STORE': 'jieba',
|
||||
'BATCH_UPLOAD_LIMIT': 20,
|
||||
'CODE_EXECUTION_ENDPOINT': '',
|
||||
'CODE_EXECUTION_API_KEY': '',
|
||||
'TOOL_ICON_CACHE_MAX_AGE': 3600,
|
||||
'KEYWORD_DATA_SOURCE_TYPE': 'database',
|
||||
'CODE_EXECUTION_API_KEY': ''
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +95,7 @@ class Config:
|
||||
# ------------------------
|
||||
# General Configurations.
|
||||
# ------------------------
|
||||
self.CURRENT_VERSION = "0.6.0"
|
||||
self.CURRENT_VERSION = "0.5.10"
|
||||
self.COMMIT_SHA = get_env('COMMIT_SHA')
|
||||
self.EDITION = "SELF_HOSTED"
|
||||
self.DEPLOY_ENV = get_env('DEPLOY_ENV')
|
||||
@@ -189,7 +186,6 @@ class Config:
|
||||
self.S3_ACCESS_KEY = get_env('S3_ACCESS_KEY')
|
||||
self.S3_SECRET_KEY = get_env('S3_SECRET_KEY')
|
||||
self.S3_REGION = get_env('S3_REGION')
|
||||
self.S3_ADDRESS_STYLE = get_env('S3_ADDRESS_STYLE')
|
||||
self.AZURE_BLOB_ACCOUNT_NAME = get_env('AZURE_BLOB_ACCOUNT_NAME')
|
||||
self.AZURE_BLOB_ACCOUNT_KEY = get_env('AZURE_BLOB_ACCOUNT_KEY')
|
||||
self.AZURE_BLOB_CONTAINER_NAME = get_env('AZURE_BLOB_CONTAINER_NAME')
|
||||
@@ -315,9 +311,7 @@ class Config:
|
||||
self.CODE_EXECUTION_API_KEY = get_env('CODE_EXECUTION_API_KEY')
|
||||
|
||||
self.API_COMPRESSION_ENABLED = get_bool_env('API_COMPRESSION_ENABLED')
|
||||
self.TOOL_ICON_CACHE_MAX_AGE = get_env('TOOL_ICON_CACHE_MAX_AGE')
|
||||
|
||||
self.KEYWORD_DATA_SOURCE_TYPE = get_env('KEYWORD_DATA_SOURCE_TYPE')
|
||||
|
||||
class CloudEditionConfig(Config):
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ api = ExternalApi(bp)
|
||||
from . import admin, apikey, extension, feature, setup, version, ping
|
||||
# Import app controllers
|
||||
from .app import (advanced_prompt_template, annotation, app, audio, completion, conversation, generator, message,
|
||||
model_config, site, statistic, workflow, workflow_run, workflow_app_log, workflow_statistic, agent)
|
||||
model_config, site, statistic, workflow, workflow_run, workflow_app_log, workflow_statistic)
|
||||
# Import auth controllers
|
||||
from .auth import activate, data_source_oauth, login, oauth
|
||||
# Import billing controllers
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
from flask_restful import Resource, reqparse
|
||||
|
||||
from controllers.console import api
|
||||
from controllers.console.app.wraps import get_app_model
|
||||
from controllers.console.setup import setup_required
|
||||
from controllers.console.wraps import account_initialization_required
|
||||
from libs.helper import uuid_value
|
||||
from libs.login import login_required
|
||||
from models.model import AppMode
|
||||
from services.agent_service import AgentService
|
||||
|
||||
|
||||
class AgentLogApi(Resource):
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@get_app_model(mode=[AppMode.AGENT_CHAT])
|
||||
def get(self, app_model):
|
||||
"""Get agent logs"""
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('message_id', type=uuid_value, required=True, location='args')
|
||||
parser.add_argument('conversation_id', type=uuid_value, required=True, location='args')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
return AgentService.get_agent_logs(
|
||||
app_model,
|
||||
args['conversation_id'],
|
||||
args['message_id']
|
||||
)
|
||||
|
||||
api.add_resource(AgentLogApi, '/apps/<uuid:app_id>/agent/logs')
|
||||
@@ -123,6 +123,7 @@ class AppApi(Resource):
|
||||
tool_runtime = ToolManager.get_agent_tool_runtime(
|
||||
tenant_id=current_user.current_tenant_id,
|
||||
agent_tool=agent_tool_entity,
|
||||
agent_callback=None
|
||||
)
|
||||
manager = ToolParameterConfigurationManager(
|
||||
tenant_id=current_user.current_tenant_id,
|
||||
|
||||
@@ -12,7 +12,6 @@ from controllers.console import api
|
||||
from controllers.console.app.wraps import get_app_model
|
||||
from controllers.console.setup import setup_required
|
||||
from controllers.console.wraps import account_initialization_required
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from extensions.ext_database import db
|
||||
from fields.conversation_fields import (
|
||||
conversation_detail_fields,
|
||||
@@ -203,7 +202,7 @@ class ChatConversationApi(Resource):
|
||||
)
|
||||
|
||||
if app_model.mode == AppMode.ADVANCED_CHAT.value:
|
||||
query = query.where(Conversation.invoke_from != InvokeFrom.DEBUGGER.value)
|
||||
query = query.where(Conversation.override_model_configs.is_(None))
|
||||
|
||||
query = query.order_by(Conversation.created_at.desc())
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ class ModelConfigResource(Resource):
|
||||
tool_runtime = ToolManager.get_agent_tool_runtime(
|
||||
tenant_id=current_user.current_tenant_id,
|
||||
agent_tool=agent_tool_entity,
|
||||
agent_callback=None
|
||||
)
|
||||
manager = ToolParameterConfigurationManager(
|
||||
tenant_id=current_user.current_tenant_id,
|
||||
@@ -95,6 +96,7 @@ class ModelConfigResource(Resource):
|
||||
tool_runtime = ToolManager.get_agent_tool_runtime(
|
||||
tenant_id=current_user.current_tenant_id,
|
||||
agent_tool=agent_tool_entity,
|
||||
agent_callback=None
|
||||
)
|
||||
except Exception as e:
|
||||
continue
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import json
|
||||
import logging
|
||||
|
||||
from flask import abort, request
|
||||
from flask_restful import Resource, marshal_with, reqparse
|
||||
from werkzeug.exceptions import InternalServerError, NotFound
|
||||
|
||||
@@ -53,30 +52,10 @@ class DraftWorkflowApi(Resource):
|
||||
"""
|
||||
Sync draft workflow
|
||||
"""
|
||||
content_type = request.headers.get('Content-Type')
|
||||
|
||||
if 'application/json' in content_type:
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('graph', type=dict, required=True, nullable=False, location='json')
|
||||
parser.add_argument('features', type=dict, required=True, nullable=False, location='json')
|
||||
args = parser.parse_args()
|
||||
elif 'text/plain' in content_type:
|
||||
try:
|
||||
data = json.loads(request.data.decode('utf-8'))
|
||||
if 'graph' not in data or 'features' not in data:
|
||||
raise ValueError('graph or features not found in data')
|
||||
|
||||
if not isinstance(data.get('graph'), dict) or not isinstance(data.get('features'), dict):
|
||||
raise ValueError('graph or features is not a dict')
|
||||
|
||||
args = {
|
||||
'graph': data.get('graph'),
|
||||
'features': data.get('features')
|
||||
}
|
||||
except json.JSONDecodeError:
|
||||
return {'message': 'Invalid JSON data'}, 400
|
||||
else:
|
||||
abort(415)
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('graph', type=dict, required=True, nullable=False, location='json')
|
||||
parser.add_argument('features', type=dict, required=True, nullable=False, location='json')
|
||||
args = parser.parse_args()
|
||||
|
||||
workflow_service = WorkflowService()
|
||||
workflow = workflow_service.sync_draft_workflow(
|
||||
@@ -289,21 +268,11 @@ class ConvertToWorkflowApi(Resource):
|
||||
Convert expert mode of chatbot app to workflow mode
|
||||
Convert Completion App to Workflow App
|
||||
"""
|
||||
if request.data:
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('name', type=str, required=False, nullable=True, location='json')
|
||||
parser.add_argument('icon', type=str, required=False, nullable=True, location='json')
|
||||
parser.add_argument('icon_background', type=str, required=False, nullable=True, location='json')
|
||||
args = parser.parse_args()
|
||||
else:
|
||||
args = {}
|
||||
|
||||
# convert to workflow mode
|
||||
workflow_service = WorkflowService()
|
||||
new_app_model = workflow_service.convert_to_workflow(
|
||||
app_model=app_model,
|
||||
account=current_user,
|
||||
args=args
|
||||
account=current_user
|
||||
)
|
||||
|
||||
# return app id
|
||||
|
||||
@@ -12,11 +12,7 @@ from controllers.console import api
|
||||
from controllers.console.app.error import ProviderNotInitializeError
|
||||
from controllers.console.datasets.error import InvalidActionError, NoFileUploadedError, TooManyFilesError
|
||||
from controllers.console.setup import setup_required
|
||||
from controllers.console.wraps import (
|
||||
account_initialization_required,
|
||||
cloud_edition_billing_knowledge_limit_check,
|
||||
cloud_edition_billing_resource_check,
|
||||
)
|
||||
from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check
|
||||
from core.errors.error import LLMBadRequestError, ProviderTokenNotInitError
|
||||
from core.model_manager import ModelManager
|
||||
from core.model_runtime.entities.model_entities import ModelType
|
||||
@@ -211,7 +207,6 @@ class DatasetDocumentSegmentAddApi(Resource):
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@cloud_edition_billing_resource_check('vector_space')
|
||||
@cloud_edition_billing_knowledge_limit_check('add_segment')
|
||||
def post(self, dataset_id, document_id):
|
||||
# check dataset
|
||||
dataset_id = str(dataset_id)
|
||||
@@ -362,7 +357,6 @@ class DatasetDocumentSegmentBatchImportApi(Resource):
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@cloud_edition_billing_resource_check('vector_space')
|
||||
@cloud_edition_billing_knowledge_limit_check('add_segment')
|
||||
def post(self, dataset_id, document_id):
|
||||
# check dataset
|
||||
dataset_id = str(dataset_id)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import io
|
||||
|
||||
from flask import current_app, send_file
|
||||
from flask import send_file
|
||||
from flask_login import current_user
|
||||
from flask_restful import Resource, reqparse
|
||||
from werkzeug.exceptions import Forbidden
|
||||
@@ -76,27 +76,12 @@ class ToolBuiltinProviderUpdateApi(Resource):
|
||||
provider,
|
||||
args['credentials'],
|
||||
)
|
||||
|
||||
class ToolBuiltinProviderGetCredentialsApi(Resource):
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
def get(self, provider):
|
||||
user_id = current_user.id
|
||||
tenant_id = current_user.current_tenant_id
|
||||
|
||||
return ToolManageService.get_builtin_tool_provider_credentials(
|
||||
user_id,
|
||||
tenant_id,
|
||||
provider,
|
||||
)
|
||||
|
||||
class ToolBuiltinProviderIconApi(Resource):
|
||||
@setup_required
|
||||
def get(self, provider):
|
||||
icon_bytes, mimetype = ToolManageService.get_builtin_tool_provider_icon(provider)
|
||||
icon_cache_max_age = int(current_app.config.get('TOOL_ICON_CACHE_MAX_AGE'))
|
||||
return send_file(io.BytesIO(icon_bytes), mimetype=mimetype, max_age=icon_cache_max_age)
|
||||
icon_bytes, minetype = ToolManageService.get_builtin_tool_provider_icon(provider)
|
||||
return send_file(io.BytesIO(icon_bytes), mimetype=minetype)
|
||||
|
||||
class ToolModelProviderIconApi(Resource):
|
||||
@setup_required
|
||||
@@ -347,7 +332,6 @@ api.add_resource(ToolProviderListApi, '/workspaces/current/tool-providers')
|
||||
api.add_resource(ToolBuiltinProviderListToolsApi, '/workspaces/current/tool-provider/builtin/<provider>/tools')
|
||||
api.add_resource(ToolBuiltinProviderDeleteApi, '/workspaces/current/tool-provider/builtin/<provider>/delete')
|
||||
api.add_resource(ToolBuiltinProviderUpdateApi, '/workspaces/current/tool-provider/builtin/<provider>/update')
|
||||
api.add_resource(ToolBuiltinProviderGetCredentialsApi, '/workspaces/current/tool-provider/builtin/<provider>/credentials')
|
||||
api.add_resource(ToolBuiltinProviderCredentialsSchemaApi, '/workspaces/current/tool-provider/builtin/<provider>/credentials_schema')
|
||||
api.add_resource(ToolBuiltinProviderIconApi, '/workspaces/current/tool-provider/builtin/<provider>/icon')
|
||||
api.add_resource(ToolModelProviderIconApi, '/workspaces/current/tool-provider/model/<provider>/icon')
|
||||
@@ -355,7 +339,7 @@ api.add_resource(ToolModelProviderListToolsApi, '/workspaces/current/tool-provid
|
||||
api.add_resource(ToolApiProviderAddApi, '/workspaces/current/tool-provider/api/add')
|
||||
api.add_resource(ToolApiProviderGetRemoteSchemaApi, '/workspaces/current/tool-provider/api/remote')
|
||||
api.add_resource(ToolApiProviderListToolsApi, '/workspaces/current/tool-provider/api/tools')
|
||||
api.add_resource(ToolApiProviderUpdateApi, '/workspaces/current/tool-provider/api/update')
|
||||
api.add_resource(ToolApiProviderUpdateApi, '/workspaces/current/tool-provider/api/update')
|
||||
api.add_resource(ToolApiProviderDeleteApi, '/workspaces/current/tool-provider/api/delete')
|
||||
api.add_resource(ToolApiProviderGetApi, '/workspaces/current/tool-provider/api/get')
|
||||
api.add_resource(ToolApiProviderSchemaApi, '/workspaces/current/tool-provider/api/schema')
|
||||
|
||||
@@ -51,12 +51,14 @@ def cloud_edition_billing_resource_check(resource: str,
|
||||
@wraps(view)
|
||||
def decorated(*args, **kwargs):
|
||||
features = FeatureService.get_features(current_user.current_tenant_id)
|
||||
|
||||
if features.billing.enabled:
|
||||
members = features.members
|
||||
apps = features.apps
|
||||
vector_space = features.vector_space
|
||||
documents_upload_quota = features.documents_upload_quota
|
||||
annotation_quota_limit = features.annotation_quota_limit
|
||||
|
||||
if resource == 'members' and 0 < members.limit <= members.size:
|
||||
abort(403, error_msg)
|
||||
elif resource == 'apps' and 0 < apps.limit <= apps.size:
|
||||
@@ -78,29 +80,7 @@ def cloud_edition_billing_resource_check(resource: str,
|
||||
return view(*args, **kwargs)
|
||||
|
||||
return view(*args, **kwargs)
|
||||
|
||||
return decorated
|
||||
|
||||
return interceptor
|
||||
|
||||
|
||||
def cloud_edition_billing_knowledge_limit_check(resource: str,
|
||||
error_msg: str = "To unlock this feature and elevate your Dify experience, please upgrade to a paid plan."):
|
||||
def interceptor(view):
|
||||
@wraps(view)
|
||||
def decorated(*args, **kwargs):
|
||||
features = FeatureService.get_features(current_user.current_tenant_id)
|
||||
if features.billing.enabled:
|
||||
if resource == 'add_segment':
|
||||
if features.billing.subscription.plan == 'sandbox':
|
||||
abort(403, error_msg)
|
||||
else:
|
||||
return view(*args, **kwargs)
|
||||
|
||||
return view(*args, **kwargs)
|
||||
|
||||
return decorated
|
||||
|
||||
return interceptor
|
||||
|
||||
|
||||
@@ -119,5 +99,4 @@ def cloud_utm_record(view):
|
||||
except Exception as e:
|
||||
pass
|
||||
return view(*args, **kwargs)
|
||||
|
||||
return decorated
|
||||
|
||||
@@ -63,9 +63,7 @@ class MessageListApi(Resource):
|
||||
'feedback': fields.Nested(feedback_fields, attribute='user_feedback', allow_null=True),
|
||||
'retriever_resources': fields.List(fields.Nested(retriever_resource_fields)),
|
||||
'created_at': TimestampField,
|
||||
'agent_thoughts': fields.List(fields.Nested(agent_thought_fields)),
|
||||
'status': fields.String,
|
||||
'error': fields.String,
|
||||
'agent_thoughts': fields.List(fields.Nested(agent_thought_fields))
|
||||
}
|
||||
|
||||
message_infinite_scroll_pagination_fields = {
|
||||
|
||||
@@ -4,11 +4,7 @@ from werkzeug.exceptions import NotFound
|
||||
|
||||
from controllers.service_api import api
|
||||
from controllers.service_api.app.error import ProviderNotInitializeError
|
||||
from controllers.service_api.wraps import (
|
||||
DatasetApiResource,
|
||||
cloud_edition_billing_knowledge_limit_check,
|
||||
cloud_edition_billing_resource_check,
|
||||
)
|
||||
from controllers.service_api.wraps import DatasetApiResource, cloud_edition_billing_resource_check
|
||||
from core.errors.error import LLMBadRequestError, ProviderTokenNotInitError
|
||||
from core.model_manager import ModelManager
|
||||
from core.model_runtime.entities.model_entities import ModelType
|
||||
@@ -22,7 +18,6 @@ class SegmentApi(DatasetApiResource):
|
||||
"""Resource for segments."""
|
||||
|
||||
@cloud_edition_billing_resource_check('vector_space', 'dataset')
|
||||
@cloud_edition_billing_knowledge_limit_check('add_segment', 'dataset')
|
||||
def post(self, tenant_id, dataset_id, document_id):
|
||||
"""Create single segment."""
|
||||
# check dataset
|
||||
|
||||
@@ -8,7 +8,7 @@ from flask import current_app, request
|
||||
from flask_login import user_logged_in
|
||||
from flask_restful import Resource
|
||||
from pydantic import BaseModel
|
||||
from werkzeug.exceptions import Forbidden, NotFound, Unauthorized
|
||||
from werkzeug.exceptions import NotFound, Unauthorized
|
||||
|
||||
from extensions.ext_database import db
|
||||
from libs.login import _get_user
|
||||
@@ -92,13 +92,13 @@ def cloud_edition_billing_resource_check(resource: str,
|
||||
documents_upload_quota = features.documents_upload_quota
|
||||
|
||||
if resource == 'members' and 0 < members.limit <= members.size:
|
||||
raise Forbidden(error_msg)
|
||||
raise Unauthorized(error_msg)
|
||||
elif resource == 'apps' and 0 < apps.limit <= apps.size:
|
||||
raise Forbidden(error_msg)
|
||||
raise Unauthorized(error_msg)
|
||||
elif resource == 'vector_space' and 0 < vector_space.limit <= vector_space.size:
|
||||
raise Forbidden(error_msg)
|
||||
raise Unauthorized(error_msg)
|
||||
elif resource == 'documents' and 0 < documents_upload_quota.limit <= documents_upload_quota.size:
|
||||
raise Forbidden(error_msg)
|
||||
raise Unauthorized(error_msg)
|
||||
else:
|
||||
return view(*args, **kwargs)
|
||||
|
||||
@@ -107,27 +107,6 @@ def cloud_edition_billing_resource_check(resource: str,
|
||||
return interceptor
|
||||
|
||||
|
||||
def cloud_edition_billing_knowledge_limit_check(resource: str,
|
||||
api_token_type: str,
|
||||
error_msg: str = "To unlock this feature and elevate your Dify experience, please upgrade to a paid plan."):
|
||||
def interceptor(view):
|
||||
@wraps(view)
|
||||
def decorated(*args, **kwargs):
|
||||
api_token = validate_and_get_api_token(api_token_type)
|
||||
features = FeatureService.get_features(api_token.tenant_id)
|
||||
if features.billing.enabled:
|
||||
if resource == 'add_segment':
|
||||
if features.billing.subscription.plan == 'sandbox':
|
||||
raise Forbidden(error_msg)
|
||||
else:
|
||||
return view(*args, **kwargs)
|
||||
|
||||
return view(*args, **kwargs)
|
||||
|
||||
return decorated
|
||||
|
||||
return interceptor
|
||||
|
||||
def validate_dataset_token(view=None):
|
||||
def decorator(view):
|
||||
@wraps(view)
|
||||
|
||||
@@ -66,9 +66,7 @@ class MessageListApi(WebApiResource):
|
||||
'feedback': fields.Nested(feedback_fields, attribute='user_feedback', allow_null=True),
|
||||
'retriever_resources': fields.List(fields.Nested(retriever_resource_fields)),
|
||||
'created_at': TimestampField,
|
||||
'agent_thoughts': fields.List(fields.Nested(agent_thought_fields)),
|
||||
'status': fields.String,
|
||||
'error': fields.String,
|
||||
'agent_thoughts': fields.List(fields.Nested(agent_thought_fields))
|
||||
}
|
||||
|
||||
message_infinite_scroll_pagination_fields = {
|
||||
|
||||
@@ -10,10 +10,12 @@ from core.app.apps.base_app_queue_manager import AppQueueManager
|
||||
from core.app.apps.base_app_runner import AppRunner
|
||||
from core.app.entities.app_invoke_entities import (
|
||||
AgentChatAppGenerateEntity,
|
||||
InvokeFrom,
|
||||
ModelConfigWithCredentialsEntity,
|
||||
)
|
||||
from core.callback_handler.agent_tool_callback_handler import DifyAgentCallbackHandler
|
||||
from core.callback_handler.index_tool_callback_handler import DatasetIndexToolCallbackHandler
|
||||
from core.file.message_file_parser import FileTransferMethod
|
||||
from core.memory.token_buffer_memory import TokenBufferMemory
|
||||
from core.model_manager import ModelInstance
|
||||
from core.model_runtime.entities.llm_entities import LLMUsage
|
||||
@@ -30,6 +32,7 @@ from core.model_runtime.model_providers.__base.large_language_model import Large
|
||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
||||
from core.tools.entities.tool_entities import (
|
||||
ToolInvokeMessage,
|
||||
ToolInvokeMessageBinary,
|
||||
ToolParameter,
|
||||
ToolRuntimeVariablePool,
|
||||
)
|
||||
@@ -37,7 +40,7 @@ from core.tools.tool.dataset_retriever_tool import DatasetRetrieverTool
|
||||
from core.tools.tool.tool import Tool
|
||||
from core.tools.tool_manager import ToolManager
|
||||
from extensions.ext_database import db
|
||||
from models.model import Message, MessageAgentThought
|
||||
from models.model import Message, MessageAgentThought, MessageFile
|
||||
from models.tools import ToolConversationVariables
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -140,7 +143,7 @@ class BaseAgentRunner(AppRunner):
|
||||
result += f"result link: {response.message}. please tell user to check it."
|
||||
elif response.type == ToolInvokeMessage.MessageType.IMAGE_LINK or \
|
||||
response.type == ToolInvokeMessage.MessageType.IMAGE:
|
||||
result += "image has been created and sent to user already, you do not need to create it, just tell the user to check it now."
|
||||
result += "image has been created and sent to user already, you should tell user to check it now."
|
||||
else:
|
||||
result += f"tool response: {response.message}."
|
||||
|
||||
@@ -153,6 +156,7 @@ class BaseAgentRunner(AppRunner):
|
||||
tool_entity = ToolManager.get_agent_tool_runtime(
|
||||
tenant_id=self.tenant_id,
|
||||
agent_tool=tool,
|
||||
agent_callback=self.agent_callback
|
||||
)
|
||||
tool_entity.load_variables(self.variables_pool)
|
||||
|
||||
@@ -266,6 +270,87 @@ class BaseAgentRunner(AppRunner):
|
||||
prompt_tool.parameters['required'].append(parameter.name)
|
||||
|
||||
return prompt_tool
|
||||
|
||||
def extract_tool_response_binary(self, tool_response: list[ToolInvokeMessage]) -> list[ToolInvokeMessageBinary]:
|
||||
"""
|
||||
Extract tool response binary
|
||||
"""
|
||||
result = []
|
||||
|
||||
for response in tool_response:
|
||||
if response.type == ToolInvokeMessage.MessageType.IMAGE_LINK or \
|
||||
response.type == ToolInvokeMessage.MessageType.IMAGE:
|
||||
result.append(ToolInvokeMessageBinary(
|
||||
mimetype=response.meta.get('mime_type', 'octet/stream'),
|
||||
url=response.message,
|
||||
save_as=response.save_as,
|
||||
))
|
||||
elif response.type == ToolInvokeMessage.MessageType.BLOB:
|
||||
result.append(ToolInvokeMessageBinary(
|
||||
mimetype=response.meta.get('mime_type', 'octet/stream'),
|
||||
url=response.message,
|
||||
save_as=response.save_as,
|
||||
))
|
||||
elif response.type == ToolInvokeMessage.MessageType.LINK:
|
||||
# check if there is a mime type in meta
|
||||
if response.meta and 'mime_type' in response.meta:
|
||||
result.append(ToolInvokeMessageBinary(
|
||||
mimetype=response.meta.get('mime_type', 'octet/stream') if response.meta else 'octet/stream',
|
||||
url=response.message,
|
||||
save_as=response.save_as,
|
||||
))
|
||||
|
||||
return result
|
||||
|
||||
def create_message_files(self, messages: list[ToolInvokeMessageBinary]) -> list[tuple[MessageFile, bool]]:
|
||||
"""
|
||||
Create message file
|
||||
|
||||
:param messages: messages
|
||||
:return: message files, should save as variable
|
||||
"""
|
||||
result = []
|
||||
|
||||
for message in messages:
|
||||
file_type = 'bin'
|
||||
if 'image' in message.mimetype:
|
||||
file_type = 'image'
|
||||
elif 'video' in message.mimetype:
|
||||
file_type = 'video'
|
||||
elif 'audio' in message.mimetype:
|
||||
file_type = 'audio'
|
||||
elif 'text' in message.mimetype:
|
||||
file_type = 'text'
|
||||
elif 'pdf' in message.mimetype:
|
||||
file_type = 'pdf'
|
||||
elif 'zip' in message.mimetype:
|
||||
file_type = 'archive'
|
||||
# ...
|
||||
|
||||
invoke_from = self.application_generate_entity.invoke_from
|
||||
|
||||
message_file = MessageFile(
|
||||
message_id=self.message.id,
|
||||
type=file_type,
|
||||
transfer_method=FileTransferMethod.TOOL_FILE.value,
|
||||
belongs_to='assistant',
|
||||
url=message.url,
|
||||
upload_file_id=None,
|
||||
created_by_role=('account'if invoke_from in [InvokeFrom.EXPLORE, InvokeFrom.DEBUGGER] else 'end_user'),
|
||||
created_by=self.user_id,
|
||||
)
|
||||
db.session.add(message_file)
|
||||
db.session.commit()
|
||||
db.session.refresh(message_file)
|
||||
|
||||
result.append((
|
||||
message_file,
|
||||
message.save_as
|
||||
))
|
||||
|
||||
db.session.close()
|
||||
|
||||
return result
|
||||
|
||||
def create_agent_thought(self, message_id: str, message: str,
|
||||
tool_name: str, tool_input: str, messages_ids: list[str]
|
||||
@@ -279,7 +364,6 @@ class BaseAgentRunner(AppRunner):
|
||||
thought='',
|
||||
tool=tool_name,
|
||||
tool_labels_str='{}',
|
||||
tool_meta_str='{}',
|
||||
tool_input=tool_input,
|
||||
message=message,
|
||||
message_token=0,
|
||||
@@ -314,8 +398,7 @@ class BaseAgentRunner(AppRunner):
|
||||
tool_name: str,
|
||||
tool_input: Union[str, dict],
|
||||
thought: str,
|
||||
observation: Union[str, str],
|
||||
tool_invoke_meta: Union[str, dict],
|
||||
observation: str,
|
||||
answer: str,
|
||||
messages_ids: list[str],
|
||||
llm_usage: LLMUsage = None) -> MessageAgentThought:
|
||||
@@ -342,12 +425,6 @@ class BaseAgentRunner(AppRunner):
|
||||
agent_thought.tool_input = tool_input
|
||||
|
||||
if observation is not None:
|
||||
if isinstance(observation, dict):
|
||||
try:
|
||||
observation = json.dumps(observation, ensure_ascii=False)
|
||||
except Exception as e:
|
||||
observation = json.dumps(observation)
|
||||
|
||||
agent_thought.observation = observation
|
||||
|
||||
if answer is not None:
|
||||
@@ -381,15 +458,6 @@ class BaseAgentRunner(AppRunner):
|
||||
|
||||
agent_thought.tool_labels_str = json.dumps(labels)
|
||||
|
||||
if tool_invoke_meta is not None:
|
||||
if isinstance(tool_invoke_meta, dict):
|
||||
try:
|
||||
tool_invoke_meta = json.dumps(tool_invoke_meta, ensure_ascii=False)
|
||||
except Exception as e:
|
||||
tool_invoke_meta = json.dumps(tool_invoke_meta)
|
||||
|
||||
agent_thought.tool_meta_str = tool_invoke_meta
|
||||
|
||||
db.session.commit()
|
||||
db.session.close()
|
||||
|
||||
@@ -429,15 +497,7 @@ class BaseAgentRunner(AppRunner):
|
||||
tools = tools.split(';')
|
||||
tool_calls: list[AssistantPromptMessage.ToolCall] = []
|
||||
tool_call_response: list[ToolPromptMessage] = []
|
||||
try:
|
||||
tool_inputs = json.loads(agent_thought.tool_input)
|
||||
except Exception as e:
|
||||
tool_inputs = { tool: {} for tool in tools }
|
||||
try:
|
||||
tool_responses = json.loads(agent_thought.observation)
|
||||
except Exception as e:
|
||||
tool_responses = { tool: agent_thought.observation for tool in tools }
|
||||
|
||||
tool_inputs = json.loads(agent_thought.tool_input)
|
||||
for tool in tools:
|
||||
# generate a uuid for tool call
|
||||
tool_call_id = str(uuid.uuid4())
|
||||
@@ -450,7 +510,7 @@ class BaseAgentRunner(AppRunner):
|
||||
)
|
||||
))
|
||||
tool_call_response.append(ToolPromptMessage(
|
||||
content=tool_responses.get(tool, agent_thought.observation),
|
||||
content=agent_thought.observation,
|
||||
name=tool,
|
||||
tool_call_id=tool_call_id,
|
||||
))
|
||||
@@ -470,4 +530,4 @@ class BaseAgentRunner(AppRunner):
|
||||
|
||||
db.session.close()
|
||||
|
||||
return result
|
||||
return result
|
||||
@@ -17,8 +17,15 @@ from core.model_runtime.entities.message_entities import (
|
||||
UserPromptMessage,
|
||||
)
|
||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
||||
from core.tools.entities.tool_entities import ToolInvokeMeta
|
||||
from core.tools.tool_engine import ToolEngine
|
||||
from core.tools.errors import (
|
||||
ToolInvokeError,
|
||||
ToolNotFoundError,
|
||||
ToolNotSupportedError,
|
||||
ToolParameterValidationError,
|
||||
ToolProviderCredentialValidationError,
|
||||
ToolProviderNotFoundError,
|
||||
)
|
||||
from core.tools.utils.message_transformer import ToolFileMessageTransformer
|
||||
from models.model import Conversation, Message
|
||||
|
||||
|
||||
@@ -184,7 +191,7 @@ class CotAgentRunner(BaseAgentRunner):
|
||||
delta=LLMResultChunkDelta(
|
||||
index=0,
|
||||
message=AssistantPromptMessage(
|
||||
content=json.dumps(chunk, ensure_ascii=False) # if ensure_ascii=True, the text in webui maybe garbled text
|
||||
content=json.dumps(chunk)
|
||||
),
|
||||
usage=None
|
||||
)
|
||||
@@ -216,10 +223,7 @@ class CotAgentRunner(BaseAgentRunner):
|
||||
|
||||
self.save_agent_thought(agent_thought=agent_thought,
|
||||
tool_name=scratchpad.action.action_name if scratchpad.action else '',
|
||||
tool_input={
|
||||
scratchpad.action.action_name: scratchpad.action.action_input
|
||||
} if scratchpad.action else '',
|
||||
tool_invoke_meta={},
|
||||
tool_input=scratchpad.action.action_input if scratchpad.action else '',
|
||||
thought=scratchpad.thought,
|
||||
observation='',
|
||||
answer=scratchpad.agent_response,
|
||||
@@ -252,65 +256,71 @@ class CotAgentRunner(BaseAgentRunner):
|
||||
tool_instance = tool_instances.get(tool_call_name)
|
||||
if not tool_instance:
|
||||
answer = f"there is not a tool named {tool_call_name}"
|
||||
self.save_agent_thought(
|
||||
agent_thought=agent_thought,
|
||||
tool_name='',
|
||||
tool_input='',
|
||||
tool_invoke_meta=ToolInvokeMeta.error_instance(
|
||||
f"there is not a tool named {tool_call_name}"
|
||||
).to_dict(),
|
||||
thought=None,
|
||||
observation={
|
||||
tool_call_name: answer
|
||||
},
|
||||
answer=answer,
|
||||
messages_ids=[]
|
||||
)
|
||||
self.save_agent_thought(agent_thought=agent_thought,
|
||||
tool_name='',
|
||||
tool_input='',
|
||||
thought=None,
|
||||
observation=answer,
|
||||
answer=answer,
|
||||
messages_ids=[])
|
||||
self.queue_manager.publish(QueueAgentThoughtEvent(
|
||||
agent_thought_id=agent_thought.id
|
||||
), PublishFrom.APPLICATION_MANAGER)
|
||||
else:
|
||||
if isinstance(tool_call_args, str):
|
||||
try:
|
||||
tool_call_args = json.loads(tool_call_args)
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
|
||||
# invoke tool
|
||||
tool_invoke_response, message_files, tool_invoke_meta = ToolEngine.agent_invoke(
|
||||
tool=tool_instance,
|
||||
tool_parameters=tool_call_args,
|
||||
user_id=self.user_id,
|
||||
tenant_id=self.tenant_id,
|
||||
message=self.message,
|
||||
invoke_from=self.application_generate_entity.invoke_from,
|
||||
agent_tool_callback=self.agent_callback
|
||||
)
|
||||
# publish files
|
||||
for message_file, save_as in message_files:
|
||||
if save_as:
|
||||
self.variables_pool.set_file(tool_name=tool_call_name, value=message_file.id, name=save_as)
|
||||
error_response = None
|
||||
try:
|
||||
if isinstance(tool_call_args, str):
|
||||
try:
|
||||
tool_call_args = json.loads(tool_call_args)
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
|
||||
# publish message file
|
||||
self.queue_manager.publish(QueueMessageFileEvent(
|
||||
message_file_id=message_file.id
|
||||
), PublishFrom.APPLICATION_MANAGER)
|
||||
# add message file ids
|
||||
message_file_ids.append(message_file.id)
|
||||
tool_response = tool_instance.invoke(
|
||||
user_id=self.user_id,
|
||||
tool_parameters=tool_call_args
|
||||
)
|
||||
# transform tool response to llm friendly response
|
||||
tool_response = ToolFileMessageTransformer.transform_tool_invoke_messages(
|
||||
messages=tool_response,
|
||||
user_id=self.user_id,
|
||||
tenant_id=self.tenant_id,
|
||||
conversation_id=self.message.conversation_id
|
||||
)
|
||||
# extract binary data from tool invoke message
|
||||
binary_files = self.extract_tool_response_binary(tool_response)
|
||||
# create message file
|
||||
message_files = self.create_message_files(binary_files)
|
||||
# publish files
|
||||
for message_file, save_as in message_files:
|
||||
if save_as:
|
||||
self.variables_pool.set_file(tool_name=tool_call_name,
|
||||
value=message_file.id,
|
||||
name=save_as)
|
||||
self.queue_manager.publish(QueueMessageFileEvent(
|
||||
message_file_id=message_file.id
|
||||
), PublishFrom.APPLICATION_MANAGER)
|
||||
|
||||
# publish files
|
||||
for message_file, save_as in message_files:
|
||||
if save_as:
|
||||
self.variables_pool.set_file(tool_name=tool_call_name,
|
||||
value=message_file.id,
|
||||
name=save_as)
|
||||
self.queue_manager.publish(QueueMessageFileEvent(
|
||||
message_file_id=message_file.id
|
||||
), PublishFrom.APPLICATION_MANAGER)
|
||||
message_file_ids = [message_file.id for message_file, _ in message_files]
|
||||
except ToolProviderCredentialValidationError as e:
|
||||
error_response = "Please check your tool provider credentials"
|
||||
except (
|
||||
ToolNotFoundError, ToolNotSupportedError, ToolProviderNotFoundError
|
||||
) as e:
|
||||
error_response = f"there is not a tool named {tool_call_name}"
|
||||
except (
|
||||
ToolParameterValidationError
|
||||
) as e:
|
||||
error_response = f"tool parameters validation error: {e}, please check your tool parameters"
|
||||
except ToolInvokeError as e:
|
||||
error_response = f"tool invoke error: {e}"
|
||||
except Exception as e:
|
||||
error_response = f"unknown error: {e}"
|
||||
|
||||
message_file_ids = [message_file.id for message_file, _ in message_files]
|
||||
|
||||
observation = tool_invoke_response
|
||||
if error_response:
|
||||
observation = error_response
|
||||
else:
|
||||
observation = self._convert_tool_response_to_str(tool_response)
|
||||
|
||||
# save scratchpad
|
||||
scratchpad.observation = observation
|
||||
@@ -319,16 +329,9 @@ class CotAgentRunner(BaseAgentRunner):
|
||||
self.save_agent_thought(
|
||||
agent_thought=agent_thought,
|
||||
tool_name=tool_call_name,
|
||||
tool_input={
|
||||
tool_call_name: tool_call_args
|
||||
},
|
||||
tool_invoke_meta={
|
||||
tool_call_name: tool_invoke_meta.to_dict()
|
||||
},
|
||||
tool_input=tool_call_args,
|
||||
thought=None,
|
||||
observation={
|
||||
tool_call_name: observation
|
||||
},
|
||||
observation=observation,
|
||||
answer=scratchpad.agent_response,
|
||||
messages_ids=message_file_ids,
|
||||
)
|
||||
@@ -359,10 +362,9 @@ class CotAgentRunner(BaseAgentRunner):
|
||||
self.save_agent_thought(
|
||||
agent_thought=agent_thought,
|
||||
tool_name='',
|
||||
tool_input={},
|
||||
tool_invoke_meta={},
|
||||
tool_input='',
|
||||
thought=final_answer,
|
||||
observation={},
|
||||
observation='',
|
||||
answer=final_answer,
|
||||
messages_ids=[]
|
||||
)
|
||||
@@ -687,4 +689,4 @@ class CotAgentRunner(BaseAgentRunner):
|
||||
try:
|
||||
return json.dumps(tools, ensure_ascii=False)
|
||||
except json.JSONDecodeError:
|
||||
return json.dumps(tools)
|
||||
return json.dumps(tools)
|
||||
@@ -15,8 +15,15 @@ from core.model_runtime.entities.message_entities import (
|
||||
ToolPromptMessage,
|
||||
UserPromptMessage,
|
||||
)
|
||||
from core.tools.entities.tool_entities import ToolInvokeMeta
|
||||
from core.tools.tool_engine import ToolEngine
|
||||
from core.tools.errors import (
|
||||
ToolInvokeError,
|
||||
ToolNotFoundError,
|
||||
ToolNotSupportedError,
|
||||
ToolParameterValidationError,
|
||||
ToolProviderCredentialValidationError,
|
||||
ToolProviderNotFoundError,
|
||||
)
|
||||
from core.tools.utils.message_transformer import ToolFileMessageTransformer
|
||||
from models.model import Conversation, Message, MessageAgentThought
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -227,7 +234,6 @@ class FunctionCallAgentRunner(BaseAgentRunner):
|
||||
tool_name=tool_call_names,
|
||||
tool_input=tool_call_inputs,
|
||||
thought=response,
|
||||
tool_invoke_meta=None,
|
||||
observation=None,
|
||||
answer=response,
|
||||
messages_ids=[],
|
||||
@@ -253,40 +259,72 @@ class FunctionCallAgentRunner(BaseAgentRunner):
|
||||
tool_response = {
|
||||
"tool_call_id": tool_call_id,
|
||||
"tool_call_name": tool_call_name,
|
||||
"tool_response": f"there is not a tool named {tool_call_name}",
|
||||
"meta": ToolInvokeMeta.error_instance(f"there is not a tool named {tool_call_name}").to_dict()
|
||||
"tool_response": f"there is not a tool named {tool_call_name}"
|
||||
}
|
||||
tool_responses.append(tool_response)
|
||||
else:
|
||||
# invoke tool
|
||||
tool_invoke_response, message_files, tool_invoke_meta = ToolEngine.agent_invoke(
|
||||
tool=tool_instance,
|
||||
tool_parameters=tool_call_args,
|
||||
user_id=self.user_id,
|
||||
tenant_id=self.tenant_id,
|
||||
message=self.message,
|
||||
invoke_from=self.application_generate_entity.invoke_from,
|
||||
agent_tool_callback=self.agent_callback,
|
||||
)
|
||||
# publish files
|
||||
for message_file, save_as in message_files:
|
||||
if save_as:
|
||||
self.variables_pool.set_file(tool_name=tool_call_name, value=message_file.id, name=save_as)
|
||||
error_response = None
|
||||
try:
|
||||
tool_invoke_message = tool_instance.invoke(
|
||||
user_id=self.user_id,
|
||||
tool_parameters=tool_call_args,
|
||||
)
|
||||
# transform tool invoke message to get LLM friendly message
|
||||
tool_invoke_message = ToolFileMessageTransformer.transform_tool_invoke_messages(
|
||||
messages=tool_invoke_message,
|
||||
user_id=self.user_id,
|
||||
tenant_id=self.tenant_id,
|
||||
conversation_id=self.message.conversation_id
|
||||
)
|
||||
# extract binary data from tool invoke message
|
||||
binary_files = self.extract_tool_response_binary(tool_invoke_message)
|
||||
# create message file
|
||||
message_files = self.create_message_files(binary_files)
|
||||
# publish files
|
||||
for message_file, save_as in message_files:
|
||||
if save_as:
|
||||
self.variables_pool.set_file(tool_name=tool_call_name, value=message_file.id, name=save_as)
|
||||
|
||||
# publish message file
|
||||
self.queue_manager.publish(QueueMessageFileEvent(
|
||||
message_file_id=message_file.id
|
||||
), PublishFrom.APPLICATION_MANAGER)
|
||||
# add message file ids
|
||||
message_file_ids.append(message_file.id)
|
||||
|
||||
except ToolProviderCredentialValidationError as e:
|
||||
error_response = "Please check your tool provider credentials"
|
||||
except (
|
||||
ToolNotFoundError, ToolNotSupportedError, ToolProviderNotFoundError
|
||||
) as e:
|
||||
error_response = f"there is not a tool named {tool_call_name}"
|
||||
except (
|
||||
ToolParameterValidationError
|
||||
) as e:
|
||||
error_response = f"tool parameters validation error: {e}, please check your tool parameters"
|
||||
except ToolInvokeError as e:
|
||||
error_response = f"tool invoke error: {e}"
|
||||
except Exception as e:
|
||||
error_response = f"unknown error: {e}"
|
||||
|
||||
if error_response:
|
||||
observation = error_response
|
||||
tool_response = {
|
||||
"tool_call_id": tool_call_id,
|
||||
"tool_call_name": tool_call_name,
|
||||
"tool_response": error_response
|
||||
}
|
||||
tool_responses.append(tool_response)
|
||||
else:
|
||||
observation = self._convert_tool_response_to_str(tool_invoke_message)
|
||||
tool_response = {
|
||||
"tool_call_id": tool_call_id,
|
||||
"tool_call_name": tool_call_name,
|
||||
"tool_response": observation
|
||||
}
|
||||
tool_responses.append(tool_response)
|
||||
|
||||
# publish message file
|
||||
self.queue_manager.publish(QueueMessageFileEvent(
|
||||
message_file_id=message_file.id
|
||||
), PublishFrom.APPLICATION_MANAGER)
|
||||
# add message file ids
|
||||
message_file_ids.append(message_file.id)
|
||||
|
||||
tool_response = {
|
||||
"tool_call_id": tool_call_id,
|
||||
"tool_call_name": tool_call_name,
|
||||
"tool_response": tool_invoke_response,
|
||||
"meta": tool_invoke_meta.to_dict()
|
||||
}
|
||||
|
||||
tool_responses.append(tool_response)
|
||||
prompt_messages = self.organize_prompt_messages(
|
||||
prompt_template=prompt_template,
|
||||
query=None,
|
||||
@@ -303,14 +341,7 @@ class FunctionCallAgentRunner(BaseAgentRunner):
|
||||
tool_name=None,
|
||||
tool_input=None,
|
||||
thought=None,
|
||||
tool_invoke_meta={
|
||||
tool_response['tool_call_name']: tool_response['meta']
|
||||
for tool_response in tool_responses
|
||||
},
|
||||
observation={
|
||||
tool_response['tool_call_name']: tool_response['tool_response']
|
||||
for tool_response in tool_responses
|
||||
},
|
||||
observation=tool_response['tool_response'],
|
||||
answer=None,
|
||||
messages_ids=message_file_ids
|
||||
)
|
||||
|
||||
@@ -39,12 +39,12 @@ class SensitiveWordAvoidanceConfigManager:
|
||||
|
||||
if not only_structure_validate:
|
||||
typ = config["sensitive_word_avoidance"]["type"]
|
||||
sensitive_word_avoidance_config = config["sensitive_word_avoidance"]["config"]
|
||||
config = config["sensitive_word_avoidance"]["config"]
|
||||
|
||||
ModerationFactory.validate_config(
|
||||
name=typ,
|
||||
tenant_id=tenant_id,
|
||||
config=sensitive_word_avoidance_config
|
||||
config=config
|
||||
)
|
||||
|
||||
return config, ["sensitive_word_avoidance"]
|
||||
|
||||
@@ -189,6 +189,7 @@ class AdvancedChatAppGenerator(MessageBasedAppGenerator):
|
||||
logger.exception("Validation Error when generating")
|
||||
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
|
||||
except (ValueError, InvokeError) as e:
|
||||
logger.exception("Bad Request when generating")
|
||||
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
|
||||
except Exception as e:
|
||||
logger.exception("Unknown Error when generating")
|
||||
|
||||
@@ -196,7 +196,6 @@ class AdvancedChatAppGenerateTaskPipeline(BasedGenerateTaskPipeline, WorkflowCyc
|
||||
yield from self._generate_stream_outputs_when_node_started()
|
||||
|
||||
yield self._workflow_node_start_to_stream_response(
|
||||
event=event,
|
||||
task_id=self._application_generate_entity.task_id,
|
||||
workflow_node_execution=workflow_node_execution
|
||||
)
|
||||
@@ -215,16 +214,16 @@ class AdvancedChatAppGenerateTaskPipeline(BasedGenerateTaskPipeline, WorkflowCyc
|
||||
elif isinstance(event, QueueStopEvent | QueueWorkflowSucceededEvent | QueueWorkflowFailedEvent):
|
||||
workflow_run = self._handle_workflow_finished(event)
|
||||
if workflow_run:
|
||||
if workflow_run.status == WorkflowRunStatus.FAILED.value:
|
||||
err_event = QueueErrorEvent(error=ValueError(f'Run failed: {workflow_run.error}'))
|
||||
yield self._error_to_stream_response(self._handle_error(err_event))
|
||||
break
|
||||
|
||||
yield self._workflow_finish_to_stream_response(
|
||||
task_id=self._application_generate_entity.task_id,
|
||||
workflow_run=workflow_run
|
||||
)
|
||||
|
||||
if workflow_run.status == WorkflowRunStatus.FAILED.value:
|
||||
err_event = QueueErrorEvent(error=ValueError(f'Run failed: {workflow_run.error}'))
|
||||
yield self._error_to_stream_response(self._handle_error(err_event, self._message))
|
||||
break
|
||||
|
||||
if isinstance(event, QueueStopEvent):
|
||||
# Save message
|
||||
self._save_message()
|
||||
|
||||
@@ -143,12 +143,6 @@ class AgentChatAppConfigManager(BaseAppConfigManager):
|
||||
config, current_related_config_keys = RetrievalResourceConfigManager.validate_and_set_defaults(config)
|
||||
related_config_keys.extend(current_related_config_keys)
|
||||
|
||||
# dataset configs
|
||||
# dataset_query_variable
|
||||
config, current_related_config_keys = DatasetConfigManager.validate_and_set_defaults(tenant_id, app_mode,
|
||||
config)
|
||||
related_config_keys.extend(current_related_config_keys)
|
||||
|
||||
# moderation validation
|
||||
config, current_related_config_keys = SensitiveWordAvoidanceConfigManager.validate_and_set_defaults(tenant_id,
|
||||
config)
|
||||
|
||||
@@ -198,6 +198,7 @@ class AgentChatAppGenerator(MessageBasedAppGenerator):
|
||||
logger.exception("Validation Error when generating")
|
||||
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
|
||||
except (ValueError, InvokeError) as e:
|
||||
logger.exception("Bad Request when generating")
|
||||
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
|
||||
except Exception as e:
|
||||
logger.exception("Unknown Error when generating")
|
||||
|
||||
@@ -169,11 +169,10 @@ class AppRunner:
|
||||
text=advanced_completion_prompt_template.prompt
|
||||
)
|
||||
|
||||
if advanced_completion_prompt_template.role_prefix:
|
||||
memory_config.role_prefix = MemoryConfig.RolePrefix(
|
||||
user=advanced_completion_prompt_template.role_prefix.user,
|
||||
assistant=advanced_completion_prompt_template.role_prefix.assistant
|
||||
)
|
||||
memory_config.role_prefix = MemoryConfig.RolePrefix(
|
||||
user=advanced_completion_prompt_template.role_prefix.user,
|
||||
assistant=advanced_completion_prompt_template.role_prefix.assistant
|
||||
)
|
||||
else:
|
||||
prompt_template = []
|
||||
for message in prompt_template_entity.advanced_chat_prompt_template.messages:
|
||||
|
||||
@@ -195,6 +195,7 @@ class ChatAppGenerator(MessageBasedAppGenerator):
|
||||
logger.exception("Validation Error when generating")
|
||||
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
|
||||
except (ValueError, InvokeError) as e:
|
||||
logger.exception("Bad Request when generating")
|
||||
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
|
||||
except Exception as e:
|
||||
logger.exception("Unknown Error when generating")
|
||||
|
||||
@@ -184,6 +184,7 @@ class CompletionAppGenerator(MessageBasedAppGenerator):
|
||||
logger.exception("Validation Error when generating")
|
||||
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
|
||||
except (ValueError, InvokeError) as e:
|
||||
logger.exception("Bad Request when generating")
|
||||
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
|
||||
except Exception as e:
|
||||
logger.exception("Unknown Error when generating")
|
||||
|
||||
@@ -137,6 +137,7 @@ class WorkflowAppGenerator(BaseAppGenerator):
|
||||
logger.exception("Validation Error when generating")
|
||||
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
|
||||
except (ValueError, InvokeError) as e:
|
||||
logger.exception("Bad Request when generating")
|
||||
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
|
||||
except Exception as e:
|
||||
logger.exception("Unknown Error when generating")
|
||||
|
||||
@@ -162,7 +162,6 @@ class WorkflowAppGenerateTaskPipeline(BasedGenerateTaskPipeline, WorkflowCycleMa
|
||||
elif isinstance(event, QueueNodeStartedEvent):
|
||||
workflow_node_execution = self._handle_node_start(event)
|
||||
yield self._workflow_node_start_to_stream_response(
|
||||
event=event,
|
||||
task_id=self._application_generate_entity.task_id,
|
||||
workflow_node_execution=workflow_node_execution
|
||||
)
|
||||
|
||||
@@ -179,7 +179,6 @@ class WorkflowStartStreamResponse(StreamResponse):
|
||||
id: str
|
||||
workflow_id: str
|
||||
sequence_number: int
|
||||
inputs: dict
|
||||
created_at: int
|
||||
|
||||
event: StreamEvent = StreamEvent.WORKFLOW_STARTED
|
||||
@@ -230,7 +229,6 @@ class NodeStartStreamResponse(StreamResponse):
|
||||
predecessor_node_id: Optional[str] = None
|
||||
inputs: Optional[dict] = None
|
||||
created_at: int
|
||||
extras: dict = {}
|
||||
|
||||
event: StreamEvent = StreamEvent.NODE_STARTED
|
||||
workflow_run_id: str
|
||||
|
||||
@@ -14,7 +14,7 @@ from core.app.entities.task_entities import (
|
||||
PingStreamResponse,
|
||||
TaskState,
|
||||
)
|
||||
from core.errors.error import QuotaExceededError
|
||||
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
|
||||
from core.model_runtime.errors.invoke import InvokeAuthorizationError, InvokeError
|
||||
from core.moderation.output_moderation import ModerationRule, OutputModeration
|
||||
from extensions.ext_database import db
|
||||
@@ -83,12 +83,24 @@ class BasedGenerateTaskPipeline:
|
||||
:param e: exception
|
||||
:return:
|
||||
"""
|
||||
if isinstance(e, QuotaExceededError):
|
||||
return ("Your quota for Dify Hosted Model Provider has been exhausted. "
|
||||
"Please go to Settings -> Model Provider to complete your own provider credentials.")
|
||||
error_responses = {
|
||||
ValueError: None,
|
||||
ProviderTokenNotInitError: None,
|
||||
QuotaExceededError: "Your quota for Dify Hosted Model Provider has been exhausted. "
|
||||
"Please go to Settings -> Model Provider to complete your own provider credentials.",
|
||||
ModelCurrentlyNotSupportError: None,
|
||||
InvokeError: None
|
||||
}
|
||||
|
||||
message = getattr(e, 'description', str(e))
|
||||
if not message:
|
||||
# Determine the response based on the type of exception
|
||||
data = None
|
||||
for k, v in error_responses.items():
|
||||
if isinstance(e, k):
|
||||
data = v
|
||||
|
||||
if data:
|
||||
message = getattr(e, 'description', str(e)) if data is None else data
|
||||
else:
|
||||
message = 'Internal Server Error, please contact support.'
|
||||
|
||||
return message
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import json
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import Any, Optional, Union, cast
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
from core.app.entities.app_invoke_entities import AdvancedChatAppGenerateEntity, InvokeFrom, WorkflowAppGenerateEntity
|
||||
from core.app.entities.queue_entities import (
|
||||
@@ -23,9 +23,7 @@ from core.app.entities.task_entities import (
|
||||
)
|
||||
from core.file.file_obj import FileVar
|
||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
||||
from core.tools.tool_manager import ToolManager
|
||||
from core.workflow.entities.node_entities import NodeRunMetadataKey, NodeType, SystemVariable
|
||||
from core.workflow.nodes.tool.entities import ToolNodeData
|
||||
from core.workflow.workflow_engine_manager import WorkflowEngineManager
|
||||
from extensions.ext_database import db
|
||||
from models.account import Account
|
||||
@@ -71,9 +69,6 @@ class WorkflowCycleManage:
|
||||
|
||||
inputs = {**user_inputs}
|
||||
for key, value in (system_inputs or {}).items():
|
||||
if key.value == 'conversation':
|
||||
continue
|
||||
|
||||
inputs[f'sys.{key.value}'] = value
|
||||
inputs = WorkflowEngineManager.handle_special_values(inputs)
|
||||
|
||||
@@ -277,7 +272,6 @@ class WorkflowCycleManage:
|
||||
id=workflow_run.id,
|
||||
workflow_id=workflow_run.workflow_id,
|
||||
sequence_number=workflow_run.sequence_number,
|
||||
inputs=workflow_run.inputs_dict,
|
||||
created_at=int(workflow_run.created_at.timestamp())
|
||||
)
|
||||
)
|
||||
@@ -327,18 +321,15 @@ class WorkflowCycleManage:
|
||||
)
|
||||
)
|
||||
|
||||
def _workflow_node_start_to_stream_response(self, event: QueueNodeStartedEvent,
|
||||
task_id: str,
|
||||
workflow_node_execution: WorkflowNodeExecution) \
|
||||
def _workflow_node_start_to_stream_response(self, task_id: str, workflow_node_execution: WorkflowNodeExecution) \
|
||||
-> NodeStartStreamResponse:
|
||||
"""
|
||||
Workflow node start to stream response.
|
||||
:param event: queue node started event
|
||||
:param task_id: task id
|
||||
:param workflow_node_execution: workflow node execution
|
||||
:return:
|
||||
"""
|
||||
response = NodeStartStreamResponse(
|
||||
return NodeStartStreamResponse(
|
||||
task_id=task_id,
|
||||
workflow_run_id=workflow_node_execution.workflow_run_id,
|
||||
data=NodeStartStreamResponse.Data(
|
||||
@@ -353,17 +344,6 @@ class WorkflowCycleManage:
|
||||
)
|
||||
)
|
||||
|
||||
# extras logic
|
||||
if event.node_type == NodeType.TOOL:
|
||||
node_data = cast(ToolNodeData, event.node_data)
|
||||
response.data.extras['icon'] = ToolManager.get_tool_icon(
|
||||
tenant_id=self._application_generate_entity.app_config.tenant_id,
|
||||
provider_type=node_data.provider_type,
|
||||
provider_id=node_data.provider_id
|
||||
)
|
||||
|
||||
return response
|
||||
|
||||
def _workflow_node_finish_to_stream_response(self, task_id: str, workflow_node_execution: WorkflowNodeExecution) \
|
||||
-> NodeFinishStreamResponse:
|
||||
"""
|
||||
|
||||
@@ -36,7 +36,7 @@ class DifyAgentCallbackHandler(BaseCallbackHandler, BaseModel):
|
||||
print_text("\n[on_tool_end]\n", color=self.color)
|
||||
print_text("Tool: " + tool_name + "\n", color=self.color)
|
||||
print_text("Inputs: " + str(tool_inputs) + "\n", color=self.color)
|
||||
print_text("Outputs: " + str(tool_outputs)[:1000] + "\n", color=self.color)
|
||||
print_text("Outputs: " + str(tool_outputs) + "\n", color=self.color)
|
||||
print_text("\n")
|
||||
|
||||
def on_tool_error(
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
from core.callback_handler.agent_tool_callback_handler import DifyAgentCallbackHandler
|
||||
|
||||
|
||||
class DifyWorkflowCallbackHandler(DifyAgentCallbackHandler):
|
||||
"""Callback Handler that prints to std out."""
|
||||
@@ -12,7 +12,6 @@ from core.rag.datasource.entity.embedding import Embeddings
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
from libs import helper
|
||||
from models.dataset import Embedding
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -24,58 +23,32 @@ class CacheEmbedding(Embeddings):
|
||||
|
||||
def embed_documents(self, texts: list[str]) -> list[list[float]]:
|
||||
"""Embed search docs in batches of 10."""
|
||||
# use doc embedding cache or store if not exists
|
||||
text_embeddings = [None for _ in range(len(texts))]
|
||||
embedding_queue_indices = []
|
||||
for i, text in enumerate(texts):
|
||||
hash = helper.generate_text_hash(text)
|
||||
embedding = db.session.query(Embedding).filter_by(model_name=self._model_instance.model,
|
||||
hash=hash,
|
||||
provider_name=self._model_instance.provider).first()
|
||||
if embedding:
|
||||
text_embeddings[i] = embedding.get_embedding()
|
||||
else:
|
||||
embedding_queue_indices.append(i)
|
||||
if embedding_queue_indices:
|
||||
embedding_queue_texts = [texts[i] for i in embedding_queue_indices]
|
||||
embedding_queue_embeddings = []
|
||||
try:
|
||||
model_type_instance = cast(TextEmbeddingModel, self._model_instance.model_type_instance)
|
||||
model_schema = model_type_instance.get_model_schema(self._model_instance.model, self._model_instance.credentials)
|
||||
max_chunks = model_schema.model_properties[ModelPropertyKey.MAX_CHUNKS] \
|
||||
if model_schema and ModelPropertyKey.MAX_CHUNKS in model_schema.model_properties else 1
|
||||
for i in range(0, len(embedding_queue_texts), max_chunks):
|
||||
batch_texts = embedding_queue_texts[i:i + max_chunks]
|
||||
text_embeddings = []
|
||||
try:
|
||||
model_type_instance = cast(TextEmbeddingModel, self._model_instance.model_type_instance)
|
||||
model_schema = model_type_instance.get_model_schema(self._model_instance.model, self._model_instance.credentials)
|
||||
max_chunks = model_schema.model_properties[ModelPropertyKey.MAX_CHUNKS] \
|
||||
if model_schema and ModelPropertyKey.MAX_CHUNKS in model_schema.model_properties else 1
|
||||
for i in range(0, len(texts), max_chunks):
|
||||
batch_texts = texts[i:i + max_chunks]
|
||||
|
||||
embedding_result = self._model_instance.invoke_text_embedding(
|
||||
texts=batch_texts,
|
||||
user=self._user
|
||||
)
|
||||
embedding_result = self._model_instance.invoke_text_embedding(
|
||||
texts=batch_texts,
|
||||
user=self._user
|
||||
)
|
||||
|
||||
for vector in embedding_result.embeddings:
|
||||
try:
|
||||
normalized_embedding = (vector / np.linalg.norm(vector)).tolist()
|
||||
embedding_queue_embeddings.append(normalized_embedding)
|
||||
except IntegrityError:
|
||||
db.session.rollback()
|
||||
except Exception as e:
|
||||
logging.exception('Failed transform embedding: ', e)
|
||||
cache_embeddings = []
|
||||
for i, embedding in zip(embedding_queue_indices, embedding_queue_embeddings):
|
||||
text_embeddings[i] = embedding
|
||||
hash = helper.generate_text_hash(texts[i])
|
||||
if hash not in cache_embeddings:
|
||||
embedding_cache = Embedding(model_name=self._model_instance.model,
|
||||
hash=hash,
|
||||
provider_name=self._model_instance.provider)
|
||||
embedding_cache.set_embedding(embedding)
|
||||
db.session.add(embedding_cache)
|
||||
cache_embeddings.append(hash)
|
||||
db.session.commit()
|
||||
except Exception as ex:
|
||||
db.session.rollback()
|
||||
logger.error('Failed to embed documents: ', ex)
|
||||
raise ex
|
||||
for vector in embedding_result.embeddings:
|
||||
try:
|
||||
normalized_embedding = (vector / np.linalg.norm(vector)).tolist()
|
||||
text_embeddings.append(normalized_embedding)
|
||||
except IntegrityError:
|
||||
db.session.rollback()
|
||||
except Exception as e:
|
||||
logging.exception('Failed to add embedding to redis')
|
||||
|
||||
except Exception as ex:
|
||||
logger.error('Failed to embed documents: ', ex)
|
||||
raise ex
|
||||
|
||||
return text_embeddings
|
||||
|
||||
@@ -88,6 +61,8 @@ class CacheEmbedding(Embeddings):
|
||||
if embedding:
|
||||
redis_client.expire(embedding_cache_key, 600)
|
||||
return list(np.frombuffer(base64.b64decode(embedding), dtype="float"))
|
||||
|
||||
|
||||
try:
|
||||
embedding_result = self._model_instance.invoke_text_embedding(
|
||||
texts=[text],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import enum
|
||||
import importlib
|
||||
import importlib.util
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
@@ -47,7 +47,7 @@ class CodeExecutor:
|
||||
else:
|
||||
raise CodeExecutionException('Unsupported language')
|
||||
|
||||
runner, preload = template_transformer.transform_caller(code, inputs)
|
||||
runner = template_transformer.transform_caller(code, inputs)
|
||||
url = URL(CODE_EXECUTION_ENDPOINT) / 'v1' / 'sandbox' / 'run'
|
||||
headers = {
|
||||
'X-Api-Key': CODE_EXECUTION_API_KEY
|
||||
@@ -57,7 +57,6 @@ class CodeExecutor:
|
||||
'nodejs' if language == 'javascript' else
|
||||
'python3' if language == 'python3' else None,
|
||||
'code': runner,
|
||||
'preload': preload
|
||||
}
|
||||
|
||||
try:
|
||||
@@ -65,11 +64,11 @@ class CodeExecutor:
|
||||
if response.status_code == 503:
|
||||
raise CodeExecutionException('Code execution service is unavailable')
|
||||
elif response.status_code != 200:
|
||||
raise Exception(f'Failed to execute code, got status code {response.status_code}, please check if the sandbox service is running')
|
||||
raise Exception('Failed to execute code')
|
||||
except CodeExecutionException as e:
|
||||
raise e
|
||||
except Exception as e:
|
||||
raise CodeExecutionException('Failed to execute code, this is likely a network issue, please check if the sandbox service is running')
|
||||
raise CodeExecutionException('Failed to execute code')
|
||||
|
||||
try:
|
||||
response = response.json()
|
||||
|
||||
@@ -18,11 +18,10 @@ result = `<<RESULT>>${output}<<RESULT>>`
|
||||
console.log(result)
|
||||
"""
|
||||
|
||||
NODEJS_PRELOAD = """"""
|
||||
|
||||
class NodeJsTemplateTransformer(TemplateTransformer):
|
||||
@classmethod
|
||||
def transform_caller(cls, code: str, inputs: dict) -> tuple[str, str]:
|
||||
def transform_caller(cls, code: str, inputs: dict) -> str:
|
||||
"""
|
||||
Transform code to python runner
|
||||
:param code: code
|
||||
@@ -37,7 +36,7 @@ class NodeJsTemplateTransformer(TemplateTransformer):
|
||||
runner = NODEJS_RUNNER.replace('{{code}}', code)
|
||||
runner = runner.replace('{{inputs}}', inputs_str)
|
||||
|
||||
return runner, NODEJS_PRELOAD
|
||||
return runner
|
||||
|
||||
@classmethod
|
||||
def transform_response(cls, response: str) -> dict:
|
||||
|
||||
@@ -20,39 +20,9 @@ print(result)
|
||||
|
||||
"""
|
||||
|
||||
JINJA2_PRELOAD_TEMPLATE = """{% set fruits = ['Apple'] %}
|
||||
{{ 'a' }}
|
||||
{% for fruit in fruits %}
|
||||
<li>{{ fruit }}</li>
|
||||
{% endfor %}
|
||||
{% if fruits|length > 1 %}
|
||||
1
|
||||
{% endif %}
|
||||
{% for i in range(5) %}
|
||||
{% if i == 3 %}{{ i }}{% else %}{% endif %}
|
||||
{% endfor %}
|
||||
{% for i in range(3) %}
|
||||
{{ i + 1 }}
|
||||
{% endfor %}
|
||||
{% macro say_hello() %}a{{ 'b' }}{% endmacro %}
|
||||
{{ s }}{{ say_hello() }}"""
|
||||
|
||||
JINJA2_PRELOAD = f"""
|
||||
import jinja2
|
||||
|
||||
def _jinja2_preload_():
|
||||
# prepare jinja2 environment, load template and render before to avoid sandbox issue
|
||||
template = jinja2.Template('''{JINJA2_PRELOAD_TEMPLATE}''')
|
||||
template.render(s='a')
|
||||
|
||||
if __name__ == '__main__':
|
||||
_jinja2_preload_()
|
||||
|
||||
"""
|
||||
|
||||
class Jinja2TemplateTransformer(TemplateTransformer):
|
||||
@classmethod
|
||||
def transform_caller(cls, code: str, inputs: dict) -> tuple[str, str]:
|
||||
def transform_caller(cls, code: str, inputs: dict) -> str:
|
||||
"""
|
||||
Transform code to python runner
|
||||
:param code: code
|
||||
@@ -64,7 +34,7 @@ class Jinja2TemplateTransformer(TemplateTransformer):
|
||||
runner = PYTHON_RUNNER.replace('{{code}}', code)
|
||||
runner = runner.replace('{{inputs}}', json.dumps(inputs, indent=4))
|
||||
|
||||
return runner, JINJA2_PRELOAD
|
||||
return runner
|
||||
|
||||
@classmethod
|
||||
def transform_response(cls, response: str) -> dict:
|
||||
|
||||
@@ -20,12 +20,10 @@ result = f'''<<RESULT>>
|
||||
print(result)
|
||||
"""
|
||||
|
||||
PYTHON_PRELOAD = """"""
|
||||
|
||||
|
||||
class PythonTemplateTransformer(TemplateTransformer):
|
||||
@classmethod
|
||||
def transform_caller(cls, code: str, inputs: dict) -> tuple[str, str]:
|
||||
def transform_caller(cls, code: str, inputs: dict) -> str:
|
||||
"""
|
||||
Transform code to python runner
|
||||
:param code: code
|
||||
@@ -40,7 +38,7 @@ class PythonTemplateTransformer(TemplateTransformer):
|
||||
runner = PYTHON_RUNNER.replace('{{code}}', code)
|
||||
runner = runner.replace('{{inputs}}', inputs_str)
|
||||
|
||||
return runner, PYTHON_PRELOAD
|
||||
return runner
|
||||
|
||||
@classmethod
|
||||
def transform_response(cls, response: str) -> dict:
|
||||
|
||||
@@ -4,12 +4,12 @@ from abc import ABC, abstractmethod
|
||||
class TemplateTransformer(ABC):
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def transform_caller(cls, code: str, inputs: dict) -> tuple[str, str]:
|
||||
def transform_caller(cls, code: str, inputs: dict) -> str:
|
||||
"""
|
||||
Transform code to python runner
|
||||
:param code: code
|
||||
:param inputs: inputs
|
||||
:return: runner, preload
|
||||
:return:
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
+16
-33
@@ -1,4 +1,3 @@
|
||||
import concurrent.futures
|
||||
import datetime
|
||||
import json
|
||||
import logging
|
||||
@@ -651,44 +650,17 @@ class IndexingRunner:
|
||||
# chunk nodes by chunk size
|
||||
indexing_start_at = time.perf_counter()
|
||||
tokens = 0
|
||||
chunk_size = 10
|
||||
chunk_size = 100
|
||||
|
||||
embedding_model_type_instance = None
|
||||
if embedding_model_instance:
|
||||
embedding_model_type_instance = embedding_model_instance.model_type_instance
|
||||
embedding_model_type_instance = cast(TextEmbeddingModel, embedding_model_type_instance)
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
|
||||
futures = []
|
||||
for i in range(0, len(documents), chunk_size):
|
||||
chunk_documents = documents[i:i + chunk_size]
|
||||
futures.append(executor.submit(self._process_chunk, current_app._get_current_object(), index_processor,
|
||||
chunk_documents, dataset,
|
||||
dataset_document, embedding_model_instance,
|
||||
embedding_model_type_instance))
|
||||
|
||||
for future in futures:
|
||||
tokens += future.result()
|
||||
|
||||
indexing_end_at = time.perf_counter()
|
||||
|
||||
# update document status to completed
|
||||
self._update_document_index_status(
|
||||
document_id=dataset_document.id,
|
||||
after_indexing_status="completed",
|
||||
extra_update_params={
|
||||
DatasetDocument.tokens: tokens,
|
||||
DatasetDocument.completed_at: datetime.datetime.utcnow(),
|
||||
DatasetDocument.indexing_latency: indexing_end_at - indexing_start_at,
|
||||
}
|
||||
)
|
||||
|
||||
def _process_chunk(self, flask_app, index_processor, chunk_documents, dataset, dataset_document,
|
||||
embedding_model_instance, embedding_model_type_instance):
|
||||
with flask_app.app_context():
|
||||
for i in range(0, len(documents), chunk_size):
|
||||
# check document is paused
|
||||
self._check_document_paused_status(dataset_document.id)
|
||||
|
||||
tokens = 0
|
||||
chunk_documents = documents[i:i + chunk_size]
|
||||
if dataset.indexing_technique == 'high_quality' or embedding_model_type_instance:
|
||||
tokens += sum(
|
||||
embedding_model_type_instance.get_num_tokens(
|
||||
@@ -698,9 +670,9 @@ class IndexingRunner:
|
||||
)
|
||||
for document in chunk_documents
|
||||
)
|
||||
|
||||
# load index
|
||||
index_processor.load(dataset, chunk_documents)
|
||||
db.session.add(dataset)
|
||||
|
||||
document_ids = [document.metadata['doc_id'] for document in chunk_documents]
|
||||
db.session.query(DocumentSegment).filter(
|
||||
@@ -715,7 +687,18 @@ class IndexingRunner:
|
||||
|
||||
db.session.commit()
|
||||
|
||||
return tokens
|
||||
indexing_end_at = time.perf_counter()
|
||||
|
||||
# update document status to completed
|
||||
self._update_document_index_status(
|
||||
document_id=dataset_document.id,
|
||||
after_indexing_status="completed",
|
||||
extra_update_params={
|
||||
DatasetDocument.tokens: tokens,
|
||||
DatasetDocument.completed_at: datetime.datetime.utcnow(),
|
||||
DatasetDocument.indexing_latency: indexing_end_at - indexing_start_at,
|
||||
}
|
||||
)
|
||||
|
||||
def _check_document_paused_status(self, document_id: str):
|
||||
indexing_cache_key = 'document_{}_is_paused'.format(document_id)
|
||||
|
||||
@@ -166,7 +166,6 @@ class LLMGenerator:
|
||||
response = model_instance.invoke_llm(
|
||||
prompt_messages=prompt_messages,
|
||||
model_parameters={
|
||||
'temperature': 0.01,
|
||||
"max_tokens": 2000
|
||||
},
|
||||
stream=False
|
||||
|
||||
@@ -69,15 +69,13 @@ SUGGESTED_QUESTIONS_AFTER_ANSWER_INSTRUCTION_PROMPT = (
|
||||
)
|
||||
|
||||
GENERATOR_QA_PROMPT = (
|
||||
'<Task> The user will send a long text. Generate a Question and Answer pairs only using the knowledge in the long text. Please think step by step.'
|
||||
'The user will send a long text. Please think step by step.'
|
||||
'Step 1: Understand and summarize the main content of this text.\n'
|
||||
'Step 2: What key information or concepts are mentioned in this text?\n'
|
||||
'Step 3: Decompose or combine multiple pieces of information and concepts.\n'
|
||||
'Step 4: Generate questions and answers based on these key information and concepts.\n'
|
||||
'<Constraints> The questions should be clear and detailed, and the answers should be detailed and complete. '
|
||||
'You must answer in {language}, in a style that is clear and detailed in {language}. No language other than {language} should be used. \n'
|
||||
'<Format> Use the following format: Q1:\nA1:\nQ2:\nA2:...\n'
|
||||
'<QA Pairs>'
|
||||
'Step 4: Generate 20 questions and answers based on these key information and concepts.'
|
||||
'The questions should be clear and detailed, and the answers should be detailed and complete.\n'
|
||||
"Answer MUST according to the the language:{language} and in the following format: Q1:\nA1:\nQ2:\nA2:...\n"
|
||||
)
|
||||
|
||||
RULE_CONFIG_GENERATE_TEMPLATE = """Given MY INTENDED AUDIENCES and HOPING TO SOLVE using a language model, please select \
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
|
||||
- `input` (float) Input price, i.e., Prompt price
|
||||
- `output` (float) Output price, i.e., returned content price
|
||||
- `unit` (float) Pricing unit, e.g., if the price is meausred in 1M tokens, the corresponding token amount for the unit price is `0.000001`.
|
||||
- `unit` (float) Pricing unit, e.g., per 100K price is `0.000001`
|
||||
- `currency` (string) Currency unit
|
||||
|
||||
### ProviderCredentialSchema
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
|
||||
- `input` (float) 输入单价,即 Prompt 单价
|
||||
- `output` (float) 输出单价,即返回内容单价
|
||||
- `unit` (float) 价格单位,如以 1M tokens 计价,则单价对应的单位 token 数为 `0.000001`
|
||||
- `unit` (float) 价格单位,如:每 100K 的单价为 `0.000001`
|
||||
- `currency` (string) 货币单位
|
||||
|
||||
### ProviderCredentialSchema
|
||||
|
||||
@@ -73,8 +73,8 @@ PARAMETER_RULE_TEMPLATE: dict[DefaultParameterName, dict] = {
|
||||
},
|
||||
'type': 'int',
|
||||
'help': {
|
||||
'en_US': 'Specifies the upper limit on the length of generated results. If the generated results are truncated, you can increase this parameter.',
|
||||
'zh_Hans': '指定生成结果长度的上限。如果生成结果截断,可以调大该参数。',
|
||||
'en_US': 'The maximum number of tokens to generate. Requests can use up to 2048 tokens shared between prompt and completion.',
|
||||
'zh_Hans': '要生成的标记的最大数量。请求可以使用最多2048个标记,这些标记在提示和完成之间共享。',
|
||||
},
|
||||
'required': False,
|
||||
'default': 64,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import importlib
|
||||
import os
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
@@ -6,7 +7,6 @@ import yaml
|
||||
from core.model_runtime.entities.model_entities import AIModelEntity, ModelType
|
||||
from core.model_runtime.entities.provider_entities import ProviderEntity
|
||||
from core.model_runtime.model_providers.__base.ai_model import AIModel
|
||||
from core.utils.module_import_helper import get_subclasses_from_module, import_module_from_source
|
||||
|
||||
|
||||
class ModelProvider(ABC):
|
||||
@@ -104,10 +104,17 @@ class ModelProvider(ABC):
|
||||
|
||||
# Dynamic loading {model_type_name}.py file and find the subclass of AIModel
|
||||
parent_module = '.'.join(self.__class__.__module__.split('.')[:-1])
|
||||
mod = import_module_from_source(
|
||||
f'{parent_module}.{model_type_name}.{model_type_name}', model_type_py_path)
|
||||
model_class = next(filter(lambda x: x.__module__ == mod.__name__ and not x.__abstractmethods__,
|
||||
get_subclasses_from_module(mod, AIModel)), None)
|
||||
spec = importlib.util.spec_from_file_location(f"{parent_module}.{model_type_name}.{model_type_name}", model_type_py_path)
|
||||
mod = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(mod)
|
||||
|
||||
model_class = None
|
||||
for name, obj in vars(mod).items():
|
||||
if (isinstance(obj, type) and issubclass(obj, AIModel) and not obj.__abstractmethods__
|
||||
and obj != AIModel and obj.__module__ == mod.__name__):
|
||||
model_class = obj
|
||||
break
|
||||
|
||||
if not model_class:
|
||||
raise Exception(f'Missing AIModel Class for model type {model_type} in {model_type_py_path}')
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
- cohere
|
||||
- bedrock
|
||||
- togetherai
|
||||
- openrouter
|
||||
- ollama
|
||||
- mistralai
|
||||
- groq
|
||||
|
||||
@@ -5,7 +5,6 @@ model_type: llm
|
||||
features:
|
||||
- agent-thought
|
||||
- vision
|
||||
- tool-call
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 200000
|
||||
|
||||
@@ -5,7 +5,6 @@ model_type: llm
|
||||
features:
|
||||
- agent-thought
|
||||
- vision
|
||||
- tool-call
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 200000
|
||||
|
||||
@@ -5,7 +5,6 @@ model_type: llm
|
||||
features:
|
||||
- agent-thought
|
||||
- vision
|
||||
- tool-call
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 200000
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import base64
|
||||
import json
|
||||
import mimetypes
|
||||
from collections.abc import Generator
|
||||
from typing import Optional, Union, cast
|
||||
@@ -16,7 +15,6 @@ from anthropic.types import (
|
||||
MessageStreamEvent,
|
||||
completion_create_params,
|
||||
)
|
||||
from anthropic.types.beta.tools import ToolsBetaMessage
|
||||
from httpx import Timeout
|
||||
|
||||
from core.model_runtime.callbacks.base_callback import Callback
|
||||
@@ -29,7 +27,6 @@ from core.model_runtime.entities.message_entities import (
|
||||
PromptMessageTool,
|
||||
SystemPromptMessage,
|
||||
TextPromptMessageContent,
|
||||
ToolPromptMessage,
|
||||
UserPromptMessage,
|
||||
)
|
||||
from core.model_runtime.errors.invoke import (
|
||||
@@ -73,11 +70,10 @@ class AnthropicLargeLanguageModel(LargeLanguageModel):
|
||||
:return: full response or stream response chunk generator result
|
||||
"""
|
||||
# invoke model
|
||||
return self._chat_generate(model, credentials, prompt_messages, model_parameters, tools, stop, stream, user)
|
||||
return self._chat_generate(model, credentials, prompt_messages, model_parameters, stop, stream, user)
|
||||
|
||||
def _chat_generate(self, model: str, credentials: dict,
|
||||
prompt_messages: list[PromptMessage], model_parameters: dict,
|
||||
tools: Optional[list[PromptMessageTool]] = None, stop: Optional[list[str]] = None,
|
||||
prompt_messages: list[PromptMessage], model_parameters: dict, stop: Optional[list[str]] = None,
|
||||
stream: bool = True, user: Optional[str] = None) -> Union[LLMResult, Generator]:
|
||||
"""
|
||||
Invoke llm chat model
|
||||
@@ -113,26 +109,14 @@ class AnthropicLargeLanguageModel(LargeLanguageModel):
|
||||
if system:
|
||||
extra_model_kwargs['system'] = system
|
||||
|
||||
if tools:
|
||||
extra_model_kwargs['tools'] = [
|
||||
self._transform_tool_prompt(tool) for tool in tools
|
||||
]
|
||||
response = client.beta.tools.messages.create(
|
||||
model=model,
|
||||
messages=prompt_message_dicts,
|
||||
stream=stream,
|
||||
**model_parameters,
|
||||
**extra_model_kwargs
|
||||
)
|
||||
else:
|
||||
# chat model
|
||||
response = client.messages.create(
|
||||
model=model,
|
||||
messages=prompt_message_dicts,
|
||||
stream=stream,
|
||||
**model_parameters,
|
||||
**extra_model_kwargs
|
||||
)
|
||||
# chat model
|
||||
response = client.messages.create(
|
||||
model=model,
|
||||
messages=prompt_message_dicts,
|
||||
stream=stream,
|
||||
**model_parameters,
|
||||
**extra_model_kwargs
|
||||
)
|
||||
|
||||
if stream:
|
||||
return self._handle_chat_generate_stream_response(model, credentials, response, prompt_messages)
|
||||
@@ -164,13 +148,6 @@ class AnthropicLargeLanguageModel(LargeLanguageModel):
|
||||
|
||||
return self._invoke(model, credentials, prompt_messages, model_parameters, tools, stop, stream, user)
|
||||
|
||||
def _transform_tool_prompt(self, tool: PromptMessageTool) -> dict:
|
||||
return {
|
||||
'name': tool.name,
|
||||
'description': tool.description,
|
||||
'input_schema': tool.parameters
|
||||
}
|
||||
|
||||
def _transform_chat_json_prompts(self, model: str, credentials: dict,
|
||||
prompt_messages: list[PromptMessage], model_parameters: dict,
|
||||
tools: list[PromptMessageTool] | None = None, stop: list[str] | None = None,
|
||||
@@ -216,18 +193,7 @@ class AnthropicLargeLanguageModel(LargeLanguageModel):
|
||||
prompt = self._convert_messages_to_prompt_anthropic(prompt_messages)
|
||||
|
||||
client = Anthropic(api_key="")
|
||||
tokens = client.count_tokens(prompt)
|
||||
|
||||
tool_call_inner_prompts_tokens_map = {
|
||||
'claude-3-opus-20240229': 395,
|
||||
'claude-3-haiku-20240307': 264,
|
||||
'claude-3-sonnet-20240229': 159
|
||||
}
|
||||
|
||||
if model in tool_call_inner_prompts_tokens_map and tools:
|
||||
tokens += tool_call_inner_prompts_tokens_map[model]
|
||||
|
||||
return tokens
|
||||
return client.count_tokens(prompt)
|
||||
|
||||
def validate_credentials(self, model: str, credentials: dict) -> None:
|
||||
"""
|
||||
@@ -253,7 +219,7 @@ class AnthropicLargeLanguageModel(LargeLanguageModel):
|
||||
except Exception as ex:
|
||||
raise CredentialsValidateFailedError(str(ex))
|
||||
|
||||
def _handle_chat_generate_response(self, model: str, credentials: dict, response: Union[Message, ToolsBetaMessage],
|
||||
def _handle_chat_generate_response(self, model: str, credentials: dict, response: Message,
|
||||
prompt_messages: list[PromptMessage]) -> LLMResult:
|
||||
"""
|
||||
Handle llm chat response
|
||||
@@ -266,24 +232,9 @@ class AnthropicLargeLanguageModel(LargeLanguageModel):
|
||||
"""
|
||||
# transform assistant message to prompt message
|
||||
assistant_prompt_message = AssistantPromptMessage(
|
||||
content='',
|
||||
tool_calls=[]
|
||||
content=response.content[0].text
|
||||
)
|
||||
|
||||
for content in response.content:
|
||||
if content.type == 'text':
|
||||
assistant_prompt_message.content += content.text
|
||||
elif content.type == 'tool_use':
|
||||
tool_call = AssistantPromptMessage.ToolCall(
|
||||
id=content.id,
|
||||
type='function',
|
||||
function=AssistantPromptMessage.ToolCall.ToolCallFunction(
|
||||
name=content.name,
|
||||
arguments=json.dumps(content.input)
|
||||
)
|
||||
)
|
||||
assistant_prompt_message.tool_calls.append(tool_call)
|
||||
|
||||
# calculate num tokens
|
||||
if response.usage:
|
||||
# transform usage
|
||||
@@ -405,90 +356,69 @@ class AnthropicLargeLanguageModel(LargeLanguageModel):
|
||||
prompt_message_dicts = []
|
||||
for message in prompt_messages:
|
||||
if not isinstance(message, SystemPromptMessage):
|
||||
if isinstance(message, UserPromptMessage):
|
||||
message = cast(UserPromptMessage, message)
|
||||
if isinstance(message.content, str):
|
||||
message_dict = {"role": "user", "content": message.content}
|
||||
prompt_message_dicts.append(message_dict)
|
||||
else:
|
||||
sub_messages = []
|
||||
for message_content in message.content:
|
||||
if message_content.type == PromptMessageContentType.TEXT:
|
||||
message_content = cast(TextPromptMessageContent, message_content)
|
||||
sub_message_dict = {
|
||||
"type": "text",
|
||||
"text": message_content.data
|
||||
}
|
||||
sub_messages.append(sub_message_dict)
|
||||
elif message_content.type == PromptMessageContentType.IMAGE:
|
||||
message_content = cast(ImagePromptMessageContent, message_content)
|
||||
if not message_content.data.startswith("data:"):
|
||||
# fetch image data from url
|
||||
try:
|
||||
image_content = requests.get(message_content.data).content
|
||||
mime_type, _ = mimetypes.guess_type(message_content.data)
|
||||
base64_data = base64.b64encode(image_content).decode('utf-8')
|
||||
except Exception as ex:
|
||||
raise ValueError(f"Failed to fetch image data from url {message_content.data}, {ex}")
|
||||
else:
|
||||
data_split = message_content.data.split(";base64,")
|
||||
mime_type = data_split[0].replace("data:", "")
|
||||
base64_data = data_split[1]
|
||||
|
||||
if mime_type not in ["image/jpeg", "image/png", "image/gif", "image/webp"]:
|
||||
raise ValueError(f"Unsupported image type {mime_type}, "
|
||||
f"only support image/jpeg, image/png, image/gif, and image/webp")
|
||||
|
||||
sub_message_dict = {
|
||||
"type": "image",
|
||||
"source": {
|
||||
"type": "base64",
|
||||
"media_type": mime_type,
|
||||
"data": base64_data
|
||||
}
|
||||
}
|
||||
sub_messages.append(sub_message_dict)
|
||||
prompt_message_dicts.append({"role": "user", "content": sub_messages})
|
||||
elif isinstance(message, AssistantPromptMessage):
|
||||
message = cast(AssistantPromptMessage, message)
|
||||
content = []
|
||||
if message.tool_calls:
|
||||
for tool_call in message.tool_calls:
|
||||
content.append({
|
||||
"type": "tool_use",
|
||||
"id": tool_call.id,
|
||||
"name": tool_call.function.name,
|
||||
"input": json.loads(tool_call.function.arguments)
|
||||
})
|
||||
if message.content:
|
||||
content.append({
|
||||
"type": "text",
|
||||
"text": message.content
|
||||
})
|
||||
|
||||
if prompt_message_dicts[-1]["role"] == "assistant":
|
||||
prompt_message_dicts[-1]["content"].extend(content)
|
||||
else:
|
||||
prompt_message_dicts.append({
|
||||
"role": "assistant",
|
||||
"content": content
|
||||
})
|
||||
elif isinstance(message, ToolPromptMessage):
|
||||
message = cast(ToolPromptMessage, message)
|
||||
message_dict = {
|
||||
"role": "user",
|
||||
"content": [{
|
||||
"type": "tool_result",
|
||||
"tool_use_id": message.tool_call_id,
|
||||
"content": message.content
|
||||
}]
|
||||
}
|
||||
prompt_message_dicts.append(message_dict)
|
||||
else:
|
||||
raise ValueError(f"Got unknown type {message}")
|
||||
prompt_message_dicts.append(self._convert_prompt_message_to_dict(message))
|
||||
|
||||
return system, prompt_message_dicts
|
||||
|
||||
def _convert_prompt_message_to_dict(self, message: PromptMessage) -> dict:
|
||||
"""
|
||||
Convert PromptMessage to dict
|
||||
"""
|
||||
if isinstance(message, UserPromptMessage):
|
||||
message = cast(UserPromptMessage, message)
|
||||
if isinstance(message.content, str):
|
||||
message_dict = {"role": "user", "content": message.content}
|
||||
else:
|
||||
sub_messages = []
|
||||
for message_content in message.content:
|
||||
if message_content.type == PromptMessageContentType.TEXT:
|
||||
message_content = cast(TextPromptMessageContent, message_content)
|
||||
sub_message_dict = {
|
||||
"type": "text",
|
||||
"text": message_content.data
|
||||
}
|
||||
sub_messages.append(sub_message_dict)
|
||||
elif message_content.type == PromptMessageContentType.IMAGE:
|
||||
message_content = cast(ImagePromptMessageContent, message_content)
|
||||
if not message_content.data.startswith("data:"):
|
||||
# fetch image data from url
|
||||
try:
|
||||
image_content = requests.get(message_content.data).content
|
||||
mime_type, _ = mimetypes.guess_type(message_content.data)
|
||||
base64_data = base64.b64encode(image_content).decode('utf-8')
|
||||
except Exception as ex:
|
||||
raise ValueError(f"Failed to fetch image data from url {message_content.data}, {ex}")
|
||||
else:
|
||||
data_split = message_content.data.split(";base64,")
|
||||
mime_type = data_split[0].replace("data:", "")
|
||||
base64_data = data_split[1]
|
||||
|
||||
if mime_type not in ["image/jpeg", "image/png", "image/gif", "image/webp"]:
|
||||
raise ValueError(f"Unsupported image type {mime_type}, "
|
||||
f"only support image/jpeg, image/png, image/gif, and image/webp")
|
||||
|
||||
sub_message_dict = {
|
||||
"type": "image",
|
||||
"source": {
|
||||
"type": "base64",
|
||||
"media_type": mime_type,
|
||||
"data": base64_data
|
||||
}
|
||||
}
|
||||
sub_messages.append(sub_message_dict)
|
||||
|
||||
message_dict = {"role": "user", "content": sub_messages}
|
||||
elif isinstance(message, AssistantPromptMessage):
|
||||
message = cast(AssistantPromptMessage, message)
|
||||
message_dict = {"role": "assistant", "content": message.content}
|
||||
elif isinstance(message, SystemPromptMessage):
|
||||
message = cast(SystemPromptMessage, message)
|
||||
message_dict = {"role": "system", "content": message.content}
|
||||
else:
|
||||
raise ValueError(f"Got unknown type {message}")
|
||||
|
||||
return message_dict
|
||||
|
||||
def _convert_one_message_to_text(self, message: PromptMessage) -> str:
|
||||
"""
|
||||
Convert a single message to a string.
|
||||
@@ -523,8 +453,6 @@ class AnthropicLargeLanguageModel(LargeLanguageModel):
|
||||
message_text += f"{ai_prompt} [IMAGE]"
|
||||
elif isinstance(message, SystemPromptMessage):
|
||||
message_text = content
|
||||
elif isinstance(message, ToolPromptMessage):
|
||||
message_text = f"{human_prompt} {message.content}"
|
||||
else:
|
||||
raise ValueError(f"Got unknown type {message}")
|
||||
|
||||
|
||||
@@ -17,11 +17,9 @@ class BedrockProvider(ModelProvider):
|
||||
"""
|
||||
try:
|
||||
model_instance = self.get_model_instance(ModelType.LLM)
|
||||
|
||||
# Use `amazon.titan-text-lite-v1` model by default for validating credentials
|
||||
model_for_validation = credentials.get('model_for_validation', 'amazon.titan-text-lite-v1')
|
||||
bedrock_validate_model_name = credentials.get('model_for_validation', 'amazon.titan-text-lite-v1')
|
||||
model_instance.validate_credentials(
|
||||
model=model_for_validation,
|
||||
model=bedrock_validate_model_name,
|
||||
credentials=credentials
|
||||
)
|
||||
except CredentialsValidateFailedError as ex:
|
||||
|
||||
@@ -74,7 +74,7 @@ provider_credential_schema:
|
||||
label:
|
||||
en_US: Available Model Name
|
||||
zh_Hans: 可用模型名称
|
||||
type: secret-input
|
||||
type: text-input
|
||||
placeholder:
|
||||
en_US: A model you have access to (e.g. amazon.titan-text-lite-v1) for validation.
|
||||
zh_Hans: 为了进行验证,请输入一个您可用的模型名称 (例如:amazon.titan-text-lite-v1)
|
||||
|
||||
+18
-35
@@ -1,50 +1,33 @@
|
||||
model: anthropic.claude-instant-v1
|
||||
label:
|
||||
en_US: Claude Instant 1
|
||||
en_US: Claude Instant V1
|
||||
model_type: llm
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 100000
|
||||
parameter_rules:
|
||||
- name: max_tokens
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
- name: topP
|
||||
use_template: top_p
|
||||
- name: topK
|
||||
label:
|
||||
zh_Hans: 取样数量
|
||||
en_US: Top K
|
||||
type: int
|
||||
help:
|
||||
zh_Hans: 仅从每个后续标记的前 K 个选项中采样。
|
||||
en_US: Only sample from the top K options for each subsequent token.
|
||||
required: false
|
||||
default: 250
|
||||
min: 0
|
||||
max: 500
|
||||
- name: max_tokens_to_sample
|
||||
use_template: max_tokens
|
||||
required: true
|
||||
type: int
|
||||
default: 4096
|
||||
min: 1
|
||||
max: 4096
|
||||
help:
|
||||
zh_Hans: 停止前生成的最大令牌数。请注意,Anthropic Claude 模型可能会在达到 max_tokens 的值之前停止生成令牌。不同的 Anthropic Claude 模型对此参数具有不同的最大值。
|
||||
en_US: The maximum number of tokens to generate before stopping. Note that Anthropic Claude models might stop generating tokens before reaching the value of max_tokens. Different Anthropic Claude models have different maximum values for this parameter.
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
required: false
|
||||
type: float
|
||||
default: 1
|
||||
min: 0.0
|
||||
max: 1.0
|
||||
help:
|
||||
zh_Hans: 生成内容的随机性。
|
||||
en_US: The amount of randomness injected into the response.
|
||||
- name: top_p
|
||||
required: false
|
||||
type: float
|
||||
default: 0.999
|
||||
min: 0.000
|
||||
max: 1.000
|
||||
help:
|
||||
zh_Hans: 在核采样中,Anthropic Claude 按概率递减顺序计算每个后续标记的所有选项的累积分布,并在达到 top_p 指定的特定概率时将其切断。您应该更改温度或top_p,但不能同时更改两者。
|
||||
en_US: In nucleus sampling, Anthropic Claude computes the cumulative distribution over all the options for each subsequent token in decreasing probability order and cuts it off once it reaches a particular probability specified by top_p. You should alter either temperature or top_p, but not both.
|
||||
- name: top_k
|
||||
required: false
|
||||
type: int
|
||||
default: 0
|
||||
min: 0
|
||||
# tip docs from aws has error, max value is 500
|
||||
max: 500
|
||||
help:
|
||||
zh_Hans: 对于每个后续标记,仅从前 K 个选项中进行采样。使用 top_k 删除长尾低概率响应。
|
||||
en_US: Only sample from the top K options for each subsequent token. Use top_k to remove long tail low probability responses.
|
||||
pricing:
|
||||
input: '0.0008'
|
||||
output: '0.0024'
|
||||
|
||||
@@ -1,50 +1,33 @@
|
||||
model: anthropic.claude-v1
|
||||
label:
|
||||
en_US: Claude 1
|
||||
en_US: Claude V1
|
||||
model_type: llm
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 100000
|
||||
parameter_rules:
|
||||
- name: max_tokens
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
- name: top_p
|
||||
use_template: top_p
|
||||
- name: top_k
|
||||
label:
|
||||
zh_Hans: 取样数量
|
||||
en_US: Top K
|
||||
type: int
|
||||
help:
|
||||
zh_Hans: 仅从每个后续标记的前 K 个选项中采样。
|
||||
en_US: Only sample from the top K options for each subsequent token.
|
||||
required: false
|
||||
default: 250
|
||||
min: 0
|
||||
max: 500
|
||||
- name: max_tokens_to_sample
|
||||
use_template: max_tokens
|
||||
required: true
|
||||
type: int
|
||||
default: 4096
|
||||
min: 1
|
||||
max: 4096
|
||||
help:
|
||||
zh_Hans: 停止前生成的最大令牌数。请注意,Anthropic Claude 模型可能会在达到 max_tokens 的值之前停止生成令牌。不同的 Anthropic Claude 模型对此参数具有不同的最大值。
|
||||
en_US: The maximum number of tokens to generate before stopping. Note that Anthropic Claude models might stop generating tokens before reaching the value of max_tokens. Different Anthropic Claude models have different maximum values for this parameter.
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
required: false
|
||||
type: float
|
||||
default: 1
|
||||
min: 0.0
|
||||
max: 1.0
|
||||
help:
|
||||
zh_Hans: 生成内容的随机性。
|
||||
en_US: The amount of randomness injected into the response.
|
||||
- name: top_p
|
||||
required: false
|
||||
type: float
|
||||
default: 0.999
|
||||
min: 0.000
|
||||
max: 1.000
|
||||
help:
|
||||
zh_Hans: 在核采样中,Anthropic Claude 按概率递减顺序计算每个后续标记的所有选项的累积分布,并在达到 top_p 指定的特定概率时将其切断。您应该更改温度或top_p,但不能同时更改两者。
|
||||
en_US: In nucleus sampling, Anthropic Claude computes the cumulative distribution over all the options for each subsequent token in decreasing probability order and cuts it off once it reaches a particular probability specified by top_p. You should alter either temperature or top_p, but not both.
|
||||
- name: top_k
|
||||
required: false
|
||||
type: int
|
||||
default: 0
|
||||
min: 0
|
||||
# tip docs from aws has error, max value is 500
|
||||
max: 500
|
||||
help:
|
||||
zh_Hans: 对于每个后续标记,仅从前 K 个选项中进行采样。使用 top_k 删除长尾低概率响应。
|
||||
en_US: Only sample from the top K options for each subsequent token. Use top_k to remove long tail low probability responses.
|
||||
pricing:
|
||||
input: '0.008'
|
||||
output: '0.024'
|
||||
|
||||
@@ -1,50 +1,33 @@
|
||||
model: anthropic.claude-v2:1
|
||||
label:
|
||||
en_US: Claude 2.1
|
||||
en_US: Claude V2.1
|
||||
model_type: llm
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 200000
|
||||
parameter_rules:
|
||||
- name: max_tokens
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
- name: top_p
|
||||
use_template: top_p
|
||||
- name: top_k
|
||||
label:
|
||||
zh_Hans: 取样数量
|
||||
en_US: Top K
|
||||
type: int
|
||||
help:
|
||||
zh_Hans: 仅从每个后续标记的前 K 个选项中采样。
|
||||
en_US: Only sample from the top K options for each subsequent token.
|
||||
required: false
|
||||
default: 250
|
||||
min: 0
|
||||
max: 500
|
||||
- name: max_tokens_to_sample
|
||||
use_template: max_tokens
|
||||
required: true
|
||||
type: int
|
||||
default: 4096
|
||||
min: 1
|
||||
max: 4096
|
||||
help:
|
||||
zh_Hans: 停止前生成的最大令牌数。请注意,Anthropic Claude 模型可能会在达到 max_tokens 的值之前停止生成令牌。不同的 Anthropic Claude 模型对此参数具有不同的最大值。
|
||||
en_US: The maximum number of tokens to generate before stopping. Note that Anthropic Claude models might stop generating tokens before reaching the value of max_tokens. Different Anthropic Claude models have different maximum values for this parameter.
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
required: false
|
||||
type: float
|
||||
default: 1
|
||||
min: 0.0
|
||||
max: 1.0
|
||||
help:
|
||||
zh_Hans: 生成内容的随机性。
|
||||
en_US: The amount of randomness injected into the response.
|
||||
- name: top_p
|
||||
required: false
|
||||
type: float
|
||||
default: 0.999
|
||||
min: 0.000
|
||||
max: 1.000
|
||||
help:
|
||||
zh_Hans: 在核采样中,Anthropic Claude 按概率递减顺序计算每个后续标记的所有选项的累积分布,并在达到 top_p 指定的特定概率时将其切断。您应该更改温度或top_p,但不能同时更改两者。
|
||||
en_US: In nucleus sampling, Anthropic Claude computes the cumulative distribution over all the options for each subsequent token in decreasing probability order and cuts it off once it reaches a particular probability specified by top_p. You should alter either temperature or top_p, but not both.
|
||||
- name: top_k
|
||||
required: false
|
||||
type: int
|
||||
default: 0
|
||||
min: 0
|
||||
# tip docs from aws has error, max value is 500
|
||||
max: 500
|
||||
help:
|
||||
zh_Hans: 对于每个后续标记,仅从前 K 个选项中进行采样。使用 top_k 删除长尾低概率响应。
|
||||
en_US: Only sample from the top K options for each subsequent token. Use top_k to remove long tail low probability responses.
|
||||
pricing:
|
||||
input: '0.008'
|
||||
output: '0.024'
|
||||
|
||||
@@ -1,50 +1,33 @@
|
||||
model: anthropic.claude-v2
|
||||
label:
|
||||
en_US: Claude 2
|
||||
en_US: Claude V2
|
||||
model_type: llm
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 100000
|
||||
parameter_rules:
|
||||
- name: max_tokens
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
- name: top_p
|
||||
use_template: top_p
|
||||
- name: top_k
|
||||
label:
|
||||
zh_Hans: 取样数量
|
||||
en_US: Top K
|
||||
type: int
|
||||
help:
|
||||
zh_Hans: 仅从每个后续标记的前 K 个选项中采样。
|
||||
en_US: Only sample from the top K options for each subsequent token.
|
||||
required: false
|
||||
default: 250
|
||||
min: 0
|
||||
max: 500
|
||||
- name: max_tokens_to_sample
|
||||
use_template: max_tokens
|
||||
required: true
|
||||
type: int
|
||||
default: 4096
|
||||
min: 1
|
||||
max: 4096
|
||||
help:
|
||||
zh_Hans: 停止前生成的最大令牌数。请注意,Anthropic Claude 模型可能会在达到 max_tokens 的值之前停止生成令牌。不同的 Anthropic Claude 模型对此参数具有不同的最大值。
|
||||
en_US: The maximum number of tokens to generate before stopping. Note that Anthropic Claude models might stop generating tokens before reaching the value of max_tokens. Different Anthropic Claude models have different maximum values for this parameter.
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
required: false
|
||||
type: float
|
||||
default: 1
|
||||
min: 0.0
|
||||
max: 1.0
|
||||
help:
|
||||
zh_Hans: 生成内容的随机性。
|
||||
en_US: The amount of randomness injected into the response.
|
||||
- name: top_p
|
||||
required: false
|
||||
type: float
|
||||
default: 0.999
|
||||
min: 0.000
|
||||
max: 1.000
|
||||
help:
|
||||
zh_Hans: 在核采样中,Anthropic Claude 按概率递减顺序计算每个后续标记的所有选项的累积分布,并在达到 top_p 指定的特定概率时将其切断。您应该更改温度或top_p,但不能同时更改两者。
|
||||
en_US: In nucleus sampling, Anthropic Claude computes the cumulative distribution over all the options for each subsequent token in decreasing probability order and cuts it off once it reaches a particular probability specified by top_p. You should alter either temperature or top_p, but not both.
|
||||
- name: top_k
|
||||
required: false
|
||||
type: int
|
||||
default: 0
|
||||
min: 0
|
||||
# tip docs from aws has error, max value is 500
|
||||
max: 500
|
||||
help:
|
||||
zh_Hans: 对于每个后续标记,仅从前 K 个选项中进行采样。使用 top_k 删除长尾低概率响应。
|
||||
en_US: Only sample from the top K options for each subsequent token. Use top_k to remove long tail low probability responses.
|
||||
pricing:
|
||||
input: '0.008'
|
||||
output: '0.024'
|
||||
|
||||
@@ -72,16 +72,16 @@ class BedrockLargeLanguageModel(LargeLanguageModel):
|
||||
:return: full response or stream response chunk generator result
|
||||
"""
|
||||
|
||||
# invoke anthropic models via anthropic official SDK
|
||||
if "anthropic" in model:
|
||||
return self._generate_anthropic(model, credentials, prompt_messages, model_parameters, stop, stream, user)
|
||||
# invoke other models via boto3 client
|
||||
# invoke claude 3 models via anthropic official SDK
|
||||
if "anthropic.claude-3" in model:
|
||||
return self._invoke_claude3(model, credentials, prompt_messages, model_parameters, stop, stream, user)
|
||||
# invoke model
|
||||
return self._generate(model, credentials, prompt_messages, model_parameters, stop, stream, user)
|
||||
|
||||
def _generate_anthropic(self, model: str, credentials: dict, prompt_messages: list[PromptMessage], model_parameters: dict,
|
||||
def _invoke_claude3(self, model: str, credentials: dict, prompt_messages: list[PromptMessage], model_parameters: dict,
|
||||
stop: Optional[list[str]] = None, stream: bool = True, user: Optional[str] = None) -> Union[LLMResult, Generator]:
|
||||
"""
|
||||
Invoke Anthropic large language model
|
||||
Invoke Claude3 large language model
|
||||
|
||||
:param model: model name
|
||||
:param credentials: model credentials
|
||||
@@ -114,7 +114,7 @@ class BedrockLargeLanguageModel(LargeLanguageModel):
|
||||
# ref: https://github.com/anthropics/anthropic-sdk-python/blob/e84645b07ca5267066700a104b4d8d6a8da1383d/src/anthropic/resources/messages.py#L465
|
||||
# extra_model_kwargs['metadata'] = message_create_params.Metadata(user_id=user)
|
||||
|
||||
system, prompt_message_dicts = self._convert_claude_prompt_messages(prompt_messages)
|
||||
system, prompt_message_dicts = self._convert_claude3_prompt_messages(prompt_messages)
|
||||
|
||||
if system:
|
||||
extra_model_kwargs['system'] = system
|
||||
@@ -128,11 +128,11 @@ class BedrockLargeLanguageModel(LargeLanguageModel):
|
||||
)
|
||||
|
||||
if stream:
|
||||
return self._handle_claude_stream_response(model, credentials, response, prompt_messages)
|
||||
return self._handle_claude3_stream_response(model, credentials, response, prompt_messages)
|
||||
|
||||
return self._handle_claude_response(model, credentials, response, prompt_messages)
|
||||
return self._handle_claude3_response(model, credentials, response, prompt_messages)
|
||||
|
||||
def _handle_claude_response(self, model: str, credentials: dict, response: Message,
|
||||
def _handle_claude3_response(self, model: str, credentials: dict, response: Message,
|
||||
prompt_messages: list[PromptMessage]) -> LLMResult:
|
||||
"""
|
||||
Handle llm chat response
|
||||
@@ -172,7 +172,7 @@ class BedrockLargeLanguageModel(LargeLanguageModel):
|
||||
|
||||
return response
|
||||
|
||||
def _handle_claude_stream_response(self, model: str, credentials: dict, response: Stream[MessageStreamEvent],
|
||||
def _handle_claude3_stream_response(self, model: str, credentials: dict, response: Stream[MessageStreamEvent],
|
||||
prompt_messages: list[PromptMessage], ) -> Generator:
|
||||
"""
|
||||
Handle llm chat stream response
|
||||
@@ -231,7 +231,7 @@ class BedrockLargeLanguageModel(LargeLanguageModel):
|
||||
except Exception as ex:
|
||||
raise InvokeError(str(ex))
|
||||
|
||||
def _calc_claude_response_usage(self, model: str, credentials: dict, prompt_tokens: int, completion_tokens: int) -> LLMUsage:
|
||||
def _calc_claude3_response_usage(self, model: str, credentials: dict, prompt_tokens: int, completion_tokens: int) -> LLMUsage:
|
||||
"""
|
||||
Calculate response usage
|
||||
|
||||
@@ -275,7 +275,7 @@ class BedrockLargeLanguageModel(LargeLanguageModel):
|
||||
|
||||
return usage
|
||||
|
||||
def _convert_claude_prompt_messages(self, prompt_messages: list[PromptMessage]) -> tuple[str, list[dict]]:
|
||||
def _convert_claude3_prompt_messages(self, prompt_messages: list[PromptMessage]) -> tuple[str, list[dict]]:
|
||||
"""
|
||||
Convert prompt messages to dict list and system
|
||||
"""
|
||||
@@ -295,11 +295,11 @@ class BedrockLargeLanguageModel(LargeLanguageModel):
|
||||
prompt_message_dicts = []
|
||||
for message in prompt_messages:
|
||||
if not isinstance(message, SystemPromptMessage):
|
||||
prompt_message_dicts.append(self._convert_claude_prompt_message_to_dict(message))
|
||||
prompt_message_dicts.append(self._convert_claude3_prompt_message_to_dict(message))
|
||||
|
||||
return system, prompt_message_dicts
|
||||
|
||||
def _convert_claude_prompt_message_to_dict(self, message: PromptMessage) -> dict:
|
||||
def _convert_claude3_prompt_message_to_dict(self, message: PromptMessage) -> dict:
|
||||
"""
|
||||
Convert PromptMessage to dict
|
||||
"""
|
||||
@@ -405,7 +405,7 @@ class BedrockLargeLanguageModel(LargeLanguageModel):
|
||||
|
||||
if "anthropic.claude-3" in model:
|
||||
try:
|
||||
self._invoke_claude(model=model,
|
||||
self._invoke_claude3(model=model,
|
||||
credentials=credentials,
|
||||
prompt_messages=[{"role": "user", "content": "ping"}],
|
||||
model_parameters={},
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
model: jina-colbert-v1-en
|
||||
model_type: rerank
|
||||
model_properties:
|
||||
context_size: 8192
|
||||
@@ -1,3 +1,4 @@
|
||||
import importlib
|
||||
import logging
|
||||
import os
|
||||
from typing import Optional
|
||||
@@ -9,7 +10,6 @@ from core.model_runtime.entities.provider_entities import ProviderConfig, Provid
|
||||
from core.model_runtime.model_providers.__base.model_provider import ModelProvider
|
||||
from core.model_runtime.schema_validators.model_credential_schema_validator import ModelCredentialSchemaValidator
|
||||
from core.model_runtime.schema_validators.provider_credential_schema_validator import ProviderCredentialSchemaValidator
|
||||
from core.utils.module_import_helper import load_single_subclass_from_source
|
||||
from core.utils.position_helper import get_position_map, sort_to_dict_by_position_map
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -229,10 +229,15 @@ class ModelProviderFactory:
|
||||
|
||||
# Dynamic loading {model_provider_name}.py file and find the subclass of ModelProvider
|
||||
py_path = os.path.join(model_provider_dir_path, model_provider_name + '.py')
|
||||
model_provider_class = load_single_subclass_from_source(
|
||||
module_name=f'core.model_runtime.model_providers.{model_provider_name}.{model_provider_name}',
|
||||
script_path=py_path,
|
||||
parent_type=ModelProvider)
|
||||
spec = importlib.util.spec_from_file_location(f'core.model_runtime.model_providers.{model_provider_name}.{model_provider_name}', py_path)
|
||||
mod = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(mod)
|
||||
|
||||
model_provider_class = None
|
||||
for name, obj in vars(mod).items():
|
||||
if isinstance(obj, type) and issubclass(obj, ModelProvider) and obj != ModelProvider:
|
||||
model_provider_class = obj
|
||||
break
|
||||
|
||||
if not model_provider_class:
|
||||
logger.warning(f"Missing Model Provider Class that extends ModelProvider in {py_path}, Skip.")
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,10 +0,0 @@
|
||||
<svg width="25" height="21" viewBox="0 0 25 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.05858 10.1738C1.76158 10.1738 4.47988 9.56715 5.88589 8.77041C7.2919 7.97367 7.2919 7.97367 10.1977 5.91152C13.8766 3.30069 16.4779 4.17486 20.7428 4.17486" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.4182 7.63145L11.3787 7.65951C8.50565 9.69845 8.42504 9.75566 6.92566 10.6053C5.98567 11.138 4.74704 11.5436 3.75151 11.8089C2.80313 12.0615 1.71203 12.2829 1.05858 12.2829V8.06483C1.05075 8.06483 1.05422 8.06445 1.06984 8.06276C1.11491 8.05788 1.26116 8.04203 1.52896 7.9926C1.84599 7.9341 2.24205 7.84582 2.6657 7.73296C3.55657 7.49564 4.3801 7.1996 4.84612 6.93552C4.88175 6.91533 4.91635 6.89573 4.95001 6.87666C6.15007 6.19693 6.15657 6.19325 8.97708 4.1916C12.5199 1.67735 15.5815 1.83587 18.5849 1.99138C19.3056 2.0287 20.0229 2.06584 20.7428 2.06584V6.28388C19.6102 6.28388 18.6583 6.24193 17.8263 6.20527C15.1245 6.08621 13.685 6.02278 11.4182 7.63145Z" fill="black"/>
|
||||
<path d="M24.8671 4.20087L17.6613 8.36117V0.0405881L24.8671 4.20087Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.6378 0L24.9139 4.20087L17.6378 8.40176V0ZM17.6847 0.0811762V8.32058L24.8202 4.20087L17.6847 0.0811762Z" fill="black"/>
|
||||
<path d="M0.917975 10.1764C1.62098 10.1764 4.33927 10.7831 5.74529 11.5799C7.1513 12.3766 7.1513 12.3766 10.0571 14.4388C13.736 17.0496 16.3373 16.1754 20.6022 16.1754" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.929234 12.2875C0.913615 12.2858 0.910145 12.2854 0.917975 12.2854V8.06741C1.57142 8.06741 2.66253 8.28878 3.61091 8.54142C4.60644 8.80663 5.84507 9.21231 6.78506 9.74497C8.28444 10.5946 8.36505 10.6518 11.2381 12.6908L11.2776 12.7188C13.5444 14.3275 14.9839 14.2641 17.6857 14.145C18.5177 14.1083 19.4696 14.0664 20.6022 14.0664V18.2844C19.8823 18.2844 19.165 18.3216 18.4443 18.3589C15.4409 18.5144 12.3793 18.6729 8.83648 16.1587C6.01597 14.157 6.00947 14.1533 4.80941 13.4736C4.77575 13.4545 4.74115 13.4349 4.70551 13.4148C4.2395 13.1507 3.41597 12.8546 2.5251 12.6173C2.10145 12.5045 1.70538 12.4162 1.38836 12.3577C1.12056 12.3083 0.974309 12.2924 0.929234 12.2875Z" fill="black"/>
|
||||
<path d="M24.7265 16.1494L17.5207 11.9892V20.3097L24.7265 16.1494Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.4972 11.9486L24.7733 16.1494L17.4972 20.3503V11.9486ZM17.5441 12.0297V20.2691L24.6796 16.1494L17.5441 12.0297Z" fill="black"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.4 KiB |
@@ -1,46 +0,0 @@
|
||||
from collections.abc import Generator
|
||||
from typing import Optional, Union
|
||||
|
||||
from core.model_runtime.entities.llm_entities import LLMResult
|
||||
from core.model_runtime.entities.message_entities import PromptMessage, PromptMessageTool
|
||||
from core.model_runtime.entities.model_entities import AIModelEntity
|
||||
from core.model_runtime.model_providers.openai_api_compatible.llm.llm import OAIAPICompatLargeLanguageModel
|
||||
|
||||
|
||||
class OpenRouterLargeLanguageModel(OAIAPICompatLargeLanguageModel):
|
||||
|
||||
def _update_endpoint_url(self, credentials: dict):
|
||||
credentials['endpoint_url'] = "https://openrouter.ai/api/v1"
|
||||
return credentials
|
||||
|
||||
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]:
|
||||
cred_with_endpoint = self._update_endpoint_url(credentials=credentials)
|
||||
|
||||
return super()._invoke(model, cred_with_endpoint, prompt_messages, model_parameters, tools, stop, stream, user)
|
||||
|
||||
def validate_credentials(self, model: str, credentials: dict) -> None:
|
||||
cred_with_endpoint = self._update_endpoint_url(credentials=credentials)
|
||||
|
||||
return super().validate_credentials(model, cred_with_endpoint)
|
||||
|
||||
def _generate(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]:
|
||||
cred_with_endpoint = self._update_endpoint_url(credentials=credentials)
|
||||
|
||||
return super()._generate(model, cred_with_endpoint, prompt_messages, model_parameters, tools, stop, stream, user)
|
||||
|
||||
def get_customizable_model_schema(self, model: str, credentials: dict) -> AIModelEntity:
|
||||
cred_with_endpoint = self._update_endpoint_url(credentials=credentials)
|
||||
|
||||
return super().get_customizable_model_schema(model, cred_with_endpoint)
|
||||
|
||||
def get_num_tokens(self, model: str, credentials: dict, prompt_messages: list[PromptMessage],
|
||||
tools: Optional[list[PromptMessageTool]] = None) -> int:
|
||||
cred_with_endpoint = self._update_endpoint_url(credentials=credentials)
|
||||
|
||||
return super().get_num_tokens(model, cred_with_endpoint, prompt_messages, tools)
|
||||
@@ -1,11 +0,0 @@
|
||||
import logging
|
||||
|
||||
from core.model_runtime.model_providers.__base.model_provider import ModelProvider
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OpenRouterProvider(ModelProvider):
|
||||
|
||||
def validate_provider_credentials(self, credentials: dict) -> None:
|
||||
pass
|
||||
@@ -1,75 +0,0 @@
|
||||
provider: openrouter
|
||||
label:
|
||||
en_US: openrouter.ai
|
||||
icon_small:
|
||||
en_US: openrouter_square.svg
|
||||
icon_large:
|
||||
en_US: openrouter.svg
|
||||
background: "#F1EFED"
|
||||
help:
|
||||
title:
|
||||
en_US: Get your API key from openrouter.ai
|
||||
zh_Hans: 从 openrouter.ai 获取 API Key
|
||||
url:
|
||||
en_US: https://openrouter.ai/keys
|
||||
supported_model_types:
|
||||
- llm
|
||||
configurate_methods:
|
||||
- customizable-model
|
||||
model_credential_schema:
|
||||
model:
|
||||
label:
|
||||
en_US: Model Name
|
||||
zh_Hans: 模型名称
|
||||
placeholder:
|
||||
en_US: Enter full model name
|
||||
zh_Hans: 输入模型全称
|
||||
credential_form_schemas:
|
||||
- variable: api_key
|
||||
required: true
|
||||
label:
|
||||
en_US: API Key
|
||||
type: secret-input
|
||||
placeholder:
|
||||
zh_Hans: 在此输入您的 API Key
|
||||
en_US: Enter your API Key
|
||||
- variable: mode
|
||||
show_on:
|
||||
- variable: __model_type
|
||||
value: llm
|
||||
label:
|
||||
en_US: Completion mode
|
||||
type: select
|
||||
required: false
|
||||
default: chat
|
||||
placeholder:
|
||||
zh_Hans: 选择对话类型
|
||||
en_US: Select completion mode
|
||||
options:
|
||||
- value: completion
|
||||
label:
|
||||
en_US: Completion
|
||||
zh_Hans: 补全
|
||||
- value: chat
|
||||
label:
|
||||
en_US: Chat
|
||||
zh_Hans: 对话
|
||||
- variable: context_size
|
||||
label:
|
||||
zh_Hans: 模型上下文长度
|
||||
en_US: Model context size
|
||||
required: true
|
||||
type: text-input
|
||||
default: "4096"
|
||||
placeholder:
|
||||
zh_Hans: 在此输入您的模型上下文长度
|
||||
en_US: Enter your Model context size
|
||||
- variable: max_tokens_to_sample
|
||||
label:
|
||||
zh_Hans: 最大 token 上限
|
||||
en_US: Upper bound for max tokens
|
||||
show_on:
|
||||
- variable: __model_type
|
||||
value: llm
|
||||
default: "4096"
|
||||
type: text-input
|
||||
@@ -148,8 +148,7 @@ class SparkLLMClient:
|
||||
data = {
|
||||
"header": {
|
||||
"app_id": self.app_id,
|
||||
# resolve this error message => $.header.uid' length must be less or equal than 32
|
||||
"uid": user_id[:32] if user_id else None
|
||||
"uid": user_id
|
||||
},
|
||||
"parameter": {
|
||||
"chat": {
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
model: ernie-3.5-8k
|
||||
label:
|
||||
en_US: Ernie-3.5-8K
|
||||
model_type: llm
|
||||
features:
|
||||
- agent-thought
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 4096
|
||||
parameter_rules:
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
min: 0.1
|
||||
max: 1.0
|
||||
default: 0.8
|
||||
- name: top_p
|
||||
use_template: top_p
|
||||
- name: max_tokens
|
||||
use_template: max_tokens
|
||||
default: 1024
|
||||
min: 2
|
||||
max: 2048
|
||||
- name: presence_penalty
|
||||
use_template: presence_penalty
|
||||
- name: frequency_penalty
|
||||
use_template: frequency_penalty
|
||||
- name: response_format
|
||||
use_template: response_format
|
||||
- name: disable_search
|
||||
label:
|
||||
zh_Hans: 禁用搜索
|
||||
en_US: Disable Search
|
||||
type: boolean
|
||||
help:
|
||||
zh_Hans: 禁用模型自行进行外部搜索。
|
||||
en_US: Disable the model to perform external search.
|
||||
required: false
|
||||
@@ -1,37 +0,0 @@
|
||||
model: ernie-3.5-8k-0205
|
||||
label:
|
||||
en_US: Ernie-3.5-8K-0205
|
||||
model_type: llm
|
||||
features:
|
||||
- agent-thought
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 8192
|
||||
parameter_rules:
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
min: 0.1
|
||||
max: 1.0
|
||||
default: 0.8
|
||||
- name: top_p
|
||||
use_template: top_p
|
||||
- name: max_tokens
|
||||
use_template: max_tokens
|
||||
default: 1024
|
||||
min: 2
|
||||
max: 2048
|
||||
- name: presence_penalty
|
||||
use_template: presence_penalty
|
||||
- name: frequency_penalty
|
||||
use_template: frequency_penalty
|
||||
- name: response_format
|
||||
use_template: response_format
|
||||
- name: disable_search
|
||||
label:
|
||||
zh_Hans: 禁用搜索
|
||||
en_US: Disable Search
|
||||
type: boolean
|
||||
help:
|
||||
zh_Hans: 禁用模型自行进行外部搜索。
|
||||
en_US: Disable the model to perform external search.
|
||||
required: false
|
||||
@@ -1,37 +0,0 @@
|
||||
model: ernie-3.5-8k-1222
|
||||
label:
|
||||
en_US: Ernie-3.5-8K-1222
|
||||
model_type: llm
|
||||
features:
|
||||
- agent-thought
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 8192
|
||||
parameter_rules:
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
min: 0.1
|
||||
max: 1.0
|
||||
default: 0.8
|
||||
- name: top_p
|
||||
use_template: top_p
|
||||
- name: max_tokens
|
||||
use_template: max_tokens
|
||||
default: 1024
|
||||
min: 2
|
||||
max: 2048
|
||||
- name: presence_penalty
|
||||
use_template: presence_penalty
|
||||
- name: frequency_penalty
|
||||
use_template: frequency_penalty
|
||||
- name: response_format
|
||||
use_template: response_format
|
||||
- name: disable_search
|
||||
label:
|
||||
zh_Hans: 禁用搜索
|
||||
en_US: Disable Search
|
||||
type: boolean
|
||||
help:
|
||||
zh_Hans: 禁用模型自行进行外部搜索。
|
||||
en_US: Disable the model to perform external search.
|
||||
required: false
|
||||
@@ -1,37 +0,0 @@
|
||||
model: ernie-3.5-8k
|
||||
label:
|
||||
en_US: Ernie-3.5-8K
|
||||
model_type: llm
|
||||
features:
|
||||
- agent-thought
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 8192
|
||||
parameter_rules:
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
min: 0.1
|
||||
max: 1.0
|
||||
default: 0.8
|
||||
- name: top_p
|
||||
use_template: top_p
|
||||
- name: max_tokens
|
||||
use_template: max_tokens
|
||||
default: 1024
|
||||
min: 2
|
||||
max: 2048
|
||||
- name: presence_penalty
|
||||
use_template: presence_penalty
|
||||
- name: frequency_penalty
|
||||
use_template: frequency_penalty
|
||||
- name: response_format
|
||||
use_template: response_format
|
||||
- name: disable_search
|
||||
label:
|
||||
zh_Hans: 禁用搜索
|
||||
en_US: Disable Search
|
||||
type: boolean
|
||||
help:
|
||||
zh_Hans: 禁用模型自行进行外部搜索。
|
||||
en_US: Disable the model to perform external search.
|
||||
required: false
|
||||
@@ -1,37 +0,0 @@
|
||||
model: ernie-4.0-8k
|
||||
label:
|
||||
en_US: Ernie-4.0-8K
|
||||
model_type: llm
|
||||
features:
|
||||
- agent-thought
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 8192
|
||||
parameter_rules:
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
min: 0.1
|
||||
max: 1.0
|
||||
default: 0.8
|
||||
- name: top_p
|
||||
use_template: top_p
|
||||
- name: max_tokens
|
||||
use_template: max_tokens
|
||||
default: 1024
|
||||
min: 2
|
||||
max: 2048
|
||||
- name: presence_penalty
|
||||
use_template: presence_penalty
|
||||
- name: frequency_penalty
|
||||
use_template: frequency_penalty
|
||||
- name: response_format
|
||||
use_template: response_format
|
||||
- name: disable_search
|
||||
label:
|
||||
zh_Hans: 禁用搜索
|
||||
en_US: Disable Search
|
||||
type: boolean
|
||||
help:
|
||||
zh_Hans: 禁用模型自行进行外部搜索。
|
||||
en_US: Disable the model to perform external search.
|
||||
required: false
|
||||
@@ -36,4 +36,3 @@ parameter_rules:
|
||||
zh_Hans: 禁用模型自行进行外部搜索。
|
||||
en_US: Disable the model to perform external search.
|
||||
required: false
|
||||
deprecated: true
|
||||
|
||||
@@ -36,4 +36,3 @@ parameter_rules:
|
||||
zh_Hans: 禁用模型自行进行外部搜索。
|
||||
en_US: Disable the model to perform external search.
|
||||
required: false
|
||||
deprecated: true
|
||||
|
||||
@@ -27,4 +27,3 @@ parameter_rules:
|
||||
use_template: frequency_penalty
|
||||
- name: response_format
|
||||
use_template: response_format
|
||||
deprecated: true
|
||||
|
||||
@@ -36,4 +36,3 @@ parameter_rules:
|
||||
required: false
|
||||
- name: response_format
|
||||
use_template: response_format
|
||||
deprecated: true
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
model: ernie-lite-8k-0308
|
||||
label:
|
||||
en_US: ERNIE-Lite-8K-0308
|
||||
model_type: llm
|
||||
features:
|
||||
- agent-thought
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 8192
|
||||
parameter_rules:
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
min: 0.1
|
||||
max: 1.0
|
||||
default: 0.95
|
||||
- name: top_p
|
||||
use_template: top_p
|
||||
min: 0
|
||||
max: 1.0
|
||||
default: 0.7
|
||||
- name: max_tokens
|
||||
use_template: max_tokens
|
||||
default: 1024
|
||||
min: 2
|
||||
max: 1024
|
||||
- name: presence_penalty
|
||||
use_template: presence_penalty
|
||||
default: 1.0
|
||||
min: 1.0
|
||||
max: 2.0
|
||||
@@ -1,30 +0,0 @@
|
||||
model: ernie-lite-8k-0922
|
||||
label:
|
||||
en_US: ERNIE-Lite-8K-0922
|
||||
model_type: llm
|
||||
features:
|
||||
- agent-thought
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 8192
|
||||
parameter_rules:
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
min: 0.1
|
||||
max: 1.0
|
||||
default: 0.95
|
||||
- name: top_p
|
||||
use_template: top_p
|
||||
min: 0
|
||||
max: 1.0
|
||||
default: 0.7
|
||||
- name: max_tokens
|
||||
use_template: max_tokens
|
||||
default: 1024
|
||||
min: 2
|
||||
max: 1024
|
||||
- name: presence_penalty
|
||||
use_template: presence_penalty
|
||||
default: 1.0
|
||||
min: 1.0
|
||||
max: 2.0
|
||||
@@ -1,30 +0,0 @@
|
||||
model: ernie-speed-128k
|
||||
label:
|
||||
en_US: ERNIE-Speed-128K
|
||||
model_type: llm
|
||||
features:
|
||||
- agent-thought
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 128000
|
||||
parameter_rules:
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
min: 0.1
|
||||
max: 1.0
|
||||
default: 0.95
|
||||
- name: top_p
|
||||
use_template: top_p
|
||||
min: 0
|
||||
max: 1.0
|
||||
default: 0.7
|
||||
- name: max_tokens
|
||||
use_template: max_tokens
|
||||
default: 1024
|
||||
min: 2
|
||||
max: 1024
|
||||
- name: presence_penalty
|
||||
use_template: presence_penalty
|
||||
default: 1.0
|
||||
min: 1.0
|
||||
max: 2.0
|
||||
@@ -1,30 +0,0 @@
|
||||
model: ernie-speed-8k
|
||||
label:
|
||||
en_US: ERNIE-Speed-8K
|
||||
model_type: llm
|
||||
features:
|
||||
- agent-thought
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 8192
|
||||
parameter_rules:
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
min: 0.1
|
||||
max: 1.0
|
||||
default: 0.95
|
||||
- name: top_p
|
||||
use_template: top_p
|
||||
min: 0
|
||||
max: 1.0
|
||||
default: 0.7
|
||||
- name: max_tokens
|
||||
use_template: max_tokens
|
||||
default: 1024
|
||||
min: 2
|
||||
max: 1024
|
||||
- name: presence_penalty
|
||||
use_template: presence_penalty
|
||||
default: 1.0
|
||||
min: 1.0
|
||||
max: 2.0
|
||||
@@ -1,25 +0,0 @@
|
||||
model: ernie-speed-appbuilder
|
||||
label:
|
||||
en_US: ERNIE-Speed-AppBuilder
|
||||
model_type: llm
|
||||
features:
|
||||
- agent-thought
|
||||
model_properties:
|
||||
mode: chat
|
||||
context_size: 8192
|
||||
parameter_rules:
|
||||
- name: temperature
|
||||
use_template: temperature
|
||||
min: 0.1
|
||||
max: 1.0
|
||||
default: 0.95
|
||||
- name: top_p
|
||||
use_template: top_p
|
||||
min: 0
|
||||
max: 1.0
|
||||
default: 0.7
|
||||
- name: presence_penalty
|
||||
use_template: presence_penalty
|
||||
default: 1.0
|
||||
min: 1.0
|
||||
max: 2.0
|
||||
@@ -121,29 +121,15 @@ class ErnieMessage:
|
||||
|
||||
class ErnieBotModel:
|
||||
api_bases = {
|
||||
'ernie-bot': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-4k-0205',
|
||||
'ernie-bot': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions',
|
||||
'ernie-bot-4': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro',
|
||||
'ernie-bot-8k': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions',
|
||||
'ernie-bot-8k': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie_bot_8k',
|
||||
'ernie-bot-turbo': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant',
|
||||
'ernie-3.5-8k': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions',
|
||||
'ernie-3.5-8k-0205': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-8k-0205',
|
||||
'ernie-3.5-8k-1222': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-8k-1222',
|
||||
'ernie-3.5-4k-0205': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-4k-0205',
|
||||
'ernie-4.0-8k': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro',
|
||||
'ernie-speed-8k': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie_speed',
|
||||
'ernie-speed-128k': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-speed-128k',
|
||||
'ernie-speed-appbuilder': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ai_apaas',
|
||||
'ernie-lite-8k-0922': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant',
|
||||
'ernie-lite-8k-0308': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-lite-8k',
|
||||
}
|
||||
|
||||
function_calling_supports = [
|
||||
'ernie-bot',
|
||||
'ernie-bot-8k',
|
||||
'ernie-3.5-8k',
|
||||
'ernie-3.5-8k-0205',
|
||||
'ernie-3.5-8k-1222',
|
||||
'ernie-3.5-4k-0205'
|
||||
]
|
||||
|
||||
api_key: str = ''
|
||||
@@ -299,12 +285,6 @@ class ErnieBotModel:
|
||||
**parameters
|
||||
}
|
||||
|
||||
if 'max_tokens' in parameters and type(parameters['max_tokens']) == int:
|
||||
body['max_output_tokens'] = parameters['max_tokens']
|
||||
|
||||
if 'presence_penalty' in parameters and type(parameters['presence_penalty']) == float:
|
||||
body['penalty_score'] = parameters['presence_penalty']
|
||||
|
||||
if system_message:
|
||||
body['system'] = system_message
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user