Compare commits
4 Commits
60477f99f5
...
0f5ae1c4d4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f5ae1c4d4 | ||
|
|
48e42ee99a | ||
|
|
0914b458d3 | ||
|
|
368c30676e |
@@ -6,10 +6,13 @@ import com.lanyuanxiaoyao.service.ai.web.entity.vo.MessageVO;
|
||||
import com.lanyuanxiaoyao.service.ai.web.tools.ChartTool;
|
||||
import com.lanyuanxiaoyao.service.ai.web.tools.TableTool;
|
||||
import com.lanyuanxiaoyao.service.ai.web.tools.YarnTool;
|
||||
import com.lanyuanxiaoyao.service.configuration.ExecutorProvider;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import org.eclipse.collections.api.list.ImmutableList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -98,24 +101,34 @@ public class ChatController {
|
||||
|
||||
@PostMapping("async")
|
||||
public SseEmitter chatAsync(
|
||||
@RequestBody ImmutableList<MessageVO> messages
|
||||
@RequestBody ImmutableList<MessageVO> messages,
|
||||
HttpServletResponse httpResponse
|
||||
) {
|
||||
SseEmitter emitter = new SseEmitter();
|
||||
buildRequest(messages)
|
||||
.stream()
|
||||
.chatResponse()
|
||||
.subscribe(
|
||||
response -> {
|
||||
try {
|
||||
emitter.send(toMessage(response));
|
||||
} catch (IOException e) {
|
||||
emitter.completeWithError(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
},
|
||||
emitter::completeWithError,
|
||||
emitter::complete
|
||||
);
|
||||
httpResponse.setHeader("X-Accel-Buffering", "no");
|
||||
|
||||
SseEmitter emitter = new SseEmitter(20 * 60 * 1000L);
|
||||
ExecutorProvider.EXECUTORS.submit(() -> {
|
||||
buildRequest(messages)
|
||||
.stream()
|
||||
.chatResponse()
|
||||
.subscribe(
|
||||
response -> {
|
||||
try {
|
||||
emitter.send(
|
||||
SseEmitter.event()
|
||||
.data(toMessage(response))
|
||||
.reconnectTime(5 * 1000L)
|
||||
.build()
|
||||
);
|
||||
} catch (IOException e) {
|
||||
emitter.completeWithError(e);
|
||||
}
|
||||
},
|
||||
emitter::completeWithError,
|
||||
emitter::complete
|
||||
);
|
||||
});
|
||||
emitter.onTimeout(() -> emitter.completeWithError(new TimeoutException("SseEmitter Timeout")));
|
||||
return emitter;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,17 +10,17 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^6.0.0",
|
||||
"@ant-design/pro-components": "^2.8.7",
|
||||
"@ant-design/pro-components": "^2.8.9",
|
||||
"@ant-design/x": "^1.4.0",
|
||||
"@echofly/fetch-event-source": "^3.0.2",
|
||||
"@fortawesome/fontawesome-free": "^6.7.2",
|
||||
"@lightenna/react-mermaid-diagram": "^1.0.20",
|
||||
"@tinyflow-ai/react": "^0.1.10",
|
||||
"@tinyflow-ai/react": "^0.2.1",
|
||||
"ahooks": "^3.8.5",
|
||||
"amis": "^6.12.0",
|
||||
"antd": "^5.25.3",
|
||||
"axios": "^1.9.0",
|
||||
"chart.js": "^4.4.9",
|
||||
"antd": "^5.26.1",
|
||||
"axios": "^1.10.0",
|
||||
"chart.js": "^4.5.0",
|
||||
"echarts-for-react": "^3.0.2",
|
||||
"licia": "^1.48.0",
|
||||
"markdown-it": "^14.1.0",
|
||||
@@ -29,18 +29,17 @@
|
||||
"react-chartjs-2": "^5.3.0",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-router": "^7.6.1",
|
||||
"react-router": "^7.6.2",
|
||||
"styled-components": "^6.1.18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/markdown-it": "^14.1.2",
|
||||
"@types/react": "^18.3.23",
|
||||
"@types/react-dom": "^18.3.7",
|
||||
"@vitejs/plugin-react-swc": "^3.10.0",
|
||||
"@vitejs/plugin-react-swc": "^3.10.2",
|
||||
"globals": "^16.2.0",
|
||||
"sass": "^1.89.0",
|
||||
"sass": "^1.89.2",
|
||||
"typescript": "~5.8.3",
|
||||
"typescript-eslint": "^8.33.0",
|
||||
"vite": "^6.3.5",
|
||||
"vite-plugin-javascript-obfuscator": "^3.1.0"
|
||||
}
|
||||
|
||||
2115
service-web/client/pnpm-lock.yaml
generated
2115
service-web/client/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,128 +1,18 @@
|
||||
import MarkdownRender from '../util/Markdown.tsx'
|
||||
import {useState} from 'react'
|
||||
|
||||
// language=Markdown
|
||||
const markdownText = `### Hello
|
||||
|
||||
world
|
||||
tony
|
||||
jenny
|
||||
|
||||
\`\`\`javascript
|
||||
console.log('hello')
|
||||
\`\`\`
|
||||
|
||||
\`\`\`mermaid
|
||||
graph TD
|
||||
a-->b;
|
||||
\`\`\`
|
||||
|
||||
\`\`\`mermaid
|
||||
graph TD
|
||||
c-->d;
|
||||
\`\`\`
|
||||
|
||||
\`\`\`chartjs
|
||||
{
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ['苹果', '香蕉', '橙子', '葡萄', '菠萝'],
|
||||
datasets: [{
|
||||
label: '水果销量',
|
||||
data: [43, 32, 56, 29, 38],
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: '水果店周销量数据'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
\`\`\`chartjs
|
||||
{
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ['苹果', '香蕉', '橙子', '葡萄', '菠萝'],
|
||||
datasets: [{
|
||||
label: '水果销量',
|
||||
data: [43, 32, 56, 29, 38],
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: '水果店周销量数据'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
\`\`\`echart
|
||||
{
|
||||
grid: { top: 8, right: 8, bottom: 24, left: 36 },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [820, 932, 901, 934, 1290, 1330, 1320],
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
\`\`\`echart
|
||||
{
|
||||
grid: { top: 8, right: 8, bottom: 24, left: 36 },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [820, 932, 901, 934, 1290, 1330, 1320],
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
}
|
||||
\`\`\``
|
||||
import {Tinyflow} from '@tinyflow-ai/react'
|
||||
import '@tinyflow-ai/react/dist/index.css'
|
||||
|
||||
function Test() {
|
||||
const [value, setValue] = useState<string>(markdownText)
|
||||
return (
|
||||
<>
|
||||
<button onClick={() => setValue('hahaha\n' + markdownText)}>Button</button>
|
||||
<MarkdownRender content={value}/>
|
||||
</>
|
||||
<div className="flowable">
|
||||
<Tinyflow
|
||||
className="tinyflow-instance"
|
||||
style={{height: '95vh'}}
|
||||
onDataChange={(value) => {
|
||||
console.log(value)
|
||||
console.log(JSON.stringify(value))
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {ClearOutlined, UserOutlined} from '@ant-design/icons'
|
||||
import {Bubble, Sender, useXAgent, useXChat, Welcome} from '@ant-design/x'
|
||||
import {fetchEventSource} from '@echofly/fetch-event-source'
|
||||
import {useUnmount} from 'ahooks'
|
||||
import {Button, Collapse, Flex, Typography} from 'antd'
|
||||
import {isStrBlank, trim} from 'licia'
|
||||
import {useRef, useState} from 'react'
|
||||
@@ -40,6 +41,11 @@ function Conversation() {
|
||||
const abortController = useRef<AbortController | null>(null)
|
||||
const [input, setInput] = useState<string>('')
|
||||
|
||||
useUnmount(() => {
|
||||
console.log('Page Unmount')
|
||||
abortController.current?.abort()
|
||||
})
|
||||
|
||||
const [agent] = useXAgent<ChatMessage>({
|
||||
request: async (info, callbacks) => {
|
||||
await fetchEventSource(`${commonInfo.baseAiUrl}/chat/async`, {
|
||||
@@ -55,6 +61,7 @@ function Conversation() {
|
||||
})
|
||||
},
|
||||
onclose: () => callbacks.onSuccess([]),
|
||||
onerror: error => callbacks.onError(error),
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user