Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
Internet-hospital
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
yuguo
Internet-hospital
Commits
626473e4
Commit
626473e4
authored
Mar 02, 2026
by
yuguo
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix
parent
ef9bb5d9
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
471 additions
and
159 deletions
+471
-159
server/internal/agent/handler.go
server/internal/agent/handler.go
+94
-1
server/internal/service/admin/agent_handler.go
server/internal/service/admin/agent_handler.go
+87
-0
server/internal/service/admin/handler.go
server/internal/service/admin/handler.go
+6
-0
server/internal/service/admin/workflow_handler.go
server/internal/service/admin/workflow_handler.go
+65
-0
server/internal/service/consult/service.go
server/internal/service/consult/service.go
+30
-84
web/src/api/agent.ts
web/src/api/agent.ts
+163
-0
web/src/app/(main)/admin/agents/page.tsx
web/src/app/(main)/admin/agents/page.tsx
+4
-18
web/src/app/(main)/admin/knowledge/page.tsx
web/src/app/(main)/admin/knowledge/page.tsx
+9
-16
web/src/app/(main)/admin/tools/page.tsx
web/src/app/(main)/admin/tools/page.tsx
+3
-8
web/src/app/(main)/admin/workflows/page.tsx
web/src/app/(main)/admin/workflows/page.tsx
+10
-32
升级方案_智能体平台融合.md
升级方案_智能体平台融合.md
+0
-0
No files found.
server/internal/agent/handler.go
View file @
626473e4
package
internalagent
import
(
"encoding/json"
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"internet-hospital/internal/model"
"internet-hospital/pkg/agent"
"internet-hospital/pkg/database"
)
// Handler Agent HTTP处理器
...
...
@@ -21,6 +27,7 @@ func (h *Handler) RegisterRoutes(r gin.IRouter) {
g
.
GET
(
"/sessions"
,
h
.
ListSessions
)
g
.
DELETE
(
"/session/:session_id"
,
h
.
DeleteSession
)
g
.
GET
(
"/list"
,
h
.
ListAgents
)
g
.
GET
(
"/tools"
,
h
.
ListTools
)
}
func
(
h
*
Handler
)
Chat
(
c
*
gin
.
Context
)
{
...
...
@@ -54,10 +61,96 @@ func (h *Handler) ListAgents(c *gin.Context) {
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"data"
:
h
.
svc
.
ListAgents
()})
}
// ListSessions 获取用户的 Agent 会话列表
func
(
h
*
Handler
)
ListSessions
(
c
*
gin
.
Context
)
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"data"
:
[]
interface
{}{}})
userID
,
_
:=
c
.
Get
(
"user_id"
)
agentID
:=
c
.
Query
(
"agent_id"
)
var
sessions
[]
model
.
AgentSession
query
:=
database
.
GetDB
()
.
Where
(
"user_id = ?"
,
userID
)
.
Order
(
"updated_at DESC"
)
if
agentID
!=
""
{
query
=
query
.
Where
(
"agent_id = ?"
,
agentID
)
}
query
.
Find
(
&
sessions
)
type
SessionSummary
struct
{
model
.
AgentSession
LastMessage
string
`json:"last_message"`
}
result
:=
make
([]
SessionSummary
,
0
,
len
(
sessions
))
for
_
,
s
:=
range
sessions
{
var
history
[]
map
[
string
]
string
json
.
Unmarshal
([]
byte
(
s
.
History
),
&
history
)
lastMsg
:=
""
if
len
(
history
)
>
0
{
lastMsg
=
history
[
len
(
history
)
-
1
][
"content"
]
if
len
(
lastMsg
)
>
60
{
lastMsg
=
lastMsg
[
:
60
]
+
"..."
}
}
result
=
append
(
result
,
SessionSummary
{
s
,
lastMsg
})
}
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"data"
:
result
})
}
// DeleteSession 删除会话
func
(
h
*
Handler
)
DeleteSession
(
c
*
gin
.
Context
)
{
userID
,
_
:=
c
.
Get
(
"user_id"
)
sessionID
:=
c
.
Param
(
"session_id"
)
database
.
GetDB
()
.
Where
(
"session_id = ? AND user_id = ?"
,
sessionID
,
userID
)
.
Delete
(
&
model
.
AgentSession
{})
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"message"
:
"ok"
})
}
// ListTools 获取所有已注册工具列表
func
(
h
*
Handler
)
ListTools
(
c
*
gin
.
Context
)
{
registry
:=
agent
.
GetRegistry
()
allTools
:=
registry
.
All
()
type
ToolInfo
struct
{
ID
string
`json:"id"`
Name
string
`json:"name"`
Description
string
`json:"description"`
Category
string
`json:"category"`
Parameters
map
[
string
]
interface
{}
`json:"parameters"`
IsEnabled
bool
`json:"is_enabled"`
CreatedAt
string
`json:"created_at"`
}
categoryMap
:=
map
[
string
]
string
{
"query_symptom_knowledge"
:
"knowledge"
,
"recommend_department"
:
"recommendation"
,
"query_medical_record"
:
"medical"
,
"search_medical_knowledge"
:
"knowledge"
,
"query_drug"
:
"pharmacy"
,
"check_drug_interaction"
:
"safety"
,
"check_contraindication"
:
"safety"
,
"calculate_dosage"
:
"pharmacy"
,
"generate_follow_up_plan"
:
"follow_up"
,
"send_notification"
:
"notification"
,
}
result
:=
make
([]
ToolInfo
,
0
,
len
(
allTools
))
i
:=
1
for
name
,
tool
:=
range
allTools
{
params
:=
make
(
map
[
string
]
interface
{})
for
_
,
p
:=
range
tool
.
Parameters
()
{
params
[
p
.
Name
]
=
p
.
Type
}
category
:=
categoryMap
[
name
]
if
category
==
""
{
category
=
"other"
}
result
=
append
(
result
,
ToolInfo
{
ID
:
fmt
.
Sprintf
(
"%d"
,
i
),
Name
:
name
,
Description
:
tool
.
Description
(),
Category
:
category
,
Parameters
:
params
,
IsEnabled
:
true
,
CreatedAt
:
"2026-01-01"
,
})
i
++
}
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"data"
:
result
})
}
server/internal/service/admin/agent_handler.go
0 → 100644
View file @
626473e4
package
admin
import
(
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"internet-hospital/internal/model"
"internet-hospital/pkg/database"
)
// GetAgentExecutionLogs 获取 Agent 执行日志(分页)
func
(
h
*
Handler
)
GetAgentExecutionLogs
(
c
*
gin
.
Context
)
{
agentID
:=
c
.
Query
(
"agent_id"
)
start
:=
c
.
Query
(
"start"
)
end
:=
c
.
Query
(
"end"
)
page
:=
1
pageSize
:=
20
if
p
:=
c
.
Query
(
"page"
);
p
!=
""
{
if
v
,
err
:=
strconv
.
Atoi
(
p
);
err
==
nil
&&
v
>
0
{
page
=
v
}
}
if
ps
:=
c
.
Query
(
"page_size"
);
ps
!=
""
{
if
v
,
err
:=
strconv
.
Atoi
(
ps
);
err
==
nil
&&
v
>
0
&&
v
<=
100
{
pageSize
=
v
}
}
query
:=
database
.
GetDB
()
.
Model
(
&
model
.
AgentExecutionLog
{})
if
agentID
!=
""
{
query
=
query
.
Where
(
"agent_id = ?"
,
agentID
)
}
if
start
!=
""
{
query
=
query
.
Where
(
"created_at >= ?"
,
start
)
}
if
end
!=
""
{
query
=
query
.
Where
(
"created_at <= ?"
,
end
)
}
var
total
int64
query
.
Count
(
&
total
)
var
logs
[]
model
.
AgentExecutionLog
query
.
Order
(
"created_at DESC"
)
.
Offset
((
page
-
1
)
*
pageSize
)
.
Limit
(
pageSize
)
.
Find
(
&
logs
)
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"data"
:
gin
.
H
{
"list"
:
logs
,
"total"
:
total
,
"page"
:
page
,
"page_size"
:
pageSize
,
}})
}
// GetAgentStats 获取 Agent 执行统计
func
(
h
*
Handler
)
GetAgentStats
(
c
*
gin
.
Context
)
{
start
:=
c
.
Query
(
"start"
)
end
:=
c
.
Query
(
"end"
)
type
AgentStat
struct
{
AgentID
string
`json:"agent_id"`
Count
int64
`json:"count"`
AvgIterations
float64
`json:"avg_iterations"`
AvgTokens
float64
`json:"avg_tokens"`
SuccessRate
float64
`json:"success_rate"`
}
db
:=
database
.
GetDB
()
query
:=
db
.
Model
(
&
model
.
AgentExecutionLog
{})
if
start
!=
""
{
query
=
query
.
Where
(
"created_at >= ?"
,
start
)
}
if
end
!=
""
{
query
=
query
.
Where
(
"created_at <= ?"
,
end
)
}
var
stats
[]
AgentStat
query
.
Select
(
"agent_id, COUNT(*) as count, AVG(iterations) as avg_iterations, AVG(total_tokens) as avg_tokens, SUM(CASE WHEN success THEN 1 ELSE 0 END)::float / COUNT(*) as success_rate"
)
.
Group
(
"agent_id"
)
.
Scan
(
&
stats
)
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"data"
:
stats
})
}
server/internal/service/admin/handler.go
View file @
626473e4
...
...
@@ -102,7 +102,13 @@ func (h *Handler) RegisterRoutes(r *gin.RouterGroup) {
// 工作流管理
adm
.
GET
(
"/workflows"
,
h
.
ListWorkflows
)
adm
.
POST
(
"/workflows"
,
h
.
CreateWorkflow
)
adm
.
PUT
(
"/workflows/:id"
,
h
.
UpdateWorkflow
)
adm
.
PUT
(
"/workflows/:id/publish"
,
h
.
PublishWorkflow
)
adm
.
GET
(
"/workflow/executions"
,
h
.
ListWorkflowExecutions
)
// Agent 执行监控
adm
.
GET
(
"/agent/logs"
,
h
.
GetAgentExecutionLogs
)
adm
.
GET
(
"/agent/stats"
,
h
.
GetAgentStats
)
}
}
...
...
server/internal/service/admin/workflow_handler.go
View file @
626473e4
...
...
@@ -2,6 +2,7 @@ package admin
import
(
"net/http"
"strconv"
"github.com/gin-gonic/gin"
...
...
@@ -42,6 +43,33 @@ func (h *Handler) CreateWorkflow(c *gin.Context) {
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"data"
:
wf
})
}
// UpdateWorkflow 更新工作流(名称/描述/定义)
func
(
h
*
Handler
)
UpdateWorkflow
(
c
*
gin
.
Context
)
{
var
req
struct
{
Name
string
`json:"name"`
Description
string
`json:"description"`
Definition
string
`json:"definition"`
}
if
err
:=
c
.
ShouldBindJSON
(
&
req
);
err
!=
nil
{
c
.
JSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"error"
:
err
.
Error
()})
return
}
updates
:=
map
[
string
]
interface
{}{}
if
req
.
Definition
!=
""
{
updates
[
"definition"
]
=
req
.
Definition
}
if
req
.
Name
!=
""
{
updates
[
"name"
]
=
req
.
Name
}
if
req
.
Description
!=
""
{
updates
[
"description"
]
=
req
.
Description
}
database
.
GetDB
()
.
Model
(
&
model
.
WorkflowDefinition
{})
.
Where
(
"id = ?"
,
c
.
Param
(
"id"
))
.
Updates
(
updates
)
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"message"
:
"ok"
})
}
// PublishWorkflow 发布工作流
func
(
h
*
Handler
)
PublishWorkflow
(
c
*
gin
.
Context
)
{
database
.
GetDB
()
.
Model
(
&
model
.
WorkflowDefinition
{})
.
...
...
@@ -49,3 +77,40 @@ func (h *Handler) PublishWorkflow(c *gin.Context) {
Update
(
"status"
,
"active"
)
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"message"
:
"ok"
})
}
// ListWorkflowExecutions 工作流执行记录列表
func
(
h
*
Handler
)
ListWorkflowExecutions
(
c
*
gin
.
Context
)
{
workflowID
:=
c
.
Query
(
"workflow_id"
)
page
:=
1
pageSize
:=
20
if
p
:=
c
.
Query
(
"page"
);
p
!=
""
{
if
v
,
err
:=
strconv
.
Atoi
(
p
);
err
==
nil
&&
v
>
0
{
page
=
v
}
}
if
ps
:=
c
.
Query
(
"page_size"
);
ps
!=
""
{
if
v
,
err
:=
strconv
.
Atoi
(
ps
);
err
==
nil
&&
v
>
0
&&
v
<=
100
{
pageSize
=
v
}
}
var
total
int64
query
:=
database
.
GetDB
()
.
Model
(
&
model
.
WorkflowExecution
{})
if
workflowID
!=
""
{
query
=
query
.
Where
(
"workflow_id = ?"
,
workflowID
)
}
query
.
Count
(
&
total
)
var
executions
[]
model
.
WorkflowExecution
query
.
Order
(
"created_at DESC"
)
.
Offset
((
page
-
1
)
*
pageSize
)
.
Limit
(
pageSize
)
.
Find
(
&
executions
)
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"data"
:
gin
.
H
{
"list"
:
executions
,
"total"
:
total
,
"page"
:
page
,
"page_size"
:
pageSize
,
}})
}
server/internal/service/consult/service.go
View file @
626473e4
...
...
@@ -10,8 +10,8 @@ import (
"github.com/redis/go-redis/v9"
"gorm.io/gorm"
internalagent
"internet-hospital/internal/agent"
"internet-hospital/internal/model"
"internet-hospital/pkg/ai"
"internet-hospital/pkg/database"
)
...
...
@@ -196,107 +196,53 @@ func (s *Service) CancelConsult(ctx context.Context, consultID string) error {
return
s
.
db
.
Model
(
&
model
.
Consultation
{})
.
Where
(
"id = ?"
,
consultID
)
.
Update
(
"status"
,
"cancelled"
)
.
Error
}
// AIAssist AI辅助分析(鉴别诊断/用药建议)
// AIAssist AI辅助分析(鉴别诊断/用药建议)
—— 通过 Agent 调用
func
(
s
*
Service
)
AIAssist
(
ctx
context
.
Context
,
consultID
string
,
scene
string
)
(
map
[
string
]
interface
{},
error
)
{
// 获取问诊信息
var
consult
model
.
Consultation
if
err
:=
s
.
db
.
Where
(
"id = ?"
,
consultID
)
.
First
(
&
consult
)
.
Error
;
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"问诊不存在"
)
}
// 获取对话消息
var
messages
[]
model
.
ConsultMessage
s
.
db
.
Where
(
"consult_id = ?"
,
consultID
)
.
Order
(
"created_at ASC"
)
.
Find
(
&
messages
)
// 获取预问诊信息
// 获取预问诊信息以提供上下文
var
preConsult
model
.
PreConsultation
s
.
db
.
Where
(
"consultation_id = ?"
,
consultID
)
.
First
(
&
preConsult
)
// 构建对话上下文
var
chatContext
string
agentCtx
:=
map
[
string
]
interface
{}{
"patient_id"
:
consult
.
PatientID
,
"consult_id"
:
consultID
,
"chief_complaint"
:
consult
.
ChiefComplaint
,
}
if
preConsult
.
AIAnalysis
!=
""
{
chatContext
+=
"【预问诊AI分析报告】
\n
"
+
preConsult
.
AIAnalysis
+
"
\n\n
"
}
if
consult
.
ChiefComplaint
!=
""
{
chatContext
+=
"【主诉】"
+
consult
.
ChiefComplaint
+
"
\n\n
"
}
chatContext
+=
"【问诊对话记录】
\n
"
for
_
,
msg
:=
range
messages
{
role
:=
"患者"
if
msg
.
SenderType
==
"doctor"
{
role
=
"医生"
}
else
if
msg
.
SenderType
==
"system"
{
role
=
"系统"
}
chatContext
+=
role
+
":"
+
msg
.
Content
+
"
\n
"
agentCtx
[
"pre_consult_analysis"
]
=
preConsult
.
AIAnalysis
}
// 获取场景对应的Prompt模板
prompt
:=
ai
.
GetActivePromptByScene
(
scene
)
if
prompt
==
""
{
switch
scene
{
case
"consult_diagnosis"
:
prompt
=
`你是一位资深的临床医学专家,请根据以下问诊信息进行鉴别诊断分析。
请以如下markdown格式输出:
## 初步诊断
(最可能的诊断,附简要理由)
## 鉴别诊断
1. **疾病名称1** - 可能性:高/中/低,依据:...
2. **疾病名称2** - 可能性:高/中/低,依据:...
3. **疾病名称3** - 可能性:高/中/低,依据:...
## 建议检查
1. 检查项目1 - 目的:...
2. 检查项目2 - 目的:...
## 注意事项
(需要特别关注的情况)`
case
"consult_medication"
:
prompt
=
`你是一位资深的临床药学专家,请根据以下问诊信息给出用药建议。
请以如下markdown格式输出:
## 推荐用药方案
1. **药品名称1** - 规格:...,用法用量:...,疗程:...
2. **药品名称2** - 规格:...,用法用量:...,疗程:...
## 用药注意事项
1. 注意事项1
2. 注意事项2
## 禁忌与过敏提示
(相关药物禁忌和需要询问的过敏史)
## 随访建议
(用药后的观察要点和复诊建议)`
default
:
return
nil
,
fmt
.
Errorf
(
"不支持的AI场景: %s"
,
scene
)
}
var
agentID
,
message
string
switch
scene
{
case
"consult_diagnosis"
:
agentID
=
"diagnosis_agent"
message
=
"请对患者当前情况进行诊断分析,提供鉴别诊断建议"
case
"consult_medication"
:
agentID
=
"prescription_agent"
message
=
"请根据患者情况给出用药建议,包括推荐药物、用法用量和注意事项"
default
:
return
nil
,
fmt
.
Errorf
(
"不支持的AI场景: %s"
,
scene
)
}
// 调用AI(使用统一接口,自动记录日志)
aiMessages
:=
[]
ai
.
ChatMessage
{
{
Role
:
"system"
,
Content
:
prompt
},
{
Role
:
"user"
,
Content
:
chatContext
},
agentSvc
:=
internalagent
.
GetService
()
output
,
err
:=
agentSvc
.
Chat
(
ctx
,
agentID
,
consult
.
DoctorID
,
""
,
message
,
agentCtx
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"AI分析失败: %w"
,
err
)
}
result
:=
ai
.
Call
(
ctx
,
ai
.
CallParams
{
Scene
:
scene
,
UserID
:
consult
.
DoctorID
,
Messages
:
aiMessages
,
RequestSummary
:
chatContext
,
})
if
result
.
Error
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"AI分析失败: %w"
,
result
.
Error
)
if
output
==
nil
{
return
nil
,
fmt
.
Errorf
(
"agent不存在: %s"
,
agentID
)
}
return
map
[
string
]
interface
{}{
"scene"
:
scene
,
"content"
:
result
.
Content
,
"scene"
:
scene
,
"response"
:
output
.
Response
,
"tool_calls"
:
output
.
ToolCalls
,
"iterations"
:
output
.
Iterations
,
"total_tokens"
:
output
.
TotalTokens
,
},
nil
}
...
...
web/src/api/agent.ts
0 → 100644
View file @
626473e4
import
{
get
,
post
,
put
,
del
}
from
'
./request
'
;
// ==================== 类型定义 ====================
export
interface
ToolCall
{
tool_name
:
string
;
call_id
:
string
;
arguments
:
string
;
result
:
{
success
:
boolean
;
data
?:
unknown
;
error
?:
string
};
success
:
boolean
;
}
export
interface
AgentOutput
{
response
:
string
;
session_id
?:
string
;
tool_calls
?:
ToolCall
[];
iterations
?:
number
;
total_tokens
?:
number
;
finish_reason
?:
string
;
}
export
interface
AgentSession
{
id
:
number
;
session_id
:
string
;
agent_id
:
string
;
user_id
:
string
;
history
:
string
;
context
:
string
;
status
:
string
;
last_message
?:
string
;
created_at
:
string
;
updated_at
:
string
;
}
export
interface
AgentExecutionLog
{
id
:
number
;
session_id
:
string
;
agent_id
:
string
;
user_id
:
string
;
input
:
string
;
output
:
string
;
tool_calls
:
string
;
iterations
:
number
;
total_tokens
:
number
;
duration_ms
:
number
;
finish_reason
:
string
;
success
:
boolean
;
error_message
:
string
;
created_at
:
string
;
}
export
interface
WorkflowExecution
{
id
:
number
;
execution_id
:
string
;
workflow_id
:
string
;
trigger_type
:
string
;
trigger_by
:
string
;
input
:
string
;
output
:
string
;
status
:
string
;
started_at
:
string
;
completed_at
:
string
;
}
export
interface
WorkflowCreateParams
{
workflow_id
:
string
;
name
:
string
;
description
?:
string
;
category
?:
string
;
definition
?:
string
;
}
export
interface
KnowledgeCollectionParams
{
name
:
string
;
description
?:
string
;
category
?:
string
;
}
export
interface
KnowledgeDocumentParams
{
collection_id
:
string
;
title
:
string
;
content
:
string
;
}
// ==================== Agent API ====================
export
const
agentApi
=
{
chat
:
(
agentId
:
string
,
params
:
{
session_id
?:
string
;
message
:
string
;
context
?:
Record
<
string
,
unknown
>
;
})
=>
post
<
AgentOutput
>
(
`/agent/
${
agentId
}
/chat`
,
params
),
listAgents
:
()
=>
get
<
{
id
:
string
;
name
:
string
;
description
:
string
}[]
>
(
'
/agent/list
'
),
listTools
:
()
=>
get
<
{
id
:
string
;
name
:
string
;
description
:
string
;
category
:
string
;
parameters
:
Record
<
string
,
unknown
>
;
is_enabled
:
boolean
;
created_at
:
string
}[]
>
(
'
/agent/tools
'
),
getSessions
:
(
agentId
?:
string
)
=>
get
<
AgentSession
[]
>
(
'
/agent/sessions
'
,
{
params
:
agentId
?
{
agent_id
:
agentId
}
:
{}
}),
deleteSession
:
(
sessionId
:
string
)
=>
del
<
null
>
(
`/agent/session/
${
sessionId
}
`
),
getExecutionLogs
:
(
params
:
{
agent_id
?:
string
;
start
?:
string
;
end
?:
string
;
page
?:
number
;
page_size
?:
number
;
})
=>
get
<
{
list
:
AgentExecutionLog
[];
total
:
number
}
>
(
'
/admin/agent/logs
'
,
{
params
}),
getStats
:
(
params
?:
{
start
?:
string
;
end
?:
string
})
=>
get
<
{
agent_id
:
string
;
count
:
number
;
avg_iterations
:
number
;
avg_tokens
:
number
;
success_rate
:
number
}[]
>
(
'
/admin/agent/stats
'
,
{
params
}
),
};
// ==================== Workflow API ====================
export
const
workflowApi
=
{
list
:
()
=>
get
<
unknown
[]
>
(
'
/admin/workflows
'
),
create
:
(
data
:
WorkflowCreateParams
)
=>
post
<
unknown
>
(
'
/admin/workflows
'
,
data
),
update
:
(
id
:
number
,
data
:
Partial
<
WorkflowCreateParams
>
)
=>
put
<
unknown
>
(
`/admin/workflows/
${
id
}
`
,
data
),
publish
:
(
id
:
number
)
=>
post
<
null
>
(
`/admin/workflows/
${
id
}
/publish`
),
execute
:
(
workflowId
:
string
,
input
?:
Record
<
string
,
unknown
>
)
=>
post
<
{
execution_id
:
string
}
>
(
`/workflow/
${
workflowId
}
/execute`
,
input
||
{}),
getExecution
:
(
executionId
:
string
)
=>
get
<
WorkflowExecution
>
(
`/workflow/execution/
${
executionId
}
`
),
listExecutions
:
(
params
?:
{
workflow_id
?:
string
;
page
?:
number
;
page_size
?:
number
})
=>
get
<
{
list
:
WorkflowExecution
[];
total
:
number
}
>
(
'
/admin/workflow/executions
'
,
{
params
}),
getTasks
:
()
=>
get
<
unknown
[]
>
(
'
/workflow/tasks
'
),
completeTask
:
(
taskId
:
string
,
result
:
Record
<
string
,
unknown
>
)
=>
post
<
null
>
(
`/workflow/task/
${
taskId
}
/complete`
,
result
),
};
// ==================== Knowledge API ====================
export
const
knowledgeApi
=
{
listCollections
:
()
=>
get
<
unknown
[]
>
(
'
/knowledge/collections
'
),
createCollection
:
(
data
:
KnowledgeCollectionParams
)
=>
post
<
unknown
>
(
'
/knowledge/collections
'
,
data
),
listDocuments
:
(
collectionId
?:
string
)
=>
get
<
unknown
[]
>
(
'
/knowledge/documents
'
,
{
params
:
collectionId
?
{
collection_id
:
collectionId
}
:
{}
}),
createDocument
:
(
data
:
KnowledgeDocumentParams
)
=>
post
<
unknown
>
(
'
/knowledge/documents
'
,
data
),
search
:
(
query
:
string
,
topK
=
5
,
collectionId
?:
string
)
=>
post
<
unknown
[]
>
(
'
/knowledge/search
'
,
{
query
,
top_k
:
topK
,
collection_id
:
collectionId
}),
};
web/src/app/(main)/admin/agents/page.tsx
View file @
626473e4
...
...
@@ -3,10 +3,10 @@
import
{
useState
}
from
'
react
'
;
import
{
Card
,
Table
,
Tag
,
Button
,
Modal
,
Input
,
message
,
Space
,
Collapse
,
Timeline
,
Typography
}
from
'
antd
'
;
import
{
RobotOutlined
,
PlayCircleOutlined
,
ToolOutlined
,
CheckCircleOutlined
,
CloseCircleOutlined
}
from
'
@ant-design/icons
'
;
import
{
useUserStore
}
from
'
@/store/userStore
'
;
import
{
agentApi
}
from
'
@/api/agent
'
;
import
type
{
ToolCall
}
from
'
@/api/agent
'
;
const
{
Text
}
=
Typography
;
const
API
=
''
;
const
BUILTIN_AGENTS
=
[
{
id
:
'
pre_consult_agent
'
,
name
:
'
预问诊智能助手
'
,
description
:
'
通过多轮对话收集患者症状,生成预问诊报告
'
,
category
:
'
pre_consult
'
,
tools
:
[
'
query_symptom_knowledge
'
,
'
recommend_department
'
],
max_iterations
:
5
},
...
...
@@ -29,14 +29,6 @@ const categoryLabel: Record<string, string> = {
follow_up
:
'
随访管理
'
,
};
interface
ToolCall
{
tool_name
:
string
;
call_id
:
string
;
arguments
:
string
;
result
:
{
success
:
boolean
;
data
?:
unknown
;
error
?:
string
};
success
:
boolean
;
}
interface
AgentResponse
{
response
:
string
;
tool_calls
?:
ToolCall
[];
...
...
@@ -46,7 +38,6 @@ interface AgentResponse {
}
export
default
function
AgentsPage
()
{
const
{
accessToken
:
token
}
=
useUserStore
();
const
[
testModal
,
setTestModal
]
=
useState
<
{
open
:
boolean
;
agentId
:
string
;
agentName
:
string
}
>
({
open
:
false
,
agentId
:
''
,
agentName
:
''
});
const
[
testMessages
,
setTestMessages
]
=
useState
<
{
role
:
string
;
content
:
string
;
toolCalls
?:
ToolCall
[];
meta
?:
{
iterations
?:
number
;
tokens
?:
number
}
}[]
>
([]);
const
[
inputMsg
,
setInputMsg
]
=
useState
(
''
);
...
...
@@ -66,13 +57,8 @@ export default function AgentsPage() {
setTestMessages
(
prev
=>
[...
prev
,
{
role
:
'
user
'
,
content
:
userMsg
}]);
setLoading
(
true
);
try
{
const
res
=
await
fetch
(
`
${
API
}
/api/v1/agent/
${
testModal
.
agentId
}
/chat`
,
{
method
:
'
POST
'
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
,
Authorization
:
`Bearer
${
token
}
`
},
body
:
JSON
.
stringify
({
session_id
:
sessionId
,
message
:
userMsg
}),
});
const
data
=
await
res
.
json
();
const
agentData
=
data
.
data
as
AgentResponse
;
const
res
=
await
agentApi
.
chat
(
testModal
.
agentId
,
{
session_id
:
sessionId
,
message
:
userMsg
});
const
agentData
=
res
.
data
as
AgentResponse
;
const
reply
=
agentData
?.
response
||
'
无响应
'
;
setTestMessages
(
prev
=>
[...
prev
,
{
role
:
'
assistant
'
,
...
...
web/src/app/(main)/admin/knowledge/page.tsx
View file @
626473e4
...
...
@@ -3,10 +3,9 @@
import
{
useEffect
,
useState
}
from
'
react
'
;
import
{
Card
,
Table
,
Tag
,
Button
,
Modal
,
Form
,
Input
,
Select
,
message
,
Space
,
Tabs
,
Typography
}
from
'
antd
'
;
import
{
BookOutlined
,
PlusOutlined
,
SearchOutlined
,
FileTextOutlined
,
ReloadOutlined
}
from
'
@ant-design/icons
'
;
import
{
useUserStore
}
from
'
@/store/userStore
'
;
import
{
knowledgeApi
}
from
'
@/api/agent
'
;
const
{
Text
}
=
Typography
;
const
API
=
''
;
const
categoryLabel
:
Record
<
string
,
string
>
=
{
clinical_guideline
:
'
临床指南
'
,
drug
:
'
药品说明
'
,
disease
:
'
疾病百科
'
,
paper
:
'
医学论文
'
,
...
...
@@ -16,7 +15,6 @@ const categoryColor: Record<string, string> = {
};
export
default
function
KnowledgePage
()
{
const
{
accessToken
:
token
}
=
useUserStore
();
const
[
collections
,
setCollections
]
=
useState
<
any
[]
>
([]);
const
[
documents
,
setDocuments
]
=
useState
<
any
[]
>
([]);
const
[
colLoading
,
setColLoading
]
=
useState
(
false
);
...
...
@@ -30,23 +28,19 @@ export default function KnowledgePage() {
const
[
docForm
]
=
Form
.
useForm
();
const
[
searchForm
]
=
Form
.
useForm
();
const
headers
=
{
Authorization
:
`Bearer
${
token
}
`
,
'
Content-Type
'
:
'
application/json
'
};
const
fetchCollections
=
async
()
=>
{
setColLoading
(
true
);
try
{
const
res
=
await
fetch
(
`
${
API
}
/api/v1/knowledge/collections`
,
{
headers
});
const
data
=
await
res
.
json
();
setCollections
(
data
.
data
||
[]);
const
res
=
await
knowledgeApi
.
listCollections
();
setCollections
((
res
.
data
as
any
[])
||
[]);
}
catch
{}
finally
{
setColLoading
(
false
);
}
};
const
fetchDocuments
=
async
()
=>
{
setDocLoading
(
true
);
try
{
const
res
=
await
fetch
(
`
${
API
}
/api/v1/knowledge/documents`
,
{
headers
});
const
data
=
await
res
.
json
();
setDocuments
(
data
.
data
||
[]);
const
res
=
await
knowledgeApi
.
listDocuments
();
setDocuments
((
res
.
data
as
any
[])
||
[]);
}
catch
{}
finally
{
setDocLoading
(
false
);
}
};
...
...
@@ -54,7 +48,7 @@ export default function KnowledgePage() {
const
createCollection
=
async
(
values
:
any
)
=>
{
try
{
await
fetch
(
`
${
API
}
/api/v1/knowledge/collections`
,
{
method
:
'
POST
'
,
headers
,
body
:
JSON
.
stringify
(
values
)
}
);
await
knowledgeApi
.
createCollection
(
values
);
message
.
success
(
'
集合创建成功
'
);
setColModal
(
false
);
colForm
.
resetFields
();
...
...
@@ -64,7 +58,7 @@ export default function KnowledgePage() {
const
createDocument
=
async
(
values
:
any
)
=>
{
try
{
await
fetch
(
`
${
API
}
/api/v1/knowledge/documents`
,
{
method
:
'
POST
'
,
headers
,
body
:
JSON
.
stringify
(
values
)
}
);
await
knowledgeApi
.
createDocument
(
values
);
message
.
success
(
'
文档已添加
'
);
setDocModal
(
false
);
docForm
.
resetFields
();
...
...
@@ -75,9 +69,8 @@ export default function KnowledgePage() {
const
doSearch
=
async
(
values
:
any
)
=>
{
setSearching
(
true
);
try
{
const
res
=
await
fetch
(
`
${
API
}
/api/v1/knowledge/search`
,
{
method
:
'
POST
'
,
headers
,
body
:
JSON
.
stringify
(
values
)
});
const
data
=
await
res
.
json
();
setSearchResults
(
data
.
data
||
[]);
const
res
=
await
knowledgeApi
.
search
(
values
.
query
,
values
.
top_k
||
5
);
setSearchResults
((
res
.
data
as
any
[])
||
[]);
}
catch
{
message
.
error
(
'
检索失败
'
);
}
finally
{
setSearching
(
false
);
}
};
...
...
web/src/app/(main)/admin/tools/page.tsx
View file @
626473e4
...
...
@@ -6,10 +6,9 @@ import {
ToolOutlined
,
SearchOutlined
,
InfoCircleOutlined
,
ApiOutlined
,
CheckCircleOutlined
,
CodeOutlined
,
ReloadOutlined
,
}
from
'
@ant-design/icons
'
;
import
{
useUserStore
}
from
'
@/store/userStore
'
;
import
{
agentApi
}
from
'
@/api/agent
'
;
const
{
Text
}
=
Typography
;
const
API
=
''
;
interface
AgentTool
{
id
:
string
;
...
...
@@ -52,7 +51,6 @@ const statCards = [
];
export
default
function
ToolsPage
()
{
const
{
accessToken
:
token
}
=
useUserStore
();
const
[
tools
,
setTools
]
=
useState
<
AgentTool
[]
>
(
BUILTIN_TOOLS
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
searchText
,
setSearchText
]
=
useState
(
''
);
...
...
@@ -63,11 +61,8 @@ export default function ToolsPage() {
const
fetchTools
=
async
()
=>
{
setLoading
(
true
);
try
{
const
res
=
await
fetch
(
`
${
API
}
/api/v1/agent/tools`
,
{
headers
:
{
Authorization
:
`Bearer
${
token
}
`
}
});
if
(
res
.
ok
)
{
const
data
=
await
res
.
json
();
if
(
data
.
data
?.
length
>
0
)
setTools
(
data
.
data
);
}
const
res
=
await
agentApi
.
listTools
();
if
(
res
.
data
?.
length
>
0
)
setTools
(
res
.
data
as
AgentTool
[]);
}
catch
{
/* 使用内置工具列表 */
}
finally
{
setLoading
(
false
);
}
...
...
web/src/app/(main)/admin/workflows/page.tsx
View file @
626473e4
...
...
@@ -3,12 +3,10 @@
import
{
useEffect
,
useState
,
useCallback
}
from
'
react
'
;
import
{
Card
,
Table
,
Tag
,
Button
,
Modal
,
Form
,
Input
,
Select
,
message
,
Space
,
Badge
}
from
'
antd
'
;
import
{
DeploymentUnitOutlined
,
PlayCircleOutlined
,
PlusOutlined
,
EditOutlined
}
from
'
@ant-design/icons
'
;
import
{
useUserStore
}
from
'
@/store/userStore
'
;
import
{
workflowApi
}
from
'
@/api/agent
'
;
import
VisualWorkflowEditor
from
'
@/components/workflow/VisualWorkflowEditor
'
;
import
type
{
Node
,
Edge
}
from
'
@xyflow/react
'
;
const
API
=
''
;
interface
Workflow
{
id
:
number
;
workflow_id
:
string
;
...
...
@@ -31,7 +29,6 @@ const categoryLabel: Record<string, string> = {
};
export
default
function
WorkflowsPage
()
{
const
{
accessToken
:
token
}
=
useUserStore
();
const
[
workflows
,
setWorkflows
]
=
useState
<
Workflow
[]
>
([]);
const
[
createModal
,
setCreateModal
]
=
useState
(
false
);
const
[
editorModal
,
setEditorModal
]
=
useState
(
false
);
...
...
@@ -43,9 +40,8 @@ export default function WorkflowsPage() {
const
fetchWorkflows
=
async
()
=>
{
setTableLoading
(
true
);
try
{
const
res
=
await
fetch
(
`
${
API
}
/api/v1/admin/workflows`
,
{
headers
:
{
Authorization
:
`Bearer
${
token
}
`
}
});
const
data
=
await
res
.
json
();
setWorkflows
(
data
.
data
||
[]);
const
res
=
await
workflowApi
.
list
();
setWorkflows
((
res
.
data
as
Workflow
[])
||
[]);
}
catch
{}
finally
{
setTableLoading
(
false
);
}
...
...
@@ -64,11 +60,7 @@ export default function WorkflowsPage() {
},
edges
:
[{
id
:
'
e1
'
,
source_node
:
'
start
'
,
target_node
:
'
end
'
}],
};
await
fetch
(
`
${
API
}
/api/v1/admin/workflows`
,
{
method
:
'
POST
'
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
,
Authorization
:
`Bearer
${
token
}
`
},
body
:
JSON
.
stringify
({
...
values
,
definition
:
JSON
.
stringify
(
definition
)
}),
});
await
workflowApi
.
create
({
...
values
,
definition
:
JSON
.
stringify
(
definition
)
});
message
.
success
(
'
创建成功
'
);
setCreateModal
(
false
);
form
.
resetFields
();
...
...
@@ -83,38 +75,24 @@ export default function WorkflowsPage() {
const
handleSaveWorkflow
=
useCallback
(
async
(
nodes
:
Node
[],
edges
:
Edge
[])
=>
{
if
(
!
editingWorkflow
)
return
;
try
{
await
fetch
(
`
${
API
}
/api/v1/admin/workflows/
${
editingWorkflow
.
id
}
`
,
{
method
:
'
PUT
'
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
,
Authorization
:
`Bearer
${
token
}
`
},
body
:
JSON
.
stringify
({
definition
:
JSON
.
stringify
({
nodes
,
edges
})
}),
});
await
workflowApi
.
update
(
editingWorkflow
.
id
,
{
definition
:
JSON
.
stringify
({
nodes
,
edges
})
});
message
.
success
(
'
工作流已保存
'
);
fetchWorkflows
();
}
catch
{
message
.
error
(
'
保存失败
'
);
}
},
[
editingWorkflow
,
token
]);
},
[
editingWorkflow
]);
const
handleExecuteFromEditor
=
useCallback
(
async
(
nodes
:
Node
[],
edges
:
Edge
[])
=>
{
if
(
!
editingWorkflow
)
return
;
try
{
const
res
=
await
fetch
(
`
${
API
}
/api/v1/workflow/
${
editingWorkflow
.
workflow_id
}
/execute`
,
{
method
:
'
POST
'
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
,
Authorization
:
`Bearer
${
token
}
`
},
body
:
JSON
.
stringify
({
workflow_data
:
{
nodes
,
edges
}
}),
});
const
result
=
await
res
.
json
();
const
result
=
await
workflowApi
.
execute
(
editingWorkflow
.
workflow_id
,
{
workflow_data
:
{
nodes
,
edges
}
});
message
.
success
(
`执行已启动:
${
result
.
data
?.
execution_id
}
`);
} catch { message.error('执行失败'); }
}, [editingWorkflow
, token
]);
}, [editingWorkflow]);
const handleExecute = async (workflowId: string) => {
try {
const res = await fetch(`
$
{
API
}
/api/
v1
/
workflow
/
$
{
workflowId
}
/execute`,
{
method
:
'
POST
'
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
,
Authorization
:
`Bearer
${
token
}
`
}
,
body: JSON.stringify({}),
});
const data = await res.json();
message.success(`
执行已启动
:
$
{
data
.
data
?.
execution_id
}
`);
const result = await workflowApi.execute(workflowId);
message.success(`
执行已启动
:
$
{
result
.
data
?.
execution_id
}
`);
} catch { message.error('执行失败'); }
};
...
...
升级方案_智能体平台融合.md
0 → 100644
View file @
626473e4
This diff is collapsed.
Click to expand it.
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