chore: replace all cn comments of fe to en version by volc api (#320)
This commit is contained in:
@@ -271,7 +271,7 @@ describe('get-fixed-single-agent-schema', () => {
|
||||
label: 'mockedI18n',
|
||||
popoverContent: 'mockedI18n',
|
||||
},
|
||||
// 放到最前面
|
||||
// Put it up front.
|
||||
'x-index': 0,
|
||||
},
|
||||
max_tokens: {
|
||||
|
||||
@@ -58,7 +58,7 @@ const getToolText = (toolKey: ToolKey) =>
|
||||
[ToolKey.PLUGIN]: I18n.t('Plugins'),
|
||||
[ToolKey.WORKFLOW]: I18n.t('Workflows'),
|
||||
[ToolKey.IMAGEFLOW]: I18n.t('imageflow_title'),
|
||||
// 已废弃
|
||||
// Abandoned
|
||||
[ToolKey.KNOWLEDGE]: '',
|
||||
[ToolKey.VARIABLE]: I18n.t('user_profile'),
|
||||
[ToolKey.DATABASE]: I18n.t('bot_database'),
|
||||
@@ -173,7 +173,7 @@ export const ModelCapabilityAlertModelContent: FC<{
|
||||
);
|
||||
};
|
||||
|
||||
// TODO 统一封装 localStorage 服务,管理本地缓存的生命周期
|
||||
// TODO uniformly encapsulates the localStorage service and manages the lifecycle of the local cache
|
||||
export const DONT_SHOW_TIPS_LOCAL_CACHE_KEY =
|
||||
'model_capability_check_do_not_show_again';
|
||||
|
||||
@@ -184,7 +184,7 @@ export const checkModelAbility = (
|
||||
toolKeyConfigList.reduce<[AlertItem[], AlertItem[]]>(
|
||||
([notSupportedRes, poorSupportedRes], item) => {
|
||||
const { hasValidData, toolKey, toolGroupKey } = item;
|
||||
// 只在当前 tool 存在配置时才需要检查
|
||||
// Check only if the current tool configuration exists
|
||||
if (hasValidData) {
|
||||
const modelFunctionConfigType =
|
||||
abilityKey2ModelFunctionConfigType(toolKey);
|
||||
@@ -238,7 +238,7 @@ export const confirm = ({
|
||||
return new Promise(resolve => {
|
||||
const modal = Modal.confirm({
|
||||
header: null,
|
||||
// 需要比模型配置的popover默认 z-index 1030 更高,这里进行内卷
|
||||
// It needs to be higher than the default z-index 1030 of the popover configured by the model.
|
||||
zIndex: 1031,
|
||||
mask: false,
|
||||
width: 480,
|
||||
|
||||
@@ -61,13 +61,13 @@ export const useModelCapabilityCheckAndConfirm = () => {
|
||||
export function useModelCapabilityCheckModal({
|
||||
onOk,
|
||||
}: {
|
||||
/** 当新模型不满足配置时会自动弹窗确认,该参数是确认弹窗的回调 */
|
||||
/** When the new model does not meet the configuration, the pop-up window will automatically confirm. This parameter is the callback to confirm the pop-up window. */
|
||||
onOk: (modelId: string) => void;
|
||||
}): {
|
||||
modalNode: ReactNode;
|
||||
/**
|
||||
* 检查新模型能力是否满足配置,不满足的话会自动弹出确认 modal
|
||||
* @returns true 代表满足
|
||||
* Check whether the new model capability meets the configuration. If not, a confirmation modal will automatically pop up.
|
||||
* @Returns true for satisfied
|
||||
*/
|
||||
checkAndOpenModal: (modelId: string) => boolean;
|
||||
} {
|
||||
@@ -76,8 +76,8 @@ export function useModelCapabilityCheckModal({
|
||||
storeSet: { useModelStore },
|
||||
} = useBotEditor();
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
// Q:单纯通过 modalState 是不是就能判断 modal 是否需要展示,modalVisible 有点多余?
|
||||
// A:这里将 visible 和 state 拆分是为了避免弹窗在关闭动画期间 state 数据变更导致弹窗内容跳变
|
||||
// Q: Is it possible to determine whether modal needs to be displayed simply by modalState, and modalVisible is a bit redundant?
|
||||
// A: The visible and state are split here to avoid the pop-up window content jumping due to the change of state data during the closing animation
|
||||
const [modalState, setModalState] = useState<
|
||||
| {
|
||||
notSupported: AlertItem[];
|
||||
@@ -92,7 +92,7 @@ export function useModelCapabilityCheckModal({
|
||||
modalNode: modalState ? (
|
||||
<Modal
|
||||
visible={modalVisible}
|
||||
// 需要比模型配置的popover默认 z-index 1030 更高,这里进行内卷
|
||||
// It needs to be higher than the default z-index 1030 of the popover configured by the model.
|
||||
zIndex={1031}
|
||||
width={480}
|
||||
header={null}
|
||||
@@ -188,13 +188,13 @@ export const useAgentModelCapabilityCheckAndAlert = () => {
|
||||
export function useAgentModelCapabilityCheckModal({
|
||||
onOk,
|
||||
}: {
|
||||
/** 当新模型不满足配置时会自动弹窗确认,该参数是确认弹窗的回调 */
|
||||
/** When the new model does not meet the configuration, the pop-up window will automatically confirm. This parameter is the callback to confirm the pop-up window. */
|
||||
onOk: (modelId: string) => void;
|
||||
}): {
|
||||
modalNode: ReactNode;
|
||||
/**
|
||||
* 检查新模型能力是否满足配置,不满足的话会自动弹出确认 modal
|
||||
* @returns true 代表满足
|
||||
* Check whether the new model capability meets the configuration. If not, a confirmation modal will automatically pop up.
|
||||
* @Returns true for satisfied
|
||||
*/
|
||||
checkAndOpenModal: (modelId: string, agent: Agent) => boolean;
|
||||
} {
|
||||
@@ -203,8 +203,8 @@ export function useAgentModelCapabilityCheckModal({
|
||||
storeSet: { useModelStore, useDraftBotDataSetStore },
|
||||
} = useBotEditor();
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
// Q:单纯通过 modalState 是不是就能判断 modal 是否需要展示,modalVisible 有点多余?
|
||||
// A:这里将 visible 和 state 拆分是为了避免弹窗在关闭动画期间 state 数据变更导致弹窗内容跳变
|
||||
// Q: Is it possible to determine whether modal needs to be displayed simply by modalState, and modalVisible is a bit redundant?
|
||||
// A: The visible and state are split here to avoid the pop-up window content jumping due to the change of state data during the closing animation
|
||||
const [modalState, setModalState] = useState<
|
||||
| {
|
||||
notSupported: AlertItem[];
|
||||
@@ -219,7 +219,7 @@ export function useAgentModelCapabilityCheckModal({
|
||||
modalNode: modalState ? (
|
||||
<Modal
|
||||
visible={modalVisible}
|
||||
// 需要比模型配置的popover默认 z-index 1030 更高,这里进行内卷
|
||||
// It needs to be higher than the default z-index 1030 of the popover configured by the model.
|
||||
zIndex={1031}
|
||||
width={480}
|
||||
header={null}
|
||||
|
||||
@@ -101,9 +101,9 @@ const DiversityGroupItemImpl: React.FC<
|
||||
}, [form]);
|
||||
|
||||
/**
|
||||
* 这里区分一下初始化和后续操作
|
||||
* 只读状态时 customize 也默认收起否则默认展开
|
||||
* 当然只读状态无法修改 model_style
|
||||
* Here is a distinction between initialization and subsequent operations
|
||||
* In the read-only state, customize is also stowed by default, otherwise it is expanded by default
|
||||
* Of course, read-only state cannot be modified model_style
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (disabled) {
|
||||
|
||||
@@ -49,7 +49,7 @@ interface ModelFormImplProps extends ModelFormProps {
|
||||
|
||||
const ModelFormImpl: React.FC<ModelFormImplProps> = ({
|
||||
formilyCore,
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- 此规则不适用这个 case
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- this rule does not apply to this case
|
||||
formilyReact: { createSchemaField, FormProvider },
|
||||
currentModelId,
|
||||
onModelChange,
|
||||
@@ -67,7 +67,7 @@ const ModelFormImpl: React.FC<ModelFormImplProps> = ({
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// 在 promise executor 中执行回调,其中的错误会异步产生 promise rejection ,而不是导致页面白屏
|
||||
// Execute a callback in a promise executor where an error causes a promise rejection asynchronously instead of a white screen
|
||||
new Promise(() => onFormInit(form, formilyCore));
|
||||
|
||||
return onFormUnmount;
|
||||
|
||||
@@ -65,7 +65,7 @@ export const ModelSelect: React.FC<ModelSelectProps> = ({
|
||||
|
||||
const isReadonly = useBotDetailIsReadonly();
|
||||
|
||||
// 用户从特殊模型切换到正常模型后, 可选项列表将发生变化,于是用户再也切换不回去了
|
||||
// After the user switches from the special model to the normal model, the list of options will change, so the user can never switch back
|
||||
const modelList = getModelOptionList({
|
||||
onlineModelList,
|
||||
offlineModelMap,
|
||||
|
||||
@@ -45,8 +45,8 @@ export const UIModelSelect: React.FC<UIModelSelectProps> = ({
|
||||
disabled = false,
|
||||
}) => {
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
// 专业版有项目维度区分class,modal_class 与 modal_class_name存在一对多的情况,因此统一以model_class_name做分组
|
||||
// 以 modal_class_name 首次出现的顺序进行排序
|
||||
// The professional version has project dimensions to distinguish classes, modal_class and modal_class_name have one-to-many situations, so they are grouped by model_class_name
|
||||
// Sort by modal_class_name first appearance
|
||||
const modelClassSortList = getModelClassSortList(
|
||||
modelList.map(i => i.model_class_name ?? ''),
|
||||
);
|
||||
@@ -54,7 +54,7 @@ export const UIModelSelect: React.FC<UIModelSelectProps> = ({
|
||||
const modelClassGroup = groupBy(modelList, model => model.model_class_name);
|
||||
const showEndPointName = modelList.some(model => model.endpoint_name);
|
||||
|
||||
// 搜索规则: 模型名称/接入点名称包含关键词(不区分大小写)
|
||||
// Search rule: Model name/access point name contains keywords (case insensitive)
|
||||
const filterOption = (model: Model) => {
|
||||
const sugInput = inputValue.toUpperCase();
|
||||
return (
|
||||
@@ -99,9 +99,9 @@ export const UIModelSelect: React.FC<UIModelSelectProps> = ({
|
||||
};
|
||||
})
|
||||
.map(group => (
|
||||
// 修改key原因:详见https://semi.design/zh-CN/input/select - 分组模块
|
||||
// 1. 分组能力只能使用jsx
|
||||
// 2. 若Select的children需要动态更新,OptGroup上的key也需要进行更新,否则Select无法识别
|
||||
// Reason for modifying key: See https://semi.design/zh-CN/input/select - Grouping Module for details
|
||||
// 1. The grouping ability can only be used with jsx.
|
||||
// 2. If the selected children need to be dynamically updated, the key on the OptGroup also needs to be updated, otherwise Select cannot be recognized
|
||||
<Select.OptGroup key={`${inputValue}-${group.label}`} label={group.label}>
|
||||
{group.children?.map(option => (
|
||||
<Select.Option value={option.value} key={option.value}>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
import cls from 'classnames';
|
||||
@@ -83,7 +83,7 @@ function InnerImg({
|
||||
<Avatar
|
||||
className="shrink-0 rounded-[6px] border border-solid coz-stroke-primary"
|
||||
shape="square"
|
||||
// @ts-expect-error -- semi 类型定义有问题
|
||||
// @ts-expect-error -- there is a problem with the semi type definition
|
||||
bottomSlot={
|
||||
bottomBanner
|
||||
? {
|
||||
@@ -118,57 +118,57 @@ const FEATURE_ICON_MAP: Record<
|
||||
{ color: string; bg: string; icon: ReactNode }
|
||||
> = {
|
||||
[ModelTagValue.Flagship]: {
|
||||
icon: <IconCozStarFill />, //旗舰
|
||||
icon: <IconCozStarFill />, //flagship
|
||||
color: 'coz-fg-color-brand',
|
||||
bg: 'coz-mg-hglt',
|
||||
},
|
||||
[ModelTagValue.HighSpeed]: {
|
||||
icon: <IconCozLightningFill />, //高速
|
||||
icon: <IconCozLightningFill />, //high speed
|
||||
color: 'coz-fg-color-blue',
|
||||
bg: 'coz-mg-color-blue',
|
||||
},
|
||||
[ModelTagValue.CostPerformance]: {
|
||||
icon: <IconCozChatFill />, //性价比
|
||||
icon: <IconCozChatFill />, //price/performance ratio
|
||||
color: 'coz-fg-color-blue',
|
||||
bg: 'coz-mg-color-blue',
|
||||
},
|
||||
[ModelTagValue.LongText]: {
|
||||
icon: <IconCozDocumentFill />, //长文本
|
||||
icon: <IconCozDocumentFill />, //long text
|
||||
color: 'coz-fg-color-blue',
|
||||
bg: 'coz-mg-color-blue',
|
||||
},
|
||||
[ModelTagValue.RolePlaying]: {
|
||||
icon: <IconCozRoleFill />, //角色扮演
|
||||
icon: <IconCozRoleFill />, //Role Playing
|
||||
color: 'coz-fg-color-blue',
|
||||
bg: 'coz-mg-color-blue',
|
||||
},
|
||||
[ModelTagValue.ImageUnderstanding]: {
|
||||
icon: <IconCozImageFill />, //图像
|
||||
icon: <IconCozImageFill />, //image
|
||||
color: 'coz-fg-color-purple',
|
||||
bg: 'coz-mg-color-purple',
|
||||
},
|
||||
[ModelTagValue.VideoUnderstanding]: {
|
||||
icon: <IconCozVideoFill />, //视频
|
||||
icon: <IconCozVideoFill />, //video
|
||||
color: 'coz-fg-color-purple',
|
||||
bg: 'coz-mg-color-purple',
|
||||
},
|
||||
[ModelTagValue.AudioUnderstanding]: {
|
||||
icon: <IconCozMusic />, //音频
|
||||
icon: <IconCozMusic />, //Audio
|
||||
color: 'coz-fg-color-purple',
|
||||
bg: 'coz-mg-color-purple',
|
||||
},
|
||||
[ModelTagValue.CodeSpecialization]: {
|
||||
icon: <IconCozCodeFill />, //代码专精
|
||||
icon: <IconCozCodeFill />, //Code Specialization
|
||||
color: 'coz-fg-color-cyan',
|
||||
bg: 'coz-mg-color-cyan',
|
||||
},
|
||||
[ModelTagValue.ToolInvocation]: {
|
||||
icon: <IconCozWrenchFill />, //工具调用
|
||||
icon: <IconCozWrenchFill />, //tool call
|
||||
color: 'coz-fg-color-cyan',
|
||||
bg: 'coz-mg-color-cyan',
|
||||
},
|
||||
[ModelTagValue.Reasoning]: {
|
||||
icon: <IconCozLightbulbFill />, //推理
|
||||
icon: <IconCozLightbulbFill />, //inference
|
||||
color: 'coz-fg-color-cyan',
|
||||
bg: 'coz-mg-color-cyan',
|
||||
},
|
||||
|
||||
@@ -25,13 +25,13 @@ import { Avatar, Divider, Tooltip } from '@coze-arch/coze-design';
|
||||
|
||||
export type ModelOptionGroupProps =
|
||||
| {
|
||||
/** 新模型专区 */
|
||||
/** New Model Zone */
|
||||
type: 'new';
|
||||
name: string;
|
||||
tips?: string;
|
||||
}
|
||||
| {
|
||||
/** 普通系列模型 */
|
||||
/** Ordinary series model */
|
||||
type?: 'normal';
|
||||
icon: string;
|
||||
name: string;
|
||||
|
||||
@@ -18,7 +18,7 @@ import { I18n } from '@coze-arch/i18n';
|
||||
import { Avatar, Tag } from '@coze-arch/coze-design';
|
||||
import { type Model } from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
/** 极简版 ModelOption,用于 Button 展示或 Select 已选栏 */
|
||||
/** Minimalist ModelOption for Button Display or Select Selected Bar */
|
||||
export function ModelOptionThumb({ model }: { model: Model }) {
|
||||
return (
|
||||
<div className="px-[4px] flex items-center gap-[4px]">
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
/* eslint-disable complexity -- ignore */
|
||||
import { type PropsWithChildren, useRef } from 'react';
|
||||
|
||||
@@ -47,7 +47,7 @@ export type ModelOptionProps = {
|
||||
model: Model;
|
||||
selected?: boolean;
|
||||
disabled?: boolean;
|
||||
/** 返回是否切换成功 */
|
||||
/** Return whether the switch was successful */
|
||||
onClick: () => boolean;
|
||||
} & (
|
||||
| {
|
||||
@@ -65,9 +65,9 @@ export type ModelOptionProps = {
|
||||
| {
|
||||
enableJumpDetail: true;
|
||||
/**
|
||||
* 点击跳转模型管理页面
|
||||
* Click to jump to the model management page
|
||||
*
|
||||
* 因为该组件定位是纯 UI 组件,且不同模块 space id 获取的方式不尽相同,因此跳转行为和 url 的拼接就不内置了
|
||||
* Because the component positioning is a pure UI component, and the way to obtain the space id of different modules is different, the splicing of jump behavior and url is not built-in
|
||||
*/
|
||||
onDetailClick: (modelId: string) => void;
|
||||
}
|
||||
@@ -81,7 +81,7 @@ export function ModelOption({
|
||||
onClick,
|
||||
...props
|
||||
}: ModelOptionProps) {
|
||||
/** 这个 ref 纯粹为了判断是否 hover */
|
||||
/** This ref is purely for judging whether to hover or not. */
|
||||
const ref = useRef<HTMLElement>(null);
|
||||
const isHovering = useHover(ref);
|
||||
const { scene } = useBotCreatorContext();
|
||||
@@ -93,7 +93,7 @@ export function ModelOption({
|
||||
?.filter(t => t.tag_class === ModelTagClass.ModelFunction && t.tag_name)
|
||||
.map(t => t.tag_name);
|
||||
|
||||
// 付费墙,开源版不支持该功能
|
||||
// Paywall, open source version does not support this feature
|
||||
const isProModel =
|
||||
model.model_status_details?.is_new_model ||
|
||||
model.model_status_details?.is_advanced_model;
|
||||
@@ -114,9 +114,9 @@ export function ModelOption({
|
||||
? 'coz-mg-hglt hover:coz-mg-hglt-hovered'
|
||||
: 'hover:coz-mg-secondary-hovered active:coz-mg-secondary-pressed',
|
||||
disabled ? 'cursor-not-allowed' : 'cursor-pointer',
|
||||
// 以下 cls 只为实现 hover、active、last 时隐藏上下分割线(注意分割线在 model-info-border,设计师的小心思)
|
||||
// The following cls only hide the upper and lower dividing lines when implementing hover, active, and last (note that the dividing lines are in model-info-border, the designer's careful thought)
|
||||
styles['model-option'],
|
||||
// @ts-expect-error -- 不知道为什么会报错
|
||||
// @ts-expect-error -- I don't know why the error is reported.
|
||||
{ [styles['model-option_selected']]: selected },
|
||||
)}
|
||||
onClick={() => {
|
||||
@@ -232,7 +232,7 @@ export function ModelOption({
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
|
||||
// 付费墙拦截
|
||||
// paywall blocking
|
||||
if (isProModel && !isNewModelAvailable) {
|
||||
openPremiumPaywallModal();
|
||||
return;
|
||||
@@ -295,8 +295,8 @@ function ModelTag({
|
||||
}
|
||||
|
||||
/**
|
||||
* hover 展示若干图标(比如跳转模型详情页、详细配置)时,要对图标下的内容有个渐变遮罩效果
|
||||
* 该方法用于计算遮罩样式
|
||||
* When hovering to display several icons (such as jumping to the model details page and detailed configuration), there should be a gradual change mask effect on the content under the icon
|
||||
* This method is used to calculate the mask style
|
||||
*/
|
||||
function calcMaskStyle(buttonVisible: Array<boolean | undefined>) {
|
||||
const btnNum = buttonVisible.reduce(
|
||||
@@ -309,9 +309,9 @@ function calcMaskStyle(buttonVisible: Array<boolean | undefined>) {
|
||||
|
||||
const BTN_WIDTH = 32;
|
||||
const BTN_GAP = 3;
|
||||
/** 不随按钮数量变化的遮罩固定宽度 */
|
||||
/** Fixed width of mask that does not vary with the number of buttons */
|
||||
const PRESET_PADDING = 16;
|
||||
/** 遮罩的渐变宽度 */
|
||||
/** A gradual change in the width of the mask */
|
||||
const MASK_WIDTH = 24;
|
||||
|
||||
const gradientStart =
|
||||
|
||||
@@ -31,17 +31,17 @@ import { ModelOptionThumb } from '../model-option-thumb';
|
||||
|
||||
export interface ModelSelectUIProps {
|
||||
/**
|
||||
* 是否禁止弹出 popover
|
||||
* Whether to ban popovers
|
||||
*
|
||||
* 目前内部实现既支持 disabled 时直接不允许弹出 popover(与历史逻辑一致)
|
||||
* 也支持允许弹出 popover 和查看详细配置但禁止编辑
|
||||
* 需求变更时可灵活修改
|
||||
* The current internal implementation supports both disabled and directly does not allow popovers (consistent with historical logic).
|
||||
* Also supports allowing popovers and viewing detailed configuration but prohibiting editing
|
||||
* Flexible modification when requirements change
|
||||
*/
|
||||
disabled?: boolean;
|
||||
/** 当前选中的模型 */
|
||||
/** The currently selected model */
|
||||
selectedModelId: string;
|
||||
/**
|
||||
* 是否展示跳转到模型详情页(/space/:space_id/model/:model_id)按钮
|
||||
* Whether to display the jump to model details page (/space/: space_id/model/: model_id) button
|
||||
* @default false
|
||||
*/
|
||||
enableJumpDetail?:
|
||||
@@ -50,22 +50,22 @@ export interface ModelSelectUIProps {
|
||||
}
|
||||
| false;
|
||||
/**
|
||||
* 模型选择的变更事件
|
||||
* Model-selected change events
|
||||
*
|
||||
* 返回值表示是否成功切换,对部分后续事件会有影响,比如自动关闭 popover
|
||||
* 不显式 return 则视为 true
|
||||
* The return value indicates whether the switch was successful, which will affect some subsequent events, such as automatically closing the popover.
|
||||
* No explicit return is considered true
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type -- 要实现【要么不用 return,要么必须 return boolean】没别的办法了啊
|
||||
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type -- there is no other way to implement [either do not return, or must return boolean]
|
||||
onModelChange: (model: Model) => boolean | void;
|
||||
modelList: Model[];
|
||||
/**
|
||||
* 允许业务侧自定义触发器展示,命名对齐 semi select 组件
|
||||
* Allows business side custom trigger display, named alignment semi selected components
|
||||
*
|
||||
* @param model - 当 selectedModelId 找不到对应的 model 时,这里则会传入 undefined
|
||||
* @Param model - when selectedModelId cannot find the corresponding model, this will pass undefined
|
||||
*/
|
||||
triggerRender?: (model?: Model, popoverVisible?: boolean) => ReactNode;
|
||||
/**
|
||||
* workflow 等不允许详细配置的业务会有 clickToHide 的诉求
|
||||
* Businesses such as workflow that do not allow detailed configuration will have clickToHide demands.
|
||||
* @default false
|
||||
*/
|
||||
clickToHide?: boolean;
|
||||
@@ -73,27 +73,27 @@ export interface ModelSelectUIProps {
|
||||
popoverPosition?: PopoverProps['position'];
|
||||
/** @default true */
|
||||
popoverAutoAdjustOverflow?: boolean;
|
||||
/** trigger 的 className。若传入 triggerRender 则完全由 triggerRender 接管渲染,该参数不再起作用 */
|
||||
/** The className of the trigger. If you pass in triggerRender, triggerRender takes over the rendering completely. This parameter no longer has any effect */
|
||||
className?: string;
|
||||
popoverClassName?: string;
|
||||
/**
|
||||
* 若业务侧自行在组件外部插入 Modal,则点击 Modal 也会触发 onClickOutSide 导致 popover 关闭
|
||||
* 若不希望 popover 意外关闭,则需要将 Modal 通过 modalSlot 传入
|
||||
* If the business side inserts a Modal outside the component by itself, clicking Modal will also trigger onClickOutSide and cause the popover to close.
|
||||
* If you don't want the popover to close unexpectedly, you need to pass Modal through modalSlot
|
||||
*
|
||||
* (甚至不需要设置 getPopupContainer,此时 Modal 的挂载层和 ModelSelect 的 Popover 的挂载层依然不同,但却神秘地不会再触发 onClickOutSide 了,semi 牛逼)
|
||||
* (You don't even need to set getPopupContainer, the mount layer of Modal and the mount layer of ModelSelect's Popover are still different, but mysteriously no longer trigger onClickOutSide, semi awesome)
|
||||
*/
|
||||
modalSlot?: ReactNode;
|
||||
|
||||
/** 模型详细配置信息,不传则隐藏详细配置的按钮入口 */
|
||||
/** The detailed configuration information of the model will be hidden if the button entrance of the detailed configuration is not passed. */
|
||||
modelConfigProps?: ModelConfigProps;
|
||||
|
||||
/** 弹窗有多种渲染场景,提供选项来定制渲染层级已避免覆盖 */
|
||||
/** The pop-up window has a variety of rendering scenarios, providing options to customize the rendering hierarchy to avoid overwriting */
|
||||
zIndex?: number;
|
||||
|
||||
/** 模型列表额外头部插槽 */
|
||||
/** Model List Extra Head Slots */
|
||||
modelListExtraHeaderSlot?: ReactNode;
|
||||
|
||||
/** 是否默认展开模型列表 */
|
||||
/** Whether to expand the model list by default */
|
||||
defaultOpen?: boolean;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ export function ModelSelectUI({
|
||||
zIndex = 999,
|
||||
defaultOpen = false,
|
||||
}: ModelSelectUIProps) {
|
||||
/** 为了实现 Popover 跟 Select 宽度一致,通过该 ref 获取 Select 宽度(若传入 triggerRender 则不再需要保持一致) */
|
||||
/** In order to achieve the same width as Select for Popover, get the Select width through this ref (if you pass in triggerRender, you no longer need to keep it consistent) */
|
||||
const selectRef = useRef<HTMLDivElement>(null);
|
||||
const [popoverVisible, setPopoverVisible] = useState(defaultOpen);
|
||||
const [detailConfigVisible, setDetailConfigVisible] = useState(false);
|
||||
@@ -124,7 +124,7 @@ export function ModelSelectUI({
|
||||
({ model_type }) => selectedModelId === String(model_type),
|
||||
);
|
||||
|
||||
// 需要实现 group + custom option 效果,Select 组件兼容性不佳,不得不自行实现 Popover
|
||||
// Need to implement group + custom option effect, Select component compatibility is not good, have to implement Popover
|
||||
return (
|
||||
<Popover
|
||||
zIndex={zIndex}
|
||||
@@ -161,7 +161,7 @@ export function ModelSelectUI({
|
||||
) : null}
|
||||
|
||||
<PopoverModelListView
|
||||
// 用 hidden 而不是直接条件性挂载以便保留 scrollTop,设计师的小心思
|
||||
// Use hidden instead of direct conditional mount to preserve scrollTop, designer's care
|
||||
hidden={detailConfigVisible}
|
||||
disabled={disabled}
|
||||
selectedModelId={selectedModelId}
|
||||
|
||||
@@ -35,15 +35,15 @@ import { ModelSelectUI, type ModelSelectUIProps } from '../model-select-ui';
|
||||
|
||||
export interface ModelSelectProps extends ModelSelectUIProps {
|
||||
/**
|
||||
* 是否允许选择高级模型/新模型,否则内置弹窗拦截
|
||||
* 当不传或设置为 auto 时,则由组件内置判断用户是否是付费用户(国内专业版,海外 premium)
|
||||
* Whether to allow selection of advanced models/new models, otherwise built-in pop-up blocking
|
||||
* When not passing or setting to auto, the built-in component determines whether the user is a paying user (domestic professional version, overseas premium)
|
||||
* @default auto
|
||||
*/
|
||||
canSelectSuperiorModel?: boolean | 'auto';
|
||||
}
|
||||
|
||||
/**
|
||||
* 该组件相比 ModelSelectUI 单纯多了付费拦截功能
|
||||
* This component has more paid interception functions than ModelSelectUI
|
||||
*/
|
||||
export function ModelSelect({
|
||||
onModelChange,
|
||||
@@ -58,12 +58,12 @@ export function ModelSelect({
|
||||
fetchPremiumPlan: s.fetchPremiumPlan,
|
||||
})),
|
||||
);
|
||||
// 国内:是否允许使用新模型/高级模型
|
||||
// Domestic: Whether to allow the use of new models/advanced models
|
||||
const isBenefitAvailable = useBenefitAvailable({
|
||||
scene: PremiumPaywallScene.NewModel,
|
||||
});
|
||||
|
||||
/** 海外是否为 premium */
|
||||
/** Is it premium overseas? */
|
||||
const { isFree } = usePremiumType();
|
||||
|
||||
const canSelectSuperiorModel = isBoolean(canSelectSuperiorModelProps)
|
||||
@@ -105,7 +105,7 @@ export function ModelSelect({
|
||||
modalSlot={
|
||||
<>
|
||||
<Modal
|
||||
// ModelSelect 用到的 Popover 组件弹层默认 z-index 为 1030
|
||||
// The default z-index of the Popover component elastic layer used by ModelSelect is 1030.
|
||||
zIndex={1031}
|
||||
visible={upgradeModalState.visible}
|
||||
title={
|
||||
@@ -118,7 +118,7 @@ export function ModelSelect({
|
||||
onOk={() => {
|
||||
if (IS_CN_REGION) {
|
||||
openPremiumModal();
|
||||
// 这么操作是为了在关闭动画过程中防止 modal 内容跳变
|
||||
// This is done to prevent the modal content from jumping during the closed animation
|
||||
setUpgradeModalState(s => ({ ...s, visible: false }));
|
||||
} else {
|
||||
window.open('/premium', '_blank');
|
||||
|
||||
@@ -46,28 +46,28 @@ export interface ModelConfigProps
|
||||
extends Pick<ModelFormContextProps, 'hideDiversityCollapseButton'> {
|
||||
modelStore: UseHandleModelFormProps['modelStore'];
|
||||
/**
|
||||
* 模型配置更新
|
||||
* model configuration update
|
||||
*
|
||||
* 需要注意切换模型时,会先触发 onModelChange,由外部传入更新后的 selectedModelId,此后内部会计算新模型的 config 并触发 onConfigChange
|
||||
* It should be noted that when switching models, onModelChange will be triggered first, and the updated selectedModelId will be passed externally. After that, the new model's config will be calculated internally and onConfigChange will be triggered.
|
||||
*
|
||||
* 理想数据流是切换模型触发 onModelChange 后,外部一并传入新的 selectedModelId 和 currentConfig。或者由 onModelChange 同时抛出新的 modelId 和 config。
|
||||
* 目前这样虽然有点挫,但由于历史设计原因,改造成上述方式成本略高,暂保持现状。
|
||||
* The ideal data flow is when the switch model triggers onModelChange, and the new selectedModelId and currentConfig are passed externally. Or onModelChange throws a new modelId and config at the same time.
|
||||
* Although the current situation is a bit frustrating, due to historical design reasons, the cost of transforming it into the above method is slightly higher, and the status quo is maintained for the time being.
|
||||
*/
|
||||
onConfigChange: (value: ModelInfo) => void;
|
||||
currentConfig: ModelInfo;
|
||||
/** 当前 agent 是 single 还是 mulit */
|
||||
/** Is the current agent single or mulit? */
|
||||
agentType: 'single' | 'multi';
|
||||
/** 明确diff类型, 透传给getSchema。model-diff情况下不展示携带上下文轮数影响 */
|
||||
/** Clarify the diff type and pass it through to getSchema. In the case of model-diff, the number of rounds carrying the context is not displayed */
|
||||
diffType?: 'prompt-diff' | 'model-diff';
|
||||
}
|
||||
|
||||
interface PopoverModelConfigViewProps {
|
||||
/**
|
||||
* 需要持续保留表单实例,以便复用无比复杂的「切换模型时初始化详细配置」的逻辑
|
||||
* You need to keep the form instance continuously in order to reuse the extremely complex "initialize detailed configuration when switching models" logic
|
||||
*
|
||||
* 理想做法是在外层业务侧 onModelChange 时重置 config 值
|
||||
* 但一是该逻辑过于复杂,难以独立抽出初始化方法;
|
||||
* 二是 useHandleModelForm 使用成本又极高,不适合放到最外层业务侧去调用
|
||||
* The ideal approach is to reset the config value when onModelChange occurs on the outer business side
|
||||
* But firstly, the logic is too complicated to extract the initialization method independently.
|
||||
* Second, useHandleModelForm is very expensive to use and is not suitable for being called on the outermost business side
|
||||
*/
|
||||
visible: boolean;
|
||||
disabled?: boolean;
|
||||
@@ -76,7 +76,7 @@ interface PopoverModelConfigViewProps {
|
||||
modelConfigProps: ModelConfigProps;
|
||||
}
|
||||
|
||||
/** Popover 的 模型配置状态,对应列表状态。单纯为了避免组件过大而做的拆分 */
|
||||
/** Popover's model configuration state corresponds to the list state. Splitting purely to avoid components being too large */
|
||||
export function PopoverModelConfigView({
|
||||
visible,
|
||||
disabled,
|
||||
@@ -131,7 +131,7 @@ function ModelForm({
|
||||
disabled,
|
||||
currentModelId,
|
||||
formilyCore,
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- FormProvider 不适合用别的格式
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- FormProvider is not suitable for other formats
|
||||
formilyReact: { createSchemaField, FormProvider },
|
||||
modelConfigProps: {
|
||||
currentConfig,
|
||||
@@ -170,7 +170,7 @@ function ModelForm({
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// 在 promise executor 中执行回调,其中的错误会异步产生 promise rejection ,而不是导致页面白屏
|
||||
// Execute a callback in a promise executor where an error causes a promise rejection asynchronously instead of a white screen
|
||||
new Promise(() => handleFormInit(form, formilyCore));
|
||||
|
||||
return handleFormUnmount;
|
||||
@@ -211,13 +211,13 @@ function useInitFormily():
|
||||
node: (
|
||||
<div className="h-full flex items-center gap-y-[8px] text-[14px]">
|
||||
<IconCozWarningCircleFill
|
||||
// 该值迁移自 src/components/model-form/index.tsx
|
||||
// The value is migrated from src/components/model-form/index.tsx
|
||||
className="text-[#FF2710]"
|
||||
/>
|
||||
<div className="font-semibold leading-[22px]">
|
||||
<span>{I18n.t('model_form_fail_text')}</span>
|
||||
<span
|
||||
// 该值迁移自 src/components/model-form/index.tsx
|
||||
// The value is migrated from src/components/model-form/index.tsx
|
||||
className="cursor-pointer text-[#4D53E8]"
|
||||
onClick={retryImportFormily}
|
||||
>
|
||||
|
||||
@@ -24,7 +24,7 @@ import { type Model } from '@coze-arch/bot-api/developer_api';
|
||||
import { ModelOptionGroup } from '../model-option-group';
|
||||
import { ModelOption } from '../model-option';
|
||||
|
||||
/** Popover 的 模型列表状态,对应详细配置状态。单纯为了避免组件过大而做的拆分 */
|
||||
/** Popover's model list state corresponds to the detailed configuration state. Splitting purely to avoid oversized components */
|
||||
export function PopoverModelListView({
|
||||
hidden,
|
||||
disabled,
|
||||
@@ -38,15 +38,15 @@ export function PopoverModelListView({
|
||||
enableConfig,
|
||||
enableJumpDetail,
|
||||
}: {
|
||||
/** 是否将列表设置为 display: none(为了保留 scrollTop 信息) */
|
||||
/** Whether to set the list to display: none (to preserve scrollTop information) */
|
||||
hidden: boolean;
|
||||
disabled?: boolean;
|
||||
selectedModelId: string;
|
||||
selectedModel: Model | undefined;
|
||||
modelList: Model[];
|
||||
/** 额外头部插槽 */
|
||||
/** Extra head slot */
|
||||
extraHeaderSlot?: ReactNode;
|
||||
/** 返回是否切换成功 */
|
||||
/** Return whether the switch was successful */
|
||||
onModelClick: (model: Model) => boolean;
|
||||
onDetailClick: (modelId: string) => void;
|
||||
onConfigClick: (model: Model) => void;
|
||||
@@ -54,7 +54,7 @@ export function PopoverModelListView({
|
||||
enableJumpDetail?: boolean;
|
||||
}) {
|
||||
const { modelGroups } = useMemo(() => {
|
||||
/** 开源版本不进行分类 平铺展示 */
|
||||
/** The open-source version is not classified, but tiled */
|
||||
if (IS_OPEN_SOURCE) {
|
||||
return { modelGroups: [modelList] };
|
||||
}
|
||||
@@ -80,7 +80,7 @@ export function PopoverModelListView({
|
||||
onDetailClick={onDetailClick}
|
||||
enableConfig={
|
||||
enableConfig &&
|
||||
// 在 disabled 状态下,只能查看选中模型的详细配置
|
||||
// In the disabled state, you can only view the detailed configuration of the selected model
|
||||
(!disabled || String(model.model_type) === selectedModelId)
|
||||
}
|
||||
onConfigClick={() => {
|
||||
|
||||
@@ -32,7 +32,7 @@ export const ModelFormProvider: React.FC<
|
||||
> = ({ hideDiversityCollapseButton = false, children }) => {
|
||||
const [isGenerationDiversityOpen, setGenerationDiversityOpen] = useState(
|
||||
hideDiversityCollapseButton,
|
||||
); // 隐藏展开收起按钮时则始终展开
|
||||
); // Always expand when hiding the expand hide button
|
||||
const customizeValueMapRef = useRef<
|
||||
ModelFormContextProps['customizeValueMap']
|
||||
>({});
|
||||
|
||||
@@ -25,9 +25,9 @@ export interface ModelFormContextProps {
|
||||
customizeValues: this['customizeValueMap'][string],
|
||||
) => void;
|
||||
/**
|
||||
* 是否展示多样性设置区域的展开收起按钮
|
||||
* Whether to display the expand and close buttons of the diversity setting area
|
||||
*
|
||||
* 需求将详细配置区域放到了独立面板中,因此高度足够展示所有选项,不再需要折叠
|
||||
* Requires that the detailed configuration area be placed in a separate panel, so it is high enough to display all options, no need to fold
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
|
||||
@@ -41,9 +41,9 @@ import { useModelForm } from '../../context/model-form-context';
|
||||
import { type ModelFormProps } from '../../components/model-form';
|
||||
|
||||
const specialFieldKeyList = [
|
||||
// 这个字段是个嵌套结构 需要专门转换
|
||||
// This field is a nested structure and requires special conversion
|
||||
'HistoryRound',
|
||||
// 这个字段需要带到表单中进行变化 表单中有组件会监听这个数据 但是他不属于 model_parameter
|
||||
// This field needs to be brought to the form for change. There are components in the form that will listen to this data, but it is not part of the model_parameter
|
||||
'model_style',
|
||||
];
|
||||
|
||||
@@ -53,8 +53,8 @@ export interface UseHandleModelFormProps {
|
||||
getModelRecord: () => ModelInfo;
|
||||
editable: boolean;
|
||||
/**
|
||||
* 原本在 hook 内部调用 useBotEditor 获取 modelStore,这期暂且粗暴地挪出去
|
||||
* @todo 理想形态是彻底与 store 解耦,传入 get_type_list 接口返回值即可,或提供一个将接口返回值转换成所需结构的方法
|
||||
* Originally, useBotEditor was called inside the hook to get the modelStore, but this issue was violently moved out for the time being
|
||||
* The ideal form of @todo is to completely decouple from the store, pass in get_type_list interface return value, or provide a way to convert the interface return value into the desired structure
|
||||
*/
|
||||
modelStore: Pick<
|
||||
ModelState & ModelAction,
|
||||
@@ -63,15 +63,15 @@ export interface UseHandleModelFormProps {
|
||||
}
|
||||
|
||||
/**
|
||||
* 此处数据的流转没有做成由顶层模型设置数据完全控制表单数据,有以下几个原因:
|
||||
* 1. 需求临时变动,需要按照模型唯独记录用户设置
|
||||
* 2. 顶层数据源的设计是单例的,只能存最近模型的一份数据
|
||||
* The flow of data here does not allow the top-level model to set the data to fully control the form data for several reasons:
|
||||
* 1. Temporary changes in requirements, and user settings need to be recorded only according to the model
|
||||
* 2. The design of the top-level data source is singleton, and only one copy of the most recent model can be stored
|
||||
*
|
||||
* 最终设计是,由中间的表单层记录数据,通过表单的 onChange 来更新顶层数据源
|
||||
* 所以表单数据和顶层数据源不一定是一致的
|
||||
* The final design is that the data is recorded by the single layer in the middle, and the top-level data source is updated by the onChange of the form
|
||||
* So the form data and the top-level data source are not necessarily the same
|
||||
*
|
||||
* 每次切换模型,都会初始化表单。我在初始化的过程中抹平顶层数据源和表单数据的不一致
|
||||
* 并统一通过表单的 onChange 来更新顶层数据
|
||||
* Every time I switch the model, the form is initialized. During the initialization process, I smooth out the inconsistencies between the top-level data source and the form data
|
||||
* And update the top-level data uniformly through the onChange of the form
|
||||
*/
|
||||
// eslint-disable-next-line max-lines-per-function, @coze-arch/max-line-per-function -- q
|
||||
export const useHandleModelForm = ({
|
||||
@@ -127,7 +127,7 @@ export const useHandleModelForm = ({
|
||||
const modelRecord = getModelRecord();
|
||||
const { defaultValues } = presetValues;
|
||||
|
||||
// 服务端给新创建 bot 刷数据, 老数据无对应字段 fallback 到 custom
|
||||
// The server level flushes the data for the newly created bot, and the old data has no corresponding field fallback to custom.
|
||||
const configModelStyle: ModelStyle =
|
||||
modelRecord.model_style ?? ModelStyle.Custom;
|
||||
const flattedModelValues = convertModelInfoToFlatObject(modelRecord);
|
||||
@@ -140,8 +140,8 @@ export const useHandleModelForm = ({
|
||||
const customizeValue = customizeValueMap[currentModelId];
|
||||
|
||||
/**
|
||||
* 前端内存级别按照 Record<ModelId, Values> 保存用户的 custom 设置
|
||||
* 如果没有查找到用户的设置, 则沿用当前 bot/agent 的模型设置数据
|
||||
* Front-end memory level Save user's custom settings according to Record < ModelId, Values >
|
||||
* If the user's settings are not found, the model setting data of the current bot/agent is used
|
||||
*/
|
||||
const expectValue = merge(
|
||||
{},
|
||||
|
||||
@@ -28,7 +28,7 @@ interface FieldInitStrategy {
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户修改模型“生成多样性”参数时,切换为“自定义”模式
|
||||
* Switch to "Custom" mode when the user modifies the model "Generate Diversity" parameter
|
||||
*/
|
||||
class CustomModelStyleStrategy implements FieldInitStrategy {
|
||||
handler: (_field: DataField, form: Form) => void = (_field, form) =>
|
||||
@@ -49,7 +49,7 @@ function isDataField(field: GeneralField): field is DataField {
|
||||
}
|
||||
|
||||
/**
|
||||
* 当某个字段值小于阈值时,使用 field.feedbacks 显示提示文案
|
||||
* When a field value is less than the threshold, use field.feedbacks to display prompt text
|
||||
* https://core.formilyjs.org/zh-CN/api/models/field#ifieldfeedback
|
||||
*/
|
||||
class MinimumValueStrategy implements FieldInitStrategy {
|
||||
@@ -80,8 +80,8 @@ class MinimumValueStrategy implements FieldInitStrategy {
|
||||
|
||||
export const fieldInitStrategies = [
|
||||
new CustomModelStyleStrategy(),
|
||||
// 重复语句惩罚 < 0 时,显示提示文案
|
||||
// When the repeated sentence penalty is < 0, the prompt copy is displayed
|
||||
new MinimumValueStrategy('frequency_penalty', 0, 'model_setting_alert'),
|
||||
// 最大回复长度 < 100 时,显示提示文案
|
||||
// When the maximum reply length is < 100, the prompt copy is displayed
|
||||
new MinimumValueStrategy('max_tokens', 100, 'model_setting_alert_2'),
|
||||
];
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
} from '@coze-arch/bot-api/developer_api';
|
||||
|
||||
interface AgentModelFuncConfigCheckContext {
|
||||
// agent 中的 dataset 可能缺少元信息,需要获取完整数据的方法
|
||||
// The dataset in the agent may lack meta information and require a way to obtain the complete data
|
||||
getDatasetById: (id: string) => Dataset | undefined;
|
||||
config: Model['func_config'];
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ export const convertFormValueToModelInfo = (
|
||||
values: Record<string, unknown>,
|
||||
): ModelInfo => {
|
||||
const { HistoryRound, ContextContentType, ...rest } = values;
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- 不适用这个 case
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- not applicable to this case
|
||||
const ShortMemPolicy: ShortMemPolicy = {};
|
||||
|
||||
if (typeof HistoryRound === 'number') {
|
||||
|
||||
@@ -38,8 +38,8 @@ export const getFixedModelFormValues = (
|
||||
const parameterType = targetParameter.type;
|
||||
const { options } = targetParameter;
|
||||
|
||||
// 修正 枚举 类型的参数不在枚举范围内
|
||||
// IDL 无法写范型 转换成 string 比较
|
||||
// Fixed that parameters of type enumeration are not in the scope of enumeration
|
||||
// IDL cannot write paradigm, converted to string comparison
|
||||
if (options?.length) {
|
||||
if (options.findIndex(option => option.value === String(value)) >= 0) {
|
||||
return;
|
||||
@@ -50,7 +50,7 @@ export const getFixedModelFormValues = (
|
||||
);
|
||||
}
|
||||
|
||||
// 修正 number 类型的参数超过最大、最小值
|
||||
// Fixed number type parameters exceeding maximum and minimum values
|
||||
if (
|
||||
parameterType === ModelParamType.Float ||
|
||||
parameterType === ModelParamType.Int
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import { uniq } from 'lodash-es';
|
||||
/**
|
||||
* 以 class id 首次出现的顺序进行排序
|
||||
* Sort in the order in which the class id first appears
|
||||
*/
|
||||
export const getModelClassSortList = (classIdList: string[]) =>
|
||||
uniq(classIdList);
|
||||
|
||||
Reference in New Issue
Block a user