Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
pms-dispatch-assistant
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
姜耀祖
pms-dispatch-assistant
Commits
b61b4e32
Commit
b61b4e32
authored
Apr 18, 2025
by
赵灿灿
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修改配置信息
parent
05b75a64
Pipeline
#21037
passed with stages
in 3 minutes and 2 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
118 additions
and
90 deletions
+118
-90
LangChainController.java
...chassistant/controller/langchain/LangChainController.java
+104
-75
ai-chat-vue.js
src/main/resources/static/pages/langchain/js/ai-chat-vue.js
+14
-15
No files found.
src/main/java/com/infoepoch/pms/dispatchassistant/controller/langchain/LangChainController.java
View file @
b61b4e32
...
@@ -60,6 +60,7 @@ import java.util.concurrent.TimeUnit;
...
@@ -60,6 +60,7 @@ import java.util.concurrent.TimeUnit;
@RequestMapping
(
"/api/langchain"
)
@RequestMapping
(
"/api/langchain"
)
public
class
LangChainController
{
public
class
LangChainController
{
@Autowired
@Autowired
private
Auth
auth
;
private
Auth
auth
;
...
@@ -278,75 +279,80 @@ public class LangChainController {
...
@@ -278,75 +279,80 @@ public class LangChainController {
//调用智能体
//调用智能体
@GetMapping
(
"/sseIntelligent"
)
@GetMapping
(
"/sseIntelligent"
)
public
ResponseEntity
<
SseEmitter
>
sse
(
@RequestParam
String
chatMessage
)
{
public
ResponseEntity
<
SseEmitter
>
sse
(
@RequestParam
String
chatMessage
,
@RequestParam
String
dialogId
)
{
// curl http://10.32.41.228:39080/v1/chat/completions -X POST
logger
.
info
(
"开始调用1"
);
// -H "Content-Type:application/json;charset=UTF-8"
//String urlAddr = "http://10.32.41.35:40517/scene_gateway/agent/6809d0895428476bb6789ad70c525c97";
// -H "AI-API-CODE:usOPREkI33" -H "AI-APP-KEY:vXRDti1mJg"
String
urlAddr
=
"http://10.32.41.35:40517/scene_gateway/agent/83f77143b09c461993dd9a7db403eb94"
;
// --data '{"stream":false,"model":"Qwen1.5-32B-NPU910B","messages":[{"role":"user","content":""}]} '
SseEmitter
emitter
=
new
SseEmitter
(
0L
);
String
urlAddr
=
"http://10.32.41.35:40517/scene_gateway/agent/6809d0895428476bb6789ad70c525c97"
;
QuestionRequest
questionRequest
=
new
QuestionRequest
();
BufferedReader
reader
=
null
;
questionRequest
.
setKeyword
(
chatMessage
);
try
{
questionRequest
.
setRequestId
(
getRequestId
());
URL
url
=
new
URL
(
urlAddr
);
questionRequest
.
setDialogId
(
dialogId
);
// 建立链接
String
params
=
JsonUtils
.
objectToJson
(
questionRequest
);
HttpURLConnection
connection
=
(
HttpURLConnection
)
url
.
openConnection
();
new
Thread
(()
->
{
String
responseEntity
=
""
;
HttpURLConnection
connection
=
null
;
QuestionRequest
questionRequest
=
new
QuestionRequest
();
try
{
questionRequest
.
setKeyword
(
chatMessage
);
URL
url
=
new
URL
(
urlAddr
);
// (yyyyMMddHHmmssSSS)+6位随机数;
// 建立链接
Random
random
=
new
Random
();
connection
=
(
HttpURLConnection
)
url
.
openConnection
();
Integer
min
=
100000
;
// 最小值(6位起始)
connection
.
setRequestMethod
(
"GET"
);
Integer
max
=
999999
;
// 最大值(6位结束)
//connection.setRequestProperty("AuthToken", "4009fe23e6b648539792330c14f5ed8e");
// 生成范围:min <= num <= max
connection
.
setRequestProperty
(
"AuthToken"
,
"fc40db5b7abe47dabfe1899e61fde2d7"
);
Integer
randomNum
=
random
.
nextInt
(
max
-
min
+
1
)
+
min
;
// 允许输入和输出
String
currentDay
=
DateTool
.
format
(
new
Date
(),
"yyyyMMddHHmmssSSS"
);
connection
.
setDoInput
(
true
);
connection
.
setRequestMethod
(
"GET"
);
connection
.
setDoOutput
(
true
);
connection
.
setRequestProperty
(
"Accept"
,
"text/event-stream"
);
// 设置超时为0,表示无限制
connection
.
setRequestProperty
(
"Content-type"
,
"application/json; charset=UTF-8"
);
connection
.
setConnectTimeout
(
0
);
connection
.
setRequestProperty
(
"AuthToken"
,
"4009fe23e6b648539792330c14f5ed8e"
);
connection
.
setReadTimeout
(
0
);
connection
.
setRequestProperty
(
"Cache-Control"
,
"no-cache"
);
connection
.
setRequestProperty
(
"Connection"
,
"keep-alive"
);
logger
.
info
(
params
);
questionRequest
.
setRequestId
(
currentDay
+
randomNum
.
toString
());
try
(
OutputStream
os
=
connection
.
getOutputStream
())
{
questionRequest
.
setDialogId
(
currentDay
+
randomNum
.
toString
());
os
.
write
(
params
.
getBytes
(
StandardCharsets
.
UTF_8
));
String
params
=
JsonUtils
.
objectToJson
(
questionRequest
);
os
.
flush
();
// 允许输入和输出
}
connection
.
setDoInput
(
true
);
logger
.
info
(
"开始调用2"
);
connection
.
setDoOutput
(
true
);
// 检查响应码
// 设置超时为0,表示无限制
int
responseCode
=
connection
.
getResponseCode
();
connection
.
setConnectTimeout
(
0
);
if
(
responseCode
!=
HttpURLConnection
.
HTTP_OK
)
{
connection
.
setReadTimeout
(
0
);
emitter
.
completeWithError
(
new
RuntimeException
(
"SSE 连接失败: "
+
responseCode
));
// 传参
return
;
//String params = "prompt=哈哈哈哈";
}
// 写入POST数据
logger
.
info
(
"开始调用3"
);
DataOutputStream
out
=
new
DataOutputStream
(
connection
.
getOutputStream
());
// 持续读取 SSE 数据流
out
.
write
(
params
.
getBytes
(
StandardCharsets
.
UTF_8
));
try
(
BufferedReader
reader
=
new
BufferedReader
(
new
InputStreamReader
(
connection
.
getInputStream
())))
{
out
.
flush
();
String
line
;
out
.
close
();
while
((
line
=
reader
.
readLine
())
!=
null
)
{
// 读取SSE事件
logger
.
info
(
line
);
reader
=
new
BufferedReader
(
new
InputStreamReader
(
connection
.
getInputStream
(),
StandardCharsets
.
UTF_8
));
if
(!
line
.
startsWith
(
"data:CALLBACK#"
))
{
String
line
;
if
(
line
.
startsWith
(
"data:"
))
{
SseEmitter
emitter
=
new
SseEmitter
();
String
data
=
line
.
substring
(
5
).
trim
();
while
((
line
=
reader
.
readLine
())
!=
null
)
{
if
(
"stop"
.
equals
(
data
))
System
.
out
.
println
(
line
);
{
emitter
.
send
(
SseEmitter
.
event
().
data
(
line
));
emitter
.
send
(
SseEmitter
.
event
().
data
(
"stop"
),
MediaType
.
parseMediaType
(
"application/json; charset=UTF-8"
));
}
else
{
emitter
.
send
(
SseEmitter
.
event
().
data
(
data
),
MediaType
.
parseMediaType
(
"application/json; charset=UTF-8"
));
}
}
}
}
}
emitter
.
complete
();
// 流结束
}
catch
(
Exception
e
)
{
emitter
.
completeWithError
(
e
);
logger
.
info
(
e
.
getMessage
());
}
finally
{
if
(
connection
!=
null
)
{
connection
.
disconnect
();
}
}
}
reader
.
close
();
}).
start
();
System
.
out
.
println
(
" __stop__"
);
emitter
.
send
(
SseEmitter
.
event
().
data
(
" __stop__"
));
return
ResponseEntity
.
ok
()
emitter
.
complete
();
.
header
(
HttpHeaders
.
CONTENT_TYPE
,
MediaType
.
TEXT_EVENT_STREAM_VALUE
)
// 断开链接
.
body
(
emitter
);
connection
.
disconnect
();
return
ResponseEntity
.
ok
()
.
header
(
HttpHeaders
.
CONTENT_TYPE
,
MediaType
.
TEXT_EVENT_STREAM_VALUE
)
.
body
(
emitter
);
}
catch
(
Exception
e
)
{
logger
.
info
(
e
.
getMessage
());
e
.
printStackTrace
();
}
finally
{
return
ResponseEntity
.
ok
()
.
header
(
HttpHeaders
.
CONTENT_TYPE
,
MediaType
.
TEXT_EVENT_STREAM_VALUE
)
.
body
(
null
);
//IoUtils.copy(reader);
}
}
}
...
@@ -412,7 +418,7 @@ public class LangChainController {
...
@@ -412,7 +418,7 @@ public class LangChainController {
//调用大模型接口
//调用大模型接口
@GetMapping
(
"/sseQwen"
)
@GetMapping
(
"/sseQwen"
)
public
ResponseEntity
<
SseEmitter
>
sse
BigTwo
(
@RequestParam
String
chatMessage
,
@RequestParam
String
sessionId
)
{
public
ResponseEntity
<
SseEmitter
>
sse
Qwen
(
@RequestParam
String
chatMessage
,
@RequestParam
String
sessionId
)
{
String
history
=
redisTool
.
get
(
sessionId
);
String
history
=
redisTool
.
get
(
sessionId
);
List
<
Map
<
String
,
Object
>>
historyList
=
new
ArrayList
<>();
List
<
Map
<
String
,
Object
>>
historyList
=
new
ArrayList
<>();
...
@@ -474,6 +480,7 @@ public class LangChainController {
...
@@ -474,6 +480,7 @@ public class LangChainController {
while
((
line
=
reader
.
readLine
())
!=
null
)
{
while
((
line
=
reader
.
readLine
())
!=
null
)
{
if
(
line
.
startsWith
(
"data: "
))
{
if
(
line
.
startsWith
(
"data: "
))
{
String
data
=
line
.
substring
(
5
).
trim
();
String
data
=
line
.
substring
(
5
).
trim
();
logger
.
info
(
data
);
QwenLine
qwenLine
=
JsonUtils
.
jsonToObject
(
data
,
QwenLine
.
class
);
QwenLine
qwenLine
=
JsonUtils
.
jsonToObject
(
data
,
QwenLine
.
class
);
String
lineContent
=
qwenLine
.
getChoices
().
get
(
0
).
getDelta
().
getContent
();
String
lineContent
=
qwenLine
.
getChoices
().
get
(
0
).
getDelta
().
getContent
();
String
lineFinish
=
qwenLine
.
getChoices
().
get
(
0
).
getFinish_reason
();
String
lineFinish
=
qwenLine
.
getChoices
().
get
(
0
).
getFinish_reason
();
...
@@ -491,8 +498,6 @@ public class LangChainController {
...
@@ -491,8 +498,6 @@ public class LangChainController {
contentAssistant
.
append
(
lineContent
);
contentAssistant
.
append
(
lineContent
);
emitter
.
send
(
SseEmitter
.
event
().
data
(
lineContent
),
MediaType
.
parseMediaType
(
"application/json; charset=UTF-8"
));
emitter
.
send
(
SseEmitter
.
event
().
data
(
lineContent
),
MediaType
.
parseMediaType
(
"application/json; charset=UTF-8"
));
}
}
logger
.
info
(
line
);
logger
.
info
(
lineContent
);
// 将数据转发给前端
// 将数据转发给前端
}
}
}
}
...
@@ -516,7 +521,7 @@ public class LangChainController {
...
@@ -516,7 +521,7 @@ public class LangChainController {
private
static
final
CloseableHttpClient
httpClient
;
private
static
final
CloseableHttpClient
httpClient
;
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
LangChainController
.
class
);
static
{
static
{
PoolingHttpClientConnectionManager
connManager
=
new
PoolingHttpClientConnectionManager
();
PoolingHttpClientConnectionManager
connManager
=
new
PoolingHttpClientConnectionManager
();
connManager
.
setMaxTotal
(
100
);
connManager
.
setMaxTotal
(
100
);
...
@@ -561,8 +566,8 @@ public class LangChainController {
...
@@ -561,8 +566,8 @@ public class LangChainController {
}).
start
();
}).
start
();
// 超时和完成回调
// 超时和完成回调
emitter
.
onTimeout
(()
->
log
.
warn
(
"SSE连接超时"
));
emitter
.
onTimeout
(()
->
log
ger
.
warn
(
"SSE连接超时"
));
emitter
.
onCompletion
(()
->
log
.
info
(
"SSE连接完成"
));
emitter
.
onCompletion
(()
->
log
ger
.
info
(
"SSE连接完成"
));
return
emitter
;
return
emitter
;
}
}
...
@@ -599,7 +604,7 @@ public class LangChainController {
...
@@ -599,7 +604,7 @@ public class LangChainController {
// 统一异常处理
// 统一异常处理
private
void
handleException
(
Exception
e
,
SseEmitter
emitter
)
{
private
void
handleException
(
Exception
e
,
SseEmitter
emitter
)
{
log
.
error
(
"API调用异常"
,
e
);
log
ger
.
error
(
"API调用异常"
,
e
);
if
(
e
instanceof
SocketTimeoutException
)
{
if
(
e
instanceof
SocketTimeoutException
)
{
emitter
.
completeWithError
(
new
RuntimeException
(
"连接DeepSeek服务超时"
));
emitter
.
completeWithError
(
new
RuntimeException
(
"连接DeepSeek服务超时"
));
}
else
{
}
else
{
...
@@ -607,10 +612,34 @@ public class LangChainController {
...
@@ -607,10 +612,34 @@ public class LangChainController {
}
}
}
}
//获取sessionId
@GetMapping
(
"/getSessionId"
)
@GetMapping
(
"/getSessionId"
)
public
Result
getSessionId
()
{
public
Result
getSessionId
()
{
return
Result
.
successData
(
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
));
return
Result
.
successData
(
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
));
}
}
//获取requestId
public
String
getRequestId
()
{
// (yyyyMMddHHmmssSSS)+6位随机数;
Random
random
=
new
Random
();
Integer
min
=
100000
;
// 最小值(6位起始)
Integer
max
=
999999
;
// 最大值(6位结束)
// 生成范围:min <= num <= max
Integer
randomNum
=
random
.
nextInt
(
max
-
min
+
1
)
+
min
;
String
currentDay
=
DateTool
.
format
(
new
Date
(),
"yyyyMMddHHmmssSSS"
);
return
currentDay
+
randomNum
.
toString
();
}
//获取会话ID
@GetMapping
(
"/getDialogId"
)
public
Result
getDialogId
()
{
// (yyyyMMddHHmmssSSS)+6位随机数;
Random
random
=
new
Random
();
Integer
min
=
100000
;
// 最小值(6位起始)
Integer
max
=
999999
;
// 最大值(6位结束)
// 生成范围:min <= num <= max
Integer
randomNum
=
random
.
nextInt
(
max
-
min
+
1
)
+
min
;
String
currentDay
=
DateTool
.
format
(
new
Date
(),
"yyyyMMddHHmmssSSS"
);
return
Result
.
successData
(
currentDay
+
randomNum
.
toString
());
}
}
}
src/main/resources/static/pages/langchain/js/ai-chat-vue.js
View file @
b61b4e32
...
@@ -110,7 +110,8 @@ require(['jquery', 'vue', 'utils', 'echarts', 'global'], function ($, Vue, utils
...
@@ -110,7 +110,8 @@ require(['jquery', 'vue', 'utils', 'echarts', 'global'], function ($, Vue, utils
// 会话相关方法
// 会话相关方法
async
getSessionId
()
{
async
getSessionId
()
{
try
{
try
{
const
response
=
await
fetch
(
'../../api/langchain/getSessionId'
);
//const response = await fetch('../../api/langchain/getSessionId');
const
response
=
await
fetch
(
'../../api/langchain/getDialogId'
);
const
dataJson
=
await
response
.
json
();
const
dataJson
=
await
response
.
json
();
this
.
sessionId
=
dataJson
.
data
;
this
.
sessionId
=
dataJson
.
data
;
}
catch
(
error
)
{
}
catch
(
error
)
{
...
@@ -172,12 +173,12 @@ require(['jquery', 'vue', 'utils', 'echarts', 'global'], function ($, Vue, utils
...
@@ -172,12 +173,12 @@ require(['jquery', 'vue', 'utils', 'echarts', 'global'], function ($, Vue, utils
}
}
});
});
},
},
connectSSE
(
chatMessage
)
{
connectSSE
(
chatMessage
)
{
// 在消息列表中添加一个带"正在输入"指示器的AI消息
// 在消息列表中添加一个带"正在输入"指示器的AI消息
const
aiMessageIndex
=
this
.
messages
.
length
;
const
aiMessageIndex
=
this
.
messages
.
length
;
this
.
messages
.
push
({
role
:
'ai'
,
content
:
''
,
typing
:
true
});
this
.
messages
.
push
({
role
:
'ai'
,
content
:
''
,
typing
:
true
});
// 自动滚动到底部
// 自动滚动到底部
this
.
$nextTick
(()
=>
{
this
.
$nextTick
(()
=>
{
const
messagesDiv
=
document
.
getElementById
(
'chat-messages'
);
const
messagesDiv
=
document
.
getElementById
(
'chat-messages'
);
...
@@ -185,16 +186,14 @@ require(['jquery', 'vue', 'utils', 'echarts', 'global'], function ($, Vue, utils
...
@@ -185,16 +186,14 @@ require(['jquery', 'vue', 'utils', 'echarts', 'global'], function ($, Vue, utils
messagesDiv
.
scrollTop
=
messagesDiv
.
scrollHeight
;
messagesDiv
.
scrollTop
=
messagesDiv
.
scrollHeight
;
}
}
});
});
// 连接SSE
// 连接SSE
this
.
currentEventSource
=
new
EventSource
(
'../../api/langchain/sse
BigTwo?chatMessage='
+
encodeURIComponent
(
chatMessage
)
+
"&session
Id="
+
this
.
sessionId
);
this
.
currentEventSource
=
new
EventSource
(
'../../api/langchain/sse
Intelligent?chatMessage='
+
encodeURIComponent
(
chatMessage
)
+
"&dialog
Id="
+
this
.
sessionId
);
let
responseText
=
''
;
let
responseText
=
''
;
this
.
currentEventSource
.
onmessage
=
(
event
)
=>
{
this
.
currentEventSource
.
onmessage
=
(
event
)
=>
{
const
data
=
JSON
.
parse
(
event
.
data
);
const
data
=
JSON
.
parse
(
event
.
data
);
const
content
=
data
.
dataToSend
[
1
].
data
;
const
content
=
data
.
dataToSend
[
1
].
data
;
if
(
content
!==
"stop"
)
{
if
(
content
!==
"stop"
)
{
responseText
+=
content
;
responseText
+=
content
;
this
.
messages
[
aiMessageIndex
].
content
=
responseText
;
this
.
messages
[
aiMessageIndex
].
content
=
responseText
;
...
@@ -202,15 +201,15 @@ require(['jquery', 'vue', 'utils', 'echarts', 'global'], function ($, Vue, utils
...
@@ -202,15 +201,15 @@ require(['jquery', 'vue', 'utils', 'echarts', 'global'], function ($, Vue, utils
// 移除输入指示器
// 移除输入指示器
this
.
messages
[
aiMessageIndex
].
typing
=
false
;
this
.
messages
[
aiMessageIndex
].
typing
=
false
;
this
.
chatHistory
.
push
({
role
:
'ai'
,
content
:
responseText
});
this
.
chatHistory
.
push
({
role
:
'ai'
,
content
:
responseText
});
// 切换回发送按钮
// 切换回发送按钮
this
.
isResponding
=
false
;
this
.
isResponding
=
false
;
// 关闭事件源
// 关闭事件源
this
.
currentEventSource
.
close
();
this
.
currentEventSource
.
close
();
this
.
currentEventSource
=
null
;
this
.
currentEventSource
=
null
;
}
}
// 自动滚动到底部
// 自动滚动到底部
this
.
$nextTick
(()
=>
{
this
.
$nextTick
(()
=>
{
const
messagesDiv
=
document
.
getElementById
(
'chat-messages'
);
const
messagesDiv
=
document
.
getElementById
(
'chat-messages'
);
...
@@ -219,17 +218,17 @@ require(['jquery', 'vue', 'utils', 'echarts', 'global'], function ($, Vue, utils
...
@@ -219,17 +218,17 @@ require(['jquery', 'vue', 'utils', 'echarts', 'global'], function ($, Vue, utils
}
}
});
});
};
};
this
.
currentEventSource
.
onerror
=
()
=>
{
this
.
currentEventSource
.
onerror
=
()
=>
{
console
.
error
(
'SSE连接异常'
);
console
.
error
(
'SSE连接异常'
);
// 移除输入指示器,显示错误信息
// 移除输入指示器,显示错误信息
this
.
messages
[
aiMessageIndex
].
typing
=
false
;
this
.
messages
[
aiMessageIndex
].
typing
=
false
;
this
.
messages
[
aiMessageIndex
].
content
=
responseText
||
'抱歉,连接出现问题,请稍后再试。'
;
this
.
messages
[
aiMessageIndex
].
content
=
responseText
||
'抱歉,连接出现问题,请稍后再试。'
;
// 切换回发送按钮
// 切换回发送按钮
this
.
isResponding
=
false
;
this
.
isResponding
=
false
;
// 关闭事件源
// 关闭事件源
this
.
currentEventSource
.
close
();
this
.
currentEventSource
.
close
();
this
.
currentEventSource
=
null
;
this
.
currentEventSource
=
null
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment