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

feat: implement AI chat functionality with new components and API integration

上级 191a6af6
......@@ -2,8 +2,8 @@ import { useState, KeyboardEvent, useEffect, useRef } from 'react'
import { Button, Card, FloatButton, Input, Select } from 'antd'
import { CircleArrowLeft, CircleArrowRight } from 'lucide-react'
import { OpenAIOutlined, ArrowUpOutlined } from '@ant-design/icons'
import { useAIStore, AIMessage } from '@/stores/ai'
import MarkdownRender from '../MarkdownRender'
import { useAIStore, AIMessage } from './useAIStore'
import MarkdownRender from '@/components/MarkdownRender'
import './AIChat.scss'
export const MessageItem = ({ message }: { message: AIMessage }) => {
......@@ -74,7 +74,7 @@ export default function AIChat() {
onChange={setAI}
variant="filled"
suffixIcon={null}
popupMatchSelectWidth={110}></Select>
popupMatchSelectWidth={210}></Select>
<Button type="primary" shape="circle" icon={<ArrowUpOutlined />} onClick={handleAI} loading={isLoading} />
</div>
<div className="upload-list"></div>
......
import md5 from 'blueimp-md5'
import axios from 'axios'
import md5 from 'blueimp-md5'
import { fetchEventSource, FetchEventSourceInit } from '@fortaine/fetch-event-source'
export interface AIOption {
label: string
value: string
}
export interface AIMessage {
id?: string
role: 'user' | 'assistant' | 'system'
content: string
}
export interface AIData {
response_format?: { type: 'text' | 'json_object' }
model?: string
messages: AIMessage[]
}
export interface AIResponse {
id?: string
content: string
}
export interface InitOptions extends FetchEventSourceInit {
onMessage?: (message: AIResponse) => void
onComplete?: (message: AIMessage) => void
}
// Available AI options for different implementations
export const AI_OPTIONS: AIOption[] = [
// { label: '文心一言', value: 'yiyan' },
{ label: 'DeepSeek', value: 'siliconflow' },
{ label: '通义千问', value: 'qwen' },
// { label: '天工', value: 'tiangong' },
]
export async function getYiyanAccessToken() {
const AK = 'wY7bvMpkWeZbDVq9w3EDvpjU'
const SK = 'XJwpiJWxs5HXkOtbo6tQrvYPZFJAWdAy'
const resp = await axios.post(
`/api/qianfan/oauth/2.0/token?grant_type=client_credentials&client_id=${AK}&client_secret=${SK}`
)
return resp.data.access_token
}
import { AIData, AIMessage, InitOptions } from './types'
import { extractJSON } from '@/utils/helper'
export async function fetchAIEventSource(url: string, options: FetchEventSourceInit) {
await fetchEventSource(url, {
......@@ -58,8 +16,29 @@ export async function fetchAIEventSource(url: string, options: FetchEventSourceI
})
}
function getCommonResponseMessage(res: any) {
if (res.data === '[DONE]') return
try {
const message = JSON.parse(res.data)
if (message.choices && message.choices.length > 0) {
const content = message.choices[0].delta?.content || ''
return { id: message.id, content, json: extractJSON(content) }
}
} catch (error) {
console.error(error)
}
}
// https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Fm2vrveyu
export async function yiyan(data: AIData, options: InitOptions): Promise<void> {
const getYiyanAccessToken = async () => {
const AK = 'wY7bvMpkWeZbDVq9w3EDvpjU'
const SK = 'XJwpiJWxs5HXkOtbo6tQrvYPZFJAWdAy'
const resp = await axios.post(
`/api/qianfan/oauth/2.0/token?grant_type=client_credentials&client_id=${AK}&client_secret=${SK}`
)
return resp.data.access_token
}
const accessToken = await getYiyanAccessToken()
const params = { stream: true, ...data }
await fetchAIEventSource(
......@@ -88,15 +67,8 @@ export async function deepseek(data: AIData, options: InitOptions): Promise<void
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` },
body: JSON.stringify(params),
onmessage(res) {
if (res.data === '[DONE]') return
try {
const message = JSON.parse(res.data)
if (message.choices && message.choices.length > 0 && options.onMessage) {
options.onMessage({ id: message.id, content: message.choices[0].delta?.content || '' } as any)
}
} catch (error) {
console.error(error)
}
const message = getCommonResponseMessage(res)
if (message) options.onMessage?.(message)
},
})
}
......@@ -110,15 +82,8 @@ export async function siliconflow(data: AIData, options: InitOptions): Promise<v
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` },
body: JSON.stringify(params),
onmessage(res) {
if (res.data === '[DONE]') return
try {
const message = JSON.parse(res.data)
if (message.choices && message.choices.length > 0 && options.onMessage) {
options.onMessage({ id: message.id, content: message.choices[0].delta?.content || '' } as any)
}
} catch (error) {
console.error(error)
}
const message = getCommonResponseMessage(res)
if (message) options.onMessage?.(message)
},
})
}
......@@ -132,15 +97,8 @@ export async function qwen(data: AIData, options: InitOptions): Promise<void> {
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` },
body: JSON.stringify(params),
onmessage(res) {
if (res.data === '[DONE]') return
try {
const message = JSON.parse(res.data)
if (message.choices && message.choices.length > 0 && options.onMessage) {
options.onMessage({ id: message.id, content: message.choices[0].delta?.content || '' } as any)
}
} catch (error) {
console.error(error)
}
const message = getCommonResponseMessage(res)
if (message) options.onMessage?.(message)
},
})
}
......@@ -176,41 +134,59 @@ export async function tiangong(data: AIData, options: InitOptions): Promise<void
})
}
// Core AI API implementation
const aiService = {
yiyan,
deepseek,
siliconflow,
qwen,
tiangong,
export async function openAIStream(data: AIData, options: InitOptions): Promise<void> {
const params = { model: 'qwen-max-latest', stream: true, ...data }
await fetchEventSource('/api/openai/chat/create', {
...options,
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: 'ezijing@20250331' },
body: JSON.stringify(params),
async onopen(response) {
if (response.ok) return
else throw response
},
onmessage(res) {
const message = getCommonResponseMessage(res)
if (message) options.onMessage?.(message)
},
})
}
async post(type: string, data: AIData, options: InitOptions): Promise<void> {
export async function openAI(data: AIData, options: InitOptions): Promise<void> {
try {
const response = await axios.post(
'/api/openai/chat/create',
{ stream: true, ...data },
{ headers: { 'Content-Type': 'application/json', Authorization: 'ezijing@20250331' } }
)
const content = response.data.choices[0]?.message?.content || ''
const message: AIMessage = {
id: response.data.id,
role: 'assistant',
content,
json: extractJSON(content),
}
options.onMessage?.(message)
options.onclose?.()
} catch (error) {
console.error(error)
options.onerror?.(error)
}
}
const aiService = {
async post(data: AIData, options: InitOptions): Promise<void> {
const messages: AIMessage[] = []
const dataset = localStorage.getItem('dataset')
if (dataset) {
const datasetInfo = JSON.parse(dataset)
messages.push({ role: 'system', content: `这是一个数据集:${JSON.stringify(datasetInfo)}` })
messages.push({
role: 'system',
content: `这是一个数据集:${JSON.stringify(datasetInfo)}`,
})
}
data.messages = [...messages, ...data.messages]
switch (type) {
case 'yiyan':
return yiyan(data, options)
case 'deepseek':
return deepseek(data, options)
case 'siliconflow':
return siliconflow(data, options)
case 'qwen':
return qwen(data, options)
case 'tiangong':
return tiangong(data, options)
default:
throw new Error(`未找到对应的 AI 配置: ${type}`)
}
openAI(data, options)
},
}
......
import { AIOption } from './types'
export const AI_OPTIONS: AIOption[] = [
{ label: 'DeepSeek-R1', value: 'Pro/deepseek-ai/DeepSeek-R1' },
{ label: 'DeepSeek-V3', value: 'Pro/deepseek-ai/DeepSeek-V3' },
{ label: 'QwQ-32B', value: 'Qwen/QwQ-32B' },
{ label: 'deepseek-r1-250120', value: 'deepseek-r1-250120' },
{ label: 'doubao-pro-32k-241215', value: 'doubao-pro-32k-241215' },
{ label: 'qwen-max-latest', value: 'qwen-max-latest' },
{ label: 'qwen-long', value: 'qwen-long' },
{ label: 'hunyuan-t1-latest', value: 'hunyuan-t1-latest' },
{ label: 'hunyuan-standard-256K', value: 'hunyuan-standard-256K' },
]
import { FetchEventSourceInit } from '@fortaine/fetch-event-source'
export interface AIOption {
label: string
value: string
}
export interface AIMessage {
id?: string
role: 'user' | 'assistant' | 'system'
content: string
json?: any
}
export interface AIData {
response_format?: { type: 'text' | 'json_object' }
model?: string
messages: AIMessage[]
}
export interface AIResponse {
id: string
content: string
json?: any
}
export interface InitOptions extends FetchEventSourceInit {
onMessage?: (message: AIResponse) => void
}
import { useState, useEffect, useCallback, useRef } from 'react'
import aiService, { AIMessage, AIData, AI_OPTIONS, InitOptions } from '@/utils/ai'
import { AI_OPTIONS } from './config'
import aiService from './api'
import type { AIMessage, AIData, InitOptions } from './types'
export function useAI(globalOptions?: InitOptions) {
const [ai, setAI] = useState<string>(localStorage.getItem('ai') || 'qwen')
......@@ -24,6 +26,7 @@ export function useAI(globalOptions?: InitOptions) {
id: response.id,
role: 'assistant',
content: response.content,
json: response.json,
}
latestMessageRef.current = newMessage
......@@ -39,6 +42,7 @@ export function useAI(globalOptions?: InitOptions) {
const updatedMessage = {
...msg,
content: msg.content + response.content,
json: msg.json || response.json,
}
latestMessageRef.current = updatedMessage
setMessage(updatedMessage)
......@@ -53,6 +57,7 @@ export function useAI(globalOptions?: InitOptions) {
const post = useCallback(
async (data: AIData, options?: InitOptions) => {
return new Promise<AIMessage>((resolve, reject) => {
try {
setIsLoading(true)
......@@ -61,9 +66,9 @@ export function useAI(globalOptions?: InitOptions) {
messagesRef.current = [...messagesRef.current, ...userMessages]
setMessages((prev) => [...prev, ...userMessages])
const onComplete = options?.onComplete || globalOptions?.onComplete
await aiService.post(ai, data, {
aiService.post(
{ ...data, model: ai },
{
onMessage: (response) => {
const messageIndex = messagesRef.current.findIndex((msg) => msg.id === response.id)
updateMessage(response, messageIndex === -1)
......@@ -71,20 +76,26 @@ export function useAI(globalOptions?: InitOptions) {
onerror: (error) => {
console.error('AI service error:', error)
setIsLoading(false)
reject(error)
},
onclose: () => {
setIsLoading(false)
if (latestMessageRef.current && onComplete) {
onComplete(latestMessageRef.current)
if (latestMessageRef.current) {
resolve(latestMessageRef.current)
} else {
reject(new Error('No message received'))
}
},
...globalOptions,
...options,
})
}
)
} catch (error) {
console.error('Post error:', error)
setIsLoading(false)
reject(error)
}
})
},
[ai, updateMessage, globalOptions]
)
......
import { create } from 'zustand'
import { AI_OPTIONS } from './config'
import aiService from './api'
import type { AIOption, AIMessage, AIData, InitOptions } from './types'
interface AIState {
ai: string
options: AIOption[]
message: AIMessage | null
messages: AIMessage[]
isLoading: boolean
collapsed: boolean
setAI: (ai: string) => void
toggleCollapsed: () => void
post: (data: AIData, options?: InitOptions) => Promise<AIMessage>
}
export const useAIStore = create<AIState>((set, get) => ({
ai: localStorage.getItem('ai') || 'qwen',
options: AI_OPTIONS,
message: null,
messages: [],
isLoading: false,
collapsed: false,
setAI: (ai) => {
localStorage.setItem('ai', ai)
set({ ai })
},
toggleCollapsed: () => {
set((state) => ({ collapsed: !state.collapsed }))
},
post: async (data, options) => {
const { ai, messages } = get()
// 处理用户消息(去掉 system 角色的消息)
const userMessages = data.messages.filter((item) => item.role !== 'system')
set({
collapsed: true,
isLoading: true,
messages: [...messages, ...userMessages],
})
return new Promise<AIMessage>((resolve, reject) => {
try {
aiService.post(
{ ...data, model: ai },
{
onMessage: (response) => {
set((state) => {
const messageIndex = state.messages.findIndex((msg) => msg.id === response.id)
if (messageIndex === -1) {
// 新的 AI 回复
const newMessage: AIMessage = {
id: response.id,
role: 'assistant',
content: response.content,
json: response.json,
}
return {
message: newMessage, // 存储最新的 AI 消息
messages: [...state.messages, newMessage], // 追加到历史消息
}
} else {
// 追加内容到已有的消息
const updatedMessages = state.messages.map((msg) =>
msg.id === response.id
? { ...msg, content: msg.content + response.content, json: msg.json || response.json }
: msg
)
return {
message: updatedMessages[messageIndex], // 更新最新的 AI 消息
messages: updatedMessages,
}
}
})
},
onerror: (err) => {
console.error('AI 请求失败:', err)
set({ isLoading: false })
reject(err)
},
onclose: () => {
set({ isLoading: false })
const { message } = get()
if (message) {
resolve(message)
} else {
reject(new Error('No message received'))
}
},
...options,
}
)
} catch (err) {
console.error('AI 请求失败:', err)
set({ isLoading: false })
reject(err)
}
})
},
}))
export type { AIMessage }
......@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'
import { Button, Flex, Modal, Form, Divider, Select, Radio, Row, Col, Input } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import { useCreateChart, useUpdateChart, useViewChartQuery } from '@/hooks/useChartQuery'
import { useAI } from '@/hooks/useAI'
import { useAI } from '@/ai/useAI'
import Chart from './Chart'
interface Props {
......@@ -143,7 +143,6 @@ const Step2 = ({ fieldOptions, type, showTitle }: any) => {
<Radio.Group
options={[
{ label: '不做圆滑处理', value: 0 },
{ label: '四个角圆滑处理', value: 10 },
{ label: '两个角圆滑处理', value: [10, 10, 0, 0] },
]}></Radio.Group>
</Form.Item>
......@@ -333,22 +332,11 @@ const ModalContent = ({ setOpen, type, id = '' }: Props) => {
...results,
}
const { post } = useAI({
onComplete: (message) => {
console.log(message)
try {
const { results } = JSON.parse(message.content)
setResults(results)
console.log(results)
} catch (e) {
console.log(e)
}
},
})
const { post } = useAI()
const handlePreview = () => {
const handlePreview = async () => {
const values = form.getFieldsValue()
post({
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -390,6 +378,9 @@ const ModalContent = ({ setOpen, type, id = '' }: Props) => {
},
],
})
if (message.json && message.json.results) {
setResults(message.json.results)
}
}
const { mutate: mutateCreate } = useCreateChart()
......
import { Button, Flex, Modal, Spin } from 'antd'
import { useEffect, useState } from 'react'
import { useAI } from '@/hooks/useAI'
import { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function AIModal({ prompt }: { prompt: string }) {
......
......@@ -13,7 +13,7 @@ import {
} from 'lucide-react'
import { Menu, MenuProps } from 'antd'
import './DataLayout.scss'
import AIChat from '../ai/AIChat'
import AIChat from '@/ai/AIChat'
type MyMenuItem = {
name: string
......
......@@ -3,7 +3,7 @@ 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 { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -20,8 +20,7 @@ export default function ButtonModal() {
await form.validateFields(['independent_variables', 'dependent_variable'])
const values = form.getFieldsValue()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -36,19 +35,11 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
})
console.log(message.json)
if (message.json && message.json.results) {
form.setFieldsValue(message.json.results)
}
},
}
)
}
// AI计算
......@@ -57,8 +48,7 @@ json
const [openResults, setOpenResults] = useState(false)
const handleAICompute = async () => {
const values = await form.validateFields()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -80,22 +70,14 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
})
console.log(message.json)
if (message.json && message.json.results) {
setResults(message.json.results)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
......@@ -133,7 +115,7 @@ json
<div style={{ flex: 1 }}>
<Form.Item label="请输入最小支持度(min_support)">
<Flex gap={10}>
<Form.Item name="fit_intercept" noStyle rules={[{ required: true, message: '请选择' }]}>
<Form.Item name="min_support" noStyle rules={[{ required: true, message: '请选择' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
......@@ -155,7 +137,7 @@ json
</Form.Item>
<Form.Item label="请输入最小置信度(min_confidence)">
<Flex gap={10}>
<Form.Item name="copy_x" noStyle rules={[{ required: true, message: '请选择' }]}>
<Form.Item name="min_confidence" noStyle rules={[{ required: true, message: '请选择' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
......@@ -177,7 +159,7 @@ json
</Form.Item>
<Form.Item label="请输入最小提升度(min_lift)">
<Flex gap={10}>
<Form.Item name="n_jobs" noStyle rules={[{ required: true, message: '请输入' }]}>
<Form.Item name="min_lift" noStyle rules={[{ required: true, message: '请输入' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
......@@ -197,7 +179,7 @@ json
</Form.Item>
<Form.Item label="请输入规则最小长度(min_length)">
<Flex gap={10}>
<Form.Item name="positive" noStyle rules={[{ required: true, message: '请选择' }]}>
<Form.Item name="min_length" noStyle rules={[{ required: true, message: '请选择' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
......@@ -219,7 +201,7 @@ json
</Form.Item>
<Form.Item label="请输入规则最大长度(max_length)">
<Flex gap={10}>
<Form.Item name="positive" noStyle rules={[{ required: true, message: '请选择' }]}>
<Form.Item name="max_length" noStyle rules={[{ required: true, message: '请选择' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
......@@ -241,7 +223,7 @@ json
</Form.Item>
<Form.Item label="请输入评估指标(metric)">
<Flex gap={10}>
<Form.Item name="positive" noStyle rules={[{ required: true, message: '请选择' }]}>
<Form.Item name="metric" noStyle rules={[{ required: true, message: '请选择' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Popover
......
......@@ -3,7 +3,7 @@ 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 { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -20,8 +20,7 @@ export default function ButtonModal() {
await form.validateFields(['independent_variables', 'dependent_variable'])
const values = form.getFieldsValue()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -37,19 +36,10 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
form.setFieldsValue(message.json.results)
}
},
}
)
}
// AI计算
......@@ -58,8 +48,7 @@ json
const [openResults, setOpenResults] = useState(false)
const handleAICompute = async () => {
const values = await form.validateFields()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -80,22 +69,13 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
setResults(message.json.results)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
......
......@@ -3,7 +3,7 @@ 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 { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -20,8 +20,7 @@ export default function ButtonModal() {
await form.validateFields(['independent_variables', 'dependent_variable'])
const values = form.getFieldsValue()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -36,19 +35,10 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
form.setFieldsValue(message.json.results)
}
},
}
)
}
// AI计算
......@@ -57,8 +47,7 @@ json
const [openResults, setOpenResults] = useState(false)
const handleAICompute = async () => {
const values = await form.validateFields()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -77,31 +66,17 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
setResults(message.json.results)
}
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()
......
......@@ -3,7 +3,7 @@ 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 { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -20,8 +20,7 @@ export default function ButtonModal() {
await form.validateFields(['independent_variables', 'dependent_variable'])
const values = form.getFieldsValue()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -36,19 +35,10 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
form.setFieldsValue(message.json.results)
}
},
}
)
}
// AI计算
......@@ -57,8 +47,7 @@ json
const [openResults, setOpenResults] = useState(false)
const handleAICompute = async () => {
const values = await form.validateFields()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -78,22 +67,13 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
setResults(message.json.results)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
......
......@@ -3,7 +3,7 @@ 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 { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -20,8 +20,7 @@ export default function ButtonModal() {
await form.validateFields(['independent_variables', 'dependent_variable'])
const values = form.getFieldsValue()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -37,19 +36,10 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
form.setFieldsValue(message.json.results)
}
},
}
)
}
// AI计算
......@@ -58,8 +48,7 @@ json
const [openResults, setOpenResults] = useState(false)
const handleAICompute = async () => {
const values = await form.validateFields()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -79,22 +68,13 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
setResults(message.json.results)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
......
......@@ -3,7 +3,7 @@ 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 { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -20,8 +20,7 @@ export default function ButtonModal() {
await form.validateFields(['independent_variables'])
const values = form.getFieldsValue()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -36,19 +35,10 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
form.setFieldsValue(message.json.results)
}
},
}
)
}
// AI计算
......@@ -57,8 +47,7 @@ json
const [openResults, setOpenResults] = useState(false)
const handleAICompute = async () => {
const values = await form.validateFields()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -80,22 +69,13 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
setResults(message.json.results)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
......
......@@ -3,7 +3,7 @@ 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 { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -19,8 +19,7 @@ export default function ButtonModal() {
const handleAISet = async () => {
await form.validateFields(['independent_variables', 'dependent_variable'])
const values = form.getFieldsValue()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -37,19 +36,10 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
form.setFieldsValue(message.json.results)
}
},
}
)
}
// AI计算
......@@ -59,8 +49,7 @@ json
const handleAICompute = async () => {
const values = await form.validateFields()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -80,22 +69,14 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
})
console.log(message.json)
if (message.json && message.json.results) {
setResults(message.json.results)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
......
......@@ -3,7 +3,7 @@ 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 { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -20,8 +20,7 @@ export default function ButtonModal() {
await form.validateFields(['independent_variables', 'dependent_variable'])
const values = form.getFieldsValue()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -37,19 +36,10 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
form.setFieldsValue(message.json.results)
}
},
}
)
}
// AI计算
......@@ -58,8 +48,7 @@ json
const [openResults, setOpenResults] = useState(false)
const handleAICompute = async () => {
const values = await form.validateFields()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -81,22 +70,14 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
})
console.log(message.json)
if (message.json && message.json.results) {
setResults(message.json.results)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
......
......@@ -3,7 +3,7 @@ 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 { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -20,8 +20,7 @@ export default function ButtonModal() {
await form.validateFields(['independent_variables', 'dependent_variable'])
const values = form.getFieldsValue()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -37,19 +36,10 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
form.setFieldsValue(message.json.results)
}
},
}
)
}
// AI计算
......@@ -58,8 +48,7 @@ json
const [openResults, setOpenResults] = useState(false)
const handleAICompute = async () => {
const values = await form.validateFields()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -80,22 +69,13 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
setResults(message.json.results)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
......
......@@ -3,7 +3,7 @@ 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 { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -20,8 +20,7 @@ export default function ButtonModal() {
await form.validateFields(['independent_variables', 'dependent_variable'])
const values = form.getFieldsValue()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -37,19 +36,10 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
form.setFieldsValue(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
form.setFieldsValue(message.json.results)
}
},
}
)
}
// AI计算
......@@ -58,8 +48,7 @@ json
const [openResults, setOpenResults] = useState(false)
const handleAICompute = async () => {
const values = await form.validateFields()
post(
{
const message = await post({
response_format: { type: 'json_object' },
messages: [
{
......@@ -80,22 +69,13 @@ json
`,
},
],
},
{
onComplete: (message) => {
console.log(message)
try {
const parse = JSON.parse(message.content)
setResults(parse.results)
} catch (error) {
console.error(error)
})
if (message.json && message.json.results) {
setResults(message.json.results)
}
if (current === 1) {
setStep(3)
}
},
}
)
}
const [step, setStep] = useState<number>(-1)
......
......@@ -3,8 +3,9 @@ import { Button, Flex, Modal, Radio, Form, Row, Col } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useSearchParams } from 'react-router'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
import { useAIStore } from '@/ai/useAIStore'
import prompt from '@/ai/prompt'
import { useProcessData } from '../query'
interface ResultItem {
......@@ -21,20 +22,17 @@ export default function ButtonModal() {
}))
const selectOptions = resultsOptions.length ? resultsOptions : fieldOptions
const { isLoading, post } = useAI({
onComplete: (message) => {
if (!message.content) return
const parse = JSON.parse(message.content)
console.log(parse)
setResults(parse.results || [])
},
})
const { isLoading, post } = useAIStore()
const handleAI = () => {
post({
const handleAI = async () => {
const message = await post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.error }],
})
console.log(message.json)
if (message.json && Array.isArray(message.json.results)) {
setResults(message.json.results)
}
}
const [open, setOpen] = useState(false)
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'abnormal' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
......
......@@ -3,8 +3,9 @@ import { Button, Flex, Modal, Radio, Form, Row, Col } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useSearchParams } from 'react-router'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
import { useAIStore } from '@/ai/useAIStore'
import prompt from '@/ai/prompt'
import { useProcessData } from '../query'
interface ResultItem {
......@@ -21,20 +22,17 @@ export default function ButtonModal() {
}))
const selectOptions = resultsOptions.length ? resultsOptions : fieldOptions
const { isLoading, post } = useAI({
onComplete: (message) => {
if (!message.content) return
const parse = JSON.parse(message.content)
console.log(parse)
setResults(parse.results || [])
},
})
const { isLoading, post } = useAIStore()
const handleAI = () => {
post({
const handleAI = async () => {
const message = await post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.max }],
})
console.log(message.json)
if (message.json && Array.isArray(message.json.results)) {
setResults(message.json.results)
}
}
const [open, setOpen] = useState(false)
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'outOfRange' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
......
......@@ -3,8 +3,9 @@ import { Button, Flex, Modal, Radio, Form, Row, Col } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useSearchParams } from 'react-router'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
import { useAIStore } from '@/ai/useAIStore'
import prompt from '@/ai/prompt'
import { useProcessData } from '../query'
interface ResultItem {
......@@ -14,6 +15,7 @@ interface ResultItem {
export default function ButtonModal() {
const [searchParams] = useSearchParams()
const { fieldOptions, getFieldName } = useDataFieldQuery()
const [results, setResults] = useState<ResultItem[]>([])
const resultsOptions = results.map((result) => ({
label: result.name,
......@@ -21,20 +23,18 @@ export default function ButtonModal() {
}))
const selectOptions = resultsOptions.length ? resultsOptions : fieldOptions
const { isLoading, post } = useAI({
onComplete: (message) => {
if (!message.content) return
const parse = JSON.parse(message.content)
console.log(parse)
setResults(parse.results || [])
},
})
const handleAI = () => {
post({
const { isLoading, post } = useAIStore()
const handleAI = async () => {
const message = await post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.min }],
})
console.log(message.json)
if (message.json && Array.isArray(message.json.results)) {
setResults(message.json.results)
}
}
const [open, setOpen] = useState(false)
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'underRange' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
......
......@@ -3,8 +3,9 @@ import { Button, Checkbox, Flex, Modal, Radio, Select, Input, Form, Row, Col, Di
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useSearchParams } from 'react-router'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
import { useAIStore } from '@/ai/useAIStore'
import prompt from '@/ai/prompt'
import { useProcessData } from '../query'
const actionOptions = [
......@@ -29,26 +30,25 @@ interface ResultItem {
export default function ButtonModal() {
const [searchParams] = useSearchParams()
const { fieldOptions, getFieldName, getFieldNames } = useDataFieldQuery()
const [results, setResults] = useState<ResultItem[]>([])
const resultsOptions = results.map((result) => ({
label: result.name,
value: fieldOptions.find((option) => option.label === result.name)?.value || '',
}))
const selectOptions = resultsOptions.length ? resultsOptions : fieldOptions
const { isLoading, post } = useAI({
onComplete: (message) => {
if (!message.content) return
const parse = JSON.parse(message.content)
console.log(parse)
setResults(parse.results || [])
},
})
const handleAI = () => {
post({
const { isLoading, post } = useAIStore()
const handleAI = async () => {
const message = await post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.null }],
})
console.log(message.json)
if (message.json && Array.isArray(message.json.results)) {
setResults(message.json.results)
}
}
const [open, setOpen] = useState(false)
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'missing' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
......
......@@ -2,31 +2,38 @@ import { useEffect, useState } from 'react'
import { Button, Checkbox, Flex, Modal, Radio, Form, Row, Col, Empty } from 'antd'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useSearchParams } from 'react-router'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
import { useAIStore } from '@/ai/useAIStore'
import prompt from '@/ai/prompt'
import { useProcessData } from '../query'
interface ResultItem {
line: number
lines: number[]
desc: string
}
export default function ButtonModal() {
const [searchParams] = useSearchParams()
const [results, setResults] = useState<Array<{ line: number; lines: number[]; desc: string }>>([])
const [results, setResults] = useState<ResultItem[]>([])
useEffect(() => {
if (searchParams.get('results')) {
setResults(JSON.parse(searchParams.get('results') || '') as any)
setResults(JSON.parse(searchParams.get('results') || '') as ResultItem[])
setOpen(true)
}
}, [searchParams])
const { isLoading, post } = useAI({
onComplete: (message) => {
if (!message.content) return
const parse = JSON.parse(message.content)
console.log(parse)
setResults(parse.results || [])
},
})
const { isLoading, post } = useAIStore()
const handleAI = () => {
post({ response_format: { type: 'json_object' }, messages: [{ role: 'user', content: prompt.repeat }] })
const handleAI = async () => {
const message = await post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.repeat }],
})
console.log(message.json)
if (message.json && Array.isArray(message.json.results)) {
setResults(message.json.results)
}
}
const [open, setOpen] = useState(false)
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'duplicate' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'sort' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
......
......@@ -3,19 +3,15 @@ import { Button, Flex, Modal, Radio, Form, Row, Col } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useProcessData } from '../query'
import { useAI } from '@/hooks/useAI'
import { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
const [result, setResult] = useState('')
const { isLoading, post } = useAI({
onComplete: (message) => {
setResult(message?.content || '')
},
})
const { isLoading, post } = useAI()
const handleAI = async () => {
post({
const message = await post({
messages: [
{
role: 'user',
......@@ -62,6 +58,7 @@ export default function ButtonModal() {
},
],
})
if (message.content) setResult(message.content)
}
const { fieldOptions, getFieldName } = useDataFieldQuery()
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'trim' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'merge' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'split' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'punctuation' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'type' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
......
......@@ -4,7 +4,7 @@ import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useProcessData } from '../query'
import { MinusCircleOutlined } from '@ant-design/icons'
import { useAI } from '@/hooks/useAI'
import { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -26,14 +26,10 @@ export default function ButtonModal() {
const step = Form.useWatch('step', form)
const [result, setResult] = useState('')
const { isLoading, post } = useAI({
onComplete: (message) => {
setResult(message?.content || '')
},
})
const { isLoading, post } = useAI()
const handleAI = async () => {
post({
const message = await post({
messages: [
{
role: 'user',
......@@ -95,6 +91,7 @@ ${action === '固定步长分箱' ? `最小值 ${min}、最大值 ${max}、步
},
],
})
if (message.content) setResult(message.content)
}
// 处理下一步按钮逻辑
const handleNext = async () => {
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'mapping' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
return { ...query, progress: data.progress, message: data.message, remove }
......
......@@ -4,7 +4,7 @@ import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import FunctionInput from '@/components/data/FunctionInput'
import { useProcessData } from '../query'
import { useAI } from '@/hooks/useAI'
import { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
const functionShortcutOptions = [
......@@ -95,18 +95,14 @@ export default function ButtonModal() {
const action = Form.useWatch('action', form)
const [result, setResult] = useState('')
const { isLoading, post } = useAI({
onComplete: (message) => {
setResult(message?.content || '')
},
})
const { isLoading, post } = useAI()
const handleAI = async () => {
const values = form.getFieldsValue()
const selectedFunction = values.function
const functionFormula = values.content || ''
post({
const message = await post({
messages: [
{
role: 'user',
......@@ -130,6 +126,7 @@ export default function ButtonModal() {
},
],
})
if (message.content) setResult(message.content)
}
// 处理下一步按钮逻辑
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'date' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
return { ...query, progress: data.progress, message: data.message, remove }
......
......@@ -3,7 +3,7 @@ import { Button, Flex, Modal, Radio, Input, Form, Row, Col } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useProcessData } from '../query'
import { useAI } from '@/hooks/useAI'
import { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -19,14 +19,10 @@ export default function ButtonModal() {
const formSmFun = Form.useWatch('sm_fun', form)
const [result, setResult] = useState('')
const { isLoading, post } = useAI({
onComplete: (message) => {
setResult(message?.content || '')
},
})
const { isLoading, post } = useAI()
const handleAI = async () => {
post({
const message = await post({
messages: [
{
role: 'user',
......@@ -73,6 +69,7 @@ export default function ButtonModal() {
},
],
})
if (message.content) setResult(message.content)
}
// 处理下一步按钮逻辑
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'anonymization' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
return { ...query, progress: data.progress, message: data.message, remove }
......
......@@ -5,7 +5,7 @@ import AppProgressSteps from '@/components/AppProgressSteps'
import { useProcessData } from '../query'
import { MinusCircleOutlined } from '@ant-design/icons'
import { uniqBy } from 'lodash-es'
import { useAI } from '@/hooks/useAI'
import { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -36,14 +36,10 @@ export default function ButtonModal() {
}, [field, data.list])
const [result, setResult] = useState('')
const { isLoading, post } = useAI({
onComplete: (message) => {
setResult(message?.content || '')
},
})
const { isLoading, post } = useAI()
const handleAI = async () => {
post({
const message = await post({
messages: [
{
role: 'user',
......@@ -86,6 +82,7 @@ export default function ButtonModal() {
},
],
})
if (message.content) setResult(message.content)
}
// 处理下一步按钮逻辑
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'grouping' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
return { ...query, progress: data.progress, message: data.message, remove }
......
......@@ -3,7 +3,7 @@ import { Button, Flex, Modal, Input, Form, Select } from 'antd'
import AppProgressSteps from '@/components/AppProgressSteps'
import FunctionInput from '@/components/data/FunctionInput'
import { useProcessData } from '../query'
import { useAI } from '@/hooks/useAI'
import { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
const functionOptions = [
......@@ -26,18 +26,14 @@ export default function ButtonModal() {
const [form] = Form.useForm()
const [result, setResult] = useState('')
const { isLoading, post } = useAI({
onComplete: (message) => {
setResult(message?.content || '')
},
})
const { isLoading, post } = useAI()
const handleAI = async () => {
const values = form.getFieldsValue()
const selectedFunction = values.function
const functionFormula = values.content || ''
post({
const message = await post({
messages: [
{
role: 'user',
......@@ -61,6 +57,7 @@ export default function ButtonModal() {
},
],
})
if (message.content) setResult(message.content)
}
// 处理下一步按钮逻辑
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'logic' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
return { ...query, progress: data.progress, message: data.message, remove }
......
......@@ -4,7 +4,7 @@ import { useDataQuery, useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { uniqBy } from 'lodash-es'
import { useProcessData } from '../query'
import { useAI } from '@/hooks/useAI'
import { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function ButtonModal() {
......@@ -39,14 +39,10 @@ export default function ButtonModal() {
}
const [result, setResult] = useState('')
const { isLoading, post } = useAI({
onComplete: (message) => {
setResult(message?.content || '')
},
})
const { isLoading, post } = useAI()
const handleAI = async () => {
post({
const message = await post({
messages: [
{
role: 'user',
......@@ -85,6 +81,7 @@ export default function ButtonModal() {
},
],
})
if (message.content) setResult(message.content)
}
// 处理下一步按钮逻辑
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'mapping' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
return { ...query, progress: data.progress, message: data.message, remove }
......
......@@ -3,7 +3,7 @@ import { Button, Flex, Modal, Input, Form, Select } from 'antd'
import AppProgressSteps from '@/components/AppProgressSteps'
import FunctionInput from '@/components/data/FunctionInput'
import { useProcessData } from '../query'
import { useAI } from '@/hooks/useAI'
import { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
const functionOptions = [
......@@ -35,18 +35,14 @@ export default function ButtonModal() {
const [form] = Form.useForm()
const [result, setResult] = useState('')
const { isLoading, post } = useAI({
onComplete: (message) => {
setResult(message?.content || '')
},
})
const { isLoading, post } = useAI()
const handleAI = async () => {
const values = form.getFieldsValue()
const selectedFunction = values.function
const functionFormula = values.content || ''
post({
const message = await post({
messages: [
{
role: 'user',
......@@ -70,6 +66,7 @@ export default function ButtonModal() {
},
],
})
if (message.content) setResult(message.content)
}
// 处理下一步按钮逻辑
const handleNext = async () => {
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'numeric' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
return { ...query, progress: data.progress, message: data.message, remove }
......
......@@ -3,7 +3,7 @@ import { Button, Flex, Modal, Input, Form, Select } from 'antd'
import AppProgressSteps from '@/components/AppProgressSteps'
import FunctionInput from '@/components/data/FunctionInput'
import { useProcessData } from '../query'
import { useAI } from '@/hooks/useAI'
import { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
const functionOptions = [
......@@ -49,18 +49,14 @@ export default function ButtonModal() {
const { mutate, isPending, progress, message, remove } = useProcessData()
const [result, setResult] = useState('')
const { isLoading, post } = useAI({
onComplete: (message) => {
setResult(message?.content || '')
},
})
const { isLoading, post } = useAI()
const handleAI = async () => {
const values = form.getFieldsValue()
const selectedFunction = values.function
const functionFormula = values.content || ''
post({
const message = await post({
messages: [
{
role: 'user',
......@@ -84,6 +80,7 @@ export default function ButtonModal() {
},
],
})
if (message.content) setResult(message.content)
}
// 开始处理
const handleStart = () => {
......
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { processData } from './api'
import type { ProcessDataParams } from './types'
import { useProcessProgressQuery } from '@/hooks/useQuery'
// 处理数据
export function useProcessData() {
const queryClient = useQueryClient()
const { data, start, remove } = useProcessProgressQuery({ function_name: 'text' })
const query = useMutation({
......@@ -14,7 +13,6 @@ export function useProcessData() {
},
onSuccess: () => {
start()
queryClient.invalidateQueries({ queryKey: ['data'] })
},
})
return { ...query, progress: data.progress, message: data.message, remove }
......
......@@ -3,8 +3,8 @@ import { Button, Radio, Flex, Modal, Empty } from 'antd'
import type { RadioChangeEvent } from 'antd'
import { useNavigate } from 'react-router'
import AppSteps from '@/components/AppSteps'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
import { useAIStore } from '@/ai/useAIStore'
import prompt from '@/ai/prompt'
import { useDataFieldQuery } from '@/hooks/useQuery'
interface ResultItem {
......@@ -13,26 +13,25 @@ interface ResultItem {
}
export default function ButtonModal() {
const [results, setResults] = useState<ResultItem[]>([])
const { fieldOptions } = useDataFieldQuery()
const [results, setResults] = useState<ResultItem[]>([])
const resultsOptions = results.map((result) => ({
label: result.name,
value: fieldOptions.find((option) => option.label === result.name)?.value || '',
}))
const { isLoading, post } = useAI({
onComplete: (message) => {
if (!message.content) return
const parse = JSON.parse(message.content)
console.log(parse)
setResults(parse.results || [])
},
})
const handleAI = () => {
post({
const { isLoading, post } = useAIStore()
const handleAI = async () => {
const message = await post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.min }],
messages: [{ role: 'user', content: prompt.error }],
})
console.log(message.json)
if (message.json && Array.isArray(message.json.results)) {
setResults(message.json.results)
}
}
const navigate = useNavigate()
......
......@@ -3,8 +3,9 @@ import { Button, Radio, Flex, Modal, Empty } from 'antd'
import type { RadioChangeEvent } from 'antd'
import { useNavigate } from 'react-router'
import AppSteps from '@/components/AppSteps'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
import { useAIStore } from '@/ai/useAIStore'
import prompt from '@/ai/prompt'
import { useDataFieldQuery } from '@/hooks/useQuery'
interface ResultItem {
......@@ -20,19 +21,17 @@ export default function ButtonModal() {
value: fieldOptions.find((option) => option.label === result.name)?.value || '',
}))
const { isLoading, post } = useAI({
onComplete: (message) => {
if (!message.content) return
const parse = JSON.parse(message.content)
console.log(parse)
setResults(parse.results || [])
},
})
const handleAI = () => {
post({
const { isLoading, post } = useAIStore()
const handleAI = async () => {
const message = await post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.max }],
})
console.log(message.json)
if (message.json && Array.isArray(message.json.results)) {
setResults(message.json.results)
}
}
const navigate = useNavigate()
......
......@@ -3,8 +3,8 @@ import { Button, Radio, Flex, Modal, Empty } from 'antd'
import type { RadioChangeEvent } from 'antd'
import { useNavigate } from 'react-router'
import AppSteps from '@/components/AppSteps'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
import { useAIStore } from '@/ai/useAIStore'
import prompt from '@/ai/prompt'
import { useDataFieldQuery } from '@/hooks/useQuery'
interface ResultItem {
......@@ -13,26 +13,25 @@ interface ResultItem {
}
export default function ButtonModal() {
const [results, setResults] = useState<ResultItem[]>([])
const { fieldOptions } = useDataFieldQuery()
const [results, setResults] = useState<ResultItem[]>([])
const resultsOptions = results.map((result) => ({
label: result.name,
value: fieldOptions.find((option) => option.label === result.name)?.value || '',
}))
const { isLoading, post } = useAI({
onComplete: (message) => {
if (!message.content) return
const parse = JSON.parse(message.content)
console.log(parse)
setResults(parse.results || [])
},
})
const handleAI = () => {
post({
const { isLoading, post } = useAIStore()
const handleAI = async () => {
const message = await post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.min }],
})
console.log(message.json)
if (message.json && Array.isArray(message.json.results)) {
setResults(message.json.results)
}
}
const navigate = useNavigate()
......
......@@ -3,8 +3,9 @@ import { Button, Checkbox, Empty, Flex, Modal } from 'antd'
import type { CheckboxProps } from 'antd'
import { useNavigate } from 'react-router'
import AppSteps from '@/components/AppSteps'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
import { useAIStore } from '@/ai/useAIStore'
import prompt from '@/ai/prompt'
import { useDataFieldQuery } from '@/hooks/useQuery'
const CheckboxGroup = Checkbox.Group
......@@ -15,28 +16,24 @@ interface ResultItem {
}
export default function ButtonModal() {
const [results, setResults] = useState<ResultItem[]>([])
const { fieldOptions } = useDataFieldQuery()
const [results, setResults] = useState<ResultItem[]>([])
const resultsOptions = results.map((result) => ({
label: result.name,
value: fieldOptions.find((option) => option.label === result.name)?.value || '',
}))
const { isLoading, post } = useAI({
onComplete: (message) => {
if (!message.content) return
const { isLoading, post } = useAIStore()
const parse = JSON.parse(message.content)
console.log(parse)
setResults(parse.results || [])
},
})
const handleAI = () => {
post({
const handleAI = async () => {
const message = await post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.null }],
})
console.log(message.json)
if (message.json && Array.isArray(message.json.results)) {
setResults(message.json.results)
}
}
const navigate = useNavigate()
......
import { useState, useMemo } from 'react'
import { useState, useMemo, useEffect } from 'react'
import { Button, Flex, Modal, Table, Checkbox } from 'antd'
import { DownloadOutlined } from '@ant-design/icons'
import { useDataFieldQuery } from '@/hooks/useQuery'
import { useAI } from '@/hooks/useAI'
import { useDataFieldQuery, useDataQuery } from '@/hooks/useQuery'
import { utils, writeFile } from 'xlsx'
interface ResultItem {
name: string
[key: string]: any
}
const buttons = ['最大值', '最小值', '平均值', '中位数', '众数', '1/4位数', '3/4位数', '方差', '标准差', '极差']
interface DataField {
name: string
english_name: string
type: string
}
interface DataListItem {
[key: string]: string | number
}
interface Stats {
最大值: number
最小值: number
平均值: number
中位数: number
众数: number
'1/4位数': number
'3/4位数': number
方差: number
标准差: number
极差: number
}
const buttons = [
'最大值',
'最小值',
'平均值',
'中位数',
'众数',
'1/4位数',
'3/4位数',
'方差',
'标准差',
'极差',
] as const
export default function ButtonModal() {
const { data = [] } = useDataFieldQuery()
const { data } = useDataQuery()
const { getFieldOptions } = useDataFieldQuery()
const numberFields = getFieldOptions('number') as DataField[]
const [results, setResults] = useState<ResultItem[]>(
data.filter((item: any) => {
return item.type.includes('DECIMAL') || item.type.includes('SMALLINT')
})
)
const { isLoading, post } = useAI({
onComplete: (message) => {
if (!message.content) return
const parse = JSON.parse(message.content)
console.log(parse)
setResults(parse.results || {})
},
const [selectedButtons, setSelectedButtons] = useState<string[]>([])
const calculateStats = (values: number[]): Stats => {
const sortedValues = [...values].sort((a, b) => a - b)
const n = values.length
const sum = values.reduce((a, b) => a + b, 0)
const mean = sum / n
const variance = values.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / n
const roundToTwo = (num: number) => Math.round(num * 100) / 100
return {
最大值: roundToTwo(Math.max(...values)),
最小值: roundToTwo(Math.min(...values)),
平均值: roundToTwo(mean),
中位数: roundToTwo(
n % 2 === 0 ? (sortedValues[n / 2 - 1] + sortedValues[n / 2]) / 2 : sortedValues[Math.floor(n / 2)]
),
众数: roundToTwo(
(() => {
const frequency: { [key: number]: number } = {}
values.forEach((v) => (frequency[v] = (frequency[v] || 0) + 1))
return Number(Object.entries(frequency).sort((a, b) => b[1] - a[1])[0][0])
})()
),
'1/4位数': roundToTwo(sortedValues[Math.floor(n * 0.25)]),
'3/4位数': roundToTwo(sortedValues[Math.floor(n * 0.75)]),
方差: roundToTwo(variance),
标准差: roundToTwo(Math.sqrt(variance)),
极差: roundToTwo(Math.max(...values) - Math.min(...values)),
}
}
const results = numberFields.map((field) => {
const fieldData = (data.list as DataListItem[])
.map((item) => Number(item[field.english_name]))
.filter((v: number) => !isNaN(v))
if (fieldData.length === 0) return field
const stats = calculateStats(fieldData)
const result: ResultItem = { name: field.name }
selectedButtons.forEach((button) => {
result[button] = stats[button as keyof Stats]
})
const handleAI = () => {
const names = results.map((item: any) => item.name).join(',')
post({
response_format: { type: 'json_object' },
messages: [
{
role: 'user',
content: `请帮我计算数据集中,字段${names}${selectedButtons.join('、')}
返回格式示例:
json
{
results:[
{ name: "字段1", 计算类型(中文):"计算结果" },
{ name: "字段2", 计算类型(中文):"计算结果" },
]
}`,
},
],
return result
})
}
const [open, setOpen] = useState(false)
const [title, setTitle] = useState('')
......@@ -57,8 +108,6 @@ json
setOpen(true)
}
const [selectedButtons, setSelectedButtons] = useState<string[]>([])
const dataSource = results.map((item) => {
return { ...item, key: item.name }
})
......@@ -111,19 +160,7 @@ json
{button}
</Button>
))}
<Modal
title={title}
open={open}
footer={
<Flex justify="center" gap={20}>
<Button type="primary" loading={isLoading} onClick={handleAI}>
一键计算
</Button>
</Flex>
}
destroyOnClose
width={1000}
onCancel={() => setOpen(false)}>
<Modal title={title} open={open} footer={null} destroyOnClose width={1000} onCancel={() => setOpen(false)}>
<div style={{ minHeight: 300, padding: '20px 0' }}>
<Flex justify="space-between" align="center" style={{ marginBottom: '20px' }}>
<div>
......
......@@ -3,25 +3,29 @@ import { Button, Empty, Flex, Modal } from 'antd'
import { useNavigate } from 'react-router'
import AppSteps from '@/components/AppSteps'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
import { useAIStore } from '@/ai/useAIStore'
import prompt from '@/ai/prompt'
interface ResultItem {
line: number
lines: number[]
desc: string
}
export default function ButtonModal() {
const [results, setResults] = useState<Array<{ line: number; lines: number[]; desc: string }>>([])
const [results, setResults] = useState<ResultItem[]>([])
const { isLoading, post } = useAI({
onComplete: (message) => {
if (!message.content) return
const parse = JSON.parse(message.content)
console.log(parse)
setResults(parse.results || [])
},
})
const handleAI = () => {
post({
const { isLoading, post } = useAIStore()
const handleAI = async () => {
const message = await post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.repeat }],
})
console.log(message.json)
if (message.json && Array.isArray(message.json.results)) {
setResults(message.json.results)
}
}
const navigate = useNavigate()
......
import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
import { useAIStore } from '@/stores/ai'
import { Button, message } from 'antd'
import { useAIStore } from '@/ai/useAIStore'
export default function DataWriteUpload() {
const [messageApi, contextHolder] = message.useMessage()
const post = useAIStore((state) => state.post)
const isLoading = useAIStore((state) => state.isLoading)
function handleClick(type: number) {
async function handleClick(type: number) {
messageApi.open({ type: 'loading', content: '数据正在智能分析中,请您耐心等待', duration: 0 })
if (type == 1) {
post({
await post({
messages: [
{
role: 'user',
......@@ -29,7 +30,7 @@ export default function DataWriteUpload() {
],
})
} else {
post({
await post({
messages: [
{
role: 'user',
......@@ -50,6 +51,8 @@ export default function DataWriteUpload() {
],
})
}
messageApi.destroy()
}
return (
......@@ -57,10 +60,11 @@ export default function DataWriteUpload() {
title="数据理解"
buttons={
<>
<Button type="primary" onClick={() => handleClick(1)} loading={isLoading}>
{contextHolder}
<Button type="primary" onClick={() => handleClick(1)}>
一键理解数据字段
</Button>
<Button type="primary" onClick={() => handleClick(2)} loading={isLoading}>
<Button type="primary" onClick={() => handleClick(2)}>
一键梳理字段关系
</Button>
</>
......
......@@ -11,6 +11,7 @@ export function useCopyDataset() {
onSuccess: () => {
message.success('复制成功')
queryClient.invalidateQueries({ queryKey: ['data'] })
queryClient.invalidateQueries({ queryKey: ['dataFiled'] })
},
})
}
import { Button, Flex, Modal, Spin } from 'antd'
import { useEffect, useState } from 'react'
import { useAI } from '@/hooks/useAI'
import { useAI } from '@/ai/useAI'
import MarkdownRender from '@/components/MarkdownRender'
export default function DataReport() {
......
import { create } from 'zustand'
import aiService, { AIOption, AIMessage, AIData, AI_OPTIONS, InitOptions } from '@/utils/ai'
\ No newline at end of file
interface AIState {
ai: string
options: AIOption[]
message: AIMessage | null
messages: AIMessage[]
isLoading: boolean
collapsed: boolean
setAI: (ai: string) => void
toggleCollapsed: () => void
post: (data: AIData, options?: InitOptions) => Promise<void>
}
export const useAIStore = create<AIState>((set, get) => ({
ai: localStorage.getItem('ai') || 'qwen',
options: AI_OPTIONS,
message: null,
messages: [],
isLoading: false,
collapsed: false,
setAI: (ai) => {
localStorage.setItem('ai', ai)
set({ ai })
},
toggleCollapsed: () => {
set((state) => ({ collapsed: !state.collapsed }))
},
post: async (data, options) => {
const { ai, messages } = get()
// 处理用户消息(去掉 system 角色的消息)
const userMessages = data.messages.filter((item) => item.role !== 'system')
set({
collapsed: true,
isLoading: true,
messages: [...messages, ...userMessages],
})
try {
await aiService.post(ai, data, {
onMessage: (response) => {
set((state) => {
const messageIndex = state.messages.findIndex((msg) => msg.id === response.id)
if (messageIndex === -1) {
// 新的 AI 回复
const newMessage: AIMessage = { id: response.id, role: 'assistant', content: response.content }
return {
message: newMessage, // 存储最新的 AI 消息
messages: [...state.messages, newMessage], // 追加到历史消息
}
} else {
// 追加内容到已有的消息
const updatedMessages = state.messages.map((msg) =>
msg.id === response.id ? { ...msg, content: msg.content + response.content } : msg
)
return {
message: updatedMessages[messageIndex], // 更新最新的 AI 消息
messages: updatedMessages,
}
}
})
},
onerror: (err) => {
console.error('AI 请求失败:', err)
set({ isLoading: false })
},
onclose: () => {
set({ isLoading: false })
},
...options,
})
} catch (err) {
console.error('AI 请求失败:', err)
set({ isLoading: false })
}
},
}))
export type { AIMessage }
export function extractJSON(str: string) {
const jsonRegex = /(\{.*\}|\[.*\])/s
const match = str.match(jsonRegex)
if (!match) return null
try {
return JSON.parse(match[0])
} catch (e) {
return null
}
}
......@@ -10,13 +10,7 @@ export default defineConfig({
open: true,
host: 'dev.ezijing.com',
proxy: {
// '/api/resource/bi': {
// target: 'https://saas-lab.ezijing.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api\/bi/, '/api/resource/bi'),
// },
// '/api/resource/bi': 'https://saas-lab.ezijing.com/api/resource/bi',
'/api': 'https://saas-lab.ezijing.com',
'/api': 'https://saas-bi.ezijing.com',
},
},
resolve: {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论