Skip to content

MLXChatExample: fix VLM image handling on iOS (PhotosPicker, EXIF, empty assistant trim)#472

Merged
davidkoski merged 2 commits into
ml-explore:mainfrom
john-rocky:fix/ios-photospicker
Jun 15, 2026
Merged

MLXChatExample: fix VLM image handling on iOS (PhotosPicker, EXIF, empty assistant trim)#472
davidkoski merged 2 commits into
ml-explore:mainfrom
john-rocky:fix/ios-photospicker

Conversation

@john-rocky

Copy link
Copy Markdown
Contributor

Summary

Three iOS-only fixes in `MLXChatExample` so VLM image input actually works on iPhone:

  1. PhotosPicker instead of `fileImporter` — `fileImporter` shows the Files app on iOS, which doesn't expose the photo library. Replace with `.photosPicker` for image / video selection. Custom `Transferable` wrappers (`PickedImage` / `PickedVideo`) request the right content type explicitly so loading is reliable.

  2. Normalize EXIF orientation before saving — `UIImage.jpegData()` writes the EXIF orientation tag but leaves pixel data in raw sensor orientation. `CIImage(contentsOf:)` (used downstream for the model input) does not apply that EXIF tag, so portrait / landscape photos arrive at the VLM rotated. Re-render through `UIGraphicsImageRenderer` before writing the JPEG so the file is upright.

  3. Trim trailing empty assistant message before applying chat template — `ChatViewModel` appends an empty assistant message before generation starts (so the UI has a placeholder to stream into). When that vector is passed straight into the chat template, the template closes the assistant turn and the model emits an EOS immediately. Strip the trailing empty assistant entry, matching the implicit behavior of `ChatSession`.

macOS path unchanged — `fileImporter` still works there. The `#if os(iOS)` blocks are scoped to the new code only.

Test plan

Tested on iPhone (Daisuke の iPhone, iOS 26):

  • qwen2.5-VL-3B-Instruct-4bit, photo selected from Photos → image preview shown.
  • Re-test landscape / portrait image after merge: "describe this image" output should match the visible orientation.
  • Video selection still working.
  • Successive sends without restarting the chat.

john-rocky and others added 2 commits April 30, 2026 20:02
- Use custom Transferable types (PickedImage/PickedVideo) with explicit
  content types instead of generic Data.self for reliable PhotosPicker loading
- Normalize image orientation via UIGraphicsImageRenderer before saving
  as JPEG, since CIImage(contentsOf:) does not apply EXIF orientation
- Exclude trailing empty assistant message from model input so the chat
  template leaves the assistant turn open for generation

@davidkoski davidkoski left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thank you!

@davidkoski davidkoski merged commit 378f244 into ml-explore:main Jun 15, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants