Compare commits

..

No commits in common. "30aa0faaa17055e3f9e779419bb1a504d9abf194" and "ef0e315bdc544f2f76f4a43652a13a5bdb5bc9a4" have entirely different histories.

35 changed files with 333 additions and 1125 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 763 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 941 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 610 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon" viewBox="0 0 64 64" width="24" height="24"><defs></defs><g><path fill="#3e4347" d="M64 57.6c0 3.5-2.9 6.4-6.4 6.4H6.4C2.9 64 0 61.1 0 57.6V6.4C0 2.9 2.9 0 6.4 0h51.2C61.1 0 64 2.9 64 6.4z"></path><circle cx="32" cy="32" r="32" fill="#42ade2"></circle><path fill="#fff" d="M32 40.4c-4.6 0-8.4-3.8-8.4-8.4s3.8-8.4 8.4-8.4s8.4 3.8 8.4 8.4s-3.8 8.4-8.4 8.4"></path><path fill="#3e4347" d="M38.4 24c-3.5 0-6.4 2.9-6.4 6.4v3.2c0 3.5 2.9 6.4 6.4 6.4H64V24z"></path></g></svg>

Before

Width:  |  Height:  |  Size: 590 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon" viewBox="0 0 64 64" width="24" height="24"><defs></defs><g><g fill="#333"><path d="M0 0h4v64H0z"></path><path d="M0 60h64v4H0z"></path></g><path fill="#fb4f00" d="M38.7 60h12V6.7L38.7 20z"></path><path fill="#5c750a" d="M21.3 60h12V20l-12 13.3z"></path><path fill="#106995" d="M4 60h12V33.3L4 46.7z"></path><path fill="#9aca0a" d="M33.3 20h13.3v40H33.3z"></path><path fill="#21adf1" d="M16 33.3h13.3V60H16z"></path><path fill="#fc9100" d="M50.7 6.7H64V60H50.7z"></path></g></svg>

Before

Width:  |  Height:  |  Size: 601 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon" viewBox="0 0 64 64" width="24" height="24"><defs></defs><g><path fill="#616466" d="M28 58c0 2.2 1.8 4 4 4s4-1.8 4-4z"></path><path fill="#ffce31" d="M24.9 48H39c.8-4.3 3.5-8.5 6.3-12.9C48.6 30 52 24.7 52 19.6C52 9.9 43 2 32 2S12 9.9 12 19.6c0 5.1 3.4 10.4 6.6 15.5c2.8 4.4 5.5 8.6 6.3 12.9"></path><path fill="#c79127" d="M26.4 33.6c.1.6.3 1.2.4 1.8c.3 1.1.5 2.1.8 3.2c.9 3.8 1.7 7 2.4 9.5h.6c-.5-2.5-1.2-5.8-2.1-9.6c-.2-1-.5-2.1-.7-3.2c-.1-.5-.2-1.1-.4-1.6c.8-.2 2.7-.8 4.6-2.9c1.9 2.1 3.8 2.7 4.6 2.9c-.1.6-.2 1.1-.4 1.6c-.2 1.1-.5 2.2-.7 3.2c-.9 3.8-1.6 7.1-2.1 9.6h.6c.6-2.5 1.5-5.7 2.4-9.5c.2-1 .5-2.1.8-3.2c.1-.6.3-1.2.4-1.8c.8-.1 1.5-.3 2-.8c.6-.6.9-1.3.7-2.1c-.1-.4-.3-.9-.9-1c-.3-.1-.5-.1-.8 0s-.5.3-.6.4c-.5.6-.7 1.2-.9 1.8l-.3.9s-.8.1-2.7-1.2c-1-.7-1.3-1.2-1.6-1.5c.3-.4.6-.7.9-1.2c.1-.3.2-.5.3-.9c0-.3 0-.7-.2-1s-.4-.6-.9-.8c-.2-.1-.4-.1-.6-.1s-.4 0-.6.1c-.4.2-.7.5-.9.8s-.2.7-.2 1q0 .45.3.9q.3.75.9 1.2c-.3.3-.6.8-1.6 1.5c-1.8 1.2-2.7 1.2-2.7 1.2l-.3-.9c-.2-.6-.4-1.2-.9-1.8c-.1-.1-.3-.3-.6-.4s-.6-.1-.8 0c-.6.2-.8.7-.9 1c-.1.8.2 1.5.7 2.1c.6.5 1.3.7 2 .8M38 32.1c.2-.5.4-1.1.8-1.4c.1-.1.2-.1.2-.1h.2c.1 0 .2.1.3.4c.1.4-.1 1-.5 1.3c-.3.2-.7.4-1.1.5c0-.3 0-.5.1-.7m-6.6-4.8c.2-.2.4-.4.6-.4s.4.1.6.4s.1.7-.1 1.1c-.1.3-.3.6-.5.8c-.2-.3-.4-.5-.5-.8c-.2-.3-.3-.7-.1-1.1m-6.8 3.5c0-.2.1-.3.3-.4h.2s.1.1.2.1c.3.3.6.9.8 1.4c.1.2.1.4.2.6c-.4-.1-.8-.2-1.1-.5c-.4-.2-.6-.7-.6-1.2"></path><path fill="#94989b" d="M24.9 50h14.3v1.8H24.9zm1 3.6h12.3v1.8H25.9z"></path><path fill="#616466" d="M25.9 51.8h12.3v1.8H25.9z"></path><path fill="#94989b" d="m39.2 50l-13.3 3.6v1.9l13.3-3.7zm-12.3 7.3h10.3v1.8H26.9z"></path><path fill="#616466" d="M26.9 55.5h10.3v1.8H26.9z"></path><path fill="#94989b" d="m38.2 53.6l-11.3 3.7v1.9l11.3-3.7z"></path></g></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon" viewBox="0 0 64 64" width="24" height="24"><defs></defs><g><path fill="#d0d0d0" d="M23.6 36.7H2.9l10.3-26.2zm-18-1.9h15.3l-7.7-19.5zm55.5 1.9H40.4l10.3-26.2zm-18-1.9h15.3l-7.7-19.5z"></path><path fill="#b8c2c4" d="M50.3 10.2s-2.2-.8-3.4-1.3C42.6 7.1 37.3 5 32 5S21.4 7.2 17.1 9c-1.2.5-3.4 1.3-3.4 1.3l-3.3 2.5s2.7 1.7 4 1.2c1.1-.4 2.2-.9 3.5-1.4C22 10.9 27.1 8.8 32 8.8s10 2.1 14.1 3.8c1.2.5 2.4 1 3.5 1.4c1.4.5 4-1.2 4-1.2z"></path><path fill="#428bc1" d="M2 34.8C2 41 7 46 13.2 46s11.2-5 11.2-11.2zm37.5 0c0 6.2 5 11.2 11.2 11.2S62 41 62 34.8z"></path><path fill="#b8c2c4" d="M30.1 12.3h3.8v41.2h-3.8z"></path><path fill="#d0d0d0" d="M29 18.6h6.1v34.9H29z"></path><path fill="#545b60" d="M27.7 36.7h8.6v19.7h-8.6z"></path><circle cx="13.2" cy="13.2" r="3.8" fill="#dbb471"></circle><g fill="#545b60"><circle cx="50.8" cy="13.2" r="3.8"></circle><circle cx="13.2" cy="13.2" r="3.8"></circle></g><g fill="#fff"><circle cx="13.2" cy="13.2" r="1.9"></circle><circle cx="50.8" cy="13.2" r="1.9"></circle></g><g fill="#d0d0d0"><circle cx="32" cy="7.6" r="5.6"></circle><path d="M32 45.1c-8.3 0-15 4.2-15 9.4h30c0-5.2-6.7-9.4-15-9.4"></path></g><path fill="#545b60" d="M15.1 54.5h33.8v3.8H15.1z"></path><path fill="#6b767c" d="M11.4 58.2h41.2V62H11.4z"></path></g></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon" viewBox="0 0 64 64" width="24" height="24"><defs></defs><g><path fill="#979797" d="M64 31.7h-5.6c-7.3-5-11.9-13.2-12.4-22.1l2.8-5l-1.6-1l-2.8 5c-7.8 4-17 4-24.8 0l-2.8-5l-1.6 1l2.8 5c-.5 8.9-5.1 17.2-12.4 22.1H0v1.9h5.6c7.3 4.9 11.9 13.2 12.4 22.1l-2.8 5l1.6 1l2.8-5c7.8-4 17-4 24.8 0l2.8 5l1.6-1l-2.8-5c.5-8.9 5.1-17.2 12.4-22.1H64zm-8.7 0h-5.5c-4.7-3.2-7.8-8.6-8.1-14.4l2.8-4.9c1 7.6 4.9 14.5 10.8 19.3m-23.3-1l-2.3-4.1c.7.2 1.5.3 2.3.3s1.6-.1 2.3-.3zm3.9-3.1c.5 1.5 1.3 2.9 2.3 4.1h-4.6zm-5.5 4.1h-4.6c1-1.2 1.8-2.6 2.3-4.1zm0 1.9l-2.3 4.1c-.5-1.5-1.3-2.9-2.3-4.1zm1.6.9l2.3 4.1c-1.5-.3-3.1-.3-4.6 0zm1.6-.9h4.6c-1 1.2-1.8 2.6-2.3 4.1zm7.4-1.9c-2.1-1.5-3.5-3.9-3.7-6.6l2.9-5.1c.8 4.5 3.1 8.7 6.5 11.7zm-5.3-7.6c-2.3 1.2-5.1 1.2-7.4 0L25.5 19c2.1.8 4.3 1.1 6.5 1.1s4.4-.4 6.5-1.1zm-9 .9c-.2 2.7-1.5 5.1-3.7 6.6h-5.7c3.4-3 5.7-7.1 6.5-11.7zM23 33.6c2.1 1.5 3.5 3.9 3.7 6.6l-2.9 5.1c-.8-4.5-3.1-8.7-6.5-11.7zm5.3 7.5c2.3-1.2 5.1-1.2 7.4 0l2.9 5.1c-4.2-1.5-8.9-1.5-13.1 0zm9-.9c.2-2.7 1.5-5.1 3.7-6.6h5.7c-3.4 3-5.7 7.1-6.5 11.7zM32 13.5c3.7 0 7.4-.7 10.8-2.1L40 16.3c-5.1 2.6-11.1 2.6-16.1 0l-2.8-4.9c3.5 1.4 7.2 2.1 10.9 2.1m-12.4-1.1l2.8 4.9c-.4 5.8-3.4 11.2-8.1 14.4H8.7c5.9-4.8 9.8-11.7 10.9-19.3M8.8 33.6h5.5c4.7 3.2 7.7 8.5 8 14.4l-2.8 4.9c-1-7.6-4.9-14.6-10.7-19.3m12.4 20.2l2.8-4.9c5.1-2.6 11.1-2.6 16.1 0l2.8 4.9c-7-2.8-14.8-2.8-21.7 0m23.2-.9L41.7 48c.3-5.8 3.3-11.2 8.1-14.4h5.5c-5.9 4.7-9.8 11.7-10.9 19.3"></path></g></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon" viewBox="0 0 64 64" width="24" height="24"><defs></defs><g><path fill="#212528" d="M21.6 16.1c0 1.2-1 2.2-2.2 2.2H9.7c-1.2 0-2.2-1-2.2-2.2v-2.7c0-1.2 1-2.2 2.2-2.2h9.7c1.2 0 2.2 1 2.2 2.2zm39.1-.2c0 .6-.5 1.2-1.2 1.2h-5.2c-.6 0-1.2-.5-1.2-1.2v-1.4c0-.6.5-1.2 1.2-1.2h5.2c.6 0 1.2.5 1.2 1.2zM64 50.3c0 3-2.4 5.4-5.4 5.4H5.4c-3 0-5.4-2.4-5.4-5.4v-1.6h64z"></path><path fill="#51575b" d="M0 20.1c0-3 2.4-5.4 5.4-5.4h53.1c3 0 5.4 2.4 5.4 5.4v1.6H0z"></path><path fill="#3e4347" d="M0 21.5h64v28.3H0z"></path><path fill="#51575b" d="M54.7 18H22.6l3.2-10.8c.3-.6 1.6-1.6 2.4-1.8C33.1 4 44.1 4 49 5.4c.8.2 2.1 1.2 2.4 1.8z"></path><path fill="#3e4347" d="M53.1 29.6h-29L27 15c.2-.8 1.5-2.1 2.2-2.4c4.4-1.8 14.4-1.8 18.8 0c.7.3 1.9 1.6 2.2 2.4z"></path><path fill="#788287" d="M60.6 37.6c0 12.2-9.9 22-22 22s-22-9.8-22-22c0-12.1 9.9-22 22-22c12.2 0 22 9.9 22 22"></path><path fill="#212528" d="M58.2 37.6c0 10.8-8.8 19.6-19.6 19.6S19 48.4 19 37.6S27.8 18 38.6 18c10.8.1 19.6 8.8 19.6 19.6"></path><circle cx="38.6" cy="37.6" r="15.9" fill="#3e4347"></circle><circle cx="38.6" cy="37.6" r="8.6" fill="#212528"></circle><g fill="#f5f5f5"><path d="M50.3 30.9c0 2.7-2.2 4.9-4.9 4.9s-4.9-2.2-4.9-4.9s2.2-4.9 4.9-4.9c2.7-.1 4.9 2.2 4.9 4.9" opacity=".5"></path><circle cx="35.6" cy="40.7" r="3.1" opacity=".5"></circle><circle cx="30.1" cy="46.2" r="1.9" opacity=".5"></circle></g><path fill="#636c72" d="M15 45.3c0 1.2-1 2.2-2.2 2.2H3.6c-1.2 0-2.2-1-2.2-2.2V25.9c0-1.2 1-2.2 2.2-2.2h9.2c1.2 0 2.2 1 2.2 2.2z"></path><circle cx="10.1" cy="18.6" r="3.2" fill="#212528"></circle></g></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon" viewBox="0 0 64 64" width="24" height="24"><defs></defs><g><path fill="#231f20" d="M62 32S51.9 52 32 52S2 32 2 32s10.1-20 30-20s30 20 30 20"></path><path fill="#fff" d="M57 32s-8.4 16.7-25 16.7S7 32 7 32s8.4-16.7 25-16.7S57 32 57 32"></path><path fill="#42ade2" d="M45.4 32c0 7.5-6 13.5-13.5 13.5s-13.5-6-13.5-13.5s6-13.5 13.5-13.5s13.5 6 13.5 13.5"></path><path fill="#231f20" d="M39.4 32c0 4.1-3.4 7.5-7.5 7.5s-7.5-3.4-7.5-7.5s3.4-7.5 7.5-7.5s7.5 3.4 7.5 7.5"></path></g></svg>

