diff --git a/daras_ai_v2/base.py b/daras_ai_v2/base.py
index 7187178b7..b65a65dae 100644
--- a/daras_ai_v2/base.py
+++ b/daras_ai_v2/base.py
@@ -1298,7 +1298,6 @@ def _render_input_col(self):
self.render_form_v2()
with st.expander("⚙️ Settings"):
self.render_settings()
- st.write("---")
submitted = self.render_submit_button()
with st.div(style={"textAlign": "right"}):
st.caption(
diff --git a/daras_ai_v2/doc_search_settings_widgets.py b/daras_ai_v2/doc_search_settings_widgets.py
index b240b482f..bdeae11e6 100644
--- a/daras_ai_v2/doc_search_settings_widgets.py
+++ b/daras_ai_v2/doc_search_settings_widgets.py
@@ -4,6 +4,7 @@
import gooey_ui as st
from daras_ai_v2 import settings
from daras_ai_v2.asr import AsrModels, google_translate_language_selector
+from daras_ai_v2.prompt_vars import prompt_vars_widget
from daras_ai_v2.enum_selector_widget import enum_selector
from daras_ai_v2.search_ref import CitationStyles
@@ -104,6 +105,9 @@ def doc_search_settings(
key="query_instructions",
height=300,
)
+ prompt_vars_widget(
+ "query_instructions",
+ )
if keyword_instructions_allowed:
st.text_area(
"""
@@ -114,6 +118,9 @@ def doc_search_settings(
key="keyword_instructions",
height=300,
)
+ prompt_vars_widget(
+ "keyword_instructions",
+ )
dense_weight_ = DocSearchRequest.__fields__["dense_weight"]
st.slider(
diff --git a/daras_ai_v2/field_render.py b/daras_ai_v2/field_render.py
index 1b79c1673..554c44c65 100644
--- a/daras_ai_v2/field_render.py
+++ b/daras_ai_v2/field_render.py
@@ -11,3 +11,23 @@ def field_title_desc(model: typing.Type[BaseModel], name: str) -> str:
[field.field_info.title, field.field_info.description or ""],
)
)
+
+
+def field_title(model: typing.Type[BaseModel], name: str) -> str:
+ field = model.__fields__[name]
+ return "\n".join(
+ filter(
+ None,
+ [field.field_info.title],
+ )
+ )
+
+
+def field_desc(model: typing.Type[BaseModel], name: str) -> str:
+ field = model.__fields__[name]
+ return "\n".join(
+ filter(
+ None,
+ [field.field_info.description or ""],
+ )
+ )
diff --git a/daras_ai_v2/language_model_settings_widgets.py b/daras_ai_v2/language_model_settings_widgets.py
index e5ab27a59..39beee991 100644
--- a/daras_ai_v2/language_model_settings_widgets.py
+++ b/daras_ai_v2/language_model_settings_widgets.py
@@ -2,13 +2,27 @@
from daras_ai_v2.azure_doc_extract import azure_form_recognizer_models
from daras_ai_v2.enum_selector_widget import enum_selector
-from daras_ai_v2.field_render import field_title_desc
+from daras_ai_v2.field_render import field_title_desc, field_desc
from daras_ai_v2.language_model import LargeLanguageModels
-def language_model_settings(show_selector=True, show_document_model=False):
+def language_model_settings(
+ show_selector=True, show_document_model=False, show_only_document=False
+):
from recipes.VideoBots import VideoBotsPage
+ if show_only_document:
+ doc_model_descriptions = azure_form_recognizer_models()
+ st.selectbox(
+ f"{field_desc(VideoBotsPage.RequestModel, 'document_model')}",
+ key="document_model",
+ options=[None, *doc_model_descriptions],
+ format_func=lambda x: (
+ f"{doc_model_descriptions[x]} ({x})" if x else "———"
+ ),
+ )
+ return
+
st.write("##### 🔠 Language Model Settings")
if show_selector:
diff --git a/daras_ai_v2/prompt_vars.py b/daras_ai_v2/prompt_vars.py
index 80f13d906..4bdc27d7d 100644
--- a/daras_ai_v2/prompt_vars.py
+++ b/daras_ai_v2/prompt_vars.py
@@ -28,11 +28,14 @@ def prompt_vars_widget(*keys: str, variables_key: str = "variables"):
if not (template_vars or err):
return
- st.write("##### ⌥ Variables")
+ st.write("###### ⌥ Variables")
old_state = st.session_state.get(variables_key, {})
new_state = {}
for name in sorted(template_vars):
if name in st.session_state:
+ st.write(
+ f"⚠️ `{name}` is a reserved variable name. If you meant to create a custom variable, please use a different name."
+ )
continue
var_key = f"__{variables_key}_{name}"
st.session_state.setdefault(var_key, old_state.get(name, ""))
diff --git a/daras_ai_v2/text_to_speech_settings_widgets.py b/daras_ai_v2/text_to_speech_settings_widgets.py
index 499b502d2..9376bf450 100644
--- a/daras_ai_v2/text_to_speech_settings_widgets.py
+++ b/daras_ai_v2/text_to_speech_settings_widgets.py
@@ -141,12 +141,13 @@ class TextToSpeechProviders(Enum):
}
-def text_to_speech_settings(page):
- st.write(
- """
- ##### 🗣️ Voice Settings
- """
- )
+def text_to_speech_settings(page, show_label=True):
+ if show_label:
+ st.write(
+ """
+ ##### 🗣️ Voice Settings
+ """
+ )
col1, col2 = st.columns(2)
with col1:
diff --git a/recipes/VideoBots.py b/recipes/VideoBots.py
index 44994b7ff..148b78222 100644
--- a/recipes/VideoBots.py
+++ b/recipes/VideoBots.py
@@ -32,7 +32,8 @@
document_uploader,
)
from daras_ai_v2.enum_selector_widget import enum_multiselect
-from daras_ai_v2.field_render import field_title_desc
+from daras_ai_v2.enum_selector_widget import enum_selector
+from daras_ai_v2.field_render import field_title_desc, field_desc
from daras_ai_v2.functions import LLMTools
from daras_ai_v2.glossary import glossary_input, validate_glossary_document
from daras_ai_v2.language_model import (
@@ -163,9 +164,9 @@ class RequestModel(BaseModel):
messages: list[ConversationEntry] | None
# tts settings
- tts_provider: typing.Literal[
- tuple(e.name for e in TextToSpeechProviders)
- ] | None
+ tts_provider: (
+ typing.Literal[tuple(e.name for e in TextToSpeechProviders)] | None
+ )
uberduck_voice_name: str | None
uberduck_speaking_rate: float | None
google_voice_name: str | None
@@ -180,9 +181,9 @@ class RequestModel(BaseModel):
elevenlabs_similarity_boost: float | None
# llm settings
- selected_model: typing.Literal[
- tuple(e.name for e in LargeLanguageModels)
- ] | None
+ selected_model: (
+ typing.Literal[tuple(e.name for e in LargeLanguageModels)] | None
+ )
document_model: str | None = Field(
title="🩻 Photo / Document Intelligence",
description="When your copilot users upload a photo or pdf, what kind of document are they mostly likely to upload? "
@@ -312,26 +313,104 @@ def render_description(self):
def render_form_v2(self):
st.text_area(
"""
- ##### 📝 Prompt
- High-level system instructions.
+ #### 📝 Instructions
""",
key="bot_script",
height=300,
)
+ prompt_vars_widget(
+ "bot_script",
+ )
+
+ enum_selector(
+ LargeLanguageModels,
+ label="#### 🧠 Language Model",
+ key="selected_model",
+ use_selectbox=True,
+ )
document_uploader(
"""
-##### 📄 Documents (*optional*)
-Upload documents or enter URLs to give your copilot a knowledge base. With each incoming user message, we'll search your documents via a vector DB query.
-"""
+ #### 📄 Knowledge
+ Upload documents or enter URLs to give your copilot a knowledge base. With each incoming user message, we'll search your documents via a vector DB query.
+ """
)
- prompt_vars_widget(
- "bot_script",
- "task_instructions",
- "query_instructions",
- "keyword_instructions",
- )
+ st.markdown("#### Capabilities")
+ if not "__enable_audio" in st.session_state:
+ st.session_state["__enable_audio"] = bool(
+ st.session_state.get("tts_provider")
+ )
+ enable_audio = st.checkbox("##### 🗣️ Speech Responses", key="__enable_audio")
+ if not enable_audio:
+ st.session_state["tts_provider"] = None
+ else:
+ text_to_speech_settings(page=self, show_label=False)
+
+ if not "__enable_video" in st.session_state:
+ st.session_state["__enable_video"] = bool(
+ st.session_state.get("input_face")
+ )
+ if enable_audio:
+ st.write("---")
+ enable_video = st.checkbox(
+ "##### 🫦 Add Lipsync Video", key="__enable_video"
+ )
+ else:
+ enable_video = False
+ if not enable_video:
+ st.session_state["input_face"] = None
+ else:
+ st.file_uploader(
+ """
+ #### 👩🦰 Input Face
+ Upload a video/image that contains faces to use
+ *Recommended - mp4 / mov / png / jpg / gif*
+ """,
+ key="input_face",
+ )
+ lipsync_settings()
+ st.write("---")
+
+ if st.checkbox(
+ "##### 🔠 Translation", value=bool(st.session_state.get("user_language"))
+ ):
+ google_translate_language_selector(
+ f"{field_desc(self.RequestModel, 'user_language')}",
+ key="user_language",
+ )
+ enable_glossary = st.checkbox(
+ "📖 Add Glossary",
+ value=bool(
+ st.session_state.get("input_glossary_document")
+ or st.session_state.get("output_glossary_document")
+ ),
+ )
+ if enable_glossary:
+ st.caption(
+ """
+ Provide a glossary to customize translation and improve accuracy of domain-specific terms.
+ If not specified or invalid, no glossary will be used. Read about the expected format [here](https://docs.google.com/document/d/1TwzAvFmFYekloRKql2PXNPIyqCbsHRL8ZtnWkzAYrh8/edit?usp=sharing).
+ """
+ )
+ glossary_input(
+ f"##### {field_title_desc(self.RequestModel, 'input_glossary_document')}",
+ key="input_glossary_document",
+ )
+ glossary_input(
+ f"##### {field_title_desc(self.RequestModel, 'output_glossary_document')}",
+ key="output_glossary_document",
+ )
+ else:
+ st.session_state["input_glossary_document"] = None
+ st.session_state["output_glossary_document"] = None
+ st.write("---")
+
+ if st.checkbox(
+ "##### 🩻 Photo & Document Intelligence"
+ , value=bool(st.session_state.get("document_model"),)
+ ):
+ language_model_settings(show_only_document=True)
def validate_form_v2(self):
input_glossary = st.session_state.get("input_glossary_document", "")
@@ -356,6 +435,9 @@ def render_settings(self):
key="task_instructions",
height=300,
)
+ prompt_vars_widget(
+ "task_instructions",
+ )
st.write("---")
st.checkbox("🔗 Shorten Citation URLs", key="use_url_shortener")
@@ -366,71 +448,8 @@ def render_settings(self):
doc_search_settings(keyword_instructions_allowed=True)
st.write("---")
- language_model_settings(show_document_model=True)
-
- st.write("---")
- google_translate_language_selector(
- f"##### {field_title_desc(self.RequestModel, 'user_language')}",
- key="user_language",
- )
- enable_glossary = st.checkbox(
- "📖 Customize with Glossary",
- value=bool(
- st.session_state.get("input_glossary_document")
- or st.session_state.get("output_glossary_document")
- ),
- )
- st.markdown(
- """
- Provide a glossary to customize translation and improve accuracy of domain-specific terms.
- If not specified or invalid, no glossary will be used. Read about the expected format [here](https://docs.google.com/document/d/1TwzAvFmFYekloRKql2PXNPIyqCbsHRL8ZtnWkzAYrh8/edit?usp=sharing).
- """
- )
- if enable_glossary:
- glossary_input(
- f"##### {field_title_desc(self.RequestModel, 'input_glossary_document')}",
- key="input_glossary_document",
- )
- glossary_input(
- f"##### {field_title_desc(self.RequestModel, 'output_glossary_document')}",
- key="output_glossary_document",
- )
- else:
- st.session_state["input_glossary_document"] = None
- st.session_state["output_glossary_document"] = None
- st.write("---")
-
- if not "__enable_audio" in st.session_state:
- st.session_state["__enable_audio"] = bool(
- st.session_state.get("tts_provider")
- )
- enable_audio = st.checkbox("Enable Audio Output?", key="__enable_audio")
- if not enable_audio:
- st.write("---")
- st.session_state["tts_provider"] = None
- else:
- text_to_speech_settings(page=self)
-
- st.write("---")
- if not "__enable_video" in st.session_state:
- st.session_state["__enable_video"] = bool(
- st.session_state.get("input_face")
- )
- enable_video = st.checkbox("Enable Video Output?", key="__enable_video")
- if not enable_video:
- st.session_state["input_face"] = None
- else:
- st.file_uploader(
- """
- #### 👩🦰 Input Face
- Upload a video/image that contains faces to use
- *Recommended - mp4 / mov / png / jpg / gif*
- """,
- key="input_face",
- )
- lipsync_settings()
+ language_model_settings(show_selector=False)
- st.write("---")
enum_multiselect(
enum_cls=LLMTools,
label="##### " + field_title_desc(self.RequestModel, "tools"),
@@ -1044,10 +1063,12 @@ def messenger_bot_integration(self):
favicon = Platform(bi.platform).get_favicon()
with st.div(className="mt-2"):
st.markdown(
- f' '
- f'{bi}'
- if bi.saved_run
- else f"{bi}",
+ (
+ f' '
+ f'{bi}'
+ if bi.saved_run
+ else f"{bi}"
+ ),
unsafe_allow_html=True,
)
with col2:
@@ -1098,9 +1119,9 @@ def slack_specific_settings(self, bi: BotIntegration):
st.session_state[f"_bi_name_{bi.id}"] = (
pr and pr.title
) or self.get_recipe_title()
- st.session_state[
- f"_bi_slack_read_receipt_msg_{bi.id}"
- ] = BotIntegration._meta.get_field("slack_read_receipt_msg").default
+ st.session_state[f"_bi_slack_read_receipt_msg_{bi.id}"] = (
+ BotIntegration._meta.get_field("slack_read_receipt_msg").default
+ )
bi.slack_read_receipt_msg = st.text_input(
"""
@@ -1299,9 +1320,9 @@ def msg_container_widget(role: str):
return st.div(
className="px-3 py-1 pt-2",
style=dict(
- background="rgba(239, 239, 239, 0.6)"
- if role == CHATML_ROLE_USER
- else "#fff",
+ background=(
+ "rgba(239, 239, 239, 0.6)" if role == CHATML_ROLE_USER else "#fff"
+ ),
),
)