diff --git a/docSite/assets/imgs/image-51.png b/docSite/assets/imgs/image-51.png new file mode 100644 index 000000000..7e363302f Binary files /dev/null and b/docSite/assets/imgs/image-51.png differ diff --git a/docSite/assets/imgs/image-52.png b/docSite/assets/imgs/image-52.png new file mode 100644 index 000000000..ecccb3e0e Binary files /dev/null and b/docSite/assets/imgs/image-52.png differ diff --git a/docSite/assets/imgs/image-53.png b/docSite/assets/imgs/image-53.png new file mode 100644 index 000000000..80f2248d4 Binary files /dev/null and b/docSite/assets/imgs/image-53.png differ diff --git a/docSite/assets/imgs/image-54.png b/docSite/assets/imgs/image-54.png new file mode 100644 index 000000000..686805149 Binary files /dev/null and b/docSite/assets/imgs/image-54.png differ diff --git a/docSite/content/zh-cn/docs/guide/course/ai_settings.md b/docSite/content/zh-cn/docs/guide/course/ai_settings.md index 8f748bfb5..658d0904e 100644 --- a/docSite/content/zh-cn/docs/guide/course/ai_settings.md +++ b/docSite/content/zh-cn/docs/guide/course/ai_settings.md @@ -11,11 +11,14 @@ weight: 104 | | | | | --- | --- | --- | -| ![](/imgs/aichat0.png) | ![](/imgs/aichat02.png) | ![](/imgs/aichat2.png) | +| ![alt text](/imgs/image-51.png) | ![alt text](/imgs/image-52.png) | ![alt text](/imgs/image-53.png) | -## 返回AI内容(高级编排特有) +## 流响应(高级编排 AI 对话 特有) -这是一个开关,打开的时候,当 AI 对话模块运行时,会将其输出的内容返回到浏览器(API响应);如果关闭,AI 输出的内容不会返回到浏览器,但是生成的内容仍可以通过【AI回复】进行输出。你可以将【AI回复】连接到其他模块中。 +旧版名字叫做:返回 AI 内容;新版改名:流响应。 + +这是一个开关,打开的时候,当 AI 对话模块运行时,会将其输出的内容返回到浏览器(API响应); +如果关闭,会强制使用非流模式调用模型,并且 AI 输出的内容不会返回到浏览器,但是生成的内容仍可以通过【AI回复】进行输出。你可以将【AI回复】连接到其他模块中进行二次使用。 ### 最大上下文 @@ -33,13 +36,25 @@ weight: 104 最大回复 token 数量。注意,是回复的Tokens!不是上下文 tokens。 +通常,回复上限=min(模型允许的最大回复上限, 最大上下文-已用上下文) + +所以,一般配置模型时,不会把最大上下文配置成模型实际最大上下文,而是预留预定空间给回答,例如 128k 模型,可以配置 max_context=115000 + ### 系统提示词 被放置在上下文数组的最前面,role 为 system,用于引导模型。 +### 最大对话轮数(仅简易模式) + +可以配置模型支持的最大对话轮数,如果模型的超出上下文,系统会自动截断,尽可能保证不超模型上下文。 + +所以尽管配置 30 轮对话,实际运行时候,不一定会达到 30 轮。 + ## 引用模板 & 引用提示词 -这两个参数与知识库问答场景相关,可以控制知识库相关的提示词。 +进行知识库搜索后,你可以自定义组织检索结果构成的提示词,这个配置,仅工作流中 AI 对话节点可用。并且,只会在有引用知识库内容时才会生效。 + +![alt text](/imgs/image-54.png) ### AI 对话消息组成 diff --git a/packages/web/components/common/Image/PhotoView.tsx b/packages/web/components/common/Image/PhotoView.tsx index f1e71cf48..e7867e212 100644 --- a/packages/web/components/common/Image/PhotoView.tsx +++ b/packages/web/components/common/Image/PhotoView.tsx @@ -6,7 +6,7 @@ import { useSystem } from '../../../hooks/useSystem'; import Loading from '../MyLoading'; import MyImage from './MyImage'; -const MyPhotoView = ({ ...props }: ImageProps) => { +const MyPhotoView = (props: ImageProps) => { const { isPc } = useSystem(); return ( diff --git a/packages/web/components/common/MySlider/InputSlider.tsx b/packages/web/components/common/MySlider/InputSlider.tsx new file mode 100644 index 000000000..aefc9f568 --- /dev/null +++ b/packages/web/components/common/MySlider/InputSlider.tsx @@ -0,0 +1,76 @@ +import React, { useMemo } from 'react'; +import { Slider, SliderTrack, SliderThumb, HStack, SliderMark } from '@chakra-ui/react'; +import MyNumberInput from '../Input/NumberInput'; + +const InputSlider = ({ + onChange, + value, + max = 100, + min = 0, + step = 1 +}: { + value: number; + onChange: (index: number) => void; + max: number; + min: number; + step?: number; +}) => { + const markList = useMemo(() => { + const valLen = max - min; + return [ + valLen * 0.007 + min, + valLen * 0.2 + min, + valLen * 0.4 + min, + valLen * 0.6 + min, + valLen * 0.8 + min, + valLen * 0.985 + min + ]; + }, []); + + return ( + + + + {markList.map((val, i) => ( + + ))} + + + onChange(e ?? min)} + /> + + ); +}; + +export default InputSlider; diff --git a/packages/web/context/useSystem.tsx b/packages/web/context/useSystem.tsx index 9462b484c..f1439e066 100644 --- a/packages/web/context/useSystem.tsx +++ b/packages/web/context/useSystem.tsx @@ -25,18 +25,20 @@ const SystemStoreContextProvider = ({ children: ReactNode; device?: 'pc' | 'mobile' | null; }) => { - const [isPc] = useMediaQuery('(min-width: 900px)'); - + const [isPc] = useMediaQuery('(min-width: 900px)', { + fallback: device === 'pc' + }); useEffect(() => { setSize(isPc ? 'pc' : 'mobile'); }, [isPc]); const contextValue = useMemo( () => ({ - isPc: device ? device === 'pc' : isPc + isPc }), - [device, isPc] + [isPc] ); + return ( {children} ); diff --git a/packages/web/i18n/en/app.json b/packages/web/i18n/en/app.json index 1b63bdde9..25a653eff 100644 --- a/packages/web/i18n/en/app.json +++ b/packages/web/i18n/en/app.json @@ -3,6 +3,7 @@ "Run": "Execute", "Team Tags Set": "Team tags", "Team_Tags": "Team tags", + "ai_point_price": "Billing", "ai_settings": "AI Configuration", "all_apps": "All Applications", "app.Version name": "Version Name", @@ -19,8 +20,9 @@ "auto_execute_tip": "After turning it on, the workflow will be automatically triggered when the user enters the conversation interface. \nExecution order: 1. Dialogue starter; 2. Global variables; 3. Automatic execution.", "auto_save": "Auto save", "chat_debug": "Chat Preview", - "chat_logs": "Conversation Logs", + "chat_logs": "Logs", "chat_logs_tips": "Logs will record the online, shared, and API (requires chatId) conversation records of this app.", + "config_ai_model_params": "Click to configure AI model related properties", "config_file_upload": "Click to Configure File Upload Rules", "config_question_guide": "Configuration guess you want to ask", "confirm_copy_app_tip": "The system will create an app with the same configuration for you, but permissions will not be copied. Please confirm!", @@ -68,13 +70,15 @@ "interval.per_hour": "Every Hour", "intro": "A comprehensive model application orchestration system that offers out-of-the-box data processing and model invocation capabilities. It allows for rapid Dataset construction and workflow orchestration through Flow visualization, enabling complex Dataset scenarios!", "llm_not_support_vision": "This model does not support image recognition", - "llm_use_vision": "Enable Image Recognition", + "llm_use_vision": "Vision", "llm_use_vision_tip": "After clicking on the model selection, you can see whether the model supports image recognition and the ability to control whether to start image recognition. \nAfter starting image recognition, the model will read the image content in the file link, and if the user question is less than 500 words, it will automatically parse the image in the user question.", "logs_chat_user": "user", "logs_empty": "No logs yet~", "logs_message_total": "Total Messages", "logs_title": "Title", + "look_ai_point_price": "View all model billing standards", "mark_count": "Number of Marked Answers", + "max_histories_number": "Max histories", "module.Custom Title Tip": "This title will be displayed during the conversation.", "module.No Modules": "No Plugins Found", "module.type": "\"{{type}}\" type\n{{description}}", @@ -96,13 +100,15 @@ "plugin_cost_per_times": "{{cost}} points/time", "plugin_dispatch": "Plugin Invocation", "plugin_dispatch_tip": "Adds extra capabilities to the model. The specific plugins to be invoked will be autonomously decided by the model.\nIf a plugin is selected, the Dataset invocation will automatically be treated as a special plugin.", - "publish_channel": "Publish Channel", + "publish_channel": "Publish", "publish_success": "Publish Successful", "question_guide_tip": "After the conversation, 3 guiding questions will be generated for you.", "saved_success": "Save Successful", "search_app": "Search Application", - "setting_app": "Application Settings", - "setting_plugin": "Plugin Settings", + "setting_app": "Workflow", + "setting_plugin": "Workflow", + "stream_response": "Stream", + "stream_response_tip": "Turning this switch off forces the model to use non-streaming mode and will not output content directly. \nIn the output of the AI ​​reply, the content output by this model can be obtained for secondary processing.", "template.hard_strict": "Strict Q&A template", "template.hard_strict_des": "Based on the question and answer template, stricter requirements are imposed on the model's answers.", "template.qa_template": "Q&A template", @@ -164,7 +170,7 @@ "workflow.form_input_description_placeholder": "For example: \nAdd your information", "workflow.form_input_tip": " This module can configure multiple inputs to guide users in entering specific content.", "workflow.input_description_tip": "You can add a description to explain to users what they need to input", - "workflow.read_files": "Document Parsing", + "workflow.read_files": "Document Parse", "workflow.read_files_result": "Document Parsing Result", "workflow.read_files_result_desc": "Original document text, consisting of file names and document content, separated by hyphens between multiple files.", "workflow.read_files_tip": "Parse the documents uploaded in this round of dialogue and return the corresponding document content", @@ -175,6 +181,6 @@ "workflow.template.communication": "Communication", "workflow.user_file_input": "File Link", "workflow.user_file_input_desc": "Links to documents and images uploaded by users.", - "workflow.user_select": "User Selection", + "workflow.user_select": "User Select", "workflow.user_select_tip": "This module can configure multiple options for selection during the dialogue. Different options can lead to different workflow branches." } diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index 4ac9fa80a..1900c9dd1 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -261,17 +261,14 @@ "contribute_app_template": "Contribute Template", "core.Chat": "Chat", "core.Max Token": "Max Token", - "core.ai.AI settings": "AI Settings", - "core.ai.Ai point price": "AI Points Consumption", "core.ai.Max context": "Max Context", - "core.ai.Model": "AI Model", + "core.ai.Model": "Model", "core.ai.Not deploy rerank model": "Re-rank Model Not Deployed", "core.ai.Prompt": "Prompt", "core.ai.Support tool": "Function Call", "core.ai.model.Dataset Agent Model": "File read model", "core.ai.model.Vector Model": "Index model", "core.ai.model.doc_index_and_dialog": "Document Index & Dialog Index", - "core.app.Ai response": "AI Response", "core.app.Api request": "API Request", "core.app.Api request desc": "Integrate into existing systems through API, or WeChat Work, Feishu, etc.", "core.app.App intro": "App Introduction", @@ -284,8 +281,7 @@ "core.app.Interval timer run": "Scheduled Execution", "core.app.Interval timer tip": "Can Execute App on Schedule", "core.app.Make a brief introduction of your app": "Give Your AI App an Introduction", - "core.app.Max histories": "Number of Chat Histories", - "core.app.Max tokens": "Response Limit", + "core.app.Max tokens": "Max response", "core.app.Name and avatar": "Avatar & Name", "core.app.Publish": "Publish", "core.app.Publish Confirm": "Confirm to Publish App? This Will Immediately Update the App Status on All Publishing Channels.", diff --git a/packages/web/i18n/en/workflow.json b/packages/web/i18n/en/workflow.json index 5b92f9048..a76add2cc 100644 --- a/packages/web/i18n/en/workflow.json +++ b/packages/web/i18n/en/workflow.json @@ -18,13 +18,13 @@ "classification_result": "Classification Result", "code.Reset template": "Reset Template", "code.Reset template confirm": "Confirm reset code template? This will reset all inputs and outputs to template values. Please save your current code.", - "code_execution": "Code Execution", + "code_execution": "Code Sandbox", "collection_metadata_filter": "Collection Metadata Filter", "complete_extraction_result": "Complete Extraction Result", "complete_extraction_result_description": "A JSON string, e.g., {\"name\":\"YY\",\"Time\":\"2023/7/2 18:00\"}", "concatenation_result": "Concatenation Result", "concatenation_text": "Concatenation Text", - "condition_checker": "Condition Checker", + "condition_checker": "Condition", "confirm_delete_field_tip": "Confirm delete this field?", "contains": "Contains", "content_to_retrieve": "Content to Retrieve", @@ -69,7 +69,7 @@ "http_extract_output": "Output field extraction", "http_extract_output_description": "Specified fields in the response value can be extracted through JSONPath syntax", "http_raw_response_description": "Raw HTTP response. Only accepts string or JSON type response data.", - "http_request": "HTTP Request", + "http_request": "HTTP", "http_request_error_info": "HTTP request error information, returns empty on success", "ifelse.Input value": "Input Value", "ifelse.Select value": "Select Value", @@ -96,7 +96,7 @@ "is_tool_output_label": "as tool response", "judgment_result": "Judgment Result", "knowledge_base_reference": "Dataset Reference", - "knowledge_base_search_merge": "Dataset Search Merge", + "knowledge_base_search_merge": "Dataset Merge", "laf_function_call_test": "Laf Function Call (Test)", "length_equal_to": "Length Equal To", "length_greater_than": "Length Greater Than", @@ -106,7 +106,7 @@ "length_not_equal_to": "Length Not Equal To", "less_than": "Less Than", "less_than_or_equal_to": "Less Than or Equal To", - "loop": "Batch execution", + "loop": "Batch Run", "loop_body": "loop body", "loop_end": "end of loop", "loop_input_array": "array", @@ -128,8 +128,8 @@ "plugin_file_abandon_tip": "Plugin global file upload has been deprecated, please adjust it as soon as possible. \nRelated functions can be achieved through plug-in input and adding image type input.", "plugin_input": "Plugin Input", "plugin_output_tool": "When the plug-in is executed as a tool, whether this field responds as a result of the tool", - "question_classification": "Question Classification", - "question_optimization": "Question Optimization", + "question_classification": "Classify", + "question_optimization": "Query extension", "quote_content_placeholder": "The structure of the reference content can be customized to better suit different scenarios. \nSome variables can be used for template configuration\n\n{{q}} - main content\n\n{{a}} - auxiliary data\n\n{{source}} - source name\n\n{{sourceId}} - source ID\n\n{{index}} - nth reference", "quote_content_tip": "The structure of the reference content can be customized to better suit different scenarios. Some variables can be used for template configuration:\n\n{{q}} - main content\n{{a}} - auxiliary data\n{{source}} - source name\n{{sourceId}} - source ID\n{{index}} - nth reference\nThey are all optional and the following are the default values:\n\n{{default}}", "quote_num": "Dataset", @@ -159,16 +159,16 @@ "template.forbid_stream_desc": "Forces the output mode of nested application streams to be disabled", "template.plugin_output": "Plugin output", "template.plugin_start": "Plugin start", - "template.system_config": "System Configuration", + "template.system_config": "System", "template.tool_call": "Tool Call", "template.tool_call_intro": "Automatically select one or more functional blocks for calling through the AI model, or call plugins.", - "template.workflow_start": "Workflow Start", - "text_concatenation": "Text Concatenation", - "text_content_extraction": "Text Content Extraction", + "template.workflow_start": "Start", + "text_concatenation": "Text Editor", + "text_content_extraction": "Text Extract", "text_to_extract": "Text to Extract", "these_variables_will_be_input_parameters_for_code_execution": "These variables will be input parameters for code execution", - "tool_call_termination": "Tool Call Termination", - "tool_custom_field": "Custom tool parameters", + "tool_call_termination": "Stop ToolCall", + "tool_custom_field": "Custom Tool", "tool_field": " Tool Field Parameter Configuration", "tool_input": "Tool Input", "tool_params.enum_placeholder": "apple \npeach \nwatermelon", diff --git a/packages/web/i18n/zh-CN/app.json b/packages/web/i18n/zh-CN/app.json index fd6561aa6..24c2dbaf8 100644 --- a/packages/web/i18n/zh-CN/app.json +++ b/packages/web/i18n/zh-CN/app.json @@ -3,6 +3,7 @@ "Run": "运行", "Team Tags Set": "团队标签", "Team_Tags": "团队标签", + "ai_point_price": "AI积分计费", "ai_settings": "AI 配置", "all_apps": "全部应用", "app.Version name": "版本名称", @@ -21,6 +22,7 @@ "chat_debug": "调试预览", "chat_logs": "对话日志", "chat_logs_tips": "日志会记录该应用的在线、分享和 API(需填写 chatId)对话记录", + "config_ai_model_params": "点击配置 AI 模型相关属性", "config_file_upload": "点击配置文件上传规则", "config_question_guide": "配置猜你想问", "confirm_copy_app_tip": "系统将为您创建一个相同配置应用,但权限不会进行复制,请确认!", @@ -74,7 +76,9 @@ "logs_empty": "还没有日志噢~", "logs_message_total": "消息总数", "logs_title": "标题", + "look_ai_point_price": "查看所有模型计费标准", "mark_count": "标注答案数量", + "max_histories_number": "最大对话轮数", "module.Custom Title Tip": "该标题名字会展示在对话过程中", "module.No Modules": "没找到插件", "module.type": "\"{{type}}\"类型\n{{description}}", @@ -103,6 +107,8 @@ "search_app": "搜索应用", "setting_app": "应用配置", "setting_plugin": "插件配置", + "stream_response": "流输出", + "stream_response_tip": "关闭该开关,可以强制模型使用非流模式,并且不会直接进行内容输出。可以在 AI 回复的输出中,获取本次模型输出的内容进行二次处理。", "template.hard_strict": "严格问答模板", "template.hard_strict_des": "在问答模板基础上,对模型的回答做更严格的要求。", "template.qa_template": "问答模板", diff --git a/packages/web/i18n/zh-CN/common.json b/packages/web/i18n/zh-CN/common.json index e92904693..39bfc1381 100644 --- a/packages/web/i18n/zh-CN/common.json +++ b/packages/web/i18n/zh-CN/common.json @@ -260,8 +260,6 @@ "contribute_app_template": "贡献模板", "core.Chat": "对话", "core.Max Token": "单条数据上限", - "core.ai.AI settings": "AI 配置", - "core.ai.Ai point price": "AI 积分消耗", "core.ai.Max context": "最大上下文", "core.ai.Model": "AI 模型", "core.ai.Not deploy rerank model": "未部署重排模型", @@ -270,7 +268,6 @@ "core.ai.model.Dataset Agent Model": "文本理解模型", "core.ai.model.Vector Model": "索引模型", "core.ai.model.doc_index_and_dialog": "文档索引 & 对话索引", - "core.app.Ai response": "返回 AI 内容", "core.app.Api request": "API 访问", "core.app.Api request desc": "通过 API 接入到已有系统中,或企微、飞书等", "core.app.App intro": "应用介绍", @@ -283,7 +280,6 @@ "core.app.Interval timer run": "定时执行", "core.app.Interval timer tip": "可定时执行应用", "core.app.Make a brief introduction of your app": "给你的 AI 应用一个介绍", - "core.app.Max histories": "聊天记录数量", "core.app.Max tokens": "回复上限", "core.app.Name and avatar": "头像 & 名称", "core.app.Publish": "发布", diff --git a/packages/web/i18n/zh-Hant/app.json b/packages/web/i18n/zh-Hant/app.json index 0f09f18ef..3d9a16c31 100644 --- a/packages/web/i18n/zh-Hant/app.json +++ b/packages/web/i18n/zh-Hant/app.json @@ -3,6 +3,7 @@ "Run": "執行", "Team Tags Set": "團隊標籤", "Team_Tags": "團隊標籤", + "ai_point_price": "AI積分計費", "ai_settings": "AI 設定", "all_apps": "所有應用程式", "app.Version name": "版本名稱", @@ -21,6 +22,7 @@ "chat_debug": "聊天預覽", "chat_logs": "對話紀錄", "chat_logs_tips": "紀錄會記錄此應用程式的線上、分享和 API(需填寫 chatId)對話紀錄", + "config_ai_model_params": "點選配置 AI 模型相關屬性", "config_file_upload": "點選設定檔案上傳規則", "config_question_guide": "配置猜你想問", "confirm_copy_app_tip": "系統將為您建立一個相同設定的應用程式,但權限不會複製,請確認!", @@ -74,7 +76,9 @@ "logs_empty": "還沒有紀錄喔~", "logs_message_total": "訊息總數", "logs_title": "標題", + "look_ai_point_price": "查看所有模型計費標準", "mark_count": "標記答案數量", + "max_histories_number": "最大對話輪數", "module.Custom Title Tip": "這個標題會顯示在對話過程中", "module.No Modules": "找不到外掛", "module.type": "\"{{type}}\" 類型\n{{description}}", @@ -103,6 +107,8 @@ "search_app": "搜尋應用程式", "setting_app": "應用程式設定", "setting_plugin": "外掛設定", + "stream_response": "流輸出", + "stream_response_tip": "關閉該開關​​,可以強制模型使用非流模式,並且不會直接進行內容輸出。\n可在 AI 回覆的輸出中,取得本次模型輸出的內容進行二次處理。", "template.hard_strict": "嚴格問答範本", "template.hard_strict_des": "在問答範本基礎上,對模型的回答做出更嚴格的要求。", "template.qa_template": "問答範本", diff --git a/packages/web/i18n/zh-Hant/common.json b/packages/web/i18n/zh-Hant/common.json index 17216d3bb..e59ab6595 100644 --- a/packages/web/i18n/zh-Hant/common.json +++ b/packages/web/i18n/zh-Hant/common.json @@ -261,8 +261,6 @@ "contribute_app_template": "貢獻範本", "core.Chat": "對話", "core.Max Token": "單筆資料上限", - "core.ai.AI settings": "AI 設定", - "core.ai.Ai point price": "AI 點數消耗", "core.ai.Max context": "最大上下文", "core.ai.Model": "AI 模型", "core.ai.Not deploy rerank model": "未部署重新排名模型", @@ -271,7 +269,6 @@ "core.ai.model.Dataset Agent Model": "檔案處理模型", "core.ai.model.Vector Model": "索引模型", "core.ai.model.doc_index_and_dialog": "文件索引與對話索引", - "core.app.Ai response": "AI 回應", "core.app.Api request": "API 存取", "core.app.Api request desc": "透過 API 整合到現有系統中,或整合到企業微信、飛書等", "core.app.App intro": "應用程式介紹", @@ -284,7 +281,6 @@ "core.app.Interval timer run": "排程執行", "core.app.Interval timer tip": "可排程執行應用程式", "core.app.Make a brief introduction of your app": "為您的 AI 應用程式寫一段介紹", - "core.app.Max histories": "聊天記錄數量", "core.app.Max tokens": "回應上限", "core.app.Name and avatar": "頭像與名稱", "core.app.Publish": "發布", diff --git a/projects/app/src/components/core/ai/AISettingModal/index.tsx b/projects/app/src/components/core/ai/AISettingModal/index.tsx index 2219faa94..314d83476 100644 --- a/projects/app/src/components/core/ai/AISettingModal/index.tsx +++ b/projects/app/src/components/core/ai/AISettingModal/index.tsx @@ -7,10 +7,18 @@ import { BoxProps, Button, Flex, - Link, + HStack, ModalBody, ModalFooter, - Switch + Switch, + TableContainer, + Tbody, + Td, + Th, + Thead, + Tr, + Table, + useDisclosure } from '@chakra-ui/react'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import MySlider from '@/components/Slider'; @@ -21,6 +29,13 @@ import AIModelSelector from '@/components/Select/AIModelSelector'; import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import { getWebLLMModel } from '@/web/common/system/utils'; +import MyIcon from '@fastgpt/web/components/common/Icon'; +import dynamic from 'next/dynamic'; +import InputSlider from '@fastgpt/web/components/common/MySlider/InputSlider'; + +const AiPointsModal = dynamic(() => + import('@/pages/price/components/Points').then((mod) => mod.AiPointsModal) +); const AIChatSettingsModal = ({ onClose, @@ -35,7 +50,7 @@ const AIChatSettingsModal = ({ }) => { const { t } = useTranslation(); const [refresh, setRefresh] = useState(false); - const { feConfigs, llmModelList } = useSystemStore(); + const { feConfigs } = useSystemStore(); const { handleSubmit, getValues, setValue, watch } = useForm({ defaultValues: defaultData @@ -69,30 +84,35 @@ const AIChatSettingsModal = ({ alignItems: 'center', fontSize: 'sm', color: 'myGray.900', - width: ['6rem', '8rem'] + width: '7rem' }; + const { + isOpen: isOpenAiPointsModal, + onClose: onCloseAiPointsModal, + onOpen: onOpenAiPointsModal + } = useDisclosure(); + return ( - {t('common:core.ai.AI settings')} + + {t('app:ai_settings')} {feConfigs?.docUrl && ( - - {t('common:common.Read intro')} - + { + window.open(getDocPath('/docs/guide/course/ai_settings/'), '_blank'); + }} + /> )} - + } w={'500px'} > @@ -113,48 +133,66 @@ const AIChatSettingsModal = ({ /> - {feConfigs && ( - - - {t('common:core.ai.Ai point price')} - - - {t('common:support.wallet.Ai point every thousand tokens', { - points: selectedModel?.charsPointsPrice || 0 - })} - - - )} - - - {t('common:core.ai.Max context')} - - {selectedModel?.maxContext || 4096}Tokens - - - - {t('common:core.ai.Support tool')} - - - - {selectedModel?.toolChoice || selectedModel?.functionCall - ? t('common:common.support') - : t('common:common.not_support')} - - - + + + + + + + + + + + + + + + + + +
+ + {t('app:ai_point_price')} + + + + {t('common:core.ai.Max context')} + + + {t('common:core.ai.Support tool')} + + +
+ {t('common:support.wallet.Ai point every thousand tokens', { + points: selectedModel?.charsPointsPrice || 0 + })} + + {Math.round((selectedModel?.maxContext || 4096) / 1000)}K + + {selectedModel?.toolChoice || selectedModel?.functionCall + ? t('common:common.support') + : t('common:common.not_support')} +
+
+ + {t('common:core.app.Temperature')} - - + { setValue(NodeInputKeyEnum.aiChatTemperature, e); @@ -163,20 +201,15 @@ const AIChatSettingsModal = ({ /> - + {t('common:core.app.Max tokens')} - - + { setValue(NodeInputKeyEnum.aiChatMaxToken, val); @@ -186,19 +219,15 @@ const AIChatSettingsModal = ({ {showMaxHistoriesSlider && ( - + - {t('common:core.app.Max histories')} + {t('app:max_histories_number')} - - + { setValue('maxHistories', e); @@ -209,13 +238,10 @@ const AIChatSettingsModal = ({ )} {showResponseAnswerText && ( - + - {t('common:core.app.Ai response')} - + {t('app:stream_response')} + )} {showVisionSwitch && ( - + {t('app:llm_use_vision')} @@ -261,6 +287,8 @@ const AIChatSettingsModal = ({ {t('common:common.Confirm')} + + {isOpenAiPointsModal && }
); }; diff --git a/projects/app/src/components/core/ai/SettingLLMModel/index.tsx b/projects/app/src/components/core/ai/SettingLLMModel/index.tsx index 2a2567ca0..c74e045db 100644 --- a/projects/app/src/components/core/ai/SettingLLMModel/index.tsx +++ b/projects/app/src/components/core/ai/SettingLLMModel/index.tsx @@ -1,16 +1,14 @@ import React, { useMemo } from 'react'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { LLMModelTypeEnum, llmModelTypeFilterMap } from '@fastgpt/global/core/ai/constants'; -import { Box, Button, css, useDisclosure } from '@chakra-ui/react'; +import { Box, css, HStack, IconButton, useDisclosure } from '@chakra-ui/react'; import type { SettingAIDataType } from '@fastgpt/global/core/app/type.d'; import AISettingModal from '@/components/core/ai/AISettingModal'; -import Avatar from '@fastgpt/web/components/common/Avatar'; -import { HUGGING_FACE_ICON } from '@fastgpt/global/common/system/constants'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import { useTranslation } from 'next-i18next'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { useMount } from 'ahooks'; -import { getModelFromList } from '@fastgpt/global/core/ai/model'; +import AIModelSelector from '@/components/Select/AIModelSelector'; type Props = { llmModelType?: `${LLMModelTypeEnum}`; @@ -19,12 +17,7 @@ type Props = { bg?: string; }; -const SettingLLMModel = ({ - llmModelType = LLMModelTypeEnum.all, - defaultData, - onChange, - bg = 'white' -}: Props) => { +const SettingLLMModel = ({ llmModelType = LLMModelTypeEnum.all, defaultData, onChange }: Props) => { const { t } = useTranslation(); const { llmModelList } = useSystemStore(); @@ -41,15 +34,6 @@ const SettingLLMModel = ({ }), [llmModelList, llmModelType] ); - - const selectedModel = useMemo(() => getModelFromList(modelList, model), [modelList, model]); - - const { - isOpen: isOpenAIChatSetting, - onOpen: onOpenAIChatSetting, - onClose: onCloseAIChatSetting - } = useDisclosure(); - // Set default model useMount(() => { if (!model && modelList.length > 0) { @@ -60,6 +44,12 @@ const SettingLLMModel = ({ } }); + const { + isOpen: isOpenAIChatSetting, + onOpen: onOpenAIChatSetting, + onClose: onCloseAIChatSetting + } = useDisclosure(); + return ( - - - + + + ({ + value: item.model, + label: item.name + }))} + onchange={(e) => { + onChange({ + ...defaultData, + model: e + }); + }} + /> + + + } + aria-label={''} + size={'mdSquare'} + onClick={onOpenAIChatSetting} + /> + + {isOpenAIChatSetting && (