dsh-data-domain-knowledge 0.1.0-alpha.13 → 0.1.0-alpha.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -56
- package/cordis.patch.yml +36 -129
- package/eval/benchmark-extraction-format.mjs +20 -0
- package/lib/client.js +3262 -4142
- package/lib/doc-page.js +1 -1
- package/lib/pages.js +1147 -364
- package/lib/types/axis-registry.d.ts +8 -1
- package/lib/types/axis-registry.d.ts.map +1 -1
- package/lib/types/axis-registry.js +62 -7
- package/lib/types/axis-registry.js.map +1 -1
- package/lib/types/convert/host.d.ts.map +1 -1
- package/lib/types/convert/host.js +3 -0
- package/lib/types/convert/host.js.map +1 -1
- package/lib/types/convert/ingest.d.ts +9 -0
- package/lib/types/convert/ingest.d.ts.map +1 -1
- package/lib/types/convert/ingest.js +68 -9
- package/lib/types/convert/ingest.js.map +1 -1
- package/lib/types/diagnosis/cards.d.ts +7 -3
- package/lib/types/diagnosis/cards.d.ts.map +1 -1
- package/lib/types/diagnosis/cards.js +13 -8
- package/lib/types/diagnosis/cards.js.map +1 -1
- package/lib/types/diagnosis/run.d.ts +4 -13
- package/lib/types/diagnosis/run.d.ts.map +1 -1
- package/lib/types/diagnosis/run.js +26 -16
- package/lib/types/diagnosis/run.js.map +1 -1
- package/lib/types/diagnosis/schema.js +2 -2
- package/lib/types/diagnosis/schema.js.map +1 -1
- package/lib/types/diagnosis/seed-source.d.ts +1 -1
- package/lib/types/diagnosis/seed-source.d.ts.map +1 -1
- package/lib/types/diagnosis/seed-source.js +5 -4
- package/lib/types/diagnosis/seed-source.js.map +1 -1
- package/lib/types/diagnosis/seed.d.ts +4 -4
- package/lib/types/diagnosis/seed.d.ts.map +1 -1
- package/lib/types/diagnosis/seed.js +6 -8
- package/lib/types/diagnosis/seed.js.map +1 -1
- package/lib/types/diagnosis/store.d.ts +18 -17
- package/lib/types/diagnosis/store.d.ts.map +1 -1
- package/lib/types/diagnosis/store.js +94 -66
- package/lib/types/diagnosis/store.js.map +1 -1
- package/lib/types/diagnosis/types.d.ts +10 -16
- package/lib/types/diagnosis/types.d.ts.map +1 -1
- package/lib/types/diagnosis/types.js.map +1 -1
- package/lib/types/environment/dsh-python.d.ts +77 -0
- package/lib/types/environment/dsh-python.d.ts.map +1 -0
- package/lib/types/environment/dsh-python.js +139 -0
- package/lib/types/environment/dsh-python.js.map +1 -0
- package/lib/types/environment/install.d.ts +9 -1
- package/lib/types/environment/install.d.ts.map +1 -1
- package/lib/types/environment/install.js +149 -24
- package/lib/types/environment/install.js.map +1 -1
- package/lib/types/environment/model-catalog.d.ts +34 -2
- package/lib/types/environment/model-catalog.d.ts.map +1 -1
- package/lib/types/environment/model-catalog.js +40 -2
- package/lib/types/environment/model-catalog.js.map +1 -1
- package/lib/types/environment/service.d.ts +13 -3
- package/lib/types/environment/service.d.ts.map +1 -1
- package/lib/types/environment/service.js +127 -23
- package/lib/types/environment/service.js.map +1 -1
- package/lib/types/environment/types.d.ts +9 -0
- package/lib/types/environment/types.d.ts.map +1 -1
- package/lib/types/events.d.ts +2 -0
- package/lib/types/events.d.ts.map +1 -1
- package/lib/types/events.js +13 -0
- package/lib/types/events.js.map +1 -1
- package/lib/types/extract-contract.d.ts +1 -1
- package/lib/types/extract-contract.d.ts.map +1 -1
- package/lib/types/extract-contract.js +34 -31
- package/lib/types/extract-contract.js.map +1 -1
- package/lib/types/extract-model.d.ts +2 -0
- package/lib/types/extract-model.d.ts.map +1 -1
- package/lib/types/extract-model.js.map +1 -1
- package/lib/types/extract-table-contract.d.ts +3 -0
- package/lib/types/extract-table-contract.d.ts.map +1 -0
- package/lib/types/extract-table-contract.js +30 -0
- package/lib/types/extract-table-contract.js.map +1 -0
- package/lib/types/extract-table.d.ts +8 -0
- package/lib/types/extract-table.d.ts.map +1 -0
- package/lib/types/extract-table.js +151 -0
- package/lib/types/extract-table.js.map +1 -0
- package/lib/types/extraction-runs.d.ts +30 -6
- package/lib/types/extraction-runs.d.ts.map +1 -1
- package/lib/types/extraction-runs.js +69 -8
- package/lib/types/extraction-runs.js.map +1 -1
- package/lib/types/fs-atomic.d.ts +0 -7
- package/lib/types/fs-atomic.d.ts.map +1 -1
- package/lib/types/fs-atomic.js +17 -2
- package/lib/types/fs-atomic.js.map +1 -1
- package/lib/types/images.d.ts +1 -1
- package/lib/types/images.d.ts.map +1 -1
- package/lib/types/images.js +2 -2
- package/lib/types/images.js.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +232 -50
- package/lib/types/index.js.map +1 -1
- package/lib/types/intent/scope.d.ts.map +1 -1
- package/lib/types/intent/scope.js +1 -0
- package/lib/types/intent/scope.js.map +1 -1
- package/lib/types/intent/tools.d.ts +19 -0
- package/lib/types/intent/tools.d.ts.map +1 -1
- package/lib/types/intent/tools.js +37 -1
- package/lib/types/intent/tools.js.map +1 -1
- package/lib/types/knowledge-bases.d.ts.map +1 -1
- package/lib/types/knowledge-bases.js +5 -16
- package/lib/types/knowledge-bases.js.map +1 -1
- package/lib/types/knowledge.d.ts +3 -0
- package/lib/types/knowledge.d.ts.map +1 -1
- package/lib/types/knowledge.js +21 -5
- package/lib/types/knowledge.js.map +1 -1
- package/lib/types/materialize-snapshot.d.ts +49 -0
- package/lib/types/materialize-snapshot.d.ts.map +1 -0
- package/lib/types/materialize-snapshot.js +2 -0
- package/lib/types/materialize-snapshot.js.map +1 -0
- package/lib/types/model-text.d.ts +1 -1
- package/lib/types/model-text.d.ts.map +1 -1
- package/lib/types/model-text.js +5 -4
- package/lib/types/model-text.js.map +1 -1
- package/lib/types/oplog.d.ts.map +1 -1
- package/lib/types/oplog.js +7 -0
- package/lib/types/oplog.js.map +1 -1
- package/lib/types/pipeline/engine.d.ts +60 -0
- package/lib/types/pipeline/engine.d.ts.map +1 -0
- package/lib/types/pipeline/engine.js +338 -0
- package/lib/types/pipeline/engine.js.map +1 -0
- package/lib/types/pipeline/store.d.ts +73 -0
- package/lib/types/pipeline/store.d.ts.map +1 -0
- package/lib/types/pipeline/store.js +143 -0
- package/lib/types/pipeline/store.js.map +1 -0
- package/lib/types/pipeline/types.d.ts +101 -0
- package/lib/types/pipeline/types.d.ts.map +1 -0
- package/lib/types/pipeline/types.js +5 -0
- package/lib/types/pipeline/types.js.map +1 -0
- package/lib/types/present.d.ts +2 -0
- package/lib/types/present.d.ts.map +1 -1
- package/lib/types/present.js +9 -4
- package/lib/types/present.js.map +1 -1
- package/lib/types/retention.d.ts +39 -0
- package/lib/types/retention.d.ts.map +1 -0
- package/lib/types/retention.js +42 -0
- package/lib/types/retention.js.map +1 -0
- package/lib/types/runtime.d.ts +115 -5
- package/lib/types/runtime.d.ts.map +1 -1
- package/lib/types/runtime.js +862 -132
- package/lib/types/runtime.js.map +1 -1
- package/lib/types/source-evidence.d.ts +9 -1
- package/lib/types/source-evidence.d.ts.map +1 -1
- package/lib/types/source-evidence.js +13 -5
- package/lib/types/source-evidence.js.map +1 -1
- package/lib/types/store/axis-references.js +3 -3
- package/lib/types/store/axis-references.js.map +1 -1
- package/lib/types/store/derived.d.ts +1 -1
- package/lib/types/store/derived.d.ts.map +1 -1
- package/lib/types/store/derived.js +41 -7
- package/lib/types/store/derived.js.map +1 -1
- package/lib/types/store/knowledge-db.d.ts +18 -0
- package/lib/types/store/knowledge-db.d.ts.map +1 -1
- package/lib/types/store/knowledge-db.js +111 -6
- package/lib/types/store/knowledge-db.js.map +1 -1
- package/lib/types/store/migrate.js +1 -1
- package/lib/types/store/migrate.js.map +1 -1
- package/lib/types/trajectory-types.d.ts +172 -0
- package/lib/types/trajectory-types.d.ts.map +1 -0
- package/lib/types/trajectory-types.js +36 -0
- package/lib/types/trajectory-types.js.map +1 -0
- package/lib/types/types.d.ts +3 -4
- package/lib/types/types.d.ts.map +1 -1
- package/lib/types/types.js.map +1 -1
- package/lib/types/wiki-finalize.d.ts +16 -0
- package/lib/types/wiki-finalize.d.ts.map +1 -1
- package/lib/types/wiki-finalize.js +26 -0
- package/lib/types/wiki-finalize.js.map +1 -1
- package/lib/types/wiki-materialize.d.ts.map +1 -1
- package/lib/types/wiki-materialize.js +3 -15
- package/lib/types/wiki-materialize.js.map +1 -1
- package/lib/types/wiki-trial-types.d.ts +3 -0
- package/lib/types/wiki-trial-types.d.ts.map +1 -1
- package/lib/types/wiki-trial.d.ts +2 -0
- package/lib/types/wiki-trial.d.ts.map +1 -1
- package/lib/types/wiki-trial.js +31 -7
- package/lib/types/wiki-trial.js.map +1 -1
- package/package.json +6 -3
- package/preset/tita-data-agent/agent.cordis.yml +36 -129
- package/src/axis-registry.ts +57 -9
- package/src/client/AttributionEventGuide.tsx +10 -9
- package/src/client/CompileDialogs.tsx +10 -2
- package/src/client/EnvironmentSetup.tsx +76 -16
- package/src/client/ExpansionGraph.tsx +13 -7
- package/src/client/ExtractionTasksPage.tsx +543 -156
- package/src/client/ImportFilesDialog.tsx +2 -13
- package/src/client/IntentTab.tsx +3 -1
- package/src/client/KnowledgeBaseTab.tsx +139 -122
- package/src/client/KnowledgeLayerSection.tsx +19 -2
- package/src/client/KnowledgePanel.tsx +17 -3
- package/src/client/ListPager.tsx +15 -5
- package/src/client/MaterializeTrajectoryView.tsx +124 -0
- package/src/client/NodeSettings.tsx +90 -25
- package/src/client/NormalizeTrajectoryView.tsx +136 -0
- package/src/client/PipelineNotice.tsx +26 -0
- package/src/client/RecallPanel.tsx +55 -25
- package/src/client/TabGuide.tsx +4 -4
- package/src/client/TrialReportView.tsx +61 -16
- package/src/client/TypeDefinitionDrawer.tsx +33 -9
- package/src/client/WikiCardPreview.tsx +43 -10
- package/src/client/WikiFlowPanel.tsx +4 -4
- package/src/client/architecture.tsx +1 -1
- package/src/client/attribution/AttributionTab.tsx +37 -36
- package/src/client/attribution/CaseView.tsx +3 -1
- package/src/client/attribution/EventView.tsx +14 -4
- package/src/client/attribution/RunView.tsx +2 -2
- package/src/client/attribution/ViewSwitch.tsx +20 -5
- package/src/client/attribution/graph-options.ts +38 -31
- package/src/client/attribution/model.ts +16 -9
- package/src/client/graph/palette.ts +165 -0
- package/src/client/pages.css +224 -28
- package/src/client/pages.tsx +33 -11
- package/src/client/styles.css +61 -6
- package/src/client/wiki-trial.ts +30 -1
- package/src/convert/host.ts +3 -0
- package/src/convert/ingest.ts +73 -9
- package/src/diagnosis/cards.ts +13 -8
- package/src/diagnosis/run.ts +27 -17
- package/src/diagnosis/schema.ts +2 -2
- package/src/diagnosis/seed-source.ts +5 -4
- package/src/diagnosis/seed.ts +6 -8
- package/src/diagnosis/store.ts +99 -69
- package/src/diagnosis/types.ts +10 -16
- package/src/environment/dsh-python.ts +156 -0
- package/src/environment/install.ts +134 -19
- package/src/environment/model-catalog.ts +45 -3
- package/src/environment/service.ts +111 -23
- package/src/environment/types.ts +6 -0
- package/src/events.ts +12 -0
- package/src/extract-contract.ts +6 -3
- package/src/extract-model.ts +2 -0
- package/src/extract-table-contract.ts +29 -0
- package/src/extract-table.ts +126 -0
- package/src/extraction-runs.ts +70 -11
- package/src/fs-atomic.ts +19 -2
- package/src/images.ts +2 -2
- package/src/index.ts +207 -72
- package/src/intent/scope.ts +1 -0
- package/src/intent/tools.ts +38 -1
- package/src/knowledge-bases.ts +4 -12
- package/src/knowledge.ts +24 -4
- package/src/materialize-snapshot.ts +46 -0
- package/src/model-text.ts +5 -3
- package/src/oplog.ts +7 -0
- package/src/pipeline/engine.ts +312 -0
- package/src/pipeline/store.ts +147 -0
- package/src/pipeline/types.ts +92 -0
- package/src/present.ts +10 -4
- package/src/retention.ts +76 -0
- package/src/runtime.ts +853 -131
- package/src/source-evidence.ts +12 -5
- package/src/store/axis-references.ts +3 -3
- package/src/store/derived.ts +40 -7
- package/src/store/knowledge-db.ts +111 -5
- package/src/store/migrate.ts +1 -1
- package/src/trajectory-types.ts +142 -0
- package/src/types.ts +3 -4
- package/src/wiki-finalize.ts +28 -0
- package/src/wiki-materialize.ts +3 -14
- package/src/wiki-trial-types.ts +3 -0
- package/src/wiki-trial.ts +26 -7
- package/src/client/convert/ConvertPanel.tsx +0 -583
- package/src/client/convert/styles.css +0 -138
- package/src/client/convert/styles.ts +0 -49
|
@@ -6,7 +6,7 @@ import type { ReactNode } from 'react'
|
|
|
6
6
|
/**
|
|
7
7
|
* 智能归因的 Event 说明页。
|
|
8
8
|
*
|
|
9
|
-
* 这页解释 Document 如何并行提取 Knowledge 与 Event
|
|
9
|
+
* 这页解释 Document 如何并行提取 Knowledge 与 Event,以及 Knowledge 卡片如何引用 Event。
|
|
10
10
|
* Event 记录一次具体发生;坐标负责定位问题域。把这件事放在整页里,是因为它需要同时讲关系、例子和边界,
|
|
11
11
|
* 不能压缩成侧栏里的 tooltip。
|
|
12
12
|
*/
|
|
@@ -19,12 +19,13 @@ export function AttributionEventGuide(): ReactNode {
|
|
|
19
19
|
<h2>一份文档,如何得到 Knowledge 与 Event</h2>
|
|
20
20
|
<p>
|
|
21
21
|
同一份 Document 并行提取两类内容:Knowledge 保存可复用的事实与方法;Event 保存一次具体发生、
|
|
22
|
-
它的时间线、证据和结果。两者都通过 Object × Action × Scene
|
|
22
|
+
它的时间线、证据和结果。两者都通过 Object × Action × Scene 归一;WikiCard 由 Knowledge 组织生成,
|
|
23
|
+
并用坐标引用相关 Event。
|
|
23
24
|
</p>
|
|
24
25
|
</div>
|
|
25
26
|
<div className="attributionGuideFormula" aria-label="核心关系">
|
|
26
27
|
<span>核心关系</span>
|
|
27
|
-
<code>Document → {`{ Knowledge[], Event[] }`} → WikiCard</code>
|
|
28
|
+
<code>Document → {`{ Knowledge[], Event[] }`} → Knowledge → WikiCard → Event refs</code>
|
|
28
29
|
</div>
|
|
29
30
|
</header>
|
|
30
31
|
|
|
@@ -32,18 +33,18 @@ export function AttributionEventGuide(): ReactNode {
|
|
|
32
33
|
<div className="attributionGuideSectionHead">
|
|
33
34
|
<p className="attributionGuideKicker">先看关系</p>
|
|
34
35
|
<h3 id="attribution-event-map-title">同一份文档,并行产出两种信息</h3>
|
|
35
|
-
<p>Document 保留原始证据;Knowledge 与 Event
|
|
36
|
+
<p>Document 保留原始证据;Knowledge 与 Event 是并列事实。WikiCard 组织 Knowledge,并按坐标引用 Event。</p>
|
|
36
37
|
</div>
|
|
37
38
|
|
|
38
|
-
<div className="attributionGuidePipeline" role="img" aria-label="Document 并行提取 Knowledge 和 Event
|
|
39
|
+
<div className="attributionGuidePipeline" role="img" aria-label="Document 并行提取 Knowledge 和 Event;Knowledge 按坐标生成 WikiCard,Event 按坐标建立引用">
|
|
39
40
|
<GuideNode tone="source" icon={<FileText size={17} />} label="Document" title="原始记录" detail="复盘、工单、聊天、日志说明" />
|
|
40
41
|
<GuideConnector label="并行抽取" />
|
|
41
42
|
<div className="attributionGuideBranches">
|
|
42
43
|
<GuideNode tone="knowledge" icon={<Lightbulb size={17} />} label="Knowledge" title="知识与方法" detail="可脱离本次事件复用" />
|
|
43
44
|
<GuideNode tone="event" icon={<CircleDot size={17} />} label="Event" title="一次具体发生" detail="时间线、证据、结果与缺项" />
|
|
44
45
|
</div>
|
|
45
|
-
<GuideConnector label="
|
|
46
|
-
<GuideNode tone="card" icon={<GitBranch size={17} />} label="WikiCard" title="
|
|
46
|
+
<GuideConnector label="Knowledge 成卡;Event 引用" />
|
|
47
|
+
<GuideNode tone="card" icon={<GitBranch size={17} />} label="WikiCard" title="知识组织页" detail="组织 Knowledge,链接同坐标 Event" />
|
|
47
48
|
</div>
|
|
48
49
|
|
|
49
50
|
<div className="attributionGuideRelations" aria-label="补充关系">
|
|
@@ -120,9 +121,9 @@ export function AttributionEventGuide(): ReactNode {
|
|
|
120
121
|
<h3 id="attribution-event-memory-title">Event 记录经历,Knowledge 保存可复用判断</h3>
|
|
121
122
|
<p>
|
|
122
123
|
多个 Event 可以成为总结 Knowledge 的证据,但提炼需要单独验证,不能因相似就自动合并。
|
|
123
|
-
Agent 按坐标找到 WikiCard
|
|
124
|
+
Agent 按坐标找到 WikiCard 后,可以读取可复用 Knowledge,并用 `get_knowledge_events` 沿卡片引用查看历史 Event;Event 可补全后续复盘文档。
|
|
124
125
|
</p>
|
|
125
|
-
<p className="attributionGuideClosingRule"><strong>一句话:</strong>Document 同时抽 Knowledge 与 Event
|
|
126
|
+
<p className="attributionGuideClosingRule"><strong>一句话:</strong>Document 同时抽 Knowledge 与 Event;Knowledge 生成 WikiCard,Event 按坐标被引用并独立保存。</p>
|
|
126
127
|
</div>
|
|
127
128
|
</section>
|
|
128
129
|
</article>
|
|
@@ -121,7 +121,15 @@ function elapsed(from: string, to: number): string {
|
|
|
121
121
|
* 条形只是让人一眼看出「大概到哪了」,精确的账在文字里。没有这一行文字,那条按阶段均分
|
|
122
122
|
* 的进度条就会被当成精确值,而在「抽取」这一段特别慢的库里它会显得长期不动。
|
|
123
123
|
*/
|
|
124
|
-
|
|
124
|
+
/**
|
|
125
|
+
* 编译进度 → 0..1 的比例。**这是唯一一份**(0070)。
|
|
126
|
+
*
|
|
127
|
+
* 曾经有两个副本,而它们对「已结束」的处理不一致:一个只要 `finishedAt` 存在就返回
|
|
128
|
+
* 满格(把 failed / cancelled 也画成「完成」),另一个排除了这两种状态。同一个失败在
|
|
129
|
+
* 导入对话框里是满格主色、在编译对话框里是红色未完成 —— 两屏说两件事。
|
|
130
|
+
* 所以导出它,让两个消费者用同一份判断。
|
|
131
|
+
*/
|
|
132
|
+
export function compileRatio(progress: CompileProgressView): number {
|
|
125
133
|
if (progress.finishedAt !== undefined && progress.state !== 'cancelled' && progress.state !== 'failed') return 1
|
|
126
134
|
const total = progress.steps.length || 1
|
|
127
135
|
const done = progress.steps.filter(step => step.state === 'done').length
|
|
@@ -168,7 +176,7 @@ export function CompileProgressDialog({ open, onOpenChange, progress, mine, queu
|
|
|
168
176
|
const completed = done && progress?.state !== 'cancelled' && progress?.state !== 'failed'
|
|
169
177
|
const stopped = progress?.state === 'cancelled'
|
|
170
178
|
const failed = progress?.state === 'failed'
|
|
171
|
-
const ratio = progress === null ? 0 :
|
|
179
|
+
const ratio = progress === null ? 0 : compileRatio(progress)
|
|
172
180
|
const doneSteps = progress?.steps.filter(step => step.state === 'done').length ?? 0
|
|
173
181
|
const finishedText = progress?.outcome
|
|
174
182
|
?? (progress === null ? (queued === true ? '排在前面那一次编译之后,轮到它就会开始。' : '正在建立编译任务…') : '编译结束。')
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState, type ReactNode } from 'react'
|
|
2
2
|
import { Button, cn, Select, SelectContent, SelectItem, SelectLabel, SelectGroup, SelectTrigger, SelectValue } from '@tita-agent/ui/components'
|
|
3
3
|
import { AlertCircle, Check, ChevronDown, Download, LoaderCircle, RefreshCw } from '@tita-agent/ui/icons'
|
|
4
|
-
import type
|
|
5
|
-
import type { EnvironmentView } from '../environment/types.js'
|
|
4
|
+
import { downloadBytes, formatBytes, type ModelSelection, type ModelOptionView } from '../environment/model-catalog.js'
|
|
5
|
+
import type { EnvironmentCurrentModel, EnvironmentView } from '../environment/types.js'
|
|
6
6
|
|
|
7
7
|
async function environmentRequest(init?: RequestInit): Promise<EnvironmentView> {
|
|
8
8
|
const response = await fetch(init ? '/knowledge/environment/prepare' : '/knowledge/environment', init)
|
|
@@ -41,42 +41,91 @@ export function useKnowledgeEnvironment(visible: boolean, revision: number) {
|
|
|
41
41
|
|
|
42
42
|
type EnvironmentController = ReturnType<typeof useKnowledgeEnvironment>
|
|
43
43
|
|
|
44
|
-
function ModelSelect({ id, label, value, options, disabled, onChange }: {
|
|
44
|
+
function ModelSelect({ id, label, value, options, currentModel, disabled, onChange }: {
|
|
45
45
|
id: string
|
|
46
46
|
label: string
|
|
47
47
|
value: string
|
|
48
48
|
options: ModelOptionView[]
|
|
49
|
+
currentModel: EnvironmentCurrentModel
|
|
49
50
|
disabled: boolean
|
|
50
51
|
onChange: (value: string) => void
|
|
51
52
|
}): ReactNode {
|
|
52
53
|
const chosen = options.find(option => option.id === value)
|
|
53
|
-
const descriptionId = `${id}-description`
|
|
54
54
|
return <div className="grid min-w-0 gap-1.5">
|
|
55
55
|
<label htmlFor={id} className="text-xs font-medium text-tita-ink">{label}</label>
|
|
56
56
|
<Select value={value} onValueChange={onChange} disabled={disabled}>
|
|
57
|
-
<SelectTrigger id={id}
|
|
57
|
+
<SelectTrigger id={id} className="w-full"><SelectValue>{chosen?.label ?? '请选择模型'}</SelectValue></SelectTrigger>
|
|
58
58
|
<SelectContent position="popper" align="start" className="max-h-64">
|
|
59
59
|
<SelectGroup>
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
{
|
|
60
|
+
{!currentModel.id && <>
|
|
61
|
+
<SelectLabel>当前运行</SelectLabel>
|
|
62
|
+
<SelectItem value={`${id}-current`} disabled className="h-auto items-start py-1.5">
|
|
63
|
+
{currentModel.state === 'active' ? `当前使用:${currentModel.label}` : '当前未启用'}
|
|
64
|
+
</SelectItem>
|
|
65
|
+
</>}
|
|
66
|
+
<SelectLabel>模型选项 · 按资源占用从低到高</SelectLabel>
|
|
67
|
+
{options.map(option => <SelectItem key={option.id} value={option.id} className="h-auto items-start py-2">
|
|
68
|
+
<span className="flex min-w-0 flex-1 flex-col gap-0.5">
|
|
69
|
+
<span className="flex min-w-0 items-center gap-2">
|
|
70
|
+
<span className="min-w-0 flex-1 truncate font-medium">{option.label}</span>
|
|
71
|
+
{/* 下载状态:不知道就不标(服务端没给资源目录时 `installed` 是 undefined)。 */}
|
|
72
|
+
{option.installed === true && <span className="shrink-0 rounded-md border border-tita-tone-green-line bg-tita-tone-green-tint px-1.5 py-0.5 text-[10px] font-medium leading-none text-tita-tone-green">已下载</span>}
|
|
73
|
+
{option.installed === false && <span className="shrink-0 rounded-md border border-tita-line bg-tita-surface-muted px-1.5 py-0.5 text-[10px] font-medium leading-none text-tita-ink-muted">需下载</span>}
|
|
74
|
+
{option.id === currentModel.id && <span className="shrink-0 rounded-md border border-tita-line bg-tita-surface-muted px-1.5 py-0.5 text-[10px] font-medium leading-none text-tita-ink">当前使用</span>}
|
|
75
|
+
</span>
|
|
76
|
+
<span className="line-clamp-2 text-[11px] leading-snug text-tita-ink-muted">
|
|
77
|
+
{option.download}{option.dimension ? ` · ${option.dimension} 维` : ''} · {option.description}
|
|
78
|
+
</span>
|
|
79
|
+
</span>
|
|
63
80
|
</SelectItem>)}
|
|
64
81
|
</SelectGroup>
|
|
65
82
|
</SelectContent>
|
|
66
83
|
</Select>
|
|
67
|
-
<p id={descriptionId} className="m-0 text-xs leading-relaxed text-tita-ink-muted">
|
|
68
|
-
{chosen ? `${chosen.description} 下载约 ${chosen.download}${chosen.dimension ? `,输出 ${chosen.dimension} 维` : ''}。` : '请选择模型。'}
|
|
69
|
-
</p>
|
|
70
84
|
{chosen?.modelCardUrl && <a href={chosen.modelCardUrl} target="_blank" rel="noreferrer" className="w-fit text-xs text-tita-ink underline underline-offset-2">查看模型卡与许可</a>}
|
|
71
85
|
</div>
|
|
72
86
|
}
|
|
73
87
|
|
|
88
|
+
/**
|
|
89
|
+
* 这次点「安装」会下多少。
|
|
90
|
+
*
|
|
91
|
+
* 模型列表里每个选项自己标了「已下载 / 需下载」,但人真正要判断的是**这一次的总量**:
|
|
92
|
+
* 两个模型都可能已下载(那就只是补依赖 + 自检),也可能只差一个。所以把所选的两个加起来,
|
|
93
|
+
* 已下载的不重复计 —— 已下载的模型不会重新下载(HF 缓存 + 目标目录都在)。
|
|
94
|
+
*/
|
|
95
|
+
function DownloadSummary({ embedding, rerank, chosen }: { embedding: ModelOptionView[]; rerank: ModelOptionView[]; chosen: ModelSelection }): ReactNode {
|
|
96
|
+
const pick = (options: ModelOptionView[], id: string): ModelOptionView | undefined => options.find(option => option.id === id)
|
|
97
|
+
const pending = [pick(embedding, chosen.embedding), pick(rerank, chosen.rerank)]
|
|
98
|
+
.filter((option): option is ModelOptionView => option !== undefined && option.installed === false)
|
|
99
|
+
if (pending.length === 0) {
|
|
100
|
+
return <p className="m-0 text-xs leading-relaxed text-tita-ink-muted" role="status">
|
|
101
|
+
{pick(embedding, chosen.embedding)?.installed === true && pick(rerank, chosen.rerank)?.installed === true
|
|
102
|
+
? '所选模型都已下载,安装只需补齐推理依赖并重新自检。'
|
|
103
|
+
: '无法读取模型下载状态,安装会按需要补齐。'}
|
|
104
|
+
</p>
|
|
105
|
+
}
|
|
106
|
+
const bytes = pending.reduce((sum, option) => sum + (downloadBytes(option.download) ?? 0), 0)
|
|
107
|
+
// 两个以上才报合计:一个模型时合计与它自己那句是同一个数,纯重复。
|
|
108
|
+
const total = pending.length > 1 && bytes > 0 ? `,合计${formatBytes(bytes)}` : ''
|
|
109
|
+
return <p className="m-0 text-xs leading-relaxed text-tita-ink" role="status">
|
|
110
|
+
本次需下载{pending.map(option => `${option.label}(${option.download})`).join('、')}{total};已下载的不会重下。
|
|
111
|
+
</p>
|
|
112
|
+
}
|
|
113
|
+
|
|
74
114
|
export function EnvironmentNotice({ controller, onOpen }: { controller: EnvironmentController; onOpen: () => void }): ReactNode {
|
|
75
115
|
const { view, error, busy } = controller
|
|
76
116
|
if (!error && (!view || view.report.state === 'ready')) return null
|
|
117
|
+
const items = view?.report.items ?? []
|
|
118
|
+
const failed = items.some(item => item.state === 'failed')
|
|
119
|
+
const missing = items.some(item => item.state === 'missing')
|
|
120
|
+
const previouslyChecked = Boolean(view?.report.checkedAt)
|
|
121
|
+
const message = error ? '环境状态读取失败'
|
|
122
|
+
: busy ? view?.job?.stage ?? '正在检查运行环境'
|
|
123
|
+
: failed ? '模型推理自检未通过,请查看原因并修复'
|
|
124
|
+
: missing ? '请准备或启用向量与重排模型,再运行自检'
|
|
125
|
+
: previouslyChecked ? '模型配置或资源已变化,请重新自检' : '首次使用前,请准备并自检向量与重排模型'
|
|
77
126
|
return <div className="mx-3 mt-2 flex shrink-0 items-center gap-2 border-b border-tita-line pb-2 text-xs text-tita-ink" role="status">
|
|
78
127
|
{busy ? <LoaderCircle size={14} className="tita-spin shrink-0" /> : <AlertCircle size={14} className="shrink-0 text-tita-warning" />}
|
|
79
|
-
<span className="min-w-0 flex-1">{
|
|
128
|
+
<span className="min-w-0 flex-1">{message}</span>
|
|
80
129
|
<Button variant="outline" size="sm" onClick={onOpen}>环境准备</Button>
|
|
81
130
|
</div>
|
|
82
131
|
}
|
|
@@ -93,6 +142,11 @@ export function EnvironmentSetup({ controller }: { controller: EnvironmentContro
|
|
|
93
142
|
const running = job?.state === 'running'
|
|
94
143
|
const failure = job?.state === 'failed' ? job.error : undefined
|
|
95
144
|
const chosen = selection ?? view?.selection
|
|
145
|
+
/** 已下载、但当前选择没用到的那些:只报出来,不替人删。 */
|
|
146
|
+
const unusedModels = view ? [
|
|
147
|
+
...view.models.embedding.filter(option => option.installed === true && option.id !== view.selection.embedding),
|
|
148
|
+
...view.models.rerank.filter(option => option.installed === true && option.id !== view.selection.rerank),
|
|
149
|
+
] : []
|
|
96
150
|
const selectionChanged = Boolean(chosen && view && (chosen.embedding !== view.selection.embedding || chosen.rerank !== view.selection.rerank))
|
|
97
151
|
return <section id="tita-environment" tabIndex={-1} aria-labelledby="tita-environment-title" className="tita-settingsSection">
|
|
98
152
|
<div className="tita-settingsSectionHeader">
|
|
@@ -113,12 +167,13 @@ export function EnvironmentSetup({ controller }: { controller: EnvironmentContro
|
|
|
113
167
|
</li>)}
|
|
114
168
|
</ul>
|
|
115
169
|
{view && chosen && <div className="my-4 grid gap-3" aria-label="模型选择">
|
|
116
|
-
<ModelSelect id="tita-embedding-model" label="向量模型" value={chosen.embedding} options={view.models.embedding} disabled={busy}
|
|
170
|
+
<ModelSelect id="tita-embedding-model" label="向量模型" value={chosen.embedding} currentModel={view.current.embedding} options={view.models.embedding} disabled={busy}
|
|
117
171
|
onChange={value => setSelection(current => ({ ...(current ?? view.selection), embedding: value as ModelSelection['embedding'] }))} />
|
|
118
|
-
<ModelSelect id="tita-rerank-model" label="重排模型" value={chosen.rerank} options={view.models.rerank} disabled={busy}
|
|
172
|
+
<ModelSelect id="tita-rerank-model" label="重排模型" value={chosen.rerank} currentModel={view.current.rerank} options={view.models.rerank} disabled={busy}
|
|
119
173
|
onChange={value => setSelection(current => ({ ...(current ?? view.selection), rerank: value as ModelSelection['rerank'] }))} />
|
|
174
|
+
<DownloadSummary embedding={view.models.embedding} rerank={view.models.rerank} chosen={chosen} />
|
|
120
175
|
{selectionChanged && <p className="m-0 text-xs leading-relaxed text-tita-warning" role="status">
|
|
121
|
-
|
|
176
|
+
安装将启用所选本地模型,并替换高级设置中的自定义模型路径。自检失败会恢复原设置。更改向量模型后,请构建检索索引。
|
|
122
177
|
</p>}
|
|
123
178
|
</div>}
|
|
124
179
|
{!view && !error && <p className="text-xs text-tita-ink-muted" role="status">正在读取环境状态…</p>}
|
|
@@ -132,12 +187,17 @@ export function EnvironmentSetup({ controller }: { controller: EnvironmentContro
|
|
|
132
187
|
<Button variant="outline" size="sm" disabled={busy || selectionChanged} onClick={() => { void prepare('check') }}><RefreshCw size={13} />重新自检</Button>
|
|
133
188
|
{running && <Button variant="ghost" size="sm" disabled={controller.busy && !running} onClick={() => { void prepare('cancel') }}>停止</Button>}
|
|
134
189
|
</div>
|
|
135
|
-
{ready && <p className="mb-0 mt-3 text-xs text-tita-ink-muted"
|
|
190
|
+
{ready && <p className="mb-0 mt-3 text-xs text-tita-ink-muted">环境自检通过。已有卡片请构建检索索引,文档无需重新抽取。</p>}
|
|
136
191
|
<Button variant="ghost" size="sm" className="mt-2" aria-expanded={details} aria-controls="tita-environment-details" onClick={() => setDetails(value => !value)}>
|
|
137
192
|
<ChevronDown size={13} />{details ? '收起检查详情' : '检查详情与日志'}
|
|
138
193
|
</Button>
|
|
139
194
|
{details && <div id="tita-environment-details" className="mt-2 grid gap-2 text-xs leading-relaxed text-tita-ink-muted">
|
|
140
195
|
{view?.report.checkedAt && <p className="m-0">最近自检:{new Date(view.report.checkedAt).toLocaleString()}</p>}
|
|
196
|
+
{/* 切换模型不会删掉旧的:它们留在资源目录里,重下不会发生,但会占磁盘。
|
|
197
|
+
这里只如实列出来 —— 删目录是不可逆的,不该由这一栏的一个按钮决定。 */}
|
|
198
|
+
{unusedModels.length > 0 && <p className="m-0">
|
|
199
|
+
已下载但未启用:{unusedModels.map(option => `${option.label}(${option.download})`).join('、')}。它们留在资源目录里,不会被重新下载。
|
|
200
|
+
</p>}
|
|
141
201
|
{view?.report.items.map(item => item.path && <p key={item.id} className="m-0 break-all">{item.label}:{item.path}</p>)}
|
|
142
202
|
{job?.logs.length ? <pre className="m-0 max-h-40 overflow-auto whitespace-pre-wrap break-all rounded-tita-control bg-tita-surface-muted p-2 font-mono">{job.logs.join('\n')}</pre> : null}
|
|
143
203
|
</div>}
|
|
@@ -33,6 +33,10 @@ import { ExternalLink } from '@tita-agent/ui/icons'
|
|
|
33
33
|
import { layoutGraph, type PlacedGraph, type PlacedNode } from './graph/layout.ts'
|
|
34
34
|
import { cardKey, expansionGraphData, radiusOf, type ExpansionHit, type ExpansionNeighbor } from './graph/expansion.ts'
|
|
35
35
|
import { edgeStyleOf } from './graph/edges.ts'
|
|
36
|
+
import {
|
|
37
|
+
HIT_FILL as PALETTE_HIT_FILL, LABEL_FAINT as PALETTE_LABEL_FAINT, LABEL_INK as PALETTE_LABEL_INK,
|
|
38
|
+
NEIGHBOR_FILL as PALETTE_NEIGHBOR_FILL, OUTLINE_MUTED as PALETTE_OUTLINE_MUTED,
|
|
39
|
+
} from './graph/palette.ts'
|
|
36
40
|
import { styles } from './styles.ts'
|
|
37
41
|
|
|
38
42
|
export type { ExpansionHit, ExpansionNeighbor } from './graph/expansion.ts'
|
|
@@ -62,14 +66,16 @@ const EXPANSION_METRICS = { nodeW: 104, nodeH: 26, linkDistance: 72, stage: 300,
|
|
|
62
66
|
/*
|
|
63
67
|
* 画布侧的颜色都是**字面量**:canvas 渲染器不认 CSS 变量,写 `var(--tita-primary)`
|
|
64
68
|
* 会被解析成全透明黑(`parseColor` 的兜底)。图例上的色块必须与画布上的圆点同色,
|
|
65
|
-
* 所以它在 CSS
|
|
69
|
+
* 所以它在 CSS 里写了一份,并在注释里点名这里 —— 画布这一侧的值全部来自
|
|
70
|
+
* `graph/palette.ts`(三处各写一份正是它们漂开的真正原因)。
|
|
66
71
|
*/
|
|
67
|
-
const HIT_FILL =
|
|
68
|
-
const NEIGHBOR_FILL =
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
const
|
|
72
|
+
const HIT_FILL = PALETTE_HIT_FILL
|
|
73
|
+
const NEIGHBOR_FILL = PALETTE_NEIGHBOR_FILL
|
|
74
|
+
/** 命中点的描边与填充同色:它是一个实心点,靠邻居的「空心」来区分两者。 */
|
|
75
|
+
const OUTLINE = PALETTE_HIT_FILL
|
|
76
|
+
const OUTLINE_MUTED = PALETTE_OUTLINE_MUTED
|
|
77
|
+
const LABEL_INK = PALETTE_LABEL_INK
|
|
78
|
+
const LABEL_FAINT = PALETTE_LABEL_FAINT
|
|
73
79
|
/** 标签用的字面量字族:同上,canvas 读不到 `--font-tita`。 */
|
|
74
80
|
const LABEL_FONT = '-apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif'
|
|
75
81
|
|