Before

Width:  |  Height:  |  Size: 601 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon" viewBox="0 0 64 64" width="24" height="24"><defs></defs><g><path fill="#0071bc" d="M57.9 32c.2-.2.3-.4.5-.6c3.9-5.6 4.7-10.7 2.3-14.5c-2.2-3.5-7-5.5-13.4-5.5c-1.1 0-2.3.1-3.5.2C40.9 5.7 36.7 2 32 2s-8.9 3.7-11.8 9.6c-1.2-.1-2.4-.2-3.5-.2c-6.4 0-11.2 1.9-13.4 5.5c-2.4 3.8-1.6 9 2.3 14.5c.2.2.4.4.5.6c-.2.2-.3.4-.5.6C1.8 38.2 1 43.4 3.4 47.2c2.2 3.5 7 5.5 13.4 5.5c1.1 0 2.3-.1 3.5-.2c2.8 5.8 7 9.5 11.7 9.5s8.9-3.7 11.8-9.6c1.2.1 2.4.2 3.5.2c6.4 0 11.2-1.9 13.4-5.5c2.4-3.8 1.6-9-2.3-14.5c-.2-.2-.4-.4-.5-.6M47.2 13.1c5.7 0 9.9 1.6 11.8 4.6c2 3.2 1.2 7.7-2.3 12.7l-.1.1c-2.5-3-5.8-6-9.7-8.6c-.6-3.2-1.4-6.1-2.5-8.7c1-.1 2-.1 2.8-.1m-7.4 31.3c-2.6 1.4-5.2 2.5-7.8 3.5c-2.6-1-5.3-2.1-7.8-3.5c-1.9-1-3.7-2.1-5.5-3.3c-.5-2.9-.8-6-.8-9.2s.3-6.3.8-9.2c1.7-1.2 3.5-2.2 5.5-3.3c2.6-1.4 5.2-2.5 7.8-3.5c2.6 1 5.3 2.1 7.8 3.5c1.9 1 3.7 2.1 5.5 3.3c.5 2.9.8 6 .8 9.2s-.3 6.3-.8 9.2c-1.7 1.2-3.6 2.3-5.5 3.3m5-.8c-.6 2.5-1.3 4.9-2.3 7c-2.6-.3-5.2-.9-7.9-1.8c2.1-.8 4.1-1.8 6.1-2.8c1.5-.8 2.8-1.6 4.1-2.4m-15.4 5.2c-2.7.8-5.4 1.4-7.9 1.8c-.9-2.1-1.7-4.4-2.3-7c1.3.8 2.6 1.6 4 2.3c2.1 1.1 4.1 2 6.2 2.9m-12.8-9.1c-3.2-2.4-6-5-8.1-7.7c2.1-2.7 4.9-5.3 8.1-7.7c-.3 2.4-.5 5-.5 7.7s.1 5.2.5 7.7m2.6-19.3c.6-2.5 1.3-4.9 2.3-7c2.6.3 5.2.9 7.9 1.8c-2.1.8-4.1 1.8-6.1 2.9c-1.5.7-2.8 1.5-4.1 2.3m15.4-5.2c2.7-.8 5.4-1.4 7.9-1.8c.9 2.1 1.7 4.4 2.3 7c-1.3-.8-2.6-1.6-4-2.3c-2.1-1.1-4.1-2-6.2-2.9m12.8 9.1c3.2 2.4 6 5 8.1 7.7c-2.1 2.7-4.9 5.3-8.1 7.7c.3-2.4.5-5 .5-7.7s-.1-5.2-.5-7.7M32 3.9c3.8 0 7.2 3 9.8 7.9c-3.1.5-6.4 1.3-9.8 2.5c-3.3-1.2-6.6-2-9.8-2.5c2.6-4.9 6-7.9 9.8-7.9M7.2 30.4c-3.5-5-4.3-9.5-2.3-12.7c1.9-3 6.1-4.6 11.8-4.6c.9 0 1.8 0 2.7.1c-1.1 2.6-1.9 5.5-2.5 8.7c-3.8 2.6-7.1 5.6-9.7 8.5m9.6 20.5c-5.7 0-9.9-1.6-11.8-4.6c-2-3.2-1.2-7.7 2.3-12.7c0 0 0-.1.1-.1c2.5 3 5.8 6 9.7 8.6c.6 3.2 1.4 6.1 2.5 8.7c-1 .1-1.9.1-2.8.1M32 60.1c-3.8 0-7.2-3-9.8-7.9c3.1-.5 6.4-1.3 9.8-2.5c3.3 1.2 6.6 2 9.8 2.5c-2.6 4.9-6 7.9-9.8 7.9m27-13.8c-1.9 3-6.1 4.6-11.8 4.6c-.9 0-1.8 0-2.7-.1c1.1-2.6 1.9-5.5 2.5-8.7c3.8-2.6 7.1-5.6 9.7-8.6c0 0 0 .1.1.1c3.5 5 4.3 9.5 2.2 12.7"></path><circle cx="32" cy="32" r="5.6" fill="#ed4c5c"></circle></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon" viewBox="0 0 64 64" width="24" height="24"><defs></defs><g><g fill="#ff9d27"><path d="M10.9 48.7c4-4 4.4-5 6.9-2.5s1.5 2.8-2.5 6.9c-3 3-6.8 2.4-6.8 2.4s-.6-3.8 2.4-6.8"></path><path d="M18.5 52.8c1.6-4.2 2.1-4.7-.2-6s-2.3-.4-3.8 3.8c-1.2 3.1.2 5.9.2 5.9s2.7-.5 3.8-3.7"></path></g><path fill="#fdf516" d="M16.2 48.9c.9-2.3.9-2.8 2.1-2.1c1.3.7 1 1 .1 3.3c-.6 1.7-2.1 2.1-2.1 2.1s-.7-1.5-.1-3.3"></path><path fill="#ff9d27" d="M17.1 45.7c-1.3-2.3-1.8-1.8-6-.2c-3.1 1.2-3.7 3.8-3.7 3.8s2.8 1.4 5.9.2c4.2-1.6 5.1-1.6 3.8-3.8"></path><g fill="#fdf516"><path d="M15 47.8c2.3-.9 2.8-.9 2.1-2.1c-.7-1.3-1-1-3.3-.1c-1.7.6-2.1 2.1-2.1 2.1s1.6.7 3.3.1"></path><path d="M13.9 47.6c2.2-2.2 2.4-2.8 3.8-1.4s.8 1.6-1.4 3.8c-1.7 1.7-3.8 1.3-3.8 1.3s-.2-2 1.4-3.7"></path></g><path fill="#3baacf" d="M18.5 38C12.3 27.6 2 31.9 2 31.9s14.7-14.7 24.6-4.8z"></path><path fill="#428bc1" d="m23.3 30.3l3.2-3.2C16.7 17.2 2 31.9 2 31.9s12.9-9.2 21.3-1.6"></path><path fill="#3baacf" d="M26 45.5C36.4 51.7 32.1 62 32.1 62s14.7-14.7 4.8-24.6z"></path><path fill="#428bc1" d="m33.7 40.7l3.2-3.2c9.9 9.9-4.8 24.6-4.8 24.6s9.2-13 1.6-21.4"></path><path fill="#c5d0d8" d="M48.8 30.9C37.1 42.5 24.2 48.8 19.7 44.3s1.8-17.4 13.4-29.1c13.6-13.6 28.7-13 28.7-13s.5 15.1-13 28.7"></path><path fill="#dae3ea" d="M45.8 27.6C34.2 39.2 22.6 46.8 19.9 44.1s4.9-14.3 16.5-25.9C50 4.6 62 2 62 2s-2.6 12-16.2 25.6"></path><path fill="#c94747" d="M24.3 47.5c-.5.5-1.3.5-1.8 0l-6-6c-.5-.5-.5-1.4 0-1.9l1.8-1.8l7.8 7.8z"></path><path fill="#f15744" d="M22.6 45.7c-.5.5-1.1.7-1.4.4l-3.4-3.4c-.3-.3-.1-.9.4-1.4l1.8-1.8l4.4 4.4z"></path><path fill="#3e4347" d="M20.9 48.2c-.3.3-1 .3-1.3 0l-3.9-3.9c-.3-.3-.2-.9.1-1.2l1.2-1.2l5.1 5.1z"></path><path fill="#62727a" d="M20.1 47.4c-.3.3-.9.4-1.1.2l-2.7-2.7c-.2-.2-.1-.7.3-1l1.2-1.2l3.5 3.5z"></path><path fill="#c94747" d="M61.8 2.2S56.4 2 49.1 4.8l10.1 10.1C62 7.6 61.8 2.2 61.8 2.2"></path><path fill="#f15744" d="M61.8 2.2s-4.3.9-10.8 4.6l6.2 6.2c3.7-6.5 4.6-10.8 4.6-10.8"></path><circle cx="43.5" cy="20.5" r="5" fill="#edf4f9"></circle><circle cx="43.5" cy="20.5" r="3.3" fill="#3baacf"></circle><circle cx="33.5" cy="30.5" r="5" fill="#edf4f9"></circle><circle cx="33.5" cy="30.5" r="3.3" fill="#3baacf"></circle><g fill="#fff"><path d="M48.9 6.9c-.3.3-.9.3-1.2 0s-.3-.9 0-1.2s.9-.3 1.2 0s.3.9 0 1.2"></path><circle cx="50.6" cy="8.6" r=".8"></circle><circle cx="53" cy="11" r=".8"></circle><circle cx="55.3" cy="13.4" r=".8"></circle><circle cx="57.7" cy="15.7" r=".8"></circle></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -1,30 +1,29 @@
{
"projectTitle": "数联网科创智能体",
"newChat": "新对话",
"selectAPrompt": "选择一个提示词",
"githubRepository": "GitHub 仓库",
"settings": "设置",
"metering": "计量",
"sidebarTitle": "对话历史",
"error": "错误",
"somethingWentWrong": "出现了错误",
"validationSelectModel": "请选择一个模型以继续",
"deleteHistoryConfirmation": "你确定要删除这个历史记录吗?",
"editHistoryTitle": "输入一个新的标题",
"temporaryChat": "临时对话",
"more": {
"copy": {
"group": "复制",
"asText": "复制为文本",
"asMarkdown": "复制为 Markdown",
"success": "已复制到剪贴板!"
},
"download": {
"group": "下载",
"text": "文本文件 (.txt)",
"markdown": "Markdown 文件 (.md)",
"json": "JSON 文件 (.json)"
},
"share": "分享"
}
"newChat": "新聊天",
"selectAPrompt": "选择一个提示词",
"githubRepository": "GitHub 仓库",
"settings": "设置",
"metering": "计量",
"sidebarTitle": "聊天历史",
"error": "错误",
"somethingWentWrong": "出现了错误",
"validationSelectModel": "请选择一个模型以继续",
"deleteHistoryConfirmation": "你确定要删除这个历史记录吗?",
"editHistoryTitle": "输入一个新的标题",
"temporaryChat": "临时聊天",
"more": {
"copy": {
"group": "复制",
"asText": "复制为文本",
"asMarkdown": "复制为 Markdown",
"success": "已复制到剪贴板!"
},
"download": {
"group": "下载",
"text": "文本文件 (.txt)",
"markdown": "Markdown 文件 (.md)",
"json": "JSON 文件 (.json)"
},
"share": "分享"
}
}

