Skip to content

Commit 4c89c13

Browse files
committed
copilot propisitions again
1 parent 677216a commit 4c89c13

3 files changed

Lines changed: 46 additions & 33 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ All notable changes to this project will be documented in this file.
1717
JavaScript required.
1818

1919
### Changed
20-
- `ui/components.py`: uploaded image files are resized to ≤500×500 px
21-
**before** preview generation and before being forwarded to the VLM/backend.
22-
Original full-resolution files are no longer sent to the pipeline.
20+
- `ui/components.py`: uploaded image files are resized to ≤500×500 px for
21+
the inline chat preview. Original paths are still forwarded to the
22+
backend/pipeline for format detection and metadata extraction.
2323
- `ui/components.py`: `msg_input` textbox and `submit_btn` button no longer
2424
carry custom `elem_id` attributes (only needed for the removed JS hook).
2525
- `ui/components.py`: `submit_btn` is now part of `handle_chat` outputs so

src/ai_agent/core/handlers.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
from ai_agent.retriever.software_doc import SoftwareDoc
2828
from ai_agent.utils.file_validator import FileValidator
2929
from ai_agent.utils.tags import strip_tags, parse_exclusions
30-
from ai_agent.utils.previews import _build_preview_for_vlm
30+
from ai_agent.utils.previews import _build_preview_for_vlm, resize_uploaded_image
3131
from ai_agent.utils.utils import _coerce_files_to_paths, _is_affirmative
3232

3333
from ai_agent.agent.agent import run_agent
@@ -298,15 +298,29 @@ def respond(
298298
if file_paths:
299299
state.last_files = file_paths
300300

301-
# Build VLM preview (but don't add to reply text yet)
301+
# Build VLM preview (but don't add to reply text yet).
302+
# Resize plain images before loading them into memory so that
303+
# _build_preview_for_vlm never has to load a huge numpy array
304+
# just to downscale it. Non-image files (DICOM, NIfTI, …) pass
305+
# through unchanged. Metadata is extracted from the originals.
306+
resized_for_preview = [resize_uploaded_image(p) for p in file_paths]
307+
resize_temps = [r for r, p in zip(resized_for_preview, file_paths) if r != p]
302308
try:
303-
preview_path, meta_text = _build_preview_for_vlm(file_paths)
309+
preview_path, meta_text = _build_preview_for_vlm(
310+
resized_for_preview, metadata_paths=file_paths
311+
)
304312
state.last_preview_path = preview_path
305313
state.last_image_meta = meta_text
306314
except Exception as e:
307315
log.warning("Preview build failed: %r", e)
308316
state.last_preview_path = None
309317
state.last_image_meta = None
318+
finally:
319+
for tmp in resize_temps:
320+
try:
321+
os.unlink(tmp)
322+
except Exception:
323+
pass
310324

311325
# ========================================================================
312326
# Run agent

src/ai_agent/utils/previews.py

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -72,33 +72,32 @@ def resize_uploaded_image(
7272
return path # already within bounds – no work needed
7373

7474
# thumbnail() shrinks in-place preserving aspect ratio, never upscales.
75-
img = opened_img.copy()
76-
77-
img.thumbnail((max_width, max_height), Image.Resampling.LANCZOS)
78-
79-
# Persist transparency for PNG/WebP; flatten to RGB for JPEG.
80-
if ext in (".jpg", ".jpeg"):
81-
if img.mode in ("RGBA", "P", "LA"):
82-
img = img.convert("RGB")
83-
suffix, fmt, save_kw = ".jpg", "JPEG", {"quality": 85, "optimize": True}
84-
elif ext == ".webp":
85-
suffix, fmt, save_kw = ".webp", "WEBP", {"quality": 85}
86-
else:
87-
# Preserve original format and extension so downstream format
88-
# detection (e.g. detect_ext_token) is not misled by a .png suffix.
89-
fmt = _PIL_FORMAT_MAP.get(ext, "PNG")
90-
suffix = ext if fmt != "PNG" else ".png"
91-
save_kw = {}
92-
93-
fd, tmp_path = tempfile.mkstemp(suffix=suffix)
94-
os.close(fd)
95-
img.save(tmp_path, format=fmt, **save_kw)
96-
97-
log.debug(
98-
"Resized upload %s from %dx%d → %dx%d (saved to %s)",
99-
path, orig_w, orig_h, img.width, img.height, tmp_path,
100-
)
101-
return tmp_path
75+
# Do everything inside the with-block to avoid a full-size copy.
76+
opened_img.thumbnail((max_width, max_height), Image.Resampling.LANCZOS)
77+
78+
# Persist transparency for PNG/WebP; flatten to RGB for JPEG.
79+
if ext in (".jpg", ".jpeg"):
80+
save_img = opened_img.convert("RGB") if opened_img.mode in ("RGBA", "P", "LA") else opened_img
81+
suffix, fmt, save_kw = ".jpg", "JPEG", {"quality": 85, "optimize": True}
82+
elif ext == ".webp":
83+
save_img, suffix, fmt, save_kw = opened_img, ".webp", "WEBP", {"quality": 85}
84+
else:
85+
# Preserve original format and extension so downstream format
86+
# detection (e.g. detect_ext_token) is not misled by a .png suffix.
87+
save_img = opened_img
88+
fmt = _PIL_FORMAT_MAP.get(ext, "PNG")
89+
suffix = ext if fmt != "PNG" else ".png"
90+
save_kw = {}
91+
92+
fd, tmp_path = tempfile.mkstemp(suffix=suffix)
93+
os.close(fd)
94+
save_img.save(tmp_path, format=fmt, **save_kw)
95+
96+
log.debug(
97+
"Resized upload %s from %dx%d → %dx%d (saved to %s)",
98+
path, orig_w, orig_h, save_img.width, save_img.height, tmp_path,
99+
)
100+
return tmp_path
102101

103102
except Exception:
104103
log.warning("resize_uploaded_image: could not resize %s; using original", path, exc_info=True)

0 commit comments

Comments
 (0)