Compare commits
700 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
531b4473e8 | ||
|
|
aefd0d2775 | ||
|
|
960468edf0 | ||
|
|
07ad1f58b5 | ||
|
|
095428be50 | ||
|
|
87fc8911fa | ||
|
|
58272e1ce8 | ||
|
|
700bbcb63f | ||
|
|
dde1d68876 | ||
|
|
71553a6153 | ||
|
|
d4f8de3e21 | ||
|
|
6cf5dea10d | ||
|
|
05379dfee6 | ||
|
|
5a6d49ff64 | ||
|
|
64ab940a26 | ||
|
|
55982ea36d | ||
|
|
21efcf2479 | ||
|
|
0dc7bfcadb | ||
|
|
22d99091e1 | ||
|
|
7558d3ffdc | ||
|
|
85ae41c44c | ||
|
|
91193850dd | ||
|
|
7cc04e3364 | ||
|
|
3da28090c6 | ||
|
|
1595ef2c0a | ||
|
|
83e3d81de7 | ||
|
|
18437ddda4 | ||
|
|
fd503171a1 | ||
|
|
7022139780 | ||
|
|
1e508e45af | ||
|
|
03d9ec2cad | ||
|
|
86fb48bab7 | ||
|
|
a4bc1e4a55 | ||
|
|
8681e15da5 | ||
|
|
ebc82f8b1b | ||
|
|
3bcd7bd7e1 | ||
|
|
b64d8669b1 | ||
|
|
0489044098 | ||
|
|
17e2062b72 | ||
|
|
4e4f5a698d | ||
|
|
b879d04bcd | ||
|
|
95f918f4c7 | ||
|
|
f0e1ad6088 | ||
|
|
61773af48d | ||
|
|
54cd04c3bf | ||
|
|
cd9f4ae11b | ||
|
|
3f9c748b41 | ||
|
|
d483005531 | ||
|
|
1d2db6a896 | ||
|
|
9a7a263055 | ||
|
|
6beb0b52c7 | ||
|
|
0ea167a204 | ||
|
|
6e6afa2a7c | ||
|
|
7a2a5d86bb | ||
|
|
a1a36c3494 | ||
|
|
4f350081dd | ||
|
|
b3ea0c4e1a | ||
|
|
e72a6acd03 | ||
|
|
9bb8ab89fe | ||
|
|
e78da66d1a | ||
|
|
9ee21fd5e5 | ||
|
|
a22c04c9b2 | ||
|
|
3bb5bfaca7 | ||
|
|
c4bf5ee7e5 | ||
|
|
5e1e688f84 | ||
|
|
80d9bf68f3 | ||
|
|
65f2e3e363 | ||
|
|
68d27ff2bc | ||
|
|
034da30811 | ||
|
|
3db0cdcd19 | ||
|
|
42181a6f1d | ||
|
|
ec8cbf2550 | ||
|
|
9a1bd079da | ||
|
|
4213c4379c | ||
|
|
05cda17e2e | ||
|
|
cda6e54f0b | ||
|
|
51d8ba6408 | ||
|
|
b571c7d22d | ||
|
|
a0c91f565e | ||
|
|
280c750165 | ||
|
|
fec9337fda | ||
|
|
b84f252f2f | ||
|
|
5c998ccce2 | ||
|
|
0e3cfd2cfb | ||
|
|
4040831a23 | ||
|
|
a3a2308659 | ||
|
|
6d43c71d13 | ||
|
|
8315b6f37f | ||
|
|
7bc708e6ae | ||
|
|
e6f2c5c2fe | ||
|
|
5cab781362 | ||
|
|
02d7994bae | ||
|
|
b740957157 | ||
|
|
2480ec1272 | ||
|
|
35c98a0d14 | ||
|
|
0964a5ad5b | ||
|
|
a95131efe9 | ||
|
|
7783cdf3c4 | ||
|
|
7a65f33cb6 | ||
|
|
6efd01db3f | ||
|
|
1e2322b573 | ||
|
|
2cb2241a66 | ||
|
|
64efdd7881 | ||
|
|
be28e32803 | ||
|
|
468422baee | ||
|
|
7b1c6c8c64 | ||
|
|
7ff0ea0bfe | ||
|
|
6bed4356f0 | ||
|
|
73b65f7305 | ||
|
|
0ea52eced9 | ||
|
|
498e9ba9f6 | ||
|
|
125695665b | ||
|
|
0e08b3ae85 | ||
|
|
7cb8f99e7e | ||
|
|
d15cb527d0 | ||
|
|
9cb36174fd | ||
|
|
6265f94ef2 | ||
|
|
09d90b654c | ||
|
|
64e2bca2e6 | ||
|
|
328ece6d73 | ||
|
|
fabb8c2044 | ||
|
|
6ca75df880 | ||
|
|
3d4dfaced1 | ||
|
|
d532bf3bb6 | ||
|
|
e1fd288875 | ||
|
|
91eae9cfa8 | ||
|
|
b0059942d3 | ||
|
|
a716982878 | ||
|
|
3d4e48f9f5 | ||
|
|
1f212d3156 | ||
|
|
7d91ef6ba1 | ||
|
|
2a450b00de | ||
|
|
3a97068248 | ||
|
|
1d9d95899a | ||
|
|
7ae8e52b57 | ||
|
|
f5c195a1d0 | ||
|
|
78a6b662d3 | ||
|
|
5f814eb76c | ||
|
|
d9e5ebb464 | ||
|
|
bce0e9183c | ||
|
|
c40a7bcf22 | ||
|
|
97a7d447ab | ||
|
|
f803b9538b | ||
|
|
1ac34c1702 | ||
|
|
e07b480da1 | ||
|
|
9036af57e3 | ||
|
|
93288f9b5c | ||
|
|
f40dd8b013 | ||
|
|
c6b83d0695 | ||
|
|
592c850198 | ||
|
|
4a3930ac7b | ||
|
|
c05ba0af3e | ||
|
|
630ee51df6 | ||
|
|
d0e75e26c3 | ||
|
|
62c36c3072 | ||
|
|
baef309064 | ||
|
|
d717cbad9c | ||
|
|
5ef0624605 | ||
|
|
af2930a371 | ||
|
|
98f0f9fe84 | ||
|
|
28a23271e9 | ||
|
|
f1ba0bdf10 | ||
|
|
0d5513f374 | ||
|
|
4812cc308c | ||
|
|
584f7faded | ||
|
|
08dcef2d8b | ||
|
|
68218733a2 | ||
|
|
eb64cbf3d4 | ||
|
|
f0e8a55522 | ||
|
|
5ec5a0bde4 | ||
|
|
1cc56dd553 | ||
|
|
64e949a88b | ||
|
|
a2390a7c97 | ||
|
|
559661bb6c | ||
|
|
79326de263 | ||
|
|
3815891b28 | ||
|
|
42d474382a | ||
|
|
fe691f2d44 | ||
|
|
3ee41a8ab1 | ||
|
|
7ca41dff8a | ||
|
|
ba2e86993e | ||
|
|
13878046a2 | ||
|
|
49ff8bf54f | ||
|
|
e9cc5a3993 | ||
|
|
b213964b63 | ||
|
|
bfbed44270 | ||
|
|
9b07d88392 | ||
|
|
3f8ed109f9 | ||
|
|
3f969627a4 | ||
|
|
d92970819a | ||
|
|
23e756fa9b | ||
|
|
5f58126fbf | ||
|
|
dcfd0ffb8f | ||
|
|
17221d056c | ||
|
|
4a9dcfada4 | ||
|
|
bb6c2bb020 | ||
|
|
a8760a34de | ||
|
|
1e432a5782 | ||
|
|
cb861ef2bb | ||
|
|
7cee8fd87a | ||
|
|
8ce0e5d348 | ||
|
|
90bce7c89f | ||
|
|
b840d0bcce | ||
|
|
bfa6d28289 | ||
|
|
f6e6ca9747 | ||
|
|
75f8d39648 | ||
|
|
9a939eba5a | ||
|
|
4e93efe821 | ||
|
|
8bdbee80a0 | ||
|
|
6bdf5dcc03 | ||
|
|
0bf0a9d78a | ||
|
|
38e9fea601 | ||
|
|
d2366b3b46 | ||
|
|
3aff93083a | ||
|
|
eb998199db | ||
|
|
1dd794af1b | ||
|
|
08c9923e7e | ||
|
|
06b109ca87 | ||
|
|
9b039335c7 | ||
|
|
041378e5fd | ||
|
|
6dc5ae10e3 | ||
|
|
5807f4c283 | ||
|
|
8ef4445908 | ||
|
|
8a0609e970 | ||
|
|
9f33b5009b | ||
|
|
50e66db8a1 | ||
|
|
c3e83b569a | ||
|
|
85d1c5ea7e | ||
|
|
ec1d126a02 | ||
|
|
e857695e70 | ||
|
|
fa9b2051fe | ||
|
|
d450efcffe | ||
|
|
2a6c84c200 | ||
|
|
138a952ace | ||
|
|
eb6528ecd2 | ||
|
|
2c30bbfa09 | ||
|
|
c5a78c2135 | ||
|
|
f03362ee41 | ||
|
|
fad3167d97 | ||
|
|
ad949681dd | ||
|
|
27999d76b0 | ||
|
|
83278352d6 | ||
|
|
fcc56f5fef | ||
|
|
4ebe2ecc32 | ||
|
|
e684cba527 | ||
|
|
888dc19ee0 | ||
|
|
731aea702f | ||
|
|
09e22bc76a | ||
|
|
74406d88a0 | ||
|
|
e5f9d97560 | ||
|
|
59e768aaea | ||
|
|
6a7cb24a5b | ||
|
|
1db40d534c | ||
|
|
11d6e30f7e | ||
|
|
9d5214aaae | ||
|
|
010b906271 | ||
|
|
16bf944edf | ||
|
|
5bae5a099a | ||
|
|
f771ea9521 | ||
|
|
994efbf37c | ||
|
|
938cd86c88 | ||
|
|
1339cbadbc | ||
|
|
bd0ad570ad | ||
|
|
234e649a7e | ||
|
|
c431dbc842 | ||
|
|
76283060d9 | ||
|
|
75ba506db4 | ||
|
|
e086ca60df | ||
|
|
04acaa9b12 | ||
|
|
7a824bf18c | ||
|
|
769de2e526 | ||
|
|
c9950609c9 | ||
|
|
ccee6cfea5 | ||
|
|
f626c618be | ||
|
|
3b601a9e3d | ||
|
|
3d5f63d595 | ||
|
|
6933f2f495 | ||
|
|
79c7e8626a | ||
|
|
4a017d311c | ||
|
|
0c8ad5fe8d | ||
|
|
68ce0db011 | ||
|
|
c36de1a1e9 | ||
|
|
44ef759abd | ||
|
|
0c3d9844be | ||
|
|
854c62a4ca | ||
|
|
5ed4fd5299 | ||
|
|
af5ec43571 | ||
|
|
24d685879e | ||
|
|
e801a2ec46 | ||
|
|
d7b56d1590 | ||
|
|
b925f8890b | ||
|
|
5d80ee994a | ||
|
|
da8f955ca2 | ||
|
|
2e04582c5e | ||
|
|
e69994f727 | ||
|
|
d8dc26127d | ||
|
|
f73bd2dfda | ||
|
|
9f08b60348 | ||
|
|
75c2f36b30 | ||
|
|
39c02a6064 | ||
|
|
52c119befd | ||
|
|
23903ded3f | ||
|
|
4799fbac72 | ||
|
|
16a7d55271 | ||
|
|
be0bafcc50 | ||
|
|
defc51a074 | ||
|
|
09709c210d | ||
|
|
8ebb2f54eb | ||
|
|
b831aab115 | ||
|
|
8e322162cc | ||
|
|
6a8a6509b8 | ||
|
|
707dff09f8 | ||
|
|
17c8fca40f | ||
|
|
415f9757e9 | ||
|
|
27394f0699 | ||
|
|
8a9ca40bb6 | ||
|
|
f340ee1088 | ||
|
|
080eb5765e | ||
|
|
36c8ff184a | ||
|
|
0486f67b50 | ||
|
|
aa7e8d545c | ||
|
|
59f6a899a6 | ||
|
|
0fc98d42aa | ||
|
|
edad2644aa | ||
|
|
8a56a0393a | ||
|
|
f4cbf9a40a | ||
|
|
fb5b92f499 | ||
|
|
c286258f2b | ||
|
|
4416651589 | ||
|
|
48a33e8977 | ||
|
|
bd5ca06d8f | ||
|
|
e0985ecec3 | ||
|
|
e56b74d4af | ||
|
|
c417098c2c | ||
|
|
93527215a7 | ||
|
|
0cf3945693 | ||
|
|
ced2a9b2e2 | ||
|
|
987b231c4d | ||
|
|
7a541c1da1 | ||
|
|
74e323158d | ||
|
|
563a7409f6 | ||
|
|
b13b93e04e | ||
|
|
44568c8d65 | ||
|
|
fb277dff80 | ||
|
|
efae890650 | ||
|
|
a146f6059e | ||
|
|
3c67096cd8 | ||
|
|
a993a60f95 | ||
|
|
d3fdc77600 | ||
|
|
b62c56e36f | ||
|
|
7d72911239 | ||
|
|
9e24d7cc67 | ||
|
|
9baa24b496 | ||
|
|
da826525f7 | ||
|
|
62dfab41fd | ||
|
|
04fc811c2c | ||
|
|
8638ecbe29 | ||
|
|
6f1f93fbaf | ||
|
|
dc38d83f89 | ||
|
|
fd780780c5 | ||
|
|
6fd918f33b | ||
|
|
8fcfa8974b | ||
|
|
7e23c32c6c | ||
|
|
7fdfceeea5 | ||
|
|
bf0e62634f | ||
|
|
469ef9aab2 | ||
|
|
f7df26030d | ||
|
|
f61cbe9780 | ||
|
|
56b62cff2a | ||
|
|
0aec21cf03 | ||
|
|
ff4f6be5fc | ||
|
|
964a5022c8 | ||
|
|
849b18f677 | ||
|
|
b8c6a6a626 | ||
|
|
57fc9a9b7e | ||
|
|
068c126a23 | ||
|
|
0ed1662c7b | ||
|
|
a09377814f | ||
|
|
3cc952bb2a | ||
|
|
63c968742b | ||
|
|
a4d6f2a6fd | ||
|
|
d6de64853d | ||
|
|
344128e49d | ||
|
|
56fc9dd517 | ||
|
|
c7c1911eb1 | ||
|
|
dec8b5bef7 | ||
|
|
db7271b519 | ||
|
|
fcbee1f64f | ||
|
|
2d9443a0a1 | ||
|
|
6e3dd00d6f | ||
|
|
7a0656cd81 | ||
|
|
3b89d9e974 | ||
|
|
cd174308cf | ||
|
|
aacef47626 | ||
|
|
fcef01a41f | ||
|
|
7d19b694fa | ||
|
|
966a31b156 | ||
|
|
7538393742 | ||
|
|
3658188be2 | ||
|
|
fcd9fb9079 | ||
|
|
d1168e16d6 | ||
|
|
25a6f00dd2 | ||
|
|
13c474f084 | ||
|
|
8d78270007 | ||
|
|
a94b59c156 | ||
|
|
ae6d61ee6d | ||
|
|
74a7c94619 | ||
|
|
bdd34ac786 | ||
|
|
0e754b4732 | ||
|
|
48a9fcfabf | ||
|
|
7ae2b9ac3b | ||
|
|
a6bfe3c69b | ||
|
|
6b146f4750 | ||
|
|
1387e716d1 | ||
|
|
fadc350047 | ||
|
|
8af4994a7d | ||
|
|
b505b61bfe | ||
|
|
5d086c9383 | ||
|
|
dd0e367dc8 | ||
|
|
7110eea912 | ||
|
|
154e67ef98 | ||
|
|
4a04423373 | ||
|
|
470ea50ebb | ||
|
|
2a30f3f221 | ||
|
|
315f58fdba | ||
|
|
f027682175 | ||
|
|
2618dffcd6 | ||
|
|
ee42d5870b | ||
|
|
27500b1e08 | ||
|
|
4d71a98724 | ||
|
|
b8ba0ab391 | ||
|
|
b589612913 | ||
|
|
ec4b440469 | ||
|
|
adbecb3b25 | ||
|
|
277aacc34d | ||
|
|
dba98f7968 | ||
|
|
a2b0f3f3c2 | ||
|
|
b5e527afdb | ||
|
|
e84b05a39b | ||
|
|
631c563e71 | ||
|
|
47b304e46f | ||
|
|
27ccfc5e88 | ||
|
|
69441167d3 | ||
|
|
4b97594217 | ||
|
|
9ee601f88c | ||
|
|
75b1a299e3 | ||
|
|
2613c463a1 | ||
|
|
78e0350d36 | ||
|
|
bc2425fc3f | ||
|
|
3e861bc72f | ||
|
|
b41c464753 | ||
|
|
2817275091 | ||
|
|
e76b0cf326 | ||
|
|
cf34103e15 | ||
|
|
1588fd7d7a | ||
|
|
4507ccde6c | ||
|
|
73fffd766f | ||
|
|
e529146c5b | ||
|
|
7050e52009 | ||
|
|
4f3238c4f6 | ||
|
|
b7d27c5d50 | ||
|
|
fe94aa0564 | ||
|
|
ae60a9aced | ||
|
|
4f686b0871 | ||
|
|
c61840b7e8 | ||
|
|
9adce95367 | ||
|
|
eef943458e | ||
|
|
f5c80689d4 | ||
|
|
5eaee3130a | ||
|
|
5846473f28 | ||
|
|
94c019b484 | ||
|
|
7e1140c022 | ||
|
|
ea9044719a | ||
|
|
8a96095448 | ||
|
|
fcc8f8751b | ||
|
|
af09ae7c3e | ||
|
|
e8e6a36d7b | ||
|
|
4f89d54ef0 | ||
|
|
2f9e2fb114 | ||
|
|
b6098024b8 | ||
|
|
1700131066 | ||
|
|
189536471a | ||
|
|
f534e0bcc3 | ||
|
|
e203a18e92 | ||
|
|
575a69bf4d | ||
|
|
69fd3a0367 | ||
|
|
8f7e70298e | ||
|
|
0fa3f5a554 | ||
|
|
f420012752 | ||
|
|
c1ca916549 | ||
|
|
dfcf2bdc85 | ||
|
|
72e7acfb7d | ||
|
|
9d06c127dc | ||
|
|
0460b388ab | ||
|
|
45b84ae898 | ||
|
|
41b1cb6f2d | ||
|
|
159aaab38e | ||
|
|
dc351238f6 | ||
|
|
e6491b39c6 | ||
|
|
91b4ed8940 | ||
|
|
ab99098afd | ||
|
|
d14ce2faa0 | ||
|
|
ca293691a8 | ||
|
|
cf8955b9b6 | ||
|
|
512828fdc9 | ||
|
|
91299a96e7 | ||
|
|
4876d9e727 | ||
|
|
a856f2a0e3 | ||
|
|
0e8113e7b0 | ||
|
|
34a953589d | ||
|
|
504ea5a238 | ||
|
|
3b5997fce6 | ||
|
|
7b0f6c3e75 | ||
|
|
099b85619c | ||
|
|
0129cd3f39 | ||
|
|
84f3cbf9a9 | ||
|
|
a7af462a44 | ||
|
|
fdca08eb3d | ||
|
|
c3eeefe9fe | ||
|
|
2f6990320c | ||
|
|
ef83450425 | ||
|
|
f2f10ec9f4 | ||
|
|
7346ff2e78 | ||
|
|
1dc274ce82 | ||
|
|
2be438f9c3 | ||
|
|
1f7f51ff1e | ||
|
|
338a7ae083 | ||
|
|
04d7896a92 | ||
|
|
4b8c8c0f96 | ||
|
|
8296476d94 | ||
|
|
38b3fc26ed | ||
|
|
6852b458fa | ||
|
|
cdb41023d4 | ||
|
|
8e00e681f0 | ||
|
|
577d6dd3a6 | ||
|
|
eeecd15d9e | ||
|
|
e39b26bcc3 | ||
|
|
6b5a77f8c1 | ||
|
|
0dc9736c35 | ||
|
|
bbe2471815 | ||
|
|
bee2c56382 | ||
|
|
b05a4f51b7 | ||
|
|
608794b600 | ||
|
|
ce8829ae69 | ||
|
|
1fb27f8d5a | ||
|
|
caf8777290 | ||
|
|
7dacdab2b5 | ||
|
|
f6a8660144 | ||
|
|
1e51631eba | ||
|
|
91048dc9c1 | ||
|
|
9f8dc39e2f | ||
|
|
07aa8f4829 | ||
|
|
b504615b6d | ||
|
|
3b1811a5ff | ||
|
|
71be6d4a5a | ||
|
|
ae04d20a82 | ||
|
|
2ad3953d3f | ||
|
|
c536f1d74b | ||
|
|
d8c1695ac9 | ||
|
|
b39912d08b | ||
|
|
8f5dd08836 | ||
|
|
6a27e61321 | ||
|
|
34fa19cf1e | ||
|
|
a97cc538f6 | ||
|
|
45471c9bf4 | ||
|
|
7145192988 | ||
|
|
0935becf70 | ||
|
|
a155c906b3 | ||
|
|
fa8e82224a | ||
|
|
7088e26e09 | ||
|
|
f471bdb607 | ||
|
|
0a0bd67834 | ||
|
|
e91f8331de | ||
|
|
2e90a7fe90 | ||
|
|
3fb3c5bad5 | ||
|
|
a6753ee888 | ||
|
|
9b04d3a758 | ||
|
|
68e2b2ff9b | ||
|
|
464baa6125 | ||
|
|
78083a0b68 | ||
|
|
681e248bdf | ||
|
|
1ca9493ce9 | ||
|
|
5537a8796f | ||
|
|
e2a1ab80b0 | ||
|
|
74db9e425f | ||
|
|
3e2152a979 | ||
|
|
930c6c88ae | ||
|
|
24bc276732 | ||
|
|
17cab5c51b | ||
|
|
96dbc8e9e6 | ||
|
|
56a0d51794 | ||
|
|
1cdbd969ba | ||
|
|
d77ece2aa6 | ||
|
|
d4c804c4ac | ||
|
|
c3003f8c3a | ||
|
|
66a2e45029 | ||
|
|
b0c889c336 | ||
|
|
f470b1e555 | ||
|
|
4965983ae1 | ||
|
|
2f2b4e2f3c | ||
|
|
16c739e37f | ||
|
|
f4d51a73cd | ||
|
|
6cc29e4167 | ||
|
|
324e1de84f | ||
|
|
551bdf4802 | ||
|
|
761d9069f6 | ||
|
|
7a15b0f444 | ||
|
|
a185ee4841 | ||
|
|
7213a75212 | ||
|
|
4823977098 | ||
|
|
fa74b84ce3 | ||
|
|
7423b23d3c | ||
|
|
033ded08c7 | ||
|
|
6b397c86d2 | ||
|
|
9730f12c56 | ||
|
|
92c7a80c2e | ||
|
|
64029de11a | ||
|
|
ae363ebad6 | ||
|
|
7b6478b7f5 | ||
|
|
aef7f58c6d | ||
|
|
52450efeb3 | ||
|
|
74d218d2d5 | ||
|
|
f4a60b28ec | ||
|
|
798593bad3 | ||
|
|
778e76b00b | ||
|
|
55778562ae | ||
|
|
66b5b42952 | ||
|
|
3ff8a4f51b | ||
|
|
b2a46db524 | ||
|
|
8d66f4f34d | ||
|
|
199b546d56 | ||
|
|
bea6e5ef53 | ||
|
|
3c17dc9943 | ||
|
|
6d693ed340 | ||
|
|
f86b7aee95 | ||
|
|
fca2d98d51 | ||
|
|
2f3d3d7b55 | ||
|
|
5250817d21 | ||
|
|
6f966590d9 | ||
|
|
da16cf73c9 | ||
|
|
999cda2fc2 | ||
|
|
28f5be071a | ||
|
|
4ad8fb69c7 | ||
|
|
2cb5ab7f98 | ||
|
|
97b87f2adb | ||
|
|
d23c263f9f | ||
|
|
7f003afa2b | ||
|
|
53d52dd17f | ||
|
|
036d57ef05 | ||
|
|
b25e429687 | ||
|
|
a3f87bf123 | ||
|
|
2cab253c4a | ||
|
|
ed119f02e2 | ||
|
|
f178fc16e9 | ||
|
|
e4b2071689 | ||
|
|
146df7ed1d | ||
|
|
7e8db0a3f8 | ||
|
|
e098922219 | ||
|
|
16ca024c22 | ||
|
|
a886e9dfb3 | ||
|
|
5d6114c9ec | ||
|
|
e3b2e1f434 | ||
|
|
6145347d9b | ||
|
|
49e694cbdc | ||
|
|
f860229993 | ||
|
|
f5d93baa17 | ||
|
|
76f58c43b0 | ||
|
|
db29fcc867 | ||
|
|
2f361c23c7 | ||
|
|
4e7ac6eb4b | ||
|
|
58bca689c8 | ||
|
|
e1b2aee33c | ||
|
|
7a6e8525c5 | ||
|
|
b8db68bed1 | ||
|
|
1072f47467 | ||
|
|
cfb1d858c6 | ||
|
|
8e0e75aee6 | ||
|
|
1479c942e2 | ||
|
|
63b02b889c | ||
|
|
5a1de0e2cf | ||
|
|
ad2a402521 | ||
|
|
a14af93afc | ||
|
|
90630bca1d | ||
|
|
bf1db38e2e | ||
|
|
88e23768c6 | ||
|
|
ea8366ca92 | ||
|
|
8e1f07415f | ||
|
|
0b62e773eb | ||
|
|
1c4b1e2d2f | ||
|
|
0e53dd3854 | ||
|
|
c2fa13b6ab | ||
|
|
837c9a1444 | ||
|
|
08ec4f6b7e | ||
|
|
f5a8076da3 | ||
|
|
cf8c935694 | ||
|
|
67fd7d952a | ||
|
|
b7a3ad6fe7 | ||
|
|
0dabd2ee58 | ||
|
|
e841fc6282 | ||
|
|
ab45a46fc0 |
17
.gitignore
vendored
@@ -324,19 +324,18 @@ ASALocalRun/
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
*.dll
|
||||
*.pdb
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
/.semantic-kernel/results/src/ISS.IPSA.AiAgent.Api/plugins/BasePlugin/YesNo
|
||||
**/bin/
|
||||
**/obj/
|
||||
**/.vs/
|
||||
|
||||
/Xzy.KnowledgeBase/appsettings.Development.json
|
||||
/Xzy.KnowledgeBase/XzyAgent.db
|
||||
/Xzy.KnowledgeBase/AntSK.db
|
||||
/AntSK/AntSK.db
|
||||
/AntSK/appsettings.Development.json
|
||||
/AntSK.db
|
||||
**/tmp-memory-files/*
|
||||
**/tmp-memory-vectors/*
|
||||
/src/AntSK/AntSK.db
|
||||
/src/AntSK/appsettings.Development.json
|
||||
/src/AntSK.db
|
||||
/src/AntSK/llama_models
|
||||
/src/AntSK/AntSK.xml
|
||||
@@ -1,23 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<DocumentationFile>AntSK.Domain.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="8.1.0" />
|
||||
<PackageReference Include="MarkdownSharp" Version="2.0.5" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.137" />
|
||||
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.118" />
|
||||
|
||||
<PackageReference Include="Microsoft.SemanticKernel" Version="1.3.0" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Core" Version="1.3.0" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Core" Version="1.3.0-alpha" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.Core" Version="0.26.240121.1" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Postgres" Version="0.26.240121.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,498 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>AntSK.Domain</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:AntSK.Domain.Common.DependencyInjection.ServiceCollectionExtensions">
|
||||
<summary>
|
||||
容器扩展
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Common.DependencyInjection.ServiceCollectionExtensions.AddServicesFromAssemblies(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.String[])">
|
||||
<summary>
|
||||
从程序集中加载类型并添加到容器中
|
||||
</summary>
|
||||
<param name="services">容器</param>
|
||||
<param name="assemblies">程序集集合</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="F:AntSK.Domain.Common.DependencyInjection.ServiceLifetime.Scoped">
|
||||
<summary>
|
||||
作用域
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:AntSK.Domain.Common.DependencyInjection.ServiceLifetime.Singleton">
|
||||
<summary>
|
||||
单例
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:AntSK.Domain.Common.DependencyInjection.ServiceLifetime.Transient">
|
||||
<summary>
|
||||
瞬时
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Map.MapperExtend.ToDTOList``1(System.Object)">
|
||||
<summary>
|
||||
Entity集合转DTO集合
|
||||
</summary>
|
||||
<typeparam name="T"></typeparam>
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Map.MapperExtend.ToDTO``1(System.Object)">
|
||||
<summary>
|
||||
Entity转DTO
|
||||
</summary>
|
||||
<typeparam name="T"></typeparam>
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Map.MapperExtend.MapTo``1(System.Object,``0)">
|
||||
<summary>
|
||||
给已有对象map,适合update场景,如需过滤空值需要在AutoMapProfile 设置
|
||||
</summary>
|
||||
<typeparam name="T"></typeparam>
|
||||
<param name="self"></param>
|
||||
<param name="result"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Model.PageList`1.PageIndex">
|
||||
<summary>
|
||||
当前页,从1开始
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Model.PageList`1.PageSize">
|
||||
<summary>
|
||||
每页数量
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Model.PageList`1.TotalCount">
|
||||
<summary>
|
||||
总数
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Options.ConnectionOption.Sqlite">
|
||||
<summary>
|
||||
sqlite连接字符串
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Options.ConnectionOption.Postgres">
|
||||
<summary>
|
||||
pg链接字符串
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Apps.Name">
|
||||
<summary>
|
||||
名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Apps.Describe">
|
||||
<summary>
|
||||
描述
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Apps.Prompt">
|
||||
<summary>
|
||||
提示词
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Apps.KmsIdList">
|
||||
<summary>
|
||||
知识库ID列表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Apps.SecretKey">
|
||||
<summary>
|
||||
API调用秘钥
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.KmsDetails.FileName">
|
||||
<summary>
|
||||
文件名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.KmsDetails.Url">
|
||||
<summary>
|
||||
地址
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.KmsDetails.Type">
|
||||
<summary>
|
||||
类型 file,url
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.KmsDetails.DataCount">
|
||||
<summary>
|
||||
数据数量
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.KmsDetails.CreateTime">
|
||||
<summary>
|
||||
创建时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Kmss.Icon">
|
||||
<summary>
|
||||
图标
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Kmss.Name">
|
||||
<summary>
|
||||
名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Kmss.Describe">
|
||||
<summary>
|
||||
会话模型
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetList">
|
||||
<summary>
|
||||
获取所有list
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetListAsync">
|
||||
<summary>
|
||||
获取所有list-异步
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetList(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda查询
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetListAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda查询-异步
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.Count(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda表达式获取数量
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.CountAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda表达式获取数量-异步
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetPageList(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}},SqlSugar.PageModel)">
|
||||
<summary>
|
||||
获取分页
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<param name="page"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetPageListAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}},SqlSugar.PageModel)">
|
||||
<summary>
|
||||
获取分页-异步
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<param name="page"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetById(System.Object)">
|
||||
<summary>
|
||||
根据id获取实体
|
||||
</summary>
|
||||
<param name="id"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetByIdAsync(System.Object)">
|
||||
<summary>
|
||||
根据id获取实体-异步
|
||||
</summary>
|
||||
<param name="id"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetSingle(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda获取单个对象 (注意,需要确保唯一,如果获取到2个会报错,这种场景需要使用GetFirst)
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetSingleAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda获取单个对象-异步 (注意,需要确保唯一,如果获取到2个会报错,这种场景需要使用GetFirst)
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetFirst(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda获取单个对象
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetFirstAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda获取单个对象 --异步
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.Insert(`0)">
|
||||
<summary>
|
||||
实体插入
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertAsync(`0)">
|
||||
<summary>
|
||||
实体插入-异步
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertRange(System.Collections.Generic.List{`0})">
|
||||
<summary>
|
||||
批量插入
|
||||
</summary>
|
||||
<param name="objs"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertRangeAsync(System.Collections.Generic.List{`0})">
|
||||
<summary>
|
||||
批量插入-异步
|
||||
</summary>
|
||||
<param name="objs"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertReturnIdentity(`0)">
|
||||
<summary>
|
||||
插入返回自增列
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertReturnIdentityAsync(`0)">
|
||||
<summary>
|
||||
插入返回自增列-异步
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertReturnBigIdentity(`0)">
|
||||
<summary>
|
||||
插入返回longid
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertReturnBigIdentityAsync(`0)">
|
||||
<summary>
|
||||
插入返回longid-异步
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.DeleteByIds(System.Object[])">
|
||||
<summary>
|
||||
批量删除
|
||||
</summary>
|
||||
<param name="ids"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.DeleteByIdsAsync(System.Object[])">
|
||||
<summary>
|
||||
批量删除-异步
|
||||
</summary>
|
||||
<param name="ids"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.Delete(System.Object)">
|
||||
<summary>
|
||||
根据主键删除
|
||||
</summary>
|
||||
<param name="id"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.DeleteAsync(System.Object)">
|
||||
<summary>
|
||||
根据主键删除-异步
|
||||
</summary>
|
||||
<param name="id"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.Delete(`0)">
|
||||
<summary>
|
||||
根据实体删除
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.DeleteAsync(`0)">
|
||||
<summary>
|
||||
根据实体删除-异步
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.Delete(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据表达式删除
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.DeleteAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据表达式删除-异步
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.Update(`0)">
|
||||
<summary>
|
||||
更新
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.UpdateAsync(`0)">
|
||||
<summary>
|
||||
更新-异步
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.UpdateRange(System.Collections.Generic.List{`0})">
|
||||
<summary>
|
||||
批量更新
|
||||
</summary>
|
||||
<param name="objs"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.UpdateRangeAsync(System.Collections.Generic.List{`0})">
|
||||
<summary>
|
||||
批量更新-异步
|
||||
</summary>
|
||||
<param name="objs"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.IsAny(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
是否包含元素
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.IsAnyAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
是否包含元素-异步
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="F:AntSK.Domain.Repositories.Base.SqlSugarHelper.Sqlite">
|
||||
<summary>
|
||||
sqlserver连接
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.IsNull(System.Object)">
|
||||
<summary>
|
||||
判断是否为空,为空返回true
|
||||
</summary>
|
||||
<param name="data"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.IsNotNull(System.Object)">
|
||||
<summary>
|
||||
判断是否为空,为空返回true
|
||||
</summary>
|
||||
<param name="data"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.IsNull(System.String)">
|
||||
<summary>
|
||||
判断是否为空,为空返回true
|
||||
</summary>
|
||||
<param name="data"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToString(System.Object)">
|
||||
<summary>
|
||||
将obj类型转换为string
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToInt32(System.Object)">
|
||||
<summary>
|
||||
object 转int32
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToInt64(System.Object)">
|
||||
<summary>
|
||||
object 转int32
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToDouble(System.Object)">
|
||||
<summary>
|
||||
将字符串转double
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToDateTime(System.String)">
|
||||
<summary>
|
||||
转换为datetime类型
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToDateTime(System.String,System.String)">
|
||||
<summary>
|
||||
转换为datetime类型的格式字符串
|
||||
</summary>
|
||||
<param name="s">要转换的对象</param>
|
||||
<param name="y">格式化字符串</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToDecimal(System.Object)">
|
||||
<summary>
|
||||
将字符串转换成decimal
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.DecimalFraction(System.Decimal)">
|
||||
<summary>
|
||||
decimal保留2位小数
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ReplaceHtml(System.String)">
|
||||
<summary>
|
||||
替换html种的特殊字符
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.StreamToByte(System.IO.Stream)">
|
||||
<summary>
|
||||
流转byte
|
||||
</summary>
|
||||
<param name="stream"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Domain.Dto
|
||||
{
|
||||
public class KMFile
|
||||
{
|
||||
public string Text { get; set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
|
||||
public string LastUpdate { get; set; }
|
||||
|
||||
public string Schema { get; set; }
|
||||
|
||||
public string File { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using AntSK.Domain.Domain.Dto;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Domain.Interface
|
||||
{
|
||||
public interface IKMService
|
||||
{
|
||||
Task<List<KMFile>> GetDocumentByFileID(string fileid);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using AntSK.Domain.Common.DependencyInjection;
|
||||
using AntSK.Domain.Domain.Interface;
|
||||
using Microsoft.KernelMemory;
|
||||
using AntSK.Domain.Utils;
|
||||
using AntSK.Domain.Domain.Dto;
|
||||
|
||||
namespace AntSK.Domain.Domain.Service
|
||||
{
|
||||
[ServiceDescription(typeof(IKMService), ServiceLifetime.Scoped)]
|
||||
public class KMService(MemoryServerless _memory) : IKMService
|
||||
{
|
||||
public async Task<List<KMFile>> GetDocumentByFileID(string fileid)
|
||||
{
|
||||
var memories = await _memory.ListIndexesAsync();
|
||||
var memoryDbs = _memory.Orchestrator.GetMemoryDbs();
|
||||
List<KMFile> docTextList = new List<KMFile>();
|
||||
|
||||
foreach (var memoryIndex in memories)
|
||||
{
|
||||
foreach (var memoryDb in memoryDbs)
|
||||
{
|
||||
var list = memoryDb.GetListAsync(memoryIndex.Name, null, 100, true);
|
||||
|
||||
await foreach (var item in list)
|
||||
{
|
||||
if (item.Id.Contains(fileid))
|
||||
{
|
||||
|
||||
KMFile file = new KMFile()
|
||||
{
|
||||
Text = item.Payload.FirstOrDefault(p => p.Key == "text").Value.ConvertToString(),
|
||||
Url= item.Payload.FirstOrDefault(p => p.Key == "url").Value.ConvertToString(),
|
||||
LastUpdate= item.Payload.FirstOrDefault(p => p.Key == "last_update").Value.ConvertToString(),
|
||||
Schema = item.Payload.FirstOrDefault(p => p.Key == "schema").Value.ConvertToString(),
|
||||
File = item.Payload.FirstOrDefault(p => p.Key == "file").Value.ConvertToString(),
|
||||
};
|
||||
docTextList.Add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return docTextList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using AutoMapper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Map
|
||||
{
|
||||
public class AutoMapProfile : Profile
|
||||
{
|
||||
public AutoMapProfile()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
using AutoMapper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Map
|
||||
{
|
||||
public static class MapperExtend
|
||||
{
|
||||
/// <summary>
|
||||
/// Entity集合转DTO集合
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static List<T> ToDTOList<T>(this object value)
|
||||
{
|
||||
if (value == null)
|
||||
return new List<T>();
|
||||
|
||||
return Mapper.Map<List<T>>(value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Entity转DTO
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static T ToDTO<T>(this object value)
|
||||
{
|
||||
if (value == null)
|
||||
return default(T);
|
||||
|
||||
return Mapper.Map<T>(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 给已有对象map,适合update场景,如需过滤空值需要在AutoMapProfile 设置
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public static T MapTo<T>(this object self, T result)
|
||||
{
|
||||
if (self == null)
|
||||
return default(T);
|
||||
return (T)Mapper.Map(self, result, self.GetType(), typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Model
|
||||
{
|
||||
public class MessageInfo
|
||||
{
|
||||
public string ID { get; set; } = "";
|
||||
public string Questions { get; set; } = "";
|
||||
public string Answers { get; set; } = "";
|
||||
public string HtmlAnswers { get; set; } = "";
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Options
|
||||
{
|
||||
public class ConnectionOption
|
||||
{
|
||||
/// <summary>
|
||||
/// sqlite连接字符串
|
||||
/// </summary>
|
||||
public static string Sqlite { get; set; }
|
||||
/// <summary>
|
||||
/// pg链接字符串
|
||||
/// </summary>
|
||||
public static string Postgres { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Options
|
||||
{
|
||||
public class OpenAIOption
|
||||
{
|
||||
public static string EndPoint { get; set; }
|
||||
public static string Key { get; set; }
|
||||
public static string Model { get; set; }
|
||||
|
||||
public static string EmbeddingModel { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Repositories
|
||||
{
|
||||
[SugarTable("Kms")]
|
||||
public partial class Kmss
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true)]
|
||||
public string Id { get; set; }
|
||||
/// <summary>
|
||||
/// 图标
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Icon { get; set; }
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// 会话模型
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Describe { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using AntSK.Domain.Options;
|
||||
using AntSK.Domain.Utils;
|
||||
using System.Reflection;
|
||||
|
||||
namespace AntSK.Domain.Repositories.Base
|
||||
{
|
||||
public class SqlSugarHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// sqlserver连接
|
||||
/// </summary>
|
||||
public static SqlSugarScope Sqlite = new SqlSugarScope(new ConnectionConfig()
|
||||
{
|
||||
ConnectionString = ConnectionOption.Postgres,
|
||||
DbType = DbType.PostgreSQL,
|
||||
InitKeyType = InitKeyType.Attribute,//从特性读取主键和自增列信息
|
||||
IsAutoCloseConnection = true,
|
||||
ConfigureExternalServices = new ConfigureExternalServices
|
||||
{
|
||||
//注意: 这儿AOP设置不能少
|
||||
EntityService = (c, p) =>
|
||||
{
|
||||
/***高版C#写法***/
|
||||
//支持string?和string
|
||||
if (p.IsPrimarykey == false && new NullabilityInfoContext()
|
||||
.Create(c).WriteState is NullabilityState.Nullable)
|
||||
{
|
||||
p.IsNullable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, Db =>
|
||||
{
|
||||
Db.Aop.OnLogExecuting = (sql, pars) =>
|
||||
{
|
||||
if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT").ConvertToString() == "Development")
|
||||
{
|
||||
Console.WriteLine(sql + "\r\n" +
|
||||
Sqlite.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
|
||||
Console.WriteLine();
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
using AntSK.Domain.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Utils
|
||||
{
|
||||
public class OpenAIHttpClientHandler : HttpClientHandler
|
||||
{
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
UriBuilder uriBuilder;
|
||||
Regex regex = new Regex(@"(https?)://([^/]+)/(.*)");
|
||||
Match match = regex.Match(OpenAIOption.EndPoint);
|
||||
string xieyi = match.Groups[1].Value;
|
||||
string host = match.Groups[2].Value;
|
||||
string route = match.Groups[3].Value;
|
||||
if (match.Success)
|
||||
{
|
||||
switch (request.RequestUri.LocalPath)
|
||||
{
|
||||
case "/v1/chat/completions":
|
||||
//替换代理
|
||||
uriBuilder = new UriBuilder(request.RequestUri)
|
||||
{
|
||||
// 这里是你要修改的 URL
|
||||
Scheme = $"{xieyi}://{host}/",
|
||||
Host = host,
|
||||
Path = route + "v1/chat/completions",
|
||||
};
|
||||
request.RequestUri = uriBuilder.Uri;
|
||||
|
||||
break;
|
||||
case "/v1/embeddings":
|
||||
uriBuilder = new UriBuilder(request.RequestUri)
|
||||
{
|
||||
// 这里是你要修改的 URL
|
||||
Scheme = $"{xieyi}://{host}/",
|
||||
Host = host,
|
||||
Path = route + "v1/embeddings",
|
||||
};
|
||||
request.RequestUri = uriBuilder.Uri;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 接着,调用基类的 SendAsync 方法将你的修改后的请求发出去
|
||||
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,473 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>AntSK.Domain</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:AntSK.Domain.Common.DependencyInjection.ServiceCollectionExtensions">
|
||||
<summary>
|
||||
容器扩展
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Common.DependencyInjection.ServiceCollectionExtensions.AddServicesFromAssemblies(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.String[])">
|
||||
<summary>
|
||||
从程序集中加载类型并添加到容器中
|
||||
</summary>
|
||||
<param name="services">容器</param>
|
||||
<param name="assemblies">程序集集合</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="F:AntSK.Domain.Common.DependencyInjection.ServiceLifetime.Scoped">
|
||||
<summary>
|
||||
作用域
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:AntSK.Domain.Common.DependencyInjection.ServiceLifetime.Singleton">
|
||||
<summary>
|
||||
单例
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:AntSK.Domain.Common.DependencyInjection.ServiceLifetime.Transient">
|
||||
<summary>
|
||||
瞬时
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Map.MapperExtend.ToDTOList``1(System.Object)">
|
||||
<summary>
|
||||
Entity集合转DTO集合
|
||||
</summary>
|
||||
<typeparam name="T"></typeparam>
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Map.MapperExtend.ToDTO``1(System.Object)">
|
||||
<summary>
|
||||
Entity转DTO
|
||||
</summary>
|
||||
<typeparam name="T"></typeparam>
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Map.MapperExtend.MapTo``1(System.Object,``0)">
|
||||
<summary>
|
||||
给已有对象map,适合update场景,如需过滤空值需要在AutoMapProfile 设置
|
||||
</summary>
|
||||
<typeparam name="T"></typeparam>
|
||||
<param name="self"></param>
|
||||
<param name="result"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Model.PageList`1.PageIndex">
|
||||
<summary>
|
||||
当前页,从1开始
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Model.PageList`1.PageSize">
|
||||
<summary>
|
||||
每页数量
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Model.PageList`1.TotalCount">
|
||||
<summary>
|
||||
总数
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Options.ConnectionOption.Sqlite">
|
||||
<summary>
|
||||
sqlite连接字符串
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Apps.Name">
|
||||
<summary>
|
||||
名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Apps.Describe">
|
||||
<summary>
|
||||
描述
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.KmsDetails.FileName">
|
||||
<summary>
|
||||
文件名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.KmsDetails.DataCount">
|
||||
<summary>
|
||||
数据数量
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.KmsDetails.Status">
|
||||
<summary>
|
||||
状态
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.KmsDetails.CreateTime">
|
||||
<summary>
|
||||
创建时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Kmss.Name">
|
||||
<summary>
|
||||
名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Kmss.ChatModel">
|
||||
<summary>
|
||||
会话模型
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Kmss.EmbeddingModel">
|
||||
<summary>
|
||||
向量模型
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetList">
|
||||
<summary>
|
||||
获取所有list
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetListAsync">
|
||||
<summary>
|
||||
获取所有list-异步
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetList(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda查询
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetListAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda查询-异步
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.Count(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda表达式获取数量
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.CountAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda表达式获取数量-异步
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetPageList(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}},SqlSugar.PageModel)">
|
||||
<summary>
|
||||
获取分页
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<param name="page"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetPageListAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}},SqlSugar.PageModel)">
|
||||
<summary>
|
||||
获取分页-异步
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<param name="page"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetById(System.Object)">
|
||||
<summary>
|
||||
根据id获取实体
|
||||
</summary>
|
||||
<param name="id"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetByIdAsync(System.Object)">
|
||||
<summary>
|
||||
根据id获取实体-异步
|
||||
</summary>
|
||||
<param name="id"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetSingle(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda获取单个对象 (注意,需要确保唯一,如果获取到2个会报错,这种场景需要使用GetFirst)
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetSingleAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda获取单个对象-异步 (注意,需要确保唯一,如果获取到2个会报错,这种场景需要使用GetFirst)
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetFirst(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda获取单个对象
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.GetFirstAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据lambda获取单个对象 --异步
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.Insert(`0)">
|
||||
<summary>
|
||||
实体插入
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertAsync(`0)">
|
||||
<summary>
|
||||
实体插入-异步
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertRange(System.Collections.Generic.List{`0})">
|
||||
<summary>
|
||||
批量插入
|
||||
</summary>
|
||||
<param name="objs"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertRangeAsync(System.Collections.Generic.List{`0})">
|
||||
<summary>
|
||||
批量插入-异步
|
||||
</summary>
|
||||
<param name="objs"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertReturnIdentity(`0)">
|
||||
<summary>
|
||||
插入返回自增列
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertReturnIdentityAsync(`0)">
|
||||
<summary>
|
||||
插入返回自增列-异步
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertReturnBigIdentity(`0)">
|
||||
<summary>
|
||||
插入返回longid
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.InsertReturnBigIdentityAsync(`0)">
|
||||
<summary>
|
||||
插入返回longid-异步
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.DeleteByIds(System.Object[])">
|
||||
<summary>
|
||||
批量删除
|
||||
</summary>
|
||||
<param name="ids"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.DeleteByIdsAsync(System.Object[])">
|
||||
<summary>
|
||||
批量删除-异步
|
||||
</summary>
|
||||
<param name="ids"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.Delete(System.Object)">
|
||||
<summary>
|
||||
根据主键删除
|
||||
</summary>
|
||||
<param name="id"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.DeleteAsync(System.Object)">
|
||||
<summary>
|
||||
根据主键删除-异步
|
||||
</summary>
|
||||
<param name="id"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.Delete(`0)">
|
||||
<summary>
|
||||
根据实体删除
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.DeleteAsync(`0)">
|
||||
<summary>
|
||||
根据实体删除-异步
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.Delete(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据表达式删除
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.DeleteAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据表达式删除-异步
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.Update(`0)">
|
||||
<summary>
|
||||
更新
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.UpdateAsync(`0)">
|
||||
<summary>
|
||||
更新-异步
|
||||
</summary>
|
||||
<param name="obj"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.UpdateRange(System.Collections.Generic.List{`0})">
|
||||
<summary>
|
||||
批量更新
|
||||
</summary>
|
||||
<param name="objs"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.UpdateRangeAsync(System.Collections.Generic.List{`0})">
|
||||
<summary>
|
||||
批量更新-异步
|
||||
</summary>
|
||||
<param name="objs"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.IsAny(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
是否包含元素
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Repositories.Base.Repository`1.IsAnyAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
是否包含元素-异步
|
||||
</summary>
|
||||
<param name="whereExpression"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="F:AntSK.Domain.Repositories.Base.SqlSugarHelper.Sqlite">
|
||||
<summary>
|
||||
sqlserver连接
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.IsNull(System.Object)">
|
||||
<summary>
|
||||
判断是否为空,为空返回true
|
||||
</summary>
|
||||
<param name="data"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.IsNotNull(System.Object)">
|
||||
<summary>
|
||||
判断是否为空,为空返回true
|
||||
</summary>
|
||||
<param name="data"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.IsNull(System.String)">
|
||||
<summary>
|
||||
判断是否为空,为空返回true
|
||||
</summary>
|
||||
<param name="data"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToString(System.Object)">
|
||||
<summary>
|
||||
将obj类型转换为string
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToInt32(System.Object)">
|
||||
<summary>
|
||||
object 转int32
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToInt64(System.Object)">
|
||||
<summary>
|
||||
object 转int32
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToDouble(System.Object)">
|
||||
<summary>
|
||||
将字符串转double
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToDateTime(System.String)">
|
||||
<summary>
|
||||
转换为datetime类型
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToDateTime(System.String,System.String)">
|
||||
<summary>
|
||||
转换为datetime类型的格式字符串
|
||||
</summary>
|
||||
<param name="s">要转换的对象</param>
|
||||
<param name="y">格式化字符串</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ConvertToDecimal(System.Object)">
|
||||
<summary>
|
||||
将字符串转换成decimal
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.DecimalFraction(System.Decimal)">
|
||||
<summary>
|
||||
decimal保留2位小数
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.ReplaceHtml(System.String)">
|
||||
<summary>
|
||||
替换html种的特殊字符
|
||||
</summary>
|
||||
<param name="s"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.StreamToByte(System.IO.Stream)">
|
||||
<summary>
|
||||
流转byte
|
||||
</summary>
|
||||
<param name="stream"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
36
AntSK.sln
@@ -1,36 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.8.34330.188
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntSK", "AntSK\AntSK.csproj", "{9AA5A735-8FB1-4CC5-AB3E-D02B3A3B6682}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntSK.Domain", "AntSK.Domain\AntSK.Domain.csproj", "{64F17C9A-97C2-46FA-9345-86C5289288AD}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docker", "Docker", "{9F2E193A-5F9D-4C82-B591-CB133EEB59F0}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Dockerfile = Dockerfile
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{9AA5A735-8FB1-4CC5-AB3E-D02B3A3B6682}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9AA5A735-8FB1-4CC5-AB3E-D02B3A3B6682}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9AA5A735-8FB1-4CC5-AB3E-D02B3A3B6682}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9AA5A735-8FB1-4CC5-AB3E-D02B3A3B6682}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{64F17C9A-97C2-46FA-9345-86C5289288AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{64F17C9A-97C2-46FA-9345-86C5289288AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{64F17C9A-97C2-46FA-9345-86C5289288AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{64F17C9A-97C2-46FA-9345-86C5289288AD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {2076B7C9-2E5B-4580-9712-03F0D56BC1AF}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
119
AntSK/AntSK.xml
@@ -1,119 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>AntSK</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="M:AntSK.Controllers.FileController.UploadFile(Microsoft.AspNetCore.Http.IFormFile)">
|
||||
<summary>
|
||||
Upload FileName
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Controllers.InitController.InitTable">
|
||||
<summary>
|
||||
初始化DB 和表
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:AntSK.Controllers.OpenController">
|
||||
<summary>
|
||||
对外接口
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Controllers.OpenController.#ctor(AntSK.Services.OpenApi.IOpenApiService)">
|
||||
<summary>
|
||||
对外接口
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Controllers.OpenController.chat(AntSK.Models.OpenAIModel)">
|
||||
<summary>
|
||||
对话接口
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Pages.ChatPage.Chat.SendKms(System.String,System.String,AntSK.Domain.Repositories.Apps)">
|
||||
<summary>
|
||||
发送知识库问答
|
||||
</summary>
|
||||
<param name="questions"></param>
|
||||
<param name="msg"></param>
|
||||
<param name="app"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Pages.ChatPage.Chat.SendChat(System.String,System.String,AntSK.Domain.Repositories.Apps)">
|
||||
<summary>
|
||||
发送普通对话
|
||||
</summary>
|
||||
<param name="questions"></param>
|
||||
<param name="msg"></param>
|
||||
<param name="app"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Pages.ChatPage.Chat.HistorySummarize(System.String)">
|
||||
<summary>
|
||||
历史会话的会话总结
|
||||
</summary>
|
||||
<param name="questions"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Pages.ChatPage.OpenChat.SendKms(System.String,System.String,AntSK.Domain.Repositories.Apps)">
|
||||
<summary>
|
||||
发送知识库问答
|
||||
</summary>
|
||||
<param name="questions"></param>
|
||||
<param name="msg"></param>
|
||||
<param name="app"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Pages.ChatPage.OpenChat.SendChat(System.String,System.String,AntSK.Domain.Repositories.Apps)">
|
||||
<summary>
|
||||
发送普通对话
|
||||
</summary>
|
||||
<param name="questions"></param>
|
||||
<param name="msg"></param>
|
||||
<param name="app"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Pages.ChatPage.OpenChat.HistorySummarize(System.String)">
|
||||
<summary>
|
||||
历史会话的会话总结
|
||||
</summary>
|
||||
<param name="questions"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:AntSK.Pages.KmsPage.KmsDetail.UrlModel">
|
||||
<summary>
|
||||
根据文档ID获取文档
|
||||
</summary>
|
||||
<param name="fileid"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Services.OpenApi.OpenApiService.SendKms(System.String,AntSK.Domain.Repositories.Apps)">
|
||||
<summary>
|
||||
发送知识库问答
|
||||
</summary>
|
||||
<param name="questions"></param>
|
||||
<param name="msg"></param>
|
||||
<param name="app"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Services.OpenApi.OpenApiService.SendChat(System.String,AntSK.Domain.Repositories.Apps)">
|
||||
<summary>
|
||||
发送普通对话
|
||||
</summary>
|
||||
<param name="questions"></param>
|
||||
<param name="msg"></param>
|
||||
<param name="app"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:AntSK.Services.OpenApi.OpenApiService.HistorySummarize(AntSK.Models.OpenAIModel)">
|
||||
<summary>
|
||||
历史会话的会话总结
|
||||
</summary>
|
||||
<param name="questions"></param>
|
||||
<param name="msg"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
@@ -1,11 +0,0 @@
|
||||
@namespace AntSK.Components
|
||||
@inherits AntDomComponentBase
|
||||
|
||||
<Space Class="@ClassMapper.Class" Size="@("24")">
|
||||
<SpaceItem>
|
||||
<AvatarDropdown Name="@_currentUser.Name"
|
||||
Avatar="@_currentUser.Avatar"
|
||||
MenuItems="@AvatarMenuItems"
|
||||
OnItemSelected="HandleSelectUser" />
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
@@ -1,31 +0,0 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using AntSK.Domain.Repositories;
|
||||
|
||||
namespace AntSK.Controllers
|
||||
{
|
||||
[Route("api/[controller]/[action]")]
|
||||
[ApiController]
|
||||
public class InitController : ControllerBase
|
||||
{
|
||||
private readonly IApps_Repositories _repository;
|
||||
|
||||
public InitController(IApps_Repositories repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
/// <summary>
|
||||
/// 初始化DB 和表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public IActionResult InitTable()
|
||||
{
|
||||
_repository.GetDB().DbMaintenance.CreateDatabase();
|
||||
_repository.GetDB().CodeFirst.InitTables(typeof(Apps));
|
||||
_repository.GetDB().CodeFirst.InitTables(typeof(Kmss));
|
||||
_repository.GetDB().CodeFirst.InitTables(typeof(KmsDetails));
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
@namespace AntSK
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<AntDesign.ProLayout.BasicLayout
|
||||
Logo="@("https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg")"
|
||||
MenuData="_menuData">
|
||||
<RightContentRender>
|
||||
<AntSK.Components.RightContent />
|
||||
</RightContentRender>
|
||||
<ChildContent>
|
||||
@Body
|
||||
</ChildContent>
|
||||
<FooterRender>
|
||||
<FooterView Copyright="2024 许泽宇的技术分享" Links="Links"></FooterView>
|
||||
</FooterRender>
|
||||
</AntDesign.ProLayout.BasicLayout>
|
||||
<SettingDrawer />
|
||||
|
||||
@code
|
||||
{
|
||||
private MenuDataItem[] _menuData = { };
|
||||
|
||||
[Inject] public HttpClient HttpClient { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
_menuData = await HttpClient.GetFromJsonAsync<MenuDataItem[]>("data/menu.json");
|
||||
}
|
||||
|
||||
|
||||
public LinkItem[] Links { get; set; } =
|
||||
{
|
||||
new LinkItem
|
||||
{
|
||||
Key = "许泽宇的技术分享",
|
||||
Title = "许泽宇的技术分享",
|
||||
Href = "http://studiogpt.cn/",
|
||||
BlankTarget = true,
|
||||
},
|
||||
new LinkItem
|
||||
{
|
||||
Key = "github",
|
||||
Title = (RenderFragment)(@<Icon Type="github" />),
|
||||
Href = "https://github.com/xuzeyu91/Xzy.AntSK.KnowledgeBase",
|
||||
BlankTarget = true,
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
@namespace AntSK
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
@Body
|
||||
|
||||
@code {
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Models
|
||||
{
|
||||
public class OpenAIModel
|
||||
{
|
||||
public List<OpenAIMessage> messages { get; set; }
|
||||
}
|
||||
|
||||
public class OpenAIMessage
|
||||
{
|
||||
public string role { get; set; }
|
||||
|
||||
public string content { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AntSK.Models.OpenAPI
|
||||
{
|
||||
public class OpenAIResult
|
||||
{
|
||||
public string id { get; set; } = Guid.NewGuid().ToString();
|
||||
[JsonPropertyName("object")]
|
||||
public string obj { get; set; } = "chat.completion";
|
||||
public List<ChoicesModel> choices { get; set; }
|
||||
public long created { get; set; }
|
||||
}
|
||||
|
||||
public class ChoicesModel
|
||||
{
|
||||
public string finish_reason { get; set; } = "stop";
|
||||
public int index { get; set; } = 0;
|
||||
|
||||
public OpenAIMessage message { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
@namespace AntSK.Pages.AppPage
|
||||
@using AntSK.Domain.Repositories
|
||||
@using AntSK.Models
|
||||
@page "/App/Add"
|
||||
@page "/App/Add/{AppId}"
|
||||
@using AntSK.Services.Auth
|
||||
@inherits AuthComponentBase
|
||||
|
||||
<PageContainer Title="新增应用">
|
||||
<ChildContent>
|
||||
<Card>
|
||||
<Form Model="@_appModel"
|
||||
Style="margin-top: 8px;"
|
||||
OnFinish="HandleSubmit">
|
||||
<FormItem Label="知识库名称" LabelCol="_formItemLayout.LabelCol" WrapperCol="_formItemLayout.WrapperCol">
|
||||
<Input Placeholder="请输入知识库名称" @bind-Value="@context.Name" />
|
||||
</FormItem>
|
||||
<FormItem Label="图标" LabelCol="_formItemLayout.LabelCol" WrapperCol="_formItemLayout.WrapperCol">
|
||||
<Input Placeholder="请输入图标" @bind-Value="@context.Icon" />
|
||||
<a href="https://antblazor.com/zh-CN/components/icon" target="_blank">图标库</a>
|
||||
</FormItem>
|
||||
<FormItem Label="类型" LabelCol="_formItemLayout.LabelCol" WrapperCol="_formItemLayout.WrapperCol">
|
||||
<RadioGroup @bind-Value="context.Type">
|
||||
<Radio RadioButton Value="@("chat")">简单对话</Radio>
|
||||
<Radio RadioButton Value="@("kms")" >知识库</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem Label="描述" LabelCol="_formItemLayout.LabelCol" WrapperCol="_formItemLayout.WrapperCol">
|
||||
<Input Placeholder="请输入描述" @bind-Value="@context.Describe" />
|
||||
</FormItem>
|
||||
@if (@context.Type == "chat")
|
||||
{
|
||||
<FormItem Label="提示词" LabelCol="_formItemLayout.LabelCol" WrapperCol="_formItemLayout.WrapperCol">
|
||||
<TextArea MinRows="4" Placeholder="请输入提示词,用户输入使用{{$input}} 来做占位符" @bind-Value="@context.Prompt" />
|
||||
</FormItem>
|
||||
}
|
||||
@if (@context.Type == "kms")
|
||||
{
|
||||
<FormItem Label="知识库" LabelCol="_formItemLayout.LabelCol" WrapperCol="_formItemLayout.WrapperCol">
|
||||
<Select Mode="multiple"
|
||||
@bind-Values="kmsIds"
|
||||
Placeholder="选择知识库"
|
||||
TItemValue="string"
|
||||
TItem="string"
|
||||
Size="@AntSizeLDSType.Default"
|
||||
>
|
||||
<SelectOptions>
|
||||
@foreach (var kms in _kmsList)
|
||||
{
|
||||
<SelectOption TItem="string" TItemValue="string" Value="@kms.Id" Label="@kms.Name" />
|
||||
}
|
||||
</SelectOptions>
|
||||
</Select>
|
||||
</FormItem>
|
||||
}
|
||||
<FormItem Label=" " Style="margin-top:32px" WrapperCol="_submitFormLayout.WrapperCol">
|
||||
<Button Type="primary" HtmlType="submit">
|
||||
保存
|
||||
</Button>
|
||||
<Button OnClick="Back">
|
||||
返回
|
||||
</Button>
|
||||
</FormItem>
|
||||
@if (!string.IsNullOrEmpty(_errorMsg))
|
||||
{
|
||||
<Alert Type="@AlertType.Error"
|
||||
Message="错误"
|
||||
Description="@_errorMsg"
|
||||
ShowIcon="true" />
|
||||
}
|
||||
</Form>
|
||||
</Card>
|
||||
</ChildContent>
|
||||
</PageContainer>
|
||||
|
||||
|
||||
<style>
|
||||
.avatar-uploader > .ant-upload {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,107 +0,0 @@
|
||||
using AntDesign;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using AntSK.Domain.Repositories;
|
||||
using AntSK.Models;
|
||||
using System.IO;
|
||||
|
||||
namespace AntSK.Pages.AppPage
|
||||
{
|
||||
public partial class AddApp
|
||||
{
|
||||
[Parameter]
|
||||
public string AppId { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected IApps_Repositories _apps_Repositories { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected IKmss_Repositories _kmss_Repositories { get; set; }
|
||||
[Inject]
|
||||
protected NavigationManager NavigationManager { get; set; }
|
||||
|
||||
private Apps _appModel = new Apps() ;
|
||||
|
||||
IEnumerable <string> kmsIds;
|
||||
|
||||
private List<Kmss> _kmsList = new List<Kmss>();
|
||||
|
||||
|
||||
private string _errorMsg { get; set; }
|
||||
|
||||
private readonly FormItemLayout _formItemLayout = new FormItemLayout
|
||||
{
|
||||
LabelCol = new ColLayoutParam
|
||||
{
|
||||
Xs = new EmbeddedProperty { Span = 24 },
|
||||
Sm = new EmbeddedProperty { Span = 7 },
|
||||
},
|
||||
|
||||
WrapperCol = new ColLayoutParam
|
||||
{
|
||||
Xs = new EmbeddedProperty { Span = 24 },
|
||||
Sm = new EmbeddedProperty { Span = 12 },
|
||||
Md = new EmbeddedProperty { Span = 10 },
|
||||
}
|
||||
};
|
||||
private readonly FormItemLayout _submitFormLayout = new FormItemLayout
|
||||
{
|
||||
WrapperCol = new ColLayoutParam
|
||||
{
|
||||
Xs = new EmbeddedProperty { Span = 24, Offset = 0 },
|
||||
Sm = new EmbeddedProperty { Span = 10, Offset = 7 },
|
||||
}
|
||||
};
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
_kmsList = _kmss_Repositories.GetList();
|
||||
if (!string.IsNullOrEmpty(AppId))
|
||||
{
|
||||
//查看
|
||||
_appModel= _apps_Repositories.GetFirst(p => p.Id == AppId);
|
||||
kmsIds = _appModel.KmsIdList?.Split(",");
|
||||
}
|
||||
}
|
||||
private void HandleSubmit()
|
||||
{
|
||||
if (string.IsNullOrEmpty(AppId))
|
||||
{
|
||||
//新增
|
||||
_appModel.Id = Guid.NewGuid().ToString();
|
||||
//秘钥
|
||||
_appModel.SecretKey="sk-"+ Guid.NewGuid().ToString();
|
||||
if (_apps_Repositories.IsAny(p => p.Name == _appModel.Name))
|
||||
{
|
||||
_errorMsg = "名称已存在!";
|
||||
return;
|
||||
}
|
||||
|
||||
if (kmsIds != null && kmsIds.Count() > 0)
|
||||
{
|
||||
_appModel.KmsIdList = string.Join(",", kmsIds);
|
||||
}
|
||||
|
||||
_apps_Repositories.Insert(_appModel);
|
||||
}
|
||||
else {
|
||||
//修改
|
||||
if (kmsIds != null && kmsIds.Count() > 0)
|
||||
{
|
||||
_appModel.KmsIdList = string.Join(",", kmsIds);
|
||||
}
|
||||
|
||||
_apps_Repositories.Update(_appModel);
|
||||
}
|
||||
|
||||
|
||||
//NavigationManager.NavigateTo($"/app/detail/{_appModel.Id}");
|
||||
NavigationManager.NavigateTo($"/applist");
|
||||
}
|
||||
|
||||
|
||||
private void Back() {
|
||||
NavigationManager.NavigateTo("/applist");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
@namespace AntSK.Pages.ChatPage
|
||||
@using AntSK.Domain.Repositories
|
||||
@using AntSK.Models
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@page "/Chat"
|
||||
@page "/Chat/{AppId}"
|
||||
@using AntSK.Services.Auth
|
||||
@inherits AuthComponentBase
|
||||
|
||||
<GridRow Gutter="(16, 16)">
|
||||
<GridCol Span="12">
|
||||
<Spin Size="large" Tip="请稍等..." Spinning="@(_loading)">
|
||||
<Card Style="height:800px;overflow: auto;">
|
||||
<TitleTemplate>
|
||||
<Icon Type="setting" /> 选择应用
|
||||
<Select DataSource="@_list"
|
||||
@bind-Value="@AppId"
|
||||
DefaultValue="@("lucy")"
|
||||
ValueProperty="c=>c.Id"
|
||||
LabelProperty="c=>c.Name"
|
||||
Style="width:200px">
|
||||
</Select>
|
||||
</TitleTemplate>
|
||||
<Body>
|
||||
<div id="scrollDiv" style="height: 530px; overflow-y: auto; overflow-x: hidden;">
|
||||
<GridRow Gutter="(8, 8)">
|
||||
<Virtualize Items="@(MessageList.OrderByDescending(o => o.CreateTime).ToList())" Context="item">
|
||||
<GridCol Span="24">
|
||||
<Card Size="small">
|
||||
<TitleTemplate>
|
||||
<Text Strong><Icon Type="bulb" /> @(item.Questions)</Text>
|
||||
</TitleTemplate>
|
||||
<Extra>
|
||||
<Space>
|
||||
<SpaceItem>
|
||||
<a style="color: gray;" @onclick="@(() => OnCopyAsync(item))"><Icon Type="copy" /></a>
|
||||
</SpaceItem>
|
||||
<SpaceItem>
|
||||
<a style="color: gray;" @onclick="@(() => OnClearAsync(item.ID))"><Icon Type="rest" /></a>
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
</Extra>
|
||||
<Body>
|
||||
@((MarkupString)(item.HtmlAnswers))
|
||||
</Body>
|
||||
</Card>
|
||||
</GridCol>
|
||||
</Virtualize>
|
||||
</GridRow>
|
||||
</div>
|
||||
<div style="height: 10px;"></div>
|
||||
<AntDesign.Input @bind-Value="@(_messageInput)" DebounceMilliseconds="@(-1)" Placeholder="输入消息回车发送" OnPressEnter="@(async () => await OnSendAsync())" Disabled="@Sendding">
|
||||
<Suffix>
|
||||
<Button Icon="send" Type="@(ButtonType.Link)" OnClick="@(async () => await OnSendAsync())" Disabled="@Sendding"></Button>
|
||||
</Suffix>
|
||||
</AntDesign.Input>
|
||||
</Body>
|
||||
</Card>
|
||||
</Spin>
|
||||
</GridCol>
|
||||
<GridCol Span="12">
|
||||
<Card Style="height: 800px;overflow: auto;">
|
||||
<TitleTemplate>
|
||||
<Icon Type="search" /> 调试结果
|
||||
</TitleTemplate>
|
||||
<Extra>
|
||||
|
||||
</Extra>
|
||||
<Body>
|
||||
<AntList Bordered DataSource="@RelevantSources">
|
||||
<ChildContent Context="item">
|
||||
<span> <b>@item.SourceName </b> 相似度:<Text Mark> @item.Relevance</Text></span>
|
||||
<Body>
|
||||
@((MarkupString)(@item.Text))
|
||||
</Body>
|
||||
</ChildContent>
|
||||
</AntList>
|
||||
</Body>
|
||||
</Card>
|
||||
</GridCol>
|
||||
</GridRow>
|
||||
|
||||
|
||||
@code {
|
||||
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
using AntDesign;
|
||||
using AntSK.Domain.Model;
|
||||
using AntSK.Domain.Repositories;
|
||||
using AntSK.Domain.Utils;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Core;
|
||||
using DocumentFormat.OpenXml.EMMA;
|
||||
using MarkdownSharp;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.KernelMemory;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using Newtonsoft.Json;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace AntSK.Pages.ChatPage
|
||||
{
|
||||
public partial class Chat
|
||||
{
|
||||
[Parameter]
|
||||
public string AppId { get; set; }
|
||||
[Inject]
|
||||
protected MessageService? Message { get; set; }
|
||||
[Inject]
|
||||
protected IApps_Repositories _apps_Repositories { get; set; }
|
||||
[Inject]
|
||||
protected IKmss_Repositories _kmss_Repositories { get; set; }
|
||||
[Inject]
|
||||
protected IKmsDetails_Repositories _kmsDetails_Repositories { get; set; }
|
||||
[Inject]
|
||||
protected MemoryServerless _memory { get; set; }
|
||||
[Inject]
|
||||
protected Kernel _kernel { get; set; }
|
||||
|
||||
protected bool _loading = false;
|
||||
protected List<MessageInfo> MessageList = [];
|
||||
protected string? _messageInput;
|
||||
protected string _json = "";
|
||||
protected bool Sendding = false;
|
||||
|
||||
List<RelevantSource> RelevantSources = new List<RelevantSource>();
|
||||
|
||||
protected List<Apps> _list = new List<Apps>();
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
_list= _apps_Repositories.GetList();
|
||||
}
|
||||
protected async Task OnSendAsync()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_messageInput))
|
||||
{
|
||||
_ = Message.Info("请输入消息", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(AppId))
|
||||
{
|
||||
_ = Message.Info("请选择应用进行测试", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
Sendding = true;
|
||||
await SendAsync(_messageInput);
|
||||
_messageInput = "";
|
||||
Sendding = false;
|
||||
|
||||
}
|
||||
protected async Task OnCopyAsync(MessageInfo item)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
_messageInput = item.Questions;
|
||||
});
|
||||
}
|
||||
|
||||
protected async Task OnClearAsync(string id)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
MessageList = MessageList.Where(w => w.ID != id).ToList();
|
||||
});
|
||||
}
|
||||
|
||||
protected async Task<bool> SendAsync(string questions)
|
||||
{
|
||||
string msg = questions;
|
||||
//处理多轮会话
|
||||
if (MessageList.Count > 0)
|
||||
{
|
||||
msg = await HistorySummarize(questions);
|
||||
}
|
||||
|
||||
Apps app=_apps_Repositories.GetFirst(p => p.Id == AppId);
|
||||
switch (app.Type)
|
||||
{
|
||||
case "chat":
|
||||
//普通会话
|
||||
await SendChat(questions, msg, app);
|
||||
break;
|
||||
case "kms":
|
||||
//知识库问答
|
||||
await SendKms(questions, msg, app);
|
||||
break;
|
||||
}
|
||||
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送知识库问答
|
||||
/// </summary>
|
||||
/// <param name="questions"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
private async Task SendKms(string questions, string msg, Apps app)
|
||||
{
|
||||
//知识库问答
|
||||
var filters = new List<MemoryFilter>();
|
||||
|
||||
var kmsidList = app.KmsIdList.Split(",");
|
||||
foreach (var kmsid in kmsidList)
|
||||
{
|
||||
filters.Add(new MemoryFilter().ByTag("kmsid", kmsid));
|
||||
}
|
||||
|
||||
var kmsResult = await _memory.AskAsync(msg, index: "kms", filters: filters);
|
||||
if (kmsResult != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(kmsResult.Result))
|
||||
{
|
||||
string answers = kmsResult.Result;
|
||||
var markdown = new Markdown();
|
||||
string htmlAnswers = markdown.Transform(answers);
|
||||
var info1 = new MessageInfo()
|
||||
{
|
||||
ID = Guid.NewGuid().ToString(),
|
||||
Questions = questions,
|
||||
Answers = answers,
|
||||
HtmlAnswers = htmlAnswers,
|
||||
CreateTime = DateTime.Now,
|
||||
};
|
||||
MessageList.Add(info1);
|
||||
}
|
||||
|
||||
foreach (var x in kmsResult.RelevantSources)
|
||||
{
|
||||
foreach (var xsd in x.Partitions)
|
||||
{
|
||||
var markdown = new Markdown();
|
||||
string sourceName = x.SourceName;
|
||||
var fileDetail = _kmsDetails_Repositories.GetFirst(p => p.FileGuidName == x.SourceName);
|
||||
if (fileDetail.IsNotNull())
|
||||
{
|
||||
sourceName = fileDetail.FileName;
|
||||
}
|
||||
RelevantSources.Add(new RelevantSource() { SourceName = sourceName, Text = markdown.Transform(xsd.Text), Relevance = xsd.Relevance });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送普通对话
|
||||
/// </summary>
|
||||
/// <param name="questions"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
private async Task SendChat(string questions, string msg, Apps app)
|
||||
{
|
||||
if (string.IsNullOrEmpty(app.Prompt))
|
||||
{
|
||||
//如果模板为空,给默认提示词
|
||||
app.Prompt = "{{$input}}";
|
||||
}
|
||||
var promptTemplateFactory = new KernelPromptTemplateFactory();
|
||||
var promptTemplate = promptTemplateFactory.Create(new PromptTemplateConfig(app.Prompt));
|
||||
var renderedPrompt = await promptTemplate.RenderAsync(_kernel);
|
||||
|
||||
var func = _kernel.CreateFunctionFromPrompt(app.Prompt, new OpenAIPromptExecutionSettings());
|
||||
var chatResult = _kernel.InvokeStreamingAsync<StreamingChatMessageContent>(function: func, arguments: new KernelArguments() { ["input"] = msg });
|
||||
MessageInfo info = null;
|
||||
var markdown = new Markdown();
|
||||
await foreach (var content in chatResult)
|
||||
{
|
||||
if (info == null)
|
||||
{
|
||||
info = new MessageInfo();
|
||||
info.ID = Guid.NewGuid().ToString();
|
||||
info.Questions = questions;
|
||||
info.Answers = content.Content!;
|
||||
info.HtmlAnswers = content.Content!;
|
||||
info.CreateTime = DateTime.Now;
|
||||
|
||||
MessageList.Add(info);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.HtmlAnswers += content.Content;
|
||||
await Task.Delay(50);
|
||||
}
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
//全部处理完后再处理一次Markdown
|
||||
info!.HtmlAnswers = markdown.Transform(info.HtmlAnswers);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 历史会话的会话总结
|
||||
/// </summary>
|
||||
/// <param name="questions"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> HistorySummarize(string questions)
|
||||
{
|
||||
StringBuilder history = new StringBuilder();
|
||||
foreach (var item in MessageList)
|
||||
{
|
||||
history.Append($"user:{item.Questions}{Environment.NewLine}");
|
||||
history.Append($"assistant:{item.Answers}{Environment.NewLine}");
|
||||
}
|
||||
|
||||
KernelFunction sunFun = _kernel.Plugins.GetFunction("ConversationSummaryPlugin", "SummarizeConversation");
|
||||
var summary = await _kernel.InvokeAsync(sunFun, new() { ["input"] = $"内容是:{history.ToString()} {Environment.NewLine} 请注意用中文总结" });
|
||||
string his = summary.GetValue<string>();
|
||||
var msg = $"历史对话:{his}{Environment.NewLine} 用户问题:{Environment.NewLine}{questions}"; ;
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
public class RelevantSource
|
||||
{
|
||||
public string SourceName { get; set; }
|
||||
|
||||
public string Text { get; set; }
|
||||
public float Relevance { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
@namespace AntSK.Pages.ChatPage
|
||||
@using AntSK.Domain.Repositories
|
||||
@using AntSK.Models
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@page "/OpenChat/{AppId}"
|
||||
@layout OpenLayout
|
||||
|
||||
<div id="chat" style="display:flex; flex-direction:column; height:100%; overflow-x:hidden;">
|
||||
<PageHeader Class="site-page-header" Title="@app.Name" Subtitle="@app.Describe" />
|
||||
<div id="scrollDiv" style="flex:1; width:100%; overflow-y:auto; overflow-x:hidden;padding:10px;">
|
||||
<Virtualize Items="@(MessageList.OrderByDescending(o => o.CreateTime).ToList())" Context="item">
|
||||
<GridCol Span="24">
|
||||
<Card>
|
||||
<TitleTemplate>
|
||||
<Text Strong><Icon Type="bulb" />@(item.Questions)</Text>
|
||||
</TitleTemplate>
|
||||
<Extra>
|
||||
<Space>
|
||||
<SpaceItem>
|
||||
<a style="color: gray;" @onclick="@(() => OnCopyAsync(item))"><Icon Type="copy" /></a>
|
||||
</SpaceItem>
|
||||
<SpaceItem>
|
||||
<a style="color: gray;" @onclick="@(() => OnClearAsync(item.ID))"><Icon Type="rest" /></a>
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
</Extra>
|
||||
<Body>
|
||||
@((MarkupString)(item.HtmlAnswers))
|
||||
</Body>
|
||||
</Card>
|
||||
</GridCol>
|
||||
</Virtualize>
|
||||
</div>
|
||||
<div style="flex-shrink:0;margin:10px;">
|
||||
<AntDesign.Input @bind-Value="@(_messageInput)" DebounceMilliseconds="@(-1)" Placeholder="输入消息回车发送" OnPressEnter="@(async () => await OnSendAsync())" Disabled="@Sendding">
|
||||
<Suffix>
|
||||
<Button Icon="send" Type="@(ButtonType.Link)" OnClick="@(async () => await OnSendAsync())" Disabled="@Sendding"></Button>
|
||||
</Suffix>
|
||||
</AntDesign.Input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
using AntDesign;
|
||||
using AntSK.Domain.Model;
|
||||
using AntSK.Domain.Repositories;
|
||||
using AntSK.Domain.Utils;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Core;
|
||||
using DocumentFormat.OpenXml.EMMA;
|
||||
using MarkdownSharp;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.KernelMemory;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using Newtonsoft.Json;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace AntSK.Pages.ChatPage
|
||||
{
|
||||
public partial class OpenChat
|
||||
{
|
||||
[Parameter]
|
||||
public string AppId { get; set; }
|
||||
[Inject]
|
||||
protected MessageService? Message { get; set; }
|
||||
[Inject]
|
||||
protected IApps_Repositories _apps_Repositories { get; set; }
|
||||
[Inject]
|
||||
protected IKmss_Repositories _kmss_Repositories { get; set; }
|
||||
[Inject]
|
||||
protected IKmsDetails_Repositories _kmsDetails_Repositories { get; set; }
|
||||
[Inject]
|
||||
protected MemoryServerless _memory { get; set; }
|
||||
[Inject]
|
||||
protected Kernel _kernel { get; set; }
|
||||
|
||||
protected bool _loading = false;
|
||||
protected List<MessageInfo> MessageList = [];
|
||||
protected string? _messageInput;
|
||||
protected string _json = "";
|
||||
protected bool Sendding = false;
|
||||
|
||||
protected Apps app = new Apps();
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
app = _apps_Repositories.GetFirst(p=>p.Id==AppId);
|
||||
}
|
||||
protected async Task OnSendAsync()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_messageInput))
|
||||
{
|
||||
_ = Message.Info("请输入消息", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
Sendding = true;
|
||||
await SendAsync(_messageInput);
|
||||
_messageInput = "";
|
||||
Sendding = false;
|
||||
|
||||
}
|
||||
protected async Task OnCopyAsync(MessageInfo item)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
_messageInput = item.Questions;
|
||||
});
|
||||
}
|
||||
|
||||
protected async Task OnClearAsync(string id)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
MessageList = MessageList.Where(w => w.ID != id).ToList();
|
||||
});
|
||||
}
|
||||
|
||||
protected async Task<bool> SendAsync(string questions)
|
||||
{
|
||||
string msg = questions;
|
||||
//处理多轮会话
|
||||
if (MessageList.Count > 0)
|
||||
{
|
||||
msg = await HistorySummarize(questions);
|
||||
}
|
||||
|
||||
Apps app=_apps_Repositories.GetFirst(p => p.Id == AppId);
|
||||
switch (app.Type)
|
||||
{
|
||||
case "chat":
|
||||
//普通会话
|
||||
await SendChat(questions, msg, app);
|
||||
break;
|
||||
case "kms":
|
||||
//知识库问答
|
||||
await SendKms(questions, msg, app);
|
||||
break;
|
||||
}
|
||||
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送知识库问答
|
||||
/// </summary>
|
||||
/// <param name="questions"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
private async Task SendKms(string questions, string msg, Apps app)
|
||||
{
|
||||
//知识库问答
|
||||
var filters = new List<MemoryFilter>();
|
||||
|
||||
var kmsidList = app.KmsIdList.Split(",");
|
||||
foreach (var kmsid in kmsidList)
|
||||
{
|
||||
filters.Add(new MemoryFilter().ByTag("kmsid", kmsid));
|
||||
}
|
||||
|
||||
var kmsResult = await _memory.AskAsync(msg, index: "kms", filters: filters);
|
||||
if (kmsResult != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(kmsResult.Result))
|
||||
{
|
||||
string answers = kmsResult.Result;
|
||||
var markdown = new Markdown();
|
||||
string htmlAnswers = markdown.Transform(answers);
|
||||
var info1 = new MessageInfo()
|
||||
{
|
||||
ID = Guid.NewGuid().ToString(),
|
||||
Questions = questions,
|
||||
Answers = answers,
|
||||
HtmlAnswers = htmlAnswers,
|
||||
CreateTime = DateTime.Now,
|
||||
};
|
||||
MessageList.Add(info1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送普通对话
|
||||
/// </summary>
|
||||
/// <param name="questions"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
private async Task SendChat(string questions, string msg, Apps app)
|
||||
{
|
||||
if (string.IsNullOrEmpty(app.Prompt))
|
||||
{
|
||||
//如果模板为空,给默认提示词
|
||||
app.Prompt = "{{$input}}";
|
||||
}
|
||||
var promptTemplateFactory = new KernelPromptTemplateFactory();
|
||||
var promptTemplate = promptTemplateFactory.Create(new PromptTemplateConfig(app.Prompt));
|
||||
var renderedPrompt = await promptTemplate.RenderAsync(_kernel);
|
||||
|
||||
var func = _kernel.CreateFunctionFromPrompt(app.Prompt, new OpenAIPromptExecutionSettings());
|
||||
var chatResult = _kernel.InvokeStreamingAsync<StreamingChatMessageContent>(function: func, arguments: new KernelArguments() { ["input"] = msg });
|
||||
MessageInfo info = null;
|
||||
var markdown = new Markdown();
|
||||
await foreach (var content in chatResult)
|
||||
{
|
||||
if (info == null)
|
||||
{
|
||||
info = new MessageInfo();
|
||||
info.ID = Guid.NewGuid().ToString();
|
||||
info.Questions = questions;
|
||||
info.Answers = content.Content!;
|
||||
info.HtmlAnswers = content.Content!;
|
||||
info.CreateTime = DateTime.Now;
|
||||
|
||||
MessageList.Add(info);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.HtmlAnswers += content.Content;
|
||||
await Task.Delay(50);
|
||||
}
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
//全部处理完后再处理一次Markdown
|
||||
info!.HtmlAnswers = markdown.Transform(info.HtmlAnswers);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 历史会话的会话总结
|
||||
/// </summary>
|
||||
/// <param name="questions"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> HistorySummarize(string questions)
|
||||
{
|
||||
StringBuilder history = new StringBuilder();
|
||||
foreach (var item in MessageList)
|
||||
{
|
||||
history.Append($"user:{item.Questions}{Environment.NewLine}");
|
||||
history.Append($"assistant:{item.Answers}{Environment.NewLine}");
|
||||
}
|
||||
|
||||
KernelFunction sunFun = _kernel.Plugins.GetFunction("ConversationSummaryPlugin", "SummarizeConversation");
|
||||
var summary = await _kernel.InvokeAsync(sunFun, new() { ["input"] = $"内容是:{history.ToString()} {Environment.NewLine} 请注意用中文总结" });
|
||||
string his = summary.GetValue<string>();
|
||||
var msg = $"历史对话:{his}{Environment.NewLine} 用户问题:{Environment.NewLine}{questions}"; ;
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
.ant-card-body {
|
||||
height: 90% !important;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
@namespace AntSK.Pages.Exception
|
||||
@page "/exception/404"
|
||||
|
||||
<Result Status="404"
|
||||
Title="404"
|
||||
SubTitle="Sorry, the page you visited does not exist.">
|
||||
<Extra>
|
||||
<Button Type="primary">Back Home</Button>
|
||||
</Extra>
|
||||
</Result>
|
||||
@@ -1,29 +0,0 @@
|
||||
@namespace AntSK.Pages
|
||||
@using MarkdownSharp
|
||||
@page "/"
|
||||
@using AntSK.Services.Auth
|
||||
@inherits AuthComponentBase
|
||||
|
||||
<Body>
|
||||
@((MarkupString)(body))
|
||||
</Body>
|
||||
|
||||
@code {
|
||||
private string body = new Markdown().Transform(@"非常感谢您对**AntSK**的喜爱,您的支持对我来说是莫大的鼓励。
|
||||
|
||||
如果您对技术类视频感兴趣,欢迎关注我的B站账号,获取更多精彩内容。
|
||||
|
||||
- **Bilibili账号**:[点击这里](https://space.bilibili.com/1673184683/channel/series)
|
||||
|
||||
同时,如果您感兴趣,可以访问我的GitHub页面,查看更多开源项目和代码:
|
||||
|
||||
- **GitHub页面**:[点击这里](https://github.com/xuzeyu91)
|
||||
|
||||
另外,如果您想加入由我创建的**.Net/AI应用开发微信交流群**,欢迎先添加我的微信**(xuzeyu91)**。
|
||||
|
||||
发送“进群请求”,我将会把您邀请进群。
|
||||
|
||||
期待与您在线上交流技术,共同进步!");
|
||||
|
||||
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
@namespace AntSK.Pages.KmsPage
|
||||
@using AntSK.Domain.Repositories
|
||||
@using AntSK.Models
|
||||
@page "/Kms/Add"
|
||||
@inject IMessageService _message
|
||||
@using AntSK.Services.Auth
|
||||
@inherits AuthComponentBase
|
||||
|
||||
<PageContainer Title="新增知识库">
|
||||
<ChildContent>
|
||||
<Card>
|
||||
<Form
|
||||
Model="@_kmsModel"
|
||||
Style="margin-top: 8px;"
|
||||
OnFinish="HandleSubmit">
|
||||
<FormItem Label="知识库名称" LabelCol="_formItemLayout.LabelCol" WrapperCol="_formItemLayout.WrapperCol">
|
||||
<Input Placeholder="请输入知识库名称" @bind-Value="@context.Name" />
|
||||
</FormItem>
|
||||
<FormItem Label="图标" LabelCol="_formItemLayout.LabelCol" WrapperCol="_formItemLayout.WrapperCol">
|
||||
<Input Placeholder="请输入图标" @bind-Value="@context.Icon" />
|
||||
<a href="https://antblazor.com/zh-CN/components/icon" target="_blank">图标库</a>
|
||||
</FormItem>
|
||||
<FormItem Label="描述" LabelCol="_formItemLayout.LabelCol" WrapperCol="_formItemLayout.WrapperCol">
|
||||
<Input Placeholder="请输入描述" @bind-Value="@context.Describe" />
|
||||
</FormItem>
|
||||
<FormItem Label=" " Style="margin-top:32px" WrapperCol="_submitFormLayout.WrapperCol">
|
||||
<Button Type="primary" HtmlType="submit">
|
||||
保存
|
||||
</Button>
|
||||
</FormItem>
|
||||
@if ( !string.IsNullOrEmpty(_errorMsg))
|
||||
{
|
||||
<Alert Type="@AlertType.Error"
|
||||
Message="错误"
|
||||
Description="@_errorMsg"
|
||||
ShowIcon="true"
|
||||
/>
|
||||
}
|
||||
</Form>
|
||||
</Card>
|
||||
</ChildContent>
|
||||
</PageContainer>
|
||||
|
||||
|
||||
<style>
|
||||
.avatar-uploader > .ant-upload {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,60 +0,0 @@
|
||||
using AntDesign;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using AntSK.Domain.Repositories;
|
||||
using AntSK.Models;
|
||||
using System.IO;
|
||||
|
||||
namespace AntSK.Pages.KmsPage
|
||||
{
|
||||
|
||||
public partial class AddKms
|
||||
{
|
||||
[Inject]
|
||||
protected IKmss_Repositories _kmss_Repositories { get; set; }
|
||||
[Inject]
|
||||
protected NavigationManager NavigationManager { get; set; }
|
||||
|
||||
private string _errorMsg { get; set; }
|
||||
|
||||
private readonly Kmss _kmsModel = new Kmss() ;
|
||||
|
||||
private readonly FormItemLayout _formItemLayout = new FormItemLayout
|
||||
{
|
||||
LabelCol = new ColLayoutParam
|
||||
{
|
||||
Xs = new EmbeddedProperty { Span = 24 },
|
||||
Sm = new EmbeddedProperty { Span = 7 },
|
||||
},
|
||||
|
||||
WrapperCol = new ColLayoutParam
|
||||
{
|
||||
Xs = new EmbeddedProperty { Span = 24 },
|
||||
Sm = new EmbeddedProperty { Span = 12 },
|
||||
Md = new EmbeddedProperty { Span = 10 },
|
||||
}
|
||||
};
|
||||
private readonly FormItemLayout _submitFormLayout = new FormItemLayout
|
||||
{
|
||||
WrapperCol = new ColLayoutParam
|
||||
{
|
||||
Xs = new EmbeddedProperty { Span = 24, Offset = 0 },
|
||||
Sm = new EmbeddedProperty { Span = 10, Offset = 7 },
|
||||
}
|
||||
};
|
||||
|
||||
private void HandleSubmit()
|
||||
{
|
||||
_kmsModel.Id = Guid.NewGuid().ToString();
|
||||
if (_kmss_Repositories.IsAny(p => p.Name == _kmsModel.Name))
|
||||
{
|
||||
_errorMsg = "名称已存在!";
|
||||
return;
|
||||
}
|
||||
|
||||
_kmss_Repositories.Insert(_kmsModel);
|
||||
|
||||
NavigationManager.NavigateTo("/kmslist");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
@namespace AntSK.Pages.KmsPage
|
||||
@using AntSK.Domain.Repositories
|
||||
@using System.ComponentModel.DataAnnotations
|
||||
@page "/Kms/Detail/{KmsID}"
|
||||
@inject NavigationManager NavigationManager
|
||||
@using AntSK.Services.Auth
|
||||
@inherits AuthComponentBase
|
||||
|
||||
<div>
|
||||
<PageContainer Title="知识库文档">
|
||||
<ChildContent>
|
||||
<div class="standardList">
|
||||
<Card Class="listCard"
|
||||
Title="知识库文档"
|
||||
Style="margin-top: 24px;"
|
||||
BodyStyle="padding: 0 32px 40px 32px">
|
||||
|
||||
<Extra>
|
||||
<Dropdown Style="position: absolute; right: 20px; margin-bottom: 8px;">
|
||||
<Overlay>
|
||||
<Menu>
|
||||
@( _fileUpload( () =>FileShowModal()))
|
||||
@(_urlUpload(() => UrlShowModal()))
|
||||
</Menu>
|
||||
</Overlay>
|
||||
<ChildContent>
|
||||
<Button>导入 <Icon Type="down" /></Button>
|
||||
</ChildContent>
|
||||
</Dropdown>
|
||||
<div class="extraContent" style="margin-right:100px;">
|
||||
<Search Class="extraContentSearch" Placeholder="搜索文档" @bind-Value="_model.Id" />
|
||||
</div>
|
||||
|
||||
</Extra>
|
||||
<ChildContent >
|
||||
<AntList TItem="KmsDetails"
|
||||
DataSource="_data"
|
||||
ItemLayout="ListItemLayout.Horizontal">
|
||||
<ListItem Actions="@(new[] {
|
||||
detail(()=> FileDetail(context.Id)) ,
|
||||
delete(async ()=>await DeleteFile(context.Id)) ,
|
||||
})">
|
||||
<ListItemMeta Description="@context.Id">
|
||||
<TitleTemplate>
|
||||
<div >文件ID</div>
|
||||
</TitleTemplate>
|
||||
</ListItemMeta>
|
||||
<ListItemMeta Description="@context.Type">
|
||||
<TitleTemplate>
|
||||
<div>文件类型</div>
|
||||
</TitleTemplate>
|
||||
</ListItemMeta>
|
||||
@if(@context.Type=="file")
|
||||
{
|
||||
<ListItemMeta Avatar="" Description="@context.FileName">
|
||||
<TitleTemplate>
|
||||
<a >文件名称</a>
|
||||
</TitleTemplate>
|
||||
</ListItemMeta>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ListItemMeta Avatar="" Description="@context.Url">
|
||||
<TitleTemplate>
|
||||
<a href="@context.Url" target="_blank">Url</a>
|
||||
</TitleTemplate>
|
||||
</ListItemMeta>
|
||||
}
|
||||
|
||||
<ListItemMeta Avatar="" Description="@context.DataCount.ToString()">
|
||||
<TitleTemplate>
|
||||
<a >文档切片数量</a>
|
||||
</TitleTemplate>
|
||||
</ListItemMeta>
|
||||
<div class="listContent">
|
||||
<div class="listContentItem">
|
||||
<span>创建时间</span>
|
||||
<p>@context.CreateTime.ToString("yyyy-MM-dd HH:mm")</p>
|
||||
</div>
|
||||
</div>
|
||||
</ListItem>
|
||||
</AntList>
|
||||
</ChildContent>
|
||||
</Card>
|
||||
</div>
|
||||
</ChildContent>
|
||||
</PageContainer>
|
||||
</div>
|
||||
|
||||
<Modal Title="链接读取"
|
||||
Visible="@_urlVisible"
|
||||
OnOk="@UrlHandleOk"
|
||||
OnCancel="@UrlHandleCancel"
|
||||
ConfirmLoading="@_urlConfirmLoading">
|
||||
<Form Model="@urlModel"
|
||||
LabelColSpan="8"
|
||||
WrapperColSpan="16"
|
||||
@ref="@_urlForm">
|
||||
<FormItem Label="URL地址">
|
||||
<Input @bind-Value="@context.Url" />
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
<Modal Title="文件导入"
|
||||
Visible="@_fileVisible"
|
||||
OnOk="@FileHandleOk"
|
||||
OnCancel="@FileHandleCancel"
|
||||
ConfirmLoading="@_fileConfirmLoading">
|
||||
<Upload Action="@("api/File/UploadFile")"
|
||||
Name="file"
|
||||
Drag
|
||||
Multiple
|
||||
Accept="text/plain,
|
||||
application/msword,
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.document,
|
||||
application/vnd.ms-excel,
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,
|
||||
application/vnd.ms-powerpoint,
|
||||
application/vnd.openxmlformats-officedocument.presentationml.presentation,
|
||||
application/pdf,
|
||||
application/json,
|
||||
text/markdown"
|
||||
BeforeUpload="BeforeUpload"
|
||||
OnSingleCompleted="OnSingleCompleted">
|
||||
<p class="ant-upload-drag-icon">
|
||||
<Icon Type="inbox" />
|
||||
</p>
|
||||
<p class="ant-upload-text">单击或拖动文件到此区域进行上传</p>
|
||||
<p class="ant-upload-hint">
|
||||
支持txt、word、pdf、md、excel、ppt等文件。
|
||||
</p>
|
||||
</Upload>
|
||||
</Modal>
|
||||
|
||||
|
||||
@code {
|
||||
|
||||
RenderFragment _fileUpload(Action clickAction) =>@<MenuItem>
|
||||
<a target="_blank" rel="noopener noreferrer" @onclick="@clickAction">
|
||||
文件导入
|
||||
</a>
|
||||
</MenuItem>;
|
||||
|
||||
RenderFragment _urlUpload(Action clickAction) =>@<MenuItem>
|
||||
<a target="_blank" rel="noopener noreferrer" @onclick="@clickAction">
|
||||
链接读取
|
||||
</a>
|
||||
</MenuItem>;
|
||||
|
||||
RenderFragment detail(Action clickAction) => @<a key="detail" @onclick="@clickAction">详情</a>;
|
||||
RenderFragment delete(Action clickAction) => @<a key="edit" @onclick="@clickAction">删除</a>;
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
using AntDesign;
|
||||
using AntSK.Domain.Domain.Dto;
|
||||
using AntSK.Domain.Domain.Interface;
|
||||
using AntSK.Domain.Repositories;
|
||||
using AntSK.Domain.Utils;
|
||||
using AntSK.Models;
|
||||
using AntSK.Services;
|
||||
using DocumentFormat.OpenXml.Office2010.Excel;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using DocumentFormat.OpenXml.Vml.Spreadsheet;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.KernelMemory;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Policy;
|
||||
|
||||
namespace AntSK.Pages.KmsPage
|
||||
{
|
||||
public partial class KmsDetail
|
||||
{
|
||||
[Parameter]
|
||||
public string KmsId { get; set; }
|
||||
|
||||
private readonly KmsDetails _model = new KmsDetails();
|
||||
|
||||
bool _urlVisible = false;
|
||||
bool _urlConfirmLoading = false;
|
||||
|
||||
bool _fileVisible = false;
|
||||
bool _fileConfirmLoading = false;
|
||||
|
||||
string filePath;
|
||||
string fileName;
|
||||
|
||||
private Form<UrlModel> _urlForm;
|
||||
private UrlModel urlModel = new UrlModel();
|
||||
|
||||
private readonly IDictionary<string, ProgressStatus> _pStatus = new Dictionary<string, ProgressStatus>
|
||||
{
|
||||
{"active", ProgressStatus.Active},
|
||||
{"exception", ProgressStatus.Exception},
|
||||
{"normal", ProgressStatus.Normal},
|
||||
{"success", ProgressStatus.Success}
|
||||
};
|
||||
|
||||
private List<KmsDetails> _data =new List<KmsDetails>();
|
||||
|
||||
[Inject]
|
||||
protected IConfirmService _confirmService { get; set; }
|
||||
[Inject]
|
||||
protected IKmsDetails_Repositories _kmsDetails_Repositories { get; set; }
|
||||
[Inject]
|
||||
protected MemoryServerless _memory { get; set; }
|
||||
[Inject]
|
||||
protected IKMService iKMService { get; set; }
|
||||
[Inject]
|
||||
protected MessageService? _message { get; set; }
|
||||
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
_data =await _kmsDetails_Repositories.GetListAsync(p => p.KmsId == KmsId);
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据文档ID获取文档
|
||||
/// </summary>
|
||||
/// <param name="fileid"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
#region Url
|
||||
public class UrlModel
|
||||
{
|
||||
[Required]
|
||||
public string Url { get; set; }
|
||||
}
|
||||
private async Task UrlHandleOk(MouseEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_urlConfirmLoading = true;
|
||||
string fileid = Guid.NewGuid().ToString();
|
||||
await _memory.ImportWebPageAsync(urlModel.Url, fileid, new TagCollection() { { "kmsid", KmsId } }
|
||||
, index: "kms");
|
||||
//查询文档数量
|
||||
var docTextList =await iKMService.GetDocumentByFileID(fileid);
|
||||
|
||||
KmsDetails detial = new KmsDetails()
|
||||
{
|
||||
Id = fileid,
|
||||
KmsId = KmsId,
|
||||
Type = "url",
|
||||
Url = urlModel.Url,
|
||||
DataCount= docTextList.Count,
|
||||
CreateTime=DateTime.Now
|
||||
};
|
||||
await _kmsDetails_Repositories.InsertAsync(detial);
|
||||
_data = await _kmsDetails_Repositories.GetListAsync(p => p.KmsId == KmsId);
|
||||
|
||||
_urlVisible = false;
|
||||
_urlConfirmLoading = false;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message+" ---- "+ex.StackTrace);
|
||||
}
|
||||
}
|
||||
private void UrlHandleCancel(MouseEventArgs e)
|
||||
{
|
||||
_urlVisible = false;
|
||||
}
|
||||
private void UrlShowModal()
|
||||
{
|
||||
_urlVisible = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region File
|
||||
|
||||
|
||||
private async Task FileHandleOk(MouseEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_fileConfirmLoading = true;
|
||||
string fileid = Guid.NewGuid().ToString();
|
||||
//上传文档
|
||||
await _memory.ImportDocumentAsync(new Document(fileid)
|
||||
.AddFile(filePath)
|
||||
.AddTag("kmsid", KmsId)
|
||||
, index: "kms");
|
||||
//查询文档数量
|
||||
var docTextList = await iKMService.GetDocumentByFileID(fileid);
|
||||
string fileGuidName = Path.GetFileName(filePath);
|
||||
KmsDetails detial = new KmsDetails()
|
||||
{
|
||||
Id = fileid,
|
||||
KmsId = KmsId,
|
||||
Type = "file",
|
||||
FileName = fileName,
|
||||
FileGuidName= fileGuidName,
|
||||
DataCount = docTextList.Count,
|
||||
CreateTime = DateTime.Now
|
||||
};
|
||||
await _kmsDetails_Repositories.InsertAsync(detial);
|
||||
_data = await _kmsDetails_Repositories.GetListAsync(p => p.KmsId == KmsId);
|
||||
|
||||
_fileVisible = false;
|
||||
_fileConfirmLoading = false;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
|
||||
}
|
||||
}
|
||||
private void FileHandleCancel(MouseEventArgs e)
|
||||
{
|
||||
_fileVisible = false;
|
||||
}
|
||||
private void FileShowModal()
|
||||
{
|
||||
_fileVisible = true;
|
||||
}
|
||||
|
||||
bool BeforeUpload(UploadFileItem file)
|
||||
{
|
||||
List<string> types = new List<string>() {
|
||||
"text/plain",
|
||||
"application/msword",
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
"application/vnd.ms-excel",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
"application/vnd.ms-powerpoint",
|
||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||
"application/pdf",
|
||||
"application/json",
|
||||
"text/markdown"
|
||||
};
|
||||
var IsType = types.Contains( file.Type );
|
||||
if (!IsType)
|
||||
{
|
||||
_message.Error("文件格式错误,请重新选择!");
|
||||
}
|
||||
var IsLt500K = file.Size < 1024 *1024* 100;
|
||||
if (!IsLt500K)
|
||||
{
|
||||
_message.Error("文件需不大于100MB!");
|
||||
}
|
||||
|
||||
return IsType && IsLt500K;
|
||||
}
|
||||
private void OnSingleCompleted(UploadInfo fileinfo)
|
||||
{
|
||||
|
||||
if (fileinfo.File.State == UploadState.Success)
|
||||
{
|
||||
filePath=fileinfo.File.Url = fileinfo.File.Response;
|
||||
fileName= fileinfo.File.FileName;
|
||||
}
|
||||
}
|
||||
|
||||
private void FileDetail(string fileid)
|
||||
{
|
||||
NavigationManager.NavigateTo($"/kms/detaillist/{KmsId}/{fileid}");
|
||||
}
|
||||
|
||||
private async Task DeleteFile(string fileid)
|
||||
{
|
||||
try
|
||||
{
|
||||
var content = "是否确认删除此文档?";
|
||||
var title = "删除";
|
||||
var result = await _confirmService.Show(content, title, ConfirmButtons.YesNo);
|
||||
if (result == ConfirmResult.Yes)
|
||||
{
|
||||
var flag = await _kmsDetails_Repositories.DeleteAsync(fileid);
|
||||
if (flag)
|
||||
{
|
||||
await _memory.DeleteDocumentAsync(index: "kms", documentId: fileid);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_data = await _kmsDetails_Repositories.GetListAsync(p => p.KmsId == KmsId);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
@namespace AntSK.Pages.KmsPage
|
||||
@using AntSK.Domain.Repositories
|
||||
@using AntSK.Domain.Domain.Dto
|
||||
@page "/Kms/DetailList/{KmsID}/{FileId}"
|
||||
@inject NavigationManager NavigationManager
|
||||
@using AntSK.Services.Auth
|
||||
@inherits AuthComponentBase
|
||||
|
||||
|
||||
<Button Type="@ButtonType.Primary" OnClick="NavigateBack">返回</Button>
|
||||
<AntList DataSource="@_data" TItem="KMFile">
|
||||
<ListItem >
|
||||
<ListItemMeta Description="@context.Text">
|
||||
<TitleTemplate>
|
||||
<a>@context.LastUpdate</a>
|
||||
</TitleTemplate>
|
||||
</ListItemMeta>
|
||||
</ListItem>
|
||||
</AntList>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using AntSK.Domain.Domain.Dto;
|
||||
using AntSK.Domain.Domain.Interface;
|
||||
using DocumentFormat.OpenXml.Office2010.Excel;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AntSK.Pages.KmsPage
|
||||
{
|
||||
public partial class KmsDetailList
|
||||
{
|
||||
[Parameter]
|
||||
public string KmsId { get; set; }
|
||||
[Parameter]
|
||||
public string FileId { get; set; }
|
||||
|
||||
[Inject]
|
||||
protected IKMService iKMService { get; set; }
|
||||
|
||||
private List<KMFile> _data = new List<KMFile>() ;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
_data = await iKMService.GetDocumentByFileID(FileId);
|
||||
}
|
||||
|
||||
private void NavigateBack() {
|
||||
NavigationManager.NavigateTo($"/kms/detail/{KmsId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
@page "/"
|
||||
@namespace AntSK.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@{
|
||||
Layout = null;
|
||||
}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>AntSK</title>
|
||||
<base href="~/" />
|
||||
<link href="_content/AntDesign/css/ant-design-blazor.css" rel="stylesheet" />
|
||||
<link href="_content/AntDesign.ProLayout/css/ant-design-pro-layout-blazor.css" rel="stylesheet" />
|
||||
<link href="./css/site.css" rel="stylesheet" />
|
||||
<link href="AntSK.styles.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<app>
|
||||
<component type="typeof(App)" render-mode="Server" />
|
||||
</app>
|
||||
|
||||
<script type="text/javascript" src="@("https://unpkg.com/@antv/g2plot@2.4.17/dist/g2plot.min.js")"></script>
|
||||
<script src="_content/AntDesign/js/ant-design-blazor.js"></script>
|
||||
<script src="_content/AntDesign.Charts/ant-design-charts-blazor.js"></script>
|
||||
<script src="_framework/blazor.server.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
177
AntSK/Program.cs
@@ -1,177 +0,0 @@
|
||||
using AntDesign.ProLayout;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Unicode;
|
||||
using AntSK.Domain.Utils;
|
||||
using AntSK.Services;
|
||||
using AntSK.Domain.Common.DependencyInjection;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using System.Reflection;
|
||||
using AntSK.Domain.Options;
|
||||
using Microsoft.KernelMemory.ContentStorage.DevTools;
|
||||
using Microsoft.KernelMemory.FileSystem.DevTools;
|
||||
using Microsoft.KernelMemory;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.KernelMemory.Postgres;
|
||||
using AntSK.Domain.Repositories;
|
||||
using Microsoft.SemanticKernel.Plugins.Core;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using AntSK.Services.Auth;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
// Add services to the container.
|
||||
builder.Services.AddControllers().AddJsonOptions(config =>
|
||||
{
|
||||
//此设定解决JsonResult中文被编码的问题
|
||||
config.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
|
||||
|
||||
config.JsonSerializerOptions.Converters.Add(new DateTimeConverter());
|
||||
config.JsonSerializerOptions.Converters.Add(new DateTimeNullableConvert());
|
||||
});
|
||||
// Add services to the container.
|
||||
builder.Services.AddRazorPages();
|
||||
builder.Services.AddServerSideBlazor();
|
||||
builder.Services.AddAntDesign();
|
||||
|
||||
builder.Services.AddAuthorizationCore();
|
||||
builder.Services.AddScoped<AuthenticationStateProvider, AntSKAuthProvider>();
|
||||
|
||||
builder.Services.AddScoped(sp => new HttpClient
|
||||
{
|
||||
BaseAddress = new Uri(sp.GetService<NavigationManager>()!.BaseUri)
|
||||
});
|
||||
builder.Services.Configure<ProSettings>(builder.Configuration.GetSection("ProSettings"));
|
||||
builder.Services.AddServicesFromAssemblies("AntSK");
|
||||
builder.Services.AddServicesFromAssemblies("AntSK.Domain");
|
||||
|
||||
builder.Services.AddSwaggerGen(c =>
|
||||
{
|
||||
c.SwaggerDoc("v1", new() { Title = "AntSK.Api", Version = "v1" });
|
||||
//添加Api层注释(true表示显示控制器注释)
|
||||
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
||||
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
|
||||
c.IncludeXmlComments(xmlPath, true);
|
||||
//添加Domain层注释(true表示显示控制器注释)
|
||||
var xmlFile1 = $"{Assembly.GetExecutingAssembly().GetName().Name.Replace("Api", "Domain")}.xml";
|
||||
var xmlPath1 = Path.Combine(AppContext.BaseDirectory, xmlFile1);
|
||||
c.IncludeXmlComments(xmlPath1, true);
|
||||
c.DocInclusionPredicate((docName, apiDes) =>
|
||||
{
|
||||
if (!apiDes.TryGetMethodInfo(out MethodInfo method))
|
||||
return false;
|
||||
var version = method.DeclaringType.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);
|
||||
if (docName == "v1" && !version.Any())
|
||||
return true;
|
||||
var actionVersion = method.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);
|
||||
if (actionVersion.Any())
|
||||
return actionVersion.Any(v => v == docName);
|
||||
return version.Any(v => v == docName);
|
||||
});
|
||||
});
|
||||
|
||||
// 读取连接字符串配置
|
||||
{
|
||||
builder.Configuration.GetSection("ConnectionStrings").Get<ConnectionOption>();
|
||||
builder.Configuration.GetSection("OpenAIOption").Get<OpenAIOption>();
|
||||
builder.Configuration.GetSection("Login").Get<LoginOption>();
|
||||
}
|
||||
InitSK(builder);
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseExceptionHandler("/Error");
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseStaticFiles();
|
||||
|
||||
InitDB(app);
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.MapBlazorHub();
|
||||
app.MapFallbackToPage("/_Host");
|
||||
app.UseSwagger();
|
||||
//配置Swagger UI
|
||||
app.UseSwaggerUI(c =>
|
||||
{
|
||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "AntSK API"); //注意中间段v1要和上面SwaggerDoc定义的名字保持一致
|
||||
});
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
app.Run();
|
||||
void InitDB(WebApplication app)
|
||||
{
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
//codefirst 创建表
|
||||
var _repository = scope.ServiceProvider.GetRequiredService<IApps_Repositories>();
|
||||
_repository.GetDB().DbMaintenance.CreateDatabase();
|
||||
_repository.GetDB().CodeFirst.InitTables(typeof(Apps));
|
||||
_repository.GetDB().CodeFirst.InitTables(typeof(Kmss));
|
||||
_repository.GetDB().CodeFirst.InitTables(typeof(KmsDetails));
|
||||
}
|
||||
}
|
||||
|
||||
//初始化SK
|
||||
void InitSK(WebApplicationBuilder builder)
|
||||
{
|
||||
var services = builder.Services;
|
||||
var handler = new OpenAIHttpClientHandler();
|
||||
services.AddScoped<Kernel>((serviceProvider) =>
|
||||
{
|
||||
var kernel = Kernel.CreateBuilder()
|
||||
.AddOpenAIChatCompletion(
|
||||
modelId: OpenAIOption.Model,
|
||||
apiKey: OpenAIOption.Key,
|
||||
httpClient: new HttpClient(handler))
|
||||
.Build();
|
||||
RegisterPluginsWithKernel(kernel);
|
||||
return kernel;
|
||||
});
|
||||
//Kernel Memory
|
||||
var searchClientConfig = new SearchClientConfig
|
||||
{
|
||||
MaxAskPromptSize = 128000,
|
||||
MaxMatchesCount = 3,
|
||||
AnswerTokens = 1000,
|
||||
EmptyAnswer = "知识库未搜索到相关内容"
|
||||
};
|
||||
|
||||
var postgresConfig = builder.Configuration.GetSection("Postgres").Get<PostgresConfig>()!;
|
||||
services.AddScoped<MemoryServerless>(serviceProvider =>
|
||||
{
|
||||
var memory = new KernelMemoryBuilder()
|
||||
.WithPostgresMemoryDb(postgresConfig)
|
||||
.WithSimpleFileStorage(new SimpleFileStorageConfig { StorageType = FileSystemTypes.Volatile, Directory = "_files" })
|
||||
.WithSearchClientConfig(searchClientConfig)
|
||||
.WithOpenAITextGeneration(new OpenAIConfig()
|
||||
{
|
||||
APIKey = OpenAIOption.Key,
|
||||
TextModel = OpenAIOption.Model
|
||||
|
||||
}, null, new HttpClient(handler))
|
||||
.WithOpenAITextEmbeddingGeneration(new OpenAIConfig()
|
||||
{
|
||||
APIKey = OpenAIOption.Key,
|
||||
EmbeddingModel = OpenAIOption.EmbeddingModel
|
||||
|
||||
}, null, false, new HttpClient(handler))
|
||||
.Build<MemoryServerless>();
|
||||
return memory;
|
||||
});
|
||||
}
|
||||
void RegisterPluginsWithKernel(Kernel kernel)
|
||||
{
|
||||
kernel.ImportPluginFromObject(new ConversationSummaryPlugin(), "ConversationSummaryPlugin");
|
||||
kernel.ImportPluginFromObject(new TimePlugin(), "TimePlugin");
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
using AntSK.Domain.Options;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace AntSK.Services.Auth
|
||||
{
|
||||
public class AntSKAuthProvider : AuthenticationStateProvider
|
||||
{
|
||||
private ClaimsIdentity identity = new ClaimsIdentity();
|
||||
|
||||
public async Task<bool> SignIn(string username, string password)
|
||||
{
|
||||
if (username == LoginOption.User && password == LoginOption.Password)
|
||||
{
|
||||
// 用户认证成功,创建用户的ClaimsIdentity
|
||||
var claims = new[] { new Claim(ClaimTypes.Name, username) };
|
||||
identity = new ClaimsIdentity(claims, "AntSK");
|
||||
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 用户认证失败
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public override Task<AuthenticationState> GetAuthenticationStateAsync()
|
||||
{
|
||||
var user = new ClaimsPrincipal(identity);
|
||||
return Task.FromResult(new AuthenticationState(user));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
using AntSK.Domain.Common.DependencyInjection;
|
||||
using AntSK.Domain.Model;
|
||||
using AntSK.Domain.Repositories;
|
||||
using AntSK.Domain.Utils;
|
||||
using AntSK.Models;
|
||||
using AntSK.Models.OpenAPI;
|
||||
using AntSK.Pages.ChatPage;
|
||||
using MarkdownSharp;
|
||||
using Microsoft.KernelMemory;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using System.Text;
|
||||
using System;
|
||||
using ServiceLifetime = AntSK.Domain.Common.DependencyInjection.ServiceLifetime;
|
||||
using AntDesign.Core.Extensions;
|
||||
using Azure.AI.OpenAI;
|
||||
|
||||
namespace AntSK.Services.OpenApi
|
||||
{
|
||||
public interface IOpenApiService
|
||||
{
|
||||
Task<OpenAIResult> Chat(OpenAIModel model, string sk);
|
||||
}
|
||||
|
||||
[ServiceDescription(typeof(IOpenApiService), ServiceLifetime.Scoped)]
|
||||
public class OpenApiService(
|
||||
IApps_Repositories _apps_Repositories,
|
||||
IKmss_Repositories _kmss_Repositories,
|
||||
IKmsDetails_Repositories _kmsDetails_Repositories,
|
||||
Kernel _kernel,
|
||||
MemoryServerless _memory
|
||||
) : IOpenApiService
|
||||
{
|
||||
public async Task<OpenAIResult> Chat(OpenAIModel model,string sk)
|
||||
{
|
||||
OpenAIResult result = new OpenAIResult();
|
||||
result.created= DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
result.choices=new List<ChoicesModel>() { new ChoicesModel() { message=new OpenAIMessage() { role= "assistant" } } };
|
||||
Apps app = _apps_Repositories.GetFirst(p => p.SecretKey == sk);
|
||||
|
||||
|
||||
|
||||
if (app.IsNotNull())
|
||||
{
|
||||
string msg= await HistorySummarize(model);
|
||||
switch (app.Type)
|
||||
{
|
||||
case "chat":
|
||||
//普通会话
|
||||
result.choices[0].message.content= await SendChat( msg, app);
|
||||
break;
|
||||
case "kms":
|
||||
//知识库问答
|
||||
result.choices[0].message.content = await SendKms( msg, app);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送知识库问答
|
||||
/// </summary>
|
||||
/// <param name="questions"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> SendKms( string msg, Apps app)
|
||||
{
|
||||
string result = "";
|
||||
//知识库问答
|
||||
var filters = new List<MemoryFilter>();
|
||||
|
||||
var kmsidList = app.KmsIdList.Split(",");
|
||||
foreach (var kmsid in kmsidList)
|
||||
{
|
||||
filters.Add(new MemoryFilter().ByTag("kmsid", kmsid));
|
||||
}
|
||||
|
||||
var kmsResult = await _memory.AskAsync(msg, index: "kms", filters: filters);
|
||||
if (kmsResult != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(kmsResult.Result))
|
||||
{
|
||||
string answers = kmsResult.Result;
|
||||
result = answers;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送普通对话
|
||||
/// </summary>
|
||||
/// <param name="questions"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> SendChat( string msg, Apps app)
|
||||
{
|
||||
string result = "";
|
||||
if (string.IsNullOrEmpty(app.Prompt))
|
||||
{
|
||||
//如果模板为空,给默认提示词
|
||||
app.Prompt = "{{$input}}";
|
||||
}
|
||||
var promptTemplateFactory = new KernelPromptTemplateFactory();
|
||||
var promptTemplate = promptTemplateFactory.Create(new PromptTemplateConfig(app.Prompt));
|
||||
var renderedPrompt = await promptTemplate.RenderAsync(_kernel);
|
||||
|
||||
var func = _kernel.CreateFunctionFromPrompt(app.Prompt, new OpenAIPromptExecutionSettings());
|
||||
var chatResult = await _kernel.InvokeAsync(function: func, arguments: new KernelArguments() { ["input"] = msg });
|
||||
if (chatResult.IsNotNull())
|
||||
{
|
||||
string answers = chatResult.GetValue<string>();
|
||||
result = answers;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 历史会话的会话总结
|
||||
/// </summary>
|
||||
/// <param name="questions"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> HistorySummarize(OpenAIModel model)
|
||||
{
|
||||
|
||||
StringBuilder history = new StringBuilder();
|
||||
string questions = model.messages[model.messages.Count-1].content;
|
||||
for(int i=0;i<model.messages.Count()-1;i++)
|
||||
{
|
||||
var item = model.messages[i];
|
||||
history.Append($"{item.role}:{item.content}{Environment.NewLine}");
|
||||
}
|
||||
|
||||
KernelFunction sunFun = _kernel.Plugins.GetFunction("ConversationSummaryPlugin", "SummarizeConversation");
|
||||
var summary = await _kernel.InvokeAsync(sunFun, new() { ["input"] = $"内容是:{history.ToString()} {Environment.NewLine} 请注意用中文总结" });
|
||||
string his = summary.GetValue<string>();
|
||||
var msg = $"历史对话:{his}{Environment.NewLine}用户问题:{Environment.NewLine}{questions}"; ;
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>AntSK</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="M:AntSK.Controllers.InitController.InitTable">
|
||||
<summary>
|
||||
初始化DB 和表
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"DetailedErrors": true,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ProSettings": {
|
||||
"NavTheme": "light",
|
||||
"Layout": "side",
|
||||
"ContentWidth": "Fluid",
|
||||
"FixedHeader": false,
|
||||
"FixSiderbar": true,
|
||||
"Title": "AntSK",
|
||||
"PrimaryColor": "daybreak",
|
||||
"ColorWeak": false,
|
||||
"SplitMenus": false,
|
||||
"HeaderRender": true,
|
||||
"FooterRender": true,
|
||||
"MenuRender": true,
|
||||
"MenuHeaderRender": true,
|
||||
"HeaderHeight": 48
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"Postgres": "Host=;Port=;Database=antsk;Username=;Password="
|
||||
},
|
||||
"OpenAIOption": {
|
||||
"EndPoint": "",
|
||||
"Key": "",
|
||||
"Model": "",
|
||||
"EmbeddingModel": ""
|
||||
},
|
||||
"Postgres": {
|
||||
"ConnectionString": "Host=;Port=;Database=antsk;Username=;Password=",
|
||||
"TableNamePrefix": "km-"
|
||||
},
|
||||
"Login": {
|
||||
"User": "admin",
|
||||
"Password": "xuzeyu"
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" version="1.1" viewBox="0 0 200 200"><title>Group 28 Copy 5</title><desc>Created with Sketch.</desc><defs><linearGradient id="linearGradient-1" x1="62.102%" x2="108.197%" y1="0%" y2="37.864%"><stop offset="0%" stop-color="#4285EB"/><stop offset="100%" stop-color="#2EC7FF"/></linearGradient><linearGradient id="linearGradient-2" x1="69.644%" x2="54.043%" y1="0%" y2="108.457%"><stop offset="0%" stop-color="#29CDFF"/><stop offset="37.86%" stop-color="#148EFF"/><stop offset="100%" stop-color="#0A60FF"/></linearGradient><linearGradient id="linearGradient-3" x1="69.691%" x2="16.723%" y1="-12.974%" y2="117.391%"><stop offset="0%" stop-color="#FA816E"/><stop offset="41.473%" stop-color="#F74A5C"/><stop offset="100%" stop-color="#F51D2C"/></linearGradient><linearGradient id="linearGradient-4" x1="68.128%" x2="30.44%" y1="-35.691%" y2="114.943%"><stop offset="0%" stop-color="#FA8E7D"/><stop offset="51.264%" stop-color="#F74A5C"/><stop offset="100%" stop-color="#F51D2C"/></linearGradient></defs><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="logo" transform="translate(-20.000000, -20.000000)"><g id="Group-28-Copy-5" transform="translate(20.000000, 20.000000)"><g id="Group-27-Copy-3"><g id="Group-25" fill-rule="nonzero"><g id="2"><path id="Shape" fill="url(#linearGradient-1)" d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C99.2571609,26.9692191 101.032305,26.9692191 102.20193,28.1378823 L129.985225,55.8983314 C134.193707,60.1033528 141.017005,60.1033528 145.225487,55.8983314 C149.433969,51.69331 149.433969,44.8756232 145.225487,40.6706018 L108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z"/><path id="Shape" fill="url(#linearGradient-2)" d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C100.999864,25.6271836 105.751642,20.541824 112.729652,19.3524487 C117.915585,18.4685261 123.585219,20.4140239 129.738554,25.1889424 C125.624663,21.0784292 118.571995,14.0340304 108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z"/></g><path id="Shape" fill="url(#linearGradient-3)" d="M153.685633,135.854579 C157.894115,140.0596 164.717412,140.0596 168.925894,135.854579 L195.959977,108.842726 C200.659183,104.147384 200.659183,96.5636133 195.960527,91.8688194 L168.690777,64.7181159 C164.472332,60.5180858 157.646868,60.5241425 153.435895,64.7316526 C149.227413,68.936674 149.227413,75.7543607 153.435895,79.9593821 L171.854035,98.3623765 C173.02366,99.5310396 173.02366,101.304724 171.854035,102.473387 L153.685633,120.626849 C149.47715,124.83187 149.47715,131.649557 153.685633,135.854579 Z"/></g><ellipse id="Combined-Shape" cx="100.519" cy="100.437" fill="url(#linearGradient-4)" rx="23.6" ry="23.581"/></g></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.8 KiB |
@@ -1,26 +0,0 @@
|
||||
[
|
||||
{
|
||||
"path": "/chat",
|
||||
"name": "聊天",
|
||||
"key": "chat",
|
||||
"icon": "wechat"
|
||||
},
|
||||
{
|
||||
"path": "/applist",
|
||||
"name": "应用",
|
||||
"key": "app",
|
||||
"icon": "windows"
|
||||
},
|
||||
{
|
||||
"path": "/kmslist",
|
||||
"name": "知识库",
|
||||
"key": "kms",
|
||||
"icon": "database"
|
||||
},
|
||||
{
|
||||
"path": "/setting",
|
||||
"name": "设置",
|
||||
"key": "setting",
|
||||
"icon": "setting"
|
||||
}
|
||||
]
|
||||
27
Dockerfile
@@ -1,13 +1,26 @@
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
||||
# Build stage
|
||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||
WORKDIR /src
|
||||
|
||||
# Copy csproj and restore as distinct layers
|
||||
COPY ["src/AntSK/AntSK.csproj", "AntSK/"]
|
||||
RUN dotnet restore "AntSK/AntSK.csproj"
|
||||
|
||||
# Copy everything else and build
|
||||
COPY src/ .
|
||||
WORKDIR "/src/AntSK"
|
||||
RUN dotnet build "AntSK.csproj" -c Release -o /app/build
|
||||
RUN dotnet publish "AntSK.csproj" -c Release -o /app/publish
|
||||
|
||||
# Runtime stage
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
||||
WORKDIR /service
|
||||
EXPOSE 5000
|
||||
|
||||
WORKDIR /app
|
||||
COPY ["AntSK/bin/Release/net8.0/publish", "publish"]
|
||||
|
||||
WORKDIR /app/publish
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app/publish .
|
||||
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
RUN echo 'Asia/Shanghai' >/etc/timezone
|
||||
ENTRYPOINT ["dotnet", "AntSK.dll"]
|
||||
RUN apt update && apt install -y libpugixml-dev libtbb-dev
|
||||
ENTRYPOINT ["dotnet", "AntSK.dll"]
|
||||
|
||||
17
Dockerfile-py
Normal file
@@ -0,0 +1,17 @@
|
||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||
WORKDIR /src
|
||||
COPY ["src/AntSK/AntSK.csproj", "AntSK/"]
|
||||
RUN dotnet restore "AntSK/AntSK.csproj"
|
||||
COPY src/ .
|
||||
WORKDIR "/src/AntSK"
|
||||
RUN dotnet build "AntSK.csproj" -c Release -o /app/build
|
||||
RUN dotnet publish "AntSK.csproj" -c Release -o /app/publish
|
||||
|
||||
FROM registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk-base:v1.0.0 AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app/publish .
|
||||
|
||||
ENV PATH="/app:/opt/conda/bin:/usr/local/bin:${PATH}"
|
||||
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
RUN echo 'Asia/Shanghai' >/etc/timezone
|
||||
ENTRYPOINT ["dotnet", "AntSK.dll"]
|
||||
2
LICENSE
@@ -186,7 +186,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
Copyright [2024] [许泽宇]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
179
README.en.md
@@ -1,179 +0,0 @@
|
||||
[简体中文](./README.md) | English
|
||||
# AntSK
|
||||
|
||||
## Based on AI knowledge base/agent created by Net8+AntBlazor+SemanticKernel
|
||||
|
||||
|
||||
|
||||
## Core functions
|
||||
|
||||
|
||||
|
||||
- **Semantic Kernel**: It uses advanced natural language processing technology to accurately understand, process and respond to complex semantic queries, and provides users with accurate information retrieval and recommendation services.
|
||||
|
||||
|
||||
|
||||
- **Kernel Memory**: It has the ability to continuously learn and store knowledge points. AntSK has a long-term memory function to accumulate experience and provide a more personalized interactive experience.
|
||||
|
||||
|
||||
|
||||
- **Knowledge base**: Knowledge base documents can be created by importing knowledge base documents (Word, PDF, Excel, Txt, Markdown, Json, PPT) and other forms.
|
||||
|
||||
|
||||
|
||||
- **API plug-in system**: an open API plug-in system that allows third-party developers or service providers to easily integrate their services into AntSK and continuously enhance application functions.
|
||||
|
||||
|
||||
|
||||
- **Online search**: AntSK can obtain the latest information in real time to ensure that the information received by users is always the most timely and relevant.
|
||||
|
||||
|
||||
|
||||
- **GPTs generation**: This platform supports the creation of personalized GPT models and attempts to build your own GPT models.
|
||||
|
||||
|
||||
|
||||
- **API interface publishing**: internal functions are provided externally in the form of API, so that developers can easily translate Xzy AntSK KnowledgeBase is integrated into other applications to enhance application intelligence.
|
||||
|
||||
|
||||
|
||||
## Application scenarios
|
||||
|
||||
|
||||
|
||||
AntSK is applicable to a variety of business scenarios, such as:
|
||||
|
||||
- Enterprise level knowledge management system
|
||||
|
||||
- Automatic customer service and chat robot
|
||||
|
||||
- Enterprise Search Engine
|
||||
|
||||
- Personalized recommendation system
|
||||
|
||||
- Intelligent assisted writing
|
||||
|
||||
- Education and online learning platform
|
||||
|
||||
- Other interesting AI Apps
|
||||
|
||||
|
||||
|
||||
## Function example
|
||||
|
||||
|
||||
|
||||
First, you need to create a knowledge base
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
In the knowledge base, you can use documents or urls to import
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
Click View to view the document slicing of the knowledge base
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
Then we need to create applications, which can create dialog applications and knowledge bases.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
The application of knowledge base needs to select the existing knowledge base, which can be multiple
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
Then you can ask questions about the knowledge base documents in the dialogue
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
In addition, we can also create dialogue applications, and configure prompt word templates in corresponding applications
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
Let's see the effect
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## How do I get started?
|
||||
|
||||
Login is the default login account and password
|
||||
|
||||
Here I use Postgres as data storage and vector storage, because both the Semantic Kernel and Kernel Memory support it. Of course, you can switch to other ones.
|
||||
|
||||
The model supports openai by default. If you need to use azure openai and need to adjust the dependency injection of SK, you can also use one api for integration.
|
||||
|
||||
The following configuration files need to be configured
|
||||
|
||||
```
|
||||
|
||||
"ConnectionStrings":{
|
||||
|
||||
"Postgres": "Host=; Port=; Database=antsk; Username=; Password="
|
||||
|
||||
},
|
||||
|
||||
"OpenAIOption":{
|
||||
|
||||
"EndPoint": "",
|
||||
|
||||
"Key": "",
|
||||
|
||||
"Model": "",
|
||||
|
||||
"Embedding Model": """""
|
||||
|
||||
},
|
||||
|
||||
Postgres:{
|
||||
|
||||
"ConnectionString": "Host=; Port=; Database=antsk; Username=; Password=",
|
||||
|
||||
"TableNamePrefix": "km -"
|
||||
|
||||
},
|
||||
"Login": {
|
||||
"User": "admin",
|
||||
"Password": "xuzeyu"
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
I use CodeFirst mode. As long as the database link is configured, the table structure is automatically created
|
||||
|
||||
|
||||
|
||||
|
||||
To learn more or start using**AntSK**, you can follow my public account and join the exchange group.
|
||||
|
||||
|
||||
|
||||
## Contact me
|
||||
|
||||
If you have any questions or suggestions, please follow my public account through the following ways, and send a message to me. We also have an exchange group, which can send messages such as joining the group, and then I will bring you into the exchange group
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
We appreciate your interest in**AntSK**and look forward to working with you to create an intelligent future!
|
||||
248
README.md
@@ -1,96 +1,220 @@
|
||||
中文|[English](https://github.com/xuzeyu91/AntSK/blob/main/README.en.md)
|
||||
[简体中文](./README.zh.md) | English
|
||||
# AntSK
|
||||
## 基于.Net8+AntBlazor+SemanticKernel 打造的AI知识库/智能体
|
||||
## AI Knowledge Base/Intelligent Agent built on .Net8+AntBlazor+SemanticKernel
|
||||
|
||||
## 核心功能
|
||||
## ⭐Core Features
|
||||
|
||||
- **语义内核 (Semantic Kernel)**:采用领先的自然语言处理技术,准确理解、处理和响应复杂的语义查询,为用户提供精确的信息检索和推荐服务。
|
||||
- **Semantic Kernel**: Utilizes advanced natural language processing technology to accurately understand, process, and respond to complex semantic queries, providing users with precise information retrieval and recommendation services.
|
||||
|
||||
- **内存内核 (Kernel Memory)**:具备持续学习和存储知识点的能力,AntSK 拥有长期记忆功能,累积经验,提供更个性化的交互体验。
|
||||
- **Kernel Memory**: Capable of continuous learning and storing knowledge points, AntSK has long-term memory function, accumulates experience, and provides a more personalized interaction experience.
|
||||
|
||||
- **知识库**:通过文档(Word、PDF、Excel、Txt、Markdown、Json、PPT)等形式导入知识库,可以进行知识库文档。
|
||||
- **Knowledge Base**: Import knowledge base through documents (Word, PDF, Excel, Txt, Markdown, Json, PPT) and perform knowledge base Q&A.
|
||||
|
||||
- **API插件系统**:开放式API插件系统,允许第三方开发者或服务商轻松将其服务集成到AntSK,不断增强应用功能。
|
||||
- **GPT Generation**: This platform supports creating personalized GPT models, enabling users to build their own GPT models.
|
||||
|
||||
- **联网搜索**:AntSK,实时获取最新信息,确保用户接受到的资料总是最及时、最相关的。
|
||||
- **API Interface Publishing**: Exposes internal functions in the form of APIs, enabling developers to integrate AntSK into other applications and enhance application intelligence.
|
||||
|
||||
- **GPTs 生成**:此平台支持创建个性化的GPT模型,尝试构建您自己的GPT模型。
|
||||
- **API Plugin System**: Open API plugin system that allows third-party developers or service providers to easily integrate their services into AntSK, continuously enhancing application functionality.
|
||||
|
||||
- **API接口发布**:将内部功能以API的形式对外提供,便于开发者将AntSK 集成进其他应用,增强应用智慧。
|
||||
- **.Net Plugin System**: Open dll plugin system that allows third-party developers or service providers to easily integrate their business functions by generating dll in standard format code, continuously enhancing application functionality.
|
||||
|
||||
## 应用场景
|
||||
- **Online Search**: AntSK, real-time access to the latest information, ensuring users receive the most timely and relevant data.
|
||||
|
||||
AntSK 适用于多种业务场景,例如:
|
||||
- 企业级知识管理系统
|
||||
- 自动客服与聊天机器人
|
||||
- 企业级搜索引擎
|
||||
- 个性化推荐系统
|
||||
- 智能辅助写作
|
||||
- 教育与在线学习平台
|
||||
- 其他有意思的AI App
|
||||
- **Model Management**: Adapts and manages integration of different models from different manufacturers, including gguf types supported by **llama.cpp** and models offline running supported by **llamafactory** and **ollama**.
|
||||
|
||||
## 功能示例
|
||||
- **Domestic Innovation**: AntSK supports domestic models and databases and can run under domestic innovation conditions.
|
||||
|
||||
[视频示例](https://www.bilibili.com/video/BV1zH4y1h7Y9/)
|
||||
- **Model Fine-Tuning**: Planned based on llamafactory for model fine-tuning.
|
||||
|
||||
首先需要创建知识库
|
||||

|
||||
## ⛪Application Scenarios
|
||||
|
||||
在知识库里可以使用文档或者url进行导入
|
||||

|
||||
AntSK is suitable for various business scenarios, such as:
|
||||
- Enterprise knowledge management system
|
||||
- Automatic customer service and chatbots
|
||||
- Enterprise search engine
|
||||
- Personalized recommendation system
|
||||
- Intelligent writing assistance
|
||||
- Education and online learning platforms
|
||||
- Other interesting AI Apps
|
||||
|
||||
点击查看可以查看知识库的文档切片情况
|
||||

|
||||
## ✏️Function Examples
|
||||
### Online Demo
|
||||
[document](http://antsk.cn/)
|
||||
|
||||
然后我们需要创建应用,可以创建对话应用和知识库。
|
||||

|
||||
[demo](https://demo.antsk.cn/)
|
||||
|
||||
知识库应用需要选择已有的知识库,可以选多个
|
||||

|
||||
|
||||
然后再对话中可以对知识库的文档进行提问
|
||||

|
||||
|
||||
另外我们也可以创建对话应用,可以在对应应用中配置提示词模板
|
||||

|
||||
|
||||
下面来看看效果吧
|
||||

|
||||
|
||||
## 如何开始?
|
||||
|
||||
在这里我使用的是Postgres 作为数据存储和向量存储,因为Semantic Kernel和Kernel Memory都支持他,当然你也可以换成其他的。
|
||||
模型默认支持openai,如果需要使用azure openai需要调整SK的依赖注入,也可以使用one-api进行集成。
|
||||
Login是默认的登陆账号和密码
|
||||
需要配置如下的配置文件
|
||||
```
|
||||
"ConnectionStrings": {
|
||||
"Postgres": "Host=;Port=;Database=antsk;Username=;Password="
|
||||
Default account: test
|
||||
|
||||
Default password: test
|
||||
|
||||
Due to the low configuration of the cloud server, the local model cannot be run, so the system settings permissions have been closed. You can simply view the interface. If you want to use the local model, please download and use it on your own.
|
||||
```
|
||||
|
||||
### Other Function Examples
|
||||
[Video Demonstration](https://www.bilibili.com/video/BV1zH4y1h7Y9/)
|
||||
|
||||
## ❓How to get started?
|
||||
|
||||
Here I am using Postgres as the data and vector storage because Semantic Kernel and Kernel Memory support it, but you can also use other options.
|
||||
|
||||
The model by default supports the local model of openai, azure openai, and llama. If you need to use other models, you can integrate them using one-api.
|
||||
|
||||
The Login configuration in the configuration file is the default login account and password.
|
||||
|
||||
The following configuration file needs to be configured
|
||||
|
||||
## 1️⃣Using docker-compose
|
||||
|
||||
Provided the pg version **appsettings.json** and simplified version (Sqlite+disk) **docker-compose.simple.yml**
|
||||
|
||||
Download **docker-compose.yml** from the project root directory and place the configuration file **appsettings.json** in the same directory.
|
||||
|
||||
The pg image has already been prepared. You can modify the default username and password in docker-compose.yml, and then the database connection in your **appsettings.json** needs to be consistent.
|
||||
|
||||
Then you can execute the following command in the directory to start AntSK
|
||||
```
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## 2️⃣How to mount local models and model download directory in docker
|
||||
```
|
||||
# Non-host version, do not use local proxy
|
||||
version: '3.8'
|
||||
services:
|
||||
antsk:
|
||||
container_name: antsk
|
||||
image: registry.cn-hangzhou.aliyuncs.com/AIDotNet/antsk:v0.1.5ports:
|
||||
- 5000:5000
|
||||
networks:
|
||||
- antsk
|
||||
depends_on:
|
||||
- antskpg
|
||||
restart: always
|
||||
environment:
|
||||
- ASPNETCORE_URLS=http://*:5000
|
||||
volumes:
|
||||
- ./appsettings.json:/app/appsettings.json # Local configuration file needs to be placed in the same directory
|
||||
- D://model:/app/model
|
||||
networks:
|
||||
antsk:
|
||||
```
|
||||
Taking this as an example, it means mounting the local D://model folder of Windows into the container /app/model. If so, the model address in your appsettings.json should be configured as
|
||||
```
|
||||
model/xxx.gguf
|
||||
```
|
||||
|
||||
## 3️⃣Some meanings of configuration file
|
||||
```
|
||||
{
|
||||
"DBConnection": {
|
||||
"DbType": "Sqlite",
|
||||
"ConnectionStrings": "Data Source=AntSK.db;"
|
||||
},
|
||||
"OpenAIOption": {
|
||||
"EndPoint": "",
|
||||
"Key": "",
|
||||
"Model": "",
|
||||
"EmbeddingModel": ""
|
||||
},
|
||||
"Postgres": {
|
||||
"KernelMemory": {
|
||||
"VectorDb": "Disk",
|
||||
"ConnectionString": "Host=;Port=;Database=antsk;Username=;Password=",
|
||||
"TableNamePrefix": "km-"
|
||||
},
|
||||
"FileDir": {
|
||||
"DirectoryPath": "D:\\git\\AntBlazor\\model"
|
||||
},
|
||||
"LLamaSharp": {
|
||||
"RunType": "GPU",
|
||||
"ContextSize": 2048,
|
||||
"GpuLayerCount": 20
|
||||
},
|
||||
"Login": {
|
||||
"User": "admin",
|
||||
"Password": "xuzeyu"
|
||||
},
|
||||
"BackgroundTaskBroker": {
|
||||
"ImportKMSTask": {
|
||||
"WorkerCount": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
我使用的是CodeFirst模式,只要配置好数据库链接,表结构是自动创建的
|
||||
```
|
||||
// Supports various databases, you can check SqlSugar, MySql, SqlServer, Sqlite, Oracle, PostgreSQL, Dm, Kdbndp, Oscar, MySqlConnector, Access, OpenGauss, QuestDB, HG, ClickHouse, GBase, Odbc, OceanBaseForOracle, TDengine, GaussDB, OceanBase, Tidb, Vastbase, PolarDB, Custom
|
||||
DBConnection.DbType
|
||||
|
||||
// Connection string, need to use the corresponding string according to the different DB types
|
||||
DBConnection.ConnectionStrings
|
||||
|
||||
//The type of vector storage, supporting Postgres, Disk, Memory, Qdrant, Redis, AzureAISearch
|
||||
//Postgres and Redis require ConnectionString configuration
|
||||
//The ConnectionString of Qdrant and AzureAISearch uses Endpoint | APIKey
|
||||
KernelMemory.VectorDb
|
||||
|
||||
//Local model execution options: GPU and CPU. When using the online API, any option can be used.
|
||||
LLamaSharp.RunType
|
||||
|
||||
//Local model path, used for quick selection of models under llama, as well as saving downloaded models.
|
||||
LLamaSharp.FileDirectory
|
||||
|
||||
//Default admin account password
|
||||
Login
|
||||
|
||||
//Import asynchronous processing thread count. A higher count can be used for online API, but for local models, 1 is recommended to avoid memory overflow issues.
|
||||
BackgroundTaskBroker.ImportKMSTask.WorkerCount
|
||||
|
||||
```
|
||||
|
||||
## ⚠️Fixing Style Issues:
|
||||
Run the following in AntSK/src/AntSK:
|
||||
```
|
||||
dotnet clean
|
||||
dotnet build
|
||||
dotnet publish "AntSK.csproj"
|
||||
```
|
||||
Then navigate to AntSK/src/AntSK/bin/Release/net8.0/publish and run:
|
||||
```
|
||||
dotnet AntSK.dll
|
||||
```
|
||||
The styles should now be applied after starting.
|
||||
|
||||
I'm using CodeFirst mode for the database, so as long as the database connection is properly configured, the table structure will be created automatically.
|
||||
|
||||
## ✔️Using llamafactory
|
||||
```
|
||||
1. First, ensure that Python and pip are installed in your environment. This step is not necessary if using an image, such as version v0.2.3.2, which already includes the complete Python environment.
|
||||
2. Go to the model add page and select llamafactory.
|
||||
3. Click "Initialize" to check whether the 'pip install' environment setup is complete.
|
||||
4. Choose a model that you like.
|
||||
5. Click "Start" to begin downloading the model from the tower. This may involve a somewhat lengthy wait.
|
||||
6. After the model has finished downloading, enter http://localhost:8000/ in the request address. The default port is 8000.
|
||||
7. Click "Save" and start chatting.
|
||||
8. Many people ask about the difference between LLamaSharp and llamafactory. In fact, LLamaSharp is a .NET implementation of llama.cpp, but only supports local gguf models, while llamafactory supports a wider variety of models and uses Python implementation. The main difference lies here. Additionally, llamafactory has the ability to fine-tune models, which is an area we will focus on integrating in the future.
|
||||
```
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
[PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)
|
||||
|
||||
If you would like to contribute, feel free to create a [Pull Request](https://github.com/AIDotNet/AntSK/pulls), or give us [Bug Report](https://github.com/AIDotNet/AntSK/issues/new).
|
||||
|
||||
|
||||
想了解更多信息或开始使用 **AntSK**,可以关注我的公众号以及加入交流群。
|
||||
## 💕 Contributors
|
||||
|
||||
## 联系我
|
||||
如有任何问题或建议,请通过以下方式关注我的公众号,发消息与我联系,我们也有交流群,可以发送进群等消息,然后我会拉你进交流群
|
||||

|
||||
This project exists thanks to all the people who contribute.
|
||||
|
||||
<a href="https://github.com/AIDotNet/AntSK/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=AIDotNet/AntSK&max=1000&columns=15&anon=1" />
|
||||
</a>
|
||||
|
||||
## 🚨 Use Protocol
|
||||
This warehouse follows the [Apache-2.0 License](https://github.com/AIDotNet/AntSK?tab=Apache-2.0-1-ov-file) open source protocol.
|
||||
The Apache open source license allows the use of AntSK in commercial environments, provided that the license terms are followed. One of the main terms is to retain the copyright and license statements.
|
||||
If you plan to use AntSK in commercial projects, you need to ensure that you follow the following steps:
|
||||
1. Copyright statement containing Apache license. [Apache-2.0 License](https://github.com/AIDotNet/AntSK?tab=Apache-2.0-1-ov-file).
|
||||
2. If you modify the software source code, you need to clearly indicate these modifications in the source code.
|
||||
|
||||
## ☎️Contact Me
|
||||
If you have any questions or suggestions, please contact me through my official WeChat account. We also have a discussion group where you can send a message to join, and then I will add you to the group.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
我们对您在**AntSK**的兴趣表示感谢,并期待与您携手共创智能化的未来!
|
||||
We appreciate your interest in **AntSK** and look forward to collaborating with you to create an intelligent future!
|
||||
|
||||
238
README.zh.md
Normal file
@@ -0,0 +1,238 @@
|
||||
中文|[English](./README.md)
|
||||
# AntSK
|
||||
## 使用.Net8+Blazor+SemanticKernel 打造的AI知识库/智能体
|
||||
|
||||
## ⭐核心功能
|
||||
|
||||
- **语义内核 (Semantic Kernel)**:采用领先的自然语言处理技术,准确理解、处理和响应复杂的语义查询,为用户提供精确的信息检索和推荐服务。
|
||||
|
||||
- **内存内核 (Kernel Memory)**:具备持续学习和存储知识点的能力,AntSK 拥有长期记忆功能,累积经验,提供更个性化的交互体验。
|
||||
|
||||
- **知识库**:通过文档(Word、PDF、Excel、Txt、Markdown、Json、PPT)等形式导入知识库,可以进行知识库问答,支持本地bge-embedding 向量模型 ,以及bge-rerank 重排模型。
|
||||
|
||||
- **文生图**:集成**StableDiffusion** 本地模型,可以进行文生图。
|
||||
|
||||
- **GPTs 生成**:此平台支持创建个性化的GPT模型,尝试构建您自己的GPT模型。
|
||||
|
||||
- **API接口发布**:将内部功能以API的形式对外提供,便于开发者将AntSK 集成进其他应用,增强应用智慧。
|
||||
|
||||
- **API插件系统**:开放式API插件系统,允许第三方开发者或服务商轻松将其服务集成到AntSK,不断增强应用功能。
|
||||
|
||||
- **.Net插件系统**:开放式dll插件系统,允许第三方开发者或服务商轻松将其业务功能通过标准格式的代码生成dll后集成到AntSK,不断增强应用功能。
|
||||
|
||||
- **联网搜索**:AntSK,实时获取最新信息,确保用户接受到的资料总是最及时、最相关的。
|
||||
|
||||
- **模型管理**:适配和管理集成不同厂商的不同模型。并且支持**llama.cpp**所支持的gguf类型,以及**llamafactory** 和 **ollama** 所支持的模型离线运行
|
||||
|
||||
- **国产信创**:AntSK支持国产模型,和国产数据库,可以在信创条件下运行
|
||||
|
||||
- **模型微调**:规划中,基于llamafactory进行模型微调
|
||||
|
||||
|
||||
## ⛪应用场景
|
||||
|
||||
AntSK 适用于多种业务场景,例如:
|
||||
- 企业级知识管理系统
|
||||
- 自动客服与聊天机器人
|
||||
- 企业级搜索引擎
|
||||
- 个性化推荐系统
|
||||
- 智能辅助写作
|
||||
- 教育与在线学习平台
|
||||
- 其他有意思的AI App
|
||||
|
||||
## ✏️功能示例
|
||||
### 在线演示
|
||||
|
||||
[文档地址](http://antsk.cn/)
|
||||
|
||||
[体验地址](https://demo.antsk.cn/)
|
||||
|
||||
```
|
||||
默认账号:test
|
||||
|
||||
默认密码:test
|
||||
|
||||
由于云服务器配置较低,无法运行本地模型,所以把系统设置权限关闭了,大家看看界面即可,要使用本地模型,请下载自行使用
|
||||
|
||||
请勿在演示站点上传敏感信息
|
||||
```
|
||||
|
||||
### 其他功能示例
|
||||
[视频示例](https://www.bilibili.com/video/BV1zH4y1h7Y9/)
|
||||
|
||||
[在线文档:http://antsk.cn](http://antsk.cn)
|
||||
|
||||
## ❓如何开始?
|
||||
|
||||
在这里我使用的是Postgres 作为数据存储和向量存储,因为Semantic Kernel和Kernel Memory都支持他,当然你也可以换成其他的。
|
||||
|
||||
模型默认支持openai、azure openai、讯飞星火、阿里云积、 和llama支持的gguf本地模型 以及llamafactory的本地模型,如果需要使用其他模型,可以使用one-api进行集成。
|
||||
|
||||
配置文件中的Login配置是默认的登录账号和密码
|
||||
|
||||
需要配置如下的配置文件
|
||||
|
||||
## 1️⃣使用docker-compose
|
||||
|
||||
提供了pg版本 **appsettings.json** 和 简化版本(**Sqlite+disk**) **docker-compose.simple.yml**
|
||||
|
||||
从项目根目录下载**docker-compose.yml**,然后把配置文件**appsettings.json**和它放在统一目录,
|
||||
|
||||
这里已经把pg的镜像做好了。在docker-compose.yml中可以修改默认账号密码,然后你的**appsettings.json**的数据库连接需要保持一致。
|
||||
|
||||
然后你可以进入到目录后执行
|
||||
```
|
||||
docker-compose up -d
|
||||
```
|
||||
来启动AntSK
|
||||
|
||||
## 2️⃣如何在docker中挂载本地模型,和模型下载的目录
|
||||
```
|
||||
# 非 host 版本, 不使用本机代理
|
||||
version: '3.8'
|
||||
services:
|
||||
antsk:
|
||||
container_name: antsk
|
||||
image: registry.cn-hangzhou.aliyuncs.com/AIDotNet/antsk:v0.3.1
|
||||
ports:
|
||||
- 5000:5000
|
||||
networks:
|
||||
- antsk
|
||||
depends_on:
|
||||
- antskpg
|
||||
restart: always
|
||||
environment:
|
||||
- ASPNETCORE_URLS=http://*:5000
|
||||
volumes:
|
||||
- ./appsettings.json:/app/appsettings.json # 本地配置文件 需要放在同级目录
|
||||
- D://model:/app/model
|
||||
- D://model:/root/.cache/modelscope/hub/AI-ModelScope #使用Llamafactory时需要挂载 否则初始化的环境重启后会丢失
|
||||
networks:
|
||||
antsk:
|
||||
```
|
||||
以这个为示例,意思是把windows本地D://model的文件夹挂载进 容器内/app/model 如果是这样你的appsettings.json中的模型地址应该配置为
|
||||
```
|
||||
model/xxx.gguf
|
||||
```
|
||||
|
||||
## 3️⃣配置文件的一些含义
|
||||
```
|
||||
{
|
||||
"DBConnection": {
|
||||
"DbType": "Sqlite",
|
||||
"ConnectionStrings": "Data Source=AntSK.db;"
|
||||
},
|
||||
"KernelMemory": {
|
||||
"VectorDb": "Disk",
|
||||
"ConnectionString": "Host=;Port=;Database=antsk;Username=;Password=",
|
||||
"TableNamePrefix": "km-"
|
||||
},
|
||||
"FileDir": {
|
||||
"DirectoryPath": "D:\\git\\AntBlazor\\model"
|
||||
},
|
||||
"LLamaSharp": {
|
||||
"RunType": "GPU",
|
||||
"ContextSize": 2048,
|
||||
"GpuLayerCount": 20
|
||||
},
|
||||
"Login": {
|
||||
"User": "admin",
|
||||
"Password": "xuzeyu"
|
||||
},
|
||||
"BackgroundTaskBroker": {
|
||||
"ImportKMSTask": {
|
||||
"WorkerCount": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
//支持多种数据库,具体可以查看SqlSugar,MySql,SqlServer,Sqlite,Oracle,PostgreSQL,Dm,Kdbndp,Oscar,MySqlConnector,Access,OpenGauss,QuestDB,HG,ClickHouse,GBase,Odbc,OceanBaseForOracle,TDengine,GaussDB,OceanBase,Tidb,Vastbase,PolarDB,Custom
|
||||
DBConnection.DbType
|
||||
//连接字符串,需要根据不同DB类型,用对应的字符串
|
||||
DBConnection.ConnectionStrings
|
||||
|
||||
//向量存储的类型,支持 Postgres、Disk、Memory、Qdrant、Redis、AzureAISearch
|
||||
//Postgres、Redis需要配置 ConnectionString
|
||||
//Qdrant 和AzureAISearch 的 ConnectionString 使用 Endpoint|APIKey
|
||||
KernelMemory.VectorDb
|
||||
|
||||
//本地模型使用的运行方式 GUP CPU ,如果用在线API 这个随意使用一个即可
|
||||
LLamaSharp.RunType
|
||||
|
||||
//本地模型路径,用于在选择llama时可以快速选择目录下的模型,以及保存下载的模型
|
||||
LLamaSharp.FileDirectory
|
||||
|
||||
//默认管理员账号密码
|
||||
Login
|
||||
//导入异步处理的线程数,使用在线API可以高一点,本地模型建议1 否则容易内存溢出崩掉
|
||||
BackgroundTaskBroker.ImportKMSTask.WorkerCount
|
||||
```
|
||||
|
||||
## ⚠️找不到样式问题解决:
|
||||
AntSK/src/AntSK下执行:
|
||||
```
|
||||
dotnet clean
|
||||
dotnet build
|
||||
dotnet publish "AntSK.csproj"
|
||||
```
|
||||
再去AntSK/src/AntSK/bin/Release/net8.0/publish下
|
||||
```
|
||||
dotnet AntSK.dll
|
||||
```
|
||||
然后启动就有样式了
|
||||
|
||||
DB我使用的是CodeFirst模式,只要配置好数据库链接,表结构是自动创建的
|
||||
|
||||
## ✔️使用llamafactory
|
||||
```
|
||||
1、首先需要确保你的环境已经安装了python和pip,如果使用镜像,例如p0.2.4版本已经包含了 python全套环境则无需此步骤
|
||||
2、进入模型添加页面选择llamafactory
|
||||
3、点击初始化,可以检查pip install 环境是否完成
|
||||
4、选择一个喜欢的模型
|
||||
5、点击启动,这会开始从魔塔下载模型,你可能需要有一个较为漫长的等待
|
||||
6、等待模型下载完毕后,在请求地址输入 http://localhost:8000/ 这里默认是使用8000端口
|
||||
7、点击保存,然后就可以开始聊天了
|
||||
8、很多人会问 LLamaSharp与llamafactory有什么区别?其实这两者LLamaSharp是llama.cpp的 dotnet实现,但是只支持本地gguf模型, 而llamafactory 支持的模型种类更多,但使用的是python的实现,其主要差异在这里,另外llamafactory具有模型微调的能力,这也是我们下一步需要重点集成的部分。
|
||||
```
|
||||
|
||||
## 🤝 贡献
|
||||
|
||||
[](https://github.com/AIDotNet/AntSK/pulls)
|
||||
|
||||
如果你想贡献,可以创建一个[拉取请求](https://github.com/AIDotNet/AntSK/pulls), 或给我们[错误报告](https://github.com/AIDotNet/AntSK/issues/new).
|
||||
|
||||
|
||||
## 💕 贡献者
|
||||
|
||||
这个项目的存在要感谢所有的贡献者。
|
||||
|
||||
<a href="https://github.com/AIDotNet/AntSK/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=AIDotNet/AntSK&max=1000&columns=15&anon=1" />
|
||||
</a>
|
||||
|
||||
## 🚨 使用协议
|
||||
|
||||
本仓库遵循 [Apache-2.0 License](https://github.com/AIDotNet/AntSK?tab=Apache-2.0-1-ov-file) 开源协议。
|
||||
Apache开源许可证允许在商业环境中使用AntSK,前提是需要遵守许可证的条款。主要条款之一是要保留版权声明和许可证声明。
|
||||
|
||||
如果您打算在商业项目中使用AntSK,您需要确保遵守以下步骤:
|
||||
|
||||
1、包含Apache许可证的版权声明。 [Apache-2.0 License](https://github.com/AIDotNet/AntSK?tab=Apache-2.0-1-ov-file) 。
|
||||
|
||||
2、如果您修改了软件源代码,您需要在源代码中明确标明这些修改。
|
||||
|
||||
|
||||
## ☎️联系我
|
||||
如有任何问题或建议,请通过以下方式关注我的公众号《许泽宇的技术分享》,发消息与我联系,我们也有AIDotnet交流群,可以发送进群等消息,然后我会拉你进交流群
|
||||

|
||||
|
||||
## 🌟 Star History
|
||||
<a href="https://github.com/AIDotNet/AntSK/stargazers" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=AIDotNet/AntSK&type=Date&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=AIDotNet/AntSK&type=Date" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=AIDotNet/AntSK&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
21
docker-compose.simple.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
# 非 host 版本, 不使用本机代理
|
||||
version: '3.8'
|
||||
services:
|
||||
antsk:
|
||||
container_name: antsk
|
||||
image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:v0.4.3
|
||||
# 如果需要pytorch环境需要使用下面这个镜像,镜像比较大
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:p0.4.3
|
||||
ports:
|
||||
- 5000:5000
|
||||
networks:
|
||||
- antsk
|
||||
restart: always
|
||||
environment:
|
||||
- ASPNETCORE_URLS=http://*:5000
|
||||
volumes:
|
||||
- ./appsettings.json:/app/appsettings.json # 本地配置文件 需要放在同级目录
|
||||
- /AntSK/model:/app/model
|
||||
- /AntSK/model:/root/.cache/modelscope/hub/AI-ModelScope # LLamaFactory模型文件
|
||||
networks:
|
||||
antsk:
|
||||
58
docker-compose.yml
Normal file
@@ -0,0 +1,58 @@
|
||||
# 非 host 版本, 不使用本机代理
|
||||
version: '3.8'
|
||||
services:
|
||||
aspire-dashboard:
|
||||
container_name: aspire-dashboard
|
||||
image: mcr.microsoft.com/dotnet/aspire-dashboard:8.0
|
||||
networks:
|
||||
- antsk
|
||||
environment:
|
||||
- DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS=true
|
||||
- ASPIRE_ALLOW_UNSECURED_TRANSPORT=true
|
||||
- DASHBOARD_OTLP_AUTHMODE=ApiKey
|
||||
- DASHBOARD_OTLP_PRIMARYAPIKEY=antsk
|
||||
ports:
|
||||
- 18888:18888
|
||||
- 18889:18889
|
||||
restart: unless-stopped
|
||||
antskpg:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/pg:v0.5.0
|
||||
container_name: antskpg
|
||||
restart: always
|
||||
ports: # 生产环境建议不要暴露
|
||||
- 5432:5432
|
||||
networks:
|
||||
- antsk
|
||||
environment:
|
||||
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
|
||||
- POSTGRES_USER=username
|
||||
- POSTGRES_PASSWORD=password
|
||||
- POSTGRES_DB=antsk
|
||||
volumes:
|
||||
- ./pg/data:/var/lib/postgresql/data
|
||||
antsk:
|
||||
container_name: antsk
|
||||
image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:v0.4.3
|
||||
# 如果需要pytorch环境需要使用下面这个镜像,镜像比较大
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/xuzeyu91/antsk:p0.4.3
|
||||
ports:
|
||||
- 5000:5000
|
||||
networks:
|
||||
- antsk
|
||||
depends_on:
|
||||
- antskpg
|
||||
restart: always
|
||||
environment:
|
||||
- ASPNETCORE_URLS=http://*:5000
|
||||
- ASPNETCORE_FORWARDEDHEADERS_ENABLED=true
|
||||
- OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES=true
|
||||
- OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES= true
|
||||
- OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY=in_memory
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://aspire-dashboard:18889
|
||||
- OTEL_SERVICE_NAME=antsk
|
||||
volumes:
|
||||
- ./appsettings.json:/app/appsettings.json # 本地配置文件 需要放在同级目录
|
||||
- /AntSK/model:/app/model
|
||||
- /AntSK/model:/root/.cache/modelscope/hub/AI-ModelScope # LLamaFactory模型文件
|
||||
networks:
|
||||
antsk:
|
||||
14
docs/deploy/_category_.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"position": 3,
|
||||
"label": "部署",
|
||||
"collapsible": true,
|
||||
"collapsed": false,
|
||||
"className": "red",
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"title": "使用案例"
|
||||
},
|
||||
"customProps": {
|
||||
"description": "提供快速使用AntSK的一些案例!"
|
||||
}
|
||||
}
|
||||
56
docs/deploy/settings.md
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# 配置文件的一些含义
|
||||
```
|
||||
{
|
||||
"DBConnection": {
|
||||
"DbType": "Sqlite",
|
||||
"ConnectionStrings": "Data Source=AntSK.db;"
|
||||
},
|
||||
"KernelMemory": {
|
||||
"VectorDb": "Disk",
|
||||
"ConnectionString": "Host=;Port=;Database=antsk;Username=;Password=",
|
||||
"TableNamePrefix": "km-"
|
||||
},
|
||||
"LLamaSharp": {
|
||||
"RunType": "GPU",
|
||||
"Chat": "D:\\Code\\AI\\AntBlazor\\model\\qwen1_5-1_8b-chat-q8_0.gguf",
|
||||
"Embedding": "D:\\Code\\AI\\AntBlazor\\model\\qwen1_5-1_8b-chat-q8_0.gguf",
|
||||
"FileDirectory": "D:\\Code\\AI\\AntBlazor\\model\\"
|
||||
},
|
||||
"Login": {
|
||||
"User": "admin",
|
||||
"Password": "xuzeyu"
|
||||
},
|
||||
"BackgroundTaskBroker": {
|
||||
"ImportKMSTask": {
|
||||
"WorkerCount": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
//支持多种数据库,具体可以查看SqlSugar,MySql,SqlServer,Sqlite,Oracle,PostgreSQL,Dm,Kdbndp,Oscar,MySqlConnector,Access,OpenGauss,QuestDB,HG,ClickHouse,GBase,Odbc,OceanBaseForOracle,TDengine,GaussDB,OceanBase,Tidb,Vastbase,PolarDB,Custom
|
||||
DBConnection.DbType
|
||||
//连接字符串,需要根据不同DB类型,用对应的字符串
|
||||
DBConnection.ConnectionStrings
|
||||
|
||||
//向量存储的类型,支持 Postgres Disk Memory ,其中Postgres需要配置 ConnectionString
|
||||
KernelMemory.VectorDb
|
||||
|
||||
//本地模型使用的运行方式 GUP CPU ,如果用在线API 这个随意使用一个即可
|
||||
LLamaSharp.RunType
|
||||
//本地会话模型的模型路径 注意区分linux和windows盘符不同
|
||||
LLamaSharp.Chat
|
||||
//本地向量模型的模型路径 注意区分linux和windows盘符不同
|
||||
LLamaSharp.Embedding
|
||||
//本地模型路径,用于在选择llama时可以快速选择目录下的模型,以及保存下载的模型
|
||||
LLamaSharp.FileDirectory
|
||||
|
||||
//默认管理员账号密码
|
||||
Login
|
||||
//导入异步处理的线程数,使用在线API可以高一点,本地模型建议1 否则容易内存溢出崩掉
|
||||
BackgroundTaskBroker.ImportKMSTask.WorkerCount
|
||||
```
|
||||
57
docs/deploy/start.md
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# 如何开始?
|
||||
|
||||
在这里我使用的是Postgres 作为数据存储和向量存储,因为Semantic Kernel和Kernel Memory都支持他,当然你也可以换成其他的。
|
||||
|
||||
模型默认支持openai、azure openai 和llama支持的gguf本地模型,如果需要使用其他模型,可以使用one-api进行集成。
|
||||
|
||||
配置文件中的Login配置是默认的登陆账号和密码
|
||||
|
||||
需要配置如下的配置文件
|
||||
|
||||
## 使用docker-compose
|
||||
|
||||
提供了pg版本 **appsettings.json** 和 简化版本(Sqlite+disk) **docker-compose.simple.yml**
|
||||
|
||||
从项目根目录下载**docker-compose.yml**,然后把配置文件**appsettings.json**和它放在统一目录,
|
||||
|
||||
这里已经把pg的镜像做好了。在docker-compose.yml中可以修改默认账号密码,然后你的**appsettings.json**的数据库连接需要保持一致。
|
||||
|
||||
然后你可以进入到目录后执行
|
||||
```
|
||||
docker-compose up -d
|
||||
```
|
||||
来启动AntSK
|
||||
|
||||
## 如何在docker中挂载本地模型,和模型下载的目录
|
||||
```
|
||||
# 非 host 版本, 不使用本机代理
|
||||
version: '3.8'
|
||||
services:
|
||||
antsk:
|
||||
container_name: antsk
|
||||
image: registry.cn-hangzhou.aliyuncs.com/AIDotNet/antsk:v0.1.5
|
||||
ports:
|
||||
- 5000:5000
|
||||
networks:
|
||||
- antsk
|
||||
depends_on:
|
||||
- antskpg
|
||||
restart: always
|
||||
environment:
|
||||
- ASPNETCORE_URLS=http://*:5000
|
||||
volumes:
|
||||
- ./appsettings.json:/app/appsettings.json # 本地配置文件 需要放在同级目录
|
||||
- D://model:/app/model
|
||||
networks:
|
||||
antsk:
|
||||
```
|
||||
以这个为示例,意思是把windows本地D://model的文件夹挂载进 容器内/app/model 如果是这样你的appsettings.json中的模型地址应该配置为
|
||||
```
|
||||
model/xxx.gguf
|
||||
```
|
||||
|
||||
DB我使用的是CodeFirst模式,只要配置好数据库链接,表结构是自动创建的
|
||||
16
docs/deploy/style.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# 找不到样式问题解决
|
||||
AntSK/src/AntSK下执行:
|
||||
```
|
||||
dotnet clean
|
||||
dotnet build
|
||||
dotnet publish "AntSK.csproj"
|
||||
```
|
||||
再去AntSK/src/AntSK/bin/Release/net8.0/publish下
|
||||
```
|
||||
dotnet AntSK.dll
|
||||
```
|
||||
然后启动就有样式了
|
||||
14
docs/develop/_category_.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"position": 2,
|
||||
"label": "快速开发",
|
||||
"collapsible": true,
|
||||
"collapsed": false,
|
||||
"className": "red",
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"title": "快速开发"
|
||||
},
|
||||
"customProps": {
|
||||
"description": "快速基于项目二次开发!"
|
||||
}
|
||||
}
|
||||
14
docs/introduce/_category_.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"position": 2,
|
||||
"label": "介绍",
|
||||
"collapsible": true,
|
||||
"collapsed": false,
|
||||
"className": "red",
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"title": "使用案例"
|
||||
},
|
||||
"customProps": {
|
||||
"description": "提供快速使用AntSK的一些案例!"
|
||||
}
|
||||
}
|
||||
BIN
docs/introduce/img/对话效果.png
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
docs/introduce/img/应用.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
docs/introduce/img/应用配置.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
docs/introduce/img/文档切片.png
Normal file
|
After Width: | Height: | Size: 202 KiB |
BIN
docs/introduce/img/知识库.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
docs/introduce/img/知识库详情.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
docs/introduce/img/简单对话.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
docs/introduce/img/问答.png
Normal file
|
After Width: | Height: | Size: 170 KiB |
70
docs/introduce/readme.md
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# AntSK功能介绍
|
||||
## 基于.Net8+AntBlazor+SemanticKernel 打造的AI知识库/智能体
|
||||
|
||||
## 核心功能
|
||||
|
||||
- **语义内核 (Semantic Kernel)**:采用领先的自然语言处理技术,准确理解、处理和响应复杂的语义查询,为用户提供精确的信息检索和推荐服务。
|
||||
|
||||
- **内存内核 (Kernel Memory)**:具备持续学习和存储知识点的能力,AntSK 拥有长期记忆功能,累积经验,提供更个性化的交互体验。
|
||||
|
||||
- **知识库**:通过文档(Word、PDF、Excel、Txt、Markdown、Json、PPT)等形式导入知识库,可以进行知识库问答。
|
||||
|
||||
- **GPTs 生成**:此平台支持创建个性化的GPT模型,尝试构建您自己的GPT模型。
|
||||
|
||||
- **API接口发布**:将内部功能以API的形式对外提供,便于开发者将AntSK 集成进其他应用,增强应用智慧。
|
||||
|
||||
- **API插件系统**:开放式API插件系统,允许第三方开发者或服务商轻松将其服务集成到AntSK,不断增强应用功能。
|
||||
|
||||
- **.Net插件系统**:开放式dll插件系统,允许第三方开发者或服务商轻松将其业务功能通过标准格式的代码生成dll后集成到AntSK,不断增强应用功能。
|
||||
|
||||
- **联网搜索**:AntSK,实时获取最新信息,确保用户接受到的资料总是最及时、最相关的。
|
||||
|
||||
- **模型管理**:适配和管理集成不同厂商的不同模型。并且支持**llama.cpp**所支持的gguf类型,以及**llamafactory**所支持的模型离线运行
|
||||
|
||||
- **国产信创**:AntSK支持国产模型,和国产数据库,可以在信创条件下运行
|
||||
|
||||
- **模型微调**:规划中,基于llamafactory进行模型微调
|
||||
|
||||
|
||||
## 应用场景
|
||||
|
||||
AntSK 适用于多种业务场景,例如:
|
||||
- 企业级知识管理系统
|
||||
- 自动客服与聊天机器人
|
||||
- 企业级搜索引擎
|
||||
- 个性化推荐系统
|
||||
- 智能辅助写作
|
||||
- 教育与在线学习平台
|
||||
- 其他有意思的AI App
|
||||
|
||||
## 功能示例
|
||||
|
||||
[视频示例](https://www.bilibili.com/video/BV1zH4y1h7Y9/)
|
||||
|
||||
首先需要创建知识库
|
||||

|
||||
|
||||
在知识库里可以使用文档或者url进行导入
|
||||

|
||||
|
||||
点击查看可以查看知识库的文档切片情况
|
||||

|
||||
|
||||
然后我们需要创建应用,可以创建对话应用和知识库。
|
||||

|
||||
|
||||
知识库应用需要选择已有的知识库,可以选多个
|
||||

|
||||
|
||||
然后再对话中可以对知识库的文档进行提问
|
||||

|
||||
|
||||
另外我们也可以创建对话应用,可以在对应应用中配置提示词模板
|
||||

|
||||
|
||||
下面来看看效果吧
|
||||

|
||||
BIN
images/gzh.jpg
Normal file
|
After Width: | Height: | Size: 180 KiB |
BIN
images/对话效果.png
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 101 KiB |
BIN
images/应用.png
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 54 KiB |
BIN
images/应用配置.png
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 53 KiB |
BIN
images/知识库.png
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 47 KiB |
BIN
images/简单对话.png
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 55 KiB |
BIN
images/问答.png
|
Before Width: | Height: | Size: 174 KiB After Width: | Height: | Size: 170 KiB |
20
src/AntSK.AppHost/AntSK.AppHost.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireHost>true</IsAspireHost>
|
||||
<UserSecretsId>32ac67c8-178a-4eeb-871d-879023582e06</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AntSK\AntSK.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
5
src/AntSK.AppHost/Program.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
var builder = DistributedApplication.CreateBuilder(args);
|
||||
|
||||
builder.AddProject<Projects.AntSK>("antsk");
|
||||
|
||||
builder.Build().Run();
|
||||
8
src/AntSK.AppHost/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/AntSK.AppHost/appsettings.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"Aspire.Hosting.Dcp": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/AntSK.AppHost/aspirate-output/docker-compose.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
services:
|
||||
aspire-dashboard:
|
||||
container_name: "aspire-dashboard"
|
||||
image: "mcr.microsoft.com/dotnet/aspire-dashboard:8.0"
|
||||
environment:
|
||||
DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS: "true"
|
||||
ports:
|
||||
- target: 18888
|
||||
published: 18888
|
||||
restart: unless-stopped
|
||||
antsk:
|
||||
container_name: "antsk"
|
||||
image: "antsk:latest"
|
||||
environment:
|
||||
OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES: "true"
|
||||
OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES: "true"
|
||||
OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY: "in_memory"
|
||||
ASPNETCORE_FORWARDEDHEADERS_ENABLED: "true"
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: "http://aspire-dashboard:18889"
|
||||
OTEL_SERVICE_NAME: "antsk"
|
||||
ports:
|
||||
- target: 8080
|
||||
published: 10000
|
||||
- target: 8443
|
||||
published: 10001
|
||||
restart: unless-stopped
|
||||
17
src/AntSK.AppHost/aspirate-state.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"projectPath": ".",
|
||||
"outputPath": "aspirate-output",
|
||||
"containerImageTags": [
|
||||
"latest"
|
||||
],
|
||||
"containerBuilder": "docker",
|
||||
"outputFormat": "compose",
|
||||
"privateRegistryEmail": "aspir8@aka.ms",
|
||||
"includeDashboard": true,
|
||||
"secrets": {
|
||||
"salt": "fjamZa3pQbM1UyY4",
|
||||
"hash": "QR\u002BSEr3p2SwD/w2oPE21vrWh/EerhNyVyTkr0atIREw=",
|
||||
"secrets": {}
|
||||
},
|
||||
"processAllComponents": true
|
||||
}
|
||||
26
src/AntSK.AppHost/manifest.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"resources": {
|
||||
"antsk": {
|
||||
"type": "project.v0",
|
||||
"path": "../AntSK/AntSK.csproj",
|
||||
"env": {
|
||||
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
|
||||
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
|
||||
"OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory",
|
||||
"ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true"
|
||||
},
|
||||
"bindings": {
|
||||
"http": {
|
||||
"scheme": "http",
|
||||
"protocol": "tcp",
|
||||
"transport": "http"
|
||||
},
|
||||
"https": {
|
||||
"scheme": "https",
|
||||
"protocol": "tcp",
|
||||
"transport": "http"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
53
src/AntSK.Domain/AntSK - Backup.Domain.csproj
Normal file
@@ -0,0 +1,53 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<DocumentationFile>AntSK.Domain.xml</DocumentationFile>
|
||||
<NoWarn>CA1050,CA1707,CA2007,VSTHRD111,CS1591,RCS1110,CA5394,SKEXP0001,SKEXP0002,SKEXP0003,SKEXP0004,SKEXP0010,SKEXP0011,,SKEXP0012,SKEXP0020,SKEXP0021,SKEXP0022,SKEXP0023,SKEXP0024,SKEXP0025,SKEXP0026,SKEXP0027,SKEXP0028,SKEXP0029,SKEXP0030,SKEXP0031,SKEXP0032,SKEXP0040,SKEXP0041,SKEXP0042,SKEXP0050,SKEXP0051,SKEXP0052,SKEXP0053,SKEXP0054,SKEXP0055,SKEXP0060,SKEXP0061,SKEXP0101,SKEXP0102</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AntDesign.Charts" Version="0.5.1" />
|
||||
<PackageReference Include="AntDesign.ProLayout" Version="0.18.2" />
|
||||
<PackageReference Include="BlazorComponents.Terminal" Version="0.6.0" />
|
||||
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
|
||||
|
||||
<PackageReference Include="pythonnet" Version="3.0.3" />
|
||||
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
|
||||
<PackageReference Include="AutoMapper" Version="8.1.0" />
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||
<PackageReference Include="Markdig" Version="0.37.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.151" />
|
||||
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.118" />
|
||||
<PackageReference Include="RestSharp" Version="110.2.0" />
|
||||
<PackageReference Include="NPOI" Version="2.7.0" />
|
||||
|
||||
<PackageReference Include="Microsoft.SemanticKernel" Version="1.7.1" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Core" Version="1.7.1" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Core" Version="1.7.1-alpha" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.Core" Version="0.36.240415.2" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Postgres" Version="0.36.240415.2" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Qdrant" Version="0.36.240415.2" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Redis" Version="0.36.240415.2" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.AzureAISearch" Version="0.36.240415.2" />
|
||||
|
||||
<PackageReference Include="LLamaSharp" Version="0.11.2" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cpu" Version="0.11.2" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cuda12" Version="0.11.2" />
|
||||
<PackageReference Include="LLamaSharp.kernel-memory" Version="0.11.2" />
|
||||
<PackageReference Include="LLamaSharp.semantic-kernel" Version="0.11.2" />
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AntSK.LLamaFactory\AntSK.LLamaFactory.csproj" />
|
||||
<ProjectReference Include="..\AntSk.LLM\AntSK.LLM.csproj" />
|
||||
<ProjectReference Include="..\AntSK.OCR\AntSK.OCR.csproj" />
|
||||
<ProjectReference Include="..\MiddleWare\AntSK.BackgroundTask\AntSK.BackgroundTask.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
59
src/AntSK.Domain/AntSK.Domain.csproj
Normal file
@@ -0,0 +1,59 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<DocumentationFile>AntSK.Domain.xml</DocumentationFile>
|
||||
<NoWarn>CA1050,CA1707,CA2007,VSTHRD111,CS1591,RCS1110,CA5394,SKEXP0001,SKEXP0002,SKEXP0003,SKEXP0004,SKEXP0010,SKEXP0011,,SKEXP0012,SKEXP0020,SKEXP0021,SKEXP0022,SKEXP0023,SKEXP0024,SKEXP0025,SKEXP0026,SKEXP0027,SKEXP0028,SKEXP0029,SKEXP0030,SKEXP0031,SKEXP0032,SKEXP0040,SKEXP0041,SKEXP0042,SKEXP0050,SKEXP0051,SKEXP0052,SKEXP0053,SKEXP0054,SKEXP0055,SKEXP0060,SKEXP0061,SKEXP0101,SKEXP0102,KMEXP00</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AntDesign.Charts" Version="0.5.5" />
|
||||
<PackageReference Include="AntDesign.ProLayout" Version="0.19.7" />
|
||||
<PackageReference Include="BlazorComponents.Terminal" Version="0.6.0" />
|
||||
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
|
||||
|
||||
<PackageReference Include="pythonnet" Version="3.0.3" />
|
||||
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.7.0" />
|
||||
|
||||
<PackageReference Include="AutoMapper" Version="8.1.0" />
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||
<PackageReference Include="Markdig" Version="0.37.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftVersion)" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.166" />
|
||||
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.118" />
|
||||
<PackageReference Include="RestSharp" Version="$(RestSharpVersion)" />
|
||||
<PackageReference Include="NPOI" Version="2.7.1" />
|
||||
|
||||
<PackageReference Include="Microsoft.SemanticKernel" Version="$(SKVersion)" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Core" Version="$(SKVersion)" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Core" Version="$(SKVersion)-alpha" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.Core" Version="$(KMVersion)" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Postgres" Version="$(KMVersion)" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Qdrant" Version="$(KMVersion)" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Redis" Version="$(KMVersion)" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.AzureAISearch" Version="$(KMVersion)" />
|
||||
|
||||
<PackageReference Include="LLamaSharp" Version="$(LLamaSharpVersion)" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cpu" Version="$(LLamaSharpVersion)" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cuda12" Version="$(LLamaSharpVersion)" />
|
||||
<PackageReference Include="LLamaSharp.kernel-memory" Version="$(LLamaSharpVersion)" />
|
||||
<PackageReference Include="LLamaSharp.semantic-kernel" Version="$(LLamaSharpVersion)" />
|
||||
|
||||
<PackageReference Include="Serilog" Version="4.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.1-dev-10391" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.2" />
|
||||
<PackageReference Include="Serilog.Sinks.Seq" Version="8.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.OpenTelemetry" Version="4.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AntSK.LLamaFactory\AntSK.LLamaFactory.csproj" />
|
||||
<ProjectReference Include="..\AntSk.LLM\AntSK.LLM.csproj" />
|
||||
<ProjectReference Include="..\AntSK.OCR\AntSK.OCR.csproj" />
|
||||
<ProjectReference Include="..\MiddleWare\AntSK.BackgroundTask\AntSK.BackgroundTask.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
1059
src/AntSK.Domain/AntSK.Domain.xml
Normal file
8
src/AntSK.Domain/Common/AntSkFunctionAttribute.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace AntSK.Domain.Common
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class AntSkFunctionAttribute : Attribute
|
||||
{
|
||||
// 自定义的ActionAttribute
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,5 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Common.DependencyInjection
|
||||
{
|
||||
175
src/AntSK.Domain/Common/DependencyInjection/InitExtensions.cs
Normal file
@@ -0,0 +1,175 @@
|
||||
using AntSK.Domain.Domain.Model.Constant;
|
||||
using AntSK.Domain.Domain.Service;
|
||||
using AntSK.Domain.Repositories;
|
||||
using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using SqlSugar;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Common.DependencyInjection
|
||||
{
|
||||
public static class InitExtensions
|
||||
{
|
||||
private static ILogger _logger;
|
||||
|
||||
public static void InitLog(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
/// <summary>
|
||||
/// 使用codefirst创建数据库表
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
public static WebApplication CodeFirst(this WebApplication app)
|
||||
{
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
// 获取仓储服务
|
||||
var _repository = scope.ServiceProvider.GetRequiredService<IApps_Repositories>();
|
||||
|
||||
// 创建数据库(如果不存在)
|
||||
_repository.GetDB().DbMaintenance.CreateDatabase();
|
||||
|
||||
// 获取当前应用程序域中所有程序集
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
|
||||
// 在所有程序集中查找具有[SugarTable]特性的类
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
// 获取该程序集中所有具有SugarTable特性的类型
|
||||
var entityTypes = assembly.GetTypes()
|
||||
.Where(type => TypeIsEntity(type));
|
||||
|
||||
// 为每个找到的类型初始化数据库表
|
||||
foreach (var type in entityTypes)
|
||||
{
|
||||
_repository.GetDB().CodeFirst.InitTables(type);
|
||||
}
|
||||
}
|
||||
//安装向量插件
|
||||
_repository.GetDB().Ado.ExecuteCommandAsync($"CREATE EXTENSION IF NOT EXISTS vector;");
|
||||
|
||||
_logger.LogInformation("初始化表结构完成");
|
||||
}
|
||||
return app;
|
||||
}
|
||||
|
||||
public static WebApplication InitDbData(this WebApplication app)
|
||||
{
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
// 初始化字典
|
||||
var _dic_Repository = scope.ServiceProvider.GetRequiredService<IDics_Repositories>();
|
||||
var llamafactoryStart = _dic_Repository.GetFirst(p => p.Type == LLamaFactoryConstantcs.LLamaFactorDic && p.Key == LLamaFactoryConstantcs.IsStartKey);
|
||||
if (llamafactoryStart==null)
|
||||
{
|
||||
llamafactoryStart = new Dics();
|
||||
llamafactoryStart.Id=Guid.NewGuid().ToString();
|
||||
llamafactoryStart.Type = LLamaFactoryConstantcs.LLamaFactorDic;
|
||||
llamafactoryStart.Key = LLamaFactoryConstantcs.IsStartKey;
|
||||
llamafactoryStart.Value = "false";
|
||||
_dic_Repository.Insert(llamafactoryStart);
|
||||
}
|
||||
_logger.LogInformation("初始化数据库初始数据完成");
|
||||
}
|
||||
return app;
|
||||
}
|
||||
/// <summary>
|
||||
/// 加载数据库的插件
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
public static WebApplication LoadFun(this WebApplication app)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
//codefirst 创建表
|
||||
var funRep = scope.ServiceProvider.GetRequiredService<IFuns_Repositories>();
|
||||
var functionService = scope.ServiceProvider.GetRequiredService<FunctionService>();
|
||||
var funs = funRep.GetList();
|
||||
foreach (var fun in funs)
|
||||
{
|
||||
functionService.FuncLoad(fun.Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message + " ---- " + ex.StackTrace);
|
||||
}
|
||||
return app;
|
||||
}
|
||||
private static bool TypeIsEntity(Type type)
|
||||
{
|
||||
// 检查类型是否具有SugarTable特性
|
||||
return type.GetCustomAttributes(typeof(SugarTable), inherit: false).Length > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// swagger 初始化
|
||||
/// </summary>
|
||||
/// <param name="serviceCollection"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddAntSKSwagger(this IServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddSwaggerGen(c =>
|
||||
{
|
||||
c.SwaggerDoc("v1", new() { Title = "AntSK.Api", Version = "v1" });
|
||||
//添加Api层注释(true表示显示控制器注释)
|
||||
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
||||
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
|
||||
c.IncludeXmlComments(xmlPath, true);
|
||||
//添加Domain层注释(true表示显示控制器注释)
|
||||
var xmlFile1 = $"{Assembly.GetExecutingAssembly().GetName().Name.Replace("Api", "Domain")}.xml";
|
||||
var xmlPath1 = Path.Combine(AppContext.BaseDirectory, xmlFile1);
|
||||
c.IncludeXmlComments(xmlPath1, true);
|
||||
c.DocInclusionPredicate((docName, apiDes) =>
|
||||
{
|
||||
if (!apiDes.TryGetMethodInfo(out MethodInfo method))
|
||||
return false;
|
||||
var version = method.DeclaringType.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);
|
||||
if (docName == "v1" && !version.Any())
|
||||
return true;
|
||||
var actionVersion = method.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);
|
||||
if (actionVersion.Any())
|
||||
return actionVersion.Any(v => v == docName);
|
||||
return version.Any(v => v == docName);
|
||||
});
|
||||
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
|
||||
{
|
||||
Description = "Directly enter bearer {token} in the box below (note that there is a space between bearer and token)",
|
||||
Name = "Authorization",
|
||||
In = ParameterLocation.Header,
|
||||
Type = SecuritySchemeType.ApiKey,
|
||||
});
|
||||
c.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||
{
|
||||
{
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Reference = new OpenApiReference()
|
||||
{
|
||||
Id = "Bearer",
|
||||
Type = ReferenceType.SecurityScheme
|
||||
}
|
||||
}, Array.Empty<string>()
|
||||
}
|
||||
});
|
||||
});
|
||||
return serviceCollection;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Common.DependencyInjection
|
||||
namespace AntSK.Domain.Common.DependencyInjection
|
||||
{
|
||||
public class ServiceDescriptionAttribute : Attribute
|
||||
{
|
||||
21
src/AntSK.Domain/Common/Embedding/BuilderBgeExtensions.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using LLamaSharp.KernelMemory;
|
||||
using Microsoft.KernelMemory.AI;
|
||||
using Microsoft.KernelMemory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Common.Embedding
|
||||
{
|
||||
public static class BuilderBgeExtensions
|
||||
{
|
||||
public static IKernelMemoryBuilder WithBgeTextEmbeddingGeneration(this IKernelMemoryBuilder builder, HuggingfaceTextEmbeddingGenerator textEmbeddingGenerator)
|
||||
{
|
||||
builder.AddSingleton((ITextEmbeddingGenerator)textEmbeddingGenerator);
|
||||
builder.AddIngestionEmbeddingGenerator(textEmbeddingGenerator);
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using LLama.Common;
|
||||
using LLama;
|
||||
using LLamaSharp.KernelMemory;
|
||||
using Microsoft.KernelMemory.AI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using AntSK.Domain.Domain.Other.Bge;
|
||||
|
||||
namespace AntSK.Domain.Common.Embedding
|
||||
{
|
||||
public class HuggingfaceTextEmbeddingGenerator : ITextEmbeddingGenerator, ITextTokenizer, IDisposable
|
||||
{
|
||||
public int MaxTokens => 1024;
|
||||
|
||||
public int MaxTokenTotal => 1024;
|
||||
|
||||
|
||||
private readonly dynamic _embedder;
|
||||
|
||||
public HuggingfaceTextEmbeddingGenerator(string pyDllPath,string modelName)
|
||||
{
|
||||
_embedder = BgeEmbeddingConfig.LoadModel(pyDllPath, modelName);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
BgeEmbeddingConfig.Dispose();
|
||||
}
|
||||
|
||||
//public async Task<IList<ReadOnlyMemory<float>>> GenerateEmbeddingAsync(IList<string> data, CancellationToken cancellationToken = default)
|
||||
//{
|
||||
// IList<ReadOnlyMemory<float>> results = new List<ReadOnlyMemory<float>>();
|
||||
|
||||
// foreach (var d in data)
|
||||
// {
|
||||
// var embeddings = await EmbeddingConfig.GetEmbedding(d);
|
||||
// results.Add(new ReadOnlyMemory<float>(embeddings));
|
||||
// }
|
||||
// return results;
|
||||
//}
|
||||
|
||||
public async Task<Microsoft.KernelMemory.Embedding> GenerateEmbeddingAsync(string text, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var embeddings = await BgeEmbeddingConfig.GetEmbedding(text);
|
||||
return new Microsoft.KernelMemory.Embedding(embeddings);
|
||||
}
|
||||
|
||||
public int CountTokens(string text)
|
||||
{
|
||||
return BgeEmbeddingConfig.TokenCount(text);
|
||||
}
|
||||
|
||||
public IReadOnlyList<string> GetTokens(string text)
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
822
src/AntSK.Domain/Common/Excel/ExeclHelper.cs
Normal file
@@ -0,0 +1,822 @@
|
||||
using NPOI.HSSF.UserModel;
|
||||
using NPOI.SS.UserModel;
|
||||
using NPOI.SS.Util;
|
||||
using NPOI.XSSF.Streaming;
|
||||
using NPOI.XSSF.UserModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain
|
||||
{
|
||||
public class ExeclHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 将excel导入到datatable
|
||||
/// </summary>
|
||||
/// <param name="filePath">excel路径</param>
|
||||
/// <param name="isColumnName">第一行是否是列名</param>
|
||||
/// <returns>返回datatable</returns>
|
||||
public static DataTable ExcelToDataTable(string filePath, bool isColumnName)
|
||||
{
|
||||
DataTable dataTable = null;
|
||||
FileStream fs = null;
|
||||
DataColumn column = null;
|
||||
DataRow dataRow = null;
|
||||
IWorkbook workbook = null;
|
||||
ISheet sheet = null;
|
||||
IRow row = null;
|
||||
ICell cell = null;
|
||||
int startRow = 0;
|
||||
try
|
||||
{
|
||||
using (fs = File.OpenRead(filePath))
|
||||
{
|
||||
// 2007版本
|
||||
if (filePath.Contains(".xlsx"))
|
||||
workbook = new XSSFWorkbook(fs);
|
||||
// 2003版本
|
||||
else if (filePath.Contains(".xls"))
|
||||
workbook = new HSSFWorkbook(fs);
|
||||
|
||||
if (workbook != null)
|
||||
{
|
||||
sheet = workbook.GetSheetAt(0);//读取第一个sheet,当然也可以循环读取每个sheet
|
||||
dataTable = new DataTable();
|
||||
if (sheet != null)
|
||||
{
|
||||
int rowCount = sheet.LastRowNum;//总行数
|
||||
if (rowCount > 0)
|
||||
{
|
||||
IRow firstRow = sheet.GetRow(0);//第一行
|
||||
int cellCount = firstRow.LastCellNum;//列数
|
||||
|
||||
//构建datatable的列
|
||||
if (isColumnName)
|
||||
{
|
||||
startRow = 1;//如果第一行是列名,则从第二行开始读取
|
||||
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
|
||||
{
|
||||
cell = firstRow.GetCell(i);
|
||||
if (cell != null)
|
||||
{
|
||||
if (cell.StringCellValue != null)
|
||||
{
|
||||
column = new DataColumn(cell.StringCellValue);
|
||||
dataTable.Columns.Add(column);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
|
||||
{
|
||||
column = new DataColumn("column" + (i + 1));
|
||||
dataTable.Columns.Add(column);
|
||||
}
|
||||
}
|
||||
|
||||
//填充行
|
||||
for (int i = startRow; i <= rowCount; ++i)
|
||||
{
|
||||
row = sheet.GetRow(i);
|
||||
if (row == null) continue;
|
||||
|
||||
dataRow = dataTable.NewRow();
|
||||
for (int j = row.FirstCellNum; j < cellCount; ++j)
|
||||
{
|
||||
cell = row.GetCell(j);
|
||||
if (cell == null)
|
||||
{
|
||||
dataRow[j] = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
//CellType(Unknown = -1,Numeric = 0,String = 1,Formula = 2,Blank = 3,Boolean = 4,Error = 5,)
|
||||
switch (cell.CellType)
|
||||
{
|
||||
case CellType.Blank:
|
||||
dataRow[j] = "";
|
||||
break;
|
||||
case CellType.Numeric:
|
||||
short format = cell.CellStyle.DataFormat;
|
||||
//对时间格式(2015.12.5、2015/12/5、2015-12-5等)的处理
|
||||
if (format == 14 || format == 31 || format == 57 || format == 58)
|
||||
dataRow[j] = cell.DateCellValue;
|
||||
else
|
||||
dataRow[j] = cell.NumericCellValue;
|
||||
break;
|
||||
case CellType.String:
|
||||
dataRow[j] = cell.StringCellValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
dataTable.Rows.Add(dataRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return dataTable;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (fs != null)
|
||||
{
|
||||
fs.Close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将excel导入到datatable
|
||||
/// </summary>
|
||||
/// <param name="stream">流</param>
|
||||
/// <param name="isColumnName">第一行是否是列名</param>
|
||||
/// <returns></returns>
|
||||
public static DataTable ExcelToDataTable(Stream stream, bool isColumnName)
|
||||
{
|
||||
DataTable dataTable = null;
|
||||
DataColumn column = null;
|
||||
DataRow dataRow = null;
|
||||
IWorkbook workbook = new XSSFWorkbook(stream);
|
||||
ISheet sheet = null;
|
||||
IRow row = null;
|
||||
ICell cell = null;
|
||||
int startRow = 0;
|
||||
try
|
||||
{
|
||||
|
||||
if (workbook != null)
|
||||
{
|
||||
sheet = workbook.GetSheetAt(0);//读取第一个sheet,当然也可以循环读取每个sheet
|
||||
dataTable = new DataTable();
|
||||
if (sheet != null)
|
||||
{
|
||||
int rowCount = sheet.LastRowNum;//总行数
|
||||
if (rowCount > 0)
|
||||
{
|
||||
IRow firstRow = sheet.GetRow(0);//第一行
|
||||
int cellCount = firstRow.LastCellNum;//列数
|
||||
|
||||
//构建datatable的列
|
||||
if (isColumnName)
|
||||
{
|
||||
startRow = 1;//如果第一行是列名,则从第二行开始读取
|
||||
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
|
||||
{
|
||||
cell = firstRow.GetCell(i);
|
||||
if (cell != null)
|
||||
{
|
||||
if (cell.StringCellValue != null)
|
||||
{
|
||||
column = new DataColumn(cell.StringCellValue);
|
||||
dataTable.Columns.Add(column);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
|
||||
{
|
||||
column = new DataColumn("column" + (i + 1));
|
||||
dataTable.Columns.Add(column);
|
||||
}
|
||||
}
|
||||
|
||||
//填充行
|
||||
for (int i = startRow; i <= rowCount; ++i)
|
||||
{
|
||||
row = sheet.GetRow(i);
|
||||
if (row == null) continue;
|
||||
|
||||
dataRow = dataTable.NewRow();
|
||||
for (int j = row.FirstCellNum; j < cellCount; ++j)
|
||||
{
|
||||
cell = row.GetCell(j);
|
||||
if (cell == null)
|
||||
{
|
||||
dataRow[j] = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
//CellType(Unknown = -1,Numeric = 0,String = 1,Formula = 2,Blank = 3,Boolean = 4,Error = 5,)
|
||||
switch (cell.CellType)
|
||||
{
|
||||
case CellType.Blank:
|
||||
dataRow[j] = "";
|
||||
break;
|
||||
case CellType.Numeric:
|
||||
short format = cell.CellStyle.DataFormat;
|
||||
//对时间格式(2015.12.5、2015/12/5、2015-12-5等)的处理
|
||||
if (format == 14 || format == 31 || format == 57 || format == 58)
|
||||
dataRow[j] = cell.DateCellValue;
|
||||
else
|
||||
dataRow[j] = cell.NumericCellValue;
|
||||
break;
|
||||
case CellType.String:
|
||||
dataRow[j] = cell.StringCellValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
dataTable.Rows.Add(dataRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dataTable;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// excel转list
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="stream"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<TResult> ExcelToList<TResult>(Stream stream) where TResult : new()
|
||||
{
|
||||
var propertyInfos = typeof(TResult).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.CustomAttributes.Count() > 0)
|
||||
.OrderBy(p => p.GetCustomAttribute<ExeclPropertyAttribute>().Order).ToArray();
|
||||
|
||||
List<TResult> list = new List<TResult>();
|
||||
|
||||
IWorkbook workbook = new XSSFWorkbook(stream);
|
||||
ISheet sheet = null;
|
||||
IRow row = null;
|
||||
ICell cell = null;
|
||||
int startRow = 1;
|
||||
try
|
||||
{
|
||||
|
||||
if (workbook != null)
|
||||
{
|
||||
sheet = workbook.GetSheetAt(0);//读取第一个sheet,当然也可以循环读取每个sheet
|
||||
if (sheet != null)
|
||||
{
|
||||
int rowCount = sheet.LastRowNum;//总行数
|
||||
if (rowCount > 0)
|
||||
{
|
||||
IRow firstRow = sheet.GetRow(0);//第一行
|
||||
int cellCount = firstRow.LastCellNum;//列数
|
||||
|
||||
//填充行
|
||||
for (int i = startRow; i <= rowCount; ++i)
|
||||
{
|
||||
row = sheet.GetRow(i);
|
||||
if (row == null) continue;
|
||||
bool emptyRow = true;//是否空行
|
||||
TResult dataModel = new TResult();
|
||||
|
||||
for (int j = row.FirstCellNum; j < cellCount; ++j)
|
||||
{
|
||||
var execlPropertyAttribute = propertyInfos[j].GetCustomAttribute<ExeclPropertyAttribute>();
|
||||
|
||||
cell = row.GetCell(j);
|
||||
if (cell == null)
|
||||
{
|
||||
propertyInfos[j].SetValue(dataModel, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (cell.CellType)
|
||||
{
|
||||
case CellType.Blank:
|
||||
propertyInfos[j].SetValue(dataModel, "");
|
||||
break;
|
||||
case CellType.Numeric:
|
||||
short format = cell.CellStyle.DataFormat;
|
||||
//对时间格式(2015.12.5、2015/12/5、2015-12-5等)的处理
|
||||
if (format == 14 || format == 31 || format == 57 || format == 58)
|
||||
propertyInfos[j].SetValue(dataModel, cell.DateCellValue);
|
||||
else
|
||||
{
|
||||
if (execlPropertyAttribute.CellType == CellType.String)
|
||||
{
|
||||
propertyInfos[j].SetValue(dataModel, cell.NumericCellValue.ToString());
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
propertyInfos[j].SetValue(dataModel, cell.NumericCellValue);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CellType.String:
|
||||
propertyInfos[j].SetValue(dataModel, cell.StringCellValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cell != null && !string.IsNullOrEmpty(cell.ToString().Trim()))
|
||||
{
|
||||
emptyRow = false;
|
||||
}
|
||||
}
|
||||
//非空数据行数据添加到DataTable
|
||||
if (!emptyRow)
|
||||
{
|
||||
list.Add(dataModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static IEnumerable<TResult> ExcelToListFileName<TResult>(Stream stream, string fileName) where TResult : new()
|
||||
{
|
||||
var propertyInfos = typeof(TResult).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.CustomAttributes.Count() > 0)
|
||||
.OrderBy(p => p.GetCustomAttribute<ExeclPropertyAttribute>().Order).ToArray();
|
||||
|
||||
List<TResult> list = new List<TResult>();
|
||||
|
||||
IWorkbook workbook = null;
|
||||
if (fileName.Contains(".xlsx"))
|
||||
workbook = new XSSFWorkbook(stream);
|
||||
// 2003版本
|
||||
else if (fileName.Contains(".xls"))
|
||||
workbook = new HSSFWorkbook(stream);
|
||||
ISheet sheet = null;
|
||||
IRow row = null;
|
||||
ICell cell = null;
|
||||
int startRow = 1;
|
||||
try
|
||||
{
|
||||
|
||||
if (workbook != null)
|
||||
{
|
||||
sheet = workbook.GetSheetAt(0);//读取第一个sheet,当然也可以循环读取每个sheet
|
||||
if (sheet != null)
|
||||
{
|
||||
int rowCount = sheet.LastRowNum;//总行数
|
||||
if (rowCount > 0)
|
||||
{
|
||||
IRow firstRow = sheet.GetRow(0);//第一行
|
||||
int cellCount = firstRow.LastCellNum;//列数
|
||||
|
||||
//填充行
|
||||
for (int i = startRow; i <= rowCount; ++i)
|
||||
{
|
||||
row = sheet.GetRow(i);
|
||||
if (row == null) continue;
|
||||
bool emptyRow = true;//是否空行
|
||||
TResult dataModel = new TResult();
|
||||
|
||||
for (int j = row.FirstCellNum; j < cellCount; ++j)
|
||||
{
|
||||
var execlPropertyAttribute = propertyInfos[j].GetCustomAttribute<ExeclPropertyAttribute>();
|
||||
|
||||
cell = row.GetCell(j);
|
||||
if (cell == null)
|
||||
{
|
||||
propertyInfos[j].SetValue(dataModel, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (cell.CellType)
|
||||
{
|
||||
case CellType.Blank:
|
||||
propertyInfos[j].SetValue(dataModel, "");
|
||||
break;
|
||||
case CellType.Numeric:
|
||||
short format = cell.CellStyle.DataFormat;
|
||||
//对时间格式(2015.12.5、2015/12/5、2015-12-5等)的处理
|
||||
if (format == 14 || format == 31 || format == 57 || format == 58)
|
||||
propertyInfos[j].SetValue(dataModel, cell.DateCellValue);
|
||||
else
|
||||
{
|
||||
if (execlPropertyAttribute.CellType == CellType.String)
|
||||
{
|
||||
propertyInfos[j].SetValue(dataModel, cell.NumericCellValue.ToString());
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
propertyInfos[j].SetValue(dataModel, cell.NumericCellValue);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CellType.String:
|
||||
propertyInfos[j].SetValue(dataModel, cell.StringCellValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cell != null && !string.IsNullOrEmpty(cell.ToString().Trim()))
|
||||
{
|
||||
emptyRow = false;
|
||||
}
|
||||
}
|
||||
//非空数据行数据添加到DataTable
|
||||
if (!emptyRow)
|
||||
{
|
||||
list.Add(dataModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// excel转list-根据sheetName得到List
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="sheetName"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<TResult> ExcelToList<TResult>(Stream stream, string sheetName) where TResult : new()
|
||||
{
|
||||
var propertyInfos = typeof(TResult).GetProperties(BindingFlags.Public | BindingFlags.Instance)
|
||||
.OrderBy(p => p.GetCustomAttribute<ExeclPropertyAttribute>().Order).ToArray();
|
||||
|
||||
List<TResult> list = new List<TResult>();
|
||||
|
||||
IWorkbook workbook = new XSSFWorkbook(stream);
|
||||
ISheet sheet = null;
|
||||
IRow row = null;
|
||||
ICell cell = null;
|
||||
int startRow = 1;
|
||||
try
|
||||
{
|
||||
|
||||
if (workbook != null)
|
||||
{
|
||||
sheet = workbook.GetSheet(sheetName);//根据sheet读取对应的DataTable
|
||||
if (sheet != null)
|
||||
{
|
||||
int rowCount = sheet.LastRowNum;//总行数
|
||||
if (rowCount > 0)
|
||||
{
|
||||
IRow firstRow = sheet.GetRow(0);//第一行
|
||||
int cellCount = firstRow.LastCellNum;//列数
|
||||
|
||||
//填充行
|
||||
for (int i = startRow; i <= rowCount; ++i)
|
||||
{
|
||||
row = sheet.GetRow(i);
|
||||
if (row == null) continue;
|
||||
bool emptyRow = true;//是否空行
|
||||
|
||||
TResult dataModel = new TResult();
|
||||
|
||||
for (int j = row.FirstCellNum; j < cellCount; ++j)
|
||||
{
|
||||
var execlPropertyAttribute = propertyInfos[j].GetCustomAttribute<ExeclPropertyAttribute>();
|
||||
|
||||
cell = row.GetCell(j);
|
||||
if (cell == null)
|
||||
{
|
||||
propertyInfos[j].SetValue(dataModel, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (cell.CellType)
|
||||
{
|
||||
case CellType.Blank:
|
||||
propertyInfos[j].SetValue(dataModel, "");
|
||||
break;
|
||||
case CellType.Numeric:
|
||||
short format = cell.CellStyle.DataFormat;
|
||||
//对时间格式(2015.12.5、2015/12/5、2015-12-5等)的处理
|
||||
if (format == 14 || format == 31 || format == 57 || format == 58)
|
||||
propertyInfos[j].SetValue(dataModel, cell.DateCellValue);
|
||||
else
|
||||
{
|
||||
if (execlPropertyAttribute.CellType == CellType.String)
|
||||
{
|
||||
propertyInfos[j].SetValue(dataModel, cell.NumericCellValue.ToString());
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
propertyInfos[j].SetValue(dataModel, cell.NumericCellValue);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case CellType.String:
|
||||
propertyInfos[j].SetValue(dataModel, cell.StringCellValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cell != null && !string.IsNullOrEmpty(cell.ToString().Trim()))
|
||||
{
|
||||
emptyRow = false;
|
||||
}
|
||||
}
|
||||
//非空数据行数据添加到DataTable
|
||||
if (!emptyRow)
|
||||
{
|
||||
list.Add(dataModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List导出excel 二进制流
|
||||
/// </summary>
|
||||
/// <typeparam name="T">实体</typeparam>
|
||||
/// <param name="data">List</param>
|
||||
/// <param name="sheetName">sheetname 可不填,默认Sheet0</param>
|
||||
/// <returns></returns>
|
||||
public static byte[] ListToExcel<T>(T[] data, string sheetName = "Sheet0")
|
||||
{
|
||||
IWorkbook workbook = null;
|
||||
IRow row = null;
|
||||
ISheet sheet = null;
|
||||
ICell cell = null;
|
||||
var propertyInfos = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)
|
||||
.OrderBy(p => p.GetCustomAttribute<ExeclPropertyAttribute>().Order).ToArray();
|
||||
workbook = new XSSFWorkbook();
|
||||
sheet = workbook.CreateSheet(sheetName);//创建一个名称为Sheet0的表
|
||||
int rowCount = data.Count();//行数
|
||||
int columnCount = propertyInfos.Length;//列数
|
||||
//设置列头
|
||||
row = sheet.CreateRow(0);//excel第一行设为列头
|
||||
for (int c = 0; c < columnCount; c++)
|
||||
{
|
||||
cell = row.CreateCell(c);
|
||||
cell.SetCellValue(propertyInfos[c].GetCustomAttribute<ExeclPropertyAttribute>().DisplayName);
|
||||
}
|
||||
//设置每行每列的单元格,
|
||||
for (int i = 0; i < rowCount; i++)
|
||||
{
|
||||
row = sheet.CreateRow(i + 1);
|
||||
for (int j = 0; j < columnCount; j++)
|
||||
{
|
||||
cell = row.CreateCell(j);//excel第二行开始写入数据
|
||||
cell.SetCellValue(propertyInfos[j].GetValue(data[i])?.ToString());
|
||||
}
|
||||
}
|
||||
using (MemoryStream memoryStream = new MemoryStream())
|
||||
{
|
||||
workbook.Write(memoryStream);//向打开的这个xls文件中写入数据
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dt导出excel 二进制流
|
||||
/// </summary>
|
||||
/// <param name="dt">datatable</param>
|
||||
/// <param name="strFile">strFile</param>
|
||||
/// <returns></returns>
|
||||
public static byte[] DataTableToExcel(DataTable dt, string strFile, string sheetName = "Sheet0")
|
||||
{
|
||||
bool result = false;
|
||||
IWorkbook workbook = null;
|
||||
FileStream fs = null;
|
||||
IRow row = null;
|
||||
ISheet sheet = null;
|
||||
ICell cell = null;
|
||||
|
||||
if (dt != null && dt.Rows.Count > 0)
|
||||
{
|
||||
workbook = new XSSFWorkbook();
|
||||
sheet = workbook.CreateSheet(sheetName);//创建一个名称为Sheet0的表
|
||||
int rowCount = dt.Rows.Count;//行数
|
||||
int columnCount = dt.Columns.Count;//列数
|
||||
|
||||
//设置列头
|
||||
row = sheet.CreateRow(0);//excel第一行设为列头
|
||||
for (int c = 0; c < columnCount; c++)
|
||||
{
|
||||
cell = row.CreateCell(c);
|
||||
cell.SetCellValue(dt.Columns[c].ColumnName);
|
||||
}
|
||||
|
||||
//设置每行每列的单元格,
|
||||
for (int i = 0; i < rowCount; i++)
|
||||
{
|
||||
row = sheet.CreateRow(i + 1);
|
||||
for (int j = 0; j < columnCount; j++)
|
||||
{
|
||||
cell = row.CreateCell(j);//excel第二行开始写入数据
|
||||
cell.SetCellValue(dt.Rows[i][j].ToString());
|
||||
}
|
||||
}
|
||||
using (MemoryStream memoryStream = new MemoryStream())
|
||||
{
|
||||
workbook.Write(memoryStream);//向打开的这个xls文件中写入数据
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List写入excel
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="strFile">路径</param>
|
||||
/// <param name="sheetName"></param>
|
||||
/// <returns></returns>
|
||||
public static bool ListWriteExcel<T>(T[] data, string strFile, string sheetName = "Sheet0")
|
||||
{
|
||||
bool result = false;
|
||||
IWorkbook workbook = null;
|
||||
FileStream fs = null;
|
||||
IRow row = null;
|
||||
ISheet sheet = null;
|
||||
ICell cell = null;
|
||||
try
|
||||
{
|
||||
var propertyInfos = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)
|
||||
.OrderBy(p => p.GetCustomAttribute<ExeclPropertyAttribute>().Order).ToArray();
|
||||
workbook = new XSSFWorkbook();
|
||||
sheet = workbook.CreateSheet(sheetName);//创建一个名称为Sheet0的表
|
||||
int rowCount = data.Count();//行数
|
||||
int columnCount = propertyInfos.Length;//列数
|
||||
//设置列头
|
||||
row = sheet.CreateRow(0);//excel第一行设为列头
|
||||
for (int c = 0; c < columnCount; c++)
|
||||
{
|
||||
cell = row.CreateCell(c);
|
||||
cell.SetCellValue(propertyInfos[c].GetCustomAttribute<ExeclPropertyAttribute>().DisplayName);
|
||||
}
|
||||
//设置每行每列的单元格,
|
||||
for (int i = 0; i < rowCount; i++)
|
||||
{
|
||||
row = sheet.CreateRow(i + 1);
|
||||
for (int j = 0; j < columnCount; j++)
|
||||
{
|
||||
cell = row.CreateCell(j);//excel第二行开始写入数据
|
||||
cell.SetCellValue(propertyInfos[j].GetValue(data[i])?.ToString());
|
||||
}
|
||||
}
|
||||
using (fs = File.OpenWrite(strFile))
|
||||
{
|
||||
workbook.Write(fs);//向打开的这个xls文件中写入数据
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (fs != null)
|
||||
{
|
||||
fs.Close();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// dt写入excel
|
||||
/// </summary>
|
||||
/// <param name="dt">datatable</param>
|
||||
/// <param name="strFile">路径</param>
|
||||
/// <returns></returns>
|
||||
public static bool DataTableWriteExcel(DataTable dt, string strFile, string sheetName = "Sheet0")
|
||||
{
|
||||
bool result = false;
|
||||
IWorkbook workbook = null;
|
||||
FileStream fs = null;
|
||||
IRow row = null;
|
||||
ISheet sheet = null;
|
||||
ICell cell = null;
|
||||
try
|
||||
{
|
||||
if (dt != null && dt.Rows.Count > 0)
|
||||
{
|
||||
workbook = new XSSFWorkbook();
|
||||
sheet = workbook.CreateSheet(sheetName);//创建一个名称为Sheet0的表
|
||||
int rowCount = dt.Rows.Count;//行数
|
||||
int columnCount = dt.Columns.Count;//列数
|
||||
|
||||
//设置列头
|
||||
row = sheet.CreateRow(0);//excel第一行设为列头
|
||||
for (int c = 0; c < columnCount; c++)
|
||||
{
|
||||
cell = row.CreateCell(c);
|
||||
cell.SetCellValue(dt.Columns[c].ColumnName);
|
||||
}
|
||||
|
||||
//设置每行每列的单元格,
|
||||
for (int i = 0; i < rowCount; i++)
|
||||
{
|
||||
row = sheet.CreateRow(i + 1);
|
||||
for (int j = 0; j < columnCount; j++)
|
||||
{
|
||||
cell = row.CreateCell(j);//excel第二行开始写入数据
|
||||
cell.SetCellValue(dt.Rows[i][j].ToString());
|
||||
}
|
||||
}
|
||||
using (fs = File.OpenWrite(strFile))
|
||||
{
|
||||
workbook.Write(fs);//向打开的这个xls文件中写入数据
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (fs != null)
|
||||
{
|
||||
fs.Close();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置单元格下拉框(除去标题行)
|
||||
/// </summary>
|
||||
/// <param name="workbook"></param>
|
||||
/// <param name="sheet"></param>
|
||||
/// <param name="ddlList"></param>
|
||||
/// <param name="firstcol"></param>
|
||||
/// <param name="lastcol"></param>
|
||||
public static void SetCellDropdownList(IWorkbook workbook, ISheet sheet, List<string> ddlList, string sheetname, int sheetIndex, int firstcol, int lastcol)
|
||||
{
|
||||
|
||||
# region 低版本Excel【HSSFWorkbook】设置下拉框
|
||||
//ISheet sheet2 = workbook.CreateSheet(sheetname);
|
||||
|
||||
////隐藏
|
||||
//workbook.SetSheetHidden(sheetIndex, 1);
|
||||
//int rowIndex = 0;
|
||||
//foreach (var item in ddlList)
|
||||
//{
|
||||
// IRow vrow = sheet2.CreateRow(rowIndex);
|
||||
// vrow.CreateCell(0).SetCellValue(item);
|
||||
|
||||
// rowIndex++;
|
||||
//}
|
||||
|
||||
////创建的下拉项的区域:
|
||||
//var rangeName = sheetname + "Range";
|
||||
//IName range = workbook.CreateName();
|
||||
//range.RefersToFormula = sheetname + "!$A$1:$A$" + rowIndex;
|
||||
//range.NameName = rangeName;
|
||||
//CellRangeAddressList regions = new CellRangeAddressList(1, 65535, firstcol, lastcol);
|
||||
|
||||
//DVConstraint constraint = DVConstraint.CreateFormulaListConstraint(rangeName);
|
||||
//HSSFDataValidation dataValidate = new HSSFDataValidation(regions, constraint);
|
||||
//dataValidate.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。");
|
||||
//dataValidate.ShowPromptBox = true;
|
||||
//sheet.AddValidationData(dataValidate);
|
||||
#endregion
|
||||
|
||||
//高版本excel【XSSFWorkbook】 设置下拉框
|
||||
XSSFSheet sheetDDL = (XSSFSheet)workbook.CreateSheet(sheetname);
|
||||
workbook.SetSheetHidden(sheetIndex, 1); //隐藏下拉框数据sheet
|
||||
String[] datas = ddlList.ToArray(); //下拉框数据源
|
||||
XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper(sheetDDL);
|
||||
XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint)dvHelper.CreateExplicitListConstraint(datas);
|
||||
CellRangeAddressList addressList = new CellRangeAddressList(1, 65535, firstcol, lastcol); //下拉设置列
|
||||
XSSFDataValidation validation = (XSSFDataValidation)dvHelper.CreateValidation(dvConstraint, addressList);
|
||||
|
||||
validation.SuppressDropDownArrow = true;
|
||||
validation.ShowErrorBox = true;
|
||||
validation.ShowPromptBox = true;
|
||||
sheet.AddValidationData(validation);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/AntSK.Domain/Common/Excel/ExeclPropertyAttribute.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using NPOI.SS.UserModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain
|
||||
{
|
||||
public class ExeclPropertyAttribute : Attribute
|
||||
{
|
||||
public ExeclPropertyAttribute()
|
||||
{
|
||||
|
||||
}
|
||||
public ExeclPropertyAttribute(string displayName, int order, CellType cellType = CellType.String)
|
||||
{
|
||||
DisplayName = displayName;
|
||||
Order = order;
|
||||
CellType = cellType;
|
||||
}
|
||||
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
public int Order { get; set; }
|
||||
|
||||
public CellType CellType { get; set; }
|
||||
}
|
||||
}
|
||||
73
src/AntSK.Domain/Common/LLamaFactory/ProcessWrapper.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using Amazon.Runtime.Internal.Util;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Common.LLamaFactory
|
||||
{
|
||||
public class ProcessWrapper(ILogger<ProcessWrapper> _logger)
|
||||
{
|
||||
private Process process;
|
||||
|
||||
public static bool isProcessComplete = false;
|
||||
|
||||
|
||||
public void StartProcess(string arguments, string workingDirectory)
|
||||
{
|
||||
process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "python",
|
||||
Arguments = arguments,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true,
|
||||
WorkingDirectory = workingDirectory
|
||||
}
|
||||
};
|
||||
using (Process start = Process.Start(process.StartInfo))
|
||||
{
|
||||
using (StreamReader reader = start.StandardOutput)
|
||||
{
|
||||
string result = reader.ReadToEnd();
|
||||
if (result != null)
|
||||
{
|
||||
if (result.Contains(":8000"))
|
||||
{
|
||||
isProcessComplete = true;
|
||||
}
|
||||
}
|
||||
_logger.LogInformation(result);
|
||||
}
|
||||
start.WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
public string WaitForProcessExit()
|
||||
{
|
||||
process.WaitForExit();
|
||||
return process.StandardOutput.ReadToEnd();
|
||||
}
|
||||
|
||||
public void KillProcess()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!process.HasExited)
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// Process already exited.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/AntSK.Domain/Common/Map/AutoMapProfile.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using AutoMapper;
|
||||
|
||||
namespace AntSK.Domain.Common.Map
|
||||
{
|
||||
public class AutoMapProfile : Profile
|
||||
{
|
||||
public AutoMapProfile()
|
||||
{
|
||||
//CreateMap<PMP_BizCase_Main_Max, BizcaseQueryDTO>();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/AntSK.Domain/Common/Map/MapperExtend.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
namespace AntSK.Domain.Common.Map
|
||||
{
|
||||
public static class MapperExtend
|
||||
{
|
||||
/// <summary>
|
||||
/// Entity集合转DTO集合
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static List<T> ToDTOList<T>(this object value)
|
||||
{
|
||||
if (value == null)
|
||||
return new List<T>();
|
||||
|
||||
return AutoMapper.Mapper.Map<List<T>>(value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Entity转DTO
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static T ToDTO<T>(this object value)
|
||||
{
|
||||
if (value == null)
|
||||
return default(T);
|
||||
|
||||
return AutoMapper.Mapper.Map<T>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,7 @@
|
||||
using AutoMapper;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Map
|
||||
namespace AntSK.Domain.Common.Map
|
||||
{
|
||||
public static class MapperRegister
|
||||
{
|
||||
@@ -16,7 +11,6 @@ namespace AntSK.Domain.Map
|
||||
{
|
||||
cfg.CreateMissingTypeMaps = true;
|
||||
cfg.ValidateInlineMaps = false;
|
||||
cfg.ShouldMapMethod = m => false;
|
||||
cfg.AddProfile<AutoMapProfile>();
|
||||
});
|
||||
|
||||
@@ -27,7 +21,6 @@ namespace AntSK.Domain.Map
|
||||
{
|
||||
cfg.CreateMissingTypeMaps = true;
|
||||
cfg.ValidateInlineMaps = false;
|
||||
cfg.ShouldMapMethod = m => false;
|
||||
cfg.AddProfile<AutoMapProfile>();
|
||||
});
|
||||
}
|
||||
23
src/AntSK.Domain/Domain/Interface/IChatService.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using AntSK.Domain.Domain.Model;
|
||||
using AntSK.Domain.Domain.Model.Dto;
|
||||
using AntSK.Domain.Repositories;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AntSK.Domain.Domain.Interface
|
||||
{
|
||||
public interface IChatService
|
||||
{
|
||||
IAsyncEnumerable<string> SendChatByAppAsync(Apps app, ChatHistory history);
|
||||
|
||||
IAsyncEnumerable<StreamingKernelContent> SendKmsByAppAsync(Apps app, string questions, ChatHistory history, string filePath, List<RelevantSource> relevantSources = null);
|
||||
Task<string> SendImgByAppAsync(Apps app, string questions);
|
||||
Task<ChatHistory> GetChatHistory(List<Chats> MessageList, ChatHistory history);
|
||||
}
|
||||
}
|
||||
9
src/AntSK.Domain/Domain/Interface/IHttpService.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using RestSharp;
|
||||
|
||||
namespace AntSK.Domain.Domain.Interface
|
||||
{
|
||||
public interface IHttpService
|
||||
{
|
||||
Task<RestResponse> PostAsync(string url, Object jsonBody);
|
||||
}
|
||||
}
|
||||