Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions ui/src/api/API_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,18 @@ System 接口地址。
页面根据路由 `resourceScope` 选择当前范围的完整业务 API 对象,并将其传给需要请求的 Card
Action、Drawer 或 Dialog。复用方直接使用 `typeof XxxApi` 约束完整 API 对象;不要为每组 Action
额外维护逐方法接口,例如 `ModelActionApi`,也不要使用不断扩展的 `Pick<typeof XxxApi, ...>`。
完整 API 对象的方法集合不同时,共用组件使用完整对象类型的联合,例如
`typeof ModelApi | typeof SystemSharedModelApi`,不为凑齐类型添加其他范围不存在的接口。
仅展示数据的组件不接收 API。

### 模型选项查询

`workspace/model/model.ts` 的 `getModelListWithShared(query)` 请求
`/workspace/<workspaceId>/model_list`,支持 `name`、`model_type`、`model_name` 筛选。
将 `shared_model` 与 `model` 按共享在前的顺序合并为 `ModelItem[]`,分别标记
`source: 'shared'` 与 `source: 'workspace'`。`SelectModel` 的接口选项统一通过此方法查询,
工作流通过 Store 同名方法使用缓存或强制刷新。模型管理列表继续使用 `getModelList`。

### 工具列表查询

`workspace/tool/tool.ts` 的 `getAllTool(query)` 查询支持 `folder_id` 筛选的工作空间工具
Expand All @@ -111,6 +121,12 @@ Action、Drawer 或 Dialog。复用方直接使用 `typeof XxxApi` 约束完整
组装为 `{ id_list, folder_id }`,`putBatchDeleteKnowledge` 将 ID 数组组装为 `{ id_list }`,
分别使用 PUT 请求 `batch_move` 和 `batch_delete`。页面和 Action 负责类型判断及 loading。

知识库创建通过 `postKnowledge`、`postWebKnowledge` 分别提交到 `/base`、`/web`;
`postLarkKnowledge` 沿用飞书扩展接口 `/lark/save`,当前开源后端未包含该实现。
基础创建字段由 `KnowledgeCreatePayload` 统一维护,Web、飞书请求扩展对应类型;工作流创建
复用基础字段并附加 `work_flow` 及可选的 `KnowledgeWorkflowTemplate` 商店模板。
成功后的用户资料刷新、列表刷新和路由跳转由创建弹窗负责。

## 枚举与类型组织

API 枚举与类型统一在 `src/api` 范围内管理,相关规则由本文档统一维护。
Expand Down
20 changes: 19 additions & 1 deletion ui/src/api/admin/workspace/knowledge/knowledge.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { del, get, post, put } from '../../core/request'
import type { ParamsPage, ResponsePage } from '../../core/types'
import type { Dict, KnowledgeDetail, KnowledgeItem } from '@/api/types'
import type { Dict, KnowledgeDetail, KnowledgeItem, KnowledgeCreatePayload, WebKnowledgeCreatePayload, LarkKnowledgeCreatePayload } from '@/api/types'
import { getWorkspaceId } from '@/utils/resource-context'

const getPrefix = () => {
Expand All @@ -22,6 +22,21 @@ const getKnowledgeDetail = (knowledgeId: string) => {
return get<KnowledgeDetail>(`${getPrefix()}/${knowledgeId}`)
}

/** 创建通用知识库。 */
const postKnowledge = (payload: KnowledgeCreatePayload) => {
return post<KnowledgeCreatePayload, KnowledgeItem>(`${getPrefix()}/base`, payload)
}

/** 创建 Web 知识库。 */
const postWebKnowledge = (payload: WebKnowledgeCreatePayload) => {
return post<WebKnowledgeCreatePayload, KnowledgeItem>(`${getPrefix()}/web`, payload)
}

/** 创建飞书知识库,沿用飞书扩展接口。 */
const postLarkKnowledge = (payload: LarkKnowledgeCreatePayload) => {
return post<LarkKnowledgeCreatePayload, KnowledgeItem>(`${getPrefix()}/lark/save`, payload)
}

/** 删除工作空间知识库。 */
const deleteKnowledge = (knowledgeId: string) => {
return del<boolean>(`${getPrefix()}/${knowledgeId}`)
Expand Down Expand Up @@ -53,6 +68,9 @@ const importKnowledgeBundle = (payload: FormData) => {
}

export default {
postKnowledge,
postWebKnowledge,
postLarkKnowledge,
deleteKnowledge,
getAllKnowledge,
getKnowledgeDetail,
Expand Down
10 changes: 4 additions & 6 deletions ui/src/api/admin/workspace/knowledge/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import type {
DefaultModelSettingPayload,
Dict,
KnowledgeItem,
KnowledgeType,
KnowledgeCreatePayload,
KnowledgeWorkflowTemplate,
KnowledgeWorkflowAction,
KnowledgeWorkflowDebugPayload,
KnowledgeWorkflowDetail,
Expand All @@ -17,12 +18,9 @@ interface KnowledgeWorkflowPayload {
work_flow: LogicFlow.GraphConfigData
}

interface CreateKnowledgeWorkflowPayload {
name: string
desc?: string
folder_id: string
type: KnowledgeType
interface CreateKnowledgeWorkflowPayload extends KnowledgeCreatePayload {
work_flow: LogicFlow.GraphConfigData
work_flow_template?: KnowledgeWorkflowTemplate
}

const getPrefix = () => {
Expand Down
23 changes: 22 additions & 1 deletion ui/src/api/admin/workspace/model/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ const getModelList = (query?: Dict<unknown>) => {
return get<ModelItem[]>(getPrefix(), query)
}

/** 获取包含已授权共享模型的下拉选项。 */
const getModelListWithShared = (query?: Dict<unknown>): Promise<ModelItem[]> => {
return get<{ shared_model: ModelItem[]; model: ModelItem[] }>(`/workspace/${getWorkspaceId()}/model_list`, query).then(
({ shared_model, model }) => [
...shared_model.map((model): ModelItem => ({ ...model, source: 'shared' })),
...model.map((model): ModelItem => ({ ...model, source: 'workspace' })),
],
)
}

/** 创建工作空间模型。 */
const postModel = (payload: ModelPayload) => {
return post<ModelPayload, ModelItem>(getPrefix(), payload)
Expand Down Expand Up @@ -52,4 +62,15 @@ const putPauseModelDownload = (modelId: string) => {
return put<undefined, boolean>(`${getPrefix()}/${modelId}/pause_download`)
}

export default { deleteModel, getModelDetail, getModelList, getModelMeta, getModelParamsForm, postModel, putModel, putModelParamsForm, putPauseModelDownload }
export default {
deleteModel,
getModelDetail,
getModelList,
getModelListWithShared,
getModelMeta,
getModelParamsForm,
postModel,
putModel,
putModelParamsForm,
putPauseModelDownload,
}
28 changes: 28 additions & 0 deletions ui/src/api/types/knowledge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,31 @@ export interface KnowledgeWorkflowDetail {
create_time?: string
update_time?: string
}

/** 创建知识库共用的基本信息。 */
export interface KnowledgeCreatePayload {
name: string
desc: string
embedding_model_id: string
folder_id: string
type: KnowledgeType
}

/** 创建 Web 知识库的站点配置。 */
export interface WebKnowledgeCreatePayload extends KnowledgeCreatePayload {
source_url: string
selector: string
}

/** 创建飞书知识库的应用配置。 */
export interface LarkKnowledgeCreatePayload extends KnowledgeCreatePayload {
app_id: string
app_secret: string
folder_token: string
}

/** 知识库工作流商店模板。 */
export interface KnowledgeWorkflowTemplate {
downloadUrl: string
downloadCallbackUrl?: string
}
6 changes: 6 additions & 0 deletions ui/src/components/COMPONENT_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,10 @@ Knowledge 配置器复用 `SelectKnowledgeDialog` 选择可选知识库,沿用
相同 Embedding 模型约束。打开时传入已选快照,确认后回写可选知识库并清理已取消 ID 对应的
默认值;取消不修改配置。

Model 配置器通过 `getSelectModelList(query)` 注入加载可选模型,返回 `Promise<ModelItem[]>`。
上层提供 `ModelApi.getModelListWithShared` 或工作流的 `store.force.getModelListWithShared`;
循环体转发同名注入。该名称用于数据加载能力,与业务 API 方法名区分。

Model 配置器的默认模型也使用 `SelectModel`,仅展示已选的可选模型,不开启参数设置入口。
选择时将模型 ID 转换为包含已配置参数的 `default_value` 对象,清空时重置为空对象。

Expand Down Expand Up @@ -521,6 +525,8 @@ Skills 场景传入 `[TOOL_TYPE.SKILL]`,并通过 `title` 指定标题。两

按供应商分组展示模型,单选 `v-model` 为字符串,`multiple` 模式为字符串数组,变化时触发 `change`。`options` 为
`ModelItem[]`,`providerOptions` 为 `ModelProviderItem[]`,模型列表和供应商列表均由使用方查询。
需要接口加载的模型选项统一使用 `getModelListWithShared`,共享标签读取 `source: 'shared'`。
动态表单运行时的配置快照及默认模型的已选子集继续由上层提供,不额外查询全量模型。

只有 `status === MODEL_STATUS.SUCCESS` 的选项可选,同供应商内可用模型排在前面。
`canEditParams` 默认 `false`,开启且为单选时显示参数按钮;多选不加载或修改参数。
Expand Down
30 changes: 19 additions & 11 deletions ui/src/components/mk-dynamics-form/Demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@
import { ref, computed, provide } from 'vue'
import { ElMessage } from 'element-plus'
import type { Dict } from '@/api/types'
import { dynamicFormTypeOptions, MkDynamicsForm, MkDynamicsFormConstructor, type DynamicFormValue, type FormField, type VisibilityFieldOption } from '@/components/mk-dynamics-form'
import modelAPI from '@/api/admin/workspace/model/model'
import {
dynamicFormTypeOptions,
MkDynamicsForm,
MkDynamicsFormConstructor,
type DynamicFormValue,
type FormField,
type VisibilityFieldOption,
} from '@/components/mk-dynamics-form'
import ModelApi from '@/api/admin/workspace/model/model'

defineOptions({ name: 'MkDynamicsFormDemo' })
provide('getSelectModelList', modelAPI.getModelList)
provide('getModelParamsForm', modelAPI.getModelParamsForm)
provide('getSelectModelList', ModelApi.getModelListWithShared)
provide('getModelParamsForm', ModelApi.getModelParamsForm)
const constructorRef = ref<InstanceType<typeof MkDynamicsFormConstructor>>()
const dynamicsFormRef = ref<InstanceType<typeof MkDynamicsForm>>()

Expand All @@ -26,7 +33,13 @@ const visibilityFieldOptions = computed<VisibilityFieldOption[]>(() => [
self: true,
children: formFieldList.value
.filter((_, index) => index !== editIndex.value) // 排除正在编辑的字段,避免自引用
.map((item) => ({ label: getFieldLabel(item), value: item.field, input_type: item.input_type, option_list: item.option_list, attrs: item.attrs })),
.map((item) => ({
label: getFieldLabel(item),
value: item.field,
input_type: item.input_type,
option_list: item.option_list,
attrs: item.attrs,
})),
},
])

Expand Down Expand Up @@ -162,12 +175,7 @@ const validateForm = async () => {

<!-- 添加/编辑字段弹窗 -->
<MkDialog v-model="dialogVisible" :title="isEdit ? '编辑字段' : '添加字段'" width="600px" append-to-body destroy-on-close>
<MkDynamicsFormConstructor
ref="constructorRef"
v-model="currentField"
:enable-visibility="true"
:left-options="visibilityFieldOptions"
/>
<MkDynamicsFormConstructor ref="constructorRef" v-model="currentField" :enable-visibility="true" :left-options="visibilityFieldOptions" />
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitField">确定</el-button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<script setup lang="ts">
import type { ModelItem } from '@/api/types'
import type { DynamicFormValue } from '../../type'
import { computed, inject, ref } from 'vue'
import SelectModel from '@/components/business/select-model/index.vue'
import { providerList as providerOptions } from '../../items/model/provider-data'
import { MODEL_TYPE_LABELS } from '@/constants/model'
const getSelectModelList = inject<(params: { model_type: string }) => Promise<DynamicFormValue>>('getSelectModelList')
const getSelectModelList = inject<(params: { model_type: string }) => Promise<ModelItem[]>>('getSelectModelList')
const getModelParamsForm = inject<(modelId: string) => Promise<DynamicFormValue>>('getModelParamsForm')

const props = defineProps<{ modelValue: DynamicFormValue }>()
Expand Down Expand Up @@ -70,12 +71,12 @@ function fetchDefaultParams(modelId: string) {
}
})
}
const rawModelOptions = ref<DynamicFormValue[]>([])
const rawModelOptions = ref<ModelItem[]>([])

const fetchModelByType = (type: string) => {
if (!type || !getSelectModelList) return
getSelectModelList({ model_type: type }).then((res: DynamicFormValue) => {
rawModelOptions.value = res
getSelectModelList({ model_type: type }).then((models) => {
rawModelOptions.value = models
})
}

Expand Down
19 changes: 19 additions & 0 deletions ui/src/views/VIEW_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,14 @@ src/views/knowledge/
│ ├── index.ts
│ ├── MoveKnowledgeAction.vue
│ └── DeleteKnowledgeAction.vue
├── create-knowledge/
│ ├── CreateKnowledgeDropdown.vue # 知识库创建菜单与弹窗入口
│ ├── CreateBaseKnowledgeDialog.vue # 通用知识库创建
│ ├── CreateWebKnowledgeDialog.vue # Web 站点配置与创建
│ ├── CreateLarkKnowledgeDialog.vue # 飞书应用配置与创建
│ ├── CreateWorkflowKnowledgeDialog.vue # 工作流知识库创建
│ └── components/
│ └── KnowledgeBaseForm.vue # 名称、描述与 Embedding 模型表单
└── template.ts
```

Expand All @@ -146,6 +154,17 @@ src/views/knowledge/
更新卡片所属目录,在具体目录转出时通过 `delete` 移除卡片,在全部目录或转入当前目录时保留。
批量转移与删除使用对应批量接口,成功后退出选择模式并刷新列表。

`CreateKnowledgeDropdown` 内聚四类创建弹窗 Ref 和打开动作,列表页传入目标 `folderId`,通过
`refresh` 刷新列表。入口支持 `trigger` 插槽替换默认创建按钮,下拉使用 `persistent`。
各弹窗接收 `folderId`,通过 `open()` 打开;工作流额外接受可选的商店模板。共用的
`KnowledgeBaseForm` 负责名称、描述、Embedding 模型必填校验以及工作空间和共享模型查询,
通过 `ModelApi.getModelListWithShared({ model_type: 'EMBEDDING' })` 一次加载模型选项,
复用 `SelectModel`,允许创建模型后刷新选项。Web、飞书的特有字段留在对应弹窗中。
创建前校验表单,提交期间禁止重复提交和关闭;成功后刷新用户基础资料并通知列表刷新,
普通类型进入文档列表,工作流进入画布。每次打开及关闭动画结束后清理表单,工作流模板使用
`cloneDeep` 隔离;创建流程使用 Workspace API,不通过路由字符串推测 System 范围。
飞书创建沿用扩展接口 `/lark/save`,部署环境需要提供该接口;导入目前仅展示菜单入口。

当前工具页面按工具类型组织维护表单,共用的参数和代码设置保留在
`tool-form/component/` 中:

Expand Down
23 changes: 2 additions & 21 deletions ui/src/views/knowledge/KnowledgeView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { RESOURCE_TYPE } from '@/api/enums'
import { FOLDER_ENTRIES, FOLDER_ENTRY_ID } from '@/constants'
import FolderTree from '@/components/business/folder-tree/index.vue'
import KnowledgeCard from './knowledge-card/KnowledgeCard.vue'
import CreateWorkflowKnowledgeDialog from './create-knowledge/CreateWorkflowKnowledgeDialog.vue'
import CreateKnowledgeDropdown from './create-knowledge/CreateKnowledgeDropdown.vue'
import {
AuthorizeKnowledgeAction,
DeleteKnowledgeAction,
Expand Down Expand Up @@ -52,10 +52,6 @@ function handleCreateFolder() {

/* 创建知识库 */
const createFolderId = computed(() => currentFolder.value.id || FOLDER_ENTRY_ID.ALL)
const createWorkflowKnowledgeDialogRef = useTemplateRef<InstanceType<typeof CreateWorkflowKnowledgeDialog>>('createWorkflowKnowledgeDialogRef')
function handleCreateWorkflowKnowledge() {
createWorkflowKnowledgeDialogRef.value?.open()
}

/* 知识库查询 */
const knowledgeData = ref<KnowledgeItem[]>([])
Expand Down Expand Up @@ -200,20 +196,7 @@ function handleBatchDelete() {
<span>{{ batchSelectionMode ? '取消选择' : '批量选择' }}</span>
</el-button>
<!-- 创建 -->
<MkDropdown v-if="!batchSelectionMode" trigger="click" placement="bottom-end">
<el-button type="primary">
<span class="mr-1">创建</span>
<MkIcon name="icon_down_outlined" :size="14" />
</el-button>
<template #dropdown>
<MkDropdownMenu class="w-52!">
<MkDropdownItem>通用知识库</MkDropdownItem>
<MkDropdownItem>Web 站点知识库</MkDropdownItem>
<MkDropdownItem @click="handleCreateWorkflowKnowledge">工作流知识库</MkDropdownItem>
<MkDropdownItem divided>导入创建</MkDropdownItem>
</MkDropdownMenu>
</template>
</MkDropdown>
<CreateKnowledgeDropdown v-if="!batchSelectionMode" :folder-id="createFolderId" @refresh="refreshKnowledge" />
</template>
</div>
</component>
Expand Down Expand Up @@ -287,6 +270,4 @@ function handleBatchDelete() {
</MkViewLayout>

<MoveToDialog ref="batchMoveToDialogRef" :loading="knowledgeOperationLoading" :source="RESOURCE_TYPE.KNOWLEDGE" @submit="handleBatchMove" />

<CreateWorkflowKnowledgeDialog ref="createWorkflowKnowledgeDialogRef" :folder-id="createFolderId" />
</template>
Loading
Loading