提交 eadfbd45 authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 25767edf
......@@ -24,8 +24,9 @@
"openai": "^4.87.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-markdown": "^10.1.0",
"react-markdown": "^10.0.0",
"react-router": "^7.3.0",
"react-syntax-highlighter": "^15.6.1",
"remark-gfm": "^4.0.1",
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
"zustand": "^5.0.3"
......@@ -2835,6 +2836,19 @@
"reusify": "^1.0.4"
}
},
"node_modules/fault": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz",
"integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==",
"license": "MIT",
"dependencies": {
"format": "^0.2.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
......@@ -2941,6 +2955,14 @@
"integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==",
"license": "MIT"
},
"node_modules/format": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
"integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==",
"engines": {
"node": ">=0.4.x"
}
},
"node_modules/formdata-node": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
......@@ -3186,6 +3208,16 @@
"node": ">= 0.4"
}
},
"node_modules/hast-util-parse-selector": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz",
"integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-to-jsx-runtime": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
......@@ -3226,6 +3258,86 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/hastscript": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz",
"integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==",
"license": "MIT",
"dependencies": {
"@types/hast": "^2.0.0",
"comma-separated-tokens": "^1.0.0",
"hast-util-parse-selector": "^2.0.0",
"property-information": "^5.0.0",
"space-separated-tokens": "^1.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hastscript/node_modules/@types/hast": {
"version": "2.3.10",
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz",
"integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==",
"license": "MIT",
"dependencies": {
"@types/unist": "^2"
}
},
"node_modules/hastscript/node_modules/@types/unist": {
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
"license": "MIT"
},
"node_modules/hastscript/node_modules/comma-separated-tokens": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz",
"integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/hastscript/node_modules/property-information": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz",
"integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==",
"license": "MIT",
"dependencies": {
"xtend": "^4.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/hastscript/node_modules/space-separated-tokens": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz",
"integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/highlight.js": {
"version": "10.7.3",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
"integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
"license": "BSD-3-Clause",
"engines": {
"node": "*"
}
},
"node_modules/highlightjs-vue": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz",
"integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==",
"license": "CC0-1.0"
},
"node_modules/html-url-attributes": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
......@@ -3544,6 +3656,20 @@
"loose-envify": "cli.js"
}
},
"node_modules/lowlight": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz",
"integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==",
"license": "MIT",
"dependencies": {
"fault": "^1.0.0",
"highlight.js": "~10.7.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/lucide-react": {
"version": "0.477.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.477.0.tgz",
......@@ -4791,6 +4917,15 @@
"node": ">= 0.8.0"
}
},
"node_modules/prismjs": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
"integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/property-information": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/property-information/-/property-information-7.0.0.tgz",
......@@ -5476,9 +5611,9 @@
"license": "MIT"
},
"node_modules/react-markdown": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz",
"integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==",
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.0.0.tgz",
"integrity": "sha512-4mTz7Sya/YQ1jYOrkwO73VcFdkFJ8L8I9ehCxdcV0XrClHyOJGKbBk5FR4OOOG+HnyKw5u+C/Aby9TwinCteYA==",
"license": "MIT",
"dependencies": {
"@types/hast": "^3.0.0",
......@@ -5526,6 +5661,139 @@
}
}
},
"node_modules/react-syntax-highlighter": {
"version": "15.6.1",
"resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.1.tgz",
"integrity": "sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.3.1",
"highlight.js": "^10.4.1",
"highlightjs-vue": "^1.0.0",
"lowlight": "^1.17.0",
"prismjs": "^1.27.0",
"refractor": "^3.6.0"
},
"peerDependencies": {
"react": ">= 0.14.0"
}
},
"node_modules/refractor": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz",
"integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==",
"license": "MIT",
"dependencies": {
"hastscript": "^6.0.0",
"parse-entities": "^2.0.0",
"prismjs": "~1.27.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/refractor/node_modules/character-entities": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
"integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/refractor/node_modules/character-entities-legacy": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
"integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/refractor/node_modules/character-reference-invalid": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
"integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/refractor/node_modules/is-alphabetical": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
"integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/refractor/node_modules/is-alphanumerical": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
"integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
"license": "MIT",
"dependencies": {
"is-alphabetical": "^1.0.0",
"is-decimal": "^1.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/refractor/node_modules/is-decimal": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
"integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/refractor/node_modules/is-hexadecimal": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
"integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/refractor/node_modules/parse-entities": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
"integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
"license": "MIT",
"dependencies": {
"character-entities": "^1.0.0",
"character-entities-legacy": "^1.0.0",
"character-reference-invalid": "^1.0.0",
"is-alphanumerical": "^1.0.0",
"is-decimal": "^1.0.0",
"is-hexadecimal": "^1.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/refractor/node_modules/prismjs": {
"version": "1.27.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz",
"integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
......@@ -6736,6 +7004,15 @@
"node": ">=0.8"
}
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"license": "MIT",
"engines": {
"node": ">=0.4"
}
},
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
......
......@@ -26,8 +26,9 @@
"openai": "^4.87.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-markdown": "^10.1.0",
"react-markdown": "^10.0.0",
"react-router": "^7.3.0",
"react-syntax-highlighter": "^15.6.1",
"remark-gfm": "^4.0.1",
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
"zustand": "^5.0.3"
......
......@@ -22,7 +22,12 @@ export default function AppSteps({ items, ...props }: StepsProps) {
)
}
return (
<Steps className="app-process-steps" progressDot={customDot} labelPlacement="vertical" {...props}>
<Steps
className="app-process-steps"
progressDot={customDot}
labelPlacement="vertical"
style={{ margin: '80px' }}
{...props}>
{items?.map(({ title, ...item }, index) => {
return (
<Steps.Step
......
import Markdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
import { dark } from 'react-syntax-highlighter/dist/esm/styles/prism'
export default function MarkdownRender(props: { children?: string }) {
return <Markdown remarkPlugins={[remarkGfm]}>{props.children}</Markdown>
return (
<Markdown
remarkPlugins={[remarkGfm]}
components={{
code(props) {
console.log(props)
const { children, className, ...rest } = props
const match = /language-(\w+)/.exec(className || '')
return match ? (
<SyntaxHighlighter
{...rest}
PreTag="div"
children={String(children).replace(/\n$/, '')}
language={match[1]}
style={dark}
/>
) : (
<code {...rest} className={className}>
{children}
</code>
)
},
}}>
{props.children}
</Markdown>
)
}
import { useState, useEffect, useCallback } from 'react'
import { useState, useEffect, useCallback, useRef } from 'react'
import aiService, { AIMessage, AIData, AI_OPTIONS, InitOptions } from '@/utils/ai'
export function useAI(globalOptions?: InitOptions) {
const [ai, setAI] = useState<string>(localStorage.getItem('ai') || 'qwen')
const [messages, setMessages] = useState<AIMessage[]>([])
const [message, setMessage] = useState<AIMessage | null>(null) // 存储最新的消息
const [message, setMessage] = useState<AIMessage | null>(null)
const [isLoading, setIsLoading] = useState<boolean>(false)
// 使用 useRef 存储最新消息,避免闭包问题
const latestMessageRef = useRef<AIMessage | null>(null)
// 使用 useRef 存储消息列表,避免异步更新问题
const messagesRef = useRef<AIMessage[]>([])
useEffect(() => {
localStorage.setItem('ai', ai)
}, [ai])
// 更新消息的辅助函数
const updateMessage = useCallback((response: any, isNew: boolean) => {
if (isNew) {
// 新消息
const newMessage: AIMessage = {
id: response.id,
role: 'assistant',
content: response.content,
}
latestMessageRef.current = newMessage
messagesRef.current = [...messagesRef.current, newMessage]
// 更新状态
setMessage(newMessage)
setMessages(messagesRef.current)
} else {
// 更新现有消息
messagesRef.current = messagesRef.current.map((msg) => {
if (msg.id === response.id) {
const updatedMessage = {
...msg,
content: msg.content + response.content,
}
latestMessageRef.current = updatedMessage
setMessage(updatedMessage)
return updatedMessage
}
return msg
})
setMessages([...messagesRef.current])
}
}, [])
const post = useCallback(
async (data: AIData, options?: InitOptions) => {
try {
setIsLoading(true)
// 先添加用户消息(去掉 system 角色的消息)
// 添加用户消息
const userMessages = data.messages.filter((item) => item.role !== 'system')
setMessages((prevMessages) => [...prevMessages, ...userMessages])
let latestMessage: AIMessage | null = null
messagesRef.current = [...messagesRef.current, ...userMessages]
setMessages((prev) => [...prev, ...userMessages])
const onComplete = options?.onComplete || globalOptions?.onComplete
await aiService.post(ai, data, {
onMessage: (response) => {
setMessages((prevMessages) => {
const messageIndex = prevMessages.findIndex((msg) => msg.id === response.id)
if (messageIndex === -1) {
latestMessage = { id: response.id, role: 'assistant', content: response.content }
setMessage(latestMessage) // 更新最新消息
return [...prevMessages, latestMessage]
} else {
return prevMessages.map((msg) => {
if (msg.id === response.id) {
const updatedMessage = { ...msg, content: msg.content + response.content }
latestMessage = updatedMessage
setMessage(updatedMessage) // 更新最新消息
return updatedMessage
}
return msg
})
}
})
const messageIndex = messagesRef.current.findIndex((msg) => msg.id === response.id)
updateMessage(response, messageIndex === -1)
},
onerror: () => {
onerror: (error) => {
console.error('AI service error:', error)
setIsLoading(false)
},
onclose: () => {
setIsLoading(false)
if (latestMessage && onComplete) onComplete(latestMessage)
if (latestMessageRef.current && onComplete) {
onComplete(latestMessageRef.current)
}
},
...globalOptions,
...options,
})
} catch (error) {
console.error('Post error:', error)
setIsLoading(false)
}
},
[ai]
[ai, updateMessage, globalOptions]
)
return { ai, setAI, options: AI_OPTIONS, post, messages, message, isLoading }
return {
ai,
setAI,
options: AI_OPTIONS,
post,
messages,
message,
isLoading,
}
}
import { useState } from 'react'
import { Button, Flex, Modal, Select, Form, Input, Popover, Card } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useDataFieldQuery } from '@/hooks/useQuery'
import { useAI } from '@/hooks/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
const { fieldOptions } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const { post, isLoading } = useAI()
// AI设置
const handleAISet = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设计一个Apriori算法,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
分别返回是否拟合截距项(fit_intercept):true/false、是否复制数据(copy_x):true/false、并行计算核心数(n_jobs):None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)、强制正系数(positive):true/false的值。
返回格式示例:
json
{
"results": { "fit_intercept": true, "copy_x": true, "n_jobs": 1, "positive": false}
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
}
},
}
)
}
// AI计算
const [results, setResults] = useState<any>({})
const code = `${results.code?.replace(/\\n/gi, '\n')}`
const [openResults, setOpenResults] = useState(false)
const handleAICompute = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设置的Apriori算法进行试算检查,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
是否拟合截距项(fit_intercept):${values.fit_intercept}
是否复制数据(copy_X):${values.copy_x}
并行计算核心数(n_jobs):${values.n_jobs}
强制正系数(positive):${values.positive}
返回格式示例:
json
{
results: { pass: 'true或者false,代表通过不通过', code: "Python运行的代码,markdown能解析的代码", result: "计算结果" },
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
const options = [
{ label: 'True', value: true },
{ label: 'False', value: false },
]
// 处理下一步按钮逻辑
const handleNext = async () => {
await form.validateFields()
setCurrent(current + 1)
setStep(-1)
}
// 开始处理
const handleStart = () => {
setStep(1)
handleAICompute()
}
// 关闭并重置
const handleClose = () => {
setOpen(false)
setCurrent(0)
setStep(-1)
}
const steps = [
{
title: '设置算法',
content: (
<>
<Form.Item
label="请选择自变量"
name="independent_variables"
rules={[{ required: true, message: '请选择自变量' }]}>
<Select options={fieldOptions} placeholder="请选择" mode="multiple" />
</Form.Item>
<Form.Item
label="请选择因变量"
name="dependent_variable"
rules={[{ required: true, message: '请选择因变量' }]}>
<Select options={fieldOptions} placeholder="请选择" />
</Form.Item>
<Flex gap={20}>
<div style={{ flex: 1 }}>
<Form.Item label="请输入是否拟合截距项(fit_intercept)">
<Flex gap={10}>
<Form.Item name="fit_intercept" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否拟合截距项(fit_intercept)"
content={
<>
控制模型是否包含截距项(即偏置项,用于调整模型基线)
<br />
取值范围:
<br />
True(模型更灵活,适合大多数场景)
<br />
False(模型强制通过原点,可能欠拟合)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入是否复制数据(copy_X)">
<Flex gap={10}>
<Form.Item name="copy_x" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否复制数据(copy_X)"
content={
<>
决定是否复制输入数据(避免修改原始数据)
<br />
取值范围:
<br />
True(安全但内存占用高)
<br />
False(节省内存,但可能覆盖原始数据)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入并行计算核心数(n_jobs)">
<Flex gap={10}>
<Form.Item name="n_jobs" noStyle rules={[{ required: true, message: '请输入' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
title="并行计算核心数(n_jobs)"
content={
<>
选择优化算法(不同算法支持不同正则化类型和计算效率)
<br />
取值范围:
<br />
None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入强制正系数(positive)">
<Flex gap={10}>
<Form.Item name="positive" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="强制正系数(positive)"
content={
<>
是否强制回归系数为非负值(适用于需正向解释的场景,如经济学或物理模型)
<br />
取值范围:
<br />
True(系数非负,可能牺牲模型拟合能力)
<br />
False(系数可正可负,灵活性高)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
</div>
<Button type="primary" style={{ height: '200px' }} onClick={handleAISet} loading={isLoading}>
AI设置
</Button>
</Flex>
</>
),
},
{
title: 'Apriori处理',
content: (
<>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={handleStart} loading={isLoading}>
开始处理
</Button>
<AppProgressSteps current={step} items={[{ title: '启动' }, { title: '计算' }, { title: '计算结束' }]} />
</Flex>
</>
),
},
]
const Footer = () => {
return (
<Flex justify="center" gap={20}>
{current === 0 && (
<Button
type="primary"
onClick={() => {
setOpenResults(true)
handleAICompute()
}}
loading={isLoading}>
AI检查试算
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={handleNext}>
下一步
</Button>
)}
{current === steps.length - 1 && (
<Button type="primary" onClick={handleClose} disabled={isLoading}>
关闭
</Button>
)}
</Flex>
)
}
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
Apriori
</Button>
<Modal
title={steps[current].title}
open={open}
footer={<Footer />}
destroyOnClose
width={800}
onCancel={handleClose}>
<div style={{ minHeight: 300, padding: '20px 0' }}>
<Form form={form} preserve={false}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
{step >= 3 && (
<Card style={{ marginTop: '20px' }}>
<p>计算结束!</p>
<p>计算结果如下:</p>
{results.result}
</Card>
)}
</div>
</Modal>
<Modal
title="算法试算检查"
open={openResults}
footer={null}
width={800}
loading={isLoading}
onCancel={() => setOpenResults(false)}>
<p style={{ fontSize: 20, textAlign: 'center' }}>试算检查结果:{results.pass ? '通过' : '不通过'}</p>
<MarkdownRender>{code}</MarkdownRender>
</Modal>
</>
)
}
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() {
return <DataWrap title="数据加工:数据透视" buttons={<Button type="primary">数据透视</Button>}></DataWrap>
return <DataWrap title="数据挖掘:Apriori" buttons={<ButtonModal />}></DataWrap>
}
import { useState } from 'react'
import { Button, Flex, Modal, Select, Form, Input, Popover, Card } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useDataFieldQuery } from '@/hooks/useQuery'
import { useAI } from '@/hooks/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
const { fieldOptions } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const { post, isLoading } = useAI()
// AI设置
const handleAISet = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设计一个随机森林算法,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
分别返回是否拟合截距项(fit_intercept):true/false、是否复制数据(copy_x):true/false、并行计算核心数(n_jobs):None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)、强制正系数(positive):true/false的值。
返回格式示例:
json
{
"results": { "fit_intercept": true, "copy_x": true, "n_jobs": 1, "positive": false}
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
}
},
}
)
}
// AI计算
const [results, setResults] = useState<any>({})
const code = `${results.code?.replace(/\\n/gi, '\n')}`
const [openResults, setOpenResults] = useState(false)
const handleAICompute = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设置的随机森林算法进行试算检查,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
是否拟合截距项(fit_intercept):${values.fit_intercept}
是否复制数据(copy_X):${values.copy_x}
并行计算核心数(n_jobs):${values.n_jobs}
强制正系数(positive):${values.positive}
返回格式示例:
json
{
results: { pass: 'true或者false,代表通过不通过', code: "Python运行的代码,markdown能解析的代码", result: "计算结果" },
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
const options = [
{ label: 'True', value: true },
{ label: 'False', value: false },
]
// 处理下一步按钮逻辑
const handleNext = async () => {
await form.validateFields()
setCurrent(current + 1)
setStep(-1)
}
// 开始处理
const handleStart = () => {
setStep(1)
handleAICompute()
}
// 关闭并重置
const handleClose = () => {
setOpen(false)
setCurrent(0)
setStep(-1)
}
const steps = [
{
title: '设置算法',
content: (
<>
<Form.Item
label="请选择自变量"
name="independent_variables"
rules={[{ required: true, message: '请选择自变量' }]}>
<Select options={fieldOptions} placeholder="请选择" mode="multiple" />
</Form.Item>
<Form.Item
label="请选择因变量"
name="dependent_variable"
rules={[{ required: true, message: '请选择因变量' }]}>
<Select options={fieldOptions} placeholder="请选择" />
</Form.Item>
<Flex gap={20}>
<div style={{ flex: 1 }}>
<Form.Item label="请输入是否拟合截距项(fit_intercept)">
<Flex gap={10}>
<Form.Item name="fit_intercept" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否拟合截距项(fit_intercept)"
content={
<>
控制模型是否包含截距项(即偏置项,用于调整模型基线)
<br />
取值范围:
<br />
True(模型更灵活,适合大多数场景)
<br />
False(模型强制通过原点,可能欠拟合)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入是否复制数据(copy_X)">
<Flex gap={10}>
<Form.Item name="copy_x" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否复制数据(copy_X)"
content={
<>
决定是否复制输入数据(避免修改原始数据)
<br />
取值范围:
<br />
True(安全但内存占用高)
<br />
False(节省内存,但可能覆盖原始数据)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入并行计算核心数(n_jobs)">
<Flex gap={10}>
<Form.Item name="n_jobs" noStyle rules={[{ required: true, message: '请输入' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
title="并行计算核心数(n_jobs)"
content={
<>
选择优化算法(不同算法支持不同正则化类型和计算效率)
<br />
取值范围:
<br />
None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入强制正系数(positive)">
<Flex gap={10}>
<Form.Item name="positive" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="强制正系数(positive)"
content={
<>
是否强制回归系数为非负值(适用于需正向解释的场景,如经济学或物理模型)
<br />
取值范围:
<br />
True(系数非负,可能牺牲模型拟合能力)
<br />
False(系数可正可负,灵活性高)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
</div>
<Button type="primary" style={{ height: '200px' }} onClick={handleAISet} loading={isLoading}>
AI设置
</Button>
</Flex>
</>
),
},
{
title: '随机森林处理',
content: (
<>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={handleStart} loading={isLoading}>
开始处理
</Button>
<AppProgressSteps current={step} items={[{ title: '启动' }, { title: '计算' }, { title: '计算结束' }]} />
</Flex>
</>
),
},
]
const Footer = () => {
return (
<Flex justify="center" gap={20}>
{current === 0 && (
<Button
type="primary"
onClick={() => {
setOpenResults(true)
handleAICompute()
}}
loading={isLoading}>
AI检查试算
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={handleNext}>
下一步
</Button>
)}
{current === steps.length - 1 && (
<Button type="primary" onClick={handleClose} disabled={isLoading}>
关闭
</Button>
)}
</Flex>
)
}
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
随机森林
</Button>
<Modal
title={steps[current].title}
open={open}
footer={<Footer />}
destroyOnClose
width={800}
onCancel={handleClose}>
<div style={{ minHeight: 300, padding: '20px 0' }}>
<Form form={form} preserve={false}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
{step >= 3 && (
<Card style={{ marginTop: '20px' }}>
<p>计算结束!</p>
<p>计算结果如下:</p>
{results.result}
</Card>
)}
</div>
</Modal>
<Modal
title="算法试算检查"
open={openResults}
footer={null}
width={800}
loading={isLoading}
onCancel={() => setOpenResults(false)}>
<p style={{ fontSize: 20, textAlign: 'center' }}>试算检查结果:{results.pass ? '通过' : '不通过'}</p>
<MarkdownRender>{code}</MarkdownRender>
</Modal>
</>
)
}
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() {
return <DataWrap title="数据挖掘:随机森林" buttons={<Button type="primary">随机森林</Button>}></DataWrap>
return <DataWrap title="数据挖掘:随机森林" buttons={<ButtonModal />}></DataWrap>
}
import { useState } from 'react'
import { Button, Flex, Modal, Select, Form, Input, Popover, Card } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useDataFieldQuery } from '@/hooks/useQuery'
import { useAI } from '@/hooks/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
const { fieldOptions } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const { post, isLoading } = useAI()
// AI设置
const handleAISet = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设计一个FP-Growth算法,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
分别返回是否拟合截距项(fit_intercept):true/false、是否复制数据(copy_x):true/false、并行计算核心数(n_jobs):None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)、强制正系数(positive):true/false的值。
返回格式示例:
json
{
"results": { "fit_intercept": true, "copy_x": true, "n_jobs": 1, "positive": false}
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
}
},
}
)
}
// AI计算
const [results, setResults] = useState<any>({})
const code = `${results.code?.replace(/\\n/gi, '\n')}`
const [openResults, setOpenResults] = useState(false)
const handleAICompute = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设置的FP-Growth算法进行试算检查,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
是否拟合截距项(fit_intercept):${values.fit_intercept}
是否复制数据(copy_X):${values.copy_x}
并行计算核心数(n_jobs):${values.n_jobs}
强制正系数(positive):${values.positive}
返回格式示例:
json
{
results: { pass: 'true或者false,代表通过不通过', code: "Python运行的代码,markdown能解析的代码", result: "计算结果" },
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
const options = [
{ label: 'True', value: true },
{ label: 'False', value: false },
]
// 处理下一步按钮逻辑
const handleNext = async () => {
await form.validateFields()
setCurrent(current + 1)
setStep(-1)
}
// 开始处理
const handleStart = () => {
setStep(1)
handleAICompute()
}
// 关闭并重置
const handleClose = () => {
setOpen(false)
setCurrent(0)
setStep(-1)
}
const steps = [
{
title: '设置算法',
content: (
<>
<Form.Item
label="请选择自变量"
name="independent_variables"
rules={[{ required: true, message: '请选择自变量' }]}>
<Select options={fieldOptions} placeholder="请选择" mode="multiple" />
</Form.Item>
<Form.Item
label="请选择因变量"
name="dependent_variable"
rules={[{ required: true, message: '请选择因变量' }]}>
<Select options={fieldOptions} placeholder="请选择" />
</Form.Item>
<Flex gap={20}>
<div style={{ flex: 1 }}>
<Form.Item label="请输入是否拟合截距项(fit_intercept)">
<Flex gap={10}>
<Form.Item name="fit_intercept" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否拟合截距项(fit_intercept)"
content={
<>
控制模型是否包含截距项(即偏置项,用于调整模型基线)
<br />
取值范围:
<br />
True(模型更灵活,适合大多数场景)
<br />
False(模型强制通过原点,可能欠拟合)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入是否复制数据(copy_X)">
<Flex gap={10}>
<Form.Item name="copy_x" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否复制数据(copy_X)"
content={
<>
决定是否复制输入数据(避免修改原始数据)
<br />
取值范围:
<br />
True(安全但内存占用高)
<br />
False(节省内存,但可能覆盖原始数据)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入并行计算核心数(n_jobs)">
<Flex gap={10}>
<Form.Item name="n_jobs" noStyle rules={[{ required: true, message: '请输入' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
title="并行计算核心数(n_jobs)"
content={
<>
选择优化算法(不同算法支持不同正则化类型和计算效率)
<br />
取值范围:
<br />
None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入强制正系数(positive)">
<Flex gap={10}>
<Form.Item name="positive" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="强制正系数(positive)"
content={
<>
是否强制回归系数为非负值(适用于需正向解释的场景,如经济学或物理模型)
<br />
取值范围:
<br />
True(系数非负,可能牺牲模型拟合能力)
<br />
False(系数可正可负,灵活性高)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
</div>
<Button type="primary" style={{ height: '200px' }} onClick={handleAISet} loading={isLoading}>
AI设置
</Button>
</Flex>
</>
),
},
{
title: 'FP-Growth处理',
content: (
<>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={handleStart} loading={isLoading}>
开始处理
</Button>
<AppProgressSteps current={step} items={[{ title: '启动' }, { title: '计算' }, { title: '计算结束' }]} />
</Flex>
</>
),
},
]
const Footer = () => {
return (
<Flex justify="center" gap={20}>
{current === 0 && (
<Button
type="primary"
onClick={() => {
setOpenResults(true)
handleAICompute()
}}
loading={isLoading}>
AI检查试算
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={handleNext}>
下一步
</Button>
)}
{current === steps.length - 1 && (
<Button type="primary" onClick={handleClose} disabled={isLoading}>
关闭
</Button>
)}
</Flex>
)
}
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
FP-Growth
</Button>
<Modal
title={steps[current].title}
open={open}
footer={<Footer />}
destroyOnClose
width={800}
onCancel={handleClose}>
<div style={{ minHeight: 300, padding: '20px 0' }}>
<Form form={form} preserve={false}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
{step >= 3 && (
<Card style={{ marginTop: '20px' }}>
<p>计算结束!</p>
<p>计算结果如下:</p>
{results.result}
</Card>
)}
</div>
</Modal>
<Modal
title="算法试算检查"
open={openResults}
footer={null}
width={800}
loading={isLoading}
onCancel={() => setOpenResults(false)}>
<p style={{ fontSize: 20, textAlign: 'center' }}>试算检查结果:{results.pass ? '通过' : '不通过'}</p>
<MarkdownRender>{code}</MarkdownRender>
</Modal>
</>
)
}
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() {
return <DataWrap title="数据加工:逻辑计算" buttons={<Button type="primary">逻辑计算</Button>}></DataWrap>
return <DataWrap title="数据挖掘:FP-Growth" buttons={<ButtonModal />}></DataWrap>
}
import { useState } from 'react'
import { Button, Flex, Modal, Select, Form, Input, Popover, Card } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useDataFieldQuery } from '@/hooks/useQuery'
import { useAI } from '@/hooks/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
const { fieldOptions } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const { post, isLoading } = useAI()
// AI设置
const handleAISet = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设计一个层次聚类算法,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
分别返回是否拟合截距项(fit_intercept):true/false、是否复制数据(copy_x):true/false、并行计算核心数(n_jobs):None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)、强制正系数(positive):true/false的值。
返回格式示例:
json
{
"results": { "fit_intercept": true, "copy_x": true, "n_jobs": 1, "positive": false}
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
}
},
}
)
}
// AI计算
const [results, setResults] = useState<any>({})
const code = `${results.code?.replace(/\\n/gi, '\n')}`
const [openResults, setOpenResults] = useState(false)
const handleAICompute = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设置的层次聚类算法进行试算检查,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
是否拟合截距项(fit_intercept):${values.fit_intercept}
是否复制数据(copy_X):${values.copy_x}
并行计算核心数(n_jobs):${values.n_jobs}
强制正系数(positive):${values.positive}
返回格式示例:
json
{
results: { pass: 'true或者false,代表通过不通过', code: "Python运行的代码,markdown能解析的代码", result: "计算结果" },
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
const options = [
{ label: 'True', value: true },
{ label: 'False', value: false },
]
// 处理下一步按钮逻辑
const handleNext = async () => {
await form.validateFields()
setCurrent(current + 1)
setStep(-1)
}
// 开始处理
const handleStart = () => {
setStep(1)
handleAICompute()
}
// 关闭并重置
const handleClose = () => {
setOpen(false)
setCurrent(0)
setStep(-1)
}
const steps = [
{
title: '设置算法',
content: (
<>
<Form.Item
label="请选择自变量"
name="independent_variables"
rules={[{ required: true, message: '请选择自变量' }]}>
<Select options={fieldOptions} placeholder="请选择" mode="multiple" />
</Form.Item>
<Form.Item
label="请选择因变量"
name="dependent_variable"
rules={[{ required: true, message: '请选择因变量' }]}>
<Select options={fieldOptions} placeholder="请选择" />
</Form.Item>
<Flex gap={20}>
<div style={{ flex: 1 }}>
<Form.Item label="请输入是否拟合截距项(fit_intercept)">
<Flex gap={10}>
<Form.Item name="fit_intercept" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否拟合截距项(fit_intercept)"
content={
<>
控制模型是否包含截距项(即偏置项,用于调整模型基线)
<br />
取值范围:
<br />
True(模型更灵活,适合大多数场景)
<br />
False(模型强制通过原点,可能欠拟合)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入是否复制数据(copy_X)">
<Flex gap={10}>
<Form.Item name="copy_x" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否复制数据(copy_X)"
content={
<>
决定是否复制输入数据(避免修改原始数据)
<br />
取值范围:
<br />
True(安全但内存占用高)
<br />
False(节省内存,但可能覆盖原始数据)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入并行计算核心数(n_jobs)">
<Flex gap={10}>
<Form.Item name="n_jobs" noStyle rules={[{ required: true, message: '请输入' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
title="并行计算核心数(n_jobs)"
content={
<>
选择优化算法(不同算法支持不同正则化类型和计算效率)
<br />
取值范围:
<br />
None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入强制正系数(positive)">
<Flex gap={10}>
<Form.Item name="positive" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="强制正系数(positive)"
content={
<>
是否强制回归系数为非负值(适用于需正向解释的场景,如经济学或物理模型)
<br />
取值范围:
<br />
True(系数非负,可能牺牲模型拟合能力)
<br />
False(系数可正可负,灵活性高)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
</div>
<Button type="primary" style={{ height: '200px' }} onClick={handleAISet} loading={isLoading}>
AI设置
</Button>
</Flex>
</>
),
},
{
title: '层次聚类处理',
content: (
<>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={handleStart} loading={isLoading}>
开始处理
</Button>
<AppProgressSteps current={step} items={[{ title: '启动' }, { title: '计算' }, { title: '计算结束' }]} />
</Flex>
</>
),
},
]
const Footer = () => {
return (
<Flex justify="center" gap={20}>
{current === 0 && (
<Button
type="primary"
onClick={() => {
setOpenResults(true)
handleAICompute()
}}
loading={isLoading}>
AI检查试算
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={handleNext}>
下一步
</Button>
)}
{current === steps.length - 1 && (
<Button type="primary" onClick={handleClose} disabled={isLoading}>
关闭
</Button>
)}
</Flex>
)
}
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
层次聚类
</Button>
<Modal
title={steps[current].title}
open={open}
footer={<Footer />}
destroyOnClose
width={800}
onCancel={handleClose}>
<div style={{ minHeight: 300, padding: '20px 0' }}>
<Form form={form} preserve={false}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
{step >= 3 && (
<Card style={{ marginTop: '20px' }}>
<p>计算结束!</p>
<p>计算结果如下:</p>
{results.result}
</Card>
)}
</div>
</Modal>
<Modal
title="算法试算检查"
open={openResults}
footer={null}
width={800}
loading={isLoading}
onCancel={() => setOpenResults(false)}>
<p style={{ fontSize: 20, textAlign: 'center' }}>试算检查结果:{results.pass ? '通过' : '不通过'}</p>
<MarkdownRender>{code}</MarkdownRender>
</Modal>
</>
)
}
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() {
return <DataWrap title="数据加工:数值计算" buttons={<Button type="primary">数值计算</Button>}></DataWrap>
return <DataWrap title="数据挖掘:层次聚类" buttons={<ButtonModal />}></DataWrap>
}
import { useState } from 'react'
import { Button, Flex, Modal, Select, Form, Input, Popover, Card } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useDataFieldQuery } from '@/hooks/useQuery'
import { useAI } from '@/hooks/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
const { fieldOptions } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const { post, isLoading } = useAI()
// AI设置
const handleAISet = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设计一个Holt-Winters算法,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
分别返回是否拟合截距项(fit_intercept):true/false、是否复制数据(copy_x):true/false、并行计算核心数(n_jobs):None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)、强制正系数(positive):true/false的值。
返回格式示例:
json
{
"results": { "fit_intercept": true, "copy_x": true, "n_jobs": 1, "positive": false}
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
}
},
}
)
}
// AI计算
const [results, setResults] = useState<any>({})
const code = `${results.code?.replace(/\\n/gi, '\n')}`
const [openResults, setOpenResults] = useState(false)
const handleAICompute = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设置的Holt-Winters算法进行试算检查,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
是否拟合截距项(fit_intercept):${values.fit_intercept}
是否复制数据(copy_X):${values.copy_x}
并行计算核心数(n_jobs):${values.n_jobs}
强制正系数(positive):${values.positive}
返回格式示例:
json
{
results: { pass: 'true或者false,代表通过不通过', code: "Python运行的代码,markdown能解析的代码", result: "计算结果" },
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
const options = [
{ label: 'True', value: true },
{ label: 'False', value: false },
]
// 处理下一步按钮逻辑
const handleNext = async () => {
await form.validateFields()
setCurrent(current + 1)
setStep(-1)
}
// 开始处理
const handleStart = () => {
setStep(1)
handleAICompute()
}
// 关闭并重置
const handleClose = () => {
setOpen(false)
setCurrent(0)
setStep(-1)
}
const steps = [
{
title: '设置算法',
content: (
<>
<Form.Item
label="请选择自变量"
name="independent_variables"
rules={[{ required: true, message: '请选择自变量' }]}>
<Select options={fieldOptions} placeholder="请选择" mode="multiple" />
</Form.Item>
<Form.Item
label="请选择因变量"
name="dependent_variable"
rules={[{ required: true, message: '请选择因变量' }]}>
<Select options={fieldOptions} placeholder="请选择" />
</Form.Item>
<Flex gap={20}>
<div style={{ flex: 1 }}>
<Form.Item label="请输入是否拟合截距项(fit_intercept)">
<Flex gap={10}>
<Form.Item name="fit_intercept" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否拟合截距项(fit_intercept)"
content={
<>
控制模型是否包含截距项(即偏置项,用于调整模型基线)
<br />
取值范围:
<br />
True(模型更灵活,适合大多数场景)
<br />
False(模型强制通过原点,可能欠拟合)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入是否复制数据(copy_X)">
<Flex gap={10}>
<Form.Item name="copy_x" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否复制数据(copy_X)"
content={
<>
决定是否复制输入数据(避免修改原始数据)
<br />
取值范围:
<br />
True(安全但内存占用高)
<br />
False(节省内存,但可能覆盖原始数据)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入并行计算核心数(n_jobs)">
<Flex gap={10}>
<Form.Item name="n_jobs" noStyle rules={[{ required: true, message: '请输入' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
title="并行计算核心数(n_jobs)"
content={
<>
选择优化算法(不同算法支持不同正则化类型和计算效率)
<br />
取值范围:
<br />
None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入强制正系数(positive)">
<Flex gap={10}>
<Form.Item name="positive" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="强制正系数(positive)"
content={
<>
是否强制回归系数为非负值(适用于需正向解释的场景,如经济学或物理模型)
<br />
取值范围:
<br />
True(系数非负,可能牺牲模型拟合能力)
<br />
False(系数可正可负,灵活性高)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
</div>
<Button type="primary" style={{ height: '200px' }} onClick={handleAISet} loading={isLoading}>
AI设置
</Button>
</Flex>
</>
),
},
{
title: 'Holt-Winters处理',
content: (
<>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={handleStart} loading={isLoading}>
开始处理
</Button>
<AppProgressSteps current={step} items={[{ title: '启动' }, { title: '计算' }, { title: '计算结束' }]} />
</Flex>
</>
),
},
]
const Footer = () => {
return (
<Flex justify="center" gap={20}>
{current === 0 && (
<Button
type="primary"
onClick={() => {
setOpenResults(true)
handleAICompute()
}}
loading={isLoading}>
AI检查试算
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={handleNext}>
下一步
</Button>
)}
{current === steps.length - 1 && (
<Button type="primary" onClick={handleClose} disabled={isLoading}>
关闭
</Button>
)}
</Flex>
)
}
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
Holt-Winters
</Button>
<Modal
title={steps[current].title}
open={open}
footer={<Footer />}
destroyOnClose
width={800}
onCancel={handleClose}>
<div style={{ minHeight: 300, padding: '20px 0' }}>
<Form form={form} preserve={false}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
{step >= 3 && (
<Card style={{ marginTop: '20px' }}>
<p>计算结束!</p>
<p>计算结果如下:</p>
{results.result}
</Card>
)}
</div>
</Modal>
<Modal
title="算法试算检查"
open={openResults}
footer={null}
width={800}
loading={isLoading}
onCancel={() => setOpenResults(false)}>
<p style={{ fontSize: 20, textAlign: 'center' }}>试算检查结果:{results.pass ? '通过' : '不通过'}</p>
<MarkdownRender>{code}</MarkdownRender>
</Modal>
</>
)
}
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() {
return <DataWrap title="数据加工:数据透视" buttons={<Button type="primary">数据透视</Button>}></DataWrap>
return <DataWrap title="数据挖掘:Holt-Winters" buttons={<ButtonModal />}></DataWrap>
}
import { useState } from 'react'
import { Button, Flex, Modal, Select, Form, Input, Popover, Card } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useDataFieldQuery } from '@/hooks/useQuery'
import { useAI } from '@/hooks/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
const { fieldOptions } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const { post, isLoading } = useAI()
// AI设置
const handleAISet = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设计一个K-Means算法,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
分别返回是否拟合截距项(fit_intercept):true/false、是否复制数据(copy_x):true/false、并行计算核心数(n_jobs):None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)、强制正系数(positive):true/false的值。
返回格式示例:
json
{
"results": { "fit_intercept": true, "copy_x": true, "n_jobs": 1, "positive": false}
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
}
},
}
)
}
// AI计算
const [results, setResults] = useState<any>({})
const code = `${results.code?.replace(/\\n/gi, '\n')}`
const [openResults, setOpenResults] = useState(false)
const handleAICompute = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设置的K-Means算法进行试算检查,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
是否拟合截距项(fit_intercept):${values.fit_intercept}
是否复制数据(copy_X):${values.copy_x}
并行计算核心数(n_jobs):${values.n_jobs}
强制正系数(positive):${values.positive}
返回格式示例:
json
{
results: { pass: 'true或者false,代表通过不通过', code: "Python运行的代码,markdown能解析的代码", result: "计算结果" },
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
const options = [
{ label: 'True', value: true },
{ label: 'False', value: false },
]
// 处理下一步按钮逻辑
const handleNext = async () => {
await form.validateFields()
setCurrent(current + 1)
setStep(-1)
}
// 开始处理
const handleStart = () => {
setStep(1)
handleAICompute()
}
// 关闭并重置
const handleClose = () => {
setOpen(false)
setCurrent(0)
setStep(-1)
}
const steps = [
{
title: '设置算法',
content: (
<>
<Form.Item
label="请选择自变量"
name="independent_variables"
rules={[{ required: true, message: '请选择自变量' }]}>
<Select options={fieldOptions} placeholder="请选择" mode="multiple" />
</Form.Item>
<Form.Item
label="请选择因变量"
name="dependent_variable"
rules={[{ required: true, message: '请选择因变量' }]}>
<Select options={fieldOptions} placeholder="请选择" />
</Form.Item>
<Flex gap={20}>
<div style={{ flex: 1 }}>
<Form.Item label="请输入是否拟合截距项(fit_intercept)">
<Flex gap={10}>
<Form.Item name="fit_intercept" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否拟合截距项(fit_intercept)"
content={
<>
控制模型是否包含截距项(即偏置项,用于调整模型基线)
<br />
取值范围:
<br />
True(模型更灵活,适合大多数场景)
<br />
False(模型强制通过原点,可能欠拟合)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入是否复制数据(copy_X)">
<Flex gap={10}>
<Form.Item name="copy_x" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否复制数据(copy_X)"
content={
<>
决定是否复制输入数据(避免修改原始数据)
<br />
取值范围:
<br />
True(安全但内存占用高)
<br />
False(节省内存,但可能覆盖原始数据)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入并行计算核心数(n_jobs)">
<Flex gap={10}>
<Form.Item name="n_jobs" noStyle rules={[{ required: true, message: '请输入' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
title="并行计算核心数(n_jobs)"
content={
<>
选择优化算法(不同算法支持不同正则化类型和计算效率)
<br />
取值范围:
<br />
None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入强制正系数(positive)">
<Flex gap={10}>
<Form.Item name="positive" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="强制正系数(positive)"
content={
<>
是否强制回归系数为非负值(适用于需正向解释的场景,如经济学或物理模型)
<br />
取值范围:
<br />
True(系数非负,可能牺牲模型拟合能力)
<br />
False(系数可正可负,灵活性高)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
</div>
<Button type="primary" style={{ height: '200px' }} onClick={handleAISet} loading={isLoading}>
AI设置
</Button>
</Flex>
</>
),
},
{
title: 'K-Means处理',
content: (
<>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={handleStart} loading={isLoading}>
开始处理
</Button>
<AppProgressSteps current={step} items={[{ title: '启动' }, { title: '计算' }, { title: '计算结束' }]} />
</Flex>
</>
),
},
]
const Footer = () => {
return (
<Flex justify="center" gap={20}>
{current === 0 && (
<Button
type="primary"
onClick={() => {
setOpenResults(true)
handleAICompute()
}}
loading={isLoading}>
AI检查试算
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={handleNext}>
下一步
</Button>
)}
{current === steps.length - 1 && (
<Button type="primary" onClick={handleClose} disabled={isLoading}>
关闭
</Button>
)}
</Flex>
)
}
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
K-Means
</Button>
<Modal
title={steps[current].title}
open={open}
footer={<Footer />}
destroyOnClose
width={800}
onCancel={handleClose}>
<div style={{ minHeight: 300, padding: '20px 0' }}>
<Form form={form} preserve={false}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
{step >= 3 && (
<Card style={{ marginTop: '20px' }}>
<p>计算结束!</p>
<p>计算结果如下:</p>
{results.result}
</Card>
)}
</div>
</Modal>
<Modal
title="算法试算检查"
open={openResults}
footer={null}
width={800}
loading={isLoading}
onCancel={() => setOpenResults(false)}>
<p style={{ fontSize: 20, textAlign: 'center' }}>试算检查结果:{results.pass ? '通过' : '不通过'}</p>
<MarkdownRender>{code}</MarkdownRender>
</Modal>
</>
)
}
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() {
return <DataWrap title="数据加工:数据分组" buttons={<Button type="primary">数据分组</Button>}></DataWrap>
return <DataWrap title="数据挖掘:K-Means" buttons={<ButtonModal />}></DataWrap>
}
import { useState } from 'react'
import { Button, Flex, Modal, Select, Form, Input, Popover } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { Button, Flex, Modal, Select, Form, Input, Popover, Card } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useDataFieldQuery } from '@/hooks/useQuery'
import { useAI } from '@/hooks/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
const { data } = useDataFieldQuery()
const { fieldOptions } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const fieldOptions = data?.map((item) => ({ label: item.name, value: item.name }))
const { post, isLoading } = useAI()
const [step, setStep] = useState<number>(-1)
// AI设置
const handleAISet = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设计一个线性回归算法,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
分别返回是否拟合截距项(fit_intercept):true/false、是否复制数据(copy_x):true/false、并行计算核心数(n_jobs):None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)、强制正系数(positive):true/false的值。
返回格式示例:
json
{
"results": { "fit_intercept": true, "copy_x": true, "n_jobs": 1, "positive": false}
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
}
},
}
)
}
const options = [
// AI计算
const [results, setResults] = useState<any>({})
const code = `${results.code?.replace(/\\n/gi, '\n')}`
const [openResults, setOpenResults] = useState(false)
const handleAICompute = () => {
const values = form.getFieldsValue()
post(
{
label: 'True',
value: true,
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设置的线性回归算法进行试算检查,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
是否拟合截距项(fit_intercept):${values.fit_intercept}
是否复制数据(copy_X):${values.copy_x}
并行计算核心数(n_jobs):${values.n_jobs}
强制正系数(positive):${values.positive}
返回格式示例:
json
{
results: { pass: 'true或者false,代表通过不通过', code: "Python运行的代码,markdown能解析的代码", result: "计算结果" },
}
`,
},
],
},
{
label: 'False',
value: false,
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
const options = [
{ label: 'True', value: true },
{ label: 'False', value: false },
]
// 处理下一步按钮逻辑
const handleNext = async () => {
await form.validateFields()
setCurrent(current + 1)
setStep(-1)
}
// 开始处理
const handleStart = () => {
setStep(1)
handleAICompute()
}
// 关闭并重置
const handleClose = () => {
setOpen(false)
setCurrent(0)
setStep(-1)
}
const steps = [
{
title: '设置算法',
content: (
<>
<Form.Item label="请选择自变量" name="processingMethod">
<Form.Item
label="请选择自变量"
name="independent_variables"
rules={[{ required: true, message: '请选择自变量' }]}>
<Select options={fieldOptions} placeholder="请选择" mode="multiple" />
</Form.Item>
<Form.Item label="请选择因变量" name="rule">
<Form.Item
label="请选择因变量"
name="dependent_variable"
rules={[{ required: true, message: '请选择因变量' }]}>
<Select options={fieldOptions} placeholder="请选择" />
</Form.Item>
<Flex gap={20}>
<div style={{ flex: 1 }}>
<Form.Item label="请输入是否拟合截距项(fit_intercept)" name="fit_intercept">
<Form.Item label="请输入是否拟合截距项(fit_intercept)">
<Flex gap={10}>
<Form.Item name="fit_intercept" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否拟合截距项(fit_intercept)"
content={
......@@ -59,9 +164,11 @@ export default function ButtonModal() {
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入是否复制数据(copy_X)" name="is_copy">
<Form.Item label="请输入是否复制数据(copy_X)">
<Flex gap={10}>
<Form.Item name="copy_x" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否复制数据(copy_X)"
content={
......@@ -79,9 +186,11 @@ export default function ButtonModal() {
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入并行计算核心数(n_jobs)" name="is_jobs">
<Form.Item label="请输入并行计算核心数(n_jobs)">
<Flex gap={10}>
<Form.Item name="n_jobs" noStyle rules={[{ required: true, message: '请输入' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
title="并行计算核心数(n_jobs)"
content={
......@@ -97,9 +206,11 @@ export default function ButtonModal() {
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入强制正系数(positive)" name="is_positive">
<Form.Item label="请输入强制正系数(positive)">
<Flex gap={10}>
<Form.Item name="positive" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="强制正系数(positive)"
content={
......@@ -118,7 +229,7 @@ export default function ButtonModal() {
</Flex>
</Form.Item>
</div>
<Button type="primary" style={{ height: '200px' }}>
<Button type="primary" style={{ height: '200px' }} onClick={handleAISet} loading={isLoading}>
AI设置
</Button>
</Flex>
......@@ -130,57 +241,57 @@ export default function ButtonModal() {
content: (
<>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={() => setStep(1)}>
<Button type="primary" onClick={handleStart} loading={isLoading}>
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
title: <>启动</>,
},
{
title: <>计算</>,
},
{
title: <>计算结束</>,
},
]}
/>
<AppProgressSteps current={step} items={[{ title: '启动' }, { title: '计算' }, { title: '计算结束' }]} />
</Flex>
</>
),
},
]
const Footer = () => {
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
线性回归
</Button>
<Modal
title={steps[current].title}
open={open}
footer={
<Flex justify="center" gap={20}>
{current === 0 && <Button type="primary">AI检查试算</Button>}
{current === 0 && (
<Button
type="primary"
onClick={() => {
setOpenResults(true)
handleAICompute()
}}
loading={isLoading}>
AI检查试算
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={() => setCurrent(current + 1)}>
<Button type="primary" onClick={handleNext}>
下一步
</Button>
)}
{current === steps.length - 1 && (
<Button type="primary" onClick={() => setOpen(false)}>
<Button type="primary" onClick={handleClose} disabled={isLoading}>
关闭
</Button>
)}
</Flex>
)
}
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
线性回归
</Button>
<Modal
title={steps[current].title}
open={open}
footer={<Footer />}
destroyOnClose
width={800}
onCancel={() => setOpen(false)}>
onCancel={handleClose}>
<div style={{ minHeight: 300, padding: '20px 0' }}>
<Form form={form} preserve={false}>
{steps.map((item, index) => (
......@@ -189,8 +300,25 @@ export default function ButtonModal() {
</div>
))}
</Form>
{step >= 3 && (
<Card style={{ marginTop: '20px' }}>
<p>计算结束!</p>
<p>计算结果如下:</p>
{results.result}
</Card>
)}
</div>
</Modal>
<Modal
title="算法试算检查"
open={openResults}
footer={null}
width={800}
loading={isLoading}
onCancel={() => setOpenResults(false)}>
<p style={{ fontSize: 20, textAlign: 'center' }}>试算检查结果:{results.pass ? '通过' : '不通过'}</p>
<MarkdownRender>{code}</MarkdownRender>
</Modal>
</>
)
}
import { useState } from 'react'
import { Button, Flex, Modal, Select, Form, Input, Popover, Card } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useDataFieldQuery } from '@/hooks/useQuery'
import { useAI } from '@/hooks/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
const { fieldOptions } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const { post, isLoading } = useAI()
// AI设置
const handleAISet = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设计一个逻辑回归算法,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
分别返回是否拟合截距项(fit_intercept):true/false、是否复制数据(copy_x):true/false、并行计算核心数(n_jobs):None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)、强制正系数(positive):true/false的值。
返回格式示例:
json
{
"results": { "fit_intercept": true, "copy_x": true, "n_jobs": 1, "positive": false}
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
}
},
}
)
}
// AI计算
const [results, setResults] = useState<any>({})
const code = `${results.code?.replace(/\\n/gi, '\n')}`
const [openResults, setOpenResults] = useState(false)
const handleAICompute = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设置的逻辑回归算法进行试算检查,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
是否拟合截距项(fit_intercept):${values.fit_intercept}
是否复制数据(copy_X):${values.copy_x}
并行计算核心数(n_jobs):${values.n_jobs}
强制正系数(positive):${values.positive}
返回格式示例:
json
{
results: { pass: 'true或者false,代表通过不通过', code: "Python运行的代码,markdown能解析的代码", result: "计算结果" },
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
const options = [
{ label: 'True', value: true },
{ label: 'False', value: false },
]
// 处理下一步按钮逻辑
const handleNext = async () => {
await form.validateFields()
setCurrent(current + 1)
setStep(-1)
}
// 开始处理
const handleStart = () => {
setStep(1)
handleAICompute()
}
// 关闭并重置
const handleClose = () => {
setOpen(false)
setCurrent(0)
setStep(-1)
}
const steps = [
{
title: '设置算法',
content: (
<>
<Form.Item
label="请选择自变量"
name="independent_variables"
rules={[{ required: true, message: '请选择自变量' }]}>
<Select options={fieldOptions} placeholder="请选择" mode="multiple" />
</Form.Item>
<Form.Item
label="请选择因变量"
name="dependent_variable"
rules={[{ required: true, message: '请选择因变量' }]}>
<Select options={fieldOptions} placeholder="请选择" />
</Form.Item>
<Flex gap={20}>
<div style={{ flex: 1 }}>
<Form.Item label="请输入是否拟合截距项(fit_intercept)">
<Flex gap={10}>
<Form.Item name="fit_intercept" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否拟合截距项(fit_intercept)"
content={
<>
控制模型是否包含截距项(即偏置项,用于调整模型基线)
<br />
取值范围:
<br />
True(模型更灵活,适合大多数场景)
<br />
False(模型强制通过原点,可能欠拟合)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入是否复制数据(copy_X)">
<Flex gap={10}>
<Form.Item name="copy_x" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否复制数据(copy_X)"
content={
<>
决定是否复制输入数据(避免修改原始数据)
<br />
取值范围:
<br />
True(安全但内存占用高)
<br />
False(节省内存,但可能覆盖原始数据)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入并行计算核心数(n_jobs)">
<Flex gap={10}>
<Form.Item name="n_jobs" noStyle rules={[{ required: true, message: '请输入' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
title="并行计算核心数(n_jobs)"
content={
<>
选择优化算法(不同算法支持不同正则化类型和计算效率)
<br />
取值范围:
<br />
None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入强制正系数(positive)">
<Flex gap={10}>
<Form.Item name="positive" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="强制正系数(positive)"
content={
<>
是否强制回归系数为非负值(适用于需正向解释的场景,如经济学或物理模型)
<br />
取值范围:
<br />
True(系数非负,可能牺牲模型拟合能力)
<br />
False(系数可正可负,灵活性高)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
</div>
<Button type="primary" style={{ height: '200px' }} onClick={handleAISet} loading={isLoading}>
AI设置
</Button>
</Flex>
</>
),
},
{
title: '逻辑回归处理',
content: (
<>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={handleStart} loading={isLoading}>
开始处理
</Button>
<AppProgressSteps current={step} items={[{ title: '启动' }, { title: '计算' }, { title: '计算结束' }]} />
</Flex>
</>
),
},
]
const Footer = () => {
return (
<Flex justify="center" gap={20}>
{current === 0 && (
<Button
type="primary"
onClick={() => {
setOpenResults(true)
handleAICompute()
}}
loading={isLoading}>
AI检查试算
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={handleNext}>
下一步
</Button>
)}
{current === steps.length - 1 && (
<Button type="primary" onClick={handleClose} disabled={isLoading}>
关闭
</Button>
)}
</Flex>
)
}
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
逻辑回归
</Button>
<Modal
title={steps[current].title}
open={open}
footer={<Footer />}
destroyOnClose
width={800}
onCancel={handleClose}>
<div style={{ minHeight: 300, padding: '20px 0' }}>
<Form form={form} preserve={false}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
{step >= 3 && (
<Card style={{ marginTop: '20px' }}>
<p>计算结束!</p>
<p>计算结果如下:</p>
{results.result}
</Card>
)}
</div>
</Modal>
<Modal
title="算法试算检查"
open={openResults}
footer={null}
width={800}
loading={isLoading}
onCancel={() => setOpenResults(false)}>
<p style={{ fontSize: 20, textAlign: 'center' }}>试算检查结果:{results.pass ? '通过' : '不通过'}</p>
<MarkdownRender>{code}</MarkdownRender>
</Modal>
</>
)
}
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() {
return <DataWrap title="数据挖掘:逻辑回归" buttons={<Button type="primary">逻辑回归</Button>}></DataWrap>
return <DataWrap title="数据挖掘:逻辑回归" buttons={<ButtonModal />}></DataWrap>
}
import { useState } from 'react'
import { Button, Flex, Modal, Radio, Input, Form, Row, Col, Table } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import { Button, Flex, Modal, Select, Form, Input, Popover, Card } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useDataFieldQuery } from '@/hooks/useQuery'
import { useAI } from '@/hooks/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
const { data } = useDataFieldQuery()
const { fieldOptions } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const checked = Form.useWatch('checked', form)
const { post, isLoading } = useAI()
// AI设置
const handleAISet = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设计一个支持向量机算法,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
分别返回是否拟合截距项(fit_intercept):true/false、是否复制数据(copy_x):true/false、并行计算核心数(n_jobs):None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)、强制正系数(positive):true/false的值。
返回格式示例:
json
{
"results": { "fit_intercept": true, "copy_x": true, "n_jobs": 1, "positive": false}
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
}
},
}
)
}
// AI计算
const [results, setResults] = useState<any>({})
const code = `${results.code?.replace(/\\n/gi, '\n')}`
const [openResults, setOpenResults] = useState(false)
const handleAICompute = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设置的支持向量机算法进行试算检查,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
是否拟合截距项(fit_intercept):${values.fit_intercept}
是否复制数据(copy_X):${values.copy_x}
并行计算核心数(n_jobs):${values.n_jobs}
强制正系数(positive):${values.positive}
返回格式示例:
json
{
results: { pass: 'true或者false,代表通过不通过', code: "Python运行的代码,markdown能解析的代码", result: "计算结果" },
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
const options = [
{ label: 'True', value: true },
{ label: 'False', value: false },
]
// 处理下一步按钮逻辑
const handleNext = async () => {
await form.validateFields()
setCurrent(current + 1)
setStep(-1)
}
// 开始处理
const handleStart = () => {
setStep(1)
handleAICompute()
}
// 关闭并重置
const handleClose = () => {
setOpen(false)
setCurrent(0)
setStep(-1)
}
const steps = [
{
title: '请选择值映射字段',
title: '设置算法',
content: (
<>
<Form.Item label="值映射字段名称" name="name">
<Input placeholder="请输入" />
<Form.Item
label="请选择自变量"
name="independent_variables"
rules={[{ required: true, message: '请选择自变量' }]}>
<Select options={fieldOptions} placeholder="请选择" mode="multiple" />
</Form.Item>
<Form.Item label="值映射字段英文名称" name="english_name">
<Input placeholder="请输入" />
<Form.Item
label="请选择因变量"
name="dependent_variable"
rules={[{ required: true, message: '请选择因变量' }]}>
<Select options={fieldOptions} placeholder="请选择" />
</Form.Item>
<Form.Item label="请选择值映射字段" name="checked">
<Radio.Group>
<Row gutter={[10, 10]}>
{data.map((item) => (
<Col span={8} key={item.english_name}>
<Radio value={item.name}>{item.name}</Radio>
</Col>
))}
</Row>
</Radio.Group>
<Flex gap={20}>
<div style={{ flex: 1 }}>
<Form.Item label="请输入是否拟合截距项(fit_intercept)">
<Flex gap={10}>
<Form.Item name="fit_intercept" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否拟合截距项(fit_intercept)"
content={
<>
控制模型是否包含截距项(即偏置项,用于调整模型基线)
<br />
取值范围:
<br />
True(模型更灵活,适合大多数场景)
<br />
False(模型强制通过原点,可能欠拟合)
</>
),
},
{
title: '配置值映射规则',
content: (
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入是否复制数据(copy_X)">
<Flex gap={10}>
<Form.Item name="copy_x" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否复制数据(copy_X)"
content={
<>
决定是否复制输入数据(避免修改原始数据)
<br />
取值范围:
<br />
True(安全但内存占用高)
<br />
False(节省内存,但可能覆盖原始数据)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入并行计算核心数(n_jobs)">
<Flex gap={10}>
<Form.Item name="n_jobs" noStyle rules={[{ required: true, message: '请输入' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
title="并行计算核心数(n_jobs)"
content={
<>
<Form.Item label="值映射操作字段">{checked}</Form.Item>
<Form.Item>
<Table
bordered
columns={[{ title: '序号' }, { title: '原始值' }, { title: '映射值' }]}
dataSource={[]}></Table>
选择优化算法(不同算法支持不同正则化类型和计算效率)
<br />
取值范围:
<br />
None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入强制正系数(positive)">
<Flex gap={10}>
<Form.Item name="positive" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="强制正系数(positive)"
content={
<>
是否强制回归系数为非负值(适用于需正向解释的场景,如经济学或物理模型)
<br />
取值范围:
<br />
True(系数非负,可能牺牲模型拟合能力)
<br />
False(系数可正可负,灵活性高)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
</div>
<Button type="primary" style={{ height: '200px' }} onClick={handleAISet} loading={isLoading}>
AI设置
</Button>
</Flex>
</>
),
},
{
title: '处理执行',
title: '支持向量机处理',
content: (
<>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={() => setStep(2)}>
<Button type="primary" onClick={handleStart} loading={isLoading}>
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
title: <>新建字段</>,
},
{
title: <>复制数据</>,
},
{
title: <>值映射处理</>,
},
{
title: <>处理结果</>,
description: (
<>
累计处理XX个字段
<br />
累计处理XX条记录
</>
),
},
]}
/>
<AppProgressSteps current={step} items={[{ title: '启动' }, { title: '计算' }, { title: '计算结束' }]} />
</Flex>
</>
),
},
]
const Footer = () => {
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
值映射
</Button>
<Modal
title={steps[current].title}
open={open}
footer={
<Flex justify="center" gap={20}>
{current === 1 && <Button type="primary">AI智能建议</Button>}
{current === 0 && (
<Button
type="primary"
onClick={() => {
setOpenResults(true)
handleAICompute()
}}
loading={isLoading}>
AI检查试算
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={() => setCurrent(current + 1)} disabled={!checked?.length}>
<Button type="primary" onClick={handleNext}>
下一步
</Button>
)}
{current === steps.length - 1 && (
<Button type="primary" onClick={() => setOpen(false)}>
<Button type="primary" onClick={handleClose} disabled={isLoading}>
关闭
</Button>
)}
</Flex>
)
}
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
支持向量机
</Button>
<Modal
title={steps[current].title}
open={open}
footer={<Footer />}
destroyOnClose
width={800}
onCancel={() => setOpen(false)}>
onCancel={handleClose}>
<div style={{ minHeight: 300, padding: '20px 0' }}>
<Form form={form} labelCol={{ span: 5 }} preserve={false}>
<Form form={form} preserve={false}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
{step >= 3 && (
<Card style={{ marginTop: '20px' }}>
<p>计算结束!</p>
<p>计算结果如下:</p>
{results.result}
</Card>
)}
</div>
</Modal>
<Modal
title="算法试算检查"
open={openResults}
footer={null}
width={800}
loading={isLoading}
onCancel={() => setOpenResults(false)}>
<p style={{ fontSize: 20, textAlign: 'center' }}>试算检查结果:{results.pass ? '通过' : '不通过'}</p>
<MarkdownRender>{code}</MarkdownRender>
</Modal>
</>
)
}
import { useState } from 'react'
import { Button, Flex, Modal, Select, Form, Input, Popover, Card } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useDataFieldQuery } from '@/hooks/useQuery'
import { useAI } from '@/hooks/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
const { fieldOptions } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const { post, isLoading } = useAI()
// AI设置
const handleAISet = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设计一个决策树(二分类)算法,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
分别返回是否拟合截距项(fit_intercept):true/false、是否复制数据(copy_x):true/false、并行计算核心数(n_jobs):None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)、强制正系数(positive):true/false的值。
返回格式示例:
json
{
"results": { "fit_intercept": true, "copy_x": true, "n_jobs": 1, "positive": false}
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
}
},
}
)
}
// AI计算
const [results, setResults] = useState<any>({})
const code = `${results.code?.replace(/\\n/gi, '\n')}`
const [openResults, setOpenResults] = useState(false)
const handleAICompute = () => {
const values = form.getFieldsValue()
post(
{
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `根据提供的数据集,设置的决策树(二分类)算法进行试算检查,返回JSON格式。
自变量:${values.independent_variables.join(', ')}
因变量:${values.dependent_variable}
是否拟合截距项(fit_intercept):${values.fit_intercept}
是否复制数据(copy_X):${values.copy_x}
并行计算核心数(n_jobs):${values.n_jobs}
强制正系数(positive):${values.positive}
返回格式示例:
json
{
results: { pass: 'true或者false,代表通过不通过', code: "Python运行的代码,markdown能解析的代码", result: "计算结果" },
}
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
const options = [
{ label: 'True', value: true },
{ label: 'False', value: false },
]
// 处理下一步按钮逻辑
const handleNext = async () => {
await form.validateFields()
setCurrent(current + 1)
setStep(-1)
}
// 开始处理
const handleStart = () => {
setStep(1)
handleAICompute()
}
// 关闭并重置
const handleClose = () => {
setOpen(false)
setCurrent(0)
setStep(-1)
}
const steps = [
{
title: '设置算法',
content: (
<>
<Form.Item
label="请选择自变量"
name="independent_variables"
rules={[{ required: true, message: '请选择自变量' }]}>
<Select options={fieldOptions} placeholder="请选择" mode="multiple" />
</Form.Item>
<Form.Item
label="请选择因变量"
name="dependent_variable"
rules={[{ required: true, message: '请选择因变量' }]}>
<Select options={fieldOptions} placeholder="请选择" />
</Form.Item>
<Flex gap={20}>
<div style={{ flex: 1 }}>
<Form.Item label="请输入是否拟合截距项(fit_intercept)">
<Flex gap={10}>
<Form.Item name="fit_intercept" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否拟合截距项(fit_intercept)"
content={
<>
控制模型是否包含截距项(即偏置项,用于调整模型基线)
<br />
取值范围:
<br />
True(模型更灵活,适合大多数场景)
<br />
False(模型强制通过原点,可能欠拟合)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入是否复制数据(copy_X)">
<Flex gap={10}>
<Form.Item name="copy_x" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="是否复制数据(copy_X)"
content={
<>
决定是否复制输入数据(避免修改原始数据)
<br />
取值范围:
<br />
True(安全但内存占用高)
<br />
False(节省内存,但可能覆盖原始数据)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入并行计算核心数(n_jobs)">
<Flex gap={10}>
<Form.Item name="n_jobs" noStyle rules={[{ required: true, message: '请输入' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
title="并行计算核心数(n_jobs)"
content={
<>
选择优化算法(不同算法支持不同正则化类型和计算效率)
<br />
取值范围:
<br />
None(单线程)或 ≥1 的整数(如 -1 表示使用所有核心)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
<Form.Item label="请输入强制正系数(positive)">
<Flex gap={10}>
<Form.Item name="positive" noStyle rules={[{ required: true, message: '请选择' }]}>
<Select options={options} placeholder="请选择" />
</Form.Item>
<Popover
title="强制正系数(positive)"
content={
<>
是否强制回归系数为非负值(适用于需正向解释的场景,如经济学或物理模型)
<br />
取值范围:
<br />
True(系数非负,可能牺牲模型拟合能力)
<br />
False(系数可正可负,灵活性高)
</>
}>
<QuestionCircleOutlined />
</Popover>
</Flex>
</Form.Item>
</div>
<Button type="primary" style={{ height: '200px' }} onClick={handleAISet} loading={isLoading}>
AI设置
</Button>
</Flex>
</>
),
},
{
title: '决策树(二分类)处理',
content: (
<>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={handleStart} loading={isLoading}>
开始处理
</Button>
<AppProgressSteps current={step} items={[{ title: '启动' }, { title: '计算' }, { title: '计算结束' }]} />
</Flex>
</>
),
},
]
const Footer = () => {
return (
<Flex justify="center" gap={20}>
{current === 0 && (
<Button
type="primary"
onClick={() => {
setOpenResults(true)
handleAICompute()
}}
loading={isLoading}>
AI检查试算
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={handleNext}>
下一步
</Button>
)}
{current === steps.length - 1 && (
<Button type="primary" onClick={handleClose} disabled={isLoading}>
关闭
</Button>
)}
</Flex>
)
}
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
决策树(二分类)
</Button>
<Modal
title={steps[current].title}
open={open}
footer={<Footer />}
destroyOnClose
width={800}
onCancel={handleClose}>
<div style={{ minHeight: 300, padding: '20px 0' }}>
<Form form={form} preserve={false}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
{step >= 3 && (
<Card style={{ marginTop: '20px' }}>
<p>计算结束!</p>
<p>计算结果如下:</p>
{results.result}
</Card>
)}
</div>
</Modal>
<Modal
title="算法试算检查"
open={openResults}
footer={null}
width={800}
loading={isLoading}
onCancel={() => setOpenResults(false)}>
<p style={{ fontSize: 20, textAlign: 'center' }}>试算检查结果:{results.pass ? '通过' : '不通过'}</p>
<MarkdownRender>{code}</MarkdownRender>
</Modal>
</>
)
}
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() {
return <DataWrap title="数据挖掘:决策树" buttons={<Button type="primary">决策树(二分类)</Button>}></DataWrap>
return <DataWrap title="数据挖掘:决策树" buttons={<ButtonModal />}></DataWrap>
}
......@@ -90,7 +90,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
......
......@@ -90,7 +90,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
......
......@@ -90,7 +90,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
......
......@@ -152,7 +152,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={progress}
items={[
{
......
......@@ -96,7 +96,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
......
......@@ -84,7 +84,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
......
......@@ -174,7 +174,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
......
......@@ -65,7 +65,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
......
......@@ -57,7 +57,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
......
......@@ -80,7 +80,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
......
......@@ -178,7 +178,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={progress}
items={[
{ title: '新建字段' },
......
......@@ -211,7 +211,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={progress}
items={[
{ title: '新建字段' },
......
......@@ -198,7 +198,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={progress}
items={[
{ title: '新建字段' },
......
......@@ -157,7 +157,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={progress}
items={[
{
......
......@@ -109,7 +109,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={progress}
items={[
{ title: '新建字段' },
......
......@@ -134,7 +134,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={progress}
items={[
{ title: '新建字段' },
......
......@@ -109,7 +109,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={progress}
items={[
{ title: '新建字段' },
......
......@@ -110,7 +110,6 @@ export default function ButtonModal() {
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={progress}
items={[
{ title: '新建字段' },
......
......@@ -50,15 +50,15 @@ export const routes: RouteObject[] = [
// 数据挖掘
{ path: 'digging', element: <Navigate to="linear" /> },
{ path: 'digging/linear', Component: lazy(() => import('./digging/linear/views/Index')) },
{ path: 'digging/logistic', Component: lazy(() => import('./digging/linear/views/Index')) },
{ path: 'digging/tree', Component: lazy(() => import('./digging/linear/views/Index')) },
{ path: 'digging/forest', Component: lazy(() => import('./digging/linear/views/Index')) },
{ path: 'digging/svm', Component: lazy(() => import('./digging/linear/views/Index')) },
{ path: 'digging/kmeans', Component: lazy(() => import('./digging/linear/views/Index')) },
{ path: 'digging/hierarchical', Component: lazy(() => import('./digging/linear/views/Index')) },
{ path: 'digging/apriori', Component: lazy(() => import('./digging/linear/views/Index')) },
{ path: 'digging/fpgrowth', Component: lazy(() => import('./digging/linear/views/Index')) },
{ path: 'digging/holtwinters', Component: lazy(() => import('./digging/linear/views/Index')) },
{ path: 'digging/logistic', Component: lazy(() => import('./digging/logistic/views/Index')) },
{ path: 'digging/tree', Component: lazy(() => import('./digging/tree/views/Index')) },
{ path: 'digging/forest', Component: lazy(() => import('./digging/forest/views/Index')) },
{ path: 'digging/svm', Component: lazy(() => import('./digging/svm/views/Index')) },
{ path: 'digging/kmeans', Component: lazy(() => import('./digging/kmeans/views/Index')) },
{ path: 'digging/hierarchical', Component: lazy(() => import('./digging/hierarchical/views/Index')) },
{ path: 'digging/apriori', Component: lazy(() => import('./digging/apriori/views/Index')) },
{ path: 'digging/fpgrowth', Component: lazy(() => import('./digging/fpgrowth/views/Index')) },
{ path: 'digging/holtwinters', Component: lazy(() => import('./digging/holtwinters/views/Index')) },
// 数据可视化组件
{ path: 'chart', element: <Navigate to="bar" /> },
{ path: 'chart/bar', Component: lazy(() => import('./chart/bar/views/Index')) },
......
import MarkdownRender from '@/components/MarkdownRender'
const sample = `
\`\`\`python
from sklearn.linear_model import LinearRegression\nimport numpy as np\n\n# 提取自变量和因变量\nX = np.array([['丽丽', '安全裤'], ['雅羊人', '不规则连衣裙'], ['威兰西', '网红同款连衣裙'], ['H&R', '蕾丝花边T恤'], ['H&R', '春夏新款连衣裙'], ['H&R', '秋冬款连衣裙'], ['拉夏贝尔', '泫雅风T恤'], ['艾米丽', '大码牛仔裤'], ['TARA', '春夏季新款裤子'], ['富贵人', '蕾丝花边T恤']])\ny = np.array(['丽丽', '雅羊人', '威兰西', 'H&R', 'H&R', 'H&R', '拉夏贝尔', '艾米丽', 'TARA', '富贵人'])\n\n# 将字符串数据转换为数值编码\nfrom sklearn.preprocessing import LabelEncoder\nbrand_encoder = LabelEncoder()\nproduct_encoder = LabelEncoder()\n\nX[:, 0] = brand_encoder.fit_transform(X[:, 0])\nX[:, 1] = product_encoder.fit_transform(X[:, 1])\ny = brand_encoder.transform(y)\n\n# 转换为浮点类型\nX = X.astype(float)\ny = y.astype(float)\n\n# 拟合线性回归模型\nmodel = LinearRegression(fit_intercept=True, copy_X=True, n_jobs=-1, positive=True)\ntry:\n model.fit(X, y)\n pass_status = True\nexcept Exception as e:\n pass_status = False\n\npass_status
\`\`\`
`
export default function Markdown() {
return <MarkdownRender>{sample}</MarkdownRender>
}
import { lazy } from 'react'
import type { RouteObject } from 'react-router'
export const routes: RouteObject[] = [
{
path: '/markdown',
Component: lazy(() => import('./Index')),
},
]
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论