View File

@ -1,38 +0,0 @@
import React from "react";
import { Typography, Button } from "antd";
import { AcademicCapIcon, ChevronRightIcon } from "@heroicons/react/24/outline";
const { Title } = Typography;
type Props = {
Header: React.ReactNode;
showButton?: boolean;
onClick?: () => void;
};
export const DataNavigation: React.FC<Props> = ({ Header, showButton = true, onClick }) => {
return (
<div className="flex items-center justify-between bg-white dark:bg-gray-800 rounded-lg mb-3">
{/* 左侧部分 */}
<div className="flex items-center">
<Title
level={4}
style={{ marginBottom: 0, color: "#1F2937", fontSize: "16px" }}>
{Header}
</Title>
</div>
{/* 右侧部分 */}
{showButton && (
<Button
color="default"
variant="link"
style={{ gap: 4 }}
onClick={onClick}>
<span className="text-sm"></span>
<ChevronRightIcon className="w-4 h-4" />
</Button>
)}
</div>
)
};

View File

@ -12,7 +12,7 @@ import { preprocessLaTeX } from "@/utils/latex"
function Markdown({
message,
className = "prose-lg break-words dark:prose-invert prose-p:leading-relaxed prose-pre:p-0 dark:prose-dark"
className = "prose break-words dark:prose-invert prose-p:leading-relaxed prose-pre:p-0 dark:prose-dark"
}: {
message: string
className?: string

View File

@ -1,175 +0,0 @@
import React from "react"
import { DataNavigation } from "@/components/Common/DataNavigation.tsx"
import { Card, Drawer, List } from "antd"
import { useCallback, useState } from "react"
export const PlaygroundData = () => {
// 模拟数据
const data: {
title: string
description: string
time: string
metadata?: string
}[] = [
{
title: "2019-2024年黄海清浅海域中河湖代数生物物种数据集",
description:
"数字对象标识: CSTR:13452.11.01.11.2021.242 国家海洋科学数据中心",
time: "包括2019年8月2021年8月和2024年6月",
metadata: "热 榜 第"
},
{
title: "祁连山老虎沟大本营10米气象每日值数据集V1.02018-2023",
description:
"中国科学院西北生态环境资源研究院2021年8月3日发布2021年8月3日20:48更新",
time: "包括2019年8月2021年8月和2024年6月",
metadata: "热 榜 第"
},
{
title: "李嘉图为研究老虎沟大本营2014-2018年...",
description:
"中国科学院西北生态环境资源研究院2021年8月3日发布2021年8月3日20:48更新",
time: "包括2019年8月2021年8月和2024年6月",
metadata: "热 榜 第"
},
{
title: "青海玉树B1区俄日矿勘探数据2017-2023",
description:
"数字中国集团CSTR:3260.11.1528414774204895456DT2023年地质勘探补充调查",
time: "包括2019年8月2021年8月和2024年6月",
metadata: "热 榜 第"
}
]
for (let i = 0; i < 10; i++) {
data.push({
title: "中国资源环境网",
description: "中国资源环境网2021年8月3日发布2021年8月3日20:48更新",
time: "包括2019年8月2021年8月和2024年6月"
})
}
const [open, setOpen] = useState(false)
const showDrawer = () => {
setOpen(true)
}
const onClose = () => {
setOpen(false)
}
return (
<div className="flex flex-col h-full overflow-y-hidden">
{/* 数据导航 */}
<DataNavigation
Header={
<div className="flex items-center text-[#1d4eD8] gap-1">
<svg
xmlns="http://www.w3.org/2000/svg"
className="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon"
viewBox="0 0 32 32"
width="20"
height="20">
<defs></defs>
<g>
<circle cx="22" cy="24" r="2" fill="rgb(29, 78, 216)"></circle>
<path
fill="rgb(29, 78, 216)"
d="M29.777 23.479A8.64 8.64 0 0 0 22 18a8.64 8.64 0 0 0-7.777 5.479L14 24l.223.522A8.64 8.64 0 0 0 22 30a8.64 8.64 0 0 0 7.777-5.478L30 24zM22 28a4 4 0 1 1 4-4a4.005 4.005 0 0 1-4 4M7 17h5v2H7zm0-5h12v2H7zm0-5h12v2H7z"></path>
<path
fill="rgb(29, 78, 216)"
d="M22 2H4a2.006 2.006 0 0 0-2 2v24a2.006 2.006 0 0 0 2 2h8v-2H4V4h18v11h2V4a2.006 2.006 0 0 0-2-2"></path>
</g>
</svg>
</div>
}
onClick={showDrawer}
/>
{/* 数据列表 */}
<div className="space-y-1.5 flex-1 overflow-y-auto">
{data.slice(0, 3).map((item, index) => (
<Card key={index} hoverable className="[&>*:first-child]:!p-3 h-[148px]">
<div className="flex flex-col gap-0.5">
<h3 className="text-sm font-medium text-gray-900 line-clamp-2">
{item.title}
</h3>
<p className="text-xs text-gray-500 line-clamp-2">
{item.description}
</p>
<p className="text-gray-700 truncate">{item.time}</p>
{item.metadata && (
<div className="text-green-500 text-xs px-2 py-1 rounded-full flex items-center gap-1">
<svg
xmlns="http://www.w3.org/2000/svg"
className="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon"
viewBox="0 0 24 24"
width="12"
height="12">
<defs></defs>
<g>
<path
fill="rgb(34, 197, 94)"
d="m16 11.78l4.24-7.33l1.73 1l-5.23 9.05l-6.51-3.75L5.46 19H22v2H2V3h2v14.54L9.5 8z"></path>
</g>
</svg>
{item.metadata}
</div>
)}
</div>
</Card>
))}
</div>
{/* 抽屉 */}
<Drawer
title="相关数据"
closable={{ "aria-label": "Close Button" }}
onClose={onClose}
open={open}
width={600}>
<List
itemLayout="vertical"
dataSource={data}
renderItem={(item, index) => (
<List.Item>
<List.Item.Meta
title={
<h3 className="text-sm font-medium text-gray-900">
{item.title}
</h3>
}
description={
<div className="space-y-1">
<p className="text-xs text-gray-500">{item.description}</p>
<p className="text-gray-700">{item.time}</p>
{item.metadata && (
<div className="text-green-500 text-xs px-2 py-1 rounded-full flex items-center gap-1">
<svg
xmlns="http://www.w3.org/2000/svg"
className="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon"
viewBox="0 0 24 24"
width="12"
height="12">
<defs></defs>
<g>
<path
fill="rgb(34, 197, 94)"
d="m16 11.78l4.24-7.33l1.73 1l-5.23 9.05l-6.51-3.75L5.46 19H22v2H2V3h2v14.54L9.5 8z"></path>
</g>
</svg>
{item.metadata}
</div>
)}
</div>
}
/>
</List.Item>
)}
/>
</Drawer>
</div>
)
}

View File

@ -1,84 +0,0 @@
import { Sidebar } from "@/components/Option/Sidebar.tsx"
import React, { useContext, useState } from "react"
import { useMessageOption } from "@/hooks/useMessageOption.tsx"
import { useStoreChatModelSettings } from "@/store/model.tsx"
import { Card, Tooltip } from "antd"
import { PageAssitDatabase } from "@/db"
import { EraserIcon } from "lucide-react"
import { useTranslation } from "react-i18next"
import { useQueryClient } from "@tanstack/react-query"
import { HistoryContext } from "@/components/Layouts/Layout.tsx"
export const PlaygroundHistory = () => {
const { setSystemPrompt } = useStoreChatModelSettings()
const { show, setShow } = useContext(HistoryContext)
const {
setMessages,
setHistory,
setHistoryId,
historyId,
clearChat,
setSelectedModel,
temporaryChat,
setSelectedSystemPrompt
} = useMessageOption()
const { t } = useTranslation(["option", "common", "settings"])
const queryClient = useQueryClient()
return (
<Card
className={`flex flex-col [&>:nth-child(2)]:flex-1 [&>:nth-child(2)]:overflow-y-auto w-[300px] h-full pt-16 pb-5 transition-all duration-300 ease-in-out transform ${
show
? 'opacity-100 translate-x-0'
: 'opacity-0 -translate-x-full absolute'
}`}
style={{ paddingTop: "4rem" }}
title={
<div className="flex items-center justify-between w-full">
{t("sidebarTitle")}
<Tooltip
title={t("settings:generalSettings.system.deleteChatHistory.label")}
placement="right">
<button
onClick={async () => {
const confirm = window.confirm(
t("settings:generalSettings.system.deleteChatHistory.confirm")
)
if (confirm) {
const db = new PageAssitDatabase()
await db.deleteAllChatHistory()
await queryClient.invalidateQueries({
queryKey: ["fetchChatHistory"]
})
clearChat()
}
}}
className="text-gray-600 hover:text-gray-800 dark:text-gray-300 dark:hover:text-gray-100">
<EraserIcon className="size-5" />
</button>
</Tooltip>
</div>
}>
<div className="overflow-y-auto">
<Sidebar
onClose={() => setShow(true)}
setMessages={setMessages}
setHistory={setHistory}
setHistoryId={setHistoryId}
setSelectedModel={setSelectedModel}
setSelectedSystemPrompt={setSelectedSystemPrompt}
clearChat={clearChat}
historyId={historyId}
setSystemPrompt={setSystemPrompt}
temporaryChat={temporaryChat}
history={history}
/>
</div>
</Card>
)
}

View File

@ -1,95 +0,0 @@
import React from 'react';
const SuccessIcon = () => {
return (<svg
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="w-full h-full text-green-500">
<path
d="M9 12L11 14L15 10M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>)
}
const LoadingIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
className="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon"
viewBox="0 0 24 24"
width="18"
height="18">
<defs></defs>
<g>
<path
fill="rgb(59, 130, 246)"
d="M13 2.03v2.02c4.39.54 7.5 4.53 6.96 8.92c-.46 3.64-3.32 6.53-6.96 6.96v2c5.5-.55 9.5-5.43 8.95-10.93c-.45-4.75-4.22-8.5-8.95-8.97m-2 .03c-1.95.19-3.81.94-5.33 2.2L7.1 5.74c1.12-.9 2.47-1.48 3.9-1.68zM4.26 5.67A9.9 9.9 0 0 0 2.05 11h2c.19-1.42.75-2.77 1.64-3.9zM2.06 13c.2 1.96.97 3.81 2.21 5.33l1.42-1.43A8 8 0 0 1 4.06 13zm5.04 5.37l-1.43 1.37A10 10 0 0 0 11 22v-2a8 8 0 0 1-3.9-1.63M12.5 7v5.25l4.5 2.67l-.75 1.23L11 13V7z"></path>
</g>
</svg>
)
}
export const PlaygroundIodRelevant: React.FC = () => {
const data = [
{
title: "已在29个科学数据中心的50万个科学数据集中进行搜索",
description: "已发现4个数据集",
status: "success"
},
{
title: "已在100万篇论文、2800个科创场景中进行搜索",
description: "已发现4个数据集",
status: "success"
},
{
title: "正在1000位智库专家、12万个创新机构中进行搜索",
status: "loading"
},
]
for (let i = 0; i < 10; i++) {
data.push({
title: "已在29个科学数据中心的50万个科学数据集中进行搜索" + i,
description: "已发现4个数据集",
status: "success"
})
}
return (
<div className="flex flex-col h-full">
{/* Header */}
<div className="flex justify-between items-center mb-4">
<h2 className="text-lg font-semibold text-gray-900">
</h2>
<span className="text-sm text-blue-600 font-medium">{data.length}</span>
</div>
{/* Content */}
<div className="space-y-3 flex-1 overflow-y-auto">
{
data.map((item, index) => (
<div className="flex items-start space-x-3">
<div className="w-5 h-5 mt-1 flex-shrink-0">
{item.status === "success" ? <SuccessIcon /> : <LoadingIcon />}
</div>
<div className="flex-1">
<p className="text-sm text-gray-700">
{item.title}
</p>
{item.description && <p className="text-xs text-gray-500 mt-1">{item.description}</p>}
</div>
</div>
))
}
</div>
</div>
)
}

View File

@ -58,7 +58,7 @@ export const PlaygroundMessage = (props: Props) => {
const { t } = useTranslation("common")
const { cancel, isSpeaking, speak } = useTTS()
return (
<div className="group relative flex w-full flex-col items-end justify-center pb-2 md:px-4 text-gray-800 dark:text-gray-100">
<div className="group relative flex w-full max-w-3xl flex-col items-end justify-center pb-2 md:px-4 lg:w-4/5 text-gray-800 dark:text-gray-100">
{/* <div className="text-base md:max-w-2xl lg:max-w-xl xl:max-w-3xl flex lg:px-0 m-auto w-full"> */}
<div className="flex flex-row gap-4 md:gap-6 my-2 m-auto w-full">
<div className="w-8 flex flex-col relative items-end">
@ -138,7 +138,7 @@ export const PlaygroundMessage = (props: Props) => {
</>
) : (
<p
className={`prose-lg dark:prose-invert whitespace-pre-line prose-p:leading-relaxed prose-pre:p-0 dark:prose-dark ${
className={`prose dark:prose-invert whitespace-pre-line prose-p:leading-relaxed prose-pre:p-0 dark:prose-dark ${
props.message_type &&
"italic text-gray-500 dark:text-gray-400 text-sm"
}`}>

View File

@ -1,142 +0,0 @@
import React, { useState } from "react"
import { DataNavigation } from "@/components/Common/DataNavigation.tsx"
import { Card, Drawer, List } from "antd"
export const PlaygroundScene = () => {
// 模拟数据
const data = [
{
title: "绿色化工工艺项目",
description:
"基于生物基原料采用repeal2.0可降解材料技术,开发新型环保材料。",
demander: "奥赛康药业 供方美国Propella公司"
},
{
title: "智能农业解决方案",
description: "利用物联网技术,实现精准农业管理,提高农作物产量。",
demander: "奥赛康药业 供方美国Propella公司"
},
{
title: "新能源汽车电池技术",
description: "研发高能量密度、长寿命的新型电池材料,推动电动汽车发展。",
demander: "奥赛康药业 供方美国Propella公司"
},
{
title: "碳捕集与封存技术",
description: "开发高效的碳捕集技术,减少工业排放,助力碳中和目标。",
demander: "奥赛康药业 供方美国Propella公司"
}
]
for (let i = 0; i < 10; i++) {
data.push({
title: "开发新型电池材料",
description: "研发高能量密度、长寿命的新型电池材料,推动电动汽车发展。",
demander: "奥赛康药业 供方美国Propella公司"
})
}
const [open, setOpen] = useState(false)
const showDrawer = () => {
setOpen(true)
}
const onClose = () => {
setOpen(false)
}
return (
<div className="h-full overflow-y-hidden flex flex-col">
{/* 数据导航 */}
<DataNavigation
Header={
<div className="flex items-center text-[#15803d] gap-1">
<svg
xmlns="http://www.w3.org/2000/svg"
className="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon"
viewBox="0 0 32 32"
width="20"
height="20">
<defs></defs>
<g>
<path
fill="rgb(21, 128, 61)"
d="M16 18H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2M6 6v10h10V6zm20 6v4h-4v-4zm0-2h-4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2m0 12v4h-4v-4zm0-2h-4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2m-10 2v4h-4v-4zm0-2h-4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2"></path>
</g>
</svg>
</div>
}
onClick={showDrawer}
/>
{/* 场景列表 */}
<div className="space-y-1.5 flex-1 overflow-y-auto">
{data.slice(0,3).map((item, index) => (
<Card key={index} hoverable className="[&>*:first-child]:!p-4 h-[148px]" >
<div className="flex flex-col gap-0.5">
<h3 className="text-sm font-medium text-gray-900 line-clamp-2">
{item.title}
</h3>
<p className="flex items-center gap-1.5">
<span className="inline-block bg-blue-100 text-green-800 text-xs px-2 py-1 rounded-full">
</span>
<span className="inline-block bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded-full">
</span>
</p>
<p className="text-xs text-gray-500 truncate">{item.demander}</p>
<span className="text-gray-700 line-clamp-2">
{item.description}
</span>
</div>
</Card>
))}
</div>
{/* 抽屉 */}
<Drawer
title="相关场景"
closable={{ "aria-label": "Close Button" }}
onClose={onClose}
open={open}
width={600}>
<List
itemLayout="vertical"
dataSource={data}
renderItem={(item, index) => (
<List.Item>
<List.Item.Meta
title={
<h3 className="text-sm font-medium text-gray-900">
{item.title}
</h3>
}
description={
<div className="space-y-1">
<p className="flex items-center gap-1.5">
<span className="inline-block bg-blue-100 text-green-800 text-xs px-2 py-1 rounded-full">
</span>
<span className="inline-block bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded-full">
</span>
</p>
<p className="text-xs text-gray-500">
{item.demander}
</p>
<span className="text-gray-700">
{item.description}
</span>
</div>
}
/>
</List.Item>
)}
/>
</Drawer>
</div>
)
}

View File

@ -1,136 +0,0 @@
import React, { useState } from "react"
import { DataNavigation } from "@/components/Common/DataNavigation.tsx"
import { Card, Drawer, List } from "antd"
export const PlaygroundTeam = () => {
// 模拟数据
const data = [
{
title: "绿色化工工艺项目",
description:
"基于生物基原料采用repeal2.0可降解材料技术,开发新型环保材料。",
demander: "奥赛康药业 供方美国Propella公司"
},
{
title: "智能农业解决方案",
description: "利用物联网技术,实现精准农业管理,提高农作物产量。",
demander: "奥赛康药业 供方美国Propella公司"
},
{
title: "新能源汽车电池技术",
description: "研发高能量密度、长寿命的新型电池材料,推动电动汽车发展。",
demander: "奥赛康药业 供方美国Propella公司"
},
{
title: "碳捕集与封存技术",
description: "开发高效的碳捕集技术,减少工业排放,助力碳中和目标。",
demander: "奥赛康药业 供方美国Propella公司"
}
]
for (let i = 0; i < 10; i++) {
data.push({
title: "开发新型电池材料",
description: "研发高能量密度、长寿命的新型电池材料,推动电动汽车发展。",
demander: "奥赛康药业 供方美国Propella公司"
})
}
const [open, setOpen] = useState(false)
const showDrawer = () => {
setOpen(true)
}
const onClose = () => {
setOpen(false)
}
return (
<div className="h-full overflow-y-hidden flex flex-col">
{/* 数据导航 */}
<DataNavigation
Header={
<div className="flex items-center text-[#15803d] gap-1">
<svg
xmlns="http://www.w3.org/2000/svg"
className="styles__StyledSVGIconPathComponent-sc-i3aj97-0 bxMexi svg-icon-path-icon"
viewBox="0 0 32 32"
width="20"
height="20">
<defs></defs>
<g>
<path
fill="rgb(21, 128, 61)"
d="M16 18H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2M6 6v10h10V6zm20 6v4h-4v-4zm0-2h-4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2m0 12v4h-4v-4zm0-2h-4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2m-10 2v4h-4v-4zm0-2h-4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2"></path>
</g>
</svg>
</div>
}
onClick={showDrawer}
/>
{/* 场景列表 */}
<div className="grid grid-cols-2 gap-3">
{data.slice(0,2).map((item, index) => (
<Card key={index} hoverable className="[&>*:first-child]:!p-3" >
<div className="flex flex-col gap-0.5">
<h3 className="text-sm font-medium text-gray-900 line-clamp-2">
{item.title}
</h3>
<p className="flex items-center gap-1.5">
<span className="inline-block bg-blue-100 text-green-800 text-xs px-2 py-1 rounded-full">
</span>
<span className="inline-block bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded-full">
</span>
</p>
<p className="text-xs text-gray-500 line-clamp-2">{item.description}</p>
</div>
</Card>
))}
</div>
{/* 抽屉 */}
<Drawer
title="相关团队"
closable={{ "aria-label": "Close Button" }}
onClose={onClose}
open={open}
width={600}>
<List
itemLayout="vertical"
dataSource={data}
renderItem={(item, index) => (
<List.Item>
<List.Item.Meta
title={
<h3 className="text-sm font-medium text-gray-900">
{item.title}
</h3>
}
description={
<div className="space-y-1">
<p className="flex items-center gap-1.5">
<span className="inline-block bg-blue-100 text-green-800 text-xs px-2 py-1 rounded-full">
</span>
<span className="inline-block bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded-full">
</span>
</p>
<p className="text-xs text-gray-500">
{item.description}
</p>
</div>
}
/>
</List.Item>
)}
/>
</Drawer>
</div>
)
}

View File

@ -1,46 +0,0 @@
import { DataNavigation } from "@/components/Common/DataNavigation.tsx"
import { Card, Descriptions, DescriptionsProps, Drawer, List, Spin } from "antd"
import { useCallback, useMemo, useState } from "react"
import { useMessageOption } from "@/hooks/useMessageOption.tsx"
import { useStoreMessageOption } from "@/store/option.tsx"
export const PlaygroundTokenStatistics = () => {
const { currentMeteringEntry } = useStoreMessageOption()
const items = useMemo<DescriptionsProps["items"]>(() => {
const { data } = currentMeteringEntry
return [
// {
// key: "relatedDataCount",
// label: "关联数据个数",
// children: data.relatedDataCount
// },
{
key: "iodTokenCount",
label: "数联网引用token总数",
children: data.iodTokenCount ?? 0
},
{
key: "modelInputTokenCount",
label: "大模型输入token数量",
children: data.modelInputTokenCount ?? 0
},
{
key: "modelOutputTokenCount",
label: "大模型输出token数量",
children: data.modelOutputTokenCount ?? 0
}
]
}, [currentMeteringEntry])
return (
<Card
style={{ marginBottom: "1rem" }}
className="h-full"
title={<DataNavigation title="Token统计" showButton={false} />}>
<Spin spinning={currentMeteringEntry.loading}>
<Descriptions layout="horizontal" items={items} column={2} />
</Spin>
</Card>
)
}

View File

@ -24,24 +24,18 @@ import { ProviderIcons } from "../Common/ProviderIcon"
import { NewChat } from "./NewChat"
import { PageAssistSelect } from "../Select"
import { MoreOptions } from "./MoreOptions"
import { useContext } from "react"
import { HistoryContext } from "@/components/Layouts/Layout.tsx"
type Props = {
sidebarOpen: boolean
setSidebarOpen: () => void
setSidebarOpen: (open: boolean) => void
setOpenModelSettings: (open: boolean) => void
}
export const Header: React.FC<Props> = ({
setOpenModelSettings,
setSidebarOpen,
sidebarOpen
setSidebarOpen
}) => {
const { t, i18n } = useTranslation(["option", "common"])
const isRTL = i18n?.dir() === "rtl"
const [shareModeEnabled] = useStorage("shareMode", false)
const [hideCurrentChatModelSettings] = useStorage(
"hideCurrentChatModelSettings",
@ -115,16 +109,10 @@ export const Header: React.FC<Props> = ({
</NavLink>
</div>
)}
<div style={{width: sidebarOpen ? "288px" : "205px"}} className="flex items-center justify-between transition-all duration-300 ease-in-out">
<h2
className="text-xl font-bold text-zinc-700 dark:text-zinc-300 mr-3"
style={{ lineHeight: "0" }}>
{t("projectTitle")}
</h2>
<div>
<button
className="text-gray-500 dark:text-gray-400"
onClick={() => setSidebarOpen()}>
onClick={() => setSidebarOpen(true)}>
<PanelLeftIcon className="w-6 h-6" />
</button>
</div>

View File

@ -1,50 +1,103 @@
import React, { useCallback, useEffect, useState } from "react"
import React, { useState } from "react"
import { Sidebar } from "../Option/Sidebar"
import { Drawer, Tooltip } from "antd"
import { useTranslation } from "react-i18next"
import { CurrentChatModelSettings } from "../Common/Settings/CurrentChatModelSettings"
import { Header } from "./Header"
interface History {
show: boolean
setShow: (show: boolean) => void
}
export const HistoryContext = React.createContext<History>({
show: true,
setShow: () => {}
})
import { EraserIcon } from "lucide-react"
import { PageAssitDatabase } from "@/db"
import { useMessageOption } from "@/hooks/useMessageOption"
import { useQueryClient } from "@tanstack/react-query"
import { useStoreChatModelSettings } from "@/store/model"
export default function OptionLayout({
children
}: {
children: React.ReactNode
}) {
const [showHistory, setShowHistory] = useState(true)
const [sidebarOpen, setSidebarOpen] = useState(false)
const { t } = useTranslation(["option", "common", "settings"])
const [openModelSettings, setOpenModelSettings] = useState(false)
const {
setMessages,
setHistory,
setHistoryId,
historyId,
clearChat,
setSelectedModel,
temporaryChat,
setSelectedSystemPrompt
} = useMessageOption()
const historyContextValue = {
show: showHistory,
setShow: setShowHistory
}
const useToggle = useCallback(() => {
setShowHistory(!showHistory)
}, [showHistory])
const queryClient = useQueryClient()
const { setSystemPrompt } = useStoreChatModelSettings()
return (
<div className="flex h-full w-full">
<main className="relative h-dvh w-full">
<div className="relative z-10 w-full">
<Header
sidebarOpen={showHistory}
setSidebarOpen={useToggle}
setSidebarOpen={setSidebarOpen}
setOpenModelSettings={setOpenModelSettings}
/>
</div>
{/* <div className="relative flex h-full flex-col items-center"> */}
<HistoryContext.Provider value={historyContextValue}>
{children}
</HistoryContext.Provider>
{children}
{/* </div> */}
<Drawer
title={
<div className="flex items-center justify-between">
{t("sidebarTitle")}
<Tooltip
title={t(
"settings:generalSettings.system.deleteChatHistory.label"
)}
placement="right">
<button
onClick={async () => {
const confirm = window.confirm(
t(
"settings:generalSettings.system.deleteChatHistory.confirm"
)
)
if (confirm) {
const db = new PageAssitDatabase()
await db.deleteAllChatHistory()
await queryClient.invalidateQueries({
queryKey: ["fetchChatHistory"]
})
clearChat()
}
}}
className="text-gray-600 hover:text-gray-800 dark:text-gray-300 dark:hover:text-gray-100">
<EraserIcon className="size-5" />
</button>
</Tooltip>
</div>
}
placement="left"
closeIcon={null}
onClose={() => setSidebarOpen(false)}
open={sidebarOpen}>
<Sidebar
onClose={() => setSidebarOpen(false)}
setMessages={setMessages}
setHistory={setHistory}
setHistoryId={setHistoryId}
setSelectedModel={setSelectedModel}
setSelectedSystemPrompt={setSelectedSystemPrompt}
clearChat={clearChat}
historyId={historyId}
setSystemPrompt={setSystemPrompt}
temporaryChat={temporaryChat}
history={history}
/>
</Drawer>
<CurrentChatModelSettings
open={openModelSettings}

View File

@ -1,14 +1,8 @@
import React from "react"
import { Card } from "antd"
import { PlaygroundForm } from "./PlaygroundForm"
import { PlaygroundChat } from "./PlaygroundChat"
import { useMessageOption } from "@/hooks/useMessageOption"
import { webUIResumeLastChat } from "@/services/app"
import { PlaygroundData } from '@/components/Common/Playground/Data.tsx'
import { PlaygroundScene } from "@/components/Common/Playground/Scene.tsx"
import {
formatToChatHistory,
formatToMessage,
@ -19,11 +13,6 @@ import { getLastUsedChatSystemPrompt } from "@/services/model-settings"
import { useStoreChatModelSettings } from "@/store/model"
import { useSmartScroll } from "@/hooks/useSmartScroll"
import { ChevronDown } from "lucide-react"
import { PlaygroundTeam } from "@/components/Common/Playground/Team.tsx"
import { PlaygroundTokenStatistics } from "@/components/Common/Playground/TokenStatistics.tsx"
import { PlaygroundHistory } from "@/components/Common/Playground/History.tsx"
import { PlaygroundIodRelevant } from "@/components/Common/Playground/IodRelevant.tsx"
export const Playground = () => {
const drop = React.useRef<HTMLDivElement>(null)
@ -143,43 +132,26 @@ export const Playground = () => {
return (
<div
ref={drop}
className={`relative flex gap-3 h-full items-center ${
className={`relative flex h-full flex-col items-center ${
dropState === "dragging" ? "bg-gray-100 dark:bg-gray-800" : ""
} bg-white dark:bg-[#171717]`}>
<PlaygroundHistory />
<div className="relative h-full flex-1 prose-lg flex justify-center [&>*]:max-w-[848px]">
<div
ref={containerRef}
className="custom-scrollbar bg-bottom-mask-light dark:bg-bottom-mask-dark mask-bottom-fade will-change-mask flex h-full w-full flex-col items-center overflow-x-hidden overflow-y-auto px-5">
<PlaygroundChat />
</div>
<div className="absolute bottom-0 w-full">
{!isAtBottom && (
<div className="absolute bottom-36 z-20 left-0 right-0 flex justify-center">
<button
onClick={scrollToBottom}
className="bg-gray-50 shadow border border-gray-200 dark:border-none dark:bg-white/20 p-1.5 rounded-full pointer-events-auto">
<ChevronDown className="size-4 text-gray-600 dark:text-gray-300" />
</button>
</div>
)}
<PlaygroundForm dropedFile={dropedFile} />
</div>
<div
ref={containerRef}
className="custom-scrollbar bg-bottom-mask-light dark:bg-bottom-mask-dark mask-bottom-fade will-change-mask flex h-full w-full flex-col items-center overflow-x-hidden overflow-y-auto px-5">
<PlaygroundChat />
</div>
{messages.length && (
<div className="w-1/4 h-full grid grid-rows-[auto_530px_165px] pt-16 pr-5 pb-0 border-l border-gray-200" style={{"paddingTop": "4rem"}}>
<div className="w-full overflow-y-auto border-gray-200 border-b p-3">
<PlaygroundIodRelevant />
<div className="absolute bottom-0 w-full">
{!isAtBottom && (
<div className="fixed bottom-36 z-20 left-0 right-0 flex justify-center">
<button
onClick={scrollToBottom}
className="bg-gray-50 shadow border border-gray-200 dark:border-none dark:bg-white/20 p-1.5 rounded-full pointer-events-auto">
<ChevronDown className="size-4 text-gray-600 dark:text-gray-300" />
</button>
</div>
<div className="w-full grid grid-cols-2 gap-3 custom-scrollbar border-gray-200 border-b p-3">
<PlaygroundData />
<PlaygroundScene />
</div>
<div className="w-full p-3 pb-0">
<PlaygroundTeam />
</div>
</div>
)}
)}
<PlaygroundForm dropedFile={dropedFile} />
</div>
</div>
)
}

View File

@ -20,7 +20,7 @@ export const PlaygroundChat = () => {
<>
<div className="relative flex w-full flex-col items-center pt-16 pb-4">
{messages.length === 0 && (
<div className="mt-3 w-full">
<div className="mt-32 w-full">
<PlaygroundEmpty />
</div>
)}

View File

@ -1,113 +1,130 @@
import { Card, Col, Row } from "antd"
import RocketSvg from '@/assets/icons/rocket.svg'
import BulbSvg from '@/assets/icons/bulb.svg'
import EyeSvg from '@/assets/icons/eye.svg'
import ASvg from '@/assets/icons/a.svg'
import BSvg from '@/assets/icons/b.svg'
import CSvg from '@/assets/icons/c.svg'
import DSvg from '@/assets/icons/d.svg'
import ESvg from '@/assets/icons/e.svg'
import FSvg from '@/assets/icons/f.svg'
import { useMessageOption } from "@/hooks/useMessageOption.tsx"
import { useMutation, useQueryClient } from "@tanstack/react-query"
import { cleanUrl } from "@/libs/clean-url"
import { useStorage } from "@plasmohq/storage/hook"
import { useQuery } from "@tanstack/react-query"
import { RotateCcw } from "lucide-react"
import { useEffect, useState } from "react"
import { Trans, useTranslation } from "react-i18next"
import {
getOllamaURL,
isOllamaRunning,
setOllamaURL as saveOllamaURL
} from "~/services/ollama"
export const PlaygroundEmpty = () => {
const [ollamaURL, setOllamaURL] = useState<string>("")
const { t } = useTranslation(["playground", "common"])
const [checkOllamaStatus] = useStorage("checkOllamaStatus", true)
const {
onSubmit,
setMessages,
setHistory,
setHistoryId,
historyId,
clearChat,
setSelectedModel,
temporaryChat,
setSelectedSystemPrompt
} = useMessageOption()
data: ollamaInfo,
status: ollamaStatus,
refetch,
isRefetching
} = useQuery({
queryKey: ["ollamaStatus"],
queryFn: async () => {
const ollamaURL = await getOllamaURL()
const isOk = await isOllamaRunning()
const queryClient = useQueryClient()
if (ollamaURL) {
saveOllamaURL(ollamaURL)
}
const questions = [
{
title: "如何开发一个适合超大型城市的碳普惠方法学?",
icon: <img src={RocketSvg} alt="Rocket" className="w-10 my-0" />,
return {
isOk,
ollamaURL
}
},
{
title: "如何开发一个零碳园区的数字化评价系统?",
icon: <img src={BulbSvg} alt="Rocket" className="w-10 my-0" />,
},
{
title: "如何开发一个碳定价预测系统?",
icon: <img src={EyeSvg} alt="Rocket" className="w-10 my-0" />,
},
{
title: "新药临床研究如何提升实验安全性?",
icon: <img src={ASvg} alt="Rocket" className="w-10 my-0" />,
},
{
title: "如何加速新药申报和审批?",
icon: <img src={BSvg} alt="Rocket" className="w-10 my-0" />,
},
{
title: "如何研制与司美格鲁肽相似的新药?",
icon: <img src={CSvg} alt="Rocket" className="w-10 my-0" />,
},
{
title: "如何解决固态电池的成本和寿命难题?",
icon: <img src={DSvg} alt="Rocket" className="w-10 my-0" />,
},
{
title: "如何解决船舶制造中的材料腐蚀难题?",
icon: <img src={ESvg} alt="Rocket" className="w-10 my-0" />,
},
{
title: "如何解决船舶制造中流体模拟和建模优化难题?",
icon: <img src={FSvg} alt="Rocket" className="w-10 my-0" />,
},
]
const { mutateAsync: sendMessage } = useMutation({
mutationFn: onSubmit,
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["fetchChatHistory"]
})
}
enabled: checkOllamaStatus
})
useEffect(() => {
if (ollamaInfo?.ollamaURL) {
setOllamaURL(ollamaInfo.ollamaURL)
}
}, [ollamaInfo])
function handleQuestion(message: string) {
void sendMessage({message, image: ''})
}
return (
<div className="w-full p-4">
{/* 标题区域 */}
<div className="mb-4">
<h2 className="text-xl font-bold text-gray-800" style={{lineHeight: '0'}}></h2>
<p className="text-sm text-gray-500"></p>
if (!checkOllamaStatus) {
return (
<div className="mx-auto sm:max-w-xl px-4 mt-10">
<div className="rounded-lg justify-center items-center flex flex-col border p-8 bg-gray-50 dark:bg-[#262626] dark:border-gray-600">
<h1 className="text-sm font-medium text-center text-gray-500 dark:text-gray-400 flex gap-3 items-center justify-center">
<span >👋</span>
<span className="text-gray-700 dark:text-gray-300">
{t("welcome")}
</span>
</h1>
</div>
</div>
{/* 卡片网格布局 */}
<Row gutter={[16, 16]} className="w-full">
{questions.map((item, index) => (
<Col key={index} xs={24} sm={12} md={8}>
<Card
hoverable
style={{backgroundColor: "#f3f4f6"}}
className="border border-gray-200 rounded-lg shadow-sm hover:shadow-md transition-shadow duration-200 cursor-pointer"
onClick={() => handleQuestion(item.title)}
>
<div className="flex items-center">
<div className="text-blue-500 mr-2">{item.icon}</div>
<div className="font-medium text-sm text-gray-800">{item.title}</div>
)
}
return (
<div className="mx-auto sm:max-w-xl px-4 mt-10">
<div className="rounded-lg justify-center items-center flex flex-col border p-8 bg-gray-50 dark:bg-[#262626] dark:border-gray-600">
{(ollamaStatus === "pending" || isRefetching) && (
<div className="inline-flex items-center space-x-2">
<div className="w-3 h-3 bg-blue-500 rounded-full animate-pulse"></div>
<p className="dark:text-gray-400 text-gray-900">
{t("ollamaState.searching")}
</p>
</div>
)}
{!isRefetching && ollamaStatus === "success" ? (
ollamaInfo.isOk ? (
<div className="inline-flex items-center space-x-2">
<div className="w-3 h-3 bg-green-500 rounded-full animate-pulse"></div>
<p className="dark:text-gray-400 text-gray-900">
{t("ollamaState.running")}
</p>
</div>
) : (
<div className="flex flex-col space-y-2 justify-center items-center">
<div className="inline-flex space-x-2">
<div className="w-3 h-3 bg-red-500 rounded-full animate-pulse"></div>
<p className="dark:text-gray-400 text-gray-900">
{t("ollamaState.notRunning")}
</p>
</div>
</Card>
</Col>
))}
</Row>
<input
className="bg-gray-100 dark:bg-[#262626] dark:text-gray-100 rounded-md px-4 py-2 mt-2 w-full"
type="url"
value={ollamaURL}
onChange={(e) => setOllamaURL(e.target.value)}
/>
<button
onClick={() => {
saveOllamaURL(ollamaURL)
refetch()
}}
className="inline-flex mt-4 items-center rounded-md border border-transparent bg-black px-2 py-2 text-sm font-medium leading-4 text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-white dark:text-gray-800 dark:hover:bg-gray-100 dark:focus:ring-gray-500 dark:focus:ring-offset-gray-100 disabled:opacity-50 ">
<RotateCcw className="h-4 w-4 mr-3" />
{t("common:retry")}
</button>
{ollamaURL &&
cleanUrl(ollamaURL) !== "http://127.0.0.1:11434" && (
<p className="text-xs text-gray-500 dark:text-gray-400 mb-4 text-center">
<Trans
i18nKey="playground:ollamaState.connectionError"
components={{
anchor: (
<a
href="https://github.com/n4ze3m/page-assist/blob/main/docs/connection-issue.md"
target="__blank"
className="text-blue-600 dark:text-blue-400"></a>
)
}}
/>
</p>
)}
</div>
)
) : null}
</div>
</div>
)
}

View File

@ -207,11 +207,11 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
}
return (
<div className="flex w-full flex-col items-center p-2 px-5 pt-1 pb-4">
<div className="flex w-full flex-col items-center p-2 pt-1 pb-4">
<div className="relative z-10 flex w-full flex-col items-center justify-center gap-2 text-base">
<div className="relative flex w-full flex-row justify-center gap-2 lg:w-5/5">
<div className="relative flex w-full flex-row justify-center gap-2 lg:w-4/5">
<div
className={` bg-neutral-50 dark:bg-[#262626] relative w-full max-w-[65rem] p-1 backdrop-blur-lg duration-100 border border-gray-300 rounded-xl dark:border-gray-600
className={` bg-neutral-50 dark:bg-[#262626] relative w-full max-w-[48rem] p-1 backdrop-blur-lg duration-100 border border-gray-300 rounded-xl dark:border-gray-600
${temporaryChat ? "!bg-gray-200 dark:!bg-black " : ""}
`}>
<div

View File

@ -60,7 +60,6 @@ export const useMessageOption = () => {
setHistory,
meteringEntries,
setMeteringEntries,
setCurrentMeteringEntry,
setStreaming,
streaming,
setIsFirstMessage,
@ -201,11 +200,6 @@ export const useMessageOption = () => {
date: new Date().getTime()
} as MeteringEntry
setCurrentMeteringEntry({
loading: true,
data: meter
})
if (!isRegenerate) {
newMessage = [
...messages,
@ -506,7 +500,7 @@ export const useMessageOption = () => {
// Save metering entry
const { cot, content } = responseResolver(fullText)
const currentMeteringEntry = {
const _meteringEntries = [{
...meter,
modelInputTokenCount: prompt.length,
modelOutputTokenCount: fullText.length,
@ -517,15 +511,9 @@ export const useMessageOption = () => {
cot,
responseContent: content,
modelResponseContent: fullText,
}
const _meteringEntries = [
currentMeteringEntry,
},
...meteringEntries,
]
setCurrentMeteringEntry({
loading: false,
data: currentMeteringEntry,
})
setMeteringEntries(_meteringEntries)
localStorage.setItem("meteringEntries", JSON.stringify(_meteringEntries))
} catch (e) {
@ -645,16 +633,6 @@ export const useMessageOption = () => {
let newMessage: Message[] = []
let generateMessageId = generateID()
const meter: MeteringEntry = {
id: generateMessageId,
queryContent: message,
date: new Date().getTime()
} as MeteringEntry
setCurrentMeteringEntry({
loading: true,
data: meter,
})
if (!isRegenerate) {
newMessage = [
@ -781,7 +759,6 @@ export const useMessageOption = () => {
let reasoningStartTime: Date | null = null
let reasoningEndTime: Date | null = null
let apiReasoning: boolean = false
const chatStartTime = new Date()
for await (const chunk of chunks) {
if (chunk?.additional_kwargs?.reasoning_content) {
@ -882,31 +859,6 @@ export const useMessageOption = () => {
setStreaming(false)
setIsProcessing(false)
setStreaming(false)
// Save metering entry
const { cot, content } = responseResolver(fullText)
const currentMeteringEntry = {
...meter,
modelInputTokenCount: prompt.length,
modelOutputTokenCount: fullText.length,
model: ollama.modelName ?? ollama.model,
relatedDataCount: 0,
timeTaken: new Date().getTime() - chatStartTime.getTime(),
date: chatStartTime.getTime(),
cot,
responseContent: content,
modelResponseContent: fullText,
}
const _meteringEntries = [
currentMeteringEntry,
...meteringEntries,
]
setCurrentMeteringEntry({
loading: false,
data: currentMeteringEntry,
})
setMeteringEntries(_meteringEntries)
} catch (e) {
const errorSave = await saveMessageOnError({
e,

View File

@ -21,27 +21,8 @@ const DEFAULT_RAG_QUESTION_PROMPT =
const DEFAUTL_RAG_SYSTEM_PROMPT = `You are a helpful AI assistant. Use the following pieces of context to answer the question at the end. If you don't know the answer, just say you don't know. DO NOT try to make up an answer. If the question is not related to the context, politely respond that you are tuned to only answer questions that are related to the context. {context} Question: {question} Helpful answer:`
const DEFAULT_WEBSEARCH_PROMPT = `你是一个中文AI助手。根据用户的问题请筛选出<iod-search-results>中的相关信息,并结合<iod-search-results>中的数据、场景(项目)、人员团队等类型的相关信息,
<iod-search-results> {current_date_time}.
<iod-search-results> Internet of Data)
\`<result doId="{doId}" name="{title}" authors="{authors}" dataType="{paper,dataset or algorithm}" year="{year}" url="{url}" id="{id}">{abstract}</result>\`
\`doId\`\`name\` :
\`[IoD source [id] doId: {doId} "{name}"]({url})\`
Or in Chinese:
\`[数联网引用[id] doId: {doId} "{name}"]({url})\`
For example, in English:
\`[IoD source [1] doId: 10.48550/arXiv.1803.05591v2 "On the insufficiency of existing momentum schemes for Stochastic Optimization"](http://arxiv.org/pdf/1803.05591v2.pdf)\`
Or in Chinese:
\`[数联网引用[1] doId: 10.48550/arXiv.1803.05591v2 "On the insufficiency of existing momentum schemes for Stochastic Optimization"](http://arxiv.org/pdf/1803.05591v2.pdf)\`
<iod-search-results>
{iod_search_results}
</iod-search-results>
`
const DEFAULT_WEBSEARCH_PROMPT2 = `You are an AI assistant specialized in retrieving and analyzing academic papers from Neo4j graph database.
const DEFAULT_WEBSEARCH_PROMPT = `You are an AI assistant specialized in retrieving and analyzing academic papers from Neo4j graph database.
Generate a response that how can user achieve his request based on provided search results. The current date and time are {current_date_time}.
@ -67,6 +48,7 @@ Use this information to generate a meaningful response that includes:
<iod-search-results>
{iod_search_results}
</iod-search-results>
`
const DEFAULT_WEBSEARCH2_PROMPT = `You are an AI model who is expert at searching the web and answering user's queries.

View File

@ -35,8 +35,6 @@ type State = {
setMessages: (messages: Message[]) => void
history: ChatHistory
setHistory: (history: ChatHistory) => void
currentMeteringEntry: {data: MeteringEntry, loading: boolean}
setCurrentMeteringEntry: (meteringEntry: {data: MeteringEntry, loading: boolean}) => void
meteringEntries: MeteringEntry[]
setMeteringEntries: (meteringEntries: MeteringEntry[]) => void
streaming: boolean
@ -122,8 +120,6 @@ export const useStoreMessageOption = create<State>((set) => ({
setMessages: (messages) => set({ messages }),
history: [],
setHistory: (history) => set({ history }),
currentMeteringEntry: {data: {} as MeteringEntry, loading: false},
setCurrentMeteringEntry: (currentMeteringEntry) => set({ currentMeteringEntry }),
meteringEntries: JSON.parse(localStorage.getItem("meteringEntries") || JSON.stringify([])),
setMeteringEntries: (meteringEntries) => set({ meteringEntries }),
streaming: false,

View File

@ -26,12 +26,6 @@ export const tokenizeInput = function (input: string): string[] {
}
//doipUrl = tcp://reg01.public.internetofdata.cn:21037
export const iodConfig = {
"gatewayUrl": "tcp://reg01.public.internetofdata.cn:21037",
"registry":"data/Registry",
"localRepository":"data/Repository",
"doBrowser":"http://021.node.internetapi.cn:21030/SCIDE/SCManager"
}
export const iodConfigLocal = {
"gatewayUrl": "tcp://127.0.0.1:21036",
"registry":"bdware/Registry",
"localRepository":"bdtest.local/myrepo1",
@ -40,51 +34,6 @@ export const iodConfigLocal = {
function inGrepList(str: string){
return "什么|问题|需要|合适|设计|考虑|合作|精度|传感器|最新|研究|药物".indexOf(str)!=-1;
}
export const makeSearchParamsWithDataType = function(count: number, keyword: string| string[], dataType: string){
const searchMode = [];
searchMode.push({"key":"data_type", "type":"MUST", "value":dataType})
if (typeof keyword === 'string') {
// 如果 keyword 是字符串,则直接添加一个 searchMode 条目
searchMode.push({
key: "description",
type: "MUST",
value: keyword
});
} else if (Array.isArray(keyword)) {
// 如果 keyword 是数组,则为每个元素添加一个 searchMode 条目
keyword.forEach(str => {
if (!inGrepList(str))
searchMode.push({
key: "description",
type: "SHOULD",
value: str
});
});
}
return {
action: "executeContract",
contractID: "BDBrowser",
operation: "sendRequestDirectly",
arg: {
id: iodConfig.registry,
//doipUrl:"tcp://127.0.0.1:21039",
doipUrl: iodConfig.gatewayUrl,
op: "Search",
vars:{
timeout:15000
},
attributes: {
offset: 0,
count,
bodyBase64Encoded: false,
searchMode:searchMode
},
body: ""
}
}
}
export const makeRegSearchParams = function(count: number, keyword: string| string[]){
const searchMode = [];
if (typeof keyword === 'string') {
@ -236,61 +185,92 @@ export async function localIodSearch(
const abortController = new AbortController();
setTimeout(() => abortController.abort(), 10000);
const params = makeRegSearchParams(TOTAL_SEARCH_RESULTS, keywords);
const dataParams = makeSearchParamsWithDataType(TOTAL_SEARCH_RESULTS,keywords, "data");
const scenarioParams = makeSearchParamsWithDataType(TOTAL_SEARCH_RESULTS,keywords, "scenario");
const orgParams = makeSearchParamsWithDataType(TOTAL_SEARCH_RESULTS,keywords, "organization");
try {
console.log('params------->',params)
const requests = [
fetch(iodConfig.doBrowser,{method: "POST", body: JSON.stringify(dataParams),signal: abortController.signal}),
fetch(iodConfig.doBrowser,{method: "POST", body: JSON.stringify(scenarioParams),signal: abortController.signal}),
fetch(iodConfig.doBrowser,{method: "POST", body: JSON.stringify(orgParams),signal: abortController.signal})
];
//TODO @Zhaoweijie 这三类分别是数据、场景、团队的搜索请求。
const responses = await Promise.all(requests);
const results = await Promise.all(responses.map(res => res.json()));
const allResults: IodRegistryEntry[] = [];
for (const res of results) {
// 检查顶层状态
if (res.status !== "Success") {
continue; // 跳过失败的请求
}
let body;
try {
body = JSON.parse(res.result.body);
} catch (e) {
console.warn("Failed to parse result.body as JSON", e);
continue;
}
const response = await fetch(iodConfig.doBrowser, {
method: "POST",
body: JSON.stringify(params),
signal: abortController.signal
});
if (body.code !== 0) {
continue;
}
const entries: IodRegistryEntry[] = body.data?.results || [];
// 数据清洗:补全 url 和 doId
for (const r of entries) {
r.url = r.url || r.pdf_url;
r.doId = r.doId || r.doid;
}
// 合并到总结果
allResults.push(...entries);
const res = await response.json();
if (res.status !== "Success") {
console.log(res);
return [];
}
const seenDoIds = new Set<string>();
const prunedResults: IodRegistryEntry[] = [];
for (const r of allResults) {
if (r.doId && !seenDoIds.has(r.doId)) {
seenDoIds.add(r.doId);
prunedResults.push(r);
}
const body = JSON.parse(res.result.body);
if (body.code !== 0) {
console.log(body);
return [];
}
return prunedResults;
let results: IodRegistryEntry[] = body.data?.results || [];
for (const r of results) {
r.url = r.url || r.pdf_url;
}
for (const r of results) {
r.doId = r.doId || r.doid;
}
// results 根据 doId 去重
const map = new Map<string, IodRegistryEntry>();
for (const r of results) {
map.set(r.doId, r);
}
return Array.from(map.values());
} catch (e) {
console.log(e);
return [];
}
/*
const results = (
await Promise.all(
keywords.map(async (keyword) => {
const abortController = new AbortController()
setTimeout(() => abortController.abort(), 10000)
//http://47.93.156.31:21033/SCIDE/SCManager
const params = makeRegSearchParams(TOTAL_SEARCH_RESULTS, keyword)
return fetch(iodConfig.doBrowser, {
method: "POST",
body: JSON.stringify(params),
signal: abortController.signal
})
.then((response) => response.json())
.then((res) => {
if (res.status !== "Success") {
console.log(res)
return []
}
const body = JSON.parse(res.result.body)
if (body.code !== 0) {
console.log(body)
return []
}
const results: IodRegistryEntry[] = body.data?.results || []
for (const r of results) {
r.url = r.url || r.pdf_url
}
for (const r of results) {
r.doId = r.doId || r.doid
}
return results
})
.catch((e) => {
console.log(e)
return []
})
})
)
).flat()
// results 根据 doId 去重
const map = new Map<string, IodRegistryEntry>()
for (const r of results) {
map.set(r.doId, r)
}
return Array.from(map.values())
*/
}
const ARXIV_URL_PATTERN = /^https?:\/\/arxiv\.org\//
@ -301,7 +281,6 @@ export const searchIod = async (query: string, keywords: string[]) => {
const isSimpleMode = await getIsSimpleInternetSearch()
console.log("searchMode:"+isSimpleMode+"\n kw:"+JSON.stringify(keywords)+"\n"+" ->searchResult:\n"+JSON.stringify(searchResults))
console.log("pruned Search Result:"+JSON.stringify(searchResults.map(r=>r.doId+" "+r.name)))
if (isSimpleMode) {
await getOllamaURL()
return searchResults

File diff suppressed because one or more lines are too long

View File

@ -5,9 +5,6 @@ module.exports = {
content: ["./src/**/*.tsx"],
theme: {
extend: {
width: {
'1/10': '10%',
},
backgroundImage: {
'bottom-mask-light': 'linear-gradient(0deg, transparent 0, #ffffff 160px)',
'bottom-mask-dark': 'linear-gradient(0deg, transparent 0, #171717 160px)',