asfaef
This commit is contained in:
parent
af43a3f64f
commit
eecdcb5b7e
30
gurt/api.py
30
gurt/api.py
@ -692,12 +692,12 @@ async def get_ai_response(cog: 'GurtCog', message: discord.Message, model_name:
|
|||||||
continue
|
continue
|
||||||
# Handle potential multimodal content in history (if stored that way)
|
# Handle potential multimodal content in history (if stored that way)
|
||||||
if isinstance(msg.get("content"), list):
|
if isinstance(msg.get("content"), list):
|
||||||
parts = [types.Part.from_text(part["text"]) if part["type"] == "text" else types.Part.from_uri(part["image_url"]["url"], mime_type=part["image_url"]["url"].split(";")[0].split(":")[1]) if part["type"] == "image_url" else None for part in msg["content"]]
|
parts = [types.Part(text=part["text"]) if part["type"] == "text" else types.Part(uri=part["image_url"]["url"], mime_type=part["image_url"]["url"].split(";")[0].split(":")[1]) if part["type"] == "image_url" else None for part in msg["content"]]
|
||||||
parts = [p for p in parts if p] # Filter out None parts
|
parts = [p for p in parts if p] # Filter out None parts
|
||||||
if parts:
|
if parts:
|
||||||
contents.append(types.Content(role=role, parts=parts))
|
contents.append(types.Content(role=role, parts=parts))
|
||||||
elif isinstance(msg.get("content"), str):
|
elif isinstance(msg.get("content"), str):
|
||||||
contents.append(types.Content(role=role, parts=[types.Part.from_text(msg["content"])]))
|
contents.append(types.Content(role=role, parts=[types.Part(text=msg["content"])]))
|
||||||
|
|
||||||
|
|
||||||
# --- Prepare the current message content (potentially multimodal) ---
|
# --- Prepare the current message content (potentially multimodal) ---
|
||||||
@ -723,7 +723,7 @@ async def get_ai_response(cog: 'GurtCog', message: discord.Message, model_name:
|
|||||||
mentions_str = ", ".join([f"{m['display_name']}(id:{m['id']})" for m in formatted_current_message["mentioned_users_details"]])
|
mentions_str = ", ".join([f"{m['display_name']}(id:{m['id']})" for m in formatted_current_message["mentioned_users_details"]])
|
||||||
text_content += f"\n(Message Details: Mentions=[{mentions_str}])"
|
text_content += f"\n(Message Details: Mentions=[{mentions_str}])"
|
||||||
|
|
||||||
current_message_parts.append(types.Part.from_text(text_content))
|
current_message_parts.append(types.Part(text=text_content))
|
||||||
# --- End text content construction ---
|
# --- End text content construction ---
|
||||||
|
|
||||||
if message.attachments:
|
if message.attachments:
|
||||||
@ -750,23 +750,23 @@ async def get_ai_response(cog: 'GurtCog', message: discord.Message, model_name:
|
|||||||
try:
|
try:
|
||||||
# 1. Add text part instructing AI about the file
|
# 1. Add text part instructing AI about the file
|
||||||
instruction_text = f"User attached a file: '{filename}' (Type: {mime_type}). Analyze this file from the following URI and incorporate your understanding into your response."
|
instruction_text = f"User attached a file: '{filename}' (Type: {mime_type}). Analyze this file from the following URI and incorporate your understanding into your response."
|
||||||
current_message_parts.append(types.Part.from_text(instruction_text))
|
current_message_parts.append(types.Part(text=instruction_text))
|
||||||
print(f"Added text instruction for attachment: {filename}")
|
print(f"Added text instruction for attachment: {filename}")
|
||||||
|
|
||||||
# 2. Add the URI part
|
# 2. Add the URI part
|
||||||
# Ensure mime_type doesn't contain parameters like '; charset=...' if the API doesn't like them
|
# Ensure mime_type doesn't contain parameters like '; charset=...' if the API doesn't like them
|
||||||
clean_mime_type = mime_type.split(';')[0]
|
clean_mime_type = mime_type.split(';')[0]
|
||||||
current_message_parts.append(types.Part.from_uri(uri=file_url, mime_type=clean_mime_type))
|
current_message_parts.append(types.Part(uri=file_url, mime_type=clean_mime_type))
|
||||||
print(f"Added URI part for attachment: {filename} ({clean_mime_type}) using URL: {file_url}")
|
print(f"Added URI part for attachment: {filename} ({clean_mime_type}) using URL: {file_url}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error creating types.Part for attachment {filename} ({mime_type}): {e}")
|
print(f"Error creating types.Part for attachment {filename} ({mime_type}): {e}")
|
||||||
# Optionally add a text part indicating the error
|
# Optionally add a text part indicating the error
|
||||||
current_message_parts.append(types.Part.from_text(f"(System Note: Failed to process attachment '{filename}' - {e})"))
|
current_message_parts.append(types.Part(text=f"(System Note: Failed to process attachment '{filename}' - {e})"))
|
||||||
else:
|
else:
|
||||||
print(f"Skipping unsupported or invalid attachment: {filename} (Type: {mime_type}, URL: {file_url})")
|
print(f"Skipping unsupported or invalid attachment: {filename} (Type: {mime_type}, URL: {file_url})")
|
||||||
# Optionally inform the AI that an unsupported file was attached
|
# Optionally inform the AI that an unsupported file was attached
|
||||||
current_message_parts.append(types.Part.from_text(f"(System Note: User attached an unsupported file '{filename}' of type '{mime_type}' which cannot be processed.)"))
|
current_message_parts.append(types.Part(text=f"(System Note: User attached an unsupported file '{filename}' of type '{mime_type}' which cannot be processed.)"))
|
||||||
|
|
||||||
|
|
||||||
# Ensure there's always *some* content part, even if only text or errors
|
# Ensure there's always *some* content part, even if only text or errors
|
||||||
@ -774,7 +774,7 @@ async def get_ai_response(cog: 'GurtCog', message: discord.Message, model_name:
|
|||||||
contents.append(types.Content(role="user", parts=current_message_parts))
|
contents.append(types.Content(role="user", parts=current_message_parts))
|
||||||
else:
|
else:
|
||||||
print("Warning: No content parts generated for user message.")
|
print("Warning: No content parts generated for user message.")
|
||||||
contents.append(types.Content(role="user", parts=[types.Part.from_text("")])) # Ensure content list isn't empty
|
contents.append(types.Content(role="user", parts=[types.Part(text="")])) # Ensure content list isn't empty
|
||||||
|
|
||||||
# --- Prepare Tools ---
|
# --- Prepare Tools ---
|
||||||
# Convert FunctionDeclarations from config.py (TOOLS) into a Tool object
|
# Convert FunctionDeclarations from config.py (TOOLS) into a Tool object
|
||||||
@ -1113,7 +1113,7 @@ async def get_proactive_ai_response(cog: 'GurtCog', message: discord.Message, tr
|
|||||||
]
|
]
|
||||||
# Add the final instruction
|
# Add the final instruction
|
||||||
proactive_contents.append(
|
proactive_contents.append(
|
||||||
types.Content(role="user", parts=[types.Part.from_text(
|
types.Content(role="user", parts=[types.Part(text=
|
||||||
f"Generate the response based on your plan. **CRITICAL: Your response MUST be ONLY the raw JSON object matching this schema:**\n\n{json.dumps(RESPONSE_SCHEMA['schema'], indent=2)}\n\n**Ensure nothing precedes or follows the JSON.**"
|
f"Generate the response based on your plan. **CRITICAL: Your response MUST be ONLY the raw JSON object matching this schema:**\n\n{json.dumps(RESPONSE_SCHEMA['schema'], indent=2)}\n\n**Ensure nothing precedes or follows the JSON.**"
|
||||||
)])
|
)])
|
||||||
)
|
)
|
||||||
@ -1252,25 +1252,25 @@ async def get_internal_ai_json_response(
|
|||||||
|
|
||||||
if isinstance(content_value, str):
|
if isinstance(content_value, str):
|
||||||
# Handle simple string content
|
# Handle simple string content
|
||||||
message_parts.append(types.Part.from_text(content_value))
|
message_parts.append(types.Part(text=content_value))
|
||||||
elif isinstance(content_value, list):
|
elif isinstance(content_value, list):
|
||||||
# Handle list content (e.g., multimodal from ProfileUpdater)
|
# Handle list content (e.g., multimodal from ProfileUpdater)
|
||||||
for part_data in content_value:
|
for part_data in content_value:
|
||||||
part_type = part_data.get("type")
|
part_type = part_data.get("type")
|
||||||
if part_type == "text":
|
if part_type == "text":
|
||||||
text = part_data.get("text", "")
|
text = part_data.get("text", "")
|
||||||
message_parts.append(types.Part.from_text(text))
|
message_parts.append(types.Part(text=text))
|
||||||
elif part_type == "image_data":
|
elif part_type == "image_data":
|
||||||
mime_type = part_data.get("mime_type")
|
mime_type = part_data.get("mime_type")
|
||||||
base64_data = part_data.get("data")
|
base64_data = part_data.get("data")
|
||||||
if mime_type and base64_data:
|
if mime_type and base64_data:
|
||||||
try:
|
try:
|
||||||
image_bytes = base64.b64decode(base64_data)
|
image_bytes = base64.b64decode(base64_data)
|
||||||
message_parts.append(types.Part.from_data(data=image_bytes, mime_type=mime_type))
|
message_parts.append(types.Part(data=image_bytes, mime_type=mime_type))
|
||||||
except Exception as decode_err:
|
except Exception as decode_err:
|
||||||
print(f"Error decoding/adding image part in get_internal_ai_json_response: {decode_err}")
|
print(f"Error decoding/adding image part in get_internal_ai_json_response: {decode_err}")
|
||||||
# Optionally add a placeholder text part indicating failure
|
# Optionally add a placeholder text part indicating failure
|
||||||
message_parts.append(types.Part.from_text("(System Note: Failed to process an image part)"))
|
message_parts.append(types.Part(text="(System Note: Failed to process an image part)"))
|
||||||
else:
|
else:
|
||||||
print("Warning: image_data part missing mime_type or data.")
|
print("Warning: image_data part missing mime_type or data.")
|
||||||
else:
|
else:
|
||||||
@ -1292,9 +1292,9 @@ async def get_internal_ai_json_response(
|
|||||||
f"**Ensure nothing precedes or follows the JSON.**"
|
f"**Ensure nothing precedes or follows the JSON.**"
|
||||||
)
|
)
|
||||||
if contents and contents[-1].role == "user":
|
if contents and contents[-1].role == "user":
|
||||||
contents[-1].parts.append(types.Part.from_text(f"\n\n{json_instruction_content}"))
|
contents[-1].parts.append(types.Part(text=f"\n\n{json_instruction_content}"))
|
||||||
else:
|
else:
|
||||||
contents.append(types.Content(role="user", parts=[types.Part.from_text(json_instruction_content)]))
|
contents.append(types.Content(role="user", parts=[types.Part(text=json_instruction_content)]))
|
||||||
|
|
||||||
|
|
||||||
# --- Determine Model ---
|
# --- Determine Model ---
|
||||||
|
18
test_part.py
Normal file
18
test_part.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Test script for Part constructor
|
||||||
|
try:
|
||||||
|
from gurt.api import types
|
||||||
|
print("Successfully imported types module")
|
||||||
|
|
||||||
|
# Test creating a Part with text
|
||||||
|
part = types.Part(text="test")
|
||||||
|
print(f"Successfully created Part with text: {part}")
|
||||||
|
|
||||||
|
# Test creating a Part with URI
|
||||||
|
part_uri = types.Part(uri="https://example.com", mime_type="text/plain")
|
||||||
|
print(f"Successfully created Part with URI: {part_uri}")
|
||||||
|
|
||||||
|
print("All tests passed!")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: {type(e).__name__}: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
Loading…
x
Reference in New Issue
Block a user