Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5923781
(feat:attach) warning for error, progress, removal
ManishMadan2882 Apr 3, 2025
29c8996
Merge branch 'main' of https://github.com/manishmadan2882/docsgpt
ManishMadan2882 Apr 3, 2025
bdac2ff
Merge branch 'main' of https://github.com/arc53/DocsGPT
actions-user Apr 5, 2025
e4945b4
(feat:files) link attachment to openai_api
ManishMadan2882 Apr 6, 2025
9d70032
Merge branch 'main' of https://github.com/manishmadan2882/docsgpt
ManishMadan2882 Apr 6, 2025
a37bd76
(feat:storeAttach) store in inputs, raise errors from worker
ManishMadan2882 Apr 6, 2025
244c9b9
(fix:attach) pass attachment docs as it is
ManishMadan2882 Apr 6, 2025
a651e6e
Merge branch 'main' of https://github.com/arc53/DocsGPT
actions-user Apr 7, 2025
1f3d1cc
(feat:attach) handle unsupported attachments
ManishMadan2882 Apr 7, 2025
0c11381
(feat:attch) store file mime type
ManishMadan2882 Apr 7, 2025
0c68815
Merge branch 'main' of https://github.com/manishmadan2882/docsgpt
ManishMadan2882 Apr 7, 2025
051841e
Merge branch 'main' of https://github.com/arc53/DocsGPT
actions-user Apr 8, 2025
5421bc1
(feat:attach) extend support for imgs
ManishMadan2882 Apr 8, 2025
cd7bbb4
(fix:popups) minor hover
ManishMadan2882 Apr 8, 2025
55bd90f
Merge branch 'main' of https://github.com/manishmadan2882/docsgpt
ManishMadan2882 Apr 8, 2025
ed3af2f
Merge branch 'main' of https://github.com/arc53/DocsGPT
actions-user Apr 9, 2025
dd9ea46
(feat:attach) strategy specific to google genai
ManishMadan2882 Apr 9, 2025
456784d
Merge branch 'main' of https://github.com/manishmadan2882/docsgpt
ManishMadan2882 Apr 9, 2025
6cb4577
(feat:input) hotkey for sources open
ManishMadan2882 Apr 9, 2025
b4c6b2b
(feat:utils) getOS, isTouchDevice
ManishMadan2882 Apr 9, 2025
2922577
(refactor:attach) centralize attachment state
ManishMadan2882 Apr 9, 2025
dfe6a8d
(feat:attach) simplify the format for files
ManishMadan2882 Apr 10, 2025
b468e0c
(fix:generation) attach + tools
ManishMadan2882 Apr 13, 2025
231b792
fix: streaming with tools google and openai halfway
dartpain Apr 14, 2025
5b77f38
fix: maybe
dartpain Apr 14, 2025
8b05401
(Feat:input) sleek attachment pills
ManishMadan2882 Apr 14, 2025
0293445
fix: remove comment
dartpain Apr 14, 2025
ad610d2
fix: lint ruff
dartpain Apr 14, 2025
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
11 changes: 7 additions & 4 deletions application/agents/classic_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,13 @@
):
yield {"answer": resp.message.content}
else:
completion = self.llm.gen_stream(
model=self.gpt_model, messages=messages, tools=self.tools
)
for line in completion:
# completion = self.llm.gen_stream(
# model=self.gpt_model, messages=messages, tools=self.tools
# )
# log type of resp
logger.info(f"Response type: {type(resp)}")
logger.info(f"Response: {resp}")
for line in resp:

Check warning on line 53 in application/agents/classic_agent.py

View check run for this annotation

Codecov / codecov/patch

application/agents/classic_agent.py#L51-L53

Added lines #L51 - L53 were not covered by tests
if isinstance(line, str):
yield {"answer": line}

Expand Down
69 changes: 58 additions & 11 deletions application/agents/llm_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
@abstractmethod
def handle_response(self, agent, resp, tools_dict, messages, attachments=None, **kwargs):
pass

def prepare_messages_with_attachments(self, agent, messages, attachments=None):
"""
Prepare messages with attachment content if available.
Expand All @@ -33,15 +33,53 @@

logger.info(f"Preparing messages with {len(attachments)} attachments")

# Check if the LLM has its own custom attachment handling implementation
if hasattr(agent.llm, "prepare_messages_with_attachments") and agent.llm.__class__.__name__ != "BaseLLM":
logger.info(f"Using {agent.llm.__class__.__name__}'s own prepare_messages_with_attachments method")
return agent.llm.prepare_messages_with_attachments(messages, attachments)
supported_types = agent.llm.get_supported_attachment_types()

Check warning on line 36 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L36

Added line #L36 was not covered by tests

supported_attachments = []
unsupported_attachments = []

Check warning on line 39 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L38-L39

Added lines #L38 - L39 were not covered by tests

for attachment in attachments:
mime_type = attachment.get('mime_type')
if not mime_type:
import mimetypes
file_path = attachment.get('path')
if file_path:
mime_type = mimetypes.guess_type(file_path)[0] or 'application/octet-stream'

Check warning on line 47 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L41-L47

Added lines #L41 - L47 were not covered by tests
else:
unsupported_attachments.append(attachment)
continue

Check warning on line 50 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L49-L50

Added lines #L49 - L50 were not covered by tests

if mime_type in supported_types:
supported_attachments.append(attachment)

Check warning on line 53 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L52-L53

Added lines #L52 - L53 were not covered by tests
else:
unsupported_attachments.append(attachment)

Check warning on line 55 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L55

Added line #L55 was not covered by tests

# Process supported attachments with the LLM's custom method
prepared_messages = messages
if supported_attachments:
logger.info(f"Processing {len(supported_attachments)} supported attachments with {agent.llm.__class__.__name__}'s method")
prepared_messages = agent.llm.prepare_messages_with_attachments(messages, supported_attachments)

Check warning on line 61 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L58-L61

Added lines #L58 - L61 were not covered by tests

# Process unsupported attachments with the default method
if unsupported_attachments:
logger.info(f"Processing {len(unsupported_attachments)} unsupported attachments with default method")
prepared_messages = self._append_attachment_content_to_system(prepared_messages, unsupported_attachments)

Check warning on line 66 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L64-L66

Added lines #L64 - L66 were not covered by tests

return prepared_messages

Check warning on line 68 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L68

Added line #L68 was not covered by tests

def _append_attachment_content_to_system(self, messages, attachments):
"""
Default method to append attachment content to the system prompt.

# Otherwise, append attachment content to the system prompt
Args:
messages (list): List of message dictionaries.
attachments (list): List of attachment dictionaries with content.

Returns:
list: Messages with attachment context added to the system prompt.
"""
prepared_messages = messages.copy()

# Build attachment content string
attachment_texts = []
for attachment in attachments:
logger.info(f"Adding attachment {attachment.get('id')} to context")
Expand Down Expand Up @@ -122,12 +160,13 @@
return resp

else:

text_buffer = ""

Check warning on line 163 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L163

Added line #L163 was not covered by tests
while True:
tool_calls = {}
for chunk in resp:
if isinstance(chunk, str) and len(chunk) > 0:
return
yield chunk
continue

Check warning on line 169 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L168-L169

Added lines #L168 - L169 were not covered by tests
elif hasattr(chunk, "delta"):
chunk_delta = chunk.delta

Expand Down Expand Up @@ -206,12 +245,17 @@
}
)
tool_calls = {}
if hasattr(chunk_delta, "content") and chunk_delta.content:

Check warning on line 248 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L248

Added line #L248 was not covered by tests
# Add to buffer or yield immediately based on your preference
text_buffer += chunk_delta.content
yield text_buffer
text_buffer = ""

Check warning on line 252 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L250-L252

Added lines #L250 - L252 were not covered by tests

if (
hasattr(chunk, "finish_reason")
and chunk.finish_reason == "stop"
):
return
return resp

Check warning on line 258 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L258

Added line #L258 was not covered by tests
elif isinstance(chunk, str) and len(chunk) == 0:
continue

Expand All @@ -227,7 +271,7 @@
from google.genai import types

messages = self.prepare_messages_with_attachments(agent, messages, attachments)

while True:
if not stream:
response = agent.llm.gen(
Expand Down Expand Up @@ -298,6 +342,9 @@
"content": [function_response_part.to_json_dict()],
}
)
else:
tool_call_found = False
yield result

Check warning on line 347 in application/agents/llm_handler.py

View check run for this annotation

Codecov / codecov/patch

application/agents/llm_handler.py#L346-L347

Added lines #L346 - L347 were not covered by tests

if not tool_call_found:
return response
Expand Down
7 changes: 1 addition & 6 deletions application/api/answer/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -835,12 +835,7 @@
})

if attachment_doc:
attachments.append({
"id": str(attachment_doc["_id"]),
"content": attachment_doc["content"],
"token_count": attachment_doc.get("token_count", 0),
"path": attachment_doc.get("path", "")
})
attachments.append(attachment_doc)

Check warning on line 838 in application/api/answer/routes.py

View check run for this annotation

Codecov / codecov/patch

application/api/answer/routes.py#L838

Added line #L838 was not covered by tests
except Exception as e:
logger.error(f"Error retrieving attachment {attachment_id}: {e}")

Expand Down
25 changes: 14 additions & 11 deletions application/api/user/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2506,23 +2506,26 @@
user = secure_filename(decoded_token.get("sub"))

try:
attachment_id = ObjectId()

Check warning on line 2509 in application/api/user/routes.py

View check run for this annotation

Codecov / codecov/patch

application/api/user/routes.py#L2509

Added line #L2509 was not covered by tests
original_filename = secure_filename(file.filename)
folder_name = original_filename
save_dir = os.path.join(current_dir, settings.UPLOAD_FOLDER, user, "attachments",folder_name)

save_dir = os.path.join(

Check warning on line 2512 in application/api/user/routes.py

View check run for this annotation

Codecov / codecov/patch

application/api/user/routes.py#L2512

Added line #L2512 was not covered by tests
current_dir,
settings.UPLOAD_FOLDER,
user,
"attachments",
str(attachment_id)
)
os.makedirs(save_dir, exist_ok=True)
# Create directory structure: user/attachments/filename/

file_path = os.path.join(save_dir, original_filename)

# Handle filename conflicts
if os.path.exists(file_path):
name_parts = os.path.splitext(original_filename)
timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
new_filename = f"{name_parts[0]}_{timestamp}{name_parts[1]}"
file_path = os.path.join(save_dir, new_filename)
original_filename = new_filename

file.save(file_path)
file_info = {"folder": folder_name, "filename": original_filename}
file_info = {

Check warning on line 2525 in application/api/user/routes.py

View check run for this annotation

Codecov / codecov/patch

application/api/user/routes.py#L2525

Added line #L2525 was not covered by tests
"filename": original_filename,
"attachment_id": str(attachment_id)
}
current_app.logger.info(f"Saved file: {file_path}")

# Start async task to process single file
Expand Down
9 changes: 9 additions & 0 deletions application/llm/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,12 @@

def _supports_tools(self):
raise NotImplementedError("Subclass must implement _supports_tools method")

def get_supported_attachment_types(self):
"""
Return a list of MIME types supported by this LLM for file uploads.

Returns:
list: List of supported MIME types
"""
return [] # Default: no attachments supported

Check warning on line 66 in application/llm/base.py

View check run for this annotation

Codecov / codecov/patch

application/llm/base.py#L66

Added line #L66 was not covered by tests
Loading