Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
2eb44e7
feat: intial web_platform offering
AlankritVerma01 Oct 20, 2025
ffc9dac
refactor: update ArcPlusClassifier initialization and enhance tool lo…
AlankritVerma01 Oct 20, 2025
f4a92d1
feat: enhance tool management and chat response streaming
AlankritVerma01 Oct 20, 2025
c47e1cf
chore: remove comprehensive agent integration tests
AlankritVerma01 Oct 20, 2025
ea01dea
feat: enhance chat processor and UI components for better tool output…
AlankritVerma01 Oct 20, 2025
2e01b4a
feat: enhance chat and message APIs with computed fields
AlankritVerma01 Oct 20, 2025
6fcdb71
feat(utils): add centralized device management utility
AlankritVerma01 Oct 23, 2025
f71be09
refactor(tools): migrate classification tools to Pydantic V2
AlankritVerma01 Oct 23, 2025
5d06ded
refactor(tools): migrate VQA tools to Pydantic V2
AlankritVerma01 Oct 23, 2025
59a5d56
refactor(tools): migrate segmentation tools to Pydantic V2
AlankritVerma01 Oct 23, 2025
fd81ade
refactor(tools): migrate generation tools to Pydantic V2
AlankritVerma01 Oct 23, 2025
19cff49
fix(tools): add MAIRA-2 grounding tool compatibility patches
AlankritVerma01 Oct 23, 2025
407a8c9
fix(tools): update DuckDuckGo search tool for v4.4.3 compatibility
AlankritVerma01 Oct 23, 2025
9dd5a67
refactor(backend): improve chat processing and tool management
AlankritVerma01 Oct 23, 2025
3f62221
refactor(frontend): improve UI/UX and code quality
AlankritVerma01 Oct 23, 2025
07c2401
chore: update dependencies and startup scripts
AlankritVerma01 Oct 23, 2025
c80cfbf
test: add comprehensive tool testing
AlankritVerma01 Oct 23, 2025
81bea6d
feat(backend): implement Server-Sent Events for tool loading
AlankritVerma01 Oct 23, 2025
d836838
feat(frontend): add SSE hook and progress UI for tool loading
AlankritVerma01 Oct 23, 2025
72a7783
fix(frontend): replace polling with SSE for tool loading
AlankritVerma01 Oct 23, 2025
f455b18
fix(frontend): critical SSE fixes - memory leak, API config, multiple…
AlankritVerma01 Oct 23, 2025
b521659
fix(frontend): correct token retrieval for SSE authentication
AlankritVerma01 Oct 23, 2025
bc6a8b1
fix(backend): add special initialization for tools requiring config
AlankritVerma01 Oct 23, 2025
ea52078
fix(backend): set Cohere and Pinecone env vars for RAG tool
AlankritVerma01 Oct 23, 2025
b086a54
feat(backend): add bulk loading functionality for tools
AlankritVerma01 Oct 26, 2025
e0d28cc
fix(backend): improve logging and device handling in tool management
AlankritVerma01 Oct 27, 2025
94a9bb1
feat(backend): enhance security and configuration management
AlankritVerma01 Oct 27, 2025
c7547a8
fix(frontend): refine tool loading logic and improve API integration
AlankritVerma01 Oct 27, 2025
3587d2e
feat(frontend): enhance tool loading with real-time SSE progress and …
AlankritVerma01 Oct 27, 2025
2ebd7e3
refactor(backend): update system API routes and validation logic
AlankritVerma01 Oct 27, 2025
4fb77c1
fix(frontend): update API secret handling in ApiSecretGate component
AlankritVerma01 Oct 27, 2025
657b17a
fix(backend): allow CORS preflight requests in API secret validation
AlankritVerma01 Oct 27, 2025
097478e
fix(backend): allow SSE endpoints to bypass API secret validation
AlankritVerma01 Oct 27, 2025
fea4f0b
fix(backend): update access token expiration and enhance security for…
AlankritVerma01 Oct 27, 2025
009c074
fix(segmentation): update prompt fields for compatibility and clarity
AlankritVerma01 Oct 27, 2025
b354363
fix(segmentation): remove json_schema_extra for prompt fields
AlankritVerma01 Oct 27, 2025
b2a0203
fix(vqa): remove json_schema_extra from image_paths field for clarity
AlankritVerma01 Oct 27, 2025
5f71514
fix(config): correct file extension validation and sync limits
AlankritVerma01 Oct 29, 2025
d05412a
feat(validation): add comprehensive input validation
AlankritVerma01 Oct 29, 2025
98896e6
fix(sse): correct event type and add error handling
AlankritVerma01 Oct 29, 2025
ba17344
fix(api): implement snake_case to camelCase mapping
AlankritVerma01 Oct 29, 2025
6c4aab5
fix(backend): correct tool display name access
AlankritVerma01 Oct 29, 2025
9d9c59a
feat(chat): connect image upload and display
AlankritVerma01 Oct 29, 2025
9f59846
feat(chat): connect chat menu actions and fix state management
AlankritVerma01 Oct 29, 2025
03de915
feat(cleanup): add file cleanup on patient and chat deletion
AlankritVerma01 Oct 29, 2025
dbfc7a6
feat(db): configure SQLite for multi-user concurrency
AlankritVerma01 Oct 29, 2025
273869f
feat(concurrency): add thread safety locks to ToolManager
AlankritVerma01 Oct 29, 2025
917a606
test(backend): add concurrency test suite
AlankritVerma01 Oct 29, 2025
68387e2
feat(memory): add chat memory management system
AlankritVerma01 Oct 29, 2025
105831e
fix(scans): add missing settings import
AlankritVerma01 Oct 29, 2025
d103ed1
fix(deps): add missing psutil dependency
AlankritVerma01 Oct 29, 2025
3c13462
chore(config): add database files to gitignore and psutil to environm…
AlankritVerma01 Oct 29, 2025
e01d99c
fix(schemas): allow empty content in MessageResponse for failed assis…
AlankritVerma01 Oct 29, 2025
856cef1
fix(tools): add explicit json_schema_extra for List parameters to fix…
AlankritVerma01 Oct 29, 2025
74a9840
refactor(tools): update prompt_coords and organs fields to use defaul…
AlankritVerma01 Oct 29, 2025
d905fcb
feat(chat): enhance image handling in ChatProcessor
AlankritVerma01 Oct 29, 2025
24fbcc2
fix(tool-manager): serialize tool loading to prevent Python import de…
AlankritVerma01 Oct 29, 2025
f93493e
feat(tools): add schema validation script and integrate into startup
AlankritVerma01 Oct 29, 2025
1006c67
feat(startup): integrate schema validation into backend startup script
AlankritVerma01 Oct 29, 2025
204b0ba
feat(tools): enhance model loading and error handling across tools
AlankritVerma01 Oct 30, 2025
689df2f
fix: prevent duplicate SystemMessage errors in Google Gemini
AlankritVerma01 Oct 30, 2025
f345fa3
fix: whitelist /uploads/ path for direct image access
AlankritVerma01 Oct 30, 2025
48c400d
fix: correct type definitions for tool execution data
AlankritVerma01 Oct 30, 2025
cb3ff45
fix: add snake_case to camelCase transformation in tool API
AlankritVerma01 Oct 30, 2025
3faac42
feat: add ToolOutputsSidebar component for detailed tool execution view
AlankritVerma01 Oct 30, 2025
d1662c7
feat: integrate ToolOutputsSidebar into chat interface
AlankritVerma01 Oct 30, 2025
a1a7703
fix: add edge case handling and error recovery to ImageModal
AlankritVerma01 Oct 30, 2025
38c5751
chore: remove obsolete ToolHistoryDrawer component
AlankritVerma01 Oct 30, 2025
4cd17d3
fix: correct MemoryStats type to match backend API response
AlankritVerma01 Oct 30, 2025
d5a5d6e
feat: add image preview with delete functionality in chat input
AlankritVerma01 Oct 30, 2025
d0ab086
fix(agent): add safety checks for empty messages array
AlankritVerma01 Oct 30, 2025
29d48a1
fix(chat-processor): prevent crash on empty agent messages during str…
AlankritVerma01 Oct 30, 2025
7935141
feat(chat-input): add comprehensive error handling and UX improvements
AlankritVerma01 Oct 30, 2025
1ada596
fix(chat-interface): implement proper stream cleanup and abort handling
AlankritVerma01 Oct 30, 2025
2d69b70
fix(message): replace innerHTML with proper React state for image errors
AlankritVerma01 Oct 30, 2025
7028cdf
refactor(message-activity): improve code maintainability and fix null…
AlankritVerma01 Oct 30, 2025
1ecc69b
feat(ui): add graceful error handling and scroll locking
AlankritVerma01 Oct 30, 2025
5e78677
fix(scan-gallery): add error handling for medical scan images
AlankritVerma01 Oct 30, 2025
c4b350c
fix(tool-outputs): add image error handling and fix null checks
AlankritVerma01 Oct 30, 2025
b4bd502
fix(tool-sidebar): improve error handling and fix dependency issues
AlankritVerma01 Oct 30, 2025
d10f509
refactor(api): remove unused getToolExecutions function
AlankritVerma01 Oct 30, 2025
10d5b5e
chore: small fix
AlankritVerma01 Oct 30, 2025
e16473e
Fix semaphore leak during backend shutdown
AlankritVerma01 Oct 30, 2025
37c6942
Enhance file path handling and response formatting
AlankritVerma01 Oct 30, 2025
88bd0af
Implement eager-loading of tools at startup, excluding X-ray generator
AlankritVerma01 Oct 30, 2025
68497f3
Enhance chat processor and UI for tool execution tracking
AlankritVerma01 Oct 31, 2025
9158170
feat(backend): add Pydantic response models for memory and tools APIs
AlankritVerma01 Oct 31, 2025
cc0c067
feat(frontend): add OpenAPI infrastructure with type-safe client
AlankritVerma01 Oct 31, 2025
e255f14
refactor(frontend): migrate all API modules to OpenAPI client
AlankritVerma01 Oct 31, 2025
549b569
refactor(frontend): update components for strict type safety
AlankritVerma01 Oct 31, 2025
689cb19
feat(frontend): add OpenAPI tooling and validation infrastructure
AlankritVerma01 Oct 31, 2025
49f04d7
fix(tools): repair tool schema validation script
AlankritVerma01 Oct 31, 2025
bcab40b
fix(frontend): critical SSE streaming architecture fix
AlankritVerma01 Oct 31, 2025
57bc7bb
refactor(frontend): enhance chat input and tool outputs components
AlankritVerma01 Oct 31, 2025
f8ec1dc
refactor(chat): improve image extraction logic in Message component
AlankritVerma01 Oct 31, 2025
30c6250
refactor(chat): enhance message parsing in ChatProcessor
AlankritVerma01 Nov 1, 2025
08da332
refactor(frontend): streamline ToolOutputsSidebar and ToolResultCard …
AlankritVerma01 Nov 1, 2025
c1eab8b
feat(chat): enhance message rendering with Markdown support
AlankritVerma01 Nov 1, 2025
7df3c72
refactor(chat): clean up image path handling in extractFinalImages fu…
AlankritVerma01 Nov 1, 2025
3ce68fc
feat(tools): add comprehensive tool validation script
AlankritVerma01 Nov 1, 2025
5390ea5
feat(tools): enhance ArcPlusClassifierTool with model weights handling
AlankritVerma01 Nov 3, 2025
66f2445
feat(auth): add headers to registration and login API calls
AlankritVerma01 Nov 3, 2025
31f27a6
fix(tools): ensure consistent tensor data types across models
AlankritVerma01 Nov 3, 2025
f3e9e61
chore(frontend): simplify vercel.json configuration
AlankritVerma01 Nov 3, 2025
5b9f22f
Fix tool loading issues and implement sequential loading strategy
AlankritVerma01 Nov 4, 2025
f7eeda2
Simplify MAIRA-2 model loading - use AutoModel with trust_remote_code
AlankritVerma01 Nov 4, 2025
9957ab6
Add fallback loading strategy for MAIRA-2 model
AlankritVerma01 Nov 4, 2025
5083c0b
Attempt to load MAIRA-2 with config-based approach
AlankritVerma01 Nov 4, 2025
b6bd241
Fix tool errors for image analysis
AlankritVerma01 Nov 4, 2025
8636cf1
Fix multiple tool execution issues
AlankritVerma01 Nov 5, 2025
d150466
Enhance tool management and image processing capabilities
AlankritVerma01 Nov 5, 2025
0adffc6
Refactor ToolManager and ImageResolvingToolWrapper for improved compa…
AlankritVerma01 Nov 5, 2025
69034f5
fix: ensure tool execution image paths have leading slash for fronten…
AlankritVerma01 Nov 5, 2025
9435395
chore: temporarily disable image wrapper/registry imports
AlankritVerma01 Nov 5, 2025
d0d1349
fix: resolve black image display issue in chat messages
AlankritVerma01 Nov 5, 2025
532c4ae
debug: enhance image error messages in tool outputs sidebar
AlankritVerma01 Nov 5, 2025
f3a24dd
feat: add support for temporary file handling in backend
AlankritVerma01 Nov 8, 2025
58d4967
refactor: improve chat message and tool result card styles
AlankritVerma01 Nov 9, 2025
b8fc897
Merge branch 'dev' into feat/web-platform
AlankritVerma01 Dec 5, 2025
1871d81
feat: add setup script and test scripts for MedRAX tools
AlankritVerma01 Dec 5, 2025
187973d
chore: update dependencies and configuration files for backend
AlankritVerma01 Dec 5, 2025
df9d93e
chore: remove MedRAX dependency from configuration files
AlankritVerma01 Dec 5, 2025
6bb1283
chore: update huggingface-hub and tokenizers dependencies
AlankritVerma01 Dec 5, 2025
99884f9
chore: add python-jose dependency for JWT handling
AlankritVerma01 Dec 5, 2025
82453a8
fix: improve handling of embed token weights in LlavaMetaForCausalLM
AlankritVerma01 Dec 5, 2025
dacd5de
fix: update dtype parameter in XRayPhraseGroundingTool model loading
AlankritVerma01 Dec 5, 2025
41cb488
fix: normalize raw tool output handling in ToolResultCard component
AlankritVerma01 Dec 8, 2025
4e1857f
fix: enhance scan retrieval logic in ChatProcessor
AlankritVerma01 Dec 8, 2025
8777d69
fix: synchronize chat list and sidebar state in ChatInterface
AlankritVerma01 Dec 8, 2025
fa57fe2
feat: enhance CheXagent VQA tool with bounding box visualization
AlankritVerma01 Dec 8, 2025
e18fa4e
refactor: update MedGemma VQA tool for direct model integration
AlankritVerma01 Dec 8, 2025
3250318
chore: update Next.js to version 15.5.7 and enhance MarkdownRenderer …
AlankritVerma01 Dec 8, 2025
e66175f
feat: enhance image handling in ChatProcessor and file utilities
AlankritVerma01 Dec 8, 2025
01d793e
chore: update .gitignore and refine frontend build configurations
AlankritVerma01 Dec 28, 2025
14bbd02
chore: update backend startup script to use dynamic port configuration
AlankritVerma01 Feb 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
Expand Down Expand Up @@ -61,6 +60,12 @@ local_settings.py
db.sqlite3
db.sqlite3-journal

