fix(knowledge): 统一向量化费用归属说明

This commit is contained in:
2026-09-15 10:00:06 +08:00
parent 5ed21835ae
commit c466039adb
7 changed files with 23 additions and 10 deletions

View File

@@ -20,12 +20,15 @@
- Concurrent Task Gate passed through the official project-docs check/start/status flow. This feature worktree is isolated from the MakeLore main checkout and other active tasks; the UX integration base is already present at the recorded base commit.
- The user decided that Yuxi maintains embedding providers, endpoint/API key, enabled embedding models, and dimensions. one-api does not configure embeddings; Works Square remains the creator Token Point ledger only.
- The user subsequently clarified that embedding vectorization is paid by the platform: it must not enter user usage, Token Point deductions, or Agent ceilings. Knowledge processing that triggers dialogue-model calls remains subject to the original model billing rules.
- The client should tell administrators to configure the provider and model in Yuxi, then refresh the knowledge/model directory. Remove the old Works Square activation, one-api vector-interface, and cross-end model-ID matching instructions.
- Scope is limited to the client knowledge configuration copy, shared client typing where needed to retain `dimension`, focused test fixtures/assertions, and synchronized README wording. No Yuxi, Works Square, AgentBus, authentication, payment, installation, or deployment changes.
## Outcome
- The knowledge panel and README now describe Yuxi-owned embedding configuration. The old Works Square activation, one-api vector-interface, and cross-end model-ID matching instructions were removed. The client catalog state now uses the shared model contract, including `dimension`; no embedding-specific Works/one-api filtering was present or added.
- This continuation updates the knowledge upload/indexing explanation, the empty-model guidance, the cost-ceiling explanation, and the cost-source label so platform-funded embedding is separated from billable dialogue-model calls.
- The final wording correction removes the unsupported billable OCR implication: knowledge processing is described as billing only dialogue-model calls under the original rules, while embedding remains platform-funded and outside user usage, Token Points, and Agent ceilings.
## Verification
@@ -34,12 +37,14 @@
- `pnpm run typecheck` passed; scoped ESLint for the changed client and test files passed; `git diff --check` passed.
- `pnpm run build:vite` passed Renderer, Main, Preload, and utility targets with the repository's existing Browserslist, chunk-size, and mixed-import warnings.
- `pnpm exec playwright test tests/e2e/cloud-agents.spec.ts` passed 1/1 scenario, including the updated Yuxi-only empty-catalog guidance.
- The fresh independent Reviewer completed the shared three-service review with Standards PASS and Spec PASS. The MakeLore client, README, and focused test changes had no blocking findings and require no further product changes; the review record is `D:\\Datas\\OthersProjects\\.codex-worktrees\\makelore\\20260914-embedding-review-ml-4e8b\\.project-docs\\30-worklog\\tasks\\20260914-embedding-review-ml-4e8b.md`.
- Follow-up correction verification: the focused knowledge/workflows unit run passed 22/22; the rebuilt Vite bundle passed; the cloud-agent Electron E2E passed 1/1 with the platform-funded embedding and billable dialogue-model assertions; typecheck and scoped ESLint passed (one existing CloudCosts hooks warning remains).
- The replacement fresh independent Reviewer completed the shared three-service review with Standards PASS and Spec PASS. The MakeLore client, README, and focused test changes had no blocking findings and require no further product changes; the review record is `D:\\Datas\\OthersProjects\\.codex-worktrees\\makelore\\20260915-embedding-final-review-ml-c58f10\\.project-docs\\30-worklog\\tasks\\20260915-embedding-final-review-ml-c58f10.md`.
- The user authorized this batch to be committed and merged into the repository main branch. The integration task and main checkout remain owned by the parent agent; this feature task only hands off the reviewed source commit.
- No live Yuxi/Works request, production configuration, packaging, deployment, or remote push was performed.
## Follow-ups
- Integration must include the resulting source commit. A rebuilt client is required before users see the updated guidance.
- Integration must include the resulting source commit, and a rebuilt client is required before users see the updated guidance.
## Promotion Candidates

View File

@@ -7,11 +7,11 @@
Makelore 是一个面向软件、视觉创作、智能机器人与个人云智能体的 AI 桌面工作台。当前版本为 `2.0.0`,源码提供四个模块入口;云智能体需配套配置 WS/Yuxi 服务。模块入口页按 Agents、Code、Canvas、Robot 排列统一采用横向插画卡片Agents 标语为“打造你想象中的AI助手”。工作区左上角入口点击后返回模块入口页
- `Makelore CodeAI 编程`:管理本地项目、项目智能体、对话、文件上下文、代码变更和运行时。
- `Makelore AgentsAI 智能体`:配置个人云智能体并试聊,发布后正式对话、按账号分享或创建应用 API Key。支持流式回复、审批、排队请求、附件与产物、自动任务和活动历史重新进入时恢复最近智能体与对话未确认操作可按原输入重试。聊天可提出日程建议由创建者核对能力、时间和费用后启用。知识库支持上传、索引、替换、删除及导入本人会话附件个人 MCP 凭据、Skills、子智能体可自助管理。支持智能体和会话归档、发布版本比较及恢复为草稿。所有模型调用由创建者个人词元点数支付,可按智能体设置每次任务和每日上限,费用按时间、来源、应用分页统计;分享/API 调用者保有自己的内容空间。Main 管理云会话和本机文件Renderer 通过 Host API 操作。配套服务接入见 [Yuxi MakeLore 说明](https://xerrors.github.io/Yuxi/advanced/makelore-agents.html)。 编辑采用全高桌面分栏,支持拖动调整与展开、独立滚动、小窗口配置/试用切换。首次创建按选用途、说要求、试一试引导,提供科学问答、故事、英语和笔记整理起点;回答方式可多选,特别要求直接编辑,仍以草稿的 system_prompt 保存。新助手预选云端目录的第一个可用模型并明确显示可自行更换已有助手不自动换模型。能力、知识与限制折叠到高级设置。草稿明确保存Ctrl/⌘+S保存与切换页面保留当前试用及未发送文字“保存并重新试用”使用最新保存的要求保留上次试用供对比并可复用上次问题不自动发送。示例问题仅填入输入框有运行、排队、审批或未确认操作时先处理当前试用。工具确认先展示实际操作说明与参数完整技术详情可展开。确认“开始使用”会创建仅自己可用的发布版本并进入独立对话分享与应用仍单独开启。费用上限在限制中独立保存。Enter 发送、Shift+Enter 换行F6 切换面板焦点、Esc 恢复分栏。
- `Makelore AgentsAI 智能体`:配置个人云智能体并试聊,发布后正式对话、按账号分享或创建应用 API Key。支持流式回复、审批、排队请求、附件与产物、自动任务和活动历史重新进入时恢复最近智能体与对话未确认操作可按原输入重试。聊天可提出日程建议由创建者核对能力、时间和费用后启用。知识库支持上传、索引、替换、删除及导入本人会话附件个人 MCP 凭据、Skills、子智能体可自助管理。支持智能体和会话归档、发布版本比较及恢复为草稿。除知识库 embedding 向量化外,模型调用(包括知识处理触发的对话模型调用)仍按原规则由创建者个人词元点数支付,可按智能体设置每次任务和每日上限,费用按时间、来源、应用分页统计;embedding 向量化由平台承担,不计入用户用量、词元点数或智能体费用上限;分享/API 调用者保有自己的内容空间。Main 管理云会话和本机文件Renderer 通过 Host API 操作。配套服务接入见 [Yuxi MakeLore 说明](https://xerrors.github.io/Yuxi/advanced/makelore-agents.html)。 编辑采用全高桌面分栏,支持拖动调整与展开、独立滚动、小窗口配置/试用切换。首次创建按选用途、说要求、试一试引导,提供科学问答、故事、英语和笔记整理起点;回答方式可多选,特别要求直接编辑,仍以草稿的 system_prompt 保存。新助手预选云端目录的第一个可用模型并明确显示可自行更换已有助手不自动换模型。能力、知识与限制折叠到高级设置。草稿明确保存Ctrl/⌘+S保存与切换页面保留当前试用及未发送文字“保存并重新试用”使用最新保存的要求保留上次试用供对比并可复用上次问题不自动发送。示例问题仅填入输入框有运行、排队、审批或未确认操作时先处理当前试用。工具确认先展示实际操作说明与参数完整技术详情可展开。确认“开始使用”会创建仅自己可用的发布版本并进入独立对话分享与应用仍单独开启。费用上限在限制中独立保存。Enter 发送、Shift+Enter 换行F6 切换面板焦点、Esc 恢复分栏。
云知识库的向量模型由平台管理员在 Yuxi 后台维护:在「智能体管理 → 模型供应商」启用供应商,按供应商要求填写有效的服务地址和 API Key添加并启用 embedding 模型并填写实际向量维度;one-api 不参与向量模型配置Works Square 只负责创建者词元点数账本。客户端区分目录加载中、加载失败与无可用模型,空状态提供管理员配置说明;「刷新知识库与模型」保留未提交名称,未确认的创建请求沿用原操作身份。
云知识库的 embedding 模型由平台管理员在 Yuxi 后台维护:在「智能体管理 → 模型供应商」启用供应商,按供应商要求填写有效的服务地址和 API Key添加并启用 embedding 模型并填写实际向量维度;embedding 向量化费用由平台承担不计入用户用量、词元点数或智能体费用上限one-api 不参与 embedding 配置Works Square 只负责其他应计费模型调用的创建者词元点数账本。客户端区分目录加载中、加载失败与无可用模型,空状态提供管理员配置说明;「刷新知识库与模型」保留未提交名称,未确认的创建请求沿用原操作身份。
Agents 侧栏的「渠道」统一管理个人微信账号。每个账号由唯一扫码微信身份连接可以在发布智能体前先扫码之后选择或更换目标智能体多个微信账号可以使用同一个已发布智能体切换目标不需要重新扫码。账号可单独启用、暂停、重新连接或断开不提供联系人邀请或授权调用者管理。Agent 的「使用与分享」只展示已关联渠道并提供定位入口。选中账号的二级详情保留运行/投递活动、失败文件补发和微信对话;对话可审批、停止、新开一段并保存实际产物,不同账号的会话相互隔离。自动任务可明确选择把结果发送到已经开始对话的微信账号,暂停保留目标;所有模型调用仍由智能体创建者支付,费用统计包含微信渠道。渠道需要配套版本的 AgentBus Core/微信 Adapter、Yuxi 和 Works Square桌面用户无需填写服务凭据。Main 保管操作恢复记录,重开界面不会自动重发绑定或执行请求;验证码不写入恢复记录,已移除的联系人权限操作记录只能丢弃。用户与应用分享不属于微信渠道账号管理范围。
Agents 侧栏的「渠道」统一管理个人微信账号。每个账号由唯一扫码微信身份连接可以在发布智能体前先扫码之后选择或更换目标智能体多个微信账号可以使用同一个已发布智能体切换目标不需要重新扫码。账号可单独启用、暂停、重新连接或断开不提供联系人邀请或授权调用者管理。Agent 的「使用与分享」只展示已关联渠道并提供定位入口。选中账号的二级详情保留运行/投递活动、失败文件补发和微信对话;对话可审批、停止、新开一段并保存实际产物,不同账号的会话相互隔离。自动任务可明确选择把结果发送到已经开始对话的微信账号,暂停保留目标;渠道触发的聊天等应计费模型调用仍由智能体创建者支付,费用统计包含微信渠道。渠道需要配套版本的 AgentBus Core/微信 Adapter、Yuxi 和 Works Square桌面用户无需填写服务凭据。Main 保管操作恢复记录,重开界面不会自动重发绑定或执行请求;验证码不写入恢复记录,已移除的联系人权限操作记录只能丢弃。用户与应用分享不属于微信渠道账号管理范围。
- `Makelore CanvasAI 绘画`每个设计项目Workspace维护一份从创建起就存在的 Living Form。左侧项目栏负责新建、切换和管理 Workspace并在桌面设计模式下以 256px 宽度常驻展开;中央沿用 AI 编程的安静对话画布、自然消息流和底部悬浮输入器AI 整理出的制作方案作为对话内的轻量可编辑稿持续更新;桌面端右侧同为 256px 的全高历史作品栏集中展示当前项目的制作记录与生成结果。紧凑窗口通过左侧抽屉访问项目列表,历史记录保留在时间线中。参考图从本地上传后以 `@图片N` 绑定,具体用法只写在创作提示词中。
- `Makelore RobotAI 机器`:管理机器人智能体、设备激活绑定、智能体配置与设备分配;机器人工作台的智能体位于 Robot 全局侧栏,选中后在内容区先查看绑定设备、再查看基础设置,当前智能体通过 URL 参数保持可分享选择;绑定设备时默认先选择“引导配网”或“已有激活码”。在 Windows 与 macOS 的引导路径中Makelore 可在弹窗内扫描并连接附近开放的 `Xiaozhi-*` 配网热点,失败时仍可通过系统 Wi-Fi 手动连接;后续继续复用机器人现有热点配网页面,不修改固件,也不由 Makelore 接收 Wi-Fi 密码。

View File

@@ -6,7 +6,7 @@ import type { CloudApplication, CloudBudget, CloudCostPage, CloudCostSource } fr
import { usePendingCloudInput } from './CloudPending';
const message = (e: unknown) => e instanceof Error ? e.message : '费用服务暂不可用';
const sources: Record<CloudCostSource, string> = { self: '自己使用', shared: '分享', api: 'API', scheduled: '自动任务', preview: '草稿预览', knowledge: '知识库处理', channel: '微信渠道' };
const sources: Record<CloudCostSource, string> = { self: '自己使用', shared: '分享', api: 'API', scheduled: '自动任务', preview: '草稿预览', knowledge: '知识库模型调用', channel: '微信渠道' };
export function CloudBudgetEditor({ slug }: { slug: string }) {
const [budget, setBudget] = useState<CloudBudget | null>(null);
@@ -24,7 +24,7 @@ export function CloudBudgetEditor({ slug }: { slug: string }) {
}, [slug, accept]);
return <section className="space-y-4 rounded-xl border border-border p-5">
<h2 className="font-medium"></h2>
<p className="text-sm leading-6 text-muted-foreground">API 0 </p>
<p className="text-sm leading-6 text-muted-foreground">APIembedding 0 </p>
<form className="flex flex-wrap items-end gap-4" onSubmit={async e => {
e.preventDefault(); setBusy(true); setError('');
try { accept(await cloudAgentsApi.call('saveBudget', { slug, request_limit_points: requestLimit.trim() || null, daily_limit_points: dailyLimit.trim() || null })); }

View File

@@ -65,7 +65,7 @@ export function CloudKnowledgePanel({ slug, onCreated, onDeleted }: { slug: stri
return <details className="rounded-lg border p-4">
<summary className="min-h-8 cursor-pointer text-sm font-medium"></summary>
<div className="mt-4 space-y-4 text-sm">
<p className="text-xs leading-5 text-muted-foreground">使</p>
<p className="text-xs leading-5 text-muted-foreground">使embedding </p>
{error && <p role="alert" className="text-destructive">{error}</p>}
{catalogError && <p role="alert" className="text-destructive">{catalogError}</p>}
<div className="flex flex-wrap gap-2">
@@ -85,7 +85,7 @@ export function CloudKnowledgePanel({ slug, onCreated, onDeleted }: { slug: stri
{catalog?.models.map(m => <option key={m.id} value={m.id}>{m.name}</option>)}
</select>
{!catalogLoading && !catalogError && catalog && !catalog.models.length && <div className="space-y-2 text-xs leading-5 text-muted-foreground">
<p> Yuxi </p>
<p>Embedding Yuxi </p>
<details>
<summary className="cursor-pointer font-medium text-foreground"></summary>
<ol className="mt-2 list-decimal space-y-1 pl-5">

View File

@@ -100,9 +100,13 @@ test('personal cloud Agent creation, draft save and leave protection in Electron
await page.getByRole('button', { name: '高级设置', exact: true }).click();
await page.getByRole('button', { name: '知识', exact: true }).click();
await page.getByText('管理我的知识文档', { exact: true }).click();
const knowledgeDescription = page.getByText(/上传到知识库的文档可供/);
await expect(knowledgeDescription).toContainText('embedding 向量化由平台承担,不计入用户用量、词元点数或智能体费用上限');
await expect(knowledgeDescription).toContainText('知识处理如触发对话模型调用,仍按原模型实际用量计费');
await page.getByRole('button', { name: '新建知识库', exact: true }).click();
await expect(page.getByLabel('向量模型', { exact: true })).toBeDisabled();
await page.getByText('管理员配置说明', { exact: true }).click();
await expect(page.getByText(/Embedding 只在 Yuxi 配置/)).toBeVisible();
await expect(page.getByText(/Yuxi 后台/)).toContainText('智能体管理 → 模型供应商');
await expect(page.getByText(/Yuxi 后台/)).toContainText('服务地址和 API Key');
await expect(page.getByText(/Works Square 运营后台|one-api/)).toHaveCount(0);

View File

@@ -118,6 +118,8 @@ it('saves independent Agent ceilings and pages cost results under the active sou
render(<><CloudBudgetEditor slug={slug} /><CloudCosts slug={slug} applications={[]} /></>);
const request = await screen.findByLabelText('每次任务上限(词元点数)');
await waitFor(() => expect(request).toBeEnabled());
expect(screen.getByRole('option', { name: '知识库模型调用' })).toBeInTheDocument();
expect(screen.getByText(/知识处理触发的对话模型调用仍按实际用量计入费用/)).toHaveTextContent('embedding 向量化由平台承担,不计入用户用量、词元点数或智能体费用上限');
fireEvent.change(request, { target: { value: '20.50' } });
fireEvent.change(screen.getByLabelText('每日上限(词元点数)'), { target: { value: '100' } });
fireEvent.click(screen.getByRole('button', { name: '保存费用上限' }));

View File

@@ -20,8 +20,10 @@ function openCreation() {
it('explains who configures an empty embedding catalog and refreshes without losing the name', async () => {
api.call.mockResolvedValueOnce(empty).mockResolvedValueOnce(available);
openCreation();
expect(await screen.findByText('暂时没有可用的向量模型。请联系平台管理员在 Yuxi 完成配置,然后刷新。')).toBeVisible();
expect(await screen.findByText('暂时没有可用的向量模型。Embedding 只在 Yuxi 配置,请联系平台管理员启用后刷新;向量化费用由平台承担,不计入用户用量或智能体费用上限。')).toBeVisible();
expect(screen.getByRole('combobox', { name: '向量模型' })).toBeDisabled();
expect(screen.getByText(/上传到知识库的文档可供/)).toHaveTextContent('embedding 向量化由平台承担,不计入用户用量、词元点数或智能体费用上限');
expect(screen.getByText(/上传到知识库的文档可供/)).toHaveTextContent('知识处理如触发对话模型调用,仍按原模型实际用量计费');
fireEvent.click(screen.getByText('管理员配置说明'));
expect(screen.getByText(/Yuxi 后台/)).toHaveTextContent('智能体管理 → 模型供应商');
expect(screen.getByText(/Yuxi 后台/)).toHaveTextContent('服务地址和 API Key');