Skip to content

Commit a3dd967

Browse files
authored
feat: 对话增加历史记录 (#485)
1 parent 5a49716 commit a3dd967

File tree

31 files changed

+1121
-569
lines changed

31 files changed

+1121
-569
lines changed

apps/application/serializers/chat_serializers.py

+25-2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ def delete(self, with_valid=True):
5656
QuerySet(Chat).filter(id=self.data.get('chat_id'), application_id=self.data.get('application_id')).delete()
5757
return True
5858

59+
class ClientChatHistory(serializers.Serializer):
60+
application_id = serializers.UUIDField(required=True, error_messages=ErrMessage.uuid("应用id"))
61+
client_id = serializers.UUIDField(required=True, error_messages=ErrMessage.uuid("客户端id"))
62+
63+
def page(self, current_page: int, page_size: int, with_valid=True):
64+
if with_valid:
65+
self.is_valid(raise_exception=True)
66+
queryset = QuerySet(Chat).filter(client_id=self.data.get('client_id'),
67+
application_id=self.data.get('application_id'))
68+
queryset = queryset.order_by('-create_time')
69+
return page_search(current_page, page_size, queryset, lambda row: ChatSerializerModel(row).data)
70+
5971
class Query(serializers.Serializer):
6072
abstract = serializers.CharField(required=False, error_messages=ErrMessage.char("摘要"))
6173
history_day = serializers.IntegerField(required=True, error_messages=ErrMessage.integer("历史天数"))
@@ -282,6 +294,12 @@ class Meta:
282294
'create_time', 'update_time']
283295

284296

297+
class ChatSerializerModel(serializers.ModelSerializer):
298+
class Meta:
299+
model = Chat
300+
fields = ['id', 'application_id', 'abstract', 'client_id']
301+
302+
285303
class ChatRecordSerializer(serializers.Serializer):
286304
class Operate(serializers.Serializer):
287305
chat_id = serializers.UUIDField(required=True, error_messages=ErrMessage.uuid("对话id"))
@@ -319,13 +337,16 @@ def one(self, current_role: RoleConstants, with_valid=True):
319337
class Query(serializers.Serializer):
320338
application_id = serializers.UUIDField(required=True)
321339
chat_id = serializers.UUIDField(required=True)
340+
order_asc = serializers.BooleanField(required=False)
322341

323342
def list(self, with_valid=True):
324343
if with_valid:
325344
self.is_valid(raise_exception=True)
326345
QuerySet(ChatRecord).filter(chat_id=self.data.get('chat_id'))
346+
order_by = 'create_time' if self.data.get('order_asc') is None or self.data.get(
347+
'order_asc') else '-create_time'
327348
return [ChatRecordSerializerModel(chat_record).data for chat_record in
328-
QuerySet(ChatRecord).filter(chat_id=self.data.get('chat_id')).order_by("create_time")]
349+
QuerySet(ChatRecord).filter(chat_id=self.data.get('chat_id')).order_by(order_by)]
329350

330351
@staticmethod
331352
def reset_chat_record(chat_record):
@@ -354,8 +375,10 @@ def reset_chat_record(chat_record):
354375
def page(self, current_page: int, page_size: int, with_valid=True):
355376
if with_valid:
356377
self.is_valid(raise_exception=True)
378+
order_by = 'create_time' if self.data.get('order_asc') is None or self.data.get(
379+
'order_asc') else '-create_time'
357380
page = page_search(current_page, page_size,
358-
QuerySet(ChatRecord).filter(chat_id=self.data.get('chat_id')).order_by("create_time"),
381+
QuerySet(ChatRecord).filter(chat_id=self.data.get('chat_id')).order_by(order_by),
359382
post_records_handler=lambda chat_record: self.reset_chat_record(chat_record))
360383
return page
361384

apps/application/swagger_api/chat_api.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@
1212
from common.mixins.api_mixin import ApiMixin
1313

1414

15+
class ChatClientHistoryApi(ApiMixin):
16+
@staticmethod
17+
def get_request_params_api():
18+
return [openapi.Parameter(name='application_id',
19+
in_=openapi.IN_PATH,
20+
type=openapi.TYPE_STRING,
21+
required=True,
22+
description='应用id')
23+
]
24+
25+
1526
class ChatApi(ApiMixin):
1627
@staticmethod
1728
def get_request_body_api():
@@ -80,7 +91,7 @@ def get_request_body_api():
8091
'problem_optimization'],
8192
properties={
8293
'id': openapi.Schema(type=openapi.TYPE_STRING, title="应用id",
83-
description="应用id,修改的时候传,创建的时候不传"),
94+
description="应用id,修改的时候传,创建的时候不传"),
8495
'model_id': openapi.Schema(type=openapi.TYPE_STRING, title="模型id", description="模型id"),
8596
'dataset_id_list': openapi.Schema(type=openapi.TYPE_ARRAY,
8697
items=openapi.Schema(type=openapi.TYPE_STRING),

apps/application/template/embed.js

+14-10
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,17 @@ const chatButtonHtml=
5353

5454
const getChatContainerHtml=(protocol,host,token)=>{
5555
return `<div id="maxkb-chat-container">
56-
<iframe id="maxkb-chat" src=${protocol}://${host}/ui/chat/${token}></iframe>
57-
<div class="maxkb-operate"><div class="maxkb-closeviewport maxkb-viewportnone"><svg style="vertical-align: middle;overflow: hidden;" t="1710214539671" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="rgb(100, 106, 115)" width="16" height="16"><path d="M85.333333 384c25.6 0 42.666667-17.066667 42.666667-42.666667V128h213.333333c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666666H85.333333c-25.6 0-42.666667 17.066667-42.666666 42.666666v256c0 25.6 17.066667 42.666667 42.666666 42.666667zM938.666667 640c-25.6 0-42.666667 17.066667-42.666667 42.666667v213.333333h-213.333333c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666666h256c25.6 0 42.666667-17.066667 42.666666-42.666666v-256c0-25.6-17.066667-42.666667-42.666666-42.666667zM601.6 401.066667c4.266667 8.533333 12.8 17.066667 21.333333 21.333333 4.266667 4.266667 12.8 4.266667 17.066667 4.266667h256c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666667h-153.6l226.133333-226.133333c17.066667-17.066667 17.066667-42.666667 0-59.733333-8.533333-8.533333-17.066667-12.8-29.866666-12.8s-21.333333 4.266667-29.866667 12.8L682.666667 281.6V128c0-25.6-17.066667-42.666667-42.666667-42.666667s-42.666667 17.066667-42.666667 42.666667v256c0 4.266667 0 12.8 4.266667 17.066667zM115.2 968.533333L341.333333 742.4V896c0 25.6 17.066667 42.666667 42.666667 42.666667s42.666667-17.066667 42.666667-42.666667v-256c0-4.266667 0-12.8-4.266667-17.066667-4.266667-8.533333-12.8-17.066667-21.333333-21.333333-4.266667-4.266667-12.8-4.266667-17.066667-4.266667H128c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666667h153.6l-226.133333 226.133333c-17.066667 17.066667-17.066667 42.666667 0 59.733333s42.666667 17.066667 59.733333 0z" p-id="10189"></path></svg></div>
56+
<iframe id="maxkb-chat" src=${protocol}://${host}/ui/chat/${token}?mode=embed></iframe>
57+
<div class="maxkb-operate"><div class="maxkb-closeviewport maxkb-viewportnone"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
58+
<path d="M7.507 11.6645C7.73712 11.6645 7.94545 11.7578 8.09625 11.9086C8.24706 12.0594 8.34033 12.2677 8.34033 12.4978V16.7976C8.34033 17.0277 8.15378 17.2143 7.92366 17.2143H7.09033C6.86021 17.2143 6.67366 17.0277 6.67366 16.7976V14.5812L3.41075 17.843C3.24803 18.0057 2.98421 18.0057 2.82149 17.843L2.23224 17.2537C2.06952 17.091 2.06952 16.8272 2.23224 16.6645L5.56668 13.3311H3.19634C2.96622 13.3311 2.77967 13.1446 2.77967 12.9145V12.0811C2.77967 11.851 2.96622 11.6645 3.19634 11.6645H7.507ZM16.5991 2.1572C16.7619 1.99448 17.0257 1.99448 17.1884 2.1572L17.7777 2.74645C17.9404 2.90917 17.9404 3.17299 17.7777 3.33571L14.4432 6.66904H16.8136C17.0437 6.66904 17.2302 6.85559 17.2302 7.08571V7.91904C17.2302 8.14916 17.0437 8.33571 16.8136 8.33571H12.5029C12.2728 8.33571 12.0644 8.24243 11.9136 8.09163C11.7628 7.94082 11.6696 7.73249 11.6696 7.50237V3.20257C11.6696 2.97245 11.8561 2.7859 12.0862 2.7859H12.9196C13.1497 2.7859 13.3362 2.97245 13.3362 3.20257V5.419L16.5991 2.1572Z" fill="#646A73"/>
59+
</svg></div>
5860
<div class="maxkb-openviewport">
59-
<svg t="1710150885892" style="vertical-align: middle;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="rgb(100, 106, 115)" width="16" height="16" ><path d="M85.333333 384c25.6 0 42.666667-17.066667 42.666667-42.666667V128h213.333333c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666666H85.333333c-25.6 0-42.666667 17.066667-42.666666 42.666666v256c0 25.6 17.066667 42.666667 42.666666 42.666667zM938.666667 640c-25.6 0-42.666667 17.066667-42.666667 42.666667v213.333333h-213.333333c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666666h256c25.6 0 42.666667-17.066667 42.666666-42.666666v-256c0-25.6-17.066667-42.666667-42.666666-42.666667zM977.066667 68.266667c-4.266667-8.533333-12.8-17.066667-21.333334-21.333334-4.266667-4.266667-12.8-4.266667-17.066666-4.266666h-256c-25.6 0-42.666667 17.066667-42.666667 42.666666s17.066667 42.666667 42.666667 42.666667h153.6l-226.133334 226.133333c-17.066667 17.066667-17.066667 42.666667 0 59.733334 8.533333 8.533333 17.066667 12.8 29.866667 12.8s21.333333-4.266667 29.866667-12.8L896 187.733333V341.333333c0 25.6 17.066667 42.666667 42.666667 42.666667s42.666667-17.066667 42.666666-42.666667V85.333333c0-4.266667 0-12.8-4.266666-17.066666zM354.133333 610.133333L128 836.266667V682.666667c0-25.6-17.066667-42.666667-42.666667-42.666667s-42.666667 17.066667-42.666666 42.666667v256c0 4.266667 0 12.8 4.266666 17.066666 4.266667 8.533333 12.8 17.066667 21.333334 21.333334 4.266667 4.266667 12.8 4.266667 17.066666 4.266666h256c25.6 0 42.666667-17.066667 42.666667-42.666666s-17.066667-42.666667-42.666667-42.666667H187.733333l226.133334-226.133333c17.066667-17.066667 17.066667-42.666667 0-59.733334s-42.666667-17.066667-59.733334 0z" p-id="8645"></path></svg>
60-
</div>
61-
<div class="maxkb-chat-close"><svg style="vertical-align: middle;overflow: hidden;" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
62-
<path d="M9.95317 8.73169L15.5511 3.13376C15.7138 2.97104 15.9776 2.97104 16.1403 3.13376L16.7296 3.72301C16.8923 3.88573 16.8923 4.14955 16.7296 4.31227L11.1317 9.9102L16.7296 15.5081C16.8923 15.6708 16.8923 15.9347 16.7296 16.0974L16.1403 16.6866C15.9776 16.8494 15.7138 16.8494 15.5511 16.6866L9.95317 11.0887L4.35524 16.6866C4.19252 16.8494 3.9287 16.8494 3.76598 16.6866L3.17673 16.0974C3.01401 15.9347 3.01401 15.6708 3.17673 15.5081L8.77465 9.9102L3.17673 4.31227C3.01401 4.14955 3.01401 3.88573 3.17673 3.72301L3.76598 3.13376C3.9287 2.97104 4.19252 2.97104 4.35524 3.13376L9.95317 8.73169Z" fill="#646A73"/>
63-
</svg>
61+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
62+
<path d="M7.15209 11.5968C7.31481 11.4341 7.57862 11.4341 7.74134 11.5968L8.3306 12.186C8.49332 12.3487 8.49332 12.6126 8.3306 12.7753L4.99615 16.1086H7.3665C7.59662 16.1086 7.78316 16.2952 7.78316 16.5253V17.3586C7.78316 17.5887 7.59662 17.7753 7.3665 17.7753H3.05584C2.82572 17.7753 2.61738 17.682 2.46658 17.5312C2.31578 17.3804 2.2225 17.1721 2.2225 16.9419V12.6421C2.2225 12.412 2.40905 12.2255 2.63917 12.2255H3.4725C3.70262 12.2255 3.88917 12.412 3.88917 12.6421V14.8586L7.15209 11.5968ZM16.937 2.22217C17.1671 2.22217 17.3754 2.31544 17.5262 2.46625C17.677 2.61705 17.7703 2.82538 17.7703 3.0555V7.35531C17.7703 7.58543 17.5837 7.77198 17.3536 7.77198H16.5203C16.2902 7.77198 16.1036 7.58543 16.1036 7.35531V5.13888L12.8407 8.40068C12.678 8.5634 12.4142 8.5634 12.2515 8.40068L11.6622 7.81142C11.4995 7.64871 11.4995 7.38489 11.6622 7.22217L14.9966 3.88883H12.6263C12.3962 3.88883 12.2096 3.70229 12.2096 3.47217V2.63883C12.2096 2.40872 12.3962 2.22217 12.6263 2.22217H16.937Z" fill="#646A73"/>
63+
</svg></div>
64+
<div class="maxkb-chat-close"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
65+
<path d="M9.95317 8.73169L15.5511 3.13376C15.7138 2.97104 15.9776 2.97104 16.1403 3.13376L16.7296 3.72301C16.8923 3.88573 16.8923 4.14955 16.7296 4.31227L11.1317 9.9102L16.7296 15.5081C16.8923 15.6708 16.8923 15.9347 16.7296 16.0974L16.1403 16.6866C15.9776 16.8494 15.7138 16.8494 15.5511 16.6866L9.95317 11.0887L4.35524 16.6866C4.19252 16.8494 3.9287 16.8494 3.76598 16.6866L3.17673 16.0974C3.01401 15.9347 3.01401 15.6708 3.17673 15.5081L8.77465 9.9102L3.17673 4.31227C3.01401 4.14955 3.01401 3.88573 3.17673 3.72301L3.76598 3.13376C3.9287 2.97104 4.19252 2.97104 4.35524 3.13376L9.95317 8.73169Z" fill="#646A73"/>
66+
</svg>
6467
</div></div>
6568
`
6669
}
@@ -94,6 +97,7 @@ const initChat=(root)=>{
9497
const closeviewport=root.querySelector('.maxkb-closeviewport')
9598
const close_func=()=>{
9699
chat_container.style['display']=chat_container.style['display']=='block'?'none':'block'
100+
chat_button.style['display']=chat_container.style['display']=='block'?'none':'block'
97101
}
98102
close_icon=chat_container.querySelector('.maxkb-chat-close')
99103
chat_button.onclick = close_func
@@ -250,12 +254,12 @@ function initMaxkbStyle(root){
250254
border: 1px solid #ffffff;
251255
background: linear-gradient(188deg, rgba(235, 241, 255, 0.20) 39.6%, rgba(231, 249, 255, 0.20) 94.3%), #EFF0F1;
252256
box-shadow: 0px 4px 8px 0px rgba(31, 35, 41, 0.10);
253-
position: fixed;bottom: 20px;right: 45px;overflow: hidden;
257+
position: fixed;bottom: 16px;right: 16px;overflow: hidden;
254258
}
255259
256260
#maxkb #maxkb-chat-container .maxkb-operate{
257-
top: 15px;
258-
right: 10px;
261+
top: 18px;
262+
right: 15px;
259263
position: absolute;
260264
display: flex;
261265
align-items: center;

apps/application/urls.py

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
path('application/<int:current_page>/<int:page_size>', views.Application.Page.as_view(), name='application_page'),
3131
path('application/<str:application_id>/chat/open', views.ChatView.Open.as_view()),
3232
path("application/chat/open", views.ChatView.OpenTemp.as_view()),
33+
path("application/<str:application_id>/chat/client/<int:current_page>/<int:page_size>",
34+
views.ChatView.ClientChatHistoryPage.as_view()),
3335
path('application/<str:application_id>/chat/export', views.ChatView.Export.as_view(), name='export'),
3436
path('application/<str:application_id>/chat', views.ChatView.as_view(), name='chats'),
3537
path('application/<str:application_id>/chat/<int:current_page>/<int:page_size>', views.ChatView.Page.as_view()),

apps/application/views/chat_views.py

+27-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313

1414
from application.serializers.chat_message_serializers import ChatMessageSerializer
1515
from application.serializers.chat_serializers import ChatSerializers, ChatRecordSerializer
16-
from application.swagger_api.chat_api import ChatApi, VoteApi, ChatRecordApi, ImproveApi, ChatRecordImproveApi
16+
from application.swagger_api.chat_api import ChatApi, VoteApi, ChatRecordApi, ImproveApi, ChatRecordImproveApi, \
17+
ChatClientHistoryApi
1718
from common.auth import TokenAuth, has_permissions
1819
from common.constants.authentication_type import AuthenticationType
1920
from common.constants.permission_constants import Permission, Group, Operate, \
@@ -137,6 +138,28 @@ def delete(self, request: Request, application_id: str, chat_id: str):
137138
data={'application_id': application_id, 'user_id': request.user.id,
138139
'chat_id': chat_id}).delete())
139140

141+
class ClientChatHistoryPage(APIView):
142+
authentication_classes = [TokenAuth]
143+
144+
@action(methods=['GET'], detail=False)
145+
@swagger_auto_schema(operation_summary="分页获取客户端对话列表",
146+
operation_id="分页获取客户端对话列表",
147+
manual_parameters=result.get_page_request_params(
148+
ChatClientHistoryApi.get_request_params_api()),
149+
responses=result.get_page_api_response(ChatApi.get_response_body_api()),
150+
tags=["应用/对话日志"]
151+
)
152+
@has_permissions(
153+
ViewPermission([RoleConstants.APPLICATION_ACCESS_TOKEN],
154+
[lambda r, keywords: Permission(group=Group.APPLICATION, operate=Operate.USE,
155+
dynamic_tag=keywords.get('application_id'))])
156+
)
157+
def get(self, request: Request, application_id: str, current_page: int, page_size: int):
158+
return result.success(ChatSerializers.ClientChatHistory(
159+
data={'client_id': request.auth.client_id, 'application_id': application_id}).page(
160+
current_page=current_page,
161+
page_size=page_size))
162+
140163
class Page(APIView):
141164
authentication_classes = [TokenAuth]
142165

@@ -198,7 +221,7 @@ def get(self, request: Request, application_id: str, chat_id: str, chat_record_i
198221
def get(self, request: Request, application_id: str, chat_id: str):
199222
return result.success(ChatRecordSerializer.Query(
200223
data={'application_id': application_id,
201-
'chat_id': chat_id}).list())
224+
'chat_id': chat_id, 'order_asc': request.query_params.get('order_asc')}).list())
202225

203226
class Page(APIView):
204227
authentication_classes = [TokenAuth]
@@ -219,7 +242,8 @@ class Page(APIView):
219242
def get(self, request: Request, application_id: str, chat_id: str, current_page: int, page_size: int):
220243
return result.success(ChatRecordSerializer.Query(
221244
data={'application_id': application_id,
222-
'chat_id': chat_id}).page(current_page, page_size))
245+
'chat_id': chat_id, 'order_asc': request.query_params.get('order_asc')}).page(current_page,
246+
page_size))
223247

224248
class Vote(APIView):
225249
authentication_classes = [TokenAuth]

0 commit comments

Comments
 (0)