llm-dialog-manager 0.4.4__py3-none-any.whl → 0.4.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
1
  from .chat_history import ChatHistory
2
2
  from .agent import Agent
3
3
 
4
- __version__ = "0.4.4"
4
+ __version__ = "0.4.6"
@@ -2,7 +2,7 @@
2
2
  import json
3
3
  import os
4
4
  import uuid
5
- from typing import List, Dict, Optional, Union
5
+ from typing import List, Dict, Union, Optional, Any
6
6
  import logging
7
7
  from pathlib import Path
8
8
  import random
@@ -97,13 +97,30 @@ def completion(model: str, messages: List[Dict[str, Union[str, List[Union[str, I
97
97
  api_key = os.getenv(f"{service.upper()}_API_KEY")
98
98
  base_url = os.getenv(f"{service.upper()}_BASE_URL")
99
99
 
100
- def format_messages_for_api(model, messages):
101
- """Convert ChatHistory messages to the format required by the specific API."""
100
+ def format_messages_for_api(
101
+ model: str,
102
+ messages: List[Dict[str, Union[str, List[Union[str, Image.Image, Dict]]]]]
103
+ ) -> tuple[Optional[str], List[Dict[str, Any]]]:
104
+ """
105
+ Convert ChatHistory messages to the format required by the specific API.
106
+
107
+ Args:
108
+ model: The model name (e.g., "claude", "gemini", "gpt")
109
+ messages: List of message dictionaries with role and content
110
+
111
+ Returns:
112
+ tuple: (system_message, formatted_messages)
113
+ - system_message is extracted system message for Claude, None for others
114
+ - formatted_messages is the list of formatted message dictionaries
115
+ """
102
116
  if "claude" in model and "openai" not in model:
103
117
  formatted = []
104
118
  system_msg = ""
119
+
120
+ # Extract system message if present
105
121
  if messages and messages[0]["role"] == "system":
106
122
  system_msg = messages.pop(0)["content"]
123
+
107
124
  for msg in messages:
108
125
  content = msg["content"]
109
126
  if isinstance(content, str):
@@ -113,9 +130,12 @@ def completion(model: str, messages: List[Dict[str, Union[str, List[Union[str, I
113
130
  combined_content = []
114
131
  for block in content:
115
132
  if isinstance(block, str):
116
- combined_content.append({"type": "text", "text": block})
133
+ combined_content.append({
134
+ "type": "text",
135
+ "text": block
136
+ })
117
137
  elif isinstance(block, Image.Image):
118
- # For Claude, convert PIL.Image to base64
138
+ # Convert PIL.Image to base64
119
139
  buffered = io.BytesIO()
120
140
  block.save(buffered, format="PNG")
121
141
  image_base64 = base64.b64encode(buffered.getvalue()).decode("utf-8")
@@ -145,9 +165,12 @@ def completion(model: str, messages: List[Dict[str, Union[str, List[Union[str, I
145
165
  "data": block["image_base64"]["data"]
146
166
  }
147
167
  })
148
- formatted.append({"role": msg["role"], "content": combined_content})
168
+ formatted.append({
169
+ "role": msg["role"],
170
+ "content": combined_content
171
+ })
149
172
  return system_msg, formatted
150
-
173
+
151
174
  elif ("gemini" in model or "gpt" in model or "grok" in model) and "openai" not in model:
152
175
  formatted = []
153
176
  for msg in messages:
@@ -160,40 +183,75 @@ def completion(model: str, messages: List[Dict[str, Union[str, List[Union[str, I
160
183
  if isinstance(block, str):
161
184
  parts.append(block)
162
185
  elif isinstance(block, Image.Image):
186
+ # Keep PIL.Image objects as is for Gemini
163
187
  parts.append(block)
164
188
  elif isinstance(block, dict):
165
189
  if block.get("type") == "image_url":
166
- parts.append({"type": "image_url", "image_url": {"url": block["image_url"]["url"]}})
190
+ parts.append({
191
+ "type": "image_url",
192
+ "image_url": {
193
+ "url": block["image_url"]["url"]
194
+ }
195
+ })
167
196
  elif block.get("type") == "image_base64":
168
- parts.append({"type": "image_base64", "image_base64": {"data": block["image_base64"]["data"], "media_type": block["image_base64"]["media_type"]}})
169
- formatted.append({"role": msg["role"], "parts": parts})
197
+ parts.append({
198
+ "type": "image_base64",
199
+ "image_base64": {
200
+ "data": block["image_base64"]["data"],
201
+ "media_type": block["image_base64"]["media_type"]
202
+ }
203
+ })
204
+ formatted.append({
205
+ "role": msg["role"],
206
+ "parts": parts
207
+ })
170
208
  return None, formatted
171
-
209
+
172
210
  else: # OpenAI models
173
211
  formatted = []
174
212
  for msg in messages:
175
213
  content = msg["content"]
176
214
  if isinstance(content, str):
177
- formatted.append({"role": msg["role"], "content": content})
215
+ formatted.append({
216
+ "role": msg["role"],
217
+ "content": content
218
+ })
178
219
  elif isinstance(content, list):
179
- # OpenAI expects 'content' as string; images are not directly supported
180
- # You can convert images to URLs or descriptions if needed
181
- combined_content = ""
220
+ formatted_content = []
182
221
  for block in content:
183
222
  if isinstance(block, str):
184
- combined_content += block + "\n"
223
+ formatted_content.append({
224
+ "type": "text",
225
+ "text": block
226
+ })
185
227
  elif isinstance(block, Image.Image):
186
- # Convert PIL.Image to base64 or upload and use URL
228
+ # Convert PIL.Image to base64
187
229
  buffered = io.BytesIO()
188
230
  block.save(buffered, format="PNG")
189
231
  image_base64 = base64.b64encode(buffered.getvalue()).decode("utf-8")
190
- combined_content += f"[Image Base64: {image_base64[:30]}...]\n"
232
+ formatted_content.append({
233
+ "type": "image_url",
234
+ "image_url": {
235
+ "url": f"data:image/jpeg;base64,{image_base64}"
236
+ }
237
+ })
191
238
  elif isinstance(block, dict):
192
239
  if block.get("type") == "image_url":
193
- combined_content += f"[Image: {block['image_url']['url']}]\n"
240
+ formatted_content.append({
241
+ "type": "image_url",
242
+ "image_url": block["image_url"]
243
+ })
194
244
  elif block.get("type") == "image_base64":
195
- combined_content += f"[Image Base64: {block['image_base64']['data'][:30]}...]\n"
196
- formatted.append({"role": msg["role"], "content": combined_content.strip()})
245
+ formatted_content.append({
246
+ "type": "image_url",
247
+ "image_url": {
248
+ "url": f"data:image/jpeg;base64,{block['image_base64']['data']}"
249
+ }
250
+ })
251
+ formatted.append({
252
+ "role": msg["role"],
253
+ "content": formatted_content
254
+ })
197
255
  return None, formatted
198
256
 
199
257
  system_msg, formatted_messages = format_messages_for_api(model, messages.copy())
@@ -336,16 +394,21 @@ def completion(model: str, messages: List[Dict[str, Union[str, List[Union[str, I
336
394
  if model.endswith("-openai"):
337
395
  model = model[:-7] # Remove last 7 characters ("-openai")
338
396
  client = openai.OpenAI(api_key=api_key, base_url=base_url)
339
- # Set response_format based on json_format
340
- response_format = {"type": "json_object"} if json_format else {"type": "plain_text"}
341
-
342
- response = client.chat.completions.create(
343
- model=model,
344
- messages=formatted_messages,
345
- max_tokens=max_tokens,
346
- temperature=temperature,
347
- response_format=response_format # Added response_format
348
- )
397
+
398
+ # Create base parameters
399
+ params = {
400
+ "model": model,
401
+ "messages": formatted_messages,
402
+ }
403
+
404
+ # Add optional parameters
405
+ if json_format:
406
+ params["response_format"] = {"type": "json_object"}
407
+ if not ("o1" in model or "o3" in model):
408
+ params["max_tokens"] = max_tokens
409
+ params["temperature"] = temperature
410
+
411
+ response = client.chat.completions.create(**params)
349
412
  return response.choices[0].message.content
350
413
 
351
414
  # Release the API key after successful use
@@ -546,7 +609,7 @@ class Agent:
546
609
  if __name__ == "__main__":
547
610
  # Example Usage
548
611
  # Create an Agent instance (Gemini model)
549
- agent = Agent("gemini-1.5-flash", "you are Jack101", memory_enabled=True)
612
+ agent = Agent("gemini-1.5-flash-openai", "you are Jack101", memory_enabled=True)
550
613
 
551
614
  # Add an image
552
615
  agent.add_image(image_path="example.png")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: llm_dialog_manager
3
- Version: 0.4.4
3
+ Version: 0.4.6
4
4
  Summary: A Python package for managing LLM chat conversation history
5
5
  Author-email: xihajun <work@2333.fun>
6
6
  License: MIT
@@ -0,0 +1,9 @@
1
+ llm_dialog_manager/__init__.py,sha256=klLFvHayR7ew1Oh9xyhAXdXnfs82YnFUEFzw0YvxKJI,86
2
+ llm_dialog_manager/agent.py,sha256=NVQKIMebl4cYkqMaBceZ3qs1vYhq1bum9okAn8VcfCg,27680
3
+ llm_dialog_manager/chat_history.py,sha256=DKKRnj_M6h-4JncnH6KekMTghX7vMgdN3J9uOwXKzMU,10347
4
+ llm_dialog_manager/key_manager.py,sha256=shvxmn4zUtQx_p-x1EFyOmnk-WlhigbpKtxTKve-zXk,4421
5
+ llm_dialog_manager-0.4.6.dist-info/LICENSE,sha256=vWGbYgGuWpWrXL8-xi6pNcX5UzD6pWoIAZmcetyfbus,1064
6
+ llm_dialog_manager-0.4.6.dist-info/METADATA,sha256=-qTRYkfAJMJCQTkRqNrtHjUuN-xGLhLR4CJvSJURgeg,4194
7
+ llm_dialog_manager-0.4.6.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
8
+ llm_dialog_manager-0.4.6.dist-info/top_level.txt,sha256=u2EQEXW0NGAt0AAHT7jx1odXZ4rZfjcgbmJhvKFuMkI,19
9
+ llm_dialog_manager-0.4.6.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- llm_dialog_manager/__init__.py,sha256=J7qsuEH4NWFkTQVvCqHgxX1jOYnY79s9BMi02KTo3-A,86
2
- llm_dialog_manager/agent.py,sha256=ou9D8NtRt6fDXgrneXP5jZRil7XyKpCTUHCADPJmeeA,25332
3
- llm_dialog_manager/chat_history.py,sha256=DKKRnj_M6h-4JncnH6KekMTghX7vMgdN3J9uOwXKzMU,10347
4
- llm_dialog_manager/key_manager.py,sha256=shvxmn4zUtQx_p-x1EFyOmnk-WlhigbpKtxTKve-zXk,4421
5
- llm_dialog_manager-0.4.4.dist-info/LICENSE,sha256=vWGbYgGuWpWrXL8-xi6pNcX5UzD6pWoIAZmcetyfbus,1064
6
- llm_dialog_manager-0.4.4.dist-info/METADATA,sha256=Rjjs7I8JwbQ21QyMxTDrDrwzmAqMcdY30srUOJxYzWs,4194
7
- llm_dialog_manager-0.4.4.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
8
- llm_dialog_manager-0.4.4.dist-info/top_level.txt,sha256=u2EQEXW0NGAt0AAHT7jx1odXZ4rZfjcgbmJhvKFuMkI,19
9
- llm_dialog_manager-0.4.4.dist-info/RECORD,,