1
+ import json
1
2
from datetime import datetime
2
- from typing import Literal
3
+ from typing import Literal , List
3
4
4
- from langchain_core .messages import BaseMessage , HumanMessage , AIMessage , SystemMessage
5
+ from langchain_core .messages import (
6
+ BaseMessage ,
7
+ HumanMessage ,
8
+ AIMessage ,
9
+ SystemMessage ,
10
+ ToolMessage ,
11
+ ToolCall ,
12
+ )
5
13
14
+ from app .common .pyris_message import (
15
+ PyrisMessage ,
16
+ PyrisAIMessage ,
17
+ IrisMessageRole ,
18
+ PyrisToolMessage ,
19
+ )
6
20
from app .domain .data .text_message_content_dto import TextMessageContentDTO
7
- from app .common .pyris_message import PyrisMessage , IrisMessageRole
21
+ from app .domain .data .tool_call_dto import ToolCallDTO , FunctionDTO
22
+ from app .domain .data .tool_message_content_dto import ToolMessageContentDTO
8
23
9
24
10
25
def convert_iris_message_to_langchain_message (
11
26
iris_message : PyrisMessage ,
12
27
) -> BaseMessage :
13
- if len (iris_message .contents ) == 0 :
28
+ if iris_message is None or len (iris_message .contents ) == 0 :
14
29
raise ValueError ("IrisMessage contents must not be empty" )
15
30
message = iris_message .contents [0 ]
16
31
# Check if the message is of type TextMessageContentDTO
@@ -20,41 +35,122 @@ def convert_iris_message_to_langchain_message(
20
35
case IrisMessageRole .USER :
21
36
return HumanMessage (content = message .text_content )
22
37
case IrisMessageRole .ASSISTANT :
38
+ if isinstance (iris_message , PyrisAIMessage ):
39
+ tool_calls = [
40
+ ToolCall (
41
+ name = tc .function .name ,
42
+ args = tc .function .arguments ,
43
+ id = tc .id ,
44
+ )
45
+ for tc in iris_message .tool_calls
46
+ ]
47
+ return AIMessage (content = message .text_content , tool_calls = tool_calls )
23
48
return AIMessage (content = message .text_content )
24
49
case IrisMessageRole .SYSTEM :
25
50
return SystemMessage (content = message .text_content )
26
51
case _:
27
52
raise ValueError (f"Unknown message role: { iris_message .sender } " )
28
53
29
54
55
+ def convert_iris_message_to_langchain_human_message (
56
+ iris_message : PyrisMessage ,
57
+ ) -> HumanMessage :
58
+ if len (iris_message .contents ) == 0 :
59
+ raise ValueError ("IrisMessage contents must not be empty" )
60
+ message = iris_message .contents [0 ]
61
+ # Check if the message is of type TextMessageContentDTO
62
+ if not isinstance (message , TextMessageContentDTO ):
63
+ raise ValueError ("Message must be of type TextMessageContentDTO" )
64
+ return HumanMessage (content = message .text_content )
65
+
66
+
67
+ def extract_text_from_iris_message (iris_message : PyrisMessage ) -> str :
68
+ if len (iris_message .contents ) == 0 :
69
+ raise ValueError ("IrisMessage contents must not be empty" )
70
+ message = iris_message .contents [0 ]
71
+ # Check if the message is of type TextMessageContentDTO
72
+ if not isinstance (message , TextMessageContentDTO ):
73
+ raise ValueError ("Message must be of type TextMessageContentDTO" )
74
+ return message .text_content
75
+
76
+
77
+ def convert_langchain_tool_calls_to_iris_tool_calls (
78
+ tool_calls : List [ToolCall ],
79
+ ) -> List [ToolCallDTO ]:
80
+ return [
81
+ ToolCallDTO (
82
+ function = FunctionDTO (
83
+ name = tc ["name" ],
84
+ arguments = json .dumps (tc ["args" ]),
85
+ ),
86
+ id = tc ["id" ],
87
+ )
88
+ for tc in tool_calls
89
+ ]
90
+
91
+
30
92
def convert_langchain_message_to_iris_message (
31
93
base_message : BaseMessage ,
32
94
) -> PyrisMessage :
33
- match base_message .type :
34
- case "human" :
35
- role = IrisMessageRole .USER
36
- case "ai" :
37
- role = IrisMessageRole .ASSISTANT
38
- case "system" :
39
- role = IrisMessageRole .SYSTEM
40
- case _:
41
- raise ValueError (f"Unknown message type: { base_message .type } " )
42
- contents = [TextMessageContentDTO (textContent = base_message .content )]
95
+ type_to_role = {
96
+ "human" : IrisMessageRole .USER ,
97
+ "ai" : IrisMessageRole .ASSISTANT ,
98
+ "system" : IrisMessageRole .SYSTEM ,
99
+ "tool" : IrisMessageRole .TOOL ,
100
+ }
101
+
102
+ role = type_to_role .get (base_message .type )
103
+ if role is None :
104
+ raise ValueError (f"Unknown message type: { base_message .type } " )
105
+
106
+ if isinstance (base_message , (HumanMessage , SystemMessage )):
107
+ contents = [TextMessageContentDTO (textContent = base_message .content )]
108
+ elif isinstance (base_message , AIMessage ):
109
+ if base_message .tool_calls :
110
+ contents = [TextMessageContentDTO (textContent = base_message .content )]
111
+ tool_calls = convert_langchain_tool_calls_to_iris_tool_calls (
112
+ base_message .tool_calls
113
+ )
114
+ return PyrisAIMessage (
115
+ contents = contents ,
116
+ tool_calls = tool_calls ,
117
+ send_at = datetime .now (),
118
+ )
119
+ else :
120
+ contents = [TextMessageContentDTO (textContent = base_message .content )]
121
+ elif isinstance (base_message , ToolMessage ):
122
+ contents = [
123
+ ToolMessageContentDTO (
124
+ toolContent = base_message .content ,
125
+ toolName = base_message .additional_kwargs ["name" ],
126
+ toolCallId = base_message .tool_call_id ,
127
+ )
128
+ ]
129
+ return PyrisToolMessage (
130
+ contents = contents ,
131
+ send_at = datetime .now (),
132
+ )
133
+ else :
134
+ raise ValueError (f"Unknown message type: { type (base_message )} " )
43
135
return PyrisMessage (
44
136
contents = contents ,
45
137
sender = role ,
46
138
send_at = datetime .now (),
47
139
)
48
140
49
141
50
- def map_role_to_str (role : IrisMessageRole ) -> Literal ["user" , "assistant" , "system" ]:
142
+ def map_role_to_str (
143
+ role : IrisMessageRole ,
144
+ ) -> Literal ["user" , "assistant" , "system" , "tool" ]:
51
145
match role :
52
146
case IrisMessageRole .USER :
53
147
return "user"
54
148
case IrisMessageRole .ASSISTANT :
55
149
return "assistant"
56
150
case IrisMessageRole .SYSTEM :
57
151
return "system"
152
+ case IrisMessageRole .TOOL :
153
+ return "tool"
58
154
case _:
59
155
raise ValueError (f"Unknown message role: { role } " )
60
156
@@ -67,5 +163,7 @@ def map_str_to_role(role: str) -> IrisMessageRole:
67
163
return IrisMessageRole .ASSISTANT
68
164
case "system" :
69
165
return IrisMessageRole .SYSTEM
166
+ case "tool" :
167
+ return IrisMessageRole .TOOL
70
168
case _:
71
169
raise ValueError (f"Unknown message role: { role } " )
0 commit comments