-
Notifications
You must be signed in to change notification settings - Fork 5
feature: introduce /share route for web widget #853
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
0314045
4e9498d
94e19c0
e2411ef
7b253ad
bff6628
489055e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,7 +9,7 @@ | |
| from django.conf import settings | ||
| from django.contrib.auth import get_user_model | ||
| from django.db import models | ||
| from django.db.models import OuterRef, QuerySet, Subquery | ||
| from django.db.models import OuterRef, Q, QuerySet, Subquery | ||
| from django.utils.text import Truncator | ||
|
|
||
| from bots.custom_fields import CustomURLField | ||
|
|
@@ -597,6 +597,59 @@ def __str__(self): | |
| return self.url | ||
|
|
||
|
|
||
| def db_msgs_to_api_json(msgs: list["Message"]) -> typing.Iterator[dict]: | ||
| from daras_ai_v2.bots import parse_bot_html | ||
| from routers.bots_api import MSG_ID_PREFIX | ||
|
|
||
| for msg in msgs: | ||
| msg: Message | ||
| images = list( | ||
| msg.attachments.filter( | ||
| metadata__mime_type__startswith="image/" | ||
| ).values_list("url", flat=True) | ||
| ) | ||
| audios = list( | ||
| msg.attachments.filter( | ||
| metadata__mime_type__startswith="audio/" | ||
| ).values_list("url", flat=True) | ||
| ) | ||
| audio = audios and audios[0] | ||
| if msg.role == CHATML_ROLE_USER: | ||
| # any document type other than audio/image | ||
| documents = list( | ||
| msg.attachments.exclude( | ||
| Q(metadata__mime_type__startswith="image/") | ||
| | Q(metadata__mime_type__startswith="audio/") | ||
| ).values_list("url", flat=True) | ||
| ) | ||
| yield { | ||
| "role": msg.role, | ||
| "input_prompt": msg.display_content or msg.content, | ||
| "input_images": images, | ||
| "input_audio": audio, | ||
| "input_documents": documents, | ||
| "created_at": msg.created_at.isoformat(), | ||
| } | ||
| elif msg.role == CHATML_ROLE_ASSISTANT: | ||
| references = msg.saved_run.state.get("references") | ||
| buttons, text, _ = parse_bot_html(msg.display_content) | ||
| yield { | ||
| "role": msg.role, | ||
| "created_at": msg.created_at.isoformat(), | ||
| "status": "completed", | ||
| "type": "final_response", | ||
| "raw_output_text": [msg.content], | ||
| "output_text": [text], | ||
| "buttons": buttons, | ||
| "output_images": images, | ||
| "output_audio": audio, | ||
| "web_url": msg.saved_run.get_app_url(), | ||
| "user_message_id": msg.platform_msg_id, | ||
| "bot_message_id": msg.platform_msg_id.strip(MSG_ID_PREFIX), | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Wrong string method strips characters instead of prefixThe code uses |
||
| "references": references, | ||
| } | ||
|
|
||
|
|
||
| class FeedbackQuerySet(models.QuerySet): | ||
| def to_df( | ||
| self, tz=pytz.timezone(settings.TIME_ZONE), row_limit=10000 | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,6 +25,10 @@ | |
|
|
||
| from app_users.models import AppUser | ||
| from bots.models import BotIntegration, PublishedRun, Workflow | ||
| from bots.models.convo_msg import ( | ||
| Conversation, | ||
| db_msgs_to_api_json, | ||
| ) | ||
| from daras_ai.image_input import safe_filename, upload_file_from_bytes | ||
| from daras_ai_v2 import icons, settings | ||
| from daras_ai_v2.api_examples_widget import api_example_generator | ||
|
|
@@ -537,8 +541,12 @@ def chat_explore_route(request: Request): | |
|
|
||
|
|
||
| @app.get("/chat/{integration_name}-{integration_id}/") | ||
| @app.get("/chat/{integration_name}-{integration_id}/share/{conversation_id}/") | ||
| def chat_route( | ||
| request: Request, integration_id: str = None, integration_name: str = None | ||
| request: Request, | ||
| integration_id: str | None = None, | ||
| integration_name: str | None = None, | ||
| conversation_id: str | None = None, | ||
| ): | ||
| from daras_ai_v2.bot_integration_widgets import get_web_widget_embed_code | ||
| from routers.bots_api import api_hashids | ||
|
|
@@ -548,12 +556,36 @@ def chat_route( | |
| except (IndexError, BotIntegration.DoesNotExist): | ||
| raise HTTPException(status_code=404) | ||
|
|
||
| if conversation_id and bi.web_config_extras.get("enableShareConversation", False): | ||
| try: | ||
| conversation: Conversation = Conversation.objects.get( | ||
| id=api_hashids.decode(conversation_id)[0], | ||
| ) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Conversation access lacks bot integration authorization checkThe conversation is fetched only by its ID without verifying it belongs to the |
||
| except (IndexError, Conversation.DoesNotExist): | ||
| raise HTTPException(status_code=404) | ||
| mesasges = list(db_msgs_to_api_json(conversation.last_n_msgs())) | ||
| conversation_data = dict( | ||
| id=conversation_id, | ||
| bot_id=integration_id, | ||
| timestamp=conversation.created_at.isoformat(), | ||
| user_id=conversation.web_user_id, | ||
| messages=mesasges, | ||
| ) | ||
| else: | ||
| conversation_data = None | ||
|
|
||
| return templates.TemplateResponse( | ||
| "chat_fullscreen.html", | ||
| { | ||
| "request": request, | ||
| "bi": bi, | ||
| "embed_code": get_web_widget_embed_code(bi, config=dict(mode="fullscreen")), | ||
| "embed_code": get_web_widget_embed_code( | ||
| bi, | ||
| config=dict( | ||
| mode="fullscreen", | ||
| conversationData=conversation_data, | ||
| ), | ||
| ), | ||
| "meta": raw_build_meta_tags( | ||
| url=get_og_url_path(request), | ||
| title=f"Chat with {bi.name}", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Null pointer when saved_run is None
The code accesses
msg.saved_run.state.get("references")without checking ifsaved_runisNone. TheMessage.saved_runfield is defined withnull=True, default=None, so assistant messages may have no associated saved run, which would cause anAttributeErrorwhen accessing.state.