feat(web): memory manage & memory detail ui upgrade
14
web/src/assets/images/common/arrow_up.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<title>下拉</title>
|
||||||
|
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="记忆管理-记忆提取引擎-2" transform="translate(-806, -166)">
|
||||||
|
<g id="文本" transform="translate(252, 154)">
|
||||||
|
<g id="下拉" transform="translate(562, 20) scale(1, -1) translate(-562, -20)translate(554, 12)">
|
||||||
|
<rect id="矩形" opacity="0.236839658" fill-rule="nonzero" x="0" y="0" width="16" height="16"></rect>
|
||||||
|
<polyline id="路径" stroke="#5B6167" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" points="12 6 8 10 4 6"></polyline>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 920 B |
20
web/src/assets/images/common/check_green.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<title>完成</title>
|
||||||
|
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="记忆管理-记忆提取引擎-2" transform="translate(-1288, -508)" fill-rule="nonzero">
|
||||||
|
<g id="编组-26" transform="translate(846, 102)">
|
||||||
|
<g id="编组-48" transform="translate(12, 362)">
|
||||||
|
<g id="1" transform="translate(0, 32)">
|
||||||
|
<g id="编组-31" transform="translate(422, 8)">
|
||||||
|
<g id="完成" transform="translate(8, 4)">
|
||||||
|
<rect id="矩形" opacity="0.205054874" x="0" y="0" width="16" height="16"></rect>
|
||||||
|
<path d="M8,1 C4.13401843,1 1,4.13399462 1,8 C1,11.8660054 4.13401843,15 8,15 C11.8660404,15 15,11.8660054 15,8 C15,4.13400935 11.8660697,1 8,1 L8,1 Z M11.8488905,6.3221368 L7.34274977,10.9336514 C7.13545231,11.145815 6.79915605,11.145815 6.59188798,10.9336514 L4.15112422,8.43567652 C3.9436945,8.22349821 3.9436945,7.87942608 4.15112422,7.66718889 C4.35840699,7.45493698 4.69471795,7.45493698 4.90198602,7.66718889 L6.96733357,9.78080221 L11.0978817,5.55359028 C11.3053114,5.34135309 11.6416371,5.34135309 11.8489052,5.55359028 C12.0563349,5.76581275 12.0563349,6.10989961 11.8489052,6.3221368 L11.8488905,6.3221368 Z" id="形状" fill="#369F21"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
19
web/src/assets/images/common/save.svg
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<title>保存</title>
|
||||||
|
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||||
|
<g id="记忆管理-记忆提取引擎" transform="translate(-1269, -122)" stroke="#171719">
|
||||||
|
<g id="编组-26" transform="translate(846, 102)">
|
||||||
|
<g id="副操作" transform="translate(414, 11)">
|
||||||
|
<g id="保存" transform="translate(9, 9)">
|
||||||
|
<g id="编组-12" transform="translate(1.925, 1.75)">
|
||||||
|
<path d="M1.5,0 L7.33055996,0 L7.33055996,0 L10.15,2.91453026 L10.15,9 C10.15,9.82842712 9.47842712,10.5 8.65,10.5 L1.5,10.5 C0.671572875,10.5 0,9.82842712 0,9 L0,1.5 C0,0.671572875 0.671572875,0 1.5,0 Z" id="矩形"></path>
|
||||||
|
<polyline id="路径-12" stroke-linecap="round" points="2.45 0 2.45 3.5 6.825 3.5"></polyline>
|
||||||
|
<rect id="矩形" stroke-linecap="round" x="2.45" y="6.125" width="5.25" height="4.375"></rect>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
BIN
web/src/assets/images/empty/noData.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
18
web/src/assets/images/memory/clock_orange.svg
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<title>时间戳</title>
|
||||||
|
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="记忆管理-记忆提取引擎" transform="translate(-1303, -376)" fill-rule="nonzero">
|
||||||
|
<g id="编组-26" transform="translate(846, 102)">
|
||||||
|
<g id="1" transform="translate(12, 262)">
|
||||||
|
<g id="编组-31" transform="translate(437, 8)">
|
||||||
|
<g id="时间戳" transform="translate(8, 4)">
|
||||||
|
<rect id="矩形" fill="#000000" opacity="0" x="0" y="0" width="16" height="16"></rect>
|
||||||
|
<path d="M8.33332812,1.5 C11.9233281,1.5 14.8333281,4.41 14.8333281,8 C14.8333281,11.59 11.9233281,14.5 8.33332812,14.5 C4.74332813,14.5 1.83332812,11.59 1.83332812,8 C1.83332812,4.41 4.74332813,1.5 8.33332812,1.5 Z M8.33332812,2.5 C5.29567188,2.5 2.83332812,4.96234375 2.83332812,8 C2.83332812,11.0376562 5.29567188,13.5 8.33332812,13.5 C11.3709844,13.5 13.8333281,11.0376562 13.8333281,8 C13.8333281,4.96234375 11.371,2.5 8.33332812,2.5 Z M8.83332812,4.322 L8.83332812,7.775 L11.3833281,10.0336719 L10.7206719,10.782 L7.83332812,8.22532813 L7.83332812,4.322 L8.83332812,4.322 Z" id="形状" fill="#FF5D34"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
15
web/src/assets/images/memory/debug.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<title>配置管理</title>
|
||||||
|
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="记忆管理-记忆提取引擎" transform="translate(-1344, -122)" fill="#FFFFFF" fill-rule="nonzero" stroke="#FFFFFF" stroke-width="0.3">
|
||||||
|
<g id="编组-26" transform="translate(846, 102)">
|
||||||
|
<g id="副操作备份" transform="translate(490, 11)">
|
||||||
|
<g id="配置管理" transform="translate(8, 9)">
|
||||||
|
<path d="M7.42879146,7.0538149 L7.42879146,1.42856378 C7.42879146,1.19188803 7.23488102,1 6.99819188,1 C6.76150275,1 6.56757891,1.19188803 6.56757891,1.42856378 L6.56757891,7.0546319 C5.83214429,7.24550203 5.28435198,7.91628644 5.28435198,8.71456315 C5.28435198,9.51404527 5.83108621,10.1856467 6.57135586,10.3753516 C6.56898461,10.3931451 6.56772319,10.4110689 6.56757891,10.4290192 L6.56757891,12.5718916 C6.56757891,12.8085807 6.76150275,13.0004822 6.99817849,13.0004822 C7.23485423,13.0004822 7.42879146,12.8085807 7.42879146,12.5718916 L7.42879146,10.4290325 C7.42845218,10.411363 7.42702981,10.393731 7.42453235,10.3762355 C8.16639582,10.1875486 8.71563466,9.51502299 8.71563466,8.7146703 C8.71578195,7.91518818 8.16904773,7.24362695 7.42879146,7.0538283 L7.42879146,7.0538149 Z M7.60587973,9.32065717 C7.31671051,9.609836 6.8635355,9.65447605 6.52350043,9.42727705 C6.18346536,9.20007806 6.05127565,8.76431872 6.20777383,8.38649396 C6.36427201,8.0086692 6.76587074,7.79400949 7.1669665,7.87379309 C7.56806226,7.95357669 7.85694345,8.30558254 7.85694345,8.71453636 C7.85758337,8.9420223 7.76717752,9.16030816 7.60587973,9.32072414 L7.60587973,9.32065717 Z M3.13814456,2.76797625 C3.14055877,2.75020331 3.14186492,2.73229739 3.14205545,2.71436225 L3.14205545,1.42859056 C3.14205545,1.19210844 2.95034881,1.0004018 2.71386669,1.0004018 C2.47738457,1.0004018 2.28567793,1.19210844 2.28567793,1.42859056 L2.28567793,2.71436225 C2.28534183,2.73252066 2.28614702,2.75068225 2.28808875,2.76873968 C1.54783249,2.95840439 1,3.62996562 1,4.4295415 C1,5.22911737 1.54792625,5.90038395 2.28818251,6.09028975 C2.28629436,6.10780474 2.28547584,6.12541856 2.28573151,6.14303317 L2.28573151,12.5719184 C2.28573151,12.8084005 2.47743814,13.0001071 2.71392026,13.0001071 C2.95040239,13.0001071 3.14210902,12.8084005 3.14210902,12.5719184 L3.14210902,6.14305996 C3.14191505,6.12566525 3.14067166,6.1082981 3.13838564,6.09105317 C3.88019554,5.90235278 4.42884504,5.22982722 4.42884504,4.4295281 C4.42884504,3.62922898 3.88004822,2.9565561 3.13814456,2.76796286 L3.13814456,2.76797625 Z M3.31996071,5.03568909 C3.03078814,5.32485849 2.57761807,5.36949099 2.23758857,5.14229141 C1.89755906,4.91509182 1.76537191,4.47933761 1.92186671,4.10151611 C2.07836152,3.7236946 2.47995285,3.50903305 2.88104582,3.58880862 C3.28213879,3.6685842 3.57103772,4.02057858 3.57103772,4.4295281 C3.571667,4.65700012 3.48126198,4.87526953 3.31997411,5.0356757 L3.31996071,5.03568909 Z M13,4.4295415 C13,3.62894772 12.4502255,2.95656949 11.7081745,2.76797625 C11.710058,2.75017021 11.7108363,2.73226456 11.7105049,2.71436225 L11.7105049,1.42859056 C11.7105049,1.19210844 11.5187983,1.0004018 11.2823162,1.0004018 C11.0458341,1.0004018 10.8541274,1.19210844 10.8541274,1.42859056 L10.8541274,2.71436225 C10.8543217,2.73255453 10.8556637,2.75071642 10.8581455,2.76873968 C10.1178758,2.95840439 9.57080673,3.62996562 9.57080673,4.4295415 C9.57080673,5.22911737 10.1175276,5.90062503 10.8577972,6.09032993 C10.8554298,6.1080924 10.8541684,6.12598481 10.8540203,6.14390375 L10.8540203,12.5719184 C10.8540203,12.8084005 11.0457269,13.0001071 11.282209,13.0001071 C11.5186911,13.0001071 11.7103978,12.8084005 11.7103978,12.5719184 L11.7103978,6.14389035 C11.7107305,6.12626252 11.709988,6.1086308 11.7081745,6.09109335 C12.450279,5.90245993 13,5.2300817 13,4.4295281 L13,4.4295415 Z M11.8917452,5.03563552 C11.6025705,5.32476645 11.1494259,5.36936451 10.8094336,5.14215559 C10.4694413,4.91494666 10.3372926,4.47921076 10.4938036,4.10142382 C10.6503147,3.72363689 11.0518954,3.50901645 11.4529577,3.58881444 C11.85402,3.66861244 12.1428487,4.02060432 12.1428487,4.4295281 C12.1434533,4.65698737 12.0530346,4.87523566 11.8917452,5.03562213 L11.8917452,5.03563552 Z" id="形状"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -1,13 +1,15 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<title>我</title>
|
<title>我</title>
|
||||||
<g id="V1.0版" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
<g id="红熊空间-记忆库-用户记忆-详情" transform="translate(-272, -458)" stroke="#212332" stroke-width="1.5">
|
<g id="记忆库-个人记忆(RAG)" transform="translate(-268, -153)" stroke="#171719" stroke-width="1.2">
|
||||||
<g id="个人信息" transform="translate(256, 80)">
|
<g id="编组-13" transform="translate(252, 64)">
|
||||||
<g id="关于我" transform="translate(0, 361)">
|
<g id="编组-21" transform="translate(12, 88)">
|
||||||
<g id="我" transform="translate(16, 17)">
|
<g id="编组-32" transform="translate(4, 0)">
|
||||||
<circle id="椭圆形" cx="10" cy="6" r="3"></circle>
|
<g id="我" transform="translate(0, 1)">
|
||||||
<path d="M10,17 C13.8659932,17 17,16.078564 17,14.5 C17,12.921436 13.8659932,12 10,12 C6.13400675,12 3,12.9530326 3,14.5 C3,16.0469674 6.13400675,17 10,17 Z" id="椭圆形"></path>
|
<circle id="椭圆形" cx="9" cy="5.4" r="2.7"></circle>
|
||||||
|
<path d="M9,15.3 C12.4793939,15.3 15.3,14.4707076 15.3,13.05 C15.3,11.6292924 12.4793939,10.8 9,10.8 C5.52060608,10.8 2.7,11.6577293 2.7,13.05 C2.7,14.4422707 5.52060608,15.3 9,15.3 Z" id="椭圆形"></path>
|
||||||
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 988 B After Width: | Height: | Size: 1.1 KiB |
BIN
web/src/assets/images/userMemory/ai.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
18
web/src/assets/images/userMemory/me.svg
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<title>我</title>
|
||||||
|
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="记忆库-个人记忆(RAG)" transform="translate(-268, -153)" stroke="#171719" stroke-width="1.2">
|
||||||
|
<g id="编组-13" transform="translate(252, 64)">
|
||||||
|
<g id="编组-21" transform="translate(12, 88)">
|
||||||
|
<g id="编组-32" transform="translate(4, 0)">
|
||||||
|
<g id="我" transform="translate(0, 1)">
|
||||||
|
<circle id="椭圆形" cx="9" cy="5.4" r="2.7"></circle>
|
||||||
|
<path d="M9,15.3 C12.4793939,15.3 15.3,14.4707076 15.3,13.05 C15.3,11.6292924 12.4793939,10.8 9,10.8 C5.52060608,10.8 2.7,11.6577293 2.7,13.05 C2.7,14.4422707 5.52060608,15.3 9,15.3 Z" id="椭圆形"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -1,12 +1,29 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<title>热点洞察</title>
|
<title>编组 26</title>
|
||||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
|
||||||
<g id="个人记忆" transform="translate(-40, -317)" fill="#171719" fill-rule="nonzero">
|
<g id="记忆库-个人记忆(RAG)" transform="translate(-268, -357)" stroke="#171719" stroke-width="1.2">
|
||||||
<g id="编组" transform="translate(12, 12)">
|
<g id="编组-13" transform="translate(252, 64)">
|
||||||
<g id="编组-11" transform="translate(16, 104)">
|
<g id="编组-31" transform="translate(12, 292)">
|
||||||
<g id="热点洞察" transform="translate(12, 201)">
|
<g id="编组-26" transform="translate(4, 1)">
|
||||||
<path d="M3.9387755,13.4 C5.06122447,13.4 5.87755102,14.3 5.87755102,15.3 C5.87755102,15.7 5.77551019,16.1 5.57142857,16.4 C6.89795919,18.6 9.44897958,20.1 12.2040816,20.1 C12.8163265,20.1 13.4285714,20 14.0408163,19.9 C14.5510204,19.8 15.0612245,20.1 15.2653061,20.6 C15.3673469,21.1 15.0612245,21.6 14.5510204,21.8 C13.8367347,21.9 13.0204082,22 12.2040816,22 C8.63265306,22 5.46938774,20.1 3.73469387,17.2 C2.7142857,17.1 2,16.3 2,15.3 C2,14.3 2.91836735,13.4 3.9387755,13.4 L3.9387755,13.4 Z M19.3469388,5.9 C21.0816327,7.7 22,9.99999999 22,12.4 C22,14.1 21.5918367,15.7 20.7755102,17.1 C20.9795918,17.4 21.0816327,17.7 21.0816327,18.1 C21.0816327,19.2 20.1632653,20 19.1428572,20 C18.122449,20 17.1020408,19.2 17.1020408,18.2 C17.1020408,17.2 17.9183673,16.4 18.9387755,16.3 L19.0408163,16.3 L19.1428572,16 C19.7551021,14.9 20.0612245,13.7 20.0612245,12.5 C20.0612245,10.5 19.244898,8.7 17.9183674,7.30000001 C17.5102041,6.9 17.6122449,6.3 17.9183674,6 C18.3265306,5.50000001 18.9387755,5.6 19.3469388,5.9 L19.3469388,5.9 Z M12.2040816,8.7 C14.3469388,8.7 16.0816327,10.4 16.0816327,12.5 C16.0816327,14.6 14.3469388,16.3 12.2040816,16.3 C10.0612245,16.3 8.32653061,14.6 8.32653061,12.5 C8.32653061,10.4 10.0612245,8.7 12.2040816,8.7 Z M12.2040816,10.6 C11.0816327,10.6 10.2653061,11.5 10.2653061,12.5 C10.2653061,13.5 11.1836735,14.4 12.2040816,14.4 C13.2244898,14.4 14.1428571,13.5 14.1428571,12.5 C14.1428571,11.5 13.3265306,10.6 12.2040816,10.6 Z M14.1428571,2 C15.2653061,2 16.0816327,2.9 16.0816327,3.90000001 C16.0816327,4.90000001 15.1632653,5.80000001 14.1428571,5.80000001 C13.4285714,5.80000001 12.8163265,5.40000001 12.5102041,4.90000001 L12.2040816,4.90000001 C8.63265306,4.90000001 5.57142857,7.2 4.65306122,10.5 C4.55102039,11 3.9387755,11.3 3.42857142,11.2 C3.02040815,11 2.7142857,10.5 2.81632652,10 C3.9387755,5.90000002 7.81632654,3 12.2040816,3 L12.5102041,3 C12.8163265,2.40000001 13.4285714,2 14.1428571,2 L14.1428571,2 Z" id="形状"></path>
|
<g id="编组-24" transform="translate(2, 2)">
|
||||||
|
<g id="编组-23" transform="translate(7, 0)">
|
||||||
|
<path d="M3.80487741,4.75801529 C4.57304648,4.31981911 5.09090909,3.49311348 5.09090909,2.54545455 C5.09090909,1.13963882 3.95127027,0 2.54545455,0 C1.13963882,0 0,1.13963882 0,2.54545455 L0,11.4545455" id="路径" stroke-linejoin="round"></path>
|
||||||
|
<path d="M0,11.4545455 C0,12.8603612 1.13963882,14 2.54545455,14 C3.95127027,14 5.09090909,12.8603612 5.09090909,11.4545455" id="路径" stroke-linejoin="round"></path>
|
||||||
|
<path d="M5.43716946,6.89920585 C6.34272849,6.61654964 7,5.77139545 7,4.77272727 C7,3.65162269 6.17168669,2.72398105 5.09366357,2.56840585" id="路径" stroke-linejoin="round"></path>
|
||||||
|
<path d="M5.08556316,11.8284839 C6.21217524,11.3387175 7,10.2159074 7,8.90909091 C7,8.05692399 6.66499617,7.2830014 6.11950096,6.7118356" id="路径" stroke-linejoin="round"></path>
|
||||||
|
<path d="M6.05374225e-07,3.30502525 C0.598221325,3.16656842 1.19644204,3.53131423 1.79466276,4.39926267" id="路径-73"></path>
|
||||||
|
<path d="M0,6.36955959 C0,7.05675687 0.699825901,9.10572809 3.14599655,8.05286405" id="路径-74"></path>
|
||||||
|
</g>
|
||||||
|
<g id="编组-23" transform="translate(3.5, 7) scale(-1, 1) translate(-3.5, -7)">
|
||||||
|
<path d="M3.80487741,4.75801529 C4.57304648,4.31981911 5.09090909,3.49311348 5.09090909,2.54545455 C5.09090909,1.13963882 3.95127027,0 2.54545455,0 C1.13963882,0 0,1.13963882 0,2.54545455 L0,11.4545455" id="路径" stroke-linejoin="round"></path>
|
||||||
|
<path d="M0,11.4545455 C0,12.8603612 1.13963882,14 2.54545455,14 C3.95127027,14 5.09090909,12.8603612 5.09090909,11.4545455" id="路径" stroke-linejoin="round"></path>
|
||||||
|
<path d="M5.43716946,6.89920585 C6.34272849,6.61654964 7,5.77139545 7,4.77272727 C7,3.65162269 6.17168669,2.72398105 5.09366357,2.56840585" id="路径" stroke-linejoin="round"></path>
|
||||||
|
<path d="M5.08556316,11.8284839 C6.21217524,11.3387175 7,10.2159074 7,8.90909091 C7,8.05692399 6.66499617,7.2830014 6.11950096,6.7118356" id="路径" stroke-linejoin="round"></path>
|
||||||
|
<path d="M6.05374225e-07,3.30502525 C0.598221325,3.16656842 1.19644204,3.53131423 1.79466276,4.39926267" id="路径-73"></path>
|
||||||
|
<path d="M0,6.36955959 C0,7.05675687 0.699825901,9.10572809 3.14599655,8.05286405" id="路径-74"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 3.4 KiB |
BIN
web/src/assets/images/userMemory/user.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
49
web/src/components/BtnTabs/index.tsx
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* @Author: ZhaoYing
|
||||||
|
* @Date: 2026-03-19 14:05:09
|
||||||
|
* @Last Modified by: ZhaoYing
|
||||||
|
* @Last Modified time: 2026-03-19 14:05:09
|
||||||
|
*/
|
||||||
|
import { type FC } from 'react'
|
||||||
|
import { Flex } from 'antd';
|
||||||
|
import clsx from 'clsx'
|
||||||
|
|
||||||
|
/** A single tab item with a display label and unique key */
|
||||||
|
interface Tab {
|
||||||
|
label: string
|
||||||
|
key: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Props for the BtnTabs component */
|
||||||
|
interface BtnTabsProps {
|
||||||
|
/** List of tab items to render */
|
||||||
|
items: Tab[]
|
||||||
|
/** Key of the currently active tab */
|
||||||
|
activeKey: string
|
||||||
|
/** Callback fired when a tab is clicked */
|
||||||
|
onChange: (key: string) => void;
|
||||||
|
/** Optional extra class name for the container */
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Button-style tab switcher — renders tabs as pill-shaped buttons with active highlight */
|
||||||
|
const BtnTabs: FC<BtnTabsProps> = ({ items, activeKey, onChange, className }) => {
|
||||||
|
return (
|
||||||
|
<Flex align="center" gap={8} className={className || ''}>
|
||||||
|
{items.map((tab) => (
|
||||||
|
<div
|
||||||
|
key={tab.key}
|
||||||
|
onClick={() => onChange(tab.key)}
|
||||||
|
className={clsx('rb:px-2 rb:py-1 rb:rounded-[13px] rb:text-[12px] rb:leading-4.5 rb:cursor-pointer', {
|
||||||
|
'rb:bg-[#F6F6F6]': activeKey !== tab.key,
|
||||||
|
'rb:bg-[#171719] rb:text-white': activeKey === tab.key,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{tab.label}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BtnTabs
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-03-07 16:49:59
|
* @Date: 2026-03-07 16:49:59
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-07 17:14:57
|
* @Last Modified time: 2026-03-18 10:12:23
|
||||||
*/
|
*/
|
||||||
import { useEffect, useState, type FC } from 'react';
|
import { useEffect, useState, type FC } from 'react';
|
||||||
import { Select, Flex, Space } from 'antd';
|
import { Select, Flex, Space } from 'antd';
|
||||||
@@ -19,11 +19,13 @@ interface ModelSelectProps extends SelectProps {
|
|||||||
/** Extra query params passed to getModelList */
|
/** Extra query params passed to getModelList */
|
||||||
params?: Query;
|
params?: Query;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
|
fontClassName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModelSelect: FC<ModelSelectProps> = ({
|
const ModelSelect: FC<ModelSelectProps> = ({
|
||||||
params,
|
params,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
fontClassName,
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -48,7 +50,7 @@ const ModelSelect: FC<ModelSelectProps> = ({
|
|||||||
return (
|
return (
|
||||||
<Flex align="center" gap={8}>
|
<Flex align="center" gap={8}>
|
||||||
{logo && <img src={logo} className="rb:size-5 rb:rounded-md" alt="" />}
|
{logo && <img src={logo} className="rb:size-5 rb:rounded-md" alt="" />}
|
||||||
<div className="rb:flex-1 rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap">{item.name}</div>
|
<div className={`rb:flex-1 rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap ${fontClassName}`}>{item.name}</div>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1548,7 +1548,7 @@ export const en = {
|
|||||||
Meaning: 'Meaning',
|
Meaning: 'Meaning',
|
||||||
|
|
||||||
exampleMemoryExtractionResults: 'Example Memory Extraction Results',
|
exampleMemoryExtractionResults: 'Example Memory Extraction Results',
|
||||||
exampleMemoryExtractionResultsSubTitle: '(from a technology conference)',
|
exampleMemoryExtractionResultsSubTitle: 'from a technology conference',
|
||||||
|
|
||||||
extractTheNumberOfEntities: 'Extract the number of entities',
|
extractTheNumberOfEntities: 'Extract the number of entities',
|
||||||
extractTheNumberOfEntitiesDesc: 'Merge after deduplication: {{num}} (exact: {{exact}}, fuzzy: {{fuzzy}}, LLM: {{llm}})',
|
extractTheNumberOfEntitiesDesc: 'Merge after deduplication: {{num}} (exact: {{exact}}, fuzzy: {{fuzzy}}, LLM: {{llm}})',
|
||||||
@@ -1670,7 +1670,12 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re
|
|||||||
disagreementCase: 'Disagreement Case',
|
disagreementCase: 'Disagreement Case',
|
||||||
Pruned: 'Pruned',
|
Pruned: 'Pruned',
|
||||||
pruning: 'Pruning',
|
pruning: 'Pruning',
|
||||||
pruning_desc: 'Text pruning {{count}} fragments'
|
pruning_desc: 'Text pruning {{count}} fragments',
|
||||||
|
|
||||||
|
processData: 'Process Data',
|
||||||
|
finalResult: 'Final Result',
|
||||||
|
chunking: 'Chunking',
|
||||||
|
dataStatistics: 'Data Statistics',
|
||||||
},
|
},
|
||||||
memoryConversation: {
|
memoryConversation: {
|
||||||
searchPlaceholder: 'Enter user ID...',
|
searchPlaceholder: 'Enter user ID...',
|
||||||
|
|||||||
@@ -1546,7 +1546,7 @@ export const zh = {
|
|||||||
Meaning: '含义',
|
Meaning: '含义',
|
||||||
|
|
||||||
exampleMemoryExtractionResults: '示例记忆提取结果',
|
exampleMemoryExtractionResults: '示例记忆提取结果',
|
||||||
exampleMemoryExtractionResultsSubTitle: '(来自技术会议)',
|
exampleMemoryExtractionResultsSubTitle: '来自技术会议',
|
||||||
|
|
||||||
extractTheNumberOfEntities: '提取实体数量',
|
extractTheNumberOfEntities: '提取实体数量',
|
||||||
extractTheNumberOfEntitiesDesc: '去重后合并:{{num}}(精确:{{exact}},模糊:{{fuzzy}},LLM:{{llm}})',
|
extractTheNumberOfEntitiesDesc: '去重后合并:{{num}}(精确:{{exact}},模糊:{{fuzzy}},LLM:{{llm}})',
|
||||||
@@ -1666,7 +1666,12 @@ export const zh = {
|
|||||||
disagreementCase: '不一致案例',
|
disagreementCase: '不一致案例',
|
||||||
Pruned: '已剪枝',
|
Pruned: '已剪枝',
|
||||||
pruning: '剪枝',
|
pruning: '剪枝',
|
||||||
pruning_desc: '文本剪枝{{count}}个片段'
|
pruning_desc: '文本剪枝{{count}}个片段',
|
||||||
|
|
||||||
|
processData: '处理数据',
|
||||||
|
finalResult: '最终结果',
|
||||||
|
chunking: '分块',
|
||||||
|
dataStatistics: '数据统计',
|
||||||
},
|
},
|
||||||
memoryConversation: {
|
memoryConversation: {
|
||||||
chatEmpty:'有什么我可以帮您的吗?',
|
chatEmpty:'有什么我可以帮您的吗?',
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 17:00:20
|
* @Date: 2026-02-03 17:00:20
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-02-04 10:03:35
|
* @Last Modified time: 2026-03-16 15:43:42
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Line Chart Component
|
* Line Chart Component
|
||||||
@@ -84,7 +84,7 @@ const SeriesConfig = {
|
|||||||
/**
|
/**
|
||||||
* Chart color palette
|
* Chart color palette
|
||||||
*/
|
*/
|
||||||
const Colors = ['#155EEF', '#4DA8FF', '#FFB048']
|
const Colors = ['#155EEF', '#4DA8FF', '#369F21']
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -228,8 +228,8 @@ const LineChart: FC<LineCardProps> = ({ config }) => {
|
|||||||
grid: {
|
grid: {
|
||||||
left: 4,
|
left: 4,
|
||||||
right: '2%',
|
right: '2%',
|
||||||
bottom: 60,
|
bottom: 48,
|
||||||
top: 32,
|
top: 8,
|
||||||
containLabel: true
|
containLabel: true
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
@@ -243,7 +243,7 @@ const LineChart: FC<LineCardProps> = ({ config }) => {
|
|||||||
show: true,
|
show: true,
|
||||||
},
|
},
|
||||||
axisTick: {
|
axisTick: {
|
||||||
show: true
|
show: false
|
||||||
},
|
},
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
color: '#5B6167'
|
color: '#5B6167'
|
||||||
@@ -268,7 +268,7 @@ const LineChart: FC<LineCardProps> = ({ config }) => {
|
|||||||
...initialData || []
|
...initialData || []
|
||||||
]
|
]
|
||||||
}}
|
}}
|
||||||
style={{ height: '450px', width: '100%' }}
|
style={{ height: '400px', width: '100%' }}
|
||||||
opts={{ renderer: 'canvas' }}
|
opts={{ renderer: 'canvas' }}
|
||||||
notMerge={true}
|
notMerge={true}
|
||||||
lazyUpdate={true}
|
lazyUpdate={true}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 17:00:12
|
* @Date: 2026-02-03 17:00:12
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-02-03 17:00:12
|
* @Last Modified time: 2026-03-16 15:41:54
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Forgetting Engine Configuration Page
|
* Forgetting Engine Configuration Page
|
||||||
@@ -11,16 +11,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Row, Col, Form, Slider, Button, Space, message } from 'antd';
|
import { Row, Col, Form, Button, Space, message, Flex, Tooltip } from 'antd';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import RbCard from '@/components/RbCard/Card';
|
import RbCard from '@/components/RbCard/Card';
|
||||||
import strategyImpactSimulator from '@/assets/images/memory/strategyImpactSimulator.svg'
|
|
||||||
import LineChart from './components/LineChart'
|
import LineChart from './components/LineChart'
|
||||||
import { getMemoryForgetConfig, updateMemoryForgetConfig } from '@/api/memory'
|
import { getMemoryForgetConfig, updateMemoryForgetConfig } from '@/api/memory'
|
||||||
import type { ConfigForm } from './types'
|
import type { ConfigForm } from './types'
|
||||||
import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
|
import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
|
||||||
|
import RbSlider from '@/components/RbSlider';
|
||||||
|
import DescWrapper from '@/components/FormItem/DescWrapper'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration field definitions
|
* Configuration field definitions
|
||||||
@@ -154,16 +155,18 @@ const ForgettingEngine: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={12}>
|
||||||
<Col span={9}>
|
<Col span={12}>
|
||||||
<RbCard
|
<RbCard
|
||||||
title={
|
title={t('forgettingEngine.forgettingEngineConfigParams')}
|
||||||
<div className="rb:flex rb:items-center">
|
extra={<Space>
|
||||||
<img src={strategyImpactSimulator} className="rb:w-5 rb:h-5 rb:mr-2" />
|
<Button block onClick={handleReset}>{t('common.reset')}</Button>
|
||||||
{t('forgettingEngine.forgettingEngineConfigParams')}
|
<Button type="primary" loading={loading} block onClick={handleSave}>{t('common.save')}</Button>
|
||||||
</div>
|
</Space>}
|
||||||
}
|
headerType="borderless"
|
||||||
className='rb:h-full!'
|
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||||
|
className="rb:h-[calc(100vh-76px)]!"
|
||||||
|
bodyClassName="rb:h-[calc(100%-54px)] rb:overflow-y-auto! rb:p-3! rb:pt-0!"
|
||||||
>
|
>
|
||||||
<Form
|
<Form
|
||||||
form={form}
|
form={form}
|
||||||
@@ -174,7 +177,7 @@ const ForgettingEngine: React.FC = () => {
|
|||||||
lambda_mem: 0.03,
|
lambda_mem: 0.03,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Space size={24} direction="vertical" style={{ width: '100%' }}>
|
<Flex vertical gap={12}>
|
||||||
{configList.map(config => {
|
{configList.map(config => {
|
||||||
if (config.type === 'button') {
|
if (config.type === 'button') {
|
||||||
return (
|
return (
|
||||||
@@ -182,51 +185,53 @@ const ForgettingEngine: React.FC = () => {
|
|||||||
title={t(`forgettingEngine.${config.key}`)}
|
title={t(`forgettingEngine.${config.key}`)}
|
||||||
name={config.name}
|
name={config.name}
|
||||||
desc={config.type && <span>{t(`forgettingEngine.type`)}: {config.type}</span>}
|
desc={config.type && <span>{t(`forgettingEngine.type`)}: {config.type}</span>}
|
||||||
className="rb:mb-2"
|
className="rb:bg-[#F6F6F6] rb:rounded-xl rb:p-3!"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div key={config.key}>
|
<div key={config.key} className="rb:bg-[#F6F6F6] rb:rounded-xl rb:p-3">
|
||||||
<div className="rb:text-[14px] rb:font-medium rb:leading-5 rb:mb-2">
|
<Flex align="center" gap={4} className="rb:text-[14px] rb:font-medium rb:leading-5 rb:mb-2">
|
||||||
{t(`forgettingEngine.${config.key}`)}
|
{t(`forgettingEngine.${config.key}`)}
|
||||||
</div>
|
{!config.hiddenDesc && <Tooltip title={t(`forgettingEngine.${config.key}Desc`)}>
|
||||||
{!config.hiddenDesc && <div className="rb:mt-1 rb:text-[12px] rb:text-[#5B6167] rb:font-regular rb:leading-4 ">
|
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/question.svg')]"></div>
|
||||||
{t(`forgettingEngine.${config.key}Desc`)}
|
</Tooltip>}
|
||||||
</div>}
|
</Flex>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={config.name}
|
name={config.name}
|
||||||
|
extra={<DescWrapper
|
||||||
|
desc={<>
|
||||||
|
<span className="rb:text-[12px]">{t(`forgettingEngine.range`)}: {config.range?.join('-')}</span> | <span>{t(`forgettingEngine.type`)}: {config.type}</span>
|
||||||
|
</>}
|
||||||
|
/>}
|
||||||
|
className="rb:mb-0!"
|
||||||
>
|
>
|
||||||
{config.type === 'decimal'
|
{config.type === 'decimal'
|
||||||
? <Slider tooltip={{ open: false }} max={config.range?.[1] || 1} min={config.range?.[0] || 0} step={config.step ?? 0.01} style={{ margin: '0' }} />
|
? <RbSlider
|
||||||
|
max={config.range?.[1] || 1}
|
||||||
|
min={config.range?.[0] || 0}
|
||||||
|
step={config.step ?? 0.01}
|
||||||
|
isInput={true}
|
||||||
|
prefix={<span className="rb:text-[#5B6167]">{t('emotionEngine.currentValue')}:</span>}
|
||||||
|
inputClassName="rb:w-[155px]!"
|
||||||
|
/>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<div className="rb:flex rb:text-[12px] rb:items-center rb:justify-between rb:text-[#5B6167] rb:leading-5 rb:-mt-6.5">
|
|
||||||
<Space size={4}>
|
|
||||||
{config.range && <span>{t(`forgettingEngine.range`)}: {config.range?.join('-')}</span>}
|
|
||||||
{config.type && <span>{t(`forgettingEngine.type`)}: {config.type}</span>}
|
|
||||||
</Space>
|
|
||||||
<>{t('forgettingEngine.CurrentValue')}: {values?.[config.name] || 0}</>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
<Row gutter={16}>
|
</Flex>
|
||||||
<Col span={12}>
|
|
||||||
<Button block onClick={handleReset}>{t('common.reset')}</Button>
|
|
||||||
</Col>
|
|
||||||
<Col span={12}>
|
|
||||||
<Button type="primary" loading={loading} block onClick={handleSave}>{t('common.save')}</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Space>
|
|
||||||
</Form>
|
</Form>
|
||||||
</RbCard>
|
</RbCard>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={15}>
|
<Col span={12}>
|
||||||
<RbCard
|
<RbCard
|
||||||
|
title={t('forgettingEngine.forgettingCurve')}
|
||||||
|
headerType="borderless"
|
||||||
|
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||||
|
bodyClassName="rb:p-3! rb:pt-0!"
|
||||||
>
|
>
|
||||||
<LineChart
|
<LineChart
|
||||||
config={values}
|
config={values}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 17:30:51
|
* @Date: 2026-02-03 17:30:51
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-02-03 17:30:51
|
* @Last Modified time: 2026-03-19 14:06:38
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Card Component
|
* Card Component
|
||||||
@@ -10,11 +10,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { type FC, type ReactNode } from 'react'
|
import { type FC, type ReactNode } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
import { Flex, Space, Tooltip } from 'antd';
|
||||||
|
|
||||||
import RbCard from '@/components/RbCard/Card'
|
import RbCard from '@/components/RbCard/Card'
|
||||||
import down from '@/assets/images/userMemory/down.svg'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component props
|
* Component props
|
||||||
@@ -29,6 +28,7 @@ interface CardProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
headerClassName?: string;
|
headerClassName?: string;
|
||||||
bodyClassName?: string;
|
bodyClassName?: string;
|
||||||
|
extra?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Card: FC<CardProps> = ({
|
const Card: FC<CardProps> = ({
|
||||||
@@ -41,27 +41,33 @@ const Card: FC<CardProps> = ({
|
|||||||
className,
|
className,
|
||||||
headerClassName,
|
headerClassName,
|
||||||
bodyClassName,
|
bodyClassName,
|
||||||
|
extra,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
|
||||||
return (
|
return (
|
||||||
<RbCard
|
<RbCard
|
||||||
title={title}
|
title={() => <Flex
|
||||||
subTitle={subTitle}
|
align="center"
|
||||||
headerType="borderless"
|
justify="space-between"
|
||||||
extra={type && handleExpand && (
|
className="rb:font-[MiSans-Bold] rb:font-bold rb:cursor-pointer"
|
||||||
<div
|
onClick={type && handleExpand ? () => handleExpand(type) : undefined}
|
||||||
className="rb:flex rb:items-center rb:text-[14px] rb:text-[#5B6167] rb:cursor-pointer rb:font-regular rb:leading-5"
|
>
|
||||||
onClick={() => handleExpand(type)}
|
<Space size={4}>
|
||||||
>
|
{title}
|
||||||
{expanded ? t('common.foldUp') : t('common.expanded')}
|
{subTitle && <Tooltip title={subTitle}>
|
||||||
<img src={down} className={clsx("rb:w-4 rb:h-4 rb:ml-1", {
|
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/question.svg')]"></div>
|
||||||
|
</Tooltip>}
|
||||||
|
</Space>
|
||||||
|
{handleExpand && <div
|
||||||
|
className={clsx("rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/arrow_up.svg')]", {
|
||||||
'rb:rotate-180': !expanded,
|
'rb:rotate-180': !expanded,
|
||||||
})} />
|
})}
|
||||||
</div>
|
></div>}
|
||||||
)}
|
</Flex>}
|
||||||
|
headerType="borderless"
|
||||||
className={className}
|
className={className}
|
||||||
headerClassName={headerClassName}
|
headerClassName={`rb:h-[50px]! rb:pb-[12px]! rb:pt-[16px]! rb:leading-[22px]! rb:font-[MiSans-Bold] rb:font-bold rb:text-[16px] ${headerClassName}`}
|
||||||
bodyClassName={bodyClassName}
|
bodyClassName={`rb:px-3! rb:py-0! ${expanded ? 'rb:pb-3!' : 'rb:pb-0!'} ${bodyClassName}`}
|
||||||
|
extra={extra}
|
||||||
>
|
>
|
||||||
{(expanded || !(type && handleExpand)) && children}
|
{(expanded || !(type && handleExpand)) && children}
|
||||||
</RbCard>
|
</RbCard>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 17:30:11
|
* @Date: 2026-02-03 17:30:11
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-02 11:41:12
|
* @Last Modified time: 2026-03-19 14:22:20
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Result Component
|
* Result Component
|
||||||
@@ -13,13 +13,13 @@
|
|||||||
import { type FC, useState } from 'react'
|
import { type FC, useState } from 'react'
|
||||||
import { useParams } from 'react-router-dom'
|
import { useParams } from 'react-router-dom'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Space, Button, Progress, Form, Input } from 'antd'
|
import { Space, Button, Progress, Form, Input, Flex } from 'antd'
|
||||||
import { ExclamationCircleFilled, CheckCircleFilled, ClockCircleOutlined, LoadingOutlined } from '@ant-design/icons'
|
import { ExclamationCircleFilled, LoadingOutlined } from '@ant-design/icons'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
|
import ResultCard from './ResultCard'
|
||||||
import type { AnyObject } from 'antd/es/_util/type';
|
import type { AnyObject } from 'antd/es/_util/type';
|
||||||
|
|
||||||
import Card from './Card'
|
import Card from './Card'
|
||||||
import RbCard from '@/components/RbCard/Card'
|
|
||||||
import RbAlert from '@/components/RbAlert'
|
import RbAlert from '@/components/RbAlert'
|
||||||
import type { TestResult, OntologyCoverage } from '../types'
|
import type { TestResult, OntologyCoverage } from '../types'
|
||||||
import { pilotRunMemoryExtractionConfig } from '@/api/memory'
|
import { pilotRunMemoryExtractionConfig } from '@/api/memory'
|
||||||
@@ -27,6 +27,8 @@ import { type SSEMessage } from '@/utils/stream'
|
|||||||
import Tag, { type TagProps } from '@/components/Tag'
|
import Tag, { type TagProps } from '@/components/Tag'
|
||||||
import Markdown from '@/components/Markdown'
|
import Markdown from '@/components/Markdown'
|
||||||
import { groupDataByType } from '../constant'
|
import { groupDataByType } from '../constant'
|
||||||
|
import Empty from '@/components/Empty'
|
||||||
|
import NoDataIcon from '@/assets/images/empty/noData.png'
|
||||||
|
|
||||||
/** Result metric mapping */
|
/** Result metric mapping */
|
||||||
const resultObj = {
|
const resultObj = {
|
||||||
@@ -56,7 +58,7 @@ interface ModuleItem {
|
|||||||
const tagColors: {
|
const tagColors: {
|
||||||
[key: string]: TagProps['color']
|
[key: string]: TagProps['color']
|
||||||
} = {
|
} = {
|
||||||
pending: 'default',
|
pending: 'warning',
|
||||||
processing: 'processing',
|
processing: 'processing',
|
||||||
completed: 'success',
|
completed: 'success',
|
||||||
failed: 'error'
|
failed: 'error'
|
||||||
@@ -67,29 +69,55 @@ const initObj = {
|
|||||||
status: 'pending',
|
status: 'pending',
|
||||||
result: null
|
result: null
|
||||||
}
|
}
|
||||||
|
const initialExpanded = {
|
||||||
|
text_preprocessing: false,
|
||||||
|
knowledge_extraction: false,
|
||||||
|
creating_nodes_edges: false,
|
||||||
|
deduplication: false,
|
||||||
|
dataStatistics: false,
|
||||||
|
entityDeduplicationImpact: false,
|
||||||
|
disambiguation: false,
|
||||||
|
coreEntities: false,
|
||||||
|
triplet_samples: false,
|
||||||
|
ontologyCoverage: false,
|
||||||
|
}
|
||||||
|
|
||||||
const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
const [runLoading, setRunLoading] = useState(false)
|
const [runLoading, setRunLoading] = useState(false)
|
||||||
|
const [activeTab, setActiveTab] = useState('processData')
|
||||||
const [testResult, setTestResult] = useState<TestResult>({} as TestResult)
|
const [testResult, setTestResult] = useState<TestResult>({} as TestResult)
|
||||||
|
const [coreEntitiesTab, setCoreEntitiesTab] = useState<string | null>(null)
|
||||||
const [textPreprocessing, setTextPreprocessing] = useState<ModuleItem>(initObj as ModuleItem)
|
const [textPreprocessing, setTextPreprocessing] = useState<ModuleItem>(initObj as ModuleItem)
|
||||||
|
const [textPreprocessingTab, setTextPreprocessingTab] = useState('chunking')
|
||||||
const [knowledgeExtraction, setKnowledgeExtraction] = useState<ModuleItem>(initObj as ModuleItem)
|
const [knowledgeExtraction, setKnowledgeExtraction] = useState<ModuleItem>(initObj as ModuleItem)
|
||||||
const [creatingNodesEdges, setCreatingNodesEdges] = useState<ModuleItem>(initObj as ModuleItem)
|
const [creatingNodesEdges, setCreatingNodesEdges] = useState<ModuleItem>(initObj as ModuleItem)
|
||||||
const [deduplication, setDeduplication] = useState<ModuleItem>(initObj as ModuleItem)
|
const [deduplication, setDeduplication] = useState<ModuleItem>(initObj as ModuleItem)
|
||||||
const [ontologyCoverage, setOntologyCoverage] = useState<OntologyCoverage>({} as OntologyCoverage)
|
const [ontologyCoverage, setOntologyCoverage] = useState<OntologyCoverage>({} as OntologyCoverage)
|
||||||
|
|
||||||
|
const [expandedCards, setExpandedCards] = useState<Record<string, boolean>>(initialExpanded)
|
||||||
|
const toggleCard = (key: string) => {
|
||||||
|
console.log('toggleCard', key)
|
||||||
|
setExpandedCards(prev => ({ ...prev, [key]: !prev[key] }))
|
||||||
|
}
|
||||||
|
console.log('expandedCards', expandedCards)
|
||||||
|
|
||||||
const [runForm] = Form.useForm()
|
const [runForm] = Form.useForm()
|
||||||
|
const customText = Form.useWatch(['custom_text'], runForm)
|
||||||
|
|
||||||
/** Run pilot test */
|
/** Run pilot test */
|
||||||
const handleRun = () => {
|
const handleRun = () => {
|
||||||
if(!id) return
|
if(!id) return
|
||||||
|
setActiveTab('processData')
|
||||||
|
setCoreEntitiesTab(null)
|
||||||
setTextPreprocessing({...initObj} as ModuleItem)
|
setTextPreprocessing({...initObj} as ModuleItem)
|
||||||
|
setTextPreprocessingTab('chunking')
|
||||||
setKnowledgeExtraction({...initObj} as ModuleItem)
|
setKnowledgeExtraction({...initObj} as ModuleItem)
|
||||||
setCreatingNodesEdges({...initObj} as ModuleItem)
|
setCreatingNodesEdges({...initObj} as ModuleItem)
|
||||||
setDeduplication({...initObj} as ModuleItem)
|
setDeduplication({...initObj} as ModuleItem)
|
||||||
setTestResult({} as TestResult)
|
setTestResult({} as TestResult)
|
||||||
|
setExpandedCards(initialExpanded)
|
||||||
const handleStreamMessage = (list: SSEMessage[]) => {
|
const handleStreamMessage = (list: SSEMessage[]) => {
|
||||||
|
|
||||||
list.forEach((data: AnyObject) => {
|
list.forEach((data: AnyObject) => {
|
||||||
@@ -100,6 +128,7 @@ const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
|||||||
status: 'processing',
|
status: 'processing',
|
||||||
start_at: data.data.time
|
start_at: data.data.time
|
||||||
}))
|
}))
|
||||||
|
toggleCard('text_preprocessing')
|
||||||
break
|
break
|
||||||
case 'text_preprocessing_result': // Text preprocessing in progress
|
case 'text_preprocessing_result': // Text preprocessing in progress
|
||||||
setTextPreprocessing(prev => ({
|
setTextPreprocessing(prev => ({
|
||||||
@@ -121,6 +150,7 @@ const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
|||||||
status: 'processing',
|
status: 'processing',
|
||||||
start_at: data.data.time
|
start_at: data.data.time
|
||||||
}))
|
}))
|
||||||
|
toggleCard('knowledge_extraction')
|
||||||
break
|
break
|
||||||
case 'knowledge_extraction_result': // Knowledge extraction in progress
|
case 'knowledge_extraction_result': // Knowledge extraction in progress
|
||||||
setKnowledgeExtraction(prev => ({
|
setKnowledgeExtraction(prev => ({
|
||||||
@@ -142,6 +172,7 @@ const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
|||||||
status: 'processing',
|
status: 'processing',
|
||||||
start_at: data.data.time
|
start_at: data.data.time
|
||||||
}))
|
}))
|
||||||
|
toggleCard('creating_nodes_edges')
|
||||||
break
|
break
|
||||||
case 'creating_nodes_edges_result': // Creating nodes and edges in progress
|
case 'creating_nodes_edges_result': // Creating nodes and edges in progress
|
||||||
setCreatingNodesEdges(prev => ({
|
setCreatingNodesEdges(prev => ({
|
||||||
@@ -163,6 +194,7 @@ const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
|||||||
status: 'processing',
|
status: 'processing',
|
||||||
start_at: data.data.time
|
start_at: data.data.time
|
||||||
}))
|
}))
|
||||||
|
toggleCard('deduplication')
|
||||||
break
|
break
|
||||||
case 'dedup_disambiguation_result': // Deduplication and disambiguation in progress
|
case 'dedup_disambiguation_result': // Deduplication and disambiguation in progress
|
||||||
setDeduplication(prev => ({
|
setDeduplication(prev => ({
|
||||||
@@ -183,6 +215,15 @@ const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
|||||||
case 'result': // Result
|
case 'result': // Result
|
||||||
setTestResult(data.data?.extracted_result)
|
setTestResult(data.data?.extracted_result)
|
||||||
setOntologyCoverage(data.data?.ontology_coverage)
|
setOntologyCoverage(data.data?.ontology_coverage)
|
||||||
|
setExpandedCards(prev => ({
|
||||||
|
...prev,
|
||||||
|
dataStatistics: true,
|
||||||
|
entityDeduplicationImpact: true,
|
||||||
|
disambiguation: true,
|
||||||
|
coreEntities: true,
|
||||||
|
triplet_samples: true,
|
||||||
|
ontologyCoverage: true,
|
||||||
|
}))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -203,9 +244,10 @@ const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
|||||||
/** Format status tag */
|
/** Format status tag */
|
||||||
const formatTag = (status: string) => {
|
const formatTag = (status: string) => {
|
||||||
return (
|
return (
|
||||||
<Tag color={tagColors[status]}>
|
<Tag color={tagColors[status]} className="rb:flex! rb:items-center rb:gap-1 rb:bg-white! rb:border-white!">
|
||||||
{status === 'pending' && <ClockCircleOutlined className="rb:mr-1" />}
|
{status === 'pending' && <div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/memory/clock_orange.svg')]"></div>}
|
||||||
{status === 'processing' && <LoadingOutlined spin className="rb:mr-1" />}
|
{status === 'processing' && <LoadingOutlined spin className="rb:mr-1" />}
|
||||||
|
{status === 'completed' && <div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/check_green.svg')]"></div>}
|
||||||
{t(`memoryExtractionEngine.status.${status}`)}
|
{t(`memoryExtractionEngine.status.${status}`)}
|
||||||
</Tag>
|
</Tag>
|
||||||
)
|
)
|
||||||
@@ -213,294 +255,411 @@ const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
|||||||
/** Format processing time */
|
/** Format processing time */
|
||||||
const formatTime = (data: ModuleItem, color?: string) => {
|
const formatTime = (data: ModuleItem, color?: string) => {
|
||||||
if (typeof data.end_at === 'number' && typeof data.start_at === 'number') {
|
if (typeof data.end_at === 'number' && typeof data.start_at === 'number') {
|
||||||
return <div className={`rb:mt-3 rb:text-[${color ?? '#155EEF'}]`}>{t('memoryExtractionEngine.time')}{data.end_at - data.start_at}ms</div>
|
return <div className={`rb:text-[${color ?? '#155EEF'}] rb:mb-0.5`}>{t('memoryExtractionEngine.time')}{data.end_at - data.start_at}ms</div>
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
/** Convert first character to lowercase */
|
/** Convert first character to lowercase */
|
||||||
const lowercaseFirst = (str: string) => str.charAt(0).toLowerCase() + str.slice(1)
|
const lowercaseFirst = (str: string) => str.charAt(0).toLowerCase() + str.slice(1)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
title={t('memoryExtractionEngine.exampleMemoryExtractionResults')}
|
title={t('memoryExtractionEngine.exampleMemoryExtractionResults')}
|
||||||
subTitle={t('memoryExtractionEngine.exampleMemoryExtractionResultsSubTitle')}
|
subTitle={t('memoryExtractionEngine.exampleMemoryExtractionResultsSubTitle')}
|
||||||
className="rb:min-h-[calc(100vh-330px)]!"
|
|
||||||
headerClassName="rb:pb-0! rb:pt-4!"
|
headerClassName="rb:pb-0! rb:pt-4!"
|
||||||
bodyClassName="rb:min-h-[calc(100vh-388px)] rb:p-[16px_20px]!"
|
bodyClassName="rb:h-[calc(100vh-163px)]! rb:overflow-y-auto rb:p-[16px_20px]!"
|
||||||
|
extra={<Space size={8}>
|
||||||
|
<Button
|
||||||
|
icon={<div className="rb:size-3.5 rb:bg-cover rb:bg-[url('@/assets/images/common/save.svg')]"></div>}
|
||||||
|
loading={loading}
|
||||||
|
onClick={handleSave}
|
||||||
|
>{t('common.save')}</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<div className="rb:size-3.5 rb:bg-cover rb:bg-[url('@/assets/images/memory/debug.svg')]"></div>}
|
||||||
|
loading={runLoading}
|
||||||
|
onClick={handleRun}
|
||||||
|
>{t('memoryExtractionEngine.debug')}</Button>
|
||||||
|
</Space>}
|
||||||
>
|
>
|
||||||
<Form form={runForm} layout="vertical">
|
{/* <RbAlert color="orange" icon={<ExclamationCircleFilled />} className="rb:mb-3!">
|
||||||
|
{t('memoryExtractionEngine.warning')}
|
||||||
|
</RbAlert> */}
|
||||||
|
<Form form={runForm} layout="vertical" className="rb:bg-[#F6F6F6]! rb:rounded-xl rb:py-2! rb:mb-4!">
|
||||||
|
<Flex align="center" justify="space-between" className="rb:px-3! rb:mb-2!">
|
||||||
|
<div className="rb:text-[#212332] rb:font-medium rb:leading-5">{t('memoryExtractionEngine.custom_text')}</div>
|
||||||
|
<div className="rb:text-[12px] rb:text-[#5B6167] rb:leading-4.5">{customText?.length || 0}</div>
|
||||||
|
</Flex>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="custom_text"
|
name="custom_text"
|
||||||
label={t('memoryExtractionEngine.custom_text')}
|
label={t('memoryExtractionEngine.custom_text')}
|
||||||
|
noStyle
|
||||||
>
|
>
|
||||||
<Input.TextArea placeholder={t('common.pleaseEnter')} />
|
<Input.TextArea placeholder={t('common.pleaseEnter')} variant="borderless" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
<div className="rb:min-h-[calc(100vh-480px)] rb:overflow-y-auto">
|
|
||||||
{runLoading
|
{runLoading
|
||||||
? <>
|
? <>
|
||||||
<RbAlert color="blue" icon={<ExclamationCircleFilled />} className="rb:mb-3.5">
|
<RbAlert color="blue">
|
||||||
|
<div className="rb:w-full">
|
||||||
{t('memoryExtractionEngine.processing')}
|
{t('memoryExtractionEngine.processing')}
|
||||||
</RbAlert>
|
|
||||||
{/* Overall Progress */}
|
{/* Overall Progress */}
|
||||||
<div className="rb:mb-2">
|
<Flex gap={13} align="center">
|
||||||
<div className="rb:flex rb:items-center rb:justify-between rb:text-[12px] rb:leading-4 rb:font-regular">
|
<Progress percent={completedNum * 100 / 4} showInfo={false} className="rb:flex-1!" />
|
||||||
{t('memoryExtractionEngine.overallProgress')}
|
<div className="rb:text-[12px] rb:leading-4 rb:font-regular">
|
||||||
<span className="rb:text-[#155eef]">{`${completedNum}/4`}</span>
|
{t('memoryExtractionEngine.overallProgress')}{`${(completedNum*100/4).toFixed(0)}%`}
|
||||||
</div>
|
</div>
|
||||||
<Progress percent={completedNum * 100/4} showInfo={false} />
|
</Flex>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</RbAlert>
|
||||||
: !testResult || Object.keys(testResult).length === 0
|
</>
|
||||||
? <RbAlert color="orange" icon={<ExclamationCircleFilled />} className="rb:mb-3.5">
|
: !testResult || Object.keys(testResult).length === 0
|
||||||
{t('memoryExtractionEngine.warning')}
|
? <RbAlert color="orange" icon={<ExclamationCircleFilled />}>
|
||||||
</RbAlert>
|
{t('memoryExtractionEngine.warning')}
|
||||||
: <RbAlert color="green" icon={<ExclamationCircleFilled />} className="rb:mb-3.5">
|
</RbAlert>
|
||||||
{t('memoryExtractionEngine.success')}
|
: <RbAlert color="green" icon={<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/check_green.svg')]"></div>}>
|
||||||
</RbAlert>
|
{t('memoryExtractionEngine.success')}
|
||||||
}
|
</RbAlert>
|
||||||
<Space size={16} direction="vertical" style={{ width: '100%' }}>
|
}
|
||||||
{/* Text Preprocessing */}
|
|
||||||
<RbCard
|
<Space size={24} className="rb:mt-4! rb:mb-3!">
|
||||||
title={t(`memoryExtractionEngine.text_preprocessing`)}
|
{['processData', 'finalResult'].map(tab => (
|
||||||
extra={formatTag(textPreprocessing.status)}
|
<div
|
||||||
headerType="borderL"
|
className={clsx('rb:font-[MiSans-Bold] rb:font-bold rb:leading-5 rb:cursor-pointer', {
|
||||||
headerClassName="rb:before:bg-[#155EEF]!"
|
'rb:text-[#212332]': activeTab === tab,
|
||||||
>
|
'rb:text-[#A8A9AA]': activeTab !== tab,
|
||||||
{textPreprocessing.data.map((vo, index) => {
|
|
||||||
if (vo.deleted_messages) {
|
|
||||||
return <div key={index} className="rb:mb-3 rb:pb-1 rb:border-b rb:border-b-[#EBEBEB]">
|
|
||||||
<div className="rb:font-medium rb:text-[12px] rb:mb-2">{t('memoryExtractionEngine.Pruned')}</div>
|
|
||||||
{vo.deleted_messages.map((msg: any, idx: number) => (
|
|
||||||
<div key={idx} className="rb:text-[12px] rb:text-[#5B6167] rb:leading-4 rb:font-regular">
|
|
||||||
<Markdown content={'-' + t('memoryExtractionEngine.pruning') + (idx + 1) + ': ' + msg.content} />
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div key={index} className="rb:mb-3 rb:text-[12px] rb:text-[#5B6167] rb:leading-4 rb:font-regular">
|
|
||||||
<Markdown content={'-' + t('memoryExtractionEngine.fragment') + vo.chunk_index + ': ' + (vo.content.startsWith('\n') ? vo.content : '\n' + vo.content)} />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
})}
|
||||||
{formatTime(textPreprocessing)}
|
onClick={() => setActiveTab(tab)}
|
||||||
{textPreprocessing.result &&
|
>{t(`memoryExtractionEngine.${tab}`)}</div>
|
||||||
<RbAlert color="blue" icon={<CheckCircleFilled />} className="rb:mt-3">
|
))}
|
||||||
|
</Space>
|
||||||
|
|
||||||
|
{activeTab === 'processData' && <Flex vertical gap={12} className="rb:pb-3!">
|
||||||
|
{/* Text Preprocessing */}
|
||||||
|
<ResultCard
|
||||||
|
title={t(`memoryExtractionEngine.text_preprocessing`)}
|
||||||
|
extra={formatTag(textPreprocessing.status)}
|
||||||
|
expanded={expandedCards['text_preprocessing']}
|
||||||
|
handleExpand={() => toggleCard('text_preprocessing')}
|
||||||
|
>
|
||||||
|
{expandedCards['text_preprocessing'] && textPreprocessing.data?.length > 0 &&
|
||||||
|
<Space size={10} className="rb:px-1! rb:mb-3!">
|
||||||
|
{(['chunking', ...(textPreprocessing.data.some(vo => vo.deleted_messages) ? ['pruning'] : [])] as string[]).map(type => (
|
||||||
|
<div
|
||||||
|
key={type}
|
||||||
|
className={clsx("rb:rounded-[13px] rb:py-0.5 rb:px-3 rb:leading-5 rb:cursor-pointer", {
|
||||||
|
'rb:bg-white': textPreprocessingTab !== type,
|
||||||
|
'rb:bg-[#171719] rb:text-white': textPreprocessingTab === type
|
||||||
|
})}
|
||||||
|
onClick={() => setTextPreprocessingTab(type)}
|
||||||
|
>
|
||||||
|
{t(`memoryExtractionEngine.${type}`)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
{expandedCards['text_preprocessing'] && textPreprocessing.result &&
|
||||||
|
<RbAlert color="blue" className="rb:mb-2!">
|
||||||
|
<div>
|
||||||
|
<div>{formatTime(textPreprocessing)}</div>
|
||||||
{t('memoryExtractionEngine.pruning_desc', { count: textPreprocessing.result.pruning.deleted_count || 0 })},
|
{t('memoryExtractionEngine.pruning_desc', { count: textPreprocessing.result.pruning.deleted_count || 0 })},
|
||||||
{t('memoryExtractionEngine.text_preprocessing_desc', { count: textPreprocessing.result.total_chunks })},
|
{t('memoryExtractionEngine.text_preprocessing_desc', { count: textPreprocessing.result.total_chunks })},
|
||||||
{t('memoryExtractionEngine.chunkerStrategy')}: {t(`memoryExtractionEngine.${lowercaseFirst(textPreprocessing.result.chunker_strategy)}`)}
|
{t('memoryExtractionEngine.chunkerStrategy')}: {t(`memoryExtractionEngine.${lowercaseFirst(textPreprocessing.result.chunker_strategy)}`)}
|
||||||
</RbAlert>
|
|
||||||
}
|
|
||||||
</RbCard>
|
|
||||||
{/* Knowledge Extraction */}
|
|
||||||
<RbCard
|
|
||||||
title={t(`memoryExtractionEngine.knowledge_extraction`)}
|
|
||||||
extra={formatTag(knowledgeExtraction.status)}
|
|
||||||
headerType="borderL"
|
|
||||||
headerClassName="rb:before:bg-[#155EEF]!"
|
|
||||||
>
|
|
||||||
{knowledgeExtraction.data.map((vo, index) =>
|
|
||||||
<div key={index} className="rb:mb-3 rb:text-[12px] rb:text-[#5B6167] rb:leading-4 rb:font-regular">{vo.statement}</div>
|
|
||||||
)}
|
|
||||||
{formatTime(knowledgeExtraction)}
|
|
||||||
{knowledgeExtraction.result && <RbAlert color="blue" icon={<CheckCircleFilled />} className="rb:mt-3">
|
|
||||||
{t('memoryExtractionEngine.knowledge_extraction_desc', {
|
|
||||||
entities: knowledgeExtraction.result.entities_count,
|
|
||||||
statements: knowledgeExtraction.result.statements_count,
|
|
||||||
temporal_ranges_count: knowledgeExtraction.result.temporal_ranges_count,
|
|
||||||
triplets: knowledgeExtraction.result.triplets_count
|
|
||||||
})}
|
|
||||||
</RbAlert>}
|
|
||||||
</RbCard>
|
|
||||||
{/* Creating Entity Relationships */}
|
|
||||||
<RbCard
|
|
||||||
title={t(`memoryExtractionEngine.creating_nodes_edges`)}
|
|
||||||
extra={formatTag(creatingNodesEdges.status)}
|
|
||||||
headerType="borderL"
|
|
||||||
headerClassName="rb:before:bg-[#9C6FFF]!"
|
|
||||||
>
|
|
||||||
{creatingNodesEdges.data?.map((vo, index) => (
|
|
||||||
<div key={index} className="rb:mb-3 rb:text-[12px] rb:text-[#5B6167] rb:leading-4 rb:font-regular">
|
|
||||||
{vo?.result_type === 'entity_nodes_creation'
|
|
||||||
? <>{vo.type_display_name}: {vo.entity_names.join(', ')}</>
|
|
||||||
: <>{vo?.relationship_text}</>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
</RbAlert>
|
||||||
{formatTime(creatingNodesEdges, '#9C6FFF')}
|
|
||||||
{creatingNodesEdges.result && <RbAlert color="blue" icon={<CheckCircleFilled />} className="rb:mt-3">
|
|
||||||
{t('memoryExtractionEngine.creating_nodes_edges_desc', {num: creatingNodesEdges.result.entity_entity_edges_count})}
|
|
||||||
</RbAlert>}
|
|
||||||
</RbCard>
|
|
||||||
{/* Deduplication and Disambiguation */}
|
|
||||||
<RbCard
|
|
||||||
title={t(`memoryExtractionEngine.deduplication`)}
|
|
||||||
extra={formatTag(deduplication.status)}
|
|
||||||
headerType="borderL"
|
|
||||||
headerClassName="rb:before:bg-[#9C6FFF]!"
|
|
||||||
>
|
|
||||||
{Object.keys(deduplicationData).length > 0 && Object.keys(deduplicationData).map(key => {
|
|
||||||
return deduplicationData[key].map((vo, index) => (
|
|
||||||
<div key={index} className="rb:mb-3 rb:text-[12px] rb:text-[#5B6167] rb:leading-4 rb:font-regular">
|
|
||||||
{vo.message}
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
})}
|
|
||||||
{formatTime(deduplication, '#9C6FFF')}
|
|
||||||
{deduplication.result && <RbAlert color="blue" icon={<CheckCircleFilled />} className="rb:mt-3">
|
|
||||||
{t('memoryExtractionEngine.deduplication_desc', { count: deduplication.result.summary.total_merges })}<br />
|
|
||||||
</RbAlert>}
|
|
||||||
</RbCard>
|
|
||||||
|
|
||||||
{testResult && Object.keys(testResult).length > 0 && resultObj && Object.keys(resultObj).length > 0 &&
|
|
||||||
<RbCard>
|
|
||||||
<div className="rb:grid rb:grid-cols-2 rb:gap-[40px_57px]">
|
|
||||||
{Object.keys(resultObj).map((key, index) => {
|
|
||||||
const keys = (resultObj as Record<string, string>)[key].split('.')
|
|
||||||
return (
|
|
||||||
<div key={index}>
|
|
||||||
<div className="rb:text-[24px] rb:leading-7.5 rb:font-extrabold">{(testResult?.[keys[0] as keyof TestResult] as any)?.[keys[1]]}</div>
|
|
||||||
<div className="rb:text-[12px] rb:text-[#5B6167] rb:leading-4 rb:font-regular">{t(`memoryExtractionEngine.${key}`)}</div>
|
|
||||||
<div className="rb:mt-1 rb:text-[12px] rb:text-[#369F21] rb:leading-3.5 rb:font-regular">
|
|
||||||
{key === 'extractTheNumberOfEntities' && testResult.dedup
|
|
||||||
? t(`memoryExtractionEngine.${key}Desc`, {
|
|
||||||
num: testResult.dedup.total_merged_count,
|
|
||||||
exact: testResult.dedup.breakdown.exact,
|
|
||||||
fuzzy: testResult.dedup.breakdown.fuzzy,
|
|
||||||
llm: testResult.dedup.breakdown.llm,
|
|
||||||
})
|
|
||||||
: key === 'numberOfEntityDisambiguation' && testResult.disambiguation
|
|
||||||
? t(`memoryExtractionEngine.${key}Desc`, { num: testResult.disambiguation.effects?.length, block_count: testResult.disambiguation.block_count })
|
|
||||||
: key === 'numberOfRelationalTriples' && testResult.triplets
|
|
||||||
? t(`memoryExtractionEngine.${key}Desc`, { num: testResult.triplets.count })
|
|
||||||
:t(`memoryExtractionEngine.${key}Desc`)
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)})}
|
|
||||||
</div>
|
|
||||||
</RbCard>
|
|
||||||
}
|
}
|
||||||
|
{expandedCards['text_preprocessing'] && textPreprocessing.data.map((vo, index) => {
|
||||||
{testResult?.dedup?.impact && testResult.dedup.impact?.length > 0 &&
|
if (vo.deleted_messages && textPreprocessingTab === 'pruning') {
|
||||||
<RbCard
|
return <div key={index} className="rb:mb-3 rb:pb-1 rb:border-b rb:border-b-[#EBEBEB]">
|
||||||
title={t('memoryExtractionEngine.entityDeduplicationImpact')}
|
<div className="rb:font-medium rb:text-[12px] rb:mb-2">{t('memoryExtractionEngine.Pruned')}</div>
|
||||||
headerType="borderL"
|
{vo.deleted_messages.map((msg: any, idx: number) => (
|
||||||
headerClassName="rb:before:bg-[#155EEF]!"
|
<div key={idx} className="rb:leading-5">
|
||||||
>
|
<div className="rb:font-medium">-{t('memoryExtractionEngine.pruning')}{idx}:</div>
|
||||||
<div className="rb:text-[12px] rb:text-[#5B6167] rb:font-medium rb:leading-4">{t('memoryExtractionEngine.identifyDuplicates')}</div>
|
<Markdown content={msg.content} />
|
||||||
{testResult.dedup.impact.map((item, index) => (
|
</div>
|
||||||
<div key={index} className="rb:pl-2 rb:mt-2 rb:text-[12px] rb:text-[#5B6167] rb:font-regular rb:leading-4">
|
))}
|
||||||
-{t('memoryExtractionEngine.identifyDuplicatesDesc', { ...item })}
|
</div>
|
||||||
|
}
|
||||||
|
if (textPreprocessingTab === 'chunking') {
|
||||||
|
return (
|
||||||
|
<div key={index} className="rb:leading-5">
|
||||||
|
<div className="rb:font-medium">-{t('memoryExtractionEngine.fragment')}{vo.chunk_index}:</div>
|
||||||
|
<Markdown content={vo.content.startsWith('\n') ? vo.content : '\n' + vo.content} className="rb:text-[#212332]" />
|
||||||
</div>
|
</div>
|
||||||
))}
|
)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
})}
|
||||||
|
</ResultCard>
|
||||||
|
{/* Knowledge Extraction */}
|
||||||
|
<ResultCard
|
||||||
|
title={t(`memoryExtractionEngine.knowledge_extraction`)}
|
||||||
|
extra={formatTag(knowledgeExtraction.status)}
|
||||||
|
expanded={expandedCards['knowledge_extraction']}
|
||||||
|
handleExpand={() => toggleCard('knowledge_extraction')}
|
||||||
|
>
|
||||||
|
{knowledgeExtraction.result &&
|
||||||
|
<RbAlert color="blue" className="rb:mb-2!">
|
||||||
|
<div>
|
||||||
|
<div>{formatTime(knowledgeExtraction)}</div>
|
||||||
|
{t('memoryExtractionEngine.knowledge_extraction_desc', {
|
||||||
|
entities: knowledgeExtraction.result.entities_count,
|
||||||
|
statements: knowledgeExtraction.result.statements_count,
|
||||||
|
temporal_ranges_count: knowledgeExtraction.result.temporal_ranges_count,
|
||||||
|
triplets: knowledgeExtraction.result.triplets_count
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</RbAlert>
|
||||||
|
}
|
||||||
|
{knowledgeExtraction.data?.length > 0 &&
|
||||||
|
<ul className="rb:list-disc rb:ml-4 rb:mb-3">
|
||||||
|
{knowledgeExtraction.data.map((vo, index) =>
|
||||||
|
<li key={index} className="rb:leading-6">{vo.statement}</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
</ResultCard>
|
||||||
|
{/* Creating Entity Relationships */}
|
||||||
|
<ResultCard
|
||||||
|
title={t(`memoryExtractionEngine.creating_nodes_edges`)}
|
||||||
|
extra={formatTag(creatingNodesEdges.status)}
|
||||||
|
expanded={expandedCards['creating_nodes_edges']}
|
||||||
|
handleExpand={() => toggleCard('creating_nodes_edges')}
|
||||||
|
>
|
||||||
|
{creatingNodesEdges.result &&
|
||||||
|
<RbAlert color="blue" className="rb:mb-2!">
|
||||||
|
<div>
|
||||||
|
<div>{formatTime(creatingNodesEdges)}</div>
|
||||||
|
{t('memoryExtractionEngine.creating_nodes_edges_desc', { num: creatingNodesEdges.result.entity_entity_edges_count })}
|
||||||
|
</div>
|
||||||
|
</RbAlert>
|
||||||
|
}
|
||||||
|
{creatingNodesEdges.data?.length > 0 &&
|
||||||
|
<ul className="rb:list-disc rb:ml-4 rb:mb-3">
|
||||||
|
{creatingNodesEdges.data.map((vo, index) =>
|
||||||
|
<li key={index} className="rb:leading-6">
|
||||||
|
{vo?.result_type === 'entity_nodes_creation'
|
||||||
|
? <>{vo.type_display_name}: {vo.entity_names.join(', ')}</>
|
||||||
|
: <>{vo?.relationship_text}</>
|
||||||
|
}
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
</ResultCard>
|
||||||
|
{/* Deduplication and Disambiguation */}
|
||||||
|
<ResultCard
|
||||||
|
title={t(`memoryExtractionEngine.deduplication`)}
|
||||||
|
extra={formatTag(deduplication.status)}
|
||||||
|
expanded={expandedCards['deduplication']}
|
||||||
|
handleExpand={() => toggleCard('deduplication')}
|
||||||
|
>
|
||||||
|
{deduplication.result &&
|
||||||
|
<RbAlert color="blue" className="rb:mb-2!">
|
||||||
|
<div>
|
||||||
|
<div>{formatTime(deduplication)}</div>
|
||||||
|
{t('memoryExtractionEngine.deduplication_desc', { count: deduplication.result.summary.total_merges })}
|
||||||
|
</div>
|
||||||
|
</RbAlert>
|
||||||
|
}
|
||||||
|
{Object.keys(deduplicationData).length > 0 &&
|
||||||
|
<ul className="rb:list-disc rb:ml-4 rb:mb-3">
|
||||||
|
{Object.keys(deduplicationData).map(key => {
|
||||||
|
return deduplicationData[key].map((vo, index) => (
|
||||||
|
<li key={index} className="rb:leading-6">
|
||||||
|
{vo.message}
|
||||||
|
</li>
|
||||||
|
))
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
</ResultCard>
|
||||||
|
</Flex>}
|
||||||
|
|
||||||
<RbAlert color="blue" icon={<CheckCircleFilled />} className="rb:mt-3">
|
{activeTab === 'finalResult' && <Flex vertical gap={12} className="rb:pb-3!">
|
||||||
|
{!testResult || Object.keys(testResult).length === 0
|
||||||
|
? <Empty url={NoDataIcon} />
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
|
||||||
|
{testResult && Object.keys(testResult).length > 0 && resultObj && Object.keys(resultObj).length > 0 &&
|
||||||
|
<ResultCard
|
||||||
|
title={t(`memoryExtractionEngine.dataStatistics`)}
|
||||||
|
expanded={expandedCards['dataStatistics']}
|
||||||
|
handleExpand={() => toggleCard('dataStatistics')}
|
||||||
|
>
|
||||||
|
<div className="rb:grid rb:grid-cols-2 rb:gap-2.5 rb:mb-3">
|
||||||
|
{Object.keys(resultObj).map((key, index) => {
|
||||||
|
const keys = (resultObj as Record<string, string>)[key].split('.')
|
||||||
|
return (
|
||||||
|
<div key={index} className="rb:bg-white rb:rounded-lg rb:py-2 rb:px-3">
|
||||||
|
<div className="rb:text-[24px] rb:leading-8 rb:font-bold rb:font-[MiSans-Bold] rb:mb-1">{(testResult?.[keys[0] as keyof TestResult] as any)?.[keys[1]]}</div>
|
||||||
|
<div className="rb:text-[12px] rb:leading-4 rb:mb-0.5">{t(`memoryExtractionEngine.${key}`)}</div>
|
||||||
|
<div className="rb:text-[12px] rb:text-[#369F21] rb:leading-4">
|
||||||
|
{key === 'extractTheNumberOfEntities' && testResult.dedup
|
||||||
|
? t(`memoryExtractionEngine.${key}Desc`, {
|
||||||
|
num: testResult.dedup.total_merged_count,
|
||||||
|
exact: testResult.dedup.breakdown.exact,
|
||||||
|
fuzzy: testResult.dedup.breakdown.fuzzy,
|
||||||
|
llm: testResult.dedup.breakdown.llm,
|
||||||
|
})
|
||||||
|
: key === 'numberOfEntityDisambiguation' && testResult.disambiguation
|
||||||
|
? t(`memoryExtractionEngine.${key}Desc`, { num: testResult.disambiguation.effects?.length, block_count: testResult.disambiguation.block_count })
|
||||||
|
: key === 'numberOfRelationalTriples' && testResult.triplets
|
||||||
|
? t(`memoryExtractionEngine.${key}Desc`, { num: testResult.triplets.count })
|
||||||
|
: t(`memoryExtractionEngine.${key}Desc`)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</ResultCard>
|
||||||
|
}
|
||||||
|
|
||||||
|
{testResult?.dedup?.impact && testResult.dedup.impact?.length > 0 &&
|
||||||
|
<ResultCard
|
||||||
|
title={t('memoryExtractionEngine.entityDeduplicationImpact')}
|
||||||
|
expanded={expandedCards['entityDeduplicationImpact']}
|
||||||
|
handleExpand={() => toggleCard('entityDeduplicationImpact')}
|
||||||
|
>
|
||||||
|
<div className="rb:bg-white rb:rounded-xl rb:p-3 rb:mb-3">
|
||||||
|
<RbAlert color="blue" className="rb:mb-2!">
|
||||||
{t('memoryExtractionEngine.entityDeduplicationImpactDesc', { count: testResult.dedup.impact.length })}
|
{t('memoryExtractionEngine.entityDeduplicationImpactDesc', { count: testResult.dedup.impact.length })}
|
||||||
</RbAlert>
|
</RbAlert>
|
||||||
</RbCard>
|
<div className="rb:font-medium rb:leading-5 rb:mb-2">{t('memoryExtractionEngine.identifyDuplicates')}:</div>
|
||||||
}
|
|
||||||
|
|
||||||
{testResult?.disambiguation && testResult.disambiguation?.effects?.length > 0 &&
|
<ul className="rb:list-disc rb:ml-4">
|
||||||
<RbCard
|
{testResult.dedup.impact.map((item, index) => (
|
||||||
title={t('memoryExtractionEngine.theEffectOfEntityDisambiguationLLMDriven')}
|
<li key={index} className="rb:leading-6">
|
||||||
headerType="borderL"
|
{t('memoryExtractionEngine.identifyDuplicatesDesc', { ...item })}
|
||||||
headerClassName="rb:before:bg-[#155EEF]!"
|
</li>
|
||||||
>
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</ResultCard>
|
||||||
|
}
|
||||||
|
|
||||||
|
{testResult?.disambiguation && testResult.disambiguation?.effects?.length > 0 &&
|
||||||
|
<ResultCard
|
||||||
|
title={t('memoryExtractionEngine.theEffectOfEntityDisambiguationLLMDriven')}
|
||||||
|
expanded={expandedCards['disambiguation']}
|
||||||
|
handleExpand={() => toggleCard('disambiguation')}
|
||||||
|
>
|
||||||
|
<div className="rb:bg-white rb:rounded-xl rb:p-3 rb:mb-3">
|
||||||
|
<RbAlert color="blue" className="rb:mb-2!">
|
||||||
|
{t('memoryExtractionEngine.entityDeduplicationImpactDesc', { count: testResult.dedup.impact.length })}
|
||||||
|
</RbAlert>
|
||||||
{testResult.disambiguation.effects.map((item, index) => (
|
{testResult.disambiguation.effects.map((item, index) => (
|
||||||
<div key={index} className={clsx("rb:text-[12px] rb:text-[#5B6167] rb:leading-4", {
|
<div key={index} className={clsx("rb:text-[12px] rb:text-[#5B6167] rb:leading-4", {
|
||||||
'rb:mt-4': index > 0,
|
'rb:mt-5': index > 0,
|
||||||
})}>
|
})}>
|
||||||
<div className="rb:font-medium rb:mb-2">{t('memoryExtractionEngine.disagreementCase')} {index +1}:</div>
|
<div className="rb:font-medium rb:leading-5 rb:mb-1">{t('memoryExtractionEngine.disagreementCase')} {index + 1}:</div>
|
||||||
-{item.left.name}({item.left.type}) vs {item.right.name}({item.right.type}) → <span className="rb:text-[#369F21]">{item.result}</span>
|
|
||||||
|
<ul className="rb:list-disc rb:ml-4">
|
||||||
|
<li key={index} className="rb:leading-6">
|
||||||
|
{item.left.name}({item.left.type}) vs {item.right.name}({item.right.type}) → {item.result}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
</div>
|
||||||
|
</ResultCard>
|
||||||
|
}
|
||||||
|
|
||||||
<RbAlert color="blue" icon={<CheckCircleFilled />} className="rb:mt-3">
|
{testResult?.core_entities && testResult?.core_entities.length > 0 &&
|
||||||
{t('memoryExtractionEngine.entityDeduplicationImpactDesc', { count: testResult.dedup.impact.length })}
|
<ResultCard
|
||||||
</RbAlert>
|
title={t('memoryExtractionEngine.coreEntitiesAfterDedup')}
|
||||||
</RbCard>
|
expanded={expandedCards['coreEntities']}
|
||||||
}
|
handleExpand={() => toggleCard('coreEntities')}
|
||||||
|
>
|
||||||
|
<Flex gap={10} wrap className="rb:px-1! rb:mb-3! rb:gap-y-2!">
|
||||||
|
{testResult.core_entities.map((item, index) => (
|
||||||
|
<div
|
||||||
|
key={item.type}
|
||||||
|
className={clsx("rb:rounded-[13px] rb:py-0.5 rb:px-3 rb:leading-5 rb:cursor-pointer", {
|
||||||
|
'rb:bg-white': !((coreEntitiesTab && item.type === coreEntitiesTab) || (!coreEntitiesTab && index === 0)),
|
||||||
|
'rb:bg-[#171719] rb:text-white': (coreEntitiesTab && item.type === coreEntitiesTab) || (!coreEntitiesTab && index === 0)
|
||||||
|
})}
|
||||||
|
onClick={() => setCoreEntitiesTab(item.type)}
|
||||||
|
>
|
||||||
|
{item.type}({item.count})
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
<div className="rb:bg-white rb:rounded-lg rb:py-2.5 rb:px-3 rb:mb-3">
|
||||||
|
{testResult.core_entities.filter((item, index) => (coreEntitiesTab && item.type === coreEntitiesTab) || (!coreEntitiesTab && index === 0)).map((item, idx) => (
|
||||||
|
<div key={idx} className="rb:leading-5">
|
||||||
|
<div className="rb:text-[#155EEF] rb:font-medium rb:mb-2">{item.type}({item.count})</div>
|
||||||
|
|
||||||
{testResult?.core_entities && testResult?.core_entities.length > 0 &&
|
<ul className="rb:list-disc rb:ml-4">
|
||||||
<RbCard
|
{item.entities.map((entity, index) => (
|
||||||
title={t('memoryExtractionEngine.coreEntitiesAfterDedup')}
|
<li key={index} className="rb:leading-6">
|
||||||
headerType="borderL"
|
{entity}
|
||||||
headerClassName="rb:before:bg-[#369F21]!"
|
</li>
|
||||||
>
|
))}
|
||||||
<div className="rb:grid rb:grid-cols-2 rb:gap-6">
|
</ul>
|
||||||
{testResult.core_entities.map((item, idx) => (
|
</div>
|
||||||
<div key={idx} className="rb:text-[12px]">
|
))}
|
||||||
<div className="rb:text-[#369F21] rb:font-medium">{item.type}({item.count})</div>
|
</div>
|
||||||
|
</ResultCard>
|
||||||
|
}
|
||||||
|
|
||||||
<div>
|
{testResult?.triplet_samples && testResult?.triplet_samples.length > 0 &&
|
||||||
{item.entities.map((entity, index) => (
|
<ResultCard
|
||||||
<div key={index} className="rb:text-[#5B6167] rb:font-regular rb:leading-4">
|
title={t('memoryExtractionEngine.extractRelationalTriples')}
|
||||||
-{entity}
|
expanded={expandedCards['triplet_samples']}
|
||||||
</div>
|
handleExpand={() => toggleCard('triplet_samples')}
|
||||||
))}
|
>
|
||||||
</div>
|
<div className="rb:bg-white rb:rounded-xl rb:p-3 rb:mb-3">
|
||||||
</div>
|
<RbAlert color="blue"className="rb:mb-2!">
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</RbCard>
|
|
||||||
}
|
|
||||||
|
|
||||||
{testResult?.triplet_samples && testResult?.triplet_samples.length > 0 &&
|
|
||||||
<RbCard
|
|
||||||
title={t('memoryExtractionEngine.extractRelationalTriples')}
|
|
||||||
headerType="borderL"
|
|
||||||
headerClassName="rb:before:bg-[#9C6FFF]!"
|
|
||||||
>
|
|
||||||
<Space size={8} direction="vertical" className="rb:w-full">
|
|
||||||
{testResult.triplet_samples.map((item, index) => (
|
|
||||||
<div key={index} className="rb:text-[12px]">
|
|
||||||
-({item.subject}, <span className="rb:text-[#9C6FFF] rb:font-medium">{item.predicate}</span>, {item.object})
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</Space>
|
|
||||||
<RbAlert color="purple" icon={<CheckCircleFilled />} className="rb:mt-3">
|
|
||||||
{t('memoryExtractionEngine.extractRelationalTriplesDesc', { count: testResult.triplet_samples.length })}
|
{t('memoryExtractionEngine.extractRelationalTriplesDesc', { count: testResult.triplet_samples.length })}
|
||||||
</RbAlert>
|
</RbAlert>
|
||||||
</RbCard>
|
<ul className="rb:list-disc rb:ml-4">
|
||||||
}
|
{testResult.triplet_samples.map((item, index) => (
|
||||||
{ontologyCoverage && Object.keys(ontologyCoverage).length > 0 &&
|
<li key={index} className="rb:leading-6">
|
||||||
<RbCard
|
({item.subject}, <span className="rb:text-[#155EEF] rb:font-medium">{item.predicate}</span>, {item.object})
|
||||||
title={<>{t('memoryExtractionEngine.ontologyCoverage')}({ontologyCoverage.total_entities})</>}
|
</li>
|
||||||
headerType="borderL"
|
))}
|
||||||
headerClassName="rb:before:bg-[#369F21]!"
|
</ul>
|
||||||
>
|
</div>
|
||||||
<div className="rb:grid rb:grid-cols-2 rb:gap-3">
|
</ResultCard>
|
||||||
|
}
|
||||||
|
{ontologyCoverage && Object.keys(ontologyCoverage).length > 0 &&
|
||||||
|
<ResultCard
|
||||||
|
title={<>{t('memoryExtractionEngine.ontologyCoverage')}({ontologyCoverage.total_entities})</>}
|
||||||
|
expanded={expandedCards['ontologyCoverage']}
|
||||||
|
handleExpand={() => toggleCard('ontologyCoverage')}
|
||||||
|
>
|
||||||
|
<div className="rb:bg-white rb:rounded-xl rb:p-3 rb:mb-3 rb:leading-5">
|
||||||
|
<div className="rb:grid rb:grid-cols-1 rb:gap-3">
|
||||||
{(['scene_type_distribution', 'general_type_distribution', 'unmatched'] as const).map((key, idx) => {
|
{(['scene_type_distribution', 'general_type_distribution', 'unmatched'] as const).map((key, idx) => {
|
||||||
if (!ontologyCoverage[key]) return null
|
if (!ontologyCoverage[key]) return null
|
||||||
return (
|
return (
|
||||||
<div key={idx} className="rb:text-[12px]">
|
<div key={idx}>
|
||||||
<div className="rb:text-[#369F21] rb:font-medium">{t(`memoryExtractionEngine.${key}`)}({ontologyCoverage[key].type_count})</div>
|
<div className="rb:text-[#155EEF] rb:font-medium rb:mb-1">{t(`memoryExtractionEngine.${key}`)}({ontologyCoverage[key].type_count})</div>
|
||||||
<div>{t('memoryExtractionEngine.entity_total', { num: ontologyCoverage[key].entity_total })}</div>
|
<div className="rb:text-[#212332] rb:mb-1">{t('memoryExtractionEngine.entity_total', { num: ontologyCoverage[key].entity_total })}</div>
|
||||||
<div>
|
|
||||||
|
<ul className="rb:list-disc rb:ml-4">
|
||||||
{ontologyCoverage[key].types.map((type, index) => {
|
{ontologyCoverage[key].types.map((type, index) => {
|
||||||
if (!type.type || type.type === '') return null
|
if (!type.type || type.type === '') return null
|
||||||
return (
|
return (
|
||||||
<div key={index} className="rb:text-[#5B6167] rb:font-regular rb:leading-4">
|
<li key={index} className="rb:leading-6 rb:text-[#5B6167]">
|
||||||
-{type.type}({type.count})
|
{type.type}({type.count})
|
||||||
</div>
|
</li>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</RbCard>
|
</div>
|
||||||
}
|
</ResultCard>
|
||||||
|
}
|
||||||
</Space>
|
</Flex>}
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="rb:grid rb:grid-cols-2 rb:gap-4 rb:mt-5">
|
|
||||||
<Button block loading={loading} onClick={handleSave}>{t('common.save')}</Button>
|
|
||||||
<Button block type="primary" loading={runLoading} onClick={handleRun}>{t('memoryExtractionEngine.debug')}</Button>
|
|
||||||
</div>
|
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* @Author: ZhaoYing
|
||||||
|
* @Date: 2026-02-03 17:30:51
|
||||||
|
* @Last Modified by: ZhaoYing
|
||||||
|
* @Last Modified time: 2026-03-19 14:23:58
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* ResultCard Component
|
||||||
|
* Collapsible card wrapper for configuration sections
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { type FC, type ReactNode } from 'react'
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import { Flex, Space, Tooltip } from 'antd';
|
||||||
|
|
||||||
|
import RbCard from '@/components/RbCard/Card'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component props
|
||||||
|
*/
|
||||||
|
interface ResultCardProps {
|
||||||
|
title: string | ReactNode;
|
||||||
|
subTitle?: string | ReactNode;
|
||||||
|
children: ReactNode;
|
||||||
|
expanded?: boolean;
|
||||||
|
handleExpand?: () => void;
|
||||||
|
className?: string;
|
||||||
|
headerClassName?: string;
|
||||||
|
bodyClassName?: string;
|
||||||
|
extra?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ResultCard: FC<ResultCardProps> = ({
|
||||||
|
title,
|
||||||
|
subTitle,
|
||||||
|
children,
|
||||||
|
expanded,
|
||||||
|
handleExpand,
|
||||||
|
extra,
|
||||||
|
className,
|
||||||
|
headerClassName,
|
||||||
|
bodyClassName,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<RbCard
|
||||||
|
title={() => <Flex
|
||||||
|
align="center"
|
||||||
|
justify="space-between"
|
||||||
|
className="rb:font-[MiSans-Bold] rb:font-bold rb:cursor-pointer"
|
||||||
|
onClick={handleExpand}
|
||||||
|
>
|
||||||
|
<Space size={4}>
|
||||||
|
{title}
|
||||||
|
{subTitle && <Tooltip title={subTitle}>
|
||||||
|
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/question.svg')]"></div>
|
||||||
|
</Tooltip>}
|
||||||
|
</Space>
|
||||||
|
<Space size={4}>
|
||||||
|
{extra}
|
||||||
|
{handleExpand && <div
|
||||||
|
className={clsx("rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/arrow_up.svg')] rb:transition-transform", {
|
||||||
|
'rb:rotate-180': !expanded,
|
||||||
|
'rb:rotate-0': expanded,
|
||||||
|
})}
|
||||||
|
></div>}
|
||||||
|
</Space>
|
||||||
|
</Flex>}
|
||||||
|
headerType="borderless"
|
||||||
|
headerClassName={headerClassName ?? "rb:min-h-[40px]! rb:text-[#212332]! rb:text-[14px]!"}
|
||||||
|
bodyClassName={bodyClassName ?? "rb:py-0! rb:px-3!"}
|
||||||
|
className={className ?? "rb:bg-[#F6F6F6]!"}
|
||||||
|
>
|
||||||
|
{(expanded && handleExpand) && children}
|
||||||
|
</RbCard>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ResultCard
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 17:30:02
|
* @Date: 2026-02-03 17:30:02
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-06 13:50:05
|
* @Last Modified time: 2026-03-18 17:55:32
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Memory Extraction Engine Configuration Page
|
* Memory Extraction Engine Configuration Page
|
||||||
@@ -13,18 +13,19 @@
|
|||||||
import { type FC, useState, useEffect } from 'react'
|
import { type FC, useState, useEffect } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useParams } from 'react-router-dom'
|
import { useParams } from 'react-router-dom'
|
||||||
import { Row, Col, Space, Select, InputNumber, Slider, App, Form, Input } from 'antd'
|
import { Row, Col, Space, Select, InputNumber, App, Form, Input, Flex, Tooltip } from 'antd'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
|
|
||||||
import Card from './components/Card'
|
import Card from './components/Card'
|
||||||
import type { ConfigForm, Variable } from './types'
|
import type { ConfigForm, Variable } from './types'
|
||||||
import { getMemoryExtractionConfig, updateMemoryExtractionConfig } from '@/api/memory'
|
import { getMemoryExtractionConfig, updateMemoryExtractionConfig } from '@/api/memory'
|
||||||
import Markdown from '@/components/Markdown'
|
import Markdown from '@/components/Markdown'
|
||||||
import { getModelListUrl } from '@/api/models';
|
|
||||||
import { configList } from './constant'
|
import { configList } from './constant'
|
||||||
import Result from './components/Result'
|
import Result from './components/Result'
|
||||||
import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
|
import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
|
||||||
import CustomSelect from '@/components/CustomSelect'
|
import ModelSelect from '@/components/ModelSelect'
|
||||||
|
import RbSlider from '@/components/RbSlider';
|
||||||
|
import DescWrapper from '@/components/FormItem/DescWrapper'
|
||||||
|
|
||||||
/** Available configuration section keys */
|
/** Available configuration section keys */
|
||||||
const keys = [
|
const keys = [
|
||||||
@@ -35,7 +36,7 @@ const keys = [
|
|||||||
/**
|
/**
|
||||||
* Configuration description component
|
* Configuration description component
|
||||||
*/
|
*/
|
||||||
const ConfigDesc: FC<{ config: Variable, className?: string; onlyMeaning?: boolean; }> = ({ config, className, onlyMeaning = false}) => {
|
const Desc: FC<{ config: Variable, className?: string; onlyMeaning?: boolean; }> = ({ config, className, onlyMeaning = false}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
@@ -44,7 +45,6 @@ const ConfigDesc: FC<{ config: Variable, className?: string; onlyMeaning?: boole
|
|||||||
{config.control && <span className="rb:font-regular">{t('memoryExtractionEngine.control')}: {t(`memoryExtractionEngine.${config.control}`)}</span>}
|
{config.control && <span className="rb:font-regular">{t('memoryExtractionEngine.control')}: {t(`memoryExtractionEngine.${config.control}`)}</span>}
|
||||||
{config.type && <span className="rb:font-regular">{t('memoryExtractionEngine.type')}: {config.type}</span>}
|
{config.type && <span className="rb:font-regular">{t('memoryExtractionEngine.type')}: {config.type}</span>}
|
||||||
</Space>}
|
</Space>}
|
||||||
{config.meaning && <div className={clsx("rb:mt-1 rb:text-[12px] rb:text-[#5B6167] rb:font-regular rb:leading-4 ")}>{t('memoryExtractionEngine.Meaning')}: {t(`memoryExtractionEngine.${config.meaning}`)}</div>}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -122,163 +122,139 @@ const MemoryExtractionEngine: FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="rb:text-[24px] rb:font-semibold rb:leading-8 rb:mb-2">{t('memoryExtractionEngine.title')}</div>
|
<Flex align="center" gap={4} className="rb:font-[MiSans-Bold] rb:text-[16px] rb:font-bold rb:leading-5.5 rb:mb-4!">
|
||||||
<div className="rb:text-[#5B6167] rb:leading-5 rb:mb-6">{t('memoryExtractionEngine.subTitle')}</div>
|
{t('memoryExtractionEngine.title')}
|
||||||
|
<Tooltip title={t('memoryExtractionEngine.subTitle')}>
|
||||||
|
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/question.svg')]"></div>
|
||||||
|
</Tooltip>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={12}>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form form={modelForm}>
|
<Flex vertical gap={12} className="rb:h-[calc(100vh-114px)]! rb:overflow-y-auto">
|
||||||
<Form.Item
|
<Form form={modelForm}>
|
||||||
label={t('memoryExtractionEngine.model')}
|
<Form.Item
|
||||||
name="llm_id"
|
name="llm_id"
|
||||||
>
|
noStyle
|
||||||
<CustomSelect
|
>
|
||||||
url={getModelListUrl}
|
<ModelSelect
|
||||||
params={{ type: 'llm,chat', pagesize: 100, is_active: true }}
|
params={{ type: 'llm,chat' }}
|
||||||
valueKey="id"
|
className="rb:w-full! rb:h-10! rb:bg-white rb:rounded-xl"
|
||||||
labelKey="name"
|
variant="borderless"
|
||||||
hasAll={false}
|
placeholder={t('memoryExtractionEngine.model')}
|
||||||
style={{ width: '100%' }}
|
allowClear={false}
|
||||||
/>
|
fontClassName="rb:font-medium!"
|
||||||
</Form.Item>
|
/>
|
||||||
</Form>
|
</Form.Item>
|
||||||
</Col>
|
</Form>
|
||||||
</Row>
|
|
||||||
<Card
|
|
||||||
type="example"
|
|
||||||
title={t('memoryExtractionEngine.example')}
|
|
||||||
expanded={expandedKeys.includes('example')}
|
|
||||||
handleExpand={handleExpand}
|
|
||||||
>
|
|
||||||
{expandedKeys.includes('example') &&
|
|
||||||
<div className="rb:text-[14px] rb:text-[#5B6167] rb:font-regular rb:leading-5">
|
|
||||||
<Markdown content={t('memoryExtractionEngine.exampleText')} />
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</Card>
|
|
||||||
<Row gutter={[16, 16]} className="rb:mt-4">
|
|
||||||
<Col span={14}>
|
|
||||||
<Form
|
|
||||||
form={form}
|
|
||||||
>
|
|
||||||
<Space direction="vertical" size={16} style={{ width: '100%' }}>
|
|
||||||
{configList.map((item, index) => (
|
|
||||||
<Card
|
|
||||||
type={item.type}
|
|
||||||
title={t(`memoryExtractionEngine.${item.type}`)}
|
|
||||||
key={index}
|
|
||||||
expanded={expandedKeys.includes(item.type)}
|
|
||||||
handleExpand={handleExpand}
|
|
||||||
>
|
|
||||||
<Space size={20} direction="vertical" style={{width: '100%'}}>
|
|
||||||
{item.data.map(vo => (
|
|
||||||
<div
|
|
||||||
key={vo.title}
|
|
||||||
className={clsx(
|
|
||||||
`rb:p-[16px_24px] rb:rounded-lg`,
|
|
||||||
'rb:border rb:border-[#DFE4ED]',
|
|
||||||
{
|
|
||||||
'rb:shadow-[inset_4px_0px_0px_0px_#155EEF]': index % 2 === 0,
|
|
||||||
'rb:shadow-[inset_4px_0px_0px_0px_#369F21]': index % 2 !== 0,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div className="rb:text-[16px] rb:font-medium rb:leading-5.5">{t(`memoryExtractionEngine.${vo.title}`)}</div>
|
|
||||||
<div className="rb:mt-1 rb:text-[12px] rb:text-[#5B6167] rb:font-regular rb:leading-4">{t(`memoryExtractionEngine.${vo.title}SubTitle`)}</div>
|
|
||||||
|
|
||||||
{vo.list.map(config => (
|
<div className="rb:bg-white rb:rounded-xl rb:py-2.5 rb:px-4">
|
||||||
<div key={config.label}>
|
<Flex
|
||||||
{config.control === 'button' &&
|
align="center"
|
||||||
<SwitchFormItem
|
justify="space-between"
|
||||||
title={<>-{t(`memoryExtractionEngine.${config.label}`)}</>}
|
className="rb:font-[MiSans-Bold] rb:font-bold rb:cursor-pointer"
|
||||||
name={config.variableName}
|
onClick={() => handleExpand('example')}
|
||||||
desc={<ConfigDesc config={config} className="rb:ml-2" />}
|
>
|
||||||
className="rb:mt-6"
|
{t('memoryExtractionEngine.example')}
|
||||||
/>
|
<div className={clsx("rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/arrow_up.svg')]", {
|
||||||
}
|
'rb:rotate-180': !expandedKeys.includes('example'),
|
||||||
{config.control === 'select' &&
|
'rb:rotate-0': expandedKeys.includes('example'),
|
||||||
<>
|
})}></div>
|
||||||
<div className="rb:text-[14px] rb:font-medium rb:leading-5 rb:mt-6 rb:mb-2">
|
</Flex>
|
||||||
-{t(`memoryExtractionEngine.${config.label}`)}
|
|
||||||
</div>
|
{expandedKeys.includes('example') &&
|
||||||
<div className="rb:pl-2">
|
<div className="rb:text-[14px] rb:text-[#5B6167] rb:font-regular rb:leading-5 rb:mt-2.5 rb:mb-1.5">
|
||||||
|
<Markdown content={t('memoryExtractionEngine.exampleText')} />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Form form={form}>
|
||||||
|
<Flex vertical gap={16}>
|
||||||
|
{configList.map((item, index) => (
|
||||||
|
<Card
|
||||||
|
type={item.type}
|
||||||
|
title={t(`memoryExtractionEngine.${item.type}`)}
|
||||||
|
key={index}
|
||||||
|
expanded={expandedKeys.includes(item.type)}
|
||||||
|
handleExpand={handleExpand}
|
||||||
|
>
|
||||||
|
<Flex gap={16} vertical>
|
||||||
|
{item.data.map(vo => (
|
||||||
|
<Flex
|
||||||
|
key={vo.title}
|
||||||
|
vertical
|
||||||
|
gap={10}
|
||||||
|
className="rb:bg-[#F6F6F6] rb:rounded-xl rb:p-3! rb:pt-2.5!"
|
||||||
|
>
|
||||||
|
<Space size={4} className="rb:text-[#212332] rb:font-medium rb:leading-5">
|
||||||
|
{t(`memoryExtractionEngine.${vo.title}`)}
|
||||||
|
<Tooltip title={t(`memoryExtractionEngine.${vo.title}SubTitle`)}>
|
||||||
|
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/question.svg')]"></div>
|
||||||
|
</Tooltip>
|
||||||
|
</Space>
|
||||||
|
|
||||||
|
{vo.list.map(config => (
|
||||||
|
<div key={config.label} className="rb:bg-white rb:rounded-xl rb:p-3 rb:pr-2.5">
|
||||||
|
{config.control === 'button'
|
||||||
|
? <SwitchFormItem
|
||||||
|
title={t(`memoryExtractionEngine.${config.label}`)}
|
||||||
|
name={config.variableName}
|
||||||
|
desc={<DescWrapper desc={<Desc config={config} />} />}
|
||||||
|
className="rb:mt-6"
|
||||||
|
/>
|
||||||
|
: <>
|
||||||
|
{config.meaning
|
||||||
|
? <Space size={4} className="rb:text-[#212332] rb:font-medium rb:leading-5">
|
||||||
|
{t(`memoryExtractionEngine.${config.label}`)}
|
||||||
|
<Tooltip title={<>{t('memoryExtractionEngine.Meaning')}: {t(`memoryExtractionEngine.${config.meaning}`)}</>}>
|
||||||
|
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/question.svg')]"></div>
|
||||||
|
</Tooltip>
|
||||||
|
</Space>
|
||||||
|
: <div className="rb:text-[#212332] rb:font-medium rb:leading-5">
|
||||||
|
{t(`memoryExtractionEngine.${config.label}`)}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
{config.control !== 'text' && <DescWrapper desc={<Desc config={config} />} />}
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={config.variableName}
|
name={config.variableName}
|
||||||
|
className="rb:mb-0! rb:mt-2!"
|
||||||
>
|
>
|
||||||
<Select
|
{config.control === 'select'
|
||||||
disabled={config.variableName === 'iteration_period' && iterationPeriodDisabled}
|
? <Select
|
||||||
options={config.options ? config.options.map(item => ({ ...item, label: t(`memoryExtractionEngine.${item.label}`) })) : []}
|
disabled={config.variableName === 'iteration_period' && iterationPeriodDisabled}
|
||||||
/>
|
options={config.options ? config.options.map(item => ({ ...item, label: t(`memoryExtractionEngine.${item.label}`) })) : []}
|
||||||
|
/>
|
||||||
|
: config.control === 'slider'
|
||||||
|
? <RbSlider
|
||||||
|
min={config.min || 0}
|
||||||
|
max={config.max || 1}
|
||||||
|
step={config.step || 0.01}
|
||||||
|
isInput={true}
|
||||||
|
prefix={<span className="rb:text-[#5B6167]">{t('emotionEngine.currentValue')}:</span>}
|
||||||
|
inputClassName="rb:w-[155px]!"
|
||||||
|
/>
|
||||||
|
: config.control === 'inputNumber'
|
||||||
|
? <InputNumber min={config.min || 0} style={{ width: '100%' }} placeholder={t('common.pleaseEnter')} />
|
||||||
|
: config.control === 'text'
|
||||||
|
? <Input placeholder={t('common.pleaseEnter')} disabled />
|
||||||
|
: null
|
||||||
|
}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<ConfigDesc config={config} className="rb:-mt-4!" />
|
</>
|
||||||
</div>
|
}
|
||||||
</>
|
</div>
|
||||||
}
|
))}
|
||||||
{config.control === 'slider' &&
|
</Flex>
|
||||||
<>
|
))}
|
||||||
<div className="rb:text-[14px] rb:font-medium rb:leading-5 rb:mt-6 rb:mb-2">
|
</Flex>
|
||||||
-{t(`memoryExtractionEngine.${config.label}`)}
|
</Card>
|
||||||
</div>
|
))}
|
||||||
<div className="rb:pl-2">
|
</Flex>
|
||||||
<ConfigDesc config={config} className="rb:mb-2.5" />
|
</Form>
|
||||||
<Form.Item
|
</Flex>
|
||||||
name={config.variableName}
|
|
||||||
>
|
|
||||||
<Slider
|
|
||||||
style={{ margin: '0' }}
|
|
||||||
min={config.min || 0}
|
|
||||||
max={config.max || 1}
|
|
||||||
step={config.step || 0.01}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<div className="rb:flex rb:items-center rb:justify-between rb:text-[#5B6167] rb:leading-5 rb:-mt-6.5">
|
|
||||||
{config.min || 0}
|
|
||||||
<span>{t('memoryExtractionEngine.CurrentValue')}: {values?.[config.variableName as keyof ConfigForm]}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
{config.control === 'inputNumber' &&
|
|
||||||
<>
|
|
||||||
<div className="rb:text-[14px] rb:font-medium rb:leading-5 rb:mt-6 rb:mb-2">
|
|
||||||
-{t(`memoryExtractionEngine.${config.label}`)}
|
|
||||||
</div>
|
|
||||||
<div className="rb:pl-2">
|
|
||||||
<Form.Item
|
|
||||||
name={config.variableName}
|
|
||||||
>
|
|
||||||
<InputNumber min={config.min || 0} style={{ width: '100%' }} placeholder={t('common.pleaseEnter')} />
|
|
||||||
</Form.Item>
|
|
||||||
<ConfigDesc config={config} className="rb:-mt-4!" />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
{config.control === 'text' &&
|
|
||||||
<>
|
|
||||||
<div className="rb:text-[14px] rb:font-medium rb:leading-5 rb:mt-6 rb:mb-2">
|
|
||||||
-{t(`memoryExtractionEngine.${config.label}`)}
|
|
||||||
</div>
|
|
||||||
<div className="rb:pl-2">
|
|
||||||
<Form.Item
|
|
||||||
name={config.variableName}
|
|
||||||
>
|
|
||||||
<Input placeholder={t('common.pleaseEnter')} disabled />
|
|
||||||
</Form.Item>
|
|
||||||
<ConfigDesc config={config} onlyMeaning={true} className="rb:-mt-4!" />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</Space>
|
|
||||||
</Card>
|
|
||||||
))}
|
|
||||||
</Space>
|
|
||||||
</Form>
|
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={10}>
|
<Col span={12}>
|
||||||
<Result
|
<Result
|
||||||
loading={loading}
|
loading={loading}
|
||||||
handleSave={handleSave}
|
handleSave={handleSave}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 17:46:47
|
* @Date: 2026-02-03 17:46:47
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-02-03 17:46:47
|
* @Last Modified time: 2026-03-16 15:54:45
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Self Reflection Engine Configuration Page
|
* Self Reflection Engine Configuration Page
|
||||||
@@ -11,12 +11,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Row, Col, Form, App, Button, Space, Select } from 'antd';
|
import { Row, Col, Form, App, Button, Space, Select, Flex } from 'antd';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import RbCard from '@/components/RbCard/Card';
|
import RbCard from '@/components/RbCard/Card';
|
||||||
import strategyImpactSimulator from '@/assets/images/memory/strategyImpactSimulator.svg'
|
|
||||||
import { getMemoryReflectionConfig, updateMemoryReflectionConfig, pilotRunMemoryReflectionConfig } from '@/api/memory'
|
import { getMemoryReflectionConfig, updateMemoryReflectionConfig, pilotRunMemoryReflectionConfig } from '@/api/memory'
|
||||||
import type { ConfigForm, Result, ReflexionData, MemoryVerify, QualityAssessment } from './types'
|
import type { ConfigForm, Result, ReflexionData, MemoryVerify, QualityAssessment } from './types'
|
||||||
import CustomSelect from '@/components/CustomSelect';
|
import CustomSelect from '@/components/CustomSelect';
|
||||||
@@ -24,6 +23,8 @@ import { getModelListUrl } from '@/api/models'
|
|||||||
import Tag from '@/components/Tag'
|
import Tag from '@/components/Tag'
|
||||||
import { useI18n } from '@/store/locale';
|
import { useI18n } from '@/store/locale';
|
||||||
import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
|
import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
|
||||||
|
import LabelWrapper from '@/components/FormItem/LabelWrapper'
|
||||||
|
import DescWrapper from '@/components/FormItem/DescWrapper'
|
||||||
|
|
||||||
/** Configuration list */
|
/** Configuration list */
|
||||||
const configList = [
|
const configList = [
|
||||||
@@ -173,12 +174,15 @@ const SelfReflectionEngine: React.FC = () => {
|
|||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<RbCard
|
<RbCard
|
||||||
title={
|
title={t('reflectionEngine.reflectionEngineConfig')}
|
||||||
<div className="rb:flex rb:items-center">
|
extra={<Space>
|
||||||
<img src={strategyImpactSimulator} className="rb:w-5 rb:h-5 rb:mr-2" />
|
<Button block onClick={handleReset}>{t('common.reset')}</Button>
|
||||||
{t('reflectionEngine.reflectionEngineConfig')}
|
<Button type="primary" loading={loading} block onClick={handleSave}>{t('common.save')}</Button>
|
||||||
</div>
|
</Space>}
|
||||||
}
|
headerType="borderless"
|
||||||
|
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||||
|
className="rb:h-[calc(100vh-76px)]!"
|
||||||
|
bodyClassName="rb:h-[calc(100%-54px)] rb:overflow-y-auto! rb:p-4! rb:pt-0!"
|
||||||
>
|
>
|
||||||
<Form
|
<Form
|
||||||
form={form}
|
form={form}
|
||||||
@@ -189,74 +193,68 @@ const SelfReflectionEngine: React.FC = () => {
|
|||||||
lambda_mem: 0.03,
|
lambda_mem: 0.03,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{configList.map(config => {
|
<Flex vertical gap={24}>
|
||||||
if (config.type === 'customSelect') {
|
{configList.map(config => {
|
||||||
return (
|
if (config.type === 'customSelect') {
|
||||||
<div key={config.key}>
|
return (
|
||||||
<div className="rb:text-[14px] rb:font-medium rb:leading-5 rb:mb-2">
|
<div key={config.key}>
|
||||||
{t(`reflectionEngine.${config.key}`)}
|
<LabelWrapper title={t(`reflectionEngine.${config.key}`)} className="rb:mb-3">
|
||||||
|
<DescWrapper desc={t(`reflectionEngine.${config.key}_desc`)} className="rb:mt-1" />
|
||||||
|
</LabelWrapper>
|
||||||
|
<Form.Item
|
||||||
|
name={config.key}
|
||||||
|
className="rb:mb-0!"
|
||||||
|
>
|
||||||
|
<CustomSelect
|
||||||
|
url={config.url as string}
|
||||||
|
params={config.params}
|
||||||
|
valueKey='id'
|
||||||
|
labelKey='name'
|
||||||
|
hasAll={false}
|
||||||
|
placeholder={t('common.pleaseSelect')}
|
||||||
|
disabled={!values?.reflection_enabled && config.key !== 'reflection_enabled'}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
<Form.Item
|
)
|
||||||
name={config.key}
|
}
|
||||||
extra={t(`reflectionEngine.${config.key}_desc`)}
|
if (config.type === 'select') {
|
||||||
>
|
return (
|
||||||
<CustomSelect
|
<div key={config.key}>
|
||||||
url={config.url as string}
|
<LabelWrapper title={t(`reflectionEngine.${config.key}`)} className="rb:mb-3">
|
||||||
params={config.params}
|
<DescWrapper desc={t(`reflectionEngine.${config.key}_desc`)} className="rb:mt-1" />
|
||||||
valueKey='id'
|
</LabelWrapper>
|
||||||
labelKey='name'
|
<Form.Item
|
||||||
hasAll={false}
|
name={config.key}
|
||||||
placeholder={t('common.pleaseSelect')}
|
className="rb:mb-0!"
|
||||||
disabled={!values?.reflection_enabled && config.key !== 'reflection_enabled'}
|
>
|
||||||
/>
|
<Select
|
||||||
</Form.Item>
|
options={config.options?.map(vo => ({
|
||||||
</div>
|
...vo,
|
||||||
)
|
label: t(`reflectionEngine.${vo.label}`),
|
||||||
}
|
}))}
|
||||||
if (config.type === 'select') {
|
placeholder={t('common.pleaseSelect')}
|
||||||
return (
|
disabled={!values?.reflection_enabled && config.key !== 'reflection_enabled'}
|
||||||
<div key={config.key}>
|
/>
|
||||||
<div className="rb:text-[14px] rb:font-medium rb:leading-5 rb:mb-2">
|
</Form.Item>
|
||||||
{t(`reflectionEngine.${config.key}`)}
|
|
||||||
</div>
|
</div>
|
||||||
<Form.Item
|
)
|
||||||
name={config.key}
|
}
|
||||||
extra={t(`reflectionEngine.${config.key}_desc`)}
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
options={config.options?.map(vo => ({
|
|
||||||
...vo,
|
|
||||||
label: t(`reflectionEngine.${vo.label}`),
|
|
||||||
}))}
|
|
||||||
placeholder={t('common.pleaseSelect')}
|
|
||||||
disabled={!values?.reflection_enabled && config.key !== 'reflection_enabled'}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SwitchFormItem
|
<SwitchFormItem
|
||||||
title={t(`reflectionEngine.${config.key}`)}
|
title={t(`reflectionEngine.${config.key}`)}
|
||||||
name={config.key}
|
name={config.key}
|
||||||
desc={<>
|
desc={<>
|
||||||
{(config as any).hasSubTitle && <div className="rb:mt-1 rb:text-[12px] rb:text-[#5B6167] rb:font-regular rb:leading-4">{t(`reflectionEngine.${config.key}_subTitle`)}</div>}
|
{(config as any).hasSubTitle && <div className="rb:mt-1 rb:text-[12px] rb:text-[#5B6167] rb:font-regular rb:leading-4">{t(`reflectionEngine.${config.key}_subTitle`)}</div>}
|
||||||
<div className="rb:mt-1 rb:text-[12px] rb:text-[#5B6167] rb:font-regular rb:leading-4">{t(`reflectionEngine.${config.key}_desc`)}</div>
|
<div className="rb:mt-1 rb:text-[12px] rb:text-[#5B6167] rb:font-regular rb:leading-4">{t(`reflectionEngine.${config.key}_desc`)}</div>
|
||||||
</>}
|
</>}
|
||||||
className="rb:mb-6"
|
className="rb:mb-6"
|
||||||
disabled={!values?.reflection_enabled && config.key !== 'reflection_enabled'}
|
disabled={!values?.reflection_enabled && config.key !== 'reflection_enabled'}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
<Row gutter={16} className="rb:mt-3">
|
</Flex>
|
||||||
<Col span={12}>
|
|
||||||
<Button block onClick={handleReset}>{t('common.reset')}</Button>
|
|
||||||
</Col>
|
|
||||||
<Col span={12}>
|
|
||||||
<Button type="primary" loading={loading} block onClick={handleSave}>{t('common.save')}</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Form>
|
</Form>
|
||||||
</RbCard>
|
</RbCard>
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 17:53:44
|
* @Date: 2026-02-03 17:53:44
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-16 15:01:27
|
* @Last Modified time: 2026-03-16 15:23:18
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* User Memory Page
|
* User Memory Page
|
||||||
@@ -104,7 +104,7 @@ export default function UserMemory() {
|
|||||||
title={<Flex gap={4}>
|
title={<Flex gap={4}>
|
||||||
<div className="rb:size-6 rb:text-center rb:font-semibold rb:leading-6 rb:rounded-md rb:text-white rb:bg-[#155EEF]">{name[0]}</div>
|
<div className="rb:size-6 rb:text-center rb:font-semibold rb:leading-6 rb:rounded-md rb:text-white rb:bg-[#155EEF]">{name[0]}</div>
|
||||||
|
|
||||||
<Tooltip title={name || '-'}><div className={`rb:w-full rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap`}>{name || '-'}</div></Tooltip>
|
<Tooltip title={name || '-'}><div className={`rb:flex-1 rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap`}>{name || '-'}</div></Tooltip>
|
||||||
</Flex>}
|
</Flex>}
|
||||||
headerType="border"
|
headerType="border"
|
||||||
headerClassName="rb:h-[48px]! rb:mx-4!"
|
headerClassName="rb:h-[48px]! rb:mx-4!"
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 17:57:11
|
* @Date: 2026-02-03 17:57:11
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-02-03 17:57:11
|
* @Last Modified time: 2026-03-19 11:38:17
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* RAG User Memory Detail View
|
* RAG User Memory Detail View
|
||||||
@@ -12,83 +12,55 @@
|
|||||||
|
|
||||||
import { type FC, useEffect, useState } from 'react'
|
import { type FC, useEffect, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import clsx from 'clsx'
|
import { Row, Col, Skeleton, Flex } from 'antd'
|
||||||
import { Row, Col, Skeleton } from 'antd'
|
|
||||||
import { useParams } from 'react-router-dom'
|
import { useParams } from 'react-router-dom'
|
||||||
|
|
||||||
import aboutUs from '@/assets/images/userMemory/aboutUs.svg'
|
import aboutUs from '@/assets/images/userMemory/aboutUs.svg'
|
||||||
import down from '@/assets/images/userMemory/down.svg'
|
import memoryInsight from '@/assets/images/userMemory/memoryInsight.svg'
|
||||||
import interestDistribution from '@/assets/images/userMemory/interestDistribution.svg'
|
|
||||||
import RbCard from '@/components/RbCard/Card'
|
import RbCard from '@/components/RbCard/Card'
|
||||||
import type { Data } from './types'
|
import type { Data } from './types'
|
||||||
import {
|
import {
|
||||||
getChunkSummaryTag,
|
getChunkSummaryTag,
|
||||||
getUserProfile,
|
getUserProfile,
|
||||||
getTotalRagMemoryCountByUser,
|
|
||||||
getChunkInsight,
|
getChunkInsight,
|
||||||
} from '@/api/memory'
|
} from '@/api/memory'
|
||||||
import Empty from '@/components/Empty'
|
import Empty from '@/components/Empty'
|
||||||
import ConversationMemory from './components/ConversationMemory'
|
import ConversationMemory from './components/ConversationMemory'
|
||||||
|
|
||||||
/** Tag color palette */
|
|
||||||
const tagColors = ['21, 94, 239', '156, 111, 255', '255, 93, 52', '54, 159, 33']
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Title component props
|
* Title component props
|
||||||
*/
|
*/
|
||||||
interface TitleProps {
|
interface TitleProps {
|
||||||
type: string;
|
|
||||||
title: string
|
title: string
|
||||||
icon: string
|
icon: string
|
||||||
t: (key: string) => string;
|
|
||||||
expanded: boolean;
|
|
||||||
onClick: (type: string) => void;
|
|
||||||
}
|
}
|
||||||
/** Collapsible section title */
|
/** Collapsible section title */
|
||||||
const Title: FC<TitleProps> = ({ type, title, icon, t, expanded, onClick }) => (
|
const Title: FC<TitleProps> = ({ title, icon }) => (
|
||||||
<div className="rb:flex rb:items-center rb:justify-between rb:py-4.25 rb:border-b rb:border-[#DFE4ED] rb:text-[16px] rb:font-semibold rb:leading-5.5">
|
<Flex align="center" gap={4} className="rb:font-medium rb:leading-5 rb:mb-2.25!">
|
||||||
<span className="rb:flex rb:items-center">
|
<img src={icon} className="rb:size-4.5 rb:ml-0.5" />
|
||||||
<img src={icon} className="rb:w-5 rb:h-5 rb:mr-2" />
|
{title}
|
||||||
{title}
|
</Flex>
|
||||||
</span>
|
|
||||||
|
|
||||||
<span className="rb:flex rb:items-center rb:cursor-pointer rb:text-[#5B6167] rb:text-[14px] rb:font-regular rb:leading-5" onClick={() => onClick(type)}>
|
|
||||||
{t(`userMemory.${expanded ? 'foldUp' : 'expanded'}`)}
|
|
||||||
<img src={down} className={clsx("rb:w-4 rb:h-4 rb:ml-1", {
|
|
||||||
'rb:rotate-180': !expanded,
|
|
||||||
})} />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Rag: FC = () => {
|
const Rag: FC = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
const [data, setData] = useState<Data | null>(null)
|
const [data, setData] = useState<Data | null>(null)
|
||||||
const [expanded, setExpanded] = useState<string[]>(['aboutUs', 'memoryInsight',])
|
|
||||||
const [summary, setSummary] = useState<string | null>('')
|
const [summary, setSummary] = useState<string | null>('')
|
||||||
const [loading, setLoading] = useState<Record<string, boolean>>({
|
const [loading, setLoading] = useState<Record<string, boolean>>({
|
||||||
detail: true,
|
detail: true,
|
||||||
summary: true,
|
summary: true,
|
||||||
insight: true,
|
insight: true,
|
||||||
})
|
})
|
||||||
const [memory, setMemory] = useState<number | null>(null)
|
|
||||||
const [insight, setInsight] = useState<string | null>('')
|
const [insight, setInsight] = useState<string | null>('')
|
||||||
const [tags, setTags] = useState<{ tag: string; frequency: number }[]>([])
|
|
||||||
const [personas, setPersonas] = useState<string[]>([])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!id) return
|
if (!id) return
|
||||||
getMemory()
|
|
||||||
getSummary()
|
getSummary()
|
||||||
getDetail()
|
getDetail()
|
||||||
getInsightReport()
|
getInsightReport()
|
||||||
}, [id])
|
}, [id])
|
||||||
|
|
||||||
/** Toggle section expansion */
|
|
||||||
const handleTitleClick = (key: string) => {
|
|
||||||
setExpanded(expanded.includes(key) ? expanded.filter((item) => item !== key) : [...expanded, key])
|
|
||||||
}
|
|
||||||
/** Fetch user memory detail */
|
/** Fetch user memory detail */
|
||||||
const getDetail = () => {
|
const getDetail = () => {
|
||||||
if (!id) return
|
if (!id) return
|
||||||
@@ -100,13 +72,6 @@ const Rag: FC = () => {
|
|||||||
setLoading(prev => ({ ...prev, detail: false }))
|
setLoading(prev => ({ ...prev, detail: false }))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/** Fetch memory count */
|
|
||||||
const getMemory = () => {
|
|
||||||
if (!id) return
|
|
||||||
getTotalRagMemoryCountByUser(id).then((res) => {
|
|
||||||
setMemory(res as number || 0)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/** Fetch user summary */
|
/** Fetch user summary */
|
||||||
const getSummary = () => {
|
const getSummary = () => {
|
||||||
if (!id) return
|
if (!id) return
|
||||||
@@ -114,8 +79,6 @@ const Rag: FC = () => {
|
|||||||
getChunkSummaryTag(id).then((res) => {
|
getChunkSummaryTag(id).then((res) => {
|
||||||
const response = res as { summary?: string; tags?: { tag: string; frequency: number }[]; personas?: string[] }
|
const response = res as { summary?: string; tags?: { tag: string; frequency: number }[]; personas?: string[] }
|
||||||
setSummary(response.summary || null)
|
setSummary(response.summary || null)
|
||||||
setTags(response.tags || [])
|
|
||||||
setPersonas(response.personas || [])
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
setLoading(prev => ({ ...prev, summary: false }))
|
setLoading(prev => ({ ...prev, summary: false }))
|
||||||
@@ -134,82 +97,51 @@ const Rag: FC = () => {
|
|||||||
}
|
}
|
||||||
const name = loading.detail ? '' : data?.name && data?.name !== '' ? data.name : id
|
const name = loading.detail ? '' : data?.name && data?.name !== '' ? data.name : id
|
||||||
return (
|
return (
|
||||||
<Row gutter={[16, 16]} className="rb:pb-6">
|
<Row gutter={[16, 16]}>
|
||||||
<Col span={8}>
|
<Col span={8}>
|
||||||
<RbCard>
|
<RbCard
|
||||||
<div className="rb:flex rb:items-center">
|
bodyClassName="rb:p-3! rb:pt-4! rb:h-[calc(100vh-76px)]"
|
||||||
<div className="rb:flex-[0_0_auto] rb:w-20 rb:h-20 rb:text-center rb:font-semibold rb:text-[28px] rb:leading-20 rb:rounded-lg rb:text-[#FBFDFF] rb:bg-[#155EEF]">{name?.[0]}</div>
|
>
|
||||||
<div className="rb:text-[24px] rb:font-semibold rb:leading-8 rb:ml-4">
|
<Flex align="center" gap={12} className="rb:mb-6!">
|
||||||
{name}<br/>
|
<div className="rb:size-12 rb:text-center rb:font-semibold rb:text-[28px] rb:leading-12 rb:rounded-xl rb:text-white rb:bg-[#155EEF]">{name?.[0]}</div>
|
||||||
<div className="rb:text-[12px] rb:text-[#5B6167] rb:font-regular rb:leading-4 rb:mt-2">{personas?.join(' | ')}</div>
|
<div className="rb:text-[16px] rb:font-semibold rb:leading-6 rb:line-clamp-2 rb:flex-1">
|
||||||
|
{name}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Flex>
|
||||||
|
|
||||||
<div className="rb:flex rb:gap-2 rb:mb-2 rb:flex-wrap rb:mt-6.25">
|
|
||||||
{tags?.map((tag, tagIndex) => (
|
|
||||||
<span key={tag.tag} className="rb:rounded-[11px] rb:p-[0_8px] rb:leading-5.5 rb:border"
|
|
||||||
style={{
|
|
||||||
backgroundColor: `rgba(${tagColors[tagIndex % tagColors.length]}, 0.08)`,
|
|
||||||
borderColor: `rgba(${tagColors[tagIndex % tagColors.length]}, 0.3)`,
|
|
||||||
color: `rgba(${tagColors[tagIndex % tagColors.length]}, 1)`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{tag.tag}({tag.frequency})
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Total Memory */}
|
|
||||||
<div className="rb:font-regular rb:text-[12px] rb:text-[#5B6167] rb:leading-4 rb:mb-6.25">
|
|
||||||
{t('userMemory.totalNumOfMemories')}
|
|
||||||
<div className="rb:font-extrabold rb:text-[24px] rb:text-[#212332] rb:leading-7.5 rb:mt-2">{memory || 0}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* About Me */}
|
{/* About Me */}
|
||||||
<>
|
<>
|
||||||
<Title
|
<Title
|
||||||
type="aboutUs"
|
|
||||||
title={t('userMemory.aboutMe')}
|
title={t('userMemory.aboutMe')}
|
||||||
icon={aboutUs}
|
icon={aboutUs}
|
||||||
t={t}
|
|
||||||
expanded={expanded.includes('aboutUs')}
|
|
||||||
onClick={handleTitleClick}
|
|
||||||
/>
|
/>
|
||||||
{expanded.includes('aboutUs') && (
|
<div className="rb:bg-[#F6F6F6] rb:rounded-lg rb:py-2.5 rb:px-3 rb:mb-4">
|
||||||
<>
|
{loading.summary
|
||||||
{loading.summary
|
? <Skeleton />
|
||||||
? <Skeleton className="rb:mt-4" />
|
: summary
|
||||||
: summary
|
? <div className="rb:leading-5 rb:text-[#5B6167]">
|
||||||
? <div className="rb:font-regular rb:leading-5.5 rb:pt-4">
|
{summary || '-'}
|
||||||
{summary || '-'}
|
</div>
|
||||||
</div>
|
: <Empty size={88} />
|
||||||
: <Empty size={88} className="rb:mt-12 rb:mb-20.25" />
|
}
|
||||||
}
|
</div>
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
{/* Memory Insights */}
|
{/* Memory Insights */}
|
||||||
<>
|
<>
|
||||||
<Title
|
<Title
|
||||||
type="memoryInsight"
|
|
||||||
title={t('userMemory.memoryInsight')}
|
title={t('userMemory.memoryInsight')}
|
||||||
icon={interestDistribution}
|
icon={memoryInsight}
|
||||||
t={t}
|
|
||||||
expanded={expanded.includes('memoryInsight')}
|
|
||||||
onClick={handleTitleClick}
|
|
||||||
/>
|
/>
|
||||||
{expanded.includes('memoryInsight') && (
|
<div className="rb:bg-[#F6F6F6] rb:rounded-lg rb:py-2.5 rb:px-3">
|
||||||
<>
|
{loading.insight
|
||||||
{loading.insight
|
? <Skeleton />
|
||||||
? <Skeleton className="rb:mt-4" />
|
: insight
|
||||||
: insight
|
? <div className="rb:leading-5 rb:text-[#5B6167]">
|
||||||
? <div className="rb:font-regular rb:leading-5.5 rb:pt-4">
|
{insight || '-'}
|
||||||
{insight || '-'}
|
</div>
|
||||||
</div>
|
: <Empty size={88} />
|
||||||
: <Empty size={88} className="rb:mt-12 rb:mb-20.25" />
|
}
|
||||||
}
|
</div>
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
</RbCard>
|
</RbCard>
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 18:33:44
|
* @Date: 2026-02-03 18:33:44
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-02-03 18:33:44
|
* @Last Modified time: 2026-03-19 11:55:42
|
||||||
*/
|
*/
|
||||||
import { type FC, useRef } from 'react'
|
import { type FC, useRef } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import ReactEcharts from 'echarts-for-react';
|
import ReactEcharts from 'echarts-for-react';
|
||||||
|
import { Flex } from 'antd';
|
||||||
|
|
||||||
import Empty from '@/components/Empty'
|
import Empty from '@/components/Empty'
|
||||||
import Loading from '@/components/Empty/Loading'
|
import Loading from '@/components/Empty/Loading'
|
||||||
@@ -63,12 +64,12 @@ const EmotionLine: FC<EmotionLineProps> = ({ chartData, loading }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Flex vertical gap={16} className="rb-border rb:rounded-xl rb:p-4! rb:h-78">
|
||||||
<div>{t('userMemory.emotionLine')}</div>
|
<div className="rb:text-[#212332] rb:font-medium rb:leading-5">{t('userMemory.emotionLine')}</div>
|
||||||
{loading
|
{loading
|
||||||
? <Loading size={249} />
|
? <Loading size={249} />
|
||||||
: !chartData || chartData.length === 0
|
: !chartData || chartData.length === 0
|
||||||
? <Empty size={120} className="rb:mt-12 rb:mb-20.25" />
|
? <Empty size={120} className="rb:flex-1" />
|
||||||
: <ReactEcharts
|
: <ReactEcharts
|
||||||
ref={chartRef}
|
ref={chartRef}
|
||||||
option={{
|
option={{
|
||||||
@@ -175,12 +176,12 @@ const EmotionLine: FC<EmotionLineProps> = ({ chartData, loading }) => {
|
|||||||
},
|
},
|
||||||
series: getSeries()
|
series: getSeries()
|
||||||
}}
|
}}
|
||||||
style={{ height: '265px', width: '100%', minWidth: '100%' }}
|
style={{ height: '242px', width: '100%', minWidth: '100%' }}
|
||||||
notMerge={true}
|
notMerge={true}
|
||||||
lazyUpdate={true}
|
lazyUpdate={true}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</>
|
</Flex>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ const Habits = forwardRef<{ handleRefresh: () => void; }>((_props, ref) => {
|
|||||||
title={() => (<Space size={4}>
|
title={() => (<Space size={4}>
|
||||||
{t('implicitDetail.habits')}
|
{t('implicitDetail.habits')}
|
||||||
<Tooltip title={t('implicitDetail.habitsSubTitle')}>
|
<Tooltip title={t('implicitDetail.habitsSubTitle')}>
|
||||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/userMemory/question.svg')]"></div>
|
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/userMemory/question.svg')]"></div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Space>)}
|
</Space>)}
|
||||||
headerType="borderless"
|
headerType="borderless"
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 18:32:57
|
* @Date: 2026-02-03 18:32:57
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-02-03 18:32:57
|
* @Last Modified time: 2026-03-19 11:56:49
|
||||||
*/
|
*/
|
||||||
import { type FC, useMemo } from 'react'
|
import { type FC, useMemo } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import ReactEcharts from 'echarts-for-react'
|
import ReactEcharts from 'echarts-for-react'
|
||||||
|
import { Flex } from 'antd'
|
||||||
|
|
||||||
import Empty from '@/components/Empty'
|
import Empty from '@/components/Empty'
|
||||||
import Loading from '@/components/Empty/Loading'
|
import Loading from '@/components/Empty/Loading'
|
||||||
@@ -41,12 +42,12 @@ const InteractionBar: FC<InteractionBarProps> = ({ chartData, loading }) => {
|
|||||||
}, [chartData, t])
|
}, [chartData, t])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Flex vertical gap={16} className="rb-border rb:rounded-xl rb:p-4! rb:h-78">
|
||||||
<div>{t('userMemory.interaction')}</div>
|
<div className="rb:text-[#212332] rb:font-medium rb:leading-5">{t('userMemory.emotionLine')}</div>
|
||||||
{loading
|
{loading
|
||||||
? <Loading size={249} />
|
? <Loading size={249} />
|
||||||
: !chartData || chartData.length === 0
|
: !chartData || chartData.length === 0
|
||||||
? <Empty size={120} className="rb:mt-12 rb:mb-20.25" />
|
? <Empty size={120} className="rb:flex-1" />
|
||||||
: <ReactEcharts
|
: <ReactEcharts
|
||||||
option={{
|
option={{
|
||||||
color: Colors,
|
color: Colors,
|
||||||
@@ -128,10 +129,10 @@ const InteractionBar: FC<InteractionBarProps> = ({ chartData, loading }) => {
|
|||||||
},
|
},
|
||||||
series
|
series
|
||||||
}}
|
}}
|
||||||
style={{ height: '265px', width: '100%' }}
|
style={{ height: '242px', width: '100%', minWidth: '100%' }}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</>
|
</Flex>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState, forwardRef, useImperativeHandle, useMemo, useEffect } from 'react'
|
import { useState, forwardRef, useImperativeHandle, useMemo, useEffect } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useSearchParams } from 'react-router-dom'
|
import { useSearchParams, useNavigate } from 'react-router-dom'
|
||||||
import { Row, Col, Tabs, Space, Skeleton } from 'antd'
|
import { Row, Col, Flex, Space, Skeleton, Button } from 'antd'
|
||||||
|
|
||||||
import { getRelationshipEvolution, getTimelineMemories } from '@/api/memory'
|
import { getRelationshipEvolution, getTimelineMemories } from '@/api/memory'
|
||||||
import type { Node, GraphDetailRef } from '../types'
|
import type { Node, GraphDetailRef } from '../types'
|
||||||
@@ -11,7 +11,8 @@ import { formatDateTime } from '@/utils/format'
|
|||||||
import Tag from '@/components/Tag'
|
import Tag from '@/components/Tag'
|
||||||
import InteractionBar from '../components/InteractionBar'
|
import InteractionBar from '../components/InteractionBar'
|
||||||
import Empty from '@/components/Empty'
|
import Empty from '@/components/Empty'
|
||||||
import PageHeader from '../components/PageHeader'
|
import PageHeader from '@/components/Layout/PageHeader'
|
||||||
|
import BtnTabs from '@/components/BtnTabs'
|
||||||
|
|
||||||
export interface Emotion {
|
export interface Emotion {
|
||||||
emotion_intensity: number;
|
emotion_intensity: number;
|
||||||
@@ -36,6 +37,7 @@ interface Timeline {
|
|||||||
|
|
||||||
const GraphDetail = forwardRef<GraphDetailRef>((_props, ref) => {
|
const GraphDetail = forwardRef<GraphDetailRef>((_props, ref) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const navigate = useNavigate()
|
||||||
const [searchParams] = useSearchParams()
|
const [searchParams] = useSearchParams()
|
||||||
const [vo, setVo] = useState<Node | null>(null)
|
const [vo, setVo] = useState<Node | null>(null)
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
@@ -97,54 +99,75 @@ const GraphDetail = forwardRef<GraphDetailRef>((_props, ref) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHeader
|
<PageHeader
|
||||||
name={vo?.name}
|
title={vo?.name}
|
||||||
source="node"
|
extra={
|
||||||
|
<Space size={12}>
|
||||||
|
<Button
|
||||||
|
className="rb:px-2! rb:gap-0.5!"
|
||||||
|
icon={<div className="rb:size-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/common/return.svg')]"></div>}
|
||||||
|
onClick={() => navigate(-1)}
|
||||||
|
>
|
||||||
|
{t('common.return')}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<div className="rb:h-full rb:max-w-266 rb:mx-auto">
|
<Row gutter={12} className="rb:p-3! rb:pr-0! rb:h-[calc(100vh-64px)] rb:w-full! rb:flex-nowrap! rb:overflow-hidden!">
|
||||||
<div className="rb:text-[16px] rb:font-medium rb:leading-5.5 rb:mb-3">{t('userMemory.relationshipEvolution')}</div>
|
<Col flex="480px">
|
||||||
<RbCard>
|
<RbCard
|
||||||
<Row gutter={16}>
|
title={t('userMemory.relationshipEvolution')}
|
||||||
<Col span={12}>
|
headerType="borderless"
|
||||||
|
headerClassName="rb:min-h-[56px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||||
|
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-56px)] rb:overflow-y-auto!"
|
||||||
|
className="rb:h-[calc(100vh-88px)]!"
|
||||||
|
>
|
||||||
|
<Flex vertical gap={16}>
|
||||||
<EmotionLine chartData={emotionData} loading={loading} />
|
<EmotionLine chartData={emotionData} loading={loading} />
|
||||||
</Col>
|
|
||||||
<Col span={12}>
|
|
||||||
<InteractionBar chartData={interactionData} loading={loading} />
|
<InteractionBar chartData={interactionData} loading={loading} />
|
||||||
</Col>
|
</Flex>
|
||||||
</Row>
|
</RbCard>
|
||||||
</RbCard>
|
</Col>
|
||||||
|
<Col className="rb:w-[calc(100%-480px)]!">
|
||||||
<div className="rb:text-[16px] rb:font-medium rb:leading-5.5 rb:mb-3 rb:mt-6">{t('userMemory.timelineMemories')}</div>
|
<RbCard
|
||||||
<RbCard>
|
title={t('userMemory.timelineMemories')}
|
||||||
<Tabs
|
headerType="borderless"
|
||||||
activeKey={activeTab}
|
headerClassName="rb:min-h-[53px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||||
items={['timelines_memory', 'Statement', 'MemorySummary'].map(key => ({
|
bodyClassName="rb:p-3! rb:pt-0!"
|
||||||
label: t(`userMemory.${key}`),
|
className="rb:w-full!"
|
||||||
key
|
>
|
||||||
}))}
|
<BtnTabs
|
||||||
onChange={(key: string) => setActiveTab(key)}
|
className="rb:mb-4!"
|
||||||
/>
|
activeKey={activeTab}
|
||||||
{timelineLoading
|
items={['timelines_memory', 'Statement', 'MemorySummary'].map(key => ({
|
||||||
? <Skeleton active />
|
label: t(`userMemory.${key}`),
|
||||||
: !activeContent || activeContent.length === 0
|
key
|
||||||
? <Empty size={120} className="rb:mt-12 rb:mb-20.25" />
|
}))}
|
||||||
: <Space size={16} direction="vertical" className="rb:w-full">
|
onChange={(key: string) => setActiveTab(key)}
|
||||||
{activeContent.map((vo, index) => (
|
/>
|
||||||
<RbCard
|
<div className="rb:h-[calc(100vh-193px)] rb:overflow-y-auto">
|
||||||
key={index}
|
{timelineLoading
|
||||||
headerType="borderL"
|
? <Skeleton active />
|
||||||
headerClassName="rb:before:bg-[#155EEF]!"
|
: !activeContent || activeContent.length === 0
|
||||||
title={vo.text}
|
? <Empty size={120} className="rb:mt-12 rb:mb-20.25" />
|
||||||
>
|
: <Flex gap={12} vertical>
|
||||||
<div className="rb:text-[#A8A9AA] rb:text-[12px] rb:leading-4">{formatDateTime(vo.created_at)}</div>
|
{activeContent.map((vo, index) => (
|
||||||
<Tag className="rb:mt-2">{vo.type}</Tag>
|
<div
|
||||||
</RbCard>
|
key={index}
|
||||||
))}
|
className="rb-border rb:rounded-xl rb:p-3"
|
||||||
</Space>
|
>
|
||||||
}
|
<Flex align="center" justify="space-between">
|
||||||
|
<div className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4.5">{formatDateTime(vo.created_at)}</div>
|
||||||
|
<Tag>{vo.type}</Tag>
|
||||||
</RbCard>
|
</Flex>
|
||||||
</div>
|
<div className="rb:mt-3 rb:leading-5 rb:break-all">{vo.text}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</RbCard>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ const ShortTermDetail: FC = () => {
|
|||||||
title={() => (<Space size={4}>
|
title={() => (<Space size={4}>
|
||||||
{t('shortTermDetail.shortTermTitle')}
|
{t('shortTermDetail.shortTermTitle')}
|
||||||
<Tooltip title={t('shortTermDetail.shortTermSubTitle')}>
|
<Tooltip title={t('shortTermDetail.shortTermSubTitle')}>
|
||||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/userMemory/question.svg')]"></div>
|
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/userMemory/question.svg')]"></div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Space>)}
|
</Space>)}
|
||||||
headerType="borderless"
|
headerType="borderless"
|
||||||
@@ -194,7 +194,7 @@ const ShortTermDetail: FC = () => {
|
|||||||
title={() => (<Space size={4}>
|
title={() => (<Space size={4}>
|
||||||
{t('shortTermDetail.longTermTitle')}
|
{t('shortTermDetail.longTermTitle')}
|
||||||
<Tooltip title={t('shortTermDetail.longTermTitleSubTitle')}>
|
<Tooltip title={t('shortTermDetail.longTermTitleSubTitle')}>
|
||||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/userMemory/question.svg')]"></div>
|
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/userMemory/question.svg')]"></div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Space>)}
|
</Space>)}
|
||||||
headerType="borderless"
|
headerType="borderless"
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ const AddNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
|||||||
'rb:border-[#d1d5db] rb:bg-[#FCFCFD] rb:text-[#374151]': !data.isSelected
|
'rb:border-[#d1d5db] rb:bg-[#FCFCFD] rb:text-[#374151]': !data.isSelected
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/workflow/node_plus.png')]"></div>
|
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/workflow/node_plus.png')]"></div>
|
||||||
{data.label}
|
{data.label}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const NodeTools: FC<{ node: Node }> = ({
|
|||||||
<Dropdown
|
<Dropdown
|
||||||
menu={{
|
menu={{
|
||||||
items: [
|
items: [
|
||||||
{ key: 'delete', icon: <div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/common/delete_dark.svg')]"></div>, label: <Flex>{t('common.delete')}</Flex>},
|
{ key: 'delete', icon: <div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/delete_dark.svg')]"></div>, label: <Flex>{t('common.delete')}</Flex>},
|
||||||
// { key: 'copy', icon: <div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/copy_dark.svg')]"></div>, label: t('common.copy') }
|
// { key: 'copy', icon: <div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/copy_dark.svg')]"></div>, label: t('common.copy') }
|
||||||
],
|
],
|
||||||
onClick: handleClick
|
onClick: handleClick
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ const CaseList: FC<CaseListProps> = ({
|
|||||||
<Form.Item name={[caseField.name, 'logical_operator']} noStyle >
|
<Form.Item name={[caseField.name, 'logical_operator']} noStyle >
|
||||||
<Space size={2} className="rb:cursor-pointer rb:text-[#155EEF] rb:leading-4.5 rb:font-medium rb-border rb:py-px! rb:px-1! rb:rounded-sm" onClick={() => handleChangeLogicalOperator(caseIndex)}>
|
<Space size={2} className="rb:cursor-pointer rb:text-[#155EEF] rb:leading-4.5 rb:font-medium rb-border rb:py-px! rb:px-1! rb:rounded-sm" onClick={() => handleChangeLogicalOperator(caseIndex)}>
|
||||||
{logicalOperator}
|
{logicalOperator}
|
||||||
<div className="rb:size-3 rb:bg-cover rb:bg-[url('src/assets/images/workflow/refresh_active.svg')]"></div>
|
<div className="rb:size-3 rb:bg-cover rb:bg-[url('@/assets/images/workflow/refresh_active.svg')]"></div>
|
||||||
</Space>
|
</Space>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ const ConditionList: FC<CaseListProps> = ({
|
|||||||
<Form.Item name={[parentName, 'logical_operator']} noStyle >
|
<Form.Item name={[parentName, 'logical_operator']} noStyle >
|
||||||
<Space size={2} className="rb:cursor-pointer rb:text-[#155EEF] rb:leading-4.5 rb:font-medium rb-border rb:py-px! rb:px-1! rb:rounded-sm" onClick={handleChangeLogicalOperator}>
|
<Space size={2} className="rb:cursor-pointer rb:text-[#155EEF] rb:leading-4.5 rb:font-medium rb-border rb:py-px! rb:px-1! rb:rounded-sm" onClick={handleChangeLogicalOperator}>
|
||||||
{logicalOperator}
|
{logicalOperator}
|
||||||
<div className="rb:size-3 rb:bg-cover rb:bg-[url('src/assets/images/workflow/refresh_active.svg')]"></div>
|
<div className="rb:size-3 rb:bg-cover rb:bg-[url('@/assets/images/workflow/refresh_active.svg')]"></div>
|
||||||
</Space>
|
</Space>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -434,7 +434,7 @@ const Properties: FC<PropertiesProps> = ({
|
|||||||
<Dropdown
|
<Dropdown
|
||||||
menu={{
|
menu={{
|
||||||
items: [
|
items: [
|
||||||
{ key: 'delete', icon: <div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/common/delete_dark.svg')]"></div>, label: <Flex>{t('common.delete')}</Flex> },
|
{ key: 'delete', icon: <div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/delete_dark.svg')]"></div>, label: <Flex>{t('common.delete')}</Flex> },
|
||||||
// { key: 'copy', icon: <div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/copy_dark.svg')]"></div>, label: t('common.copy') }
|
// { key: 'copy', icon: <div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/copy_dark.svg')]"></div>, label: t('common.copy') }
|
||||||
],
|
],
|
||||||
onClick: handleClick
|
onClick: handleClick
|
||||||
@@ -834,7 +834,7 @@ const Properties: FC<PropertiesProps> = ({
|
|||||||
<Flex align="center" className="rb:font-medium rb:cursor-pointer" onClick={handleToggle}>
|
<Flex align="center" className="rb:font-medium rb:cursor-pointer" onClick={handleToggle}>
|
||||||
{t('workflow.config.output')}
|
{t('workflow.config.output')}
|
||||||
<div
|
<div
|
||||||
className={clsx("rb:size-3 rb:bg-cover rb:bg-[url('src/assets/images/common/caret_right_outlined.svg')]", {
|
className={clsx("rb:size-3 rb:bg-cover rb:bg-[url('@/assets/images/common/caret_right_outlined.svg')]", {
|
||||||
'rb:rotate-90': !outputCollapsed
|
'rb:rotate-90': !outputCollapsed
|
||||||
})}
|
})}
|
||||||
></div>
|
></div>
|
||||||
|
|||||||