Fix AI vision chat returning empty response when image attachments sent#2
Draft
Fix AI vision chat returning empty response when image attachments sent#2
Conversation
… add HackAI response logging Co-authored-by: youssef-ahmed-cs <127596947+youssef-ahmed-cs@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix bug with AI chat attachment processing
Fix AI vision chat returning empty response when image attachments sent
Mar 3, 2026
9a4ec7c to
ab7be91
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Four layered bugs caused vision chat to consistently return
"I received an empty response. Please try again."withsuccess: falsewhen image attachments were included.Bugs Fixed
Wrong model resolved before vision content built (
ChatService):resolver->resolve()was called afterbuildVisionContent(), so a short message like"experimenting with attachments"triggered fallback togpt-5-mini(non-vision), but the multimodal content array was already constructed. Now model is resolved first; if it drops vision capability but the session model has vision, pins back to session model.modelSupportsVision()missed fallback model IDs (ChatService): Only checked top-levelid— if resolved model was a fallback (e.g.gpt-5-minilisted only asfallbackin config), returnedfalse. Now also checksfallbackfield of any vision-capable parent.Expired presigned S3 URL sent to AI (
AttachmentController,ChatService, migration):urlcolumn stored a short-lived presigned URL from upload time. Fixes:s3_pathcolumn (migration +Attachment.$fillable)AttachmentControllerstores permanent URL in DB, returns 10-min presigned URL to client for previewChatService::resolveImageUrl()regenerates a fresh 60-min presigned URL at chat time, falls back to stored URLsuccess: trueon parser fallback string (ChatService):!empty($content)wastrueeven for the error string. Now compares againstAIResponseParser::EMPTY_RESPONSE_MESSAGE(extracted to a public constant to avoid duplication).Diagnostics
Added
Log::warninginHackAIServicethat dumps the full raw API response body wheneverchoices[0].message.contentis absent — surfaces provider-side issues (format mismatch, auth failure, model not supporting vision through the gateway).Original prompt
{
"session_id": 15,
"ai_message": "I received an empty response. Please try again.",
"model_used": "openai/gpt-oss-120b",
"processing_time_ms": 4120.55,
"success": false
} ..... { "attachments": [ 1 ], "message": "experimenting with attachments", "model": "openai/gpt-oss-120b" }
The user has attached the following files from their workspace:
TITLE: Fixing AI Chat Attachment/Vision Support – Empty Response Bug
USER INTENT: The user wants to fix a bug where the AI model is not seeing/processing attached files (images) in chat messages, resulting in "I received an empty response. Please try again." being returned.
TASK DESCRIPTION:
The user is sending chat messages with image attachments via the AI chat API, but the model consistently returns an empty response. The debugging process uncovered multiple layered bugs across
ChatService,AttachmentController, andModelResolverrelated to vision capability detection, model resolution ordering, expired S3 URLs, and a misleadingsuccessflag.EXISTING: (Bugs identified and fixed)
Bug 1 (FIXED) — Wrong model used for fallback vision check (
ChatService.php)ModelResolver::resolve()was called AFTERbuildVisionContent()was already decided. A short simple message like"experimenting with attachments"causedTokenTracker::shouldUseFallback()to downgradegpt-oss-120b→gpt-5-mini. The vision multimodal array was already built, then sent to a non-vision model → empty/broken API response.Bug 2 (FIXED, previous session) —
modelSupportsVision()didn't check fallback model IDs (ChatService.php)If the resolved model was a fallback (e.g.
gpt-5-mini, only listed asfallbackin config, not a top-level entry),modelSupportsVision()returnedfalsebecause it only scanned top-levelidfields.fallbackof any vision-capable parent model.Bug 3 (FIXED) — Expired presigned S3 URL sent to AI (
AttachmentController.php+ChatService.php)The
urlDB column stored a 10-minute presigned URL generated at upload time. By chat time, the URL was expired.resolveImageUrl()already tried to regenerate froms3_path, but TTL was only 10 minutes.resolveImageUrl(): Regenerate fresh presigned URL with 60-minute TTL at chat time.AttachmentController: Store the permanent public URL in theurlDB column. Client upload response still gets a short-lived 10-min presigned URL for preview via$responseUrl.Bug 4 (FIXED) —
success: truereturned even on parser fallback error string (ChatService.php)'success' => !empty($content)returnedtrueeven whencontentwas the fallback string"I received an empty response. Please try again."fromAIResponseParser::parse().PENDING:
"I received an empty response. Please try again."with"success": false. The empty response is genuinely coming back from the AI API itself.HackAI/ OpenRouter) may not support vision foropenai/gpt-oss-120bor may require a different image payload format.contentarray format sent to the API may not match what the provider expects (e.g. differentimage_urlstructure).HackAIService::chat()needs logging of the full raw API response body to diagnose what the provider is actually returning.CODE STATE:
D:\course laravel\devhub\app\Services\Chat\ChatService.php— Multiple fixes applied: