diff --git a/daras_ai_v2/doc_search_settings_widgets.py b/daras_ai_v2/doc_search_settings_widgets.py index 10ae86a7d..0c9ef51e0 100644 --- a/daras_ai_v2/doc_search_settings_widgets.py +++ b/daras_ai_v2/doc_search_settings_widgets.py @@ -10,7 +10,6 @@ from daras_ai_v2.embedding_model import EmbeddingModels from daras_ai_v2.enum_selector_widget import enum_selector from daras_ai_v2.gdrive_downloader import gdrive_list_urls_of_files_in_folder -from daras_ai_v2.prompt_vars import variables_input from daras_ai_v2.search_ref import CitationStyles _user_media_url_prefix = os.path.join( @@ -171,8 +170,10 @@ def doc_search_advanced_settings(): st.number_input( label=""" ###### Max Snippet Words - -After a document search, relevant snippets of your documents are returned as results. This setting adjusts the maximum number of words in each snippet. A high snippet size allows the LLM to access more information from your document results, at the cost of being verbose and potentially exhausting input tokens (which can cause a failure of the copilot to respond). Default: 300 +After a document search, relevant snippets of your documents are returned as results. +This setting adjusts the maximum number of words in each snippet (tokens = words * 2). +A high snippet size allows the LLM to access more information from your document results, \ +at the cost of being verbose and potentially exhausting input tokens (which can cause a failure of the copilot to respond). """, key="max_context_words", min_value=10, @@ -181,9 +182,10 @@ def doc_search_advanced_settings(): st.number_input( label=""" -###### Overlapping Snippet Lines -Your knowledge base documents are split into overlapping snippets. This settings adjusts how much those snippets overlap. In general you shouldn't need to adjust this. Default: 5 - +###### Snippet Overlap Ratio +Your knowledge base documents are split into overlapping snippets. +This settings adjusts how much those snippets overlap (overlap tokens = snippet tokens / overlap ratio). +In general you shouldn't need to adjust this. """, key="scroll_jump", min_value=1, @@ -194,7 +196,7 @@ def doc_search_advanced_settings(): def embeddings_model_selector(key: str): return enum_selector( EmbeddingModels, - label="##### Embeddings Model", + label="##### ✏ Embeddings Model", key=key, use_selectbox=True, ) diff --git a/daras_ai_v2/language_model.py b/daras_ai_v2/language_model.py index 12aab9200..401d3d185 100644 --- a/daras_ai_v2/language_model.py +++ b/daras_ai_v2/language_model.py @@ -33,6 +33,10 @@ from functions.recipe_functions import LLMTools DEFAULT_SYSTEM_MSG = "You are an intelligent AI assistant. Follow the instructions as closely as possible." +DEFAULT_JSON_PROMPT = ( + "Please respond directly in JSON format. " + "Don't output markdown or HTML, instead print the JSON object directly without formatting." +) CHATML_ROLE_SYSTEM = "system" CHATML_ROLE_ASSISTANT = "assistant" @@ -65,6 +69,7 @@ class LLMSpec(typing.NamedTuple): is_chat_model: bool = True is_vision_model: bool = False is_deprecated: bool = False + supports_json: bool = False class LargeLanguageModels(Enum): @@ -76,6 +81,7 @@ class LargeLanguageModels(Enum): context_window=128_000, price=10, is_vision_model=True, + supports_json=True, ) # https://platform.openai.com/docs/models/gpt-4o-mini gpt_4_o_mini = LLMSpec( @@ -85,6 +91,7 @@ class LargeLanguageModels(Enum): context_window=128_000, price=1, is_vision_model=True, + supports_json=True, ) # https://platform.openai.com/docs/models/gpt-4-turbo-and-gpt-4 gpt_4_turbo_vision = LLMSpec( @@ -97,6 +104,7 @@ class LargeLanguageModels(Enum): context_window=128_000, price=6, is_vision_model=True, + supports_json=True, ) gpt_4_vision = LLMSpec( label="GPT-4 Vision (openai) 🔻", @@ -114,6 +122,7 @@ class LargeLanguageModels(Enum): llm_api=LLMApis.openai, context_window=128_000, price=5, + supports_json=True, ) # https://platform.openai.com/docs/models/gpt-4 @@ -139,6 +148,7 @@ class LargeLanguageModels(Enum): llm_api=LLMApis.openai, context_window=4096, price=1, + supports_json=True, ) gpt_3_5_turbo_16k = LLMSpec( label="ChatGPT 16k (openai)", @@ -163,6 +173,7 @@ class LargeLanguageModels(Enum): llm_api=LLMApis.groq, context_window=8192, price=1, + supports_json=True, ) llama_3_groq_70b_tool_use = LLMSpec( label="Llama 3 Groq 70b Tool Use", @@ -170,6 +181,7 @@ class LargeLanguageModels(Enum): llm_api=LLMApis.groq, context_window=8192, price=1, + supports_json=True, ) llama3_8b = LLMSpec( label="Llama 3 8b (Meta AI)", @@ -177,6 +189,7 @@ class LargeLanguageModels(Enum): llm_api=LLMApis.groq, context_window=8192, price=1, + supports_json=True, ) llama_3_groq_8b_tool_use = LLMSpec( label="Llama 3 Groq 8b Tool Use", @@ -184,6 +197,7 @@ class LargeLanguageModels(Enum): llm_api=LLMApis.groq, context_window=8192, price=1, + supports_json=True, ) llama2_70b_chat = LLMSpec( label="Llama 2 70b Chat [Deprecated] (Meta AI)", @@ -199,6 +213,7 @@ class LargeLanguageModels(Enum): llm_api=LLMApis.groq, context_window=32_768, price=1, + supports_json=True, ) gemma_2_9b_it = LLMSpec( label="Gemma 2 9B (Google)", @@ -206,6 +221,7 @@ class LargeLanguageModels(Enum): llm_api=LLMApis.groq, context_window=8_192, price=1, + supports_json=True, ) gemma_7b_it = LLMSpec( label="Gemma 7B (Google)", @@ -213,6 +229,7 @@ class LargeLanguageModels(Enum): llm_api=LLMApis.groq, context_window=8_192, price=1, + supports_json=True, ) # https://cloud.google.com/vertex-ai/docs/generative-ai/learn/models @@ -358,6 +375,7 @@ def __init__(self, *args): self.is_deprecated = spec.is_deprecated self.is_chat_model = spec.is_chat_model self.is_vision_model = spec.is_vision_model + self.supports_json = spec.supports_json @property def value(self): @@ -431,11 +449,11 @@ def run_language_model( model: LargeLanguageModels = LargeLanguageModels[str(model)] if model.is_chat_model: - if not messages: + if prompt and not messages: # convert text prompt to chat messages messages = [ - {"role": "system", "content": DEFAULT_SYSTEM_MSG}, - {"role": "user", "content": prompt}, + format_chat_entry(role=CHATML_ROLE_SYSTEM, content=DEFAULT_SYSTEM_MSG), + format_chat_entry(role=CHATML_ROLE_USER, content=prompt), ] if not model.is_vision_model: # remove images from the messages @@ -443,6 +461,22 @@ def run_language_model( format_chat_entry(role=entry["role"], content=get_entry_text(entry)) for entry in messages ] + if ( + messages + and response_format_type == "json_object" + and "JSON" not in str(messages).upper() + ): + if messages[0]["role"] != CHATML_ROLE_SYSTEM: + messages.insert( + 0, + format_chat_entry( + role=CHATML_ROLE_SYSTEM, content=DEFAULT_JSON_PROMPT + ), + ) + else: + messages[0]["content"] = "\n\n".join( + [get_entry_text(messages[0]), DEFAULT_JSON_PROMPT] + ) entries = _run_chat_model( api=model.llm_api, model=model.model_id, @@ -628,6 +662,7 @@ def _run_chat_model( max_tokens=max_tokens, temperature=temperature, avoid_repetition=avoid_repetition, + response_format_type=response_format_type, stop=stop, ) case LLMApis.anthropic: @@ -1025,6 +1060,7 @@ def _run_groq_chat( temperature: float, avoid_repetition: bool, stop: list[str] | None, + response_format_type: ResponseFormatType | None, ): from usage_costs.cost_utils import record_cost_auto from usage_costs.models import ModelSku @@ -1040,6 +1076,8 @@ def _run_groq_chat( data["presence_penalty"] = 0.25 if stop: data["stop"] = stop + if response_format_type: + data["response_format"] = {"type": response_format_type} r = requests.post( "https://api.groq.com/openai/v1/chat/completions", json=data, diff --git a/daras_ai_v2/language_model_settings_widgets.py b/daras_ai_v2/language_model_settings_widgets.py index bdf7f4fe9..f5363cbef 100644 --- a/daras_ai_v2/language_model_settings_widgets.py +++ b/daras_ai_v2/language_model_settings_widgets.py @@ -1,49 +1,56 @@ +from pydantic import BaseModel, Field + import gooey_ui as st +from daras_ai_v2.enum_selector_widget import enum_selector, BLANK_OPTION +from daras_ai_v2.field_render import field_title_desc +from daras_ai_v2.language_model import LargeLanguageModels, ResponseFormatType, LLMApis -from daras_ai_v2.enum_selector_widget import enum_selector -from daras_ai_v2.language_model import LargeLanguageModels +class LanguageModelSettings(BaseModel): + avoid_repetition: bool | None + num_outputs: int | None + quality: float | None + max_tokens: int | None + sampling_temperature: float | None + response_format_type: ResponseFormatType = Field( + None, + title="Response Format", + ) -def language_model_settings(show_selector=True): - st.write("##### 🔠 Language Model Settings") - if show_selector: - enum_selector( - LargeLanguageModels, - label_visibility="collapsed", - key="selected_model", - use_selectbox=True, - ) +def language_model_selector( + label: str = "##### 🔠 Language Model Settings", + label_visibility: str = "visible", + key: str = "selected_model", +): + return enum_selector( + LargeLanguageModels, + label=label, + label_visibility=label_visibility, + key=key, + use_selectbox=True, + ) + - st.checkbox("Avoid Repetition", key="avoid_repetition") +def language_model_settings(selected_model: str = None): + try: + llm = LargeLanguageModels[selected_model] + except KeyError: + llm = None col1, col2 = st.columns(2) with col1: - st.slider( - label=""" -###### Answer Outputs -How many answers should the copilot generate? Additional answer outputs increase the cost of each run. - """, - key="num_outputs", - min_value=1, - max_value=4, - ) - if ( - show_selector - and not LargeLanguageModels[ - st.session_state.get("selected_model") or LargeLanguageModels.gpt_4.name - ].is_chat_model - ): + st.checkbox("Avoid Repetition", key="avoid_repetition") + if not llm or llm.supports_json: with col2: - st.slider( - label=""" -###### Attempts -Generate multiple responses and choose the best one. - """, - key="quality", - min_value=1.0, - max_value=5.0, - step=0.1, + st.selectbox( + f"###### {field_title_desc(LanguageModelSettings, 'response_format_type')}", + options=[None, "json_object"], + key="response_format_type", + format_func={ + None: BLANK_OPTION, + "json_object": "JSON Object", + }.__getitem__, ) col1, col2 = st.columns(2) @@ -68,3 +75,27 @@ def language_model_settings(show_selector=True): min_value=0.0, max_value=2.0, ) + + col1, col2 = st.columns(2) + with col1: + st.slider( + label=""" +###### Answer Outputs +How many answers should the copilot generate? Additional answer outputs increase the cost of each run. + """, + key="num_outputs", + min_value=1, + max_value=4, + ) + if llm and not llm.is_chat_model and llm.llm_api == LLMApis.openai: + with col2: + st.slider( + label=""" +###### Attempts +Generate multiple responses and choose the best one + """, + key="quality", + min_value=1.0, + max_value=5.0, + step=0.1, + ) diff --git a/recipes/BulkEval.py b/recipes/BulkEval.py index 8c5b8fc19..5cb6ddf34 100644 --- a/recipes/BulkEval.py +++ b/recipes/BulkEval.py @@ -22,6 +22,7 @@ run_language_model, LargeLanguageModels, ) +from daras_ai_v2.language_model_settings_widgets import LanguageModelSettings from daras_ai_v2.prompt_vars import render_prompt_vars from recipes.BulkRunner import read_df_any, list_view_editor, del_button from recipes.DocSearch import render_documents @@ -48,15 +49,6 @@ ] -class LLMSettingsMixin(BaseModel): - selected_model: typing.Literal[tuple(e.name for e in LargeLanguageModels)] | None - avoid_repetition: bool | None - num_outputs: int | None - quality: float | None - max_tokens: int | None - sampling_temperature: float | None - - class EvalPrompt(typing.TypedDict): name: str prompt: str @@ -168,7 +160,7 @@ def related_workflows(self) -> list: return [BulkRunnerPage, VideoBotsPage, AsrPage, DocSearchPage] - class RequestModel(LLMSettingsMixin, BasePage.RequestModel): + class RequestModelBase(BasePage.RequestModel): documents: list[str] = Field( title="Input Data Spreadsheet", description=""" @@ -193,6 +185,13 @@ class RequestModel(LLMSettingsMixin, BasePage.RequestModel): """, ) + selected_model: ( + typing.Literal[tuple(e.name for e in LargeLanguageModels)] | None + ) + + class RequestModel(LanguageModelSettings, RequestModelBase): + pass + class ResponseModel(BaseModel): output_documents: list[str] final_prompts: list[list[str]] | None diff --git a/recipes/CompareLLM.py b/recipes/CompareLLM.py index 24e64e48e..1a56692a1 100644 --- a/recipes/CompareLLM.py +++ b/recipes/CompareLLM.py @@ -7,17 +7,19 @@ import gooey_ui as st from bots.models import Workflow from daras_ai_v2.base import BasePage -from daras_ai_v2.enum_selector_widget import enum_multiselect, BLANK_OPTION -from daras_ai_v2.field_render import field_title +from daras_ai_v2.enum_selector_widget import enum_multiselect from daras_ai_v2.language_model import ( run_language_model, LargeLanguageModels, SUPERSCRIPT, ResponseFormatType, ) -from daras_ai_v2.language_model_settings_widgets import language_model_settings +from daras_ai_v2.language_model_settings_widgets import ( + language_model_settings, + LanguageModelSettings, +) from daras_ai_v2.loom_video_widget import youtube_video -from daras_ai_v2.prompt_vars import variables_input, render_prompt_vars +from daras_ai_v2.prompt_vars import render_prompt_vars DEFAULT_COMPARE_LM_META_IMG = "https://storage.googleapis.com/dara-c1b52.appspot.com/daras_ai/media/fef06d86-1f70-11ef-b8ee-02420a00015b/LLMs.jpg" @@ -40,22 +42,14 @@ class CompareLLMPage(BasePage): "sampling_temperature": 0.7, } - class RequestModel(BasePage.RequestModel): + class RequestModelBase(BasePage.RequestModel): input_prompt: str | None selected_models: ( list[typing.Literal[tuple(e.name for e in LargeLanguageModels)]] | None ) - avoid_repetition: bool | None - num_outputs: int | None - quality: float | None - max_tokens: int | None - sampling_temperature: float | None - - response_format_type: ResponseFormatType = Field( - None, - title="Response Format", - ) + class RequestModel(LanguageModelSettings, RequestModelBase): + pass class ResponseModel(BaseModel): output_text: dict[ @@ -96,16 +90,7 @@ def render_usage_guide(self): youtube_video("dhexRRDAuY8") def render_settings(self): - language_model_settings(show_selector=False) - st.selectbox( - f"###### {field_title(self.RequestModel, 'response_format_type')}", - options=[None, "json_object"], - key="response_format_type", - format_func={ - None: BLANK_OPTION, - "json_object": "JSON Object", - }.__getitem__, - ) + language_model_settings() def run(self, state: dict) -> typing.Iterator[str | None]: request: CompareLLMPage.RequestModel = self.RequestModel.parse_obj(state) diff --git a/recipes/DocExtract.py b/recipes/DocExtract.py index 2804ca849..0ef63c4e9 100644 --- a/recipes/DocExtract.py +++ b/recipes/DocExtract.py @@ -38,8 +38,15 @@ flatapply_parallel, ) from daras_ai_v2.gdrive_downloader import is_gdrive_url, gdrive_download -from daras_ai_v2.language_model import run_language_model, LargeLanguageModels -from daras_ai_v2.language_model_settings_widgets import language_model_settings +from daras_ai_v2.language_model import ( + run_language_model, + LargeLanguageModels, +) +from daras_ai_v2.language_model_settings_widgets import ( + language_model_settings, + language_model_selector, + LanguageModelSettings, +) from daras_ai_v2.loom_video_widget import youtube_video from daras_ai_v2.settings import service_account_key_path from daras_ai_v2.vector_search import ( @@ -76,7 +83,7 @@ class DocExtractPage(BasePage): ] price = 500 - class RequestModel(BasePage.RequestModel): + class RequestModelBase(BasePage.RequestModel): documents: list[FieldHttpUrl] sheet_url: FieldHttpUrl | None @@ -95,11 +102,9 @@ class RequestModel(BasePage.RequestModel): selected_model: ( typing.Literal[tuple(e.name for e in LargeLanguageModels)] | None ) - avoid_repetition: bool | None - num_outputs: int | None - quality: float | None - max_tokens: int | None - sampling_temperature: float | None + + class RequestModel(LanguageModelSettings, RequestModelBase): + pass class ResponseModel(BaseModel): pass @@ -134,11 +139,12 @@ def render_usage_guide(self): def render_settings(self): st.text_area( - "### 👩‍🏫 Task Instructions", + "##### 👩‍🏫 Task Instructions", key="task_instructions", height=300, ) - language_model_settings() + selected_model = language_model_selector() + language_model_settings(selected_model) enum_selector(AsrModels, label="##### ASR Model", key="selected_asr_model") st.write("---") @@ -464,6 +470,7 @@ def process_source( prompt=prompt, max_tokens=request.max_tokens, avoid_repetition=request.avoid_repetition, + response_format_type=request.response_format_type, ) ) update_cell(spreadsheet_id, row, Columns.summary.value, summary) diff --git a/recipes/DocSearch.py b/recipes/DocSearch.py index b864d6700..b6c1af301 100644 --- a/recipes/DocSearch.py +++ b/recipes/DocSearch.py @@ -20,9 +20,13 @@ run_language_model, LargeLanguageModels, ) -from daras_ai_v2.language_model_settings_widgets import language_model_settings +from daras_ai_v2.language_model_settings_widgets import ( + language_model_settings, + language_model_selector, + LanguageModelSettings, +) from daras_ai_v2.loom_video_widget import youtube_video -from daras_ai_v2.prompt_vars import variables_input, render_prompt_vars +from daras_ai_v2.prompt_vars import render_prompt_vars from daras_ai_v2.query_generator import generate_final_search_query from daras_ai_v2.search_ref import ( SearchReference, @@ -63,21 +67,19 @@ class DocSearchPage(BasePage): "dense_weight": 1.0, } - class RequestModel(DocSearchRequest, BasePage.RequestModel): + class RequestModelBase(DocSearchRequest, BasePage.RequestModel): task_instructions: str | None query_instructions: str | None selected_model: ( typing.Literal[tuple(e.name for e in LargeLanguageModels)] | None ) - avoid_repetition: bool | None - num_outputs: int | None - quality: float | None - max_tokens: int | None - sampling_temperature: float | None citation_style: typing.Literal[tuple(e.name for e in CitationStyles)] | None + class RequestModel(LanguageModelSettings, RequestModelBase): + pass + class ResponseModel(BaseModel): output_text: list[str] @@ -124,18 +126,19 @@ def render_example(self, state: dict): def render_settings(self): st.text_area( - "### 👩‍🏫 Task Instructions", + "##### 👩‍🏫 Task Instructions", key="task_instructions", height=300, ) st.write("---") - language_model_settings() + selected_model = language_model_selector() + language_model_settings(selected_model) st.write("---") st.write("##### 🔎 Document Search Settings") citation_style_selector() doc_extract_selector(self.request and self.request.user) - st.write("---") query_instructions_widget() + st.write("---") doc_search_advanced_settings() def preview_image(self, state: dict) -> str | None: @@ -202,6 +205,7 @@ def run_v2( prompt=response.final_prompt, max_tokens=request.max_tokens, avoid_repetition=request.avoid_repetition, + response_format_type=request.response_format_type, ) citation_style = ( diff --git a/recipes/DocSummary.py b/recipes/DocSummary.py index 7982cf5de..f26398575 100644 --- a/recipes/DocSummary.py +++ b/recipes/DocSummary.py @@ -2,7 +2,7 @@ from enum import Enum from daras_ai_v2.pydantic_validation import FieldHttpUrl -from pydantic import BaseModel +from pydantic import BaseModel, Field import gooey_ui as st from bots.models import Workflow @@ -16,8 +16,13 @@ LargeLanguageModels, run_language_model, calc_gpt_tokens, + ResponseFormatType, +) +from daras_ai_v2.language_model_settings_widgets import ( + language_model_settings, + language_model_selector, + LanguageModelSettings, ) -from daras_ai_v2.language_model_settings_widgets import language_model_settings from daras_ai_v2.pt import PromptTree from daras_ai_v2.text_splitter import text_splitter from daras_ai_v2.vector_search import ( @@ -57,7 +62,7 @@ class DocSummaryPage(BasePage): "chain_type": CombineDocumentsChains.map_reduce.name, } - class RequestModel(BasePage.RequestModel): + class RequestModelBase(BasePage.RequestModel): documents: list[FieldHttpUrl] task_instructions: str | None @@ -66,17 +71,15 @@ class RequestModel(BasePage.RequestModel): selected_model: ( typing.Literal[tuple(e.name for e in LargeLanguageModels)] | None ) - avoid_repetition: bool | None - num_outputs: int | None - quality: float | None - max_tokens: int | None - sampling_temperature: float | None chain_type: typing.Literal[tuple(e.name for e in CombineDocumentsChains)] | None selected_asr_model: typing.Literal[tuple(e.name for e in AsrModels)] | None google_translate_target: str | None + class RequestModel(LanguageModelSettings, RequestModelBase): + pass + class ResponseModel(BaseModel): output_text: list[str] @@ -111,7 +114,8 @@ def render_settings(self): # ) st.write("---") - language_model_settings() + selected_model = language_model_selector() + language_model_settings(selected_model) def preview_description(self, state: dict) -> str: return "Upload any collection of PDFs, docs and/or audio files and we'll transcribe them. Then give any GPT based instruction and we'll do a map-reduce and return the result. Great for summarizing large data sets to create structured data. Check out the examples for more." @@ -240,6 +244,7 @@ def llm(p: str) -> str: num_outputs=request.num_outputs, temperature=request.sampling_temperature, avoid_repetition=request.avoid_repetition, + response_format_type=request.response_format_type, )[0] state["prompt_tree"] = prompt_tree = [] diff --git a/recipes/GoogleGPT.py b/recipes/GoogleGPT.py index 270e53f2f..c1214bc26 100644 --- a/recipes/GoogleGPT.py +++ b/recipes/GoogleGPT.py @@ -1,7 +1,7 @@ import typing from furl import furl -from pydantic import BaseModel +from pydantic import BaseModel, Field import gooey_ui as st from bots.models import Workflow @@ -14,10 +14,15 @@ from daras_ai_v2.language_model import ( run_language_model, LargeLanguageModels, + ResponseFormatType, +) +from daras_ai_v2.language_model_settings_widgets import ( + language_model_settings, + language_model_selector, + LanguageModelSettings, ) -from daras_ai_v2.language_model_settings_widgets import language_model_settings from daras_ai_v2.loom_video_widget import youtube_video -from daras_ai_v2.prompt_vars import render_prompt_vars, variables_input +from daras_ai_v2.prompt_vars import render_prompt_vars from daras_ai_v2.query_generator import generate_final_search_query from daras_ai_v2.search_ref import ( SearchReference, @@ -73,7 +78,7 @@ class GoogleGPTPage(BasePage): dense_weight=1.0, ) - class RequestModel(GoogleSearchMixin, BasePage.RequestModel): + class RequestModelBase(BasePage.RequestModel): search_query: str site_filter: str @@ -83,11 +88,6 @@ class RequestModel(GoogleSearchMixin, BasePage.RequestModel): selected_model: ( typing.Literal[tuple(e.name for e in LargeLanguageModels)] | None ) - avoid_repetition: bool | None - num_outputs: int | None - quality: float | None - max_tokens: int | None - sampling_temperature: float | None max_search_urls: int | None @@ -100,6 +100,9 @@ class RequestModel(GoogleSearchMixin, BasePage.RequestModel): "dense_weight" ].field_info + class RequestModel(GoogleSearchMixin, LanguageModelSettings, RequestModelBase): + pass + class ResponseModel(BaseModel): output_text: list[str] @@ -140,12 +143,14 @@ def render_settings(self): height=300, ) st.write("---") - language_model_settings() + selected_model = language_model_selector() + language_model_settings(selected_model) st.write("---") serp_search_settings() st.write("---") st.write("##### 🔎 Document Search Settings") query_instructions_widget() + st.write("---") doc_search_advanced_settings() def related_workflows(self) -> list: @@ -279,4 +284,5 @@ def run_v2( prompt=response.final_prompt, max_tokens=request.max_tokens, avoid_repetition=request.avoid_repetition, + response_format_type=request.response_format_type, ) diff --git a/recipes/SEOSummary.py b/recipes/SEOSummary.py index 1c58b9336..2f95f3bd1 100644 --- a/recipes/SEOSummary.py +++ b/recipes/SEOSummary.py @@ -20,7 +20,11 @@ calc_gpt_tokens, LargeLanguageModels, ) -from daras_ai_v2.language_model_settings_widgets import language_model_settings +from daras_ai_v2.language_model_settings_widgets import ( + language_model_settings, + language_model_selector, + LanguageModelSettings, +) from daras_ai_v2.loom_video_widget import youtube_video from daras_ai_v2.scrollable_html_widget import scrollable_html from daras_ai_v2.serp_search import get_links_from_serp_api @@ -86,7 +90,7 @@ def preview_description(self, state: dict) -> str: # enable_blog_mode=False, ) - class RequestModel(GoogleSearchMixin, BaseModel): + class RequestModelBase(BaseModel): search_query: str keywords: str title: str @@ -99,11 +103,6 @@ class RequestModel(GoogleSearchMixin, BaseModel): selected_model: ( typing.Literal[tuple(e.name for e in LargeLanguageModels)] | None ) - sampling_temperature: float | None - max_tokens: int | None - num_outputs: int | None - quality: float | None - avoid_repetition: bool | None max_search_urls: int | None @@ -113,6 +112,9 @@ class RequestModel(GoogleSearchMixin, BaseModel): seed: int | None + class RequestModel(GoogleSearchMixin, LanguageModelSettings, RequestModelBase): + pass + class ResponseModel(BaseModel): output_content: list[str] @@ -181,7 +183,8 @@ def render_settings(self): st.checkbox("Enable Internal Cross-Linking", key="enable_crosslinks") st.checkbox("Enable HTML Formatting", key="enable_html") - language_model_settings() + selected_model = language_model_selector() + language_model_settings(selected_model) st.write("---") @@ -346,6 +349,7 @@ def _run_lm(request: SEOSummaryPage.RequestModel, final_prompt: str) -> list[str max_tokens=request.max_tokens, stop=[STOP_SEQ], avoid_repetition=request.avoid_repetition, + response_format_type=request.response_format_type, ) diff --git a/recipes/SmartGPT.py b/recipes/SmartGPT.py index c4720c9a0..dea7e121e 100644 --- a/recipes/SmartGPT.py +++ b/recipes/SmartGPT.py @@ -5,7 +5,6 @@ import gooey_ui as st from bots.models import Workflow -from recipes.GoogleGPT import render_output_with_refs from daras_ai_v2.base import BasePage from daras_ai_v2.functional import map_parallel from daras_ai_v2.language_model import ( @@ -14,8 +13,13 @@ CHATML_ROLE_USER, CHATML_ROLE_ASSISTANT, ) -from daras_ai_v2.language_model_settings_widgets import language_model_settings +from daras_ai_v2.language_model_settings_widgets import ( + language_model_settings, + language_model_selector, + LanguageModelSettings, +) from daras_ai_v2.pt import PromptTree +from recipes.GoogleGPT import render_output_with_refs DEFAULT_SMARTGPT_META_IMG = "https://storage.googleapis.com/dara-c1b52.appspot.com/daras_ai/media/3d71b434-9457-11ee-8edd-02420a0001c7/Smart%20GPT.jpg.png" @@ -27,7 +31,7 @@ class SmartGPTPage(BasePage): slug_versions = ["SmartGPT"] price = 20 - class RequestModel(BasePage.RequestModel): + class RequestModelBase(BasePage.RequestModel): input_prompt: str cot_prompt: str | None @@ -37,11 +41,9 @@ class RequestModel(BasePage.RequestModel): selected_model: ( typing.Literal[tuple(e.name for e in LargeLanguageModels)] | None ) - avoid_repetition: bool | None - num_outputs: int | None - quality: float | None - max_tokens: int | None - sampling_temperature: float | None + + class RequestModel(LanguageModelSettings, RequestModelBase): + pass class ResponseModel(BaseModel): output_text: list[str] @@ -80,7 +82,8 @@ def render_settings(self): """, key="dera_prompt", ) - language_model_settings() + selected_model = language_model_selector() + language_model_settings(selected_model) def related_workflows(self): from recipes.CompareLLM import CompareLLMPage @@ -118,6 +121,7 @@ def run(self, state: dict) -> typing.Iterator[str | None]: num_outputs=request.num_outputs, temperature=request.sampling_temperature, avoid_repetition=request.avoid_repetition, + response_format_type=request.response_format_type, ) state["prompt_tree"] = prompt_tree = [ { @@ -139,6 +143,7 @@ def run(self, state: dict) -> typing.Iterator[str | None]: quality=request.quality, temperature=request.sampling_temperature, avoid_repetition=request.avoid_repetition, + response_format_type=request.response_format_type, )[0], prompt_tree, ) @@ -171,6 +176,7 @@ def run(self, state: dict) -> typing.Iterator[str | None]: quality=request.quality, temperature=request.sampling_temperature, avoid_repetition=request.avoid_repetition, + response_format_type=request.response_format_type, ) state["output_text"] = dera_outputs diff --git a/recipes/SocialLookupEmail.py b/recipes/SocialLookupEmail.py index bf7a34f9f..b51682055 100644 --- a/recipes/SocialLookupEmail.py +++ b/recipes/SocialLookupEmail.py @@ -15,7 +15,11 @@ LargeLanguageModels, SUPERSCRIPT, ) -from daras_ai_v2.language_model_settings_widgets import language_model_settings +from daras_ai_v2.language_model_settings_widgets import ( + language_model_settings, + language_model_selector, + LanguageModelSettings, +) from daras_ai_v2.loom_video_widget import youtube_video from daras_ai_v2.redis_cache import redis_cache_decorator @@ -38,7 +42,7 @@ class SocialLookupEmailPage(BasePage): "sampling_temperature": 0.5, } - class RequestModel(BasePage.RequestModel): + class RequestModelBase(BasePage.RequestModel): email_address: str input_prompt: str | None @@ -50,15 +54,12 @@ class RequestModel(BasePage.RequestModel): # domain: str | None # key_words: str | None - # llm settings selected_model: ( typing.Literal[tuple(e.name for e in LargeLanguageModels)] | None ) - num_outputs: int | None - avoid_repetition: bool | None - quality: float | None - max_tokens: int | None - sampling_temperature: float | None + + class RequestModel(LanguageModelSettings, RequestModelBase): + pass class ResponseModel(BaseModel): person_data: dict @@ -126,7 +127,8 @@ def render_form_v2(self): ) def render_settings(self): - language_model_settings() + selected_model = language_model_selector() + language_model_settings(selected_model) # st.text_input("URL 1", key="url1") # st.text_input("URL 2", key="url2") @@ -174,6 +176,7 @@ def run(self, state: dict) -> typing.Iterator[str | None]: max_tokens=request.max_tokens, temperature=request.sampling_temperature, avoid_repetition=request.avoid_repetition, + response_format_type=request.response_format_type, stream=True, ) for i, entries in enumerate(chunks): diff --git a/recipes/VideoBots.py b/recipes/VideoBots.py index 9347c8fe4..3c9f5772e 100644 --- a/recipes/VideoBots.py +++ b/recipes/VideoBots.py @@ -66,7 +66,11 @@ format_chat_entry, SUPERSCRIPT, ) -from daras_ai_v2.language_model_settings_widgets import language_model_settings +from daras_ai_v2.language_model_settings_widgets import ( + language_model_settings, + language_model_selector, + LanguageModelSettings, +) from daras_ai_v2.lipsync_api import LipsyncSettings, LipsyncModel from daras_ai_v2.lipsync_settings_widgets import lipsync_settings from daras_ai_v2.loom_video_widget import youtube_video @@ -183,7 +187,7 @@ class RequestModelBase(BasePage.RequestModel): bot_script: str | None - # llm settings + # llm model selected_model: ( typing.Literal[tuple(e.name for e in LargeLanguageModels)] | None ) @@ -192,11 +196,6 @@ class RequestModelBase(BasePage.RequestModel): description="When your copilot users upload a photo or pdf, what kind of document are they mostly likely to upload? " "(via [Azure](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/how-to-guides/use-sdk-rest-api?view=doc-intel-3.1.0&tabs=linux&pivots=programming-language-rest-api))", ) - avoid_repetition: bool | None - num_outputs: int | None - quality: float | None - max_tokens: int | None - sampling_temperature: float | None # doc search task_instructions: str | None @@ -254,7 +253,9 @@ class RequestModelBase(BasePage.RequestModel): description="Give your copilot superpowers by giving it access to tools. Powered by [Function calling](https://platform.openai.com/docs/guides/function-calling).", ) - class RequestModel(LipsyncSettings, TextToSpeechSettings, RequestModelBase): + class RequestModel( + LipsyncSettings, TextToSpeechSettings, LanguageModelSettings, RequestModelBase + ): pass class ResponseModel(BaseModel): @@ -332,12 +333,7 @@ def render_form_v2(self): height=300, ) - enum_selector( - LargeLanguageModels, - label="#### 🧠 Language Model", - key="selected_model", - use_selectbox=True, - ) + language_model_selector(label="#### 🧠 Language Model") bulk_documents_uploader( """ @@ -534,10 +530,12 @@ def render_settings(self): if documents: query_instructions_widget() keyword_instructions_widget() + st.write("---") doc_search_advanced_settings() st.write("---") - language_model_settings(show_selector=False) + st.write("##### 🔠 Language Model Settings") + language_model_settings(st.session_state.get("selected_model")) st.write("---") @@ -934,6 +932,7 @@ def run_v2( num_outputs=request.num_outputs, temperature=request.sampling_temperature, avoid_repetition=request.avoid_repetition, + response_format_type=request.response_format_type, tools=request.tools, stream=True, )