# SQLite database files (including WAL mode files)
*.db
*.db-wal
*.db-shm
*.db-journal

# Flask stuff:
instance/
.webassets-cache
Expand Down
6 changes: 6 additions & 0 deletions benchmarking/system_prompts.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ You can make multiple tool calls in parallel or in sequence as needed for compre
Think critically about and criticize the tool outputs.
If you need to look up some information before asking a follow up question, you are allowed to do that.

CRITICAL - FILE PATH HANDLING:
- When you receive image paths in XML tags like <image_path id="1">path/to/file.jpg</image_path>, you MUST copy the EXACT path from between the tags
- Do NOT type paths from memory, abbreviate, or modify the UUIDs in any way
- Copy the ENTIRE path character-for-character including all hyphens and alphanumeric sequences
- A single character error in a UUID will cause tool calls to fail

CITATION REQUIREMENTS:
- When referencing information from RAG and/or web search tools, ALWAYS include numbered citations [1], [2], [3], etc.
- Use citations immediately after making claims or statements based on the above tool results.
Expand Down
9 changes: 7 additions & 2 deletions medrax/agent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,10 @@ def has_tool_calls(self, state: AgentState) -> bool:
Returns:
bool: True if tool calls exist, False otherwise.
"""
response = state["messages"][-1]
return len(response.tool_calls) > 0
messages = state["messages"]
if not messages:
return False

response = messages[-1]
# Safely check for tool_calls attribute
return hasattr(response, 'tool_calls') and len(response.tool_calls) > 0
6 changes: 6 additions & 0 deletions medrax/docs/system_prompts.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ You can make multiple tool calls in parallel or in sequence as needed for compre
Think critically about and criticize the tool outputs.
If you need to look up some information before asking a follow up question, you are allowed to do that.

CRITICAL - FILE PATH HANDLING:
- When you receive image paths in XML tags like <image_path id="1">path/to/file.jpg</image_path>, you MUST copy the EXACT path from between the tags
- Do NOT type paths from memory, abbreviate, or modify the UUIDs in any way
- Copy the ENTIRE path character-for-character including all hyphens and alphanumeric sequences
- A single character error in a UUID will cause tool calls to fail

CITATION REQUIREMENTS:
- When referencing information from RAG and/or web search tools, ALWAYS include numbered citations [1], [2], [3], etc.
- Use citations immediately after making claims or statements based on the above tool results.
Expand Down
33 changes: 21 additions & 12 deletions medrax/llava/model/builder.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import Optional
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
import torch
from medrax.llava.model import LlavaMistralForCausalLM
Expand All @@ -15,17 +16,20 @@ def load_pretrained_model(
load_in_8bit=False,
load_in_4bit=True,
device="cuda",
cache_dir: str = "/model-weights",
cache_dir: Optional[str] = None,
low_cpu_mem_usage=True,
torch_dtype=torch.bfloat16,
):

kwargs = {}

if device != "cuda":
# Device mapping strategy:
# - CUDA: Use "auto" to let HuggingFace/Accelerate handle placement, avoiding meta-tensor issues
# - CPU/MPS: Use explicit device mapping for direct control
if device == "cuda":
kwargs["device_map"] = "auto"
else:
kwargs["device_map"] = {"": device}
# else:
# kwargs["device_map"] = "auto"

if load_in_8bit:
kwargs["load_in_8bit"] = True
Expand All @@ -44,12 +48,16 @@ def load_pretrained_model(
# Load LLaVA model
if "mistral" in model_name.lower():
tokenizer = AutoTokenizer.from_pretrained(model_path, cache_dir=cache_dir)
# LLaVA-Med specific: Override to use explicit "cuda" mapping
# to ensure proper device placement for vision-language model
if device == "cuda":
kwargs["device_map"] = "cuda"
model = LlavaMistralForCausalLM.from_pretrained(
model_path,
low_cpu_mem_usage=low_cpu_mem_usage,
use_flash_attention_2=False,
# Disable low_cpu_mem_usage to avoid meta tensor errors during model loading
low_cpu_mem_usage=False,
cache_dir=cache_dir,
torch_dtype=torch_dtype,
attn_implementation="eager",
**kwargs,
)

Expand Down Expand Up @@ -110,11 +118,12 @@ def load_pretrained_model(
if not vision_tower.is_loaded:
vision_tower.load_model()

vision_tower.to(device=device, dtype=torch_dtype)
model.model.mm_projector.to(device=device, dtype=torch_dtype)

if not (load_in_4bit or load_in_8bit):
model.to(device=device, dtype=torch_dtype)
# Skip manual device placement when using auto device mapping to prevent conflicts
if kwargs.get("device_map") != "auto":
vision_tower.to(device=device, dtype=torch_dtype)
model.model.mm_projector.to(device=device, dtype=torch_dtype)
if not (load_in_4bit or load_in_8bit):
model.to(device=device, dtype=torch_dtype)

image_processor = vision_tower.image_processor

Expand Down
54 changes: 36 additions & 18 deletions medrax/llava/model/llava_arch.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,28 @@ def initialize_vision_modules(self, model_args, fsdp=None, embed_tokens=None):
def get_w(weights, keyword):
return {k.split(keyword + ".")[1]: v for k, v in weights.items() if keyword in k}

mm_projector_weights = torch.load(pretrain_mm_mlp_adapter, map_location="cpu")
self.mm_projector.load_state_dict(get_w(mm_projector_weights, "mm_projector"))
try:
mm_projector_weights = torch.load(pretrain_mm_mlp_adapter, map_location="cpu")
self.mm_projector.load_state_dict(get_w(mm_projector_weights, "mm_projector"))
except Exception as e:
print(
f"Warning: failed to load mm_projector weights from '{pretrain_mm_mlp_adapter}' due to: {e}. Continuing without these optional weights."
)

# also load additional learnable parameters during feature alignment
checkpoint_folder = os.path.dirname(pretrain_mm_mlp_adapter)
ckpts = glob(f"{checkpoint_folder}/checkpoint-*", recursive=False)
if len(ckpts) > 0:
vision_module_weights = torch.load(f"{ckpts[-1]}/mm_projector.bin", map_location="cpu")
model_dict = get_w(vision_module_weights, "vision_tower")
print(f"Loading vision module weights from {ckpts[-1]}/mm_projector.bin")
# print keys in model_dict
print(f"Loaded keys: {model_dict.keys()}")
self.vision_tower.load_state_dict(model_dict, strict=False)
try:
vision_module_weights = torch.load(f"{ckpts[-1]}/mm_projector.bin", map_location="cpu")
model_dict = get_w(vision_module_weights, "vision_tower")
print(f"Loading vision module weights from {ckpts[-1]}/mm_projector.bin")
print(f"Loaded keys: {model_dict.keys()}")
self.vision_tower.load_state_dict(model_dict, strict=False)
except Exception as e:
print(
f"Warning: failed to load optional vision module weights from '{ckpts[-1]}/mm_projector.bin' due to: {e}. Skipping."
)


class LlavaMetaForCausalLM(ABC):
Expand Down Expand Up @@ -351,17 +360,26 @@ def initialize_vision_tokenizer(self, model_args, tokenizer):
p.requires_grad = False

if model_args.pretrain_mm_mlp_adapter:
mm_projector_weights = torch.load(model_args.pretrain_mm_mlp_adapter, map_location="cpu")
embed_tokens_weight = mm_projector_weights["model.embed_tokens.weight"]
assert num_new_tokens == 2
if input_embeddings.shape == embed_tokens_weight.shape:
input_embeddings[-num_new_tokens:] = embed_tokens_weight[-num_new_tokens:]
elif embed_tokens_weight.shape[0] == num_new_tokens:
input_embeddings[-num_new_tokens:] = embed_tokens_weight
else:
raise ValueError(
f"Unexpected embed_tokens_weight shape. Pretrained: {embed_tokens_weight.shape}. Current: {input_embeddings.shape}. Numer of new tokens: {num_new_tokens}."
embed_tokens_weight = None
try:
mm_projector_weights = torch.load(model_args.pretrain_mm_mlp_adapter, map_location="cpu")
embed_tokens_weight = mm_projector_weights["model.embed_tokens.weight"]
except Exception as e:
print(
f"Warning: failed to load embed token weights from '{model_args.pretrain_mm_mlp_adapter}' due to: {e}. "
"Continuing with default-initialized tokens."
)

if embed_tokens_weight is not None:
assert num_new_tokens == 2
if input_embeddings.shape == embed_tokens_weight.shape:
input_embeddings[-num_new_tokens:] = embed_tokens_weight[-num_new_tokens:]
elif embed_tokens_weight.shape[0] == num_new_tokens:
input_embeddings[-num_new_tokens:] = embed_tokens_weight
else:
raise ValueError(
f"Unexpected embed_tokens_weight shape. Pretrained: {embed_tokens_weight.shape}. Current: {input_embeddings.shape}. Numer of new tokens: {num_new_tokens}."
)
elif model_args.mm_use_im_patch_token:
if model_args.tune_mm_mlp_adapter:
for p in self.get_input_embeddings().parameters():
Expand Down
5 changes: 4 additions & 1 deletion medrax/tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
from .segmentation import *
from .vqa import *
from .grounding import *
from .xray_generation import *
# Avoid importing heavy generation pipeline at package import time to prevent
# unnecessary diffusers/triton dependencies during unrelated tool loads.
# Import `ChestXRayGeneratorTool` directly from `medrax.tools.xray_generation`
# where needed instead of exposing it here.
from .dicom import *
from .utils import *
from .rag import *
Expand Down
63 changes: 29 additions & 34 deletions medrax/tools/browsing/duckduckgo.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
CallbackManagerForToolRun,
)
from langchain_core.tools import BaseTool
from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, ConfigDict

try:
from duckduckgo_search import DDGS
Expand Down Expand Up @@ -115,30 +115,32 @@ def _perform_search_sync(self, query: str, max_results: int = 5, region: str = "
logger.info(f"Performing web search: '{query}' (max_results={max_results}, region={region})")

try:
# Initialize DDGS with error handling
with DDGS() as ddgs:
# Perform the search
search_results = list(
ddgs.text(
keywords=query,
region=region,
safesearch="moderate",
timelimit=None,
max_results=max_results,
)
)

# Format results for the agent
formatted_results = []
for i, result in enumerate(search_results, 1):
formatted_result = {
"rank": i,
"title": result.get("title", "No title"),
"url": result.get("href", "No URL"),
"snippet": result.get("body", "No description available"),
"source": "DuckDuckGo",
}
formatted_results.append(formatted_result)
ddgs = DDGS()

search_results = list(ddgs.text(
keywords=query,
region=region,
safesearch="moderate",
max_results=max_results
))

if search_results is None:
logger.warning("DuckDuckGo returned None instead of results list")
search_results = []

formatted_results = []
for i, result in enumerate(search_results, 1):
if result is None or not isinstance(result, dict):
continue

formatted_result = {
"rank": i,
"title": result.get("title", result.get("t", "No title")),
"url": result.get("href", result.get("l", "No URL")),
"snippet": result.get("body", result.get("a", "No description available")),
"source": "DuckDuckGo",
}
formatted_results.append(formatted_result)

# Create summary for the agent
if formatted_results:
Expand All @@ -149,7 +151,6 @@ def _perform_search_sync(self, query: str, max_results: int = 5, region: str = "
else:
summary = f"No results found for '{query}'"

# Log successful completion
logger.info(f"Web search completed successfully: {len(formatted_results)} results")

return {
Expand Down Expand Up @@ -191,9 +192,7 @@ def _run(
run_manager: Callback manager (unused)

Returns:
Tuple[Dict[str, Any], Dict[str, Any]]: A tuple containing:
- output: Dictionary with search results
- metadata: Dictionary with execution metadata
Tuple[Dict[str, Any], Dict[str, Any]]: Output dictionary and metadata dictionary
"""
# Create metadata structure
metadata = {
Expand Down Expand Up @@ -249,9 +248,7 @@ async def _arun(
run_manager: Callback manager (unused)

Returns:
Tuple[Dict[str, Any], Dict[str, Any]]: A tuple containing:
- output: Dictionary with search results
- metadata: Dictionary with execution metadata
Tuple[Dict[str, Any], Dict[str, Any]]: Output dictionary and metadata dictionary
"""
# Try to get LangGraph stream writer for progress updates
writer = None
Expand Down Expand Up @@ -284,12 +281,10 @@ async def _arun(
}
)

# Use asyncio to run sync search in executor
loop = asyncio.get_event_loop()
result, metadata = await loop.run_in_executor(None, self._run, query, max_results, region)

if writer:
# Parse result to get count for progress update
results_count = result.get("results_count", 0)
writer(
{
Expand Down
3 changes: 2 additions & 1 deletion medrax/tools/browsing/web_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import requests
from bs4 import BeautifulSoup
from langchain_core.tools import BaseTool
from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, ConfigDict


class WebBrowserSchema(BaseModel):
Expand Down Expand Up @@ -77,6 +77,7 @@ class WebBrowserTool(BaseTool):
)
max_results: int = 5
args_schema: Type[BaseModel] = WebBrowserSchema
model_config = ConfigDict(arbitrary_types_allowed=True, protected_namespaces=())

def __init__(self, search_api_key: Optional[str] = None, search_engine_id: Optional[str] = None, **kwargs):
"""Initialize the web browser tool with optional search API credentials.
Expand Down
Loading