diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..8c9c4f1c --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.jsonl filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/Build.yml b/.github/workflows/Build.yml index e4f22de4..666cbf9c 100644 --- a/.github/workflows/Build.yml +++ b/.github/workflows/Build.yml @@ -12,6 +12,7 @@ concurrency: env: RESOURCE_PUBLISHER_TOKEN: ${{ secrets.RESOURCE_PUBLISHER_TOKEN }} WOLFRAMSCRIPT_ENTITLEMENTID: ${{ secrets.WOLFRAMSCRIPT_ENTITLEMENTID }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} jobs: @@ -42,5 +43,8 @@ jobs: with: path: ${{ env.PACLET_BUILD_DIR }} + - name: InstallTestDependencies + run: wolframscript -f Scripts/InstallTestDependencies.wls + - name: Test run: wolframscript -f Scripts/TestPaclet.wls \ No newline at end of file diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml index 37f3efd4..10edd31e 100644 --- a/.github/workflows/Release.yml +++ b/.github/workflows/Release.yml @@ -12,6 +12,7 @@ concurrency: env: RESOURCE_PUBLISHER_TOKEN: ${{ secrets.RESOURCE_PUBLISHER_TOKEN }} WOLFRAMSCRIPT_ENTITLEMENTID: ${{ secrets.WOLFRAMSCRIPT_ENTITLEMENTID }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} jobs: @@ -37,6 +38,9 @@ jobs: - name: Build run: wolframscript -f Scripts/BuildPaclet.wls + - name: InstallTestDependencies + run: wolframscript -f Scripts/InstallTestDependencies.wls + - name: Test run: wolframscript -f Scripts/TestPaclet.wls @@ -98,6 +102,9 @@ jobs: - name: Checkout uses: actions/checkout@v4 + - name: Unformat + run: wolframscript -f Scripts/UnformatFiles.wls + - name: BuildMX run: wolframscript -f Scripts/BuildMX.wls diff --git a/.gitignore b/.gitignore index e17c7adc..c7ba574b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ -build .DS_Store +Assets/VectorDatabases/**/*.usearch +Assets/VectorDatabases/**/*.wxf +build Source/Chatbook/64Bit/Chatbook.mx \ No newline at end of file diff --git a/Assets/DisplayFunctions.wxf b/Assets/DisplayFunctions.wxf index 2ed01ba1..805bcc5b 100644 Binary files a/Assets/DisplayFunctions.wxf and b/Assets/DisplayFunctions.wxf differ diff --git a/Assets/Tokenizers/claude.wxf b/Assets/Tokenizers/claude.wxf new file mode 100644 index 00000000..41c82a4c Binary files /dev/null and b/Assets/Tokenizers/claude.wxf differ diff --git a/Assets/Tokenizers/gpt-2.wxf b/Assets/Tokenizers/gpt-2.wxf new file mode 100644 index 00000000..5a2a3d5c Binary files /dev/null and b/Assets/Tokenizers/gpt-2.wxf differ diff --git a/Assets/Tokenizers/gpt-3.5.wxf b/Assets/Tokenizers/gpt-3.5.wxf new file mode 100644 index 00000000..ea4e0f0f Binary files /dev/null and b/Assets/Tokenizers/gpt-3.5.wxf differ diff --git a/Assets/Tokenizers/gpt-4.wxf b/Assets/Tokenizers/gpt-4.wxf new file mode 100644 index 00000000..46394dba Binary files /dev/null and b/Assets/Tokenizers/gpt-4.wxf differ diff --git a/Assets/Tokenizers/gpt-4o-text.wxf b/Assets/Tokenizers/gpt-4o-text.wxf new file mode 100644 index 00000000..5a0080bd Binary files /dev/null and b/Assets/Tokenizers/gpt-4o-text.wxf differ diff --git a/Developer/CacheTokenizers.wl b/Developer/CacheTokenizers.wl new file mode 100644 index 00000000..4fa73331 --- /dev/null +++ b/Developer/CacheTokenizers.wl @@ -0,0 +1,61 @@ +(* This is used to backport tokenizers from later versions of WL to 13.3 so they can be included in the MX build. *) + +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`ChatbookDeveloper`" ]; + +`CacheTokenizers; + +Begin[ "`Private`" ]; + +PacletInstall[ "Wolfram/LLMFunctions" ]; +Block[ { $ContextPath }, Get[ "Wolfram`LLMFunctions`" ] ]; + +Get[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; +Needs[ "Developer`" -> None ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Paths*) +$pacletDirectory = DirectoryName[ $InputFileName, 2 ]; +$tokenizerDirectory = FileNameJoin @ { $pacletDirectory, "Assets", "Tokenizers" }; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Aliases*) +ensureDirectory = GeneralUtilities`EnsureDirectory; +readWXFFile = Developer`ReadWXFFile; +writeWXFFile = Developer`WriteWXFFile; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*CacheTokenizers*) +CacheTokenizers // ClearAll; + +CacheTokenizers[ ] := + Enclose @ Module[ { tokenizers, exported }, + tokenizers = ConfirmBy[ Select[ cachedTokenizer @ All, MatchQ[ _NetEncoder ] ], AssociationQ, "Tokenizers" ]; + ConfirmAssert[ Length @ tokenizers > 0, "LengthCheck" ]; + exported = ConfirmBy[ Association @ KeyValueMap[ exportTokenizer, tokenizers ], AssociationQ, "Exported" ]; + exported + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*exportTokenizer*) +exportTokenizer // ClearAll; +exportTokenizer[ name_String, tokenizer_NetEncoder ] := + Enclose @ Module[ { dir, file, exported }, + dir = ConfirmBy[ ensureDirectory @ $tokenizerDirectory, DirectoryQ, "Directory" ]; + file = FileNameJoin @ { dir, name <> ".wxf" }; + exported = ConfirmBy[ writeWXFFile[ file, tokenizer, PerformanceGoal -> "Size" ], FileExistsQ, "Export" ]; + ConfirmMatch[ readWXFFile[ exported ][ "Hello world" ], { __Integer }, "Verification" ]; + name -> exported + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +End[ ]; +EndPackage[ ]; diff --git a/Developer/Resources/Paclets/SemanticSearch.paclet b/Developer/Resources/Paclets/SemanticSearch.paclet new file mode 100644 index 00000000..de7df530 Binary files /dev/null and b/Developer/Resources/Paclets/SemanticSearch.paclet differ diff --git a/Developer/Resources/Styles.wl b/Developer/Resources/Styles.wl index e0ec2ac8..8df97cd9 100644 --- a/Developer/Resources/Styles.wl +++ b/Developer/Resources/Styles.wl @@ -33,9 +33,9 @@ Cell[ |>, ComponentwiseContextMenu -> <| - "CellBracket" -> contextMenu[ $askMenuItem, $excludeMenuItem, Delimiter, "CellBracket" ], - "CellGroup" -> contextMenu[ $excludeMenuItem, Delimiter, "CellGroup" ], - "CellRange" -> contextMenu[ $excludeMenuItem, Delimiter, "CellRange" ] + "CellBracket" -> contextMenu[ { $askMenuItem, $excludeMenuItem, Delimiter }, "CellBracket" ], + "CellGroup" -> contextMenu[ { $excludeMenuItem, Delimiter }, "CellGroup" ], + "CellRange" -> contextMenu[ { $excludeMenuItem, Delimiter }, "CellRange" ] |>, PrivateCellOptions -> { @@ -59,7 +59,7 @@ Cell[ Cell[ StyleData[ "Text" ], - ContextMenu -> contextMenu[ $askMenuItem, Delimiter, "Text" ] + ContextMenu -> contextMenu[ { $askMenuItem, Delimiter }, "Text" ] ] @@ -77,7 +77,7 @@ Cell[ "*" -> "Item", ">" -> "ExternalLanguageDefault" }, - ContextMenu -> contextMenu[ $askMenuItem, Delimiter, "Input" ], + ContextMenu -> contextMenu[ { $askMenuItem, Delimiter }, "Input" ], CellEpilog :> With[ { $CellContext`cell = (FinishDynamic[ ]; EvaluationCell[ ]) }, Quiet @ Needs[ "Wolfram`Chatbook`" -> None ]; Symbol[ "Wolfram`Chatbook`ChatbookAction" ][ "AIAutoAssist", $CellContext`cell ] @@ -92,7 +92,7 @@ Cell[ Cell[ StyleData[ "Output" ], - ContextMenu -> contextMenu[ $askMenuItem, Delimiter, "Output" ], + ContextMenu -> contextMenu[ { $askMenuItem, Delimiter }, "Output" ], CellTrayWidgets -> <| "GearMenu" -> <| "Condition" -> False |> |> ] @@ -334,7 +334,7 @@ Cell[ TaggingRules -> <| "ChatNotebookSettings" -> <| |> |>, CellTrayWidgets -> <| "ChatWidget" -> <| "Visible" -> False |>, - "ChatFeedback" -> <| "Content" -> Cell[ BoxData @ ToBoxes @ $feedbackButtons, "ChatFeedback" ] |> + "ChatFeedback" -> <| "Content" -> Cell[ BoxData @ ToBoxes @ $feedbackButtonsV, "ChatFeedback" ] |> |>, menuInitializer[ "ChatOutput", RGBColor[ "#ecf0f5" ] ] ] @@ -611,7 +611,8 @@ Cell[ BaselinePosition -> Scaled[ 0.275 ], FrameMargins -> { { 3, 3 }, { 2, 2 } }, FrameStyle -> Directive[ AbsoluteThickness[ 1 ], GrayLevel[ 0.92941 ] ], - ImageMargins -> { { 0, 0 }, { 0, 0 } } + ImageMargins -> { { 0, 0 }, { 0, 0 } }, + BaseStyle -> { "InlineCode", AutoSpacing -> False, AutoMultiplicationSymbol -> False } ] } ] @@ -1084,13 +1085,18 @@ Cell[ Cell[ StyleData[ "UserMessageBox" ], TemplateBoxOptions -> { - DisplayFunction -> Function @ Evaluate @ FrameBox[ - Cell[ #, "Text", Background -> None ], - Background -> RGBColor[ "#edf4fc" ], - FrameMargins -> 8, - FrameStyle -> RGBColor[ "#a3c9f2" ], - RoundingRadius -> 10, - StripOnInput -> False + DisplayFunction -> Function @ Evaluate @ PaneBox[ + FrameBox[ + #, + BaseStyle -> { "Text", Editable -> False, Selectable -> False }, + Background -> RGBColor[ "#edf4fc" ], + FrameMargins -> 8, + FrameStyle -> RGBColor[ "#a3c9f2" ], + RoundingRadius -> 10, + StripOnInput -> False + ], + Alignment -> Right, + ImageSize -> { Full, Automatic } ] } ] @@ -1103,20 +1109,38 @@ Cell[ Cell[ StyleData[ "AssistantMessageBox" ], TemplateBoxOptions -> { - DisplayFunction -> Function @ Evaluate @ FrameBox[ - #, - BaseStyle -> "Text", - Background -> RGBColor[ "#fcfdff" ], - FrameMargins -> 8, - FrameStyle -> RGBColor[ "#c9ccd0" ], - ImageSize -> { Scaled[ 1 ], Automatic }, - RoundingRadius -> 10, - StripOnInput -> False + DisplayFunction -> Function @ Evaluate @ TagBox[ + FrameBox[ + #, + BaseStyle -> { "Text", Editable -> False, Selectable -> False }, + Background -> RGBColor[ "#fcfdff" ], + FrameMargins -> 8, + FrameStyle -> RGBColor[ "#c9ccd0" ], + ImageSize -> { Scaled[ 1 ], Automatic }, + RoundingRadius -> 10, + StripOnInput -> False + ], + EventHandlerTag @ { + "MouseEntered" :> + With[ { cell = EvaluationCell[ ] }, + Quiet @ Needs[ "Wolfram`Chatbook`" -> None ]; + Symbol[ "Wolfram`Chatbook`ChatbookAction" ][ "AttachAssistantMessageButtons", cell ] + ], + Method -> "Preemptive", + PassEventsDown -> Automatic, + PassEventsUp -> True + } ] } ] +Cell[ + StyleData[ "FeedbackButtonsHorizontal" ], + TemplateBoxOptions -> { DisplayFunction -> Function @ Evaluate @ ToBoxes @ $feedbackButtonsH } +] + + (* ::Subsection::Closed:: *) (*DropShadowPaneBox*) diff --git a/Developer/Resources/WorkspaceStyles.wl b/Developer/Resources/WorkspaceStyles.wl index e1f6a546..c0a062c9 100644 --- a/Developer/Resources/WorkspaceStyles.wl +++ b/Developer/Resources/WorkspaceStyles.wl @@ -19,7 +19,6 @@ Cell[ TaggingRules -> <| "ChatNotebookSettings" -> $workspaceDefaultSettings |>, WindowClickSelect -> True, WindowElements -> { "VerticalScrollBar" }, - WindowFrame -> "ModelessDialog", WindowFrameElements -> { "CloseBox", "ResizeArea" }, WindowMargins -> { { 0, Automatic }, { 0, 0 } }, WindowSize -> { $sideChatWidth, Automatic }, @@ -39,12 +38,12 @@ Cell[ Cell[ StyleData[ "ChatInput" ], CellDingbat -> None, + CellEventActions -> None, CellFrame -> 0, CellFrameLabelMargins -> 6, CellMargins -> { { 15, 10 }, { 5, 10 } }, - Selectable -> True, + Selectable -> False, ShowCellBracket -> False, - TextAlignment -> Right, CellFrameLabels -> { { None, None }, { @@ -74,9 +73,9 @@ Cell[ Background -> None, CellDingbat -> None, CellFrame -> 0, - CellMargins -> { { 10, 15 }, { 15, 12 } }, + CellMargins -> { { 10, 15 }, { 25, 12 } }, Initialization -> None, - Selectable -> True, + Selectable -> False, ShowCellBracket -> False, CellFrameLabels -> { { None, None }, @@ -121,6 +120,16 @@ Cell[ ) ] +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*CodeAssistanceWelcomeCell*) +Cell[ + StyleData[ "CodeAssistanceWelcomeCell" ], + CellMargins -> { { 10, 10 }, { 30, 10 } }, + ShowStringCharacters -> False, + TaggingRules -> <| "ChatNotebookSettings" -> <| "ExcludeFromChat" -> True |> |> +] + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Template Boxes*) @@ -159,6 +168,52 @@ Cell[ } ] +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*WelcomeToCodeAssistanceSplash*) +Cell[ + StyleData[ "WelcomeToCodeAssistanceSplash" ], + TemplateBoxOptions -> { + DisplayFunction -> Function @ Evaluate @ ToBoxes @ Framed[ + Pane[ + Grid[ + { + { Magnify[ RawBoxes @ TemplateBox[ { }, "ChatIconCodeAssistant" ], 5 ] }, + { + Style[ + "Welcome to Code Assistance Chat", + FontWeight -> Bold, + FontSize -> 17, + FontColor -> GrayLevel[ 0.25 ] + ] + }, + { "Ask me anything using the input field below." }, + { + Button[ + "View Tutorial \[RightGuillemet]", + MessageDialog[ "Not implemented yet." ], + Appearance -> None, + BaseStyle -> { "Link" } + ] + } + }, + BaseStyle -> { "Text", FontSize -> 13, FontColor -> GrayLevel[ 0.5 ], LineBreakWithin -> False }, + Spacings -> { 1, { 0, 1.25, 1.25, 0.75 } } + ], + Alignment -> { Center, Automatic }, + ImageSize -> { Scaled[ 1 ], Automatic }, + ImageSizeAction -> "ShrinkToFit" + ], + Alignment -> { Center, Automatic }, + Background -> RGBColor[ "#fcfdff" ], + FrameMargins -> { { 10, 10 }, { 10, 10 } }, + FrameStyle -> RGBColor[ "#ecf0f5" ], + ImageSize -> { Automatic, Automatic }, + RoundingRadius -> 10 + ] + } +] + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Package Footer*) diff --git a/Developer/StylesheetBuilder.wl b/Developer/StylesheetBuilder.wl index 0b8ba9ca..24cc420d 100644 --- a/Developer/StylesheetBuilder.wl +++ b/Developer/StylesheetBuilder.wl @@ -15,14 +15,6 @@ BuildStylesheets; BuildChatbookStylesheet; BuildWorkspaceStylesheet; -System`LinkedItems; -System`MenuAnchor; -System`MenuItem; -System`RawInputForm; -System`ToggleMenuItem; -System`Scope; -System`ClosingSaveDialog; - Begin[ "`Private`" ]; @@ -73,8 +65,8 @@ Get[ "Wolfram`Chatbook`" ]; (*tr*) -tr[name_?StringQ] := Dynamic[FEPrivate`FrontEndResource["ChatbookStrings", name]] -trBox[name_?StringQ] := DynamicBox[FEPrivate`FrontEndResource["ChatbookStrings", name]] +tr[ name_?StringQ ] := Dynamic[ FEPrivate`FrontEndResource[ "ChatbookStrings", name ] ] +trBox[ name_?StringQ ] := DynamicBox[ FEPrivate`FrontEndResource[ "ChatbookStrings", name ] ] (* ::Subsection::Closed:: *) @@ -101,11 +93,14 @@ $dropShadowConfig = <| $dropShadowPaneBox := $dropShadowPaneBox = With[ { img = createNinePatch @ $dropShadowConfig }, Function[ - PanelBox[ - #, - Appearance -> img, - ContentPadding -> False, - FrameMargins -> { { 0, 0 }, { 0, 0 } } + PaneBox[ + PanelBox[ + #, + Appearance -> img, + ContentPadding -> False, + FrameMargins -> { { 0, 0 }, { 0, 0 } } + ], + ImageMargins -> { { 40, 50 }, { 0, 0 } } ] ] ]; @@ -266,7 +261,7 @@ makeIconTemplateBoxStyle[ file_, icon_, boxes_ ] := $askMenuItem = MenuItem[ - "Ask AI Assistant", + "StylesheetContextMenuAskAI", KernelExecute[ With[ { $CellContext`nbo = InputNotebook[ ] }, @@ -286,7 +281,7 @@ $askMenuItem = MenuItem[ $excludeMenuItem = MenuItem[ - "Include/Exclude From AI Chat", + "StylesheetContextMenuIncludeExclude", KernelExecute[ With[ { $CellContext`nbo = InputNotebook[ ] }, @@ -305,10 +300,26 @@ $excludeMenuItem = MenuItem[ (*contextMenu*) -contextMenu[ a___, name_String, b___ ] := contextMenu[ a, FrontEndResource[ "ContextMenus", name ], b ]; -contextMenu[ a___, list_List, b___ ] := contextMenu @@ Flatten @ { a, list, b }; -contextMenu[ a___ ] := Flatten @ { a }; - +(* Note: + MenuItem cannot have Dynamic or FEPrivate`FrontEndResource expressions as its first argument. + Maybe this is a bug, but a workaround is to use ContextMenu -> Dynamic[Function[...][args]]. + The purpose of the Function is to inject resolved versions of FEPrivate`FrontEndResource. + Said differently, MenuItem can only take a String as its first argument, so we coerce the + FrontEnd to first resolve the string resources before it tries to resolve the ContextMenu. *) + +contextMenu[ a___, name_String, b___ ] := contextMenu[ a, FEPrivate`FrontEndResource[ "ContextMenus", name ], b ]; +contextMenu[ a : (_List | _FEPrivate`FrontEndResource).. ] := With[ { slot = Slot }, + Replace[ + Reap @ Module[ { i = 1 }, + Replace[ + FEPrivate`Join[ a ], + MenuItem[ s_String, rest__ ] :> ( Sow[ FEPrivate`FrontEndResource[ "ChatbookStrings", s ] ]; MenuItem[ slot[ i++ ], rest ] ), + { 2 } + ] + ], + { menu_FEPrivate`Join, { { resourceStrings__ } } } :> Dynamic[ Function[ menu ][ resourceStrings ] ] + ] +] (* ::Subsection::Closed:: *) @@ -360,7 +371,7 @@ assistantMenuInitializer[ name_String, color_ ] := ], Appearance -> $suppressButtonAppearance ], - tr["StylesheetAssistantMenuInitializerButtonTooltip"] + tr[ "StylesheetAssistantMenuInitializerButtonTooltip" ] ], RawBoxes @ TemplateBox[ { name, color }, "ChatMenuButton" ] }, @@ -387,7 +398,8 @@ assistantMenuInitializer[ name_String, color_ ] := -$feedbackButtons = Column[ { feedbackButton @ True, feedbackButton @ False }, Spacings -> { 0, { 0, 0.25, 0 } } ]; +$feedbackButtonsV := Column[ { feedbackButton @ True, feedbackButton @ False }, Spacings -> { 0, { 0, 0.25, 0 } } ]; +$feedbackButtonsH := Grid[ { { feedbackButton @ True, feedbackButton @ False } }, Spacings -> 0.2 ]; feedbackButton[ True ] := feedbackButton[ True , "ThumbsUp" ]; feedbackButton[ False ] := feedbackButton[ False, "ThumbsDown" ]; @@ -400,7 +412,7 @@ feedbackButton[ positive: True|False, name_String ] := RawBoxes @ TemplateBox[ { }, name<>"Inactive" ], RawBoxes @ TemplateBox[ { }, name<>"Active" ] ], - tr["StylesheetFeedbackButtonTooltip"] + tr[ "StylesheetFeedbackButtonTooltip" ] ], "LinkHand" ], diff --git a/Developer/VectorDatabases/DefinitionNotebooks/DocumentationURIs.nb b/Developer/VectorDatabases/DefinitionNotebooks/DocumentationURIs.nb new file mode 100644 index 00000000..be7361d9 --- /dev/null +++ b/Developer/VectorDatabases/DefinitionNotebooks/DocumentationURIs.nb @@ -0,0 +1,9665 @@ +(* Content-type: application/vnd.wolfram.mathematica *) + +(*** Wolfram Notebook File ***) +(* http://www.wolfram.com/nb *) + +(* Created By: SaveReadableNotebook *) +(* https://resources.wolframcloud.com/FunctionRepository/resources/SaveReadableNotebook *) + +Notebook[ + { + Cell[ + CellGroupData[ + { + Cell[ + "Code Assistance Documentation Vector Database", + "Title", + CellTags -> {"DefaultContent", "Name", "TemplateCell"}, + CellID -> 806838874 + ], + Cell[ + "VectorDatabaseObject based on Wolfram Language documentation and resources used for retrieval-augmented-generation in code assistance chat", + "Text", + CellTags -> {"DefaultContent", "Description", "TemplateCell"}, + CellID -> 163956104 + ], + Cell[ + TextData[ + { + "Details", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "Details", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Give a detailed description of the data, including information about the size, structure, and history of the content elements.\n\nThis section may include multiple cells, bullet lists, tables, hyperlinks and additional styles/structures as needed.\n\nAdd any other information that may be relevant, such as when the data was first created or how and why it is used within a given field. Include all relevant background or contextual information related to the data, its development, and its usage.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoDetails"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Details"}, + DefaultNewCellStyle -> "Notes", + CellTags -> {"Details", "TemplateCellGroup"}, + CellID -> 161845329 + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Data Definitions", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "ContentElements", + Cell[ + BoxData[ + FrameBox[ + Cell[ + TextData[ + { + "Define the content of the resource by assigning values to ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "ResourceData", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/ResourceData", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ". The ", + Cell[ + BoxData[ + StyleBox[ + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + FontSize -> (11 * Inherited) / 13, + ShowStringCharacters -> False + ], + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4, + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False} + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + Selectable -> False, + SelectWithContents -> True + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " icon inside ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "ResourceData", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/ResourceData", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " below represents the ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "ResourceObject", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/ResourceObject", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " defined within this notebook.\n\nEvaluating the ", + Cell[ + BoxData[ + StyleBox[ + RowBox[ + { + RowBox[ + { + "ResourceData", + "[", + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + FontSize -> (11 * Inherited) / 13, + ShowStringCharacters -> False + ], + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4, + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False} + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + Selectable -> False, + SelectWithContents -> True + ], + "]" + } + ], + "=", + "xxxx" + } + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " cell below defines the default content element of this resource, which will be returned by ", + Cell[ + BoxData[ + StyleBox[ + RowBox[ + { + TagBox[ + ButtonBox[ + StyleBox[ + "ResourceData", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/ResourceData", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + "[", + StyleBox["obj", "TI"], + "]" + } + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ".\n\nEvaluating the subsequent cells defines additional content elements with the specified element names. The element name is used to access the associated content via ", + Cell[ + BoxData[ + StyleBox[ + RowBox[ + { + TagBox[ + ButtonBox[ + StyleBox[ + "ResourceData", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/ResourceData", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + "[", + RowBox[ + {StyleBox["obj", "TI"], ",", StyleBox["element", "TI"]} + ], + "]" + } + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ".\n\nThe default content element is assigned a name either based on the ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "Head", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/Head", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " of the data or set to ", + Cell[ + BoxData[ + StyleBox[ + "\"Content\"", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ".\n\nDefine as many elements as needed using different element names. You can insert the icon using the \"Insert ResourceObject\" button in the \"Tools\" above.\n\nElements set to ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "CloudObject", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/CloudObject", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ", ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "File", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/File", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ", or ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "LocalObject", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/LocalObject", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " values will be interpreted as the content of those locations.\n\nEach content element must have a string name, preferably camel case. (Typical names describe the content element, and include ", + Cell[ + BoxData[ + StyleBox[ + "\"Dataset\"", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ", ", + Cell[ + BoxData[ + StyleBox[ + "\"Text\"", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " and ", + Cell[ + BoxData[ + StyleBox[ + "\"TimeSeries\"", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ").\n\nElements defined as functions are automatically applied to the other elements of the resource. For example, ", + Cell[ + BoxData[ + StyleBox[ + RowBox[ + { + RowBox[ + { + "ResourceData", + "[", + RowBox[ + { + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + FontSize -> (11 * Inherited) / 13, + ShowStringCharacters -> False + ], + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4, + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False} + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + Selectable -> False, + SelectWithContents -> True + ], + ",", + "\"Vertices\"" + } + ], + "]" + } + ], + "=", + RowBox[ + { + "(", + RowBox[{RowBox[{"VertexList", "[", "#Graph", "]"}], "&"}], + ")" + } + ] + } + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " will define an element named ", + Cell[ + BoxData[ + StyleBox[ + "\"Vertices\"", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " which is derived from the ", + Cell[ + BoxData[ + StyleBox[ + "\"Graph\"", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " element when requested by the user." + } + ], + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoContentElements"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Section", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "ContentElements"}, + CellTags -> { + "ContentElements", + "Data Definitions", + "TemplateCellGroup" + }, + CellID -> 41403987 + ], + Cell[ + CellGroupData[ + { + Cell[ + "Primary Content", + "Subsection", + Editable -> False, + Deletable -> False, + CellTags -> "PrimaryContent", + CellID -> 739468720 + ], + Cell[ + BoxData[ + RowBox[ + { + RowBox[ + { + RowBox[ + { + "ResourceData", + "[", + RowBox[ + { + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + ImageSizeCache -> {11.122, {2.90039, 9.09961}}, + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + ShowStringCharacters -> False, + FontSize -> (11 * Inherited) / 13 + ], + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False}, + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4 + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + SelectWithContents -> True, + Selectable -> False + ], + ",", + "\"VectorDatabase\"" + } + ], + "]" + } + ], + "=", + RowBox[ + { + RowBox[ + { + "WithCleanup", + "[", + "\[IndentingNewLine]", + RowBox[ + { + RowBox[ + { + "SetDirectory", + "[", + RowBox[{"CreateDirectory", "[", "]"}], + "]" + } + ], + ",", + "\[IndentingNewLine]", + RowBox[ + { + "VectorDatabaseObject", + "[", + RowBox[ + { + RowBox[{"File", "[", "#DatabasePath", "]"}], + ",", + RowBox[{"OverwriteTarget", "->", "True"}] + } + ], + "]" + } + ], + ",", + "\[IndentingNewLine]", + RowBox[{"ResetDirectory", "[", "]"}] + } + ], + "\[IndentingNewLine]", + "]" + } + ], + "&" + } + ] + } + ], + ";" + } + ] + ], + "Input", + CellTags -> "DefaultContent", + CellLabel -> "In[1]:=", + CellID -> 751296993 + ] + }, + Open + ] + ], + Cell[ + CellGroupData[ + { + Cell[ + "Additional Data Elements (optional)", + "Subsection", + Editable -> False, + Deletable -> False, + CellTags -> "AdditionalDataElements", + CellLabel -> "In[7]:=", + CellID -> 651134066 + ], + Cell[ + BoxData[ + { + RowBox[ + {RowBox[{"name", "=", "\"DocumentationURIs\""}], ";"} + ], + "\[IndentingNewLine]", + RowBox[ + { + RowBox[ + { + "dir", + "=", + RowBox[ + { + "FileNameJoin", + "[", + RowBox[ + { + "{", + RowBox[ + { + RowBox[ + { + "ParentDirectory", + "[", + RowBox[{RowBox[{"NotebookDirectory", "[", "]"}], ",", "3"}], + "]" + } + ], + ",", + "\"Assets/VectorDatabases\"", + ",", + "name" + } + ], + "}" + } + ], + "]" + } + ] + } + ], + ";" + } + ], + "\[IndentingNewLine]", + RowBox[ + { + RowBox[ + { + "zip", + "=", + RowBox[ + { + "CreateArchive", + "[", + RowBox[ + { + RowBox[ + { + "FileNames", + "[", + RowBox[{"All", ",", "dir", ",", "Infinity"}], + "]" + } + ], + ",", + RowBox[{"dir", "<>", "\".zip\""}], + ",", + RowBox[{"OverwriteTarget", "->", "True"}] + } + ], + "]" + } + ] + } + ], + ";" + } + ], + "\[IndentingNewLine]", + RowBox[ + { + RowBox[ + { + "obj", + "=", + RowBox[ + { + "CopyFile", + "[", + RowBox[ + { + "zip", + ",", + RowBox[ + { + "CloudObject", + "[", + RowBox[ + { + RowBox[ + {"\"VectorDatabases/\"", "<>", "name", "<>", "\".zip\""} + ], + ",", + RowBox[{"Permissions", "->", "\"Public\""}] + } + ], + "]" + } + ], + ",", + RowBox[{"OverwriteTarget", "->", "True"}] + } + ], + "]" + } + ] + } + ], + ";" + } + ], + "\[IndentingNewLine]", + RowBox[{RowBox[{"DeleteFile", "[", "zip", "]"}], ";"}] + } + ], + "Input", + CellLabel -> "In[7]:=", + CellID -> 96470356 + ], + Cell[ + BoxData[ + RowBox[ + { + RowBox[ + { + RowBox[ + { + "ResourceData", + "[", + RowBox[ + { + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + ImageSizeCache -> {11.122, {2.90039, 9.09961}}, + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + ShowStringCharacters -> False, + FontSize -> (11 * Inherited) / 13 + ], + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False}, + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4 + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + SelectWithContents -> True, + Selectable -> False + ], + ",", + "\"DatabaseDirectory\"" + } + ], + "]" + } + ], + "=", + "obj" + } + ], + ";" + } + ] + ], + "Input", + CellTags -> "DefaultContent", + CellLabel -> "In[12]:=", + CellID -> 874765044 + ], + Cell[ + BoxData[ + RowBox[ + { + RowBox[ + { + RowBox[ + { + "ResourceData", + "[", + RowBox[ + { + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + ImageSizeCache -> {11.122, {2.90039, 9.09961}}, + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + ShowStringCharacters -> False, + FontSize -> (11 * Inherited) / 13 + ], + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False}, + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4 + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + SelectWithContents -> True, + Selectable -> False + ], + ",", + "\"DatabasePath\"" + } + ], + "]" + } + ], + "=", + RowBox[ + { + "With", + "[", + RowBox[ + { + RowBox[ + { + "{", + RowBox[{"file", "=", RowBox[{"name", "<>", "\".wxf\""}]}], + "}" + } + ], + ",", + RowBox[ + { + RowBox[ + { + "FileNameJoin", + "[", + RowBox[ + {"{", RowBox[{"#DatabaseDirectory", ",", "file"}], "}"} + ], + "]" + } + ], + "&" + } + ] + } + ], + "]" + } + ] + } + ], + ";" + } + ] + ], + "Input", + CellTags -> "DefaultContent", + CellLabel -> "In[13]:=", + CellID -> 874765045 + ] + }, + Open + ] + ] + }, + Open + ] + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Examples", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "ExampleNotebook", + Cell[ + BoxData[ + FrameBox[ + Cell[ + TextData[ + { + "Demonstrate the data's usage, starting with the most basic use case and describing each example in a preceding text cell.\n\nWithin a group, individual examples can be delimited by inserting page breaks between them (using Tools \[FilledRightTriangle] Insert Delimiter).\n\nExamples should be grouped into Subsection and Subsubsection cells similarly to existing documentation pages. Here are some typical Subsection names and the types of examples they normally contain:\n\n ", + Cell[ + BoxData[ + StyleBox[ + TemplateBox[ + { + StyleBox[ + "\"\[FilledSmallSquare] \"", + FontColor -> RGBColor[0.8, 0.043, 0.008], + StripOnInput -> False + ], + StyleBox[ + "\"Basic Examples: \"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontSize -> 14, + StripOnInput -> False + ] + }, + "RowDefault" + ], + ShowStringCharacters -> False + ] + ] + ], + "most basic usage\n ", + Cell[ + BoxData[ + StyleBox[ + TemplateBox[ + { + StyleBox[ + "\"\[FilledSmallSquare] \"", + FontColor -> RGBColor[0.8, 0.043, 0.008], + StripOnInput -> False + ], + StyleBox[ + "\"Scope: \"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontSize -> 14, + StripOnInput -> False + ] + }, + "RowDefault" + ], + ShowStringCharacters -> False + ] + ] + ], + "show the breadth of the data\n ", + Cell[ + BoxData[ + StyleBox[ + TemplateBox[ + { + StyleBox[ + "\"\[FilledSmallSquare] \"", + FontColor -> RGBColor[0.8, 0.043, 0.008], + StripOnInput -> False + ], + StyleBox[ + "\"Applications: \"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontSize -> 14, + StripOnInput -> False + ] + }, + "RowDefault" + ], + ShowStringCharacters -> False + ] + ] + ], + "standard industry or academic applications\n ", + Cell[ + BoxData[ + StyleBox[ + TemplateBox[ + { + StyleBox[ + "\"\[FilledSmallSquare] \"", + FontColor -> RGBColor[0.8, 0.043, 0.008], + StripOnInput -> False + ], + StyleBox[ + "\"Properties and Relations: \"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontSize -> 14, + StripOnInput -> False + ] + }, + "RowDefault" + ], + ShowStringCharacters -> False + ] + ] + ], + "how the data relates to other data\n ", + Cell[ + BoxData[ + StyleBox[ + TemplateBox[ + { + StyleBox[ + "\"\[FilledSmallSquare] \"", + FontColor -> RGBColor[0.8, 0.043, 0.008], + StripOnInput -> False + ], + StyleBox[ + "\"Possible Issues: \"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontSize -> 14, + StripOnInput -> False + ] + }, + "RowDefault" + ], + ShowStringCharacters -> False + ] + ] + ], + "limitations or unexpected behavior a user might experience\n ", + Cell[ + BoxData[ + StyleBox[ + TemplateBox[ + { + StyleBox[ + "\"\[FilledSmallSquare] \"", + FontColor -> RGBColor[0.8, 0.043, 0.008], + StripOnInput -> False + ], + StyleBox[ + "\"Neat Examples: \"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontSize -> 14, + StripOnInput -> False + ] + }, + "RowDefault" + ], + ShowStringCharacters -> False + ] + ] + ], + "particularly interesting, unconventional, or otherwise unique usage" + } + ], + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoExampleNotebook"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Section", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "ExampleNotebook"}, + CellTags -> {"ExampleNotebook", "Examples", "TemplateCellGroup"}, + CellID -> 661218443 + ], + Cell[ + CellGroupData[ + { + Cell[ + "Basic Examples", + "Subsection", + CellLabel -> "In[4]:=", + CellID -> 462042388 + ], + Cell[ + TextData[ + { + "Get the ", + Cell[ + BoxData[ + TagBox[ + ButtonBox[ + StyleBox[ + "VectorDatabaseObject", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/VectorDatabaseObject", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ] + ], + "InlineFormula", + FontFamily -> "Source Sans Pro" + ], + ":" + } + ], + "Text", + CellTags -> "DefaultContent", + CellID -> 395385424 + ], + Cell[ + CellGroupData[ + { + Cell[ + BoxData[ + RowBox[ + { + "db", + "=", + RowBox[ + { + "ResourceData", + "[", + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + ImageSizeCache -> {11.122, {2.90039, 9.09961}}, + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + ShowStringCharacters -> False, + FontSize -> (11 * Inherited) / 13 + ], + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False}, + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4 + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + SelectWithContents -> True, + Selectable -> False + ], + "]" + } + ] + } + ] + ], + "Input", + CellTags -> "DefaultContent", + CellLabel -> "In[1]:=", + CellID -> 464452425 + ], + Cell[ + BoxData[ + InterpretationBox[ + RowBox[ + { + TagBox["VectorDatabaseObject", "SummaryHead"], + "[", + DynamicModuleBox[ + {Typeset`open$$ = False, Typeset`embedState$$ = "Ready"}, + TemplateBox[ + { + PaneSelectorBox[ + { + False -> + GridBox[ + { + { + PaneBox[ + ButtonBox[ + DynamicBox[ + FEPrivate`FrontEndResource["FEBitmaps", "SummaryBoxOpener"], + ImageSizeCache -> {10.869, {0.0, 10.869}} + ], + Appearance -> None, + BaseStyle -> { }, + ButtonFunction :> (Typeset`open$$ = True), + Evaluator -> Automatic, + Method -> "Preemptive" + ], + Alignment -> {Center, Center}, + ImageSize -> + Dynamic[ + { + Automatic, + Times[ + 3.5, + Times[ + CurrentValue["FontCapHeight"], + AbsoluteCurrentValue[Magnification]^(-1) + ] + ] + } + ] + ], + GridBox[ + { + { + RowBox[ + { + TagBox["\"ID: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["\"DocumentationURIs\"", "SummaryItem"] + } + ] + }, + { + RowBox[ + { + TagBox["\"Elements: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["683800", "SummaryItem"] + } + ] + } + }, + AutoDelete -> False, + BaseStyle -> { + ShowStringCharacters -> False, + NumberMarks -> False, + PrintPrecision -> 3, + ShowSyntaxStyles -> False + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Automatic}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{2}}, "Rows" -> {{Automatic}}} + ] + } + }, + AutoDelete -> False, + BaselinePosition -> {1, 1}, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Top}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + True -> + GridBox[ + { + { + PaneBox[ + ButtonBox[ + DynamicBox[ + FEPrivate`FrontEndResource["FEBitmaps", "SummaryBoxCloser"], + ImageSizeCache -> {10.869, {0.0, 10.869}} + ], + Appearance -> None, + BaseStyle -> { }, + ButtonFunction :> (Typeset`open$$ = False), + Evaluator -> Automatic, + Method -> "Preemptive" + ], + Alignment -> {Center, Center}, + ImageSize -> + Dynamic[ + { + Automatic, + Times[ + 3.5, + Times[ + CurrentValue["FontCapHeight"], + AbsoluteCurrentValue[Magnification]^(-1) + ] + ] + } + ] + ], + GridBox[ + { + { + RowBox[ + { + TagBox["\"ID: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["\"DocumentationURIs\"", "SummaryItem"] + } + ] + }, + { + RowBox[ + { + TagBox["\"Elements: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["683800", "SummaryItem"] + } + ] + }, + { + RowBox[ + { + TagBox["\"Vector length: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["256", "SummaryItem"] + } + ] + }, + { + RowBox[ + { + TagBox["\"Working precision: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["\"Integer8\"", "SummaryItem"] + } + ] + }, + { + RowBox[ + { + TagBox["\"Distance function: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["EuclideanDistance", "SummaryItem"] + } + ] + }, + { + RowBox[ + { + TagBox["\"Location: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox[ + TemplateBox[ + { + RowBox[ + { + "File", + "[", + RowBox[{"\[LeftSkeleton]", "1", "\[RightSkeleton]"}], + "]" + } + ], + RowBox[ + { + "File", + "[", + TemplateBox[ + { + "\"C:\\\\Users\\\\rhennigan\\\\AppData\\\\Local\\\\Temp\\\\DocumentationURIs-6dd5ca26-4e67-4d6f-ad1d-5859efeebde3-Extracted\\\\DocumentationURIs.wxf\"" + }, + "FileArgument" + ], + "]" + } + ] + }, + "ClickToCopy2" + ], + "SummaryItem" + ] + } + ] + } + }, + AutoDelete -> False, + BaseStyle -> { + ShowStringCharacters -> False, + NumberMarks -> False, + PrintPrecision -> 3, + ShowSyntaxStyles -> False + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Automatic}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{2}}, "Rows" -> {{Automatic}}} + ] + } + }, + AutoDelete -> False, + BaselinePosition -> {1, 1}, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Top}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ] + }, + Dynamic[Typeset`open$$], + ImageSize -> Automatic + ] + }, + "SummaryPanel" + ], + DynamicModuleValues :> { } + ], + "]" + } + ], + VectorDatabaseObject[ + <| + "DistanceFunction" -> EuclideanDistance, + "FeatureExtractor" -> Identity, + "GeneratedAssetLocation" -> + File[ + "C:\\Users\\rhennigan\\AppData\\Local\\Temp\\DocumentationURIs-6dd5ca26-4e67-4d6f-ad1d-5859efeebde3-Extracted\\DocumentationURIs.wxf" + ], + "ID" -> "DocumentationURIs", + "Location" -> + File[ + "C:\\Users\\rhennigan\\AppData\\Local\\Temp\\DocumentationURIs-6dd5ca26-4e67-4d6f-ad1d-5859efeebde3-Extracted\\DocumentationURIs.wxf" + ], + "ResolvedFeatureExtractor" -> Identity, + "VectorDatabaseInfo" -> <| + "DistanceFunction" -> "l2sq", + "WorkingPrecision" -> "i8", + "Connectivity" -> 16, + "ExpansionAdd" -> 256, + "ExpansionSearch" -> 2048, + "Capacity" -> 683800, + "Dimensions" -> 256 + |>, + "Version" -> 1.1, + "WorkingPrecision" -> "Integer8", + "Evaluator" -> "c++", + "DatabaseType" -> "USearch", + "MetadataKeys" -> { }, + "Dimensions" -> {683800, 256}, + "Hash" -> 63144803136871464942014094071819592114 + |> + ], + Editable -> False, + SelectWithContents -> True, + Selectable -> False + ] + ], + "Output", + CellTags -> "DefaultContent", + CellLabel -> "Out[1]=", + CellID -> 135685633 + ] + }, + Open + ] + ], + Cell["Search it:", "Text", CellID -> 477433615], + Cell[ + BoxData[ + RowBox[ + { + RowBox[ + { + "vector", + "=", + RowBox[ + { + "RandomInteger", + "[", + RowBox[ + { + RowBox[ + {"{", RowBox[{RowBox[{"-", "128"}], ",", "127"}], "}"} + ], + ",", + "256" + } + ], + "]" + } + ] + } + ], + ";" + } + ] + ], + "Input", + CellLabel -> "In[3]:=", + CellID -> 174568640 + ], + Cell[ + CellGroupData[ + { + Cell[ + BoxData[ + RowBox[ + { + "VectorDatabaseSearch", + "[", + RowBox[{"db", ",", "vector", ",", "\"Index\""}], + "]" + } + ] + ], + "Input", + CellLabel -> "In[5]:=", + CellID -> 14128918 + ], + Cell[ + BoxData[RowBox[{"{", "250003", "}"}]], + "Output", + CellLabel -> "Out[5]=", + CellID -> 8379989 + ] + }, + Open + ] + ] + }, + Open + ] + ], + Cell[ + "Scope & Additional Elements", + "Subsection", + CellID -> 979821957 + ], + Cell["Visualizations", "Subsection", CellID -> 50804313], + Cell["Analysis", "Subsection", CellID -> 866856397] + }, + Open + ] + ], + Cell[ + CellGroupData[ + { + Cell[ + "Source & Additional Information", + "Section", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Source & Additional Information"}, + CellTags -> {"Source & Additional Information", "TemplateSection"}, + CellID -> 871630328 + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Submitted By", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "ContributedBy", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Enter the name of the person, people or organization that should be publicly credited with submitting this data.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoContributedBy"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "ContributedBy"}, + DefaultNewCellStyle -> "Text", + CellTags -> { + "Contributed By", + "ContributedBy", + "Submitted By", + "TemplateCellGroup" + }, + CellID -> 731311331 + ], + Cell[ + "Wolfram Staff", + "Text", + CellEventActions -> { + Inherited, + {"KeyDown", "\t"} :> + Replace[ + SelectionMove[SelectedNotebook[], After, Cell]; + NotebookFind[ + SelectedNotebook[], + "TabNext", + Next, + CellTags, + AutoScroll -> True, + WrapAround -> True + ], + Blank[NotebookSelection] :> + SelectionMove[ + SelectedNotebook[], + All, + CellContents, + AutoScroll -> True + ] + ], + PassEventsDown -> False, + PassEventsUp -> False + }, + CellTags -> {"DefaultContent", "TabNext"}, + CellID -> 316640766 + ] + }, + Open + ] + ], + Cell[ + TextData[ + { + "Source/Reference Citation", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "Citation", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Give a bibliographic-style citation for the original source of the data and/or its components.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoCitation"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Citation"}, + DefaultNewCellStyle -> "Text", + CellTags -> { + "Citation", + "Source/Reference Citation", + "TemplateCellGroup" + }, + CellID -> 657892269 + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Detailed Source Information", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "Detailed Source Information", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Add bibliographic details about the original source and publication of the data.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoDetailedSourceInformation"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Detailed Source Information"}, + CellTags -> {"Detailed Source Information", "TemplateSection"}, + CellID -> 67505013 + ], + Cell[ + "Author/Creator", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDAuthor"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"Author/Creator", "SMDAuthor", "TemplateCellGroup"}, + CellID -> 62010071 + ], + Cell[ + "Source Title", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDTitle"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"SMDTitle", "Source Title", "TemplateCellGroup"}, + CellID -> 15581079 + ], + Cell[ + "Source Date", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDDate"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"SMDDate", "Source Date", "TemplateCellGroup"}, + CellID -> 251981362 + ], + Cell[ + "Source Publisher", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDPublisher"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"SMDPublisher", "Source Publisher", "TemplateCellGroup"}, + CellID -> 910715536 + ], + Cell[ + "Geographic Coverage", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDGeographicCoverage"}, + DefaultNewCellStyle -> "Text", + CellTags -> { + "Geographic Coverage", + "SMDGeographicCoverage", + "TemplateCellGroup" + }, + CellID -> 346798217 + ], + Cell[ + "Temporal Coverage", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDTemporalCoverage"}, + DefaultNewCellStyle -> "Text", + CellTags -> { + "SMDTemporalCoverage", + "TemplateCellGroup", + "Temporal Coverage" + }, + CellID -> 135354521 + ], + Cell[ + "Source Language", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDLanguage"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"SMDLanguage", "Source Language", "TemplateCellGroup"}, + CellID -> 146694705 + ], + Cell[ + "Rights", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDRights"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"Rights", "SMDRights", "TemplateCellGroup"}, + CellID -> 190531069 + ] + }, + Open + ] + ], + Cell[ + TextData[ + { + "Links", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "Links", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "List additional URLs or hyperlinks for external information related to the data.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoLinks"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Links"}, + DefaultNewCellStyle -> "Item", + CellTags -> {"Links", "TemplateCellGroup"}, + CellID -> 255897931 + ], + Cell[ + TextData[ + { + "Keywords", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "Keywords", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "List relevant terms that should be used to include the data in search results.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoKeywords"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Keywords"}, + DefaultNewCellStyle -> "Item", + CellTags -> {"Keywords", "TemplateCellGroup"}, + CellID -> 266337689 + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Categories", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "Categories", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Select any categories which the data covers.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoCategories"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Categories"}, + DefaultNewCellStyle -> "Item", + CellTags -> {"Categories", "TemplateCellGroup"}, + CellID -> 885722481 + ], + Cell[ + BoxData[ + TagBox[ + GridBox[ + { + { + TagBox[ + GridBox[ + { + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Agriculture"}], + "\" \"", + "\"Agriculture\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Computer Systems"}], + "\" \"", + "\"Computer Systems\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Economics"}], + "\" \"", + "\"Economics\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Geometry Data"}], + "\" \"", + "\"Geometry Data\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Healthcare"}], + "\" \"", + "\"Healthcare\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Language"}], + "\" \"", + "\"Language\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Mathematics"}], + "\" \"", + "\"Mathematics\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Politics"}], + "\" \"", + "\"Politics\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Statistics"}], + "\" \"", + "\"Statistics\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + } + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ], + TagBox[ + GridBox[ + { + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Astronomy"}], + "\" \"", + "\"Astronomy\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Culture"}], + "\" \"", + "\"Culture\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Education"}], + "\" \"", + "\"Education\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Government"}], + "\" \"", + "\"Government\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "History"}], + "\" \"", + "\"History\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Life Science"}], + "\" \"", + "\"Life Science\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Medicine"}], + "\" \"", + "\"Medicine\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Reference"}], + "\" \"", + "\"Reference\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Text & Literature"}], + "\" \"", + "\"Text & Literature\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + } + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ], + TagBox[ + GridBox[ + { + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Chemistry"}], + "\" \"", + "\"Chemistry\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Demographics"}], + "\" \"", + "\"Demographics\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Engineering"}], + "\" \"", + "\"Engineering\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Graphics"}], + "\" \"", + "\"Graphics\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Human Activities"}], + "\" \"", + "\"Human Activities\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Machine Learning"}], + "\" \"", + "\"Machine Learning\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Meteorology"}], + "\" \"", + "\"Meteorology\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Social Media"}], + "\" \"", + "\"Social Media\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Transportation"}], + "\" \"", + "\"Transportation\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + } + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ], + TagBox[ + GridBox[ + { + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Computational Universe"}], + "\" \"", + "\"Computational Universe\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Earth Science"}], + "\" \"", + "\"Earth Science\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Geography"}], + "\" \"", + "\"Geography\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Health"}], + "\" \"", + "\"Health\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Images"}], + "\" \"", + "\"Images\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Manufacturing"}], + "\" \"", + "\"Manufacturing\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Physical Sciences"}], + "\" \"", + "\"Physical Sciences\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Sociology"}], + "\" \"", + "\"Sociology\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + {"\"\""} + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ] + } + }, + AutoDelete -> False, + BaseStyle -> {"ControlStyle"}, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Top}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{2}}} + ], + "Grid" + ] + ], + "Output", + Editable -> False, + Deletable -> False, + TaggingRules -> { + "CheckboxData" -> "OEM6eJxVTm0KgkAUjMjSiG7iIcQKhMDwdYFVx1pa3WXf2x/evpUg6tcM88FMkeaUkMwGtK2DuCA57conuhf6YcWbq+aoJJVgZM6KIHZUoruc0pu3Dl5m2pdK8LBeg2O3dqLtxMP6012wCQacnnstqo0suSjD+BrZCQa/znLAmjBO/4PHahJ452N2WaCsmGYKLSP+OzRgG3yH++xAm5MS9QYdBUrS" + }, + CellTags -> {"Categories", "Categories-Checkboxes", "CheckboxCell"}, + CellID -> 460292996 + ] + }, + Open + ] + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Content Types", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "ContentTypes", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Select any of the types of data included in the content elements.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoContentTypes"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "ContentTypes"}, + DefaultNewCellStyle -> "Item", + CellTags -> {"Content Types", "ContentTypes", "TemplateCellGroup"}, + CellID -> 765263253 + ], + Cell[ + BoxData[ + TagBox[ + GridBox[ + { + { + TagBox[ + GridBox[ + { + { + TemplateBox[ + { + CheckboxBox[False, {False, "Audio"}], + "\" \"", + StyleBox[ + "\"Audio\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + { + TemplateBox[ + { + CheckboxBox[False, {False, "Image"}], + "\" \"", + StyleBox[ + "\"Image\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + { + TemplateBox[ + { + CheckboxBox["Vector Database", {False, "Vector Database"}], + "\" \"", + StyleBox[ + "\"Vector Database\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + } + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ], + TagBox[ + GridBox[ + { + { + TemplateBox[ + { + CheckboxBox[False, {False, "Entity Store"}], + "\" \"", + StyleBox[ + "\"Entity Store\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + { + TemplateBox[ + { + CheckboxBox[False, {False, "Numerical Data"}], + "\" \"", + StyleBox[ + "\"Numerical Data\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + { + TemplateBox[ + { + CheckboxBox[False, {False, "Video"}], + "\" \"", + StyleBox[ + "\"Video\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + } + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ], + TagBox[ + GridBox[ + { + { + TemplateBox[ + { + CheckboxBox[False, {False, "Geospatial Data"}], + "\" \"", + StyleBox[ + "\"Geospatial Data\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + { + TemplateBox[ + { + CheckboxBox[False, {False, "Text"}], + "\" \"", + StyleBox[ + "\"Text\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + {"\"\""} + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ], + TagBox[ + GridBox[ + { + { + TemplateBox[ + { + CheckboxBox[False, {False, "Graphs"}], + "\" \"", + StyleBox[ + "\"Graphs\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + { + TemplateBox[ + { + CheckboxBox[False, {False, "Time Series"}], + "\" \"", + StyleBox[ + "\"Time Series\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + {"\"\""} + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ] + } + }, + AutoDelete -> False, + BaseStyle -> {"ControlStyle", ShowStringCharacters -> False}, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Top}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{2}}} + ], + "Grid" + ] + ], + "Output", + Editable -> False, + Deletable -> False, + TaggingRules -> { + "CheckboxData" -> "OEM6eJxdjtEKgkAQRQk0EyV/oR/wI2QjECKjid5XnUjSnWVn9sG/b416qNfLPfeeKishBplHhHXjxXopIVEP7J7Y31ccHQcWKG7YCbndXotuNWNAasGJOa280KRl6ErYnB1ZdDJDrsgIGrnOFjnMNVYGMr/tRNHop79wWwfOWYeiFwLSyszgW8YglSnPoViboMjxQY+Lxjd8y0QnMiHLL8jkXYfLPUSLcwmFoimA2H9uVfQCKx5XrQ==" + }, + CellTags -> {"CheckboxCell", "ContentTypes", "ContentTypes-Checkboxes"}, + CellID -> 413260493 + ] + }, + Open + ] + ], + Cell[ + TextData[ + { + "Related Resource Objects", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "SeeAlso", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "List the names of published resource objects from any Wolfram repository that are related to this data.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoSeeAlso"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SeeAlso"}, + DefaultNewCellStyle -> "Item", + CellTags -> { + "Related Resource Objects", + "SeeAlso", + "TemplateCellGroup" + }, + CellID -> 398191659 + ], + Cell[ + TextData[ + { + "Related Symbols", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "RelatedSymbols", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "List documented, system-level Wolfram Language symbols related to the data.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoRelatedSymbols"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "RelatedSymbols"}, + DefaultNewCellStyle -> "Item", + CellTags -> {"Related Symbols", "RelatedSymbols", "TemplateCellGroup"}, + CellID -> 661598311 + ] + }, + Open + ] + ], + Cell[ + TextData[ + { + "Author Notes", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "AuthorNotes", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Include any notes you would like to be published along with the resource.\n\nThese notes will be available to all users and can include known limitations or possible improvements to the data.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoAuthorNotes"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Section", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "AuthorNotes"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"Author Notes", "AuthorNotes", "TemplateCellGroup"}, + CellID -> 823423117 + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Submission Notes", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "SubmissionNotes", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Enter any additional information that you would like to communicate to the reviewer here. This section will not be included in the published resource.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoSubmissionNotes"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Section", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SubmissionNotes"}, + DefaultNewCellStyle -> "Text", + CellTags -> { + "Submission Notes", + "SubmissionNotes", + "TemplateCellGroup" + }, + CellID -> 161504757 + ], + Cell[ + "This should be marked as non-discoverable, since it's not very useful without the relevant internal Chatbook code that interprets the results.", + "Text", + CellID -> 246497798 + ] + }, + Open + ] + ] + }, + Open + ] + ] + }, + Visible -> True, + TaggingRules -> { + "ResourceType" -> "Data", + "ResourceCreateNotebook" -> True, + "TemplateVersion" -> "2022.09.15", + "CreationTimestamp" -> 3932453782.0, + "UpdatedTimestamp" -> 3932453782.0, + "CompatibilityTest" -> + HoldComplete[ + BinaryDeserialize[ + BaseDecode[ + "OEM6eJzVWltT20YUji9cCg4d0ulM0yc95IFmEnJpZ3pJ20BtIHSAAGuSPrKWjmwNa62yuwL0U9o/0r/XsyvJNo5kJNu0qSeTyNLqO9+e237rjVuVD5q8H/DQd3auAwFSetx3K3LhJPRAudmPq7K67+LftW3fwX8Wdj6ElMm1R+9A6OdHYb8DQrjms7GlRxDahxO8aDRDIcBX7ygLwb0nH+xc4hVV+i2uoMP5BY6qH3hSyUabdrue3z0NGUjSOAXJQ2FDOwqA1FtUUaRZf+vbkMty4TfG7Qs9LAZ81OS+gmt1TFXPreXN/AjAkWQjtUciqaDfZB7SPm+B6/neKN3z4SuWJpW+ljVU1o9CxpDY5scPEwOn0EWqIJCp63VDYVwzmO7roqROIeDSU1xEMWCMIxOgmolfRS7vUo+FAiNTkfePqc1A7ftSUcbIV3kM3cVpnD2VWxttfiMyK0QJzIffuaft1Q5pYOYQ+rZ+012ILZOHuc415KjUab0aY5GAeUrfJoyrZoVUzkn1p19GblRfrRjymL+SfFOU/GO3nuOlGgFtb6XFr3xTBFL+WBQ1vXgbKgwjOLqgVjDSjNqwjXk1R9hVXXQtYDQCB3FX33DmYCAxMX35a1HgY+FdIuD5ZdwW9gTgNyGXznyZtIMMb7TKotMgAN8583vUdxg4TWBMTnTMvCxM8BF+Le0lG2Gx4yUIZL0NfZyAAm1uT/AwmB0Ua7exzfQVtoNLTOgvmzioy4UH8mmzB/ZFh1/j7bXhbW2dNNJn5tsa2qMhU6a+fZXBlHye3iIQ12ZmqAt3s0Eg5EWbnwUOXid9Pz/KcwC/EeAa3lhKS2B5j/EOZec9vaSNelR+X9TsHqg3nuOAHzei4uW6S307ava4Z0PLo4x3R4k1EmJC4SqJ6ys2ZepfZFGn+HTdPNVrEoEPIeCsyYPEA8xJDZ7gcjGY700DI2DpkrLQFqEp7Rm7RJnFLr1Iky6RIfJlWQp+p0yNJVJm3OoND6X+PIKrgT8zfRwXiDwsS/lRKOEAutSO9rs+F3F3SmMt6zoa2cX3qqilDNyxwptUhjOamdRjq3LxAN80jXG3rN+6oNI2dtPi3EoJS2IVmQP2RSpB3gXd3GpECW1U86Ievd/SdWn4yaV97NldzNTlfd8Yi25xcm3AOmfiCXDhvpfOSA5Who9gO0NvD8yP2KzIndLLIPW579mUHQseAHrL6LlpOY8Qzd5EVJNm2NiWktue0d4ncrt0bQcJWxIh/aivc2h524iRNp8PnEkTskYM0CEo6uj9QbIDI8tNT8UbkIfxiGen4ILQ2W2lj4bdZT5RGTE6RivePQ32UPEWtH6APv9o63nPfB5v4Z5gls3KhJ1ECX3/OBelnKAvhzNJwX+Xi4SbwAvaBWJjQMrp9rNczHi1y8qD2NjUQv7OTE5W9gW9V0TPTwX1ian449mjUELW34W1aXT+Ri6PcWGfX7b/EyU/VbdAgOe39qtx6dycObhGwT/LhbkLyZ5P+oZ7phbqT3LxZ1PmZXGLSvGfi/njvxXgM5H8hGT3D7nzILagAfaf8QqZRXe/KrhcZartqalOKbf3J/zGnv44jtUWBuNmJ8vuucLOU37PEpy5iO6//tSfja3h6dHSv3RUMAc9n9l6S2+xsF+QsNP3zESx1PnEDjwX+DiFhqcgg56zGOuP7Jlt5RejNqDGk7fcxOaBXmBeK0S350S2yc1Mbw5+XaTM0yv4MRWY71qg1MZUdGP09C4+KCN1XQLkfqKR49npzp10zjaYs6RBI3162wHgUINioxpOaXWkcY11sZKQdbnwvufZvdwi/dZ8TJHeP8QBGIVYe5I/2j1PWn6CawlcRT0sWSvRddaLl5svLC4sLZyExV1L9cB6z5mLDrVin1uKW24SMCtudyzaHB4U39o3GqNqmPxduUlJ79aokNpKByzbCE3HcgXvW9Ty4QppJWSfWJLjnz5YLg4K9TT6NNJI1hUXiCQtuA5weQFn02pxK+KhdeXJnoZWIrJoqHgfI4BtkkWWzX3EVZh0OOdRQjia4tN+gEM7DFLrr3MOpGtyq/j5bXwMnKb/W4QWnpPm5RdZEm30LHRM+tRm+h1Wfrad+kNne1L2w0PSvIVsuKro0OqxqTRrVktppXpxx+VtFPL/r4Fhvt402TSi+eXCLmUSBiO+PoU+v4SdfqCinWuKG4h0WyzHh67HJN57vsOv2p7CWcYj4mX0Hz1LhOU=" + ] + ] + ], + "DefinitionNotebookFramework" -> "DefinitionNotebookClient", + "RuntimeConfiguration" -> { + "Contexts" -> {"DataResource`", "DataResource`DefinitionNotebook`"}, + "DefaultContentMethod" -> "Legacy", + "HintPods" -> True, + "LoadingMethod" -> "Paclet", + "PacletName" -> "DataResource", + "SourceID" -> "aab60bd760a6c130942c461f106d46d75083799b" + }, + "ToolsOpen" -> True, + "StatusMessage" -> "", + "SubmissionReviewData" -> {"Review" -> False}, + "AutoUpdate" -> True + }, + CreateCellID -> True, + StyleDefinitions -> + Notebook[ + { + Cell[StyleData[StyleDefinitions -> "Default.nb"]], + Cell[ + StyleData[All, "Working"], + WindowToolbars -> { }, + DockedCells -> { + Cell[ + BoxData[TemplateBox[{}, "MainGridTemplate"]], + "DockedCell", + CellMargins -> {{-10, -10}, {-8, -8}}, + CellFrame -> 0, + Background -> RGBColor[0.16078, 0.40392, 0.56078], + CellTags -> {"MainDockedCell"}, + CacheGraphics -> False + ], + Cell[ + BoxData[TemplateBox[{}, "ToolsGridTemplate"]], + "DockedCell", + TaggingRules -> {"Tools" -> True}, + CellTags -> {"ToolbarDockedCell"}, + CellFrameMargins -> {{0, 0}, {2, 2}}, + CellFrame -> {{0, 0}, {1, 0}}, + CacheGraphics -> False, + CellOpen -> + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ToolsOpen"}, + True + ] + ] + ] + }, + PrivateNotebookOptions -> { + "FileOutlineCache" -> False, + "SafeFileOpen" -> "IgnoreCache" + }, + CellLabelAutoDelete -> False, + CodeAssistOptions -> {"AutoDetectHyperlinks" -> False}, + AutoQuoteCharacters -> { }, + PasteAutoQuoteCharacters -> { } + ], + Cell["Hint Styles", "Section"], + Cell[ + StyleData[ + "MoreInfoText", + StyleDefinitions -> StyleData["Text"] + ], + FontColor -> GrayLevel[0.25] + ], + Cell[ + StyleData[ + "ErrorText", + StyleDefinitions -> StyleData["Text"] + ], + ShowCellBracket -> False, + CellMargins -> {{66, Inherited}, {10, 10}}, + CellElementSpacings -> {"CellMinHeight" -> 0, "ClosedCellHeight" -> 0}, + FontWeight -> Bold, + FontColor -> RGBColor[1, 0, 0] + ], + Cell[ + StyleData[ + "WarningText", + StyleDefinitions -> StyleData["Text"] + ], + ShowCellBracket -> False, + CellMargins -> {{66, 35}, {0, 0}}, + FontSize -> 14, + GridBoxOptions -> {BaseStyle -> {}} + ], + Cell["Template Boxes", "Section"], + Cell[ + StyleData["MoreInfoOpenerIconTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + PaneSelectorBox[ + { + False -> + GraphicsBox[ + { + Thickness[0.090909], + StyleBox[ + { + JoinedCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJJIGYC4oSnF5RuVyo58OlumvteXcIBxj//Pfjx0tky\nDp8u+SYJzFB0kGQJ49MtUnBYIKV/V4UNRis5GHKskYl6AlOnDNUHM0cFaq4I\nnD/niMKGogx+OB+oO8X6Phtcf/+hrxox/Qxw80HKftZ9sYfZ/7BKZJ37w1f2\nMPfB+DD3w/h+SQIRlluE4foh9vDBzYfQHHD7izMmvq2xZ4K7r9CW6/rigr/2\nMPfD+DD/wfgw/8P0w8IHZj4s/GD2w8IX5j708AcA2Xetpg==\n " + ], + CurveClosed -> {1} + ] + }, + { + JoinForm[{"Miter", 3.25}], + Thickness[0.045818], + RGBColor[0.62744, 0.62744, 0.62744, 1.0] + }, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + }, + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0} + } + }, + { + CompressedData[ + "\n1:eJxTTMoPSmViYGCQBGIQ3b48/JRRi4jD3qBpin2m8g5n6j32194VhvNZnvdo\nvPUVdoh2sntxM0feQfiT4/m0q0IOQNnSwtvyDmxCIvbHYoQcMhnyG1lUFRyk\neR/oTlAAym/iKVyTjeAf2aiXt/gggt+odqhtubgiXP+k00CLYxXh5mdrf5t+\nd7Ii3P5LDPeYOE8pwt33vfTBHMGnig4w98P4j5fOPqJgIArn539oPRlyUBSu\n/9OGgOxZ5mJw88sKgS5aKwa3XzOm/9DXF2Jw98H4MPfD+DD/wfTD/A8zHxY+\nMPth4QdzHyx80cMfAIsMpwk=\n " + ], + CompressedData[ + "\n1:eJxTTMoPSmViYGCQB2IQXTFnkfJOGwmHsNp125Lq+R1g/G8aMf2HvvI4KP39\nVvrgjgAGH6b+c19wicp0IQeBKrPVduICcL6EWjDr4ksCqPLTBeH8211/U7+n\nCMH5S+7v45tjLAznX773gHvySwS/qdhtyrc2ETj/04aA7FnfReH8RxHi2y8e\nEIPzNUHOzRCH8x8vnX1E4QOCP+/98mPe5RJw/o9goAoWSTj/6vMs7W/TJR0O\nX9ZOlVwk4PB2no3OlVsI/jKgcRs+STlonhY4vstCzCFoh1zr64syDkBXssXP\nEHO4WvFSzbADwa9JNAo1yJKA82H+gfFh/oXxA29JA7Ug+GY2e4OmJQrB+f83\nVX/aMEEQzrerjFhhelYAzofFB3r8AgApYdcE\n " + ] + } + ] + }, + {FaceForm[RGBColor[0.62744, 0.62744, 0.62744, 1.0]]}, + StripOnInput -> False + ] + }, + ImageSize -> {11.0, 11.0}, + PlotRange -> {{0.0, 11.0}, {0.0, 11.0}}, + AspectRatio -> Automatic + ], + True -> + GraphicsBox[ + { + Thickness[0.090909], + StyleBox[ + { + JoinedCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJJIGYC4oSnF5RuVyo58OlumvteXcIBxj//Pfjx0tky\nDp8u+SYJzFB0kGQJ49MtUnBYIKV/V4UNRis5GHKskYl6AlOnDNUHM0cFaq4I\nnD/niMKGogx+OB+oO8X6Phtcf/+hrxox/Qxw80HKftZ9sYfZ/7BKZJ37w1f2\nMPfB+DD3w/h+SQIRlluE4foh9vDBzYfQHHD7izMmvq2xZ4K7r9CW6/rigr/2\nMPfD+DD/wfgw/8P0w8IHZj4s/GD2w8IX5j708AcA2Xetpg==\n " + ], + CurveClosed -> {1} + ] + }, + { + JoinForm[{"Miter", 3.25}], + Thickness[0.045818], + RGBColor[0.5, 0.5, 0.5, 1.0] + }, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJJIGYC4oSnF5RuVyo58OlumvteXcIBxj//Pfjx0tky\nDp8u+SYJzFB0kGQJ49MtUnBYIKV/V4UNRis5GHKskYl6AlOnDNUHM0cFaq4I\nnD/niMKGogx+OB+oO8X6Phtcf/+hrxox/Qxw80HKftZ9sYfZ/7BKZJ37w1f2\nMPfB+DD3w/h+SQIRlluE4foh9vDBzYfQHHD7izMmvq2xZ4K7r9CW6/rigr/2\nMPfD+DD/wfgw/8P0w8IHZj4s/GD2w8IX5j708AcA2Xetpg==\n " + ] + ] + }, + {FaceForm[RGBColor[0.5, 0.5, 0.5, 1.0]]}, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + }, + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0} + } + }, + { + CompressedData[ + "\n1:eJxTTMoPSmViYGCQBGIQ3b48/JRRi4jD3qBpin2m8g5n6j32194VhvNZnvdo\nvPUVdoh2sntxM0feQfiT4/m0q0IOQNnSwtvyDmxCIvbHYoQcMhnyG1lUFRyk\neR/oTlAAym/iKVyTjeAf2aiXt/gggt+odqhtubgiXP+k00CLYxXh5mdrf5t+\nd7Ii3P5LDPeYOE8pwt33vfTBHMGnig4w98P4j5fOPqJgIArn539oPRlyUBSu\n/9OGgOxZ5mJw88sKgS5aKwa3XzOm/9DXF2Jw98H4MPfD+DD/wfTD/A8zHxY+\nMPth4QdzHyx80cMfAIsMpwk=\n " + ], + CompressedData[ + "\n1:eJxTTMoPSmViYGCQB2IQXTFnkfJOGwmHsNp125Lq+R1g/G8aMf2HvvI4KP39\nVvrgjgAGH6b+c19wicp0IQeBKrPVduICcL6EWjDr4ksCqPLTBeH8211/U7+n\nCMH5S+7v45tjLAznX773gHvySwS/qdhtyrc2ETj/04aA7FnfReH8RxHi2y8e\nEIPzNUHOzRCH8x8vnX1E4QOCP+/98mPe5RJw/o9goAoWSTj/6vMs7W/TJR0O\nX9ZOlVwk4PB2no3OlVsI/jKgcRs+STlonhY4vstCzCFoh1zr64syDkBXssXP\nEHO4WvFSzbADwa9JNAo1yJKA82H+gfFh/oXxA29JA7Ug+GY2e4OmJQrB+f83\nVX/aMEEQzrerjFhhelYAzofFB3r8AgApYdcE\n " + ] + } + ] + }, + {FaceForm[RGBColor[0.99998, 0.99998, 0.99998, 1.0]]}, + StripOnInput -> False + ] + }, + ImageSize -> {11.0, 11.0}, + PlotRange -> {{0.0, 11.0}, {0.0, 11.0}}, + AspectRatio -> Automatic + ] + }, + Dynamic[CurrentValue["MouseOver"]], + ImageSize -> Automatic, + FrameMargins -> 0 + ] + ]) + } + ], + Cell[ + StyleData["MoreInfoOpenerButtonTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + AdjustmentBox[ + DynamicModuleBox[ + { + RSNB`mPosRegion$$, + RSNB`attachPos$$, + RSNB`offsetPos$$, + RSNB`horizontalRegion$$, + RSNB`verticalRegion$$, + RSNB`chooseAttachLocation$$ + }, + TagBox[ + TemplateBox[ + { + TemplateBox[{}, "MoreInfoOpenerIconTemplate"], + "\"Click for more information\"" + }, + "PrettyTooltipTemplate" + ], + EventHandlerTag[ + { + "MouseDown" :> + AttachCell[ + ParentBox[EvaluationBox[]], + #2, + RSNB`chooseAttachLocation$$[], + RemovalConditions -> {"EvaluatorQuit", "MouseClickOutside"} + ], + Method -> "Preemptive", + PassEventsDown -> Automatic, + PassEventsUp -> True + } + ] + ], + DynamicModuleValues :> { + { + DownValues[RSNB`mPosRegion$$] = { + HoldPattern[RSNB`mPosRegion$$[]] :> + RSNB`mPosRegion$$[Ceiling[MousePosition["WindowScaled"]*3]], + HoldPattern[ + RSNB`mPosRegion$$[ + Pattern[RSNB`reg, {Blank[Integer], Blank[Integer]}] + ] + ] :> RSNB`reg, + HoldPattern[RSNB`mPosRegion$$[BlankNullSequence[]]] :> None + } + }, + { + DownValues[RSNB`attachPos$$] = { + HoldPattern[ + RSNB`attachPos$$[ + { + Pattern[RSNB`h$, Blank[Integer]], + Pattern[RSNB`v$, Blank[Integer]] + } + ] + ] :> { + RSNB`horizontalRegion$$[RSNB`h$], + RSNB`verticalRegion$$[RSNB`v$] + } + } + }, + { + DownValues[RSNB`offsetPos$$] = { + HoldPattern[ + RSNB`offsetPos$$[ + { + Pattern[RSNB`h$, Blank[Integer]], + Pattern[RSNB`v$, Blank[Integer]] + } + ] + ] :> { + RSNB`horizontalRegion$$[4 - RSNB`h$], + RSNB`verticalRegion$$[4 - RSNB`v$] + } + } + }, + { + DownValues[RSNB`horizontalRegion$$] = { + HoldPattern[RSNB`horizontalRegion$$[1]] :> Left, + HoldPattern[RSNB`horizontalRegion$$[2]] :> Center, + HoldPattern[RSNB`horizontalRegion$$[3]] :> Right + } + }, + { + DownValues[RSNB`verticalRegion$$] = { + HoldPattern[RSNB`verticalRegion$$[1]] :> Top, + HoldPattern[RSNB`verticalRegion$$[2]] :> Top, + HoldPattern[RSNB`verticalRegion$$[3]] :> Top + } + }, + { + DownValues[RSNB`chooseAttachLocation$$] = { + HoldPattern[RSNB`chooseAttachLocation$$[]] :> + With[ { RSNB`p$ = RSNB`mPosRegion$$[] }, + Apply[ + Sequence, + { + RSNB`offsetPos$$[RSNB`p$], + {-30, 30}, + RSNB`attachPos$$[RSNB`p$] + } + ] + ] + } + } + } + ], + BoxBaselineShift -> -0.5, + BoxMargins -> 0.2 + ] + ]) + } + ], + Cell[ + StyleData["InlineMoreInfoOpenerButtonTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + AdjustmentBox[ + DynamicModuleBox[ + { + RSNB`mPosRegion$$, + RSNB`attachPos$$, + RSNB`offsetPos$$, + RSNB`horizontalRegion$$, + RSNB`verticalRegion$$, + RSNB`chooseAttachLocation$$ + }, + TagBox[ + TemplateBox[ + {TemplateBox[{}, "MoreInfoOpenerIconTemplate"], #4}, + "PrettyTooltipTemplate" + ], + EventHandlerTag[ + { + "MouseDown" :> + AttachCell[ + ParentBox[EvaluationBox[]], + #2, + RSNB`chooseAttachLocation$$[], + RemovalConditions -> {"EvaluatorQuit", "MouseClickOutside"} + ], + Method -> "Preemptive", + PassEventsDown -> Automatic, + PassEventsUp -> True + } + ] + ], + DynamicModuleValues :> { + { + DownValues[RSNB`mPosRegion$$] = { + HoldPattern[RSNB`mPosRegion$$[]] :> + RSNB`mPosRegion$$[Ceiling[MousePosition["WindowScaled"]*3]], + HoldPattern[ + RSNB`mPosRegion$$[ + Pattern[RSNB`reg, {Blank[Integer], Blank[Integer]}] + ] + ] :> RSNB`reg, + HoldPattern[RSNB`mPosRegion$$[BlankNullSequence[]]] :> None + } + }, + { + DownValues[RSNB`attachPos$$] = { + HoldPattern[ + RSNB`attachPos$$[ + { + Pattern[RSNB`h$, Blank[Integer]], + Pattern[RSNB`v$, Blank[Integer]] + } + ] + ] :> { + RSNB`horizontalRegion$$[RSNB`h$], + RSNB`verticalRegion$$[RSNB`v$] + } + } + }, + { + DownValues[RSNB`offsetPos$$] = { + HoldPattern[ + RSNB`offsetPos$$[ + { + Pattern[RSNB`h$, Blank[Integer]], + Pattern[RSNB`v$, Blank[Integer]] + } + ] + ] :> { + RSNB`horizontalRegion$$[4 - RSNB`h$], + RSNB`verticalRegion$$[4 - RSNB`v$] + } + } + }, + { + DownValues[RSNB`horizontalRegion$$] = { + HoldPattern[RSNB`horizontalRegion$$[1]] :> Left, + HoldPattern[RSNB`horizontalRegion$$[2]] :> Center, + HoldPattern[RSNB`horizontalRegion$$[3]] :> Right + } + }, + { + DownValues[RSNB`verticalRegion$$] = { + HoldPattern[RSNB`verticalRegion$$[1]] :> Top, + HoldPattern[RSNB`verticalRegion$$[2]] :> Top, + HoldPattern[RSNB`verticalRegion$$[3]] :> Top + } + }, + { + DownValues[RSNB`chooseAttachLocation$$] = { + HoldPattern[RSNB`chooseAttachLocation$$[]] :> + With[ { RSNB`p$ = RSNB`mPosRegion$$[] }, + Apply[ + Sequence, + { + RSNB`offsetPos$$[RSNB`p$], + {-30, 30}, + RSNB`attachPos$$[RSNB`p$] + } + ] + ] + } + } + } + ], + BoxBaselineShift -> -0.5, + BoxMargins -> 0.2 + ] + ]) + } + ], + Cell[ + StyleData["ClickToCopyTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + PaneSelectorBox[ + { + False -> + TagBox[ + GridBox[ + { + { + #1, + ButtonBox[ + GraphicsBox[ + { + GrayLevel[0.85], + Thickness[NCache[2/45, 0.044444]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {10.5, 18.75}, + {10.5, 18.0}, + {9.0, 18.0}, + {9.0, 15.75}, + {13.5, 15.75}, + {13.5, 18.0}, + {12.0, 18.0}, + {12.0, 18.75} + }, + { + {6.0, 18.0}, + {6.0, 4.5}, + {16.5, 4.5}, + {16.5, 18.0}, + {14.25, 18.0}, + {14.25, 17.25}, + {15.75, 17.25}, + {15.75, 5.25}, + {6.75, 5.25}, + {6.75, 17.25}, + {8.25, 17.25}, + {8.25, 18.0} + }, + { + {9.75, 17.25}, + {12.75, 17.25}, + {12.75, 16.5}, + {9.75, 16.5} + } + } + ], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {8.25, 14.25}, + {14.25, 14.25}, + {14.25, 13.5}, + {8.25, 13.5} + }, + { + {8.25, 12.0}, + {14.25, 12.0}, + {14.25, 11.25}, + {8.25, 11.25} + }, + {{8.25, 9.75}, {14.25, 9.75}, {14.25, 9.0}, {8.25, 9.0}}, + {{8.25, 7.5}, {14.25, 7.5}, {14.25, 6.75}, {8.25, 6.75}} + } + ] + }, + ImageSize -> 12 + ], + ButtonFunction :> Null, + Appearance -> {"Default" -> None, "Hover" -> None, "Pressed" -> None}, + Evaluator -> Automatic, + Method -> "Preemptive" + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0.4}}} + ], + "Grid" + ], + True -> + DynamicModuleBox[ + {RSNB`clickTime$$ = 0.0, RSNB`timeout$$ = 3.0}, + TagBox[ + GridBox[ + { + { + #1, + TagBox[ + ButtonBox[ + DynamicBox[ + ToBoxes[ + Refresh[ + If[ AbsoluteTime[] - RSNB`clickTime$$ > RSNB`timeout$$, + RawBoxes[ + TemplateBox[ + { + PaneSelectorBox[ + { + False -> + GraphicsBox[ + { + GrayLevel[0.65], + Thickness[NCache[2/45, 0.044444]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {10.5, 18.75}, + {10.5, 18.0}, + {9.0, 18.0}, + {9.0, 15.75}, + {13.5, 15.75}, + {13.5, 18.0}, + {12.0, 18.0}, + {12.0, 18.75} + }, + { + {6.0, 18.0}, + {6.0, 4.5}, + {16.5, 4.5}, + {16.5, 18.0}, + {14.25, 18.0}, + {14.25, 17.25}, + {15.75, 17.25}, + {15.75, 5.25}, + {6.75, 5.25}, + {6.75, 17.25}, + {8.25, 17.25}, + {8.25, 18.0} + }, + { + {9.75, 17.25}, + {12.75, 17.25}, + {12.75, 16.5}, + {9.75, 16.5} + } + } + ], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {8.25, 14.25}, + {14.25, 14.25}, + {14.25, 13.5}, + {8.25, 13.5} + }, + { + {8.25, 12.0}, + {14.25, 12.0}, + {14.25, 11.25}, + {8.25, 11.25} + }, + {{8.25, 9.75}, {14.25, 9.75}, {14.25, 9.0}, {8.25, 9.0}}, + {{8.25, 7.5}, {14.25, 7.5}, {14.25, 6.75}, {8.25, 6.75}} + } + ] + }, + ImageSize -> 12 + ], + True -> + GraphicsBox[ + { + RGBColor[0.98824, 0.41961, 0.20392], + Thickness[NCache[2/45, 0.044444]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {10.5, 18.75}, + {10.5, 18.0}, + {9.0, 18.0}, + {9.0, 15.75}, + {13.5, 15.75}, + {13.5, 18.0}, + {12.0, 18.0}, + {12.0, 18.75} + }, + { + {6.0, 18.0}, + {6.0, 4.5}, + {16.5, 4.5}, + {16.5, 18.0}, + {14.25, 18.0}, + {14.25, 17.25}, + {15.75, 17.25}, + {15.75, 5.25}, + {6.75, 5.25}, + {6.75, 17.25}, + {8.25, 17.25}, + {8.25, 18.0} + }, + { + {9.75, 17.25}, + {12.75, 17.25}, + {12.75, 16.5}, + {9.75, 16.5} + } + } + ], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {8.25, 14.25}, + {14.25, 14.25}, + {14.25, 13.5}, + {8.25, 13.5} + }, + { + {8.25, 12.0}, + {14.25, 12.0}, + {14.25, 11.25}, + {8.25, 11.25} + }, + {{8.25, 9.75}, {14.25, 9.75}, {14.25, 9.0}, {8.25, 9.0}}, + {{8.25, 7.5}, {14.25, 7.5}, {14.25, 6.75}, {8.25, 6.75}} + } + ] + }, + ImageSize -> 12 + ] + }, + Dynamic[CurrentValue["MouseOver"]], + ImageSize -> Automatic, + FrameMargins -> 0 + ], + "\"Click to copy to the clipboard\"" + }, + "PrettyTooltipTemplate" + ] + ], + RawBoxes[ + TemplateBox[ + { + GraphicsBox[ + { + RGBColor[0, NCache[2/3, 0.66667], 0], + Thickness[NCache[2/45, 0.044444]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {10.5, 18.75}, + {10.5, 18.0}, + {9.0, 18.0}, + {9.0, 15.75}, + {13.5, 15.75}, + {13.5, 18.0}, + {12.0, 18.0}, + {12.0, 18.75} + }, + { + {6.0, 18.0}, + {6.0, 4.5}, + {16.5, 4.5}, + {16.5, 18.0}, + {14.25, 18.0}, + {14.25, 17.25}, + {15.75, 17.25}, + {15.75, 5.25}, + {6.75, 5.25}, + {6.75, 17.25}, + {8.25, 17.25}, + {8.25, 18.0} + }, + { + {9.75, 17.25}, + {12.75, 17.25}, + {12.75, 16.5}, + {9.75, 16.5} + } + } + ], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {8.25, 14.25}, + {14.25, 14.25}, + {14.25, 13.5}, + {8.25, 13.5} + }, + { + {8.25, 12.0}, + {14.25, 12.0}, + {14.25, 11.25}, + {8.25, 11.25} + }, + {{8.25, 9.75}, {14.25, 9.75}, {14.25, 9.0}, {8.25, 9.0}}, + {{8.25, 7.5}, {14.25, 7.5}, {14.25, 6.75}, {8.25, 6.75}} + } + ] + }, + ImageSize -> 12 + ], + "\"Copied\"" + }, + "PrettyTooltipTemplate" + ] + ] + ], + UpdateInterval -> 1, + TrackedSymbols :> {RSNB`clickTime$$} + ], + StandardForm + ], + Evaluator -> "System" + ], + ButtonFunction :> + (RSNB`clickTime$$ = AbsoluteTime[]; + CopyToClipboard[BinaryDeserialize[BaseDecode[#2], Defer]]), + Appearance -> {"Default" -> None, "Hover" -> None, "Pressed" -> None}, + Method -> "Queued", + Evaluator -> "System" + ], + MouseAppearanceTag["LinkHand"] + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0.4}}} + ], + "Grid" + ], + DynamicModuleValues :> { } + ] + }, + Dynamic[CurrentValue["MouseOver"]], + ImageSize -> Automatic, + FrameMargins -> 0 + ] + ]) + } + ], + Cell[ + StyleData["PrettyTooltipTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + TagBox[ + TooltipBox[ + #1, + FrameBox[ + StyleBox[ + #2, + "Text", + FontColor -> RGBColor[0.53725, 0.53725, 0.53725], + FontSize -> 12, + FontWeight -> "Plain", + FontTracking -> "Plain", + StripOnInput -> False + ], + Background -> RGBColor[0.96078, 0.96078, 0.96078], + FrameStyle -> RGBColor[0.89804, 0.89804, 0.89804], + FrameMargins -> 8, + StripOnInput -> False + ], + TooltipDelay -> 0.1, + TooltipStyle -> {Background -> None, CellFrame -> 0} + ], + Function[ + Annotation[ + #1, + Framed[ + Style[ + RSNB`$$tooltip, + "Text", + FontColor -> RGBColor[0.53725, 0.53725, 0.53725], + FontSize -> 12, + FontWeight -> "Plain", + FontTracking -> "Plain" + ], + Background -> RGBColor[0.96078, 0.96078, 0.96078], + FrameStyle -> RGBColor[0.89804, 0.89804, 0.89804], + FrameMargins -> 8 + ], + "Tooltip" + ] + ] + ] + ]) + } + ], + Cell[ + StyleData["ToolsGridTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + StyleBox[ + TagBox[ + GridBox[ + { + { + FrameBox[ + ButtonBox[ + TemplateBox[ + { + StyleBox[ + TagBox[ + GridBox[ + { + { + "\"Insert ResourceObject\"", + GraphicsBox[ + { + Thickness[0.05], + { + FaceForm[{GrayLevel[0.34902], Opacity[1.0]}], + FilledCurveBox[ + { + { + {1, 4, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3} + } + }, + { + { + {18.0, 17.5}, + {18.0, 18.328}, + {17.328, 19.0}, + {16.5, 19.0}, + {4.5, 19.0}, + {3.6716, 19.0}, + {3.0, 18.328}, + {3.0, 17.5}, + {3.0, 3.5}, + {3.0, 2.6716}, + {3.6716, 2.0}, + {4.5, 2.0}, + {16.5, 2.0}, + {17.328, 2.0}, + {18.0, 2.6716}, + {18.0, 3.5} + } + } + ] + }, + { + FaceForm[{GrayLevel[0.34902], Opacity[1.0]}], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + {{5.0, 12.0}, {5.0, 11.0}, {2.0, 11.0}, {2.0, 12.0}}, + {{2.0, 10.0}, {2.0, 9.0}, {5.0, 9.0}, {5.0, 10.0}}, + {{2.0, 14.0}, {2.0, 13.0}, {5.0, 13.0}, {5.0, 14.0}}, + {{2.0, 8.0}, {2.0, 7.0}, {5.0, 7.0}, {5.0, 8.0}}, + {{2.0, 6.0}, {2.0, 5.0}, {5.0, 5.0}, {5.0, 6.0}}, + { + {5.0, 18.0}, + {2.0, 18.0}, + {2.0, 17.0}, + {5.0, 17.0}, + {5.0, 18.0} + }, + { + {5.0, 4.0}, + {2.0, 4.0}, + {2.0, 3.0}, + {5.0, 3.0}, + {5.0, 4.0} + }, + {{2.0, 16.0}, {2.0, 15.0}, {5.0, 15.0}, {5.0, 16.0}} + } + ] + }, + { + FaceForm[{GrayLevel[1], Opacity[1.0]}], + FilledCurveBox[ + { + { + {0, 2, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3} + } + }, + { + { + {4.5, 18.0}, + {16.5, 18.0}, + {16.776, 18.0}, + {17.0, 17.776}, + {17.0, 17.5}, + {17.0, 3.5}, + {17.0, 3.2236}, + {16.776, 3.0}, + {16.5, 3.0}, + {4.5, 3.0}, + {4.2236, 3.0}, + {4.0, 3.2236}, + {4.0, 3.5}, + {4.0, 17.5}, + {4.0, 17.776}, + {4.2236, 18.0}, + {4.5, 18.0} + } + } + ] + }, + { + FaceForm[{RGBColor[0.86667, 0.06667, 0.0], Opacity[1.0]}], + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + CompressedData[ + "\n1:eJxTTMoPSmViYGAQAWIQrbtp7vvlx3QcGMBA1aH5wKmFrt/0He77907Pm6Th\nkCQQYbnFQ9shxRokoulw+KtGTP8hbQenhKcXlKL1HEIeL519JEHdASydpwPV\nr+Iw54jChiIPAwdlr+pm/R4luPyd643FbiEyDue/Bz9eCtTv8bBKZJ27rMOn\nS75JAjM0HZRyKqqWvhF2+FWXtadksoaDKlvjVGdvKbj7zq06fzUMKB8FclCu\nosMuTx4mbaD+qxUv1QwzFBwOrlji5xAs4+CSmf+h1VPcAey9biWH3LDadduU\npOHum/i2xt70npDDcW/zTkeg+yWmXuHMAMrD/Afxtzjc/w3bHZoepSvAw2fj\nw5dTN+UoOgAARNmGkQ==\n " + ], + { + {14.809, 9.3454}, + {13.744, 9.7099}, + {13.017, 10.654}, + {13.953, 10.307} + }, + { + {11.371, 7.1364}, + {10.712, 6.0044}, + {10.712, 7.177}, + {11.398, 8.1788} + }, + { + {9.8213, 12.979}, + {8.6908, 13.381}, + {8.0367, 14.264}, + {9.2241, 13.743} + }, + { + {11.738, 13.743}, + {12.925, 14.264}, + {12.271, 13.381}, + {11.141, 12.979} + }, + { + {13.177, 12.7}, + {12.603, 11.886}, + {12.637, 13.113}, + {13.309, 14.019} + }, + { + {10.481, 7.6484}, + {9.6004, 8.9331}, + {10.481, 10.128}, + {11.361, 8.9331} + }, + { + {8.8261, 11.306}, + {8.782, 12.866}, + {10.249, 12.344}, + {10.249, 10.826} + }, + { + {10.712, 12.344}, + {12.179, 12.866}, + {12.137, 11.306}, + {10.712, 10.826} + }, + { + {7.7855, 12.7}, + {7.6538, 14.019}, + {8.325, 13.113}, + {8.3587, 11.887} + }, + { + {10.114, 10.394}, + {9.2339, 9.2003}, + {7.7378, 9.6414}, + {8.6871, 10.875} + }, + { + {9.5648, 8.1792}, + {10.249, 7.177}, + {10.249, 6.004}, + {9.5887, 7.1366} + }, + { + {10.848, 10.394}, + {12.275, 10.875}, + {13.224, 9.6414}, + {11.728, 9.2003} + }, + { + {15.126, 12.009}, + {14.018, 10.766}, + {12.711, 11.252}, + {13.495, 12.364} + }, + { + {10.481, 15.384}, + {11.321, 13.946}, + {10.481, 12.872}, + {9.641, 13.946} + }, + { + {5.8362, 12.01}, + {7.467, 12.365}, + {8.2511, 11.252}, + {6.9436, 10.767} + }, + { + {7.009, 10.307}, + {7.9452, 10.655}, + {7.2182, 9.7099}, + {6.152, 9.3459} + }, + { + {6.2515, 8.9006}, + {7.3612, 9.2795}, + {8.5462, 8.9302}, + {7.5545, 8.6165} + }, + { + {7.776, 8.2109}, + {9.1027, 8.6306}, + {9.1365, 7.2193}, + {7.6098, 6.5491} + }, + { + {11.824, 7.219}, + {11.859, 8.6305}, + {13.185, 8.2104}, + {13.351, 6.5484} + }, + { + {13.407, 8.6159}, + {12.415, 8.9301}, + {13.6, 9.2795}, + {14.71, 8.8998} + } + } + ] + } + }, + AspectRatio -> Automatic, + ImageSize -> 12, + PlotRange -> {{0.0, 20.0}, {0.0, 20.0}}, + PlotRangePadding -> 0, + BaselinePosition -> Scaled[0.2] + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Center}}, "Rows" -> {{Baseline}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + "Grid" + ], + "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 11, + StripOnInput -> False + ], + "\"Insert an icon representing the ResourceObject\"" + }, + "PrettyTooltipTemplate" + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 4300058170245655723; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + + DefinitionNotebookClient`$ClickedButton = + "InsertResourceObject"; + + DefinitionNotebookClient`InsertResourceObjectIcon[ + ButtonNotebook[] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[4300058170245655723] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + FrameMargins -> {{4, 4}, {0, 0}}, + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + FEPrivate`If[ + CurrentValue["MouseOver"], + { + FontColor -> GrayLevel[1], + TaggingRules -> {"ButtonHovering" -> True} + }, + { + FontColor -> RGBColor[0.10588, 0.27059, 0.37255], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + { + FontColor -> RGBColor[0.77647, 0.81765, 0.84314], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + Evaluator -> "System" + ], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVan7pbXNXbT969tnrtxAEZANFgOJAWaAa\noEqshgDNh5gQUtL+6MVrrKEHFAfKQsyBuwfZEIgvgGoIRgTEHKB6NEOAIQbx\nBS43oLkH4i9IOMMNAYY8UBDoa4ImQABQJVA9UBeyIcAYBAoCQ49IQ4AqgeqB\nuoB6IakRyACmBKAgMBaINASoEqgeqAtiCBBQbghVXPKfemFCldihSjqhSoql\nVt6hSi6mVnkCBxSWbGQAghHxn7jSHgAhWAlh\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVcp7Jhqmt1iXTXZuWQxCQDRQBigNlgWqA\nKrEaAjQfYoJ6WLFL4zKvzg2YCCgOlIWYA3cPsiEQXwDVYNWOjCDmANWjGQIM\nMYgvcLkBzT0Qf0HCGW4IMOSBgkBfEzQBgoAqgeqBupANAcYgyKcl04k0BKgS\nqB6oC6gXkhqBDGBKAAoCY4FIQ4AqQS4Py4MYAgSUG0IVl1AxTKgSO1RJJ1RJ\nsdTKO1TJxdQqT+CAwpKNDEBMMU5MaQ8AQJMCGA==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJchr1+//vjx4/fv3//AAJANFAGKE2PI8+fPv3z5\ngsfZQFmgGjyGvHr16vfv30CR779+rzp+q3ndybhpOyEIyAaKAMWBskA1QJVY\nDQGaDzHh0sPXiTN2eXVuwERAcaAsxBy4e5ANgfgCqAardmQEMQeoHs0QYIhB\nfIHLDWjugfgLEs5wQ4AhD2QAfU3QBAgCqgSqB+pCNgQYg0AGMPSINASoEuTy\n79+BeiGpEcgApgQgAxgLRBoCVAlUD9QFMQQIKDeEKi6hYphQJXaokk6okmKp\nlXeokoupVZ7AAYUlGxkAj7PhgJjSHgDbEuv0\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> GrayLevel[0.9], + Method -> "Queued", + ImageSize -> {All, 20}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[GrayLevel[0.9], AbsoluteThickness[2]], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ], + FrameBox[ + ButtonBox[ + TemplateBox[ + { + StyleBox[ + "\"Template Input\"", + "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 11, + StripOnInput -> False + ], + "\"Format selection automatically using appropriate documentation styles\"" + }, + "PrettyTooltipTemplate" + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 2790153672590285854; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Template Input"; + DefinitionNotebookClient`TemplateInput[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[2790153672590285854] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + FrameMargins -> {{4, 4}, {0, 0}}, + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + FEPrivate`If[ + CurrentValue["MouseOver"], + { + FontColor -> GrayLevel[1], + TaggingRules -> {"ButtonHovering" -> True} + }, + { + FontColor -> RGBColor[0.10588, 0.27059, 0.37255], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + { + FontColor -> RGBColor[0.77647, 0.81765, 0.84314], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + Evaluator -> "System" + ], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVan7pbXNXbT969tnrtxAEZANFgOJAWaAa\noEqshgDNh5gQUtL+6MVrrKEHFAfKQsyBuwfZEIgvgGoIRgTEHKB6NEOAIQbx\nBS43oLkH4i9IOMMNAYY8UBDoa4ImQABQJVA9UBeyIcAYBAoCQ49IQ4AqgeqB\nuoB6IakRyACmBKAgMBaINASoEqgeqAtiCBBQbghVXPKfemFCldihSjqhSoql\nVt6hSi6mVnkCBxSWbGQAghHxn7jSHgAhWAlh\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVcp7Jhqmt1iXTXZuWQxCQDRQBigNlgWqA\nKrEaAjQfYoJ6WLFL4zKvzg2YCCgOlIWYA3cPsiEQXwDVYNWOjCDmANWjGQIM\nMYgvcLkBzT0Qf0HCGW4IMOSBgkBfEzQBgoAqgeqBupANAcYgyKcl04k0BKgS\nqB6oC6gXkhqBDGBKAAoCY4FIQ4AqQS4Py4MYAgSUG0IVl1AxTKgSO1RJJ1RJ\nsdTKO1TJxdQqT+CAwpKNDEBMMU5MaQ8AQJMCGA==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJchr1+//vjx4/fv3//AAJANFAGKE2PI8+fPv3z5\ngsfZQFmgGjyGvHr16vfv30CR779+rzp+q3ndybhpOyEIyAaKAMWBskA1QJVY\nDQGaDzHh0sPXiTN2eXVuwERAcaAsxBy4e5ANgfgCqAardmQEMQeoHs0QYIhB\nfIHLDWjugfgLEs5wQ4AhD2QAfU3QBAgCqgSqB+pCNgQYg0AGMPSINASoEuTy\n79+BeiGpEcgApgQgAxgLRBoCVAlUD9QFMQQIKDeEKi6hYphQJXaokk6okmKp\nlXeokoupVZ7AAYUlGxkAj7PhgJjSHgDbEuv0\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> GrayLevel[0.9], + Method -> "Queued", + ImageSize -> {All, 20}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[GrayLevel[0.9], AbsoluteThickness[2]], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ], + FrameBox[ + ButtonBox[ + TemplateBox[ + { + StyleBox[ + "\"Literal Input\"", + "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 11, + StripOnInput -> False + ], + "\"Format selection as literal Wolfram Language code\"" + }, + "PrettyTooltipTemplate" + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 4138174468017918531; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Literal Input"; + DefinitionNotebookClient`LiteralInput[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[4138174468017918531] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + FrameMargins -> {{4, 4}, {0, 0}}, + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + FEPrivate`If[ + CurrentValue["MouseOver"], + { + FontColor -> GrayLevel[1], + TaggingRules -> {"ButtonHovering" -> True} + }, + { + FontColor -> RGBColor[0.10588, 0.27059, 0.37255], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + { + FontColor -> RGBColor[0.77647, 0.81765, 0.84314], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + Evaluator -> "System" + ], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVan7pbXNXbT969tnrtxAEZANFgOJAWaAa\noEqshgDNh5gQUtL+6MVrrKEHFAfKQsyBuwfZEIgvgGoIRgTEHKB6NEOAIQbx\nBS43oLkH4i9IOMMNAYY8UBDoa4ImQABQJVA9UBeyIcAYBAoCQ49IQ4AqgeqB\nuoB6IakRyACmBKAgMBaINASoEqgeqAtiCBBQbghVXPKfemFCldihSjqhSoql\nVt6hSi6mVnkCBxSWbGQAghHxn7jSHgAhWAlh\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVcp7Jhqmt1iXTXZuWQxCQDRQBigNlgWqA\nKrEaAjQfYoJ6WLFL4zKvzg2YCCgOlIWYA3cPsiEQXwDVYNWOjCDmANWjGQIM\nMYgvcLkBzT0Qf0HCGW4IMOSBgkBfEzQBgoAqgeqBupANAcYgyKcl04k0BKgS\nqB6oC6gXkhqBDGBKAAoCY4FIQ4AqQS4Py4MYAgSUG0IVl1AxTKgSO1RJJ1RJ\nsdTKO1TJxdQqT+CAwpKNDEBMMU5MaQ8AQJMCGA==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJchr1+//vjx4/fv3//AAJANFAGKE2PI8+fPv3z5\ngsfZQFmgGjyGvHr16vfv30CR779+rzp+q3ndybhpOyEIyAaKAMWBskA1QJVY\nDQGaDzHh0sPXiTN2eXVuwERAcaAsxBy4e5ANgfgCqAardmQEMQeoHs0QYIhB\nfIHLDWjugfgLEs5wQ4AhD2QAfU3QBAgCqgSqB+pCNgQYg0AGMPSINASoEuTy\n79+BeiGpEcgApgQgAxgLRBoCVAlUD9QFMQQIKDeEKi6hYphQJXaokk6okmKp\nlXeokoupVZ7AAYUlGxkAj7PhgJjSHgDbEuv0\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> GrayLevel[0.9], + Method -> "Queued", + ImageSize -> {All, 20}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[GrayLevel[0.9], AbsoluteThickness[2]], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ], + FrameBox[ + ButtonBox[ + TemplateBox[ + { + StyleBox[ + "\"Insert Delimiter\"", + "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 11, + StripOnInput -> False + ], + "\"Insert example delimiter\"" + }, + "PrettyTooltipTemplate" + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 1887802176716758884; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + + DefinitionNotebookClient`$ClickedButton = + "Insert Delimiter"; + + DefinitionNotebookClient`DelimiterInsert[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[1887802176716758884] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + FrameMargins -> {{4, 4}, {0, 0}}, + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + FEPrivate`If[ + CurrentValue["MouseOver"], + { + FontColor -> GrayLevel[1], + TaggingRules -> {"ButtonHovering" -> True} + }, + { + FontColor -> RGBColor[0.10588, 0.27059, 0.37255], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + { + FontColor -> RGBColor[0.77647, 0.81765, 0.84314], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + Evaluator -> "System" + ], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVan7pbXNXbT969tnrtxAEZANFgOJAWaAa\noEqshgDNh5gQUtL+6MVrrKEHFAfKQsyBuwfZEIgvgGoIRgTEHKB6NEOAIQbx\nBS43oLkH4i9IOMMNAYY8UBDoa4ImQABQJVA9UBeyIcAYBAoCQ49IQ4AqgeqB\nuoB6IakRyACmBKAgMBaINASoEqgeqAtiCBBQbghVXPKfemFCldihSjqhSoql\nVt6hSi6mVnkCBxSWbGQAghHxn7jSHgAhWAlh\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVcp7Jhqmt1iXTXZuWQxCQDRQBigNlgWqA\nKrEaAjQfYoJ6WLFL4zKvzg2YCCgOlIWYA3cPsiEQXwDVYNWOjCDmANWjGQIM\nMYgvcLkBzT0Qf0HCGW4IMOSBgkBfEzQBgoAqgeqBupANAcYgyKcl04k0BKgS\nqB6oC6gXkhqBDGBKAAoCY4FIQ4AqQS4Py4MYAgSUG0IVl1AxTKgSO1RJJ1RJ\nsdTKO1TJxdQqT+CAwpKNDEBMMU5MaQ8AQJMCGA==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJchr1+//vjx4/fv3//AAJANFAGKE2PI8+fPv3z5\ngsfZQFmgGjyGvHr16vfv30CR779+rzp+q3ndybhpOyEIyAaKAMWBskA1QJVY\nDQGaDzHh0sPXiTN2eXVuwERAcaAsxBy4e5ANgfgCqAardmQEMQeoHs0QYIhB\nfIHLDWjugfgLEs5wQ4AhD2QAfU3QBAgCqgSqB+pCNgQYg0AGMPSINASoEuTy\n79+BeiGpEcgApgQgAxgLRBoCVAlUD9QFMQQIKDeEKi6hYphQJXaokk6okmKp\nlXeokoupVZ7AAYUlGxkAj7PhgJjSHgDbEuv0\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> GrayLevel[0.9], + Method -> "Queued", + ImageSize -> {All, 20}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[GrayLevel[0.9], AbsoluteThickness[2]], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ], + ActionMenuBox[ + FrameBox[ + ButtonBox[ + TemplateBox[ + { + StyleBox[ + TemplateBox[ + { + "\"Tables\"", + "\"\[ThinSpace]\[ThinSpace]\[ThinSpace]\[FilledDownTriangle]\"" + }, + "RowDefault" + ], + "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 11, + StripOnInput -> False + ], + "\"Table functions\"" + }, + "PrettyTooltipTemplate" + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 3216557251994556740; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = HoldForm[Null] + ] + ], + DefinitionNotebookClient`ButtonCodeID[3216557251994556740] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + FrameMargins -> {{4, 4}, {0, 0}}, + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + FEPrivate`If[ + CurrentValue["MouseOver"], + { + FontColor -> GrayLevel[1], + TaggingRules -> {"ButtonHovering" -> True} + }, + { + FontColor -> RGBColor[0.10588, 0.27059, 0.37255], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + { + FontColor -> RGBColor[0.77647, 0.81765, 0.84314], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + Evaluator -> "System" + ], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVan7pbXNXbT969tnrtxAEZANFgOJAWaAa\noEqshgDNh5gQUtL+6MVrrKEHFAfKQsyBuwfZEIgvgGoIRgTEHKB6NEOAIQbx\nBS43oLkH4i9IOMMNAYY8UBDoa4ImQABQJVA9UBeyIcAYBAoCQ49IQ4AqgeqB\nuoB6IakRyACmBKAgMBaINASoEqgeqAtiCBBQbghVXPKfemFCldihSjqhSoql\nVt6hSi6mVnkCBxSWbGQAghHxn7jSHgAhWAlh\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVcp7Jhqmt1iXTXZuWQxCQDRQBigNlgWqA\nKrEaAjQfYoJ6WLFL4zKvzg2YCCgOlIWYA3cPsiEQXwDVYNWOjCDmANWjGQIM\nMYgvcLkBzT0Qf0HCGW4IMOSBgkBfEzQBgoAqgeqBupANAcYgyKcl04k0BKgS\nqB6oC6gXkhqBDGBKAAoCY4FIQ4AqQS4Py4MYAgSUG0IVl1AxTKgSO1RJJ1RJ\nsdTKO1TJxdQqT+CAwpKNDEBMMU5MaQ8AQJMCGA==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJchr1+//vjx4/fv3//AAJANFAGKE2PI8+fPv3z5\ngsfZQFmgGjyGvHr16vfv30CR779+rzp+q3ndybhpOyEIyAaKAMWBskA1QJVY\nDQGaDzHh0sPXiTN2eXVuwERAcaAsxBy4e5ANgfgCqAardmQEMQeoHs0QYIhB\nfIHLDWjugfgLEs5wQ4AhD2QAfU3QBAgCqgSqB+pCNgQYg0AGMPSINASoEuTy\n79+BeiGpEcgApgQgAxgLRBoCVAlUD9QFMQQIKDeEKi6hYphQJXaokk6okmKp\nlXeokoupVZ7AAYUlGxkAj7PhgJjSHgDbEuv0\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> GrayLevel[0.9], + Method -> "Queued", + ImageSize -> {All, 20}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[GrayLevel[0.9], AbsoluteThickness[2]], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ], + { + "\"Insert table with two columns\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 5800166344906378520; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Tables"; + + DefinitionNotebookClient`$ClickedAction = + "Insert table with two columns"; + + DefinitionNotebookClient`TableInsert[2] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[5800166344906378520] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Insert table with three columns\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + DefinitionNotebookClient`$ButtonCodeID = 533841403879783297; + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Tables"; + + DefinitionNotebookClient`$ClickedAction = + "Insert table with three columns"; + + DefinitionNotebookClient`TableInsert[3] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[533841403879783297] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Add a row to the selected table\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 4413051590217973467; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Tables"; + + DefinitionNotebookClient`$ClickedAction = + "Add a row to the selected table"; + + DefinitionNotebookClient`TableRowInsert[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[4413051590217973467] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Sort the selected table\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 9150037060110806081; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Tables"; + + DefinitionNotebookClient`$ClickedAction = + "Sort the selected table"; + + DefinitionNotebookClient`TableSort[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[9150037060110806081] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Merge selected tables\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 2347719643166780208; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Tables"; + + DefinitionNotebookClient`$ClickedAction = + "Merge selected tables"; + + DefinitionNotebookClient`TableMerge[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[2347719643166780208] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ] + }, + Appearance -> None, + Method -> "Queued" + ], + ActionMenuBox[ + FrameBox[ + ButtonBox[ + StyleBox[ + TemplateBox[ + { + "\"Cells\"", + "\"\[ThinSpace]\[ThinSpace]\[ThinSpace]\[FilledDownTriangle]\"" + }, + "RowDefault" + ], + "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 11, + StripOnInput -> False + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 3216557251994556740; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = HoldForm[Null] + ] + ], + DefinitionNotebookClient`ButtonCodeID[3216557251994556740] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + FrameMargins -> {{4, 4}, {0, 0}}, + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + FEPrivate`If[ + CurrentValue["MouseOver"], + { + FontColor -> GrayLevel[1], + TaggingRules -> {"ButtonHovering" -> True} + }, + { + FontColor -> RGBColor[0.10588, 0.27059, 0.37255], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + { + FontColor -> RGBColor[0.77647, 0.81765, 0.84314], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + Evaluator -> "System" + ], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVan7pbXNXbT969tnrtxAEZANFgOJAWaAa\noEqshgDNh5gQUtL+6MVrrKEHFAfKQsyBuwfZEIgvgGoIRgTEHKB6NEOAIQbx\nBS43oLkH4i9IOMMNAYY8UBDoa4ImQABQJVA9UBeyIcAYBAoCQ49IQ4AqgeqB\nuoB6IakRyACmBKAgMBaINASoEqgeqAtiCBBQbghVXPKfemFCldihSjqhSoql\nVt6hSi6mVnkCBxSWbGQAghHxn7jSHgAhWAlh\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVcp7Jhqmt1iXTXZuWQxCQDRQBigNlgWqA\nKrEaAjQfYoJ6WLFL4zKvzg2YCCgOlIWYA3cPsiEQXwDVYNWOjCDmANWjGQIM\nMYgvcLkBzT0Qf0HCGW4IMOSBgkBfEzQBgoAqgeqBupANAcYgyKcl04k0BKgS\nqB6oC6gXkhqBDGBKAAoCY4FIQ4AqQS4Py4MYAgSUG0IVl1AxTKgSO1RJJ1RJ\nsdTKO1TJxdQqT+CAwpKNDEBMMU5MaQ8AQJMCGA==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJchr1+//vjx4/fv3//AAJANFAGKE2PI8+fPv3z5\ngsfZQFmgGjyGvHr16vfv30CR779+rzp+q3ndybhpOyEIyAaKAMWBskA1QJVY\nDQGaDzHh0sPXiTN2eXVuwERAcaAsxBy4e5ANgfgCqAardmQEMQeoHs0QYIhB\nfIHLDWjugfgLEs5wQ4AhD2QAfU3QBAgCqgSqB+pCNgQYg0AGMPSINASoEuTy\n79+BeiGpEcgApgQgAxgLRBoCVAlUD9QFMQQIKDeEKi6hYphQJXaokk6okmKp\nlXeokoupVZ7AAYUlGxkAj7PhgJjSHgDbEuv0\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> GrayLevel[0.9], + Method -> "Queued", + ImageSize -> {All, 20}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[GrayLevel[0.9], AbsoluteThickness[2]], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ], + { + "\"Insert comment for reviewer\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 2572781756330727330; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Cells"; + + DefinitionNotebookClient`$ClickedAction = + "Insert comment for reviewer"; + + DefinitionNotebookClient`CommentInsert[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[2572781756330727330] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Mark/unmark selected cells as comments\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 3646530685697756512; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Cells"; + + DefinitionNotebookClient`$ClickedAction = + "Mark/unmark selected cells as comments"; + + DefinitionNotebookClient`CommentToggle[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[3646530685697756512] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Mark/unmark selected cells as excluded\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 1866935765212102190; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Cells"; + + DefinitionNotebookClient`$ClickedAction = + "Mark/unmark selected cells as excluded"; + + DefinitionNotebookClient`ExclusionToggle[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[1866935765212102190] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ] + }, + Appearance -> None, + Method -> "Queued" + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxBackground -> {"Columns" -> {{None}}, "Rows" -> {GrayLevel[0.9]}}, + GridBoxFrame -> { + "Columns" -> False, + "RowsIndexed" -> {1 -> GrayLevel[0.9]} + }, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {5, {0.5}, 5}, "Rows" -> {{Automatic}}}, + FrameStyle -> GrayLevel[0.75] + ], + "Grid" + ], + ButtonBoxOptions -> { + Enabled -> + Dynamic[ + Not[TrueQ[DefinitionNotebookClient`$ButtonsDisabled]], + TrackedSymbols :> {DefinitionNotebookClient`$ButtonsDisabled} + ] + }, + StripOnInput -> False + ] + ]) + } + ], + Cell[ + StyleData["MainGridTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + StyleBox[ + TagBox[ + GridBox[ + { + { + TagBox[ + GridBox[ + { + { + GraphicsBox[ + { + Thickness[0.02963], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBWIWIGZigIIGBQcwfUAPQjOoYuc3CDugqIfxGTQg9ANj\nqLgOdj66erh5+lD7oPYwGGHno6uH86H2PDCA6jPFzkdXD+M7mENpLai4JXY+\nunogHwDQSSTa\n " + ] + ] + }, + {FaceForm[RGBColor[1.0, 1.0, 1.0, 1.0]]}, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {0.75, 1.875}, + {33.0, 1.875}, + {33.0, 0.375}, + {0.75, 0.375} + }, + { + {27.0, 19.875}, + {29.25, 19.875}, + {29.25, 4.875}, + {27.0, 4.875} + }, + { + {3.0, 4.125}, + {30.75, 4.125}, + {30.75, 2.625}, + {3.0, 2.625} + }, + { + {16.875, 32.625}, + {0.0, 24.375}, + {0.0, 22.875}, + {33.75, 22.875}, + {33.75, 24.375} + }, + {{3.75, 24.375}, {16.875, 30.75}, {30.0, 24.375}}, + { + {25.5, 22.125}, + {30.75, 22.125}, + {30.75, 20.625}, + {25.5, 20.625} + }, + { + {4.5, 19.875}, + {6.75, 19.875}, + {6.75, 4.875}, + {4.5, 4.875} + }, + { + {3.0, 22.125}, + {8.25, 22.125}, + {8.25, 20.625}, + {3.0, 20.625} + } + } + ] + }, + {FaceForm[RGBColor[0.843, 0.847, 0.847, 1.0]]}, + StripOnInput -> False + ] + }, + { + ImageSize -> {Automatic, 32}, + ImagePadding -> {{5, 0}, {0, 0}}, + BaselinePosition -> Scaled[0.25], + Background -> RGBColor[0.2902, 0.53725, 0.6902], + ImageSize -> {45.0, Automatic}, + PlotRange -> {{0.0, 33.75}, {0.0, 33.0}}, + AspectRatio -> Automatic + } + ], + StyleBox[ + TagBox[ + GridBox[ + { + { + StyleBox[ + "\"Data Resource\"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + StripOnInput -> False + ], + StyleBox[ + "\"DEFINITION NOTEBOOK\"", + FontFamily -> "Source Sans Pro", + FontTracking -> "SemiCondensed", + FontVariations -> {"CapsType" -> "AllSmallCaps"}, + StripOnInput -> False + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Baseline}}}, + AutoDelete -> False, + GridBoxDividers -> { + "ColumnsIndexed" -> {2 -> RGBColor[1.0, 1.0, 1.0]}, + "Rows" -> {{None}} + }, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Grid" + ], + FontSize -> 24, + FontColor -> RGBColor[1.0, 1.0, 1.0], + StripOnInput -> False + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Baseline}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Grid" + ], + "\[SpanFromLeft]", + "\[SpanFromLeft]", + "\[SpanFromLeft]", + "\[SpanFromLeft]", + "\[SpanFromLeft]", + "\[SpanFromLeft]", + TemplateBox[ + { + StyleBox[ + TemplateBox[ + {"\"Data Repository\"", "\" \[RightGuillemet] \""}, + "RowDefault" + ], + "Text", + FontColor -> RGBColor[1.0, 1.0, 1.0], + StripOnInput -> False + ], + "https://datarepository.wolframcloud.com/" + }, + "HyperlinkURL" + ] + }, + { + TemplateBox[ + { + TemplateBox[ + { + "\"Open Sample\"", + "\"View a completed sample definition notebook\"" + }, + "PrettyTooltipTemplate" + ], + Function[ + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 4393071033038384034; + + (DefinitionNotebookClient`$ClickedButton = "Open Sample"; + DefinitionNotebookClient`ViewExampleNotebook[ + ButtonNotebook[] + ]), + DefinitionNotebookClient`ButtonCodeID[4393071033038384034] + ] + ], + "\"View a completed sample definition notebook\"", + False + }, + "OrangeButtonTemplate" + ], + TemplateBox[ + { + TemplateBox[ + { + "\"Style Guidelines\"", + "\"View general guidelines for authoring data resources\"" + }, + "PrettyTooltipTemplate" + ], + Function[ + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 5906117565281445171; + + ( + DefinitionNotebookClient`$ClickedButton = + "Style Guidelines"; + + DefinitionNotebookClient`ViewStyleGuidelines[ + ButtonNotebook[] + ]), + DefinitionNotebookClient`ButtonCodeID[5906117565281445171] + ] + ], + "\"View general guidelines for authoring data resources\"", + False + }, + "OrangeButtonTemplate" + ], + TemplateBox[ + { + TemplateBox[ + { + TagBox[ + GridBox[ + { + { + "\"Tools\"", + PaneSelectorBox[ + { + False -> + GraphicsBox[ + { + RGBColor[1.0, 1.0, 1.0], + AbsoluteThickness[1.0], + LineBox[{{0, 0}, {0, 10}, {10, 10}, {10, 0}, {0, 0}}], + LineBox[{{5, 2.5}, {5, 7.5}}], + LineBox[{{2.5, 5}, {7.5, 5}}] + }, + ImageSize -> 12, + PlotRangePadding -> 1.5 + ], + True -> + GraphicsBox[ + { + RGBColor[1.0, 1.0, 1.0], + AbsoluteThickness[1.0], + LineBox[{{0, 0}, {0, 10}, {10, 10}, {10, 0}, {0, 0}}], + LineBox[{{2.5, 5}, {7.5, 5}}] + }, + ImageSize -> 12, + PlotRangePadding -> 1.5 + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ToolsOpen"}, + True + ] + ], + BaselinePosition -> Scaled[0.05] + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Baseline}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0.35}}} + ], + "Grid" + ], + "\"Toggle documentation toolbar\"" + }, + "PrettyTooltipTemplate" + ], + Function[ + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 5074018684552945401; + + (DefinitionNotebookClient`$ClickedButton = "Tools"; + DefinitionNotebookClient`ToggleToolbar[ButtonNotebook[]]), + DefinitionNotebookClient`ButtonCodeID[5074018684552945401] + ] + ], + "\"Toggle documentation toolbar\"", + False + }, + "OrangeButtonTemplate" + ], + TagBox[ + GridBox[ + {{"\"\"", "\"\""}}, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxDividers -> {"ColumnsIndexed" -> {2 -> True}, "Rows" -> {{False}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{2}}}, + GridBoxSpacings -> {"Columns" -> {{0.5}}}, + FrameStyle -> RGBColor[0.6451, 0.76863, 0.8451] + ], + "Grid" + ], + ActionMenuBox[ + TemplateBox[ + { + TemplateBox[ + { + TemplateBox[ + { + "\"Check\"", + TemplateBox[{5}, "Spacer1"], + "\"\[FilledDownTriangle]\"" + }, + "RowDefault" + ], + "\"Check notebook for potential errors\"" + }, + "PrettyTooltipTemplate" + ], + Function[ + Annotation[ + DefinitionNotebookClient`$ButtonCodeID = + 1898445052439169298;, + DefinitionNotebookClient`ButtonCodeID[1898445052439169298] + ] + ], + "\"Check notebook for potential errors\"", + True + }, + "OrangeButtonTemplate" + ], + { + "\"Check Definition Notebook\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 7315505126975123932; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Check"; + + DefinitionNotebookClient`$ClickedAction = + "Check Definition Notebook"; + + DefinitionNotebookClient`CheckDefinitionNotebook[ + ButtonNotebook[] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[7315505126975123932] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Check Data\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 5678342563549764489; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Check"; + DefinitionNotebookClient`$ClickedAction = "Check Data"; + DataResource`DefinitionNotebook`CheckDataDefinitions[ + ButtonNotebook[] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[5678342563549764489] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Check All\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 7222533872454612108; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Check"; + DefinitionNotebookClient`$ClickedAction = "Check All"; + ( + DefinitionNotebookClient`CheckDefinitionNotebook[ + ButtonNotebook[] + ]; + + DataResource`DefinitionNotebook`CheckDataDefinitions[ + ButtonNotebook[] + ]) + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[7222533872454612108] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ] + }, + Appearance -> None, + Method -> "Queued" + ], + ActionMenuBox[ + TemplateBox[ + { + TemplateBox[ + { + "\"Deploy\"", + TemplateBox[{5}, "Spacer1"], + "\"\[FilledDownTriangle]\"" + }, + "RowDefault" + ], + Function[ + Annotation[ + DefinitionNotebookClient`$ButtonCodeID = + 1898445052439169298;, + DefinitionNotebookClient`ButtonCodeID[1898445052439169298] + ] + ], + "\"\"", + True + }, + "OrangeButtonTemplate" + ], + { + "\"Locally on this computer\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 8714502586816766511; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Deploy"; + + DefinitionNotebookClient`$ClickedAction = + "Locally on this computer"; + + DefinitionNotebookClient`DisplayStripe[ + ButtonNotebook[], + DefinitionNotebookClient`DeployResource[ + ButtonNotebook[], + "Local" + ] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[8714502586816766511] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"For my cloud account\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 1389539917011878958; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Deploy"; + + DefinitionNotebookClient`$ClickedAction = + "For my cloud account"; + + DefinitionNotebookClient`DisplayStripe[ + ButtonNotebook[], + DefinitionNotebookClient`DeployResource[ + ButtonNotebook[], + "CloudPrivate" + ] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[1389539917011878958] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Publicly in the cloud\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 5593410685219912767; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Deploy"; + + DefinitionNotebookClient`$ClickedAction = + "Publicly in the cloud"; + + DefinitionNotebookClient`DisplayStripe[ + ButtonNotebook[], + DefinitionNotebookClient`DeployResource[ + ButtonNotebook[], + "CloudPublic" + ] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[5593410685219912767] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"In this session only (without documentation)\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 8586347731213964380; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Deploy"; + + DefinitionNotebookClient`$ClickedAction = + "In this session only (without documentation)"; + + DefinitionNotebookClient`DisplayStripe[ + ButtonNotebook[], + DefinitionNotebookClient`DeployResource[ + ButtonNotebook[], + "KernelSession" + ] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[8586347731213964380] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ] + }, + Appearance -> None, + Method -> "Queued" + ], + ItemBox[ + StyleBox[ + DynamicBox[ + ToBoxes[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "StatusMessage"}, + "" + ], + StandardForm + ], + Initialization :> + (CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "StatusMessage"} + ] = + "") + ], + "Text", + GrayLevel[1], + StripOnInput -> False + ], + ItemSize -> Fit, + StripOnInput -> False + ], + DynamicBox[ + ToBoxes[ + If[ CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "SubmissionReviewData", "Review"}, + False + ], + RawBoxes[ + TemplateBox[ + { + TemplateBox[ + { + TagBox[ + GridBox[ + { + { + GraphicsBox[ + { + Thickness[0.06349], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBWIWIGZigIEX9mCqQd8Bwv+Bnc/A54CiHs5HV6/ngJUP\np2HmwdTp4FCHTvOhqYfZrw2lhdDk0fno6tHcD1PPwOSAnY+uns8BAE8cGz4=\n\n " + ] + ] + }, + {FaceForm[RGBColor[1.0, 1.0, 1.0]]}, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgB2IWIGZigAEJBwjNB6EblHHwX9ijqofxoeoYhKC0Bg4+\nHw4apk4Uap8aDr4QDhqqDu4uVRx8URw0TJ001D5lHHwJHDRUHYMclFbCwZfG\nQUPVNSjgp+HmIWgAG/wcEg==\n " + ] + ], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJx10EEKgCAQhWGpFtEyEAYGggQj6RKeoSMErbuCR0/IWfTgCcPwy7fR9XrO\nu3fOTXWGOp2zM+ZvH2170nv+e2sFH0ijt45/XxJp9NgRPHYAb63kHhu9tf2H\neU8aPfbS9kxawAvxnrSCx3c3XzbS6JX4RFrAS34B53ckaw==\n " + ] + ] + }, + {FaceForm[RGBColor[1.0, 1.0, 1.0]]}, + StripOnInput -> False + ] + }, + ImageSize -> 15, + PlotRange -> {{0.0, 15.75}, {0.0, 16.5}}, + AspectRatio -> 1.15 + ], + "\"Submit Update\"" + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> { + "Columns" -> {{0}}, + "ColumnsIndexed" -> {2 -> 0.5}, + "Rows" -> {{0}} + } + ], + "Grid" + ], + "\"Submit changes to update your data submission\"" + }, + "PrettyTooltipTemplate" + ], + Function[ + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 3196298050911436087; + + (DefinitionNotebookClient`$ClickedButton = "SubmitUpdate"; + With[ { RSNB`nb = ButtonNotebook[] }, + DefinitionNotebookClient`DisplayStripe[ + RSNB`nb, + DefinitionNotebookClient`SubmitRepositoryUpdate[RSNB`nb], + "ShowProgress" -> True + ] + ]), + DefinitionNotebookClient`ButtonCodeID[3196298050911436087] + ] + ], + "\"Submit changes to update your data submission\"", + True + }, + "OrangeButtonTemplate" + ] + ], + RawBoxes[ + TemplateBox[ + { + TemplateBox[ + { + TagBox[ + GridBox[ + { + { + GraphicsBox[ + { + Thickness[0.06349], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBWIWIGZigIEX9mCqQd8Bwv+Bnc/A54CiHs5HV6/ngJUP\np2HmwdTp4FCHTvOhqYfZrw2lhdDk0fno6tHcD1PPwOSAnY+uns8BAE8cGz4=\n\n " + ] + ] + }, + {FaceForm[RGBColor[1.0, 1.0, 1.0]]}, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgB2IWIGZigAEJBwjNB6EblHHwX9ijqofxoeoYhKC0Bg4+\nHw4apk4Uap8aDr4QDhqqDu4uVRx8URw0TJ001D5lHHwJHDRUHYMclFbCwZfG\nQUPVNSjgp+HmIWgAG/wcEg==\n " + ] + ], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJx10EEKgCAQhWGpFtEyEAYGggQj6RKeoSMErbuCR0/IWfTgCcPwy7fR9XrO\nu3fOTXWGOp2zM+ZvH2170nv+e2sFH0ijt45/XxJp9NgRPHYAb63kHhu9tf2H\neU8aPfbS9kxawAvxnrSCx3c3XzbS6JX4RFrAS34B53ckaw==\n " + ] + ] + }, + {FaceForm[RGBColor[1.0, 1.0, 1.0]]}, + StripOnInput -> False + ] + }, + ImageSize -> 15, + PlotRange -> {{0.0, 15.75}, {0.0, 16.5}}, + AspectRatio -> 1.15 + ], + "\"Submit to Repository\"" + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> { + "Columns" -> {{0}}, + "ColumnsIndexed" -> {2 -> 0.5}, + "Rows" -> {{0}} + } + ], + "Grid" + ], + "\"Submit your data to the Wolfram Data Repository\"" + }, + "PrettyTooltipTemplate" + ], + Function[ + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 3704832848557640569; + + (DefinitionNotebookClient`$ClickedButton = "Submit"; + With[ { RSNB`nb = ButtonNotebook[] }, + DefinitionNotebookClient`DisplayStripe[ + RSNB`nb, + DefinitionNotebookClient`SubmitRepository[RSNB`nb], + "ShowProgress" -> True + ] + ]), + DefinitionNotebookClient`ButtonCodeID[3704832848557640569] + ] + ], + "\"Submit your data to the Wolfram Data Repository\"", + True + }, + "OrangeButtonTemplate" + ] + ] + ], + StandardForm + ], + Evaluator -> "System", + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> { + "Columns" -> {{Left}}, + "ColumnsIndexed" -> {-1 -> Right}, + "Rows" -> {{Center}} + }, + AutoDelete -> False, + GridBoxBackground -> { + "Columns" -> {{None}}, + "Rows" -> { + RGBColor[0.2902, 0.53725, 0.6902], + RGBColor[0.16078, 0.40392, 0.56078] + } + }, + GridBoxFrame -> { + "Columns" -> False, + "RowsIndexed" -> { + 1 -> RGBColor[0.2902, 0.53725, 0.6902], + 2 -> RGBColor[0.16078, 0.40392, 0.56078] + } + }, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> { + "Columns" -> {5, {0.9}, 5}, + "RowsIndexed" -> {1 -> 1.1, 2 -> 1.3, 3 -> 0.25} + }, + FrameStyle -> RGBColor[0.2902, 0.53725, 0.6902] + ], + "Grid" + ], + ButtonBoxOptions -> { + Enabled -> + Dynamic[ + Not[TrueQ[DefinitionNotebookClient`$ButtonsDisabled]], + TrackedSymbols :> {DefinitionNotebookClient`$ButtonsDisabled} + ] + }, + StripOnInput -> False + ] + ]) + } + ], + Cell[ + StyleData["ReviewerCommentLabelTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + TagBox[ + GridBox[ + { + { + #1, + TemplateBox[ + { + GraphicsBox[ + { + Thickness[0.02963], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBWIWIGZigIIGBQcwfUAPQjOoYuc3CDugqIfxGTQg9ANj\nqLgOdj66erh5+lD7oPYwGGHno6uH86H2PDCA6jPFzkdXD+M7mENpLai4JXY+\nunogHwDQSSTa\n " + ] + ] + }, + {FaceForm[RGBColor[1.0, 1.0, 1.0, 1.0]]}, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {0.75, 1.875}, + {33.0, 1.875}, + {33.0, 0.375}, + {0.75, 0.375} + }, + { + {27.0, 19.875}, + {29.25, 19.875}, + {29.25, 4.875}, + {27.0, 4.875} + }, + { + {3.0, 4.125}, + {30.75, 4.125}, + {30.75, 2.625}, + {3.0, 2.625} + }, + { + {16.875, 32.625}, + {0.0, 24.375}, + {0.0, 22.875}, + {33.75, 22.875}, + {33.75, 24.375} + }, + {{3.75, 24.375}, {16.875, 30.75}, {30.0, 24.375}}, + { + {25.5, 22.125}, + {30.75, 22.125}, + {30.75, 20.625}, + {25.5, 20.625} + }, + { + {4.5, 19.875}, + {6.75, 19.875}, + {6.75, 4.875}, + {4.5, 4.875} + }, + { + {3.0, 22.125}, + {8.25, 22.125}, + {8.25, 20.625}, + {3.0, 20.625} + } + } + ] + }, + {FaceForm[RGBColor[0.843, 0.847, 0.847, 1.0]]}, + StripOnInput -> False + ] + }, + { + ImageSize -> 12, + Background -> None, + ImageSize -> {45.0, Automatic}, + PlotRange -> {{0.0, 33.75}, {0.0, 33.0}}, + AspectRatio -> Automatic + } + ], + "Wolfram Data Repository Reviewer" + }, + "PrettyTooltipTemplate" + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + "Grid" + ] + ]) + } + ], + Cell[ + StyleData["CommentReplyIcon"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + Thickness[0.076923], + FaceForm[{#1, Opacity[1.0]}], + FilledCurveBox[ + {{{0, 2, 0}, {0, 1, 0}}}, + {{{1.5, 7.5}, {6.5, 11.5}, {6.5, 3.5}}} + ], + FilledCurveBox[ + { + { + {1, 4, 3}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJw9U2tIVEEUvq5iVkttZmdfuo/ZbQukJGKVqPBLUTGJ0h9hVLIJRYhUVJj2\nAjGRWCKiF0llZWRCSEnZExEJ06CotaiQyH7EIrthT3u6NXPn3jswnDlzzzlz\nvu8711u9vWJzsqIoSXwv5tuk6IsgrQvOnLf+1CRC5ZKbg3WJAIJV90rNJoJF\nXOR6sebI6W3pyXq8DxccIoGwa+uxj/v/McxNbTxZOJ3w4Rkb+ZVgWGk2ZbcQ\nYfm0V+07Jhm6St7vzVhI2JfBT78ZCkI8cj2hqe/xxaIJJm0PoWEssCgtzvCc\nlzlYYwXP5iUYHpXlHV4xasXLeh4wyKCWX2fDqcJwbfQ+w4F83vGQDT1fJ1/U\ndzJ842bsih1XB3hiI0NzrPyOq9mBPb1tjpyNDBXci5U7MVQnLhji4nMsE+9W\nc6ARL3i3XSWbXNiiLi8EzPxbbqydsaD73LgHJ2wp/OiFoKVJ8Ui+Chha6M3T\nH8NZUMPm+XB9p8h0QtATjvtxqUh0SBgV76QHZN+lszReA5pNQ66o1+8HV6O3\nrdWCBIcTuKHxHJ4NQdO1sx4Nxxy4VYBug2dVt4lMnB/vGCi7TSgWz/504Etk\nVbXlNSGkCmWHqFYbJXziYXlT7VKXEdLq2DDMwyvvksTZZ5W4OgiCjmCVFTUP\ndh+3HSKJ8y9hqUogIfqn83PkCUndQoTLQsZ2gpperL3fQJLXIMEn5F5GaD3D\nl50g2O3OIkhiCUf7v8/fMJOMuRPTmT2FjLlU+0ghY471+dV93epzr/sPPaJz\nu3Ev65sNX/8//gP5Ei2u\n " + ] + ] + }, + AspectRatio -> Automatic, + ImageSize -> {13.0, 13.0}, + PlotRange -> {{0.0, 13.0}, {0.0, 13.0}} + ] + ]) + } + ], + Cell[ + StyleData["CommentCellLabelTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + StyleBox[ + TagBox[ + GridBox[ + { + {StyleBox[#1, FontSize -> 11], "\[SpanFromLeft]"}, + { + StyleBox[ + DynamicBox[ + ToBoxes[ + DateString[ + TimeZoneConvert[DateObject[#2, TimeZone -> 0]], + { + "Month", + "/", + "Day", + "/", + "Year", + " ", + "Hour24", + ":", + "Minute" + } + ], + StandardForm + ], + SingleEvaluation -> True + ], + FontSize -> 9 + ], + ItemBox[ + ButtonBox[ + TagBox[ + StyleBox[ + TemplateBox[ + { + "\"Reply \[RightGuillemet]\"", + StyleBox["\"Reply \[RightGuillemet]\"", "HyperlinkActive"], + BaseStyle -> "Hyperlink" + }, + "MouseoverTemplate" + ], + FontSize -> 9 + ], + MouseAppearanceTag["LinkHand"] + ], + BaseStyle -> "Hyperlink", + ButtonFunction :> + (SelectionMove[ParentCell[EvaluationCell[]], After, Cell]; + DefinitionNotebookClient`CommentInsert[]), + Evaluator -> Automatic, + Method -> "Queued" + ], + Alignment -> Right + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{Automatic}}, "Rows" -> {{0}}} + ], + "Grid" + ], + "CommentLabel", + ShowStringCharacters -> False + ] + ]) + } + ], + Cell[ + StyleData["OrangeButtonTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + FrameBox[ + ButtonBox[ + StyleBox[ + #1, + "Text", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontTracking -> "Condensed", + FontSize -> 13, + FontColor -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + GrayLevel[1], + RGBColor[0.77647, 0.81765, 0.84314] + ], + Evaluator -> "System" + ], + StripOnInput -> False + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[] }, + + If[ #4, + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"] + ]; + + + With[ { RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 3145484069433207908; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = HoldForm[#2[]] + ] + ], + DefinitionNotebookClient`ButtonCodeID[3145484069433207908] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ]; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + ], + FrameMargins -> {{5, 5}, {0, 0}}, + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqAQDO9nxI0+A3RSO1VDq9U8M+T9UiFICAbKAIUJ9IQtbhm\nWc9Uadd4TAQUB8oSNASoBqt2ZIRmDpohQNficgOae5D9hWYI0NcETYAgoEpc\nhgBDj0hDgCrhuiCpEc4FxgKRhgBVIhsCBJQbQhWXUD1MqBI7VEknVEmx1Mo7\n1MrFpKLBZgh+QExpDwCSuadO\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqAQDO9nxI0+A3RyphgWT7foW6Ze+taCAKygSJAcSINMcqf\n7ta6xqtzAyYCigNlCRoCVINVOzJCMwfNEKBrcbkBzT3I/kIzBOhrgiZAEFAl\nLkOAoUekIUCVcF2Q1AjnAmOBSEOAKpENAQLKDaGKS6geJlSJHaqkE6qkWGrl\nHWrlYlLRYDMEPyCmtAcACbcv5Q==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqAQDO9nxKEy5DQtmVdaw7tOX/nxbvPEARkA0WA4sQYYpAz\neeGec3icDZQFqsFjiF/jorvP3wJFvv38ver4reZ1J+Om7YQgIBsoAhQHygLV\nAFViNQRoPsSESw9fJ87Y5dW5ARMBxYGyEHPg7kE2BOILoBqs2pERxBygejRD\ngCEG8QUuN6C5B+IvSDjDDQGGPJAB9DVBEyAIqBKoHqgL2RBgDAIZwNAj0hCg\nSqB6oC6gXkhqBDKAKQHIAMYCkYYAVQLVA3VBDAECyg2hikuoGCZUiR2qpBOq\npFhq5R2q5GJqlSfUKtnILmPxA2JKewBFU/Kd\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> RGBColor[0.16078, 0.40392, 0.56078], + Method -> "Queued", + ImageSize -> {All, 23}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[ + RGBColor[0.16078, 0.40392, 0.56078], + AbsoluteThickness[2] + ], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ] + ]) + } + ], + Cell[ + StyleData["SuggestionGridTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + StyleBox[ + FrameBox[ + AdjustmentBox[ + TagBox[ + GridBox[ + { + { + TemplateBox[ + {#2, #3, {16.0, 16.0}, {{1.0, 17.0}, {1.0, 17.0}}}, + "SuggestionIconTemplate" + ], + PaneBox[ + #1, + ImageSizeAction -> "ShrinkToFit", + BaselinePosition -> Baseline, + ImageSize -> Full + ], + RowBox[ + { + AdjustmentBox[ + TemplateBox[ + { + ActionMenuBox[ + TagBox[ + PaneSelectorBox[ + { + False -> + GraphicsBox[ + { + EdgeForm[Directive[GrayLevel[1, 0], Thickness[0.025]]], + FaceForm[#4], + RectangleBox[{-1.75, -2}, {1.75, 2}, RoundingRadius -> 0.2], + Thickness[0.15], + #5, + LineBox[{{-0.5, -1.0}, {0.5, 0.0}, {-0.5, 1.0}}] + }, + ImageSize -> {Automatic, 15}, + ImageMargins -> 0 + ], + True -> + GraphicsBox[ + { + EdgeForm[Directive[#5, Thickness[0.025]]], + FaceForm[#2], + RectangleBox[{-1.75, -2}, {1.75, 2}, RoundingRadius -> 0.2], + Thickness[0.15], + GrayLevel[1], + LineBox[{{-0.5, -1.0}, {0.5, 0.0}, {-0.5, 1.0}}] + }, + ImageSize -> {Automatic, 15}, + ImageMargins -> 0 + ] + }, + Dynamic[CurrentValue["MouseOver"]], + ImageSize -> Automatic, + FrameMargins -> 0 + ], + MouseAppearanceTag["LinkHand"] + ], + #6, + Appearance -> None, + Method -> "Queued" + ], + "\"View suggestions\"" + }, + "PrettyTooltipTemplate" + ], + BoxBaselineShift -> -0.5 + ], + " " + } + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Baseline}}}, + AutoDelete -> False, + GridBoxItemSize -> { + "Columns" -> {Automatic, Automatic, Fit}, + "Rows" -> {{Automatic}} + }, + GridBoxSpacings -> {"Columns" -> {{0.4}}} + ], + "Grid" + ], + BoxMargins -> {{0.25, -0.5}, {0.15, -0.15}} + ], + RoundingRadius -> {13, 75}, + Background -> #4, + FrameStyle -> None, + FrameMargins -> {{0, 8}, {0, 0}}, + ImageMargins -> {{0, 0}, {5, 5}}, + StripOnInput -> False + ], + "Text", + FontColor -> #5, + FontSize -> 14, + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontTracking -> "Plain", + PrivateFontOptions -> {"OperatorSubstitution" -> False}, + LineBreakWithin -> False + ] + ]) + } + ], + Cell[ + StyleData["SuggestionIconTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + Thickness[0.055556], + StyleBox[ + { + FilledCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJJIGZigIIGAwcIQ8kBxk94ekHp9k9Vh8qXaoYcOfoO\nm+a+X37stKZDTP+hrxpzdOA0TBymDqYPl7n2pnG7PHlk4Pw5RxQ2FGWIwPWD\njI3p54WbLxuVYn3fnwluD8S8H/Yo9gD5KPYA+TB7YPph9sDMh9EwcZg6FPdh\nMRfdXpi7YPph7oaZD/MXzB5c4QCzBwA/Dn+d\n " + ] + ] + }, + FaceForm[#1] + ], + StyleBox[ + { + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + { + { + {8.1753, 7.4169}, + {7.7969, 11.308}, + {7.7969, 13.38}, + {10.12, 13.38}, + {10.12, 11.308}, + {9.7415, 7.4169}, + {8.1753, 7.4169} + }, + CompressedData[ + "\n1:eJxTTMoPSmViYGCQBGIQDQFKDg+rRNa5P+RzKPOXE8vSVYTz8z+0ngxpVHCA\nqBNwmPd++THv7/IO8q2vA3fICTpUvlQz5Hgj52DLdX1xga2QQxoYyDmcYLed\nHTpfGM6/k8GQ3+giCue7M1dwq7wQg+vnmbyyKdBTAm6+tsTUK5wZknD7Pec2\nqB1qk4K772Y8iCXtAHM/jP/bquBcxyUEfyJ/ldnqOmW4/qw9JZMlWFTg5tfa\nm8bt6lSB23/2DAiowN0H48PcD+PD/AfTD/M/zHxY+MDsh4UfzH2w8EUPfwD5\nN5G6\n " + ] + } + ] + }, + FaceForm[#2] + ] + }, + ImageSize -> #3, + PlotRange -> #4, + AspectRatio -> Automatic, + BaselinePosition -> Scaled[0.1] + ] + ]) + } + ], + Cell[ + StyleData["FormEditValuesButtonTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + TemplateBox[ + { + TagBox[ + PaneBox[ + PaneSelectorBox[ + { + False -> + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzNWHlMVEcYf28XlGM5VlcRapRDDFK0sBaLBWVXUDxTKpe4JgvoQlALAsvV\nhHIoV4KK6wGiQlUqoqDcKKysDSZtPZJWTTzaxGrV2mqrNtqKB3Qnz8+Zd6Cv\ntn90vkgyv+/4zc58M9/3dEtIXZoooSgqw8r8Z2l8tjo9PT43wtE8iUrJSE5K\n0a1akKLXJenSAxKkZlD58h9y+X+M8Z7a/I3G7V/lHQgKp2kGmzw9rcrQb+j/\nZItPIGBvNywsVVGVJ01DWAqbpBYUFZ1hGsTYvssRqTLHt4nvoIgvbP6ZjM+I\nNt9PzUePPdbvcvX+ZwzTQ9vv8yMh6R04fFNY0/ciOkM8wzjXY4+F47xJgiPF\ncqRuY3kOlnUGLFq4khsv53NPv8zd7NXs/lYsR+158Gm9l1Tu7IYwmq7oJaMd\nuWMnR7jMMXLd/isYt7UXx4F9Rjtj1NmNXPPsCKyh6S9+AHzUOHEcpR3gMWM+\niQdHrq1kZFkmidvYQS633399ZBf31G21F/ZdLmmvPo0zVcyalCFg33Qr78Ce\n7+qv5jdOm8W3e39u9yN+npR3ieHQ5ArlWGwW28pBIXwfilvFcESnC2eyMoS0\nii8UstncZ2XDjiaROihGjbMcyWVJLBP0N2ELC8vm229icHFPKKo+Y3zK3Jj6\nq2lV3gFvZpk4BfSqKHwfFC4fLNDml3cVt2IGO7m+5sRzfoSNxglemGVV8dZT\nyRXqaKeJ5V1gkWIALX5bk8r5u+3x3qEbwvuN3kJ1DN9j5mLQdz60skXIeM9X\nPoPMnWYzdD4cjoGRMC3XRyI5+CNolyQhJK4A5mWdXGs7Ofs3HP+z9nz16fbf\nScz41Muf67c8B7Q7z6L5RiPMAxZxbfU1OFbDtVDNSGtmnb4qQz/W1F1ElYsc\n8rG9A6BF8x1fw2zhSnbddHHHJ115kl3rJNI1mzBL6HI2x9SglrugQzHzG7Ft\nRQ95IglF+DfwqylNb2gRugnWMnNteFWLj/+FsNlLyd3tfoTrTPWZV+vUcBnQ\ncHbre8HoTzy3ljGYxzT2Cep3MespaibRtZWwGy9vnPmkmXPgjy1fgte7Mxlk\nfhwZa/8V+9EQTZuPzwg4HBSA1J4XZqCotB1gExTO58hrYOoYM5RzcCcAHHIn\nQKpPD8eBzx12GHP0PAlfjXPI3C8J7JXlSNjt9vuSYVrKkjbwUs4R2quCwxLU\nmFJTZpCoaQjXuPqrgPmqhBhs7XH1lTsxmP889su24lOEZuzEyJE7ZJ3Gu23o\nZ9bDHvitrb2A0Um+NedwxKO/IGzrKZhn15FnRFHeAdh2zSZuXxscCXtpGorR\nkxqpRWx2zxPQsTk8/bgrxe+MaWj9UXw/be11pZih5VduxzPCqu03kiPFALPM\n3VyOCV5kv9P3ovJk6rbkipI2du3n39AwLegO3UBzn0CYH3vMfzHUMeyM4Mu6\n7Vwfiqr6BrRxBWhO0/suAxK5jm8fpoX7LszAz4bJStAanylcGCwiFbD9V2ja\nxk4ZosmNTsc+Xv51F4Xit9yduwJbqaJ0JYEfoT4xaw9YFDaBVuaId93cVb58\nMxPLsL/UIlSz2URmft3FGL2tA7YI1UAONF7HOeWnxhb6XULrJFnQsLHz+XDW\nx6ooZQjcOD4DKXsvkfnu6i1kYxpaVcw/H/5QRQl7L0lk27HfLJCtp8Rw6EqF\nfDe08F+54MjaC0jX8aDpFtglV4jhCAoH+44HzPvdfFuTy63xMGwd5GMpKq8B\nfNTRpNZj2vw4RvznkfhoZ7A/fBO9AdzTEhrM70HiNBGj1jJcRY3PJvmSHod+\nAo3Yr2j8HVXeNXMx7Cr7K7HmHOzFZGXWHpytjmPEcXx2kIzWcG15juOYqUHk\ndz+S2OwRVmFa3DkhaboljgF1R9wc6R3A/RJIz5PWe1wsNlssB0XFZgllI8Qe\nTrOhxcJSPAfqIjabhOLkNYSvFsL3XlqsG67qv264eqcYuv4gI9V/bz+Kptcf\nIbETz4ualXP+zf/+WMuWJO08i2J1P0qrYjJTIl2WyXx5NV6PK1C88/bR/7vx\nN3kqZvY=\n " + ], + {{0, 50.0}, {50.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {50.0, 50.0}, + PlotRange -> {{0, 50.0}, {0, 50.0}} + ], + True -> + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzNWG1MU1cY7m1vS4GWttBLy0dLWyhl5aultrT0C2QzM5rMIWgyluDHkMwf\nYgBF9gc1cWpijDNuRNFsv2Rmuqmb/NjIYIFkG2qyAYnAljidODfdmItu+AHs\nXi6n59x7D3LH9mPnRJLzvB/Pue95z3nfat3UWLVFKpFImpX0n6qNrRVNTRvb\n1mrpRc225tcbttW/tnJbS31DfZN/k4wGS+b/MSb/jxFvt7QX95R86TytXyMh\nWEztye1w97v7c97SBAG2tEHIqRpXX/ksnPlnCVIiMTWXz0DMN5rZSGqX4l+u\nt+wp+wn1z05Lu7ZCiIYfOjoTnf+MQfd8aFLoiZmRR4FbeEl02tQsnkFpCT/E\n+1lsUtViOezHOJYzhZdSVqVt5vvLe0/ldpzk7mbZN2I5vEPAJnjPdlBpnQOJ\n4s9Qb2V3SB0Dk9rM7b4xiJNJ4jigjSINiaAV3TO1FjEgSr+PWRjFcRR+AiyS\nX0RxqjrnCDtNO1Bcpga5HJp8tud4m/2Yd9g3WvixZxBmqpg96SqBfmDCeXrZ\nt6XjzjOaMEbvhfADYZ4UdYvhMLfhcsy8k6sl1+PvQ8EFMRymJnwm6ypRLcse\nnI7rc1kC1xshk+sVRmkcn8V2AGvfi1jKy24vxhBvs+71XI4+Zm9M6XhuR5J/\ncZaE54CcqoH3IS49eaWlvai74AJkIHWOE9GnQg/FPQl5kMW6zz2QfSh1nTKr\nqBto2I8CKXxbbQeF0VYVB27i4828hanrhRYpq4E8dF+WOBcFe8xmZv5OcxhC\n9xdiYKexjm9DSP0/AGl6A4NYdoN14SW+NqnjfkPkT++QZzD0G4pFH6u9fDvz\nLiD1XGHWxT1gnbKKr+s4AX35rxtqpfHsPrXl7n4o8Y4wlQsditTIIyBl1iVf\ngVXaZm7djLfBk3b1cWsdIcs5DFkMr3A5NKHg3RgH7dN5BsmUT9ETse6F34Cp\npkTBedxNkKno2hCrxZG/GIyq4mTKA1hnPJdj+6wVMEiYlzg6PX8mT2UqFlMV\ncU/Q0cnuJ/8ciuYcAdGYv3H0SbPnIByuL4BVUoBFjBtQX74xeQrwZmmHZwQ4\n5PrYmQ7hGSSS3HeADt0XCTicXWwdY4duOewEAIfCEMu/wYU44LmDCEOOyFTG\nVphDdL+EiZU0DkQ7NEks0FIWXgRWuuW4WOV/QDCNqSTJh6Lls7DGlY4DTFuO\nYyCTYPVVGFgseQX3Zct6Yy6mxyFSdget0zDa7n52P9wB31rvMERVLs9VxOPP\nDOYeAOu8d9Ezor/Qj0TwML+vpapBLOlvb0ElBGlujUzF7iCHQ+Xm7xS+M3RN\n/AjeTzLJth8yBH/hdzxSZfBXlMN+NHZfTvI5EvLQfic67eqzH8s+VHiRW/uF\nN9RYB2SBm8xaEwTr8EPhi5G6npsRwml/m29Dv4FfA6llNxs+3yhAMrcL9Y11\n4L7jGYTZoC6JffmTuHQWy2wEmG+MvvRqXaW5zdSE2Hi9Izj/wbuGV6EWVWN7\nU/8S0yc6TsXux1kgJbUw6nRXOf9m2g5Ae4I01Lp60cz3jphaSA3UMNSCHPDf\ngDmlrYAajk7cPlEWZsjUmjL9y1SNrhLcOCEDOn3X0HxPdOJ0ymet+4TnIxxU\nDd46fQtXj/tmgekeEMNh24+zLTgvfOWoau8wIwv9HpgAetmHxHDo1wB92nbu\n/S67bW7j13gwSI0ila6+XcAmdR0qVRUZN7AzeQWKK9KAfuAW8wbwTws32O9h\npjILojIVrKLRJyoXahH4EUjE/oqGv6OKulNWg6hyfyV6roJYqEscp2C2yilx\nHM73UW/+6+ZdckoTQn/3M9PcKlUa62DnNBerCXEMTHfEz5HII9gvxbCp4D0+\nZm4Vy0H3kjtx2Qh8LyShs1UunoPpIly9OD/OroytONx3La1+oar/rJHotB8N\n/4F6Kv1Onkz3hx+iWPRp/jm6Y/gX//sjU6U3eK4wvsIPcjvYzCRkph3sLy//\nDcvuuIyle//vxt/PCE6d\n " + ], + {{0, 50.0}, {50.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {50.0, 50.0}, + PlotRange -> {{0, 50.0}, {0, 50.0}} + ] + }, + Dynamic[CurrentValue["MouseOver"]], + ImageSize -> Automatic, + FrameMargins -> 0 + ], + ImageSize -> {Automatic, 15}, + ImageSizeAction -> "ResizeToFit" + ], + MouseAppearanceTag["LinkHand"] + ], + "\"Edit values\"" + }, + "PrettyTooltipTemplate" + ] + ]) + } + ], + Cell[ + StyleData["HintPodTitleBar"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + GrayLevel[0.97], + FilledCurveBox[ + BezierCurve[ + { + Offset[{0, -3}, {1, 1}], + Offset[{0, -1.3443}, {1, 1}], + Offset[{-1.3443, 0}, {1, 1}], + Offset[{-3, 0}, {1, 1}], + Offset[{-3, 0}, {1, 1}], + Offset[{3, 0}, {-1, 1}], + Offset[{3, 0}, {-1, 1}], + Offset[{1.3443, 0}, {-1, 1}], + Offset[{0, -1.3443}, {-1, 1}], + Offset[{0, -3}, {-1, 1}], + Offset[{0, -3}, {-1, 1}], + {-1, -1}, + {-1, -1}, + {-1, -1}, + {1, -1}, + {1, -1} + } + ] + ], + InsetBox[ + FormBox[ + StyleBox[ + "\"Notebook Analysis\"", + FontColor -> GrayLevel[0.4], + FontColor -> GrayLevel[0.4], + FontFamily -> "Source Sans Pro", + FontWeight -> Plain, + FontSize -> 13, + StripOnInput -> False + ], + TraditionalForm + ], + Offset[{8, 0}, {-1, 0}], + NCache[ImageScaled[{0, 1/2}], ImageScaled[{0, 0.5}]] + ], + TagBox[ + TagBox[ + TooltipBox[ + { + GrayLevel[0.6], + DiskBox[Offset[{-13, -10}, {1, 1}], Offset[6]], + GrayLevel[0.97], + AbsoluteThickness[1.5], + CapForm["Round"], + LineBox[ + { + {Offset[{-15, -8}, {1, 1}], Offset[{-11, -12}, {1, 1}]}, + {Offset[{-15, -12}, {1, 1}], Offset[{-11, -8}, {1, 1}]} + } + ] + }, + FrameBox[ + StyleBox[ + "\"Close analysis pod\"", + "Text", + FontColor -> RGBColor[0.53725, 0.53725, 0.53725], + FontSize -> 12, + FontWeight -> "Plain", + FontTracking -> "Plain", + StripOnInput -> False + ], + Background -> RGBColor[0.96078, 0.96078, 0.96078], + FrameStyle -> RGBColor[0.89804, 0.89804, 0.89804], + FrameMargins -> 8, + StripOnInput -> False + ], + TooltipDelay -> 0.1, + TooltipStyle -> {Background -> None, CellFrame -> 0} + ], + Annotation[#1, "Close analysis pod", "Tooltip"] & + ], + EventHandlerTag[ + { + "MouseClicked" :> NotebookDelete[EvaluationCell[]], + Method -> "Preemptive", + PassEventsDown -> Automatic, + PassEventsUp -> True + } + ] + ] + }, + AspectRatio -> Full, + ImageSize -> {Full, 20}, + PlotRange -> {{-1, 1}, {-1, 1}}, + ImageMargins -> {{0, 0}, {0, 0}}, + ImagePadding -> {{0, 0}, {0, 0}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodDelimiterTop"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + AbsoluteThickness[1], + GrayLevel[0.85], + CapForm["Round"], + LineBox[{{-1, 0}, {1, 0}}] + }, + AspectRatio -> Full, + PlotRange -> {{-1, 1}, {-1, 1}}, + ImagePadding -> {{0, 0}, {0, 0}}, + ImageSize -> {Full, 2}, + BaselinePosition -> Scaled[0.1], + ImageMargins -> {{0, 0}, {4, 0}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodDelimiterBottom"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + AbsoluteThickness[1], + GrayLevel[0.85], + CapForm["Round"], + LineBox[{{-1, 0}, {1, 0}}] + }, + AspectRatio -> Full, + PlotRange -> {{-1, 1}, {-1, 1}}, + ImagePadding -> {{0, 0}, {0, 0}}, + ImageSize -> {Full, 2}, + BaselinePosition -> Scaled[0.1], + ImageMargins -> {{0, 0}, {0, 4}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodFooter"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + GrayLevel[0.97], + FilledCurveBox[ + BezierCurve[ + { + {-1, 1}, + {-1, 1}, + Offset[{0, 3}, {-1, -1}], + Offset[{0, 3}, {-1, -1}], + Offset[{0, 1.3443}, {-1, -1}], + Offset[{1.3443, 0}, {-1, -1}], + Offset[{3, 0}, {-1, -1}], + Offset[{3, 0}, {-1, -1}], + Offset[{-3, 0}, {1, -1}], + Offset[{-3, 0}, {1, -1}], + Offset[{-1.3443, 0}, {1, -1}], + Offset[{0, 1.3443}, {1, -1}], + Offset[{0, 3}, {1, -1}], + Offset[{0, 3}, {1, -1}], + {1, 1}, + {1, 1} + } + ] + ], + InsetBox[ + BoxData[ + FormBox[ + TemplateBox[ + { + StyleBox[ + TemplateBox[{3}, "Spacer1"], + FontColor -> GrayLevel[0.4], + FontFamily -> "Source Sans Pro", + FontWeight -> Plain, + FontSize -> 12, + StripOnInput -> False + ], + StyleBox[ + #1, + FontColor -> GrayLevel[0.4], + FontFamily -> "Source Sans Pro", + FontWeight -> Plain, + FontSize -> 12, + StripOnInput -> False + ], + StyleBox[ + TemplateBox[{5}, "Spacer1"], + FontColor -> GrayLevel[0.4], + FontFamily -> "Source Sans Pro", + FontWeight -> Plain, + FontSize -> 12, + StripOnInput -> False + ] + }, + "RowDefault" + ], + TraditionalForm + ] + ], + Offset[{5, 2.5}, {-1, 0}], + {-1, 0} + ] + }, + AspectRatio -> Full, + ImageSize -> {Full, 21}, + PlotRange -> {{-1, 1}, {-1, 1}}, + ImageMargins -> {{0, 0}, {0, 3}}, + ImagePadding -> {{0, 0}, {0, 0}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodMenuItems"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + TemplateBox[ + { + #1, + FrameMargins -> 3, + Background -> GrayLevel[1], + RoundingRadius -> 0, + FrameStyle -> + Directive[ + AbsoluteThickness[1], + RGBColor[0.75686, 0.82745, 0.88235] + ], + ImageMargins -> #2 + }, + "Highlighted" + ] + ]) + } + ], + Cell[ + StyleData["HintPodActionMenuItem"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + ButtonBox[ + TemplateBox[ + { + TagBox[ + GridBox[ + {{#1, TemplateBox[{7}, "Spacer1"], #2}}, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Top}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0}}} + ], + "Grid" + ], + FrameStyle -> None, + RoundingRadius -> 0, + FrameMargins -> {{5, 2}, {2, 2}}, + ImageSize -> Full, + ImageMargins -> {{0, 0}, {0, 0}}, + Background -> + Dynamic[ + If[ CurrentValue["MouseOver"], + GrayLevel[0.96], + GrayLevel[1.0] + ] + ] + }, + "Highlighted" + ], + ButtonFunction :> ReleaseHold[#3], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "1:eJxTTMoPSmNiYGAo5gESfqW5qUWZyY5FRYmVScxAARhmAeL/QAClwDQDBPxHFg8WALJC84oz0/NSUzzzSlLTU4ssAL+sIf8=" + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> {72, 72}, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "1:eJxTTMoPSmNiYGAo5gESfqW5qUWZyY5FRYmVScxAARhmAeL/QAClwDQDBPxHFg8WALJC84oz0/NSUzzzSlLTU4ssAL+sIf8=" + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> {72, 72}, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "1:eJxTTMoPSmNiYGAo5gESfqW5qUWZyY5FRYmVScxAARhmAeL/QAClwDQDBPxHFg8WALJC84oz0/NSUzzzSlLTU4ssAL+sIf8=" + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> {72, 72}, + Interleaving -> True + ] + }, + Method -> "Queued", + Evaluator -> Automatic + ] + ]) + } + ], + Cell[ + StyleData["HintPodDisabledMenuItem"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + ButtonBox[ + TemplateBox[ + { + TagBox[ + GridBox[ + { + { + #1, + TemplateBox[{7}, "Spacer1"], + StyleBox[#2, FontOpacity -> 0.4] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Top}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0}}} + ], + "Grid" + ], + FrameStyle -> None, + RoundingRadius -> 0, + FrameMargins -> {{5, 2}, {2, 2}}, + ImageSize -> Full, + ImageMargins -> {{0, 0}, {0, 0}}, + Background -> GrayLevel[1.0] + }, + "Highlighted" + ], + ButtonFunction :> Null, + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "1:eJxTTMoPSmNiYGAo5gESfqW5qUWZyY5FRYmVScxAARhmAeL/QAClwDQDBPxHFg8WALJC84oz0/NSUzzzSlLTU4ssAL+sIf8=" + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> {72, 72}, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "1:eJxTTMoPSmNiYGAo5gESfqW5qUWZyY5FRYmVScxAARhmAeL/QAClwDQDBPxHFg8WALJC84oz0/NSUzzzSlLTU4ssAL+sIf8=" + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> {72, 72}, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "1:eJxTTMoPSmNiYGAo5gESfqW5qUWZyY5FRYmVScxAARhmAeL/QAClwDQDBPxHFg8WALJC84oz0/NSUzzzSlLTU4ssAL+sIf8=" + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> {72, 72}, + Interleaving -> True + ] + }, + Method -> "Queued", + Evaluator -> Automatic, + Enabled -> False + ] + ]) + } + ], + Cell[ + StyleData["HintPodActionLabel"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + PaneBox[ + StyleBox[ + #1, + FontColor -> GrayLevel[0.2], + FontFamily -> "Source Sans Pro", + FontWeight -> Plain, + FontSize -> 13, + LineIndent -> 0, + StripOnInput -> False + ], + FrameMargins -> 0, + ImageMargins -> 0, + BaselinePosition -> Baseline, + ImageSize -> Full + ] + ]) + } + ], + Cell[ + StyleData["HintPodMenuDelimiter"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + PaneBox[ + StyleBox[ + GraphicsBox[ + { + CapForm["Round"], + GrayLevel[0.9], + AbsoluteThickness[1], + LineBox[{{-1, 0}, {1, 0}}] + }, + AspectRatio -> Full, + PlotRange -> {{-1, 1}, {-1, 1}}, + ImageMargins -> {{0, 0}, {2, 2}}, + ImagePadding -> {{5, 5}, {0, 0}}, + ImageSize -> {Full, 2} + ], + LineIndent -> 0, + StripOnInput -> False + ], + FrameMargins -> 0, + ImageMargins -> 0, + BaselinePosition -> Baseline, + ImageSize -> Full + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconChevron"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + GrayLevel[0.2], + AbsoluteThickness[1.8], + CapForm["Round"], + JoinForm["Miter"], + LineBox[{{-0.5, 1}, {0.5, 0}, {-0.5, -1}}] + }, + AspectRatio -> Full, + BaselinePosition -> Bottom, + ImageMargins -> {{0, 4}, {0, 0}}, + ImageSize -> {5.6, 7.7} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconPopOut"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + FaceForm[GrayLevel[0.4]], + FilledCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGIlIGYC4h1yra8Dd6g4rHN/WCWip+KwRiYqxXq+isNk\nCZYwvlwEDROHqYPpKwUrUHFgAIEDKg5nzwDBG2VU/hlluPogMEMCzm9kOdpv\naC6OJi/mINR84NRCVwQfIq8M519wufHhi5Yymn4lNPOVHNLAQBHO/6YR03/o\nK5eDB9Ab69wFHJoeHZ+xexqng8r0/xPqfvM5cG9dVnl8JacD0FO6m+byOPxL\n/f4kUZHbQZr3ge4EBW6HD2IeAX9m8Dhkzyqfs2gxp8ONxmK3Kd/4HOYsUt75\np50Tbi6YesgF9b8ShJ+oCOfD3Anjw/zx9JP8pXx7hD9h4QfjqxtyAKNCBU0e\nEY4wPqr5iHh4/nvlx0tnVRyYObvkk98pOwA9+X75MRUHWWD03udHxCssngGf\nXO7X\n " + ] + ] + }, + AspectRatio -> Automatic, + ImageSize -> {14.0, 14.0}, + PlotRange -> {{0.0, 13.62}, {0.0, 13.62}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconWrench"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + GrayLevel[0.4], + AbsoluteThickness[1], + Opacity[1.0], + JoinedCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJRIGYCYmWv6mZ9n3/2cmJZvp/5BBzci37yv9wu6/Au\nysnuhaQynG8at8uT55AGXJwBDHQdPl3yTRKIUIfzo1Ks7/vzajiosjVOdfbW\nccjaUzJZokUFrv8ySLmlqoPbts9/r1iowsVh6mD6zp4BAh4NnPbA3AHTr+ss\n8/rRNoS7YXyYv2D+7H/ySf5SPrdD7D/nX29ff7H/6hXZZnGNGc6HqYPRMPED\nb+bZ6FxBqAPpOprL7YAefgCtVISU\n " + ], + CurveClosed -> {1} + ] + }, + AspectRatio -> Automatic, + BaselinePosition -> Scaled[0.2], + ImagePadding -> 0.5, + ImageSize -> {16.0, 16.0}, + PlotRange -> {{0.0, 16.0}, {0.0, 16.0}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconInfo"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + FaceForm[GrayLevel[0.4]], + FilledCurveBox[ + { + {{1, 4, 3}, {1, 3, 3}, {1, 3, 3}, {1, 3, 3}}, + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + }, + { + {1, 4, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3} + } + }, + { + { + {6.81, 13.0}, + {3.3914, 13.0}, + {0.62, 10.229}, + {0.62, 6.81}, + {0.62, 3.3914}, + {3.3914, 0.62}, + {6.81, 0.62}, + {10.229, 0.62}, + {13.0, 3.3914}, + {13.0, 6.81}, + {13.0, 10.229}, + {10.229, 13.0}, + {6.81, 13.0} + }, + CompressedData[ + "\n1:eJxTTMoPSmViYGCQB2IQbct1fXGBrbRD6+vAHXKtvA7r3B9WiayTdoCI8zgc\n/qoR039IHkoLOjCAgYKDB0iZu4CDPFijgsOsmSDAC1UnCzWPE0rLQMXZHV6x\nmAia1Ug56E1Y8MMwjdXh685bXX9VJRx4Jq9sCvRkcTh7BgREHfoPgTSwOAQB\ndb8OFHYAO4eLFeo+IQcRMIMLzoe4h9dBW2LqFc4MYYd4zdMCx38JOviYdzom\npIo4PJgjuHSvo6jDkgKQz0QdCsEelHDQjAHZJAa1VxIqLwH3Jzofok8S4i9W\nRQews67LQsJhnoKDMRjIQ9Q3wMJJwQFMJULDSRJmrhzUPKh6Blmof+QcwM6K\nkXb4Bgq2rzJQcXFovMhA5UUdciqqluo0SztsKMqY+NZG2OHV1E08hTrSDquA\noTmXQdABPX4BaWq/EA==\n " + ], + { + {8.81, 9.79}, + {8.8101, 9.5122}, + {8.5878, 9.2854}, + {8.31, 9.28}, + {7.51, 9.28}, + {7.2283, 9.28}, + {7.0, 9.5083}, + {7.0, 9.79}, + {7.0, 10.62}, + {7.0054, 10.898}, + {7.2322, 11.12}, + {7.51, 11.12}, + {8.35, 11.12}, + {8.6239, 11.115}, + {8.8447, 10.894}, + {8.85, 10.62} + } + } + ] + }, + AspectRatio -> Automatic, + ImagePadding -> 0.5, + ImageSize -> {14.0, 14.0}, + PlotRange -> {{0.0, 13.62}, {0.0, 13.62}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconNone"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { }, + AspectRatio -> Automatic, + ImageSize -> {16.0, 16.0}, + PlotRange -> {{0.0, 16.0}, {0.0, 16.0}}, + BaselinePosition -> Scaled[0.2], + ImagePadding -> 0.5 + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconIgnoreAlways"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + EdgeForm[None], + FaceForm[GrayLevel[0.4]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJTIGYCYpF17g+rROQcbLmuLy6wlXaoBguoOvQf+qoR\nw6/i8CZwh1zralWH4oyJb2vsVRx0N819v/yYqoO0/l0VtkYEv/U1UOFRBP/D\n8mPe5pyqcP0z8oSaD3ipws2H0famcbs8fVQd2BqnOnevUXUAa+dWdUgSiLDc\nckLVwQPounXHVeB8kK1TmxH8gN7peULOKnD9EP+owM2H+QvmzyUFIBEeuHxC\nmb+c2CtuuP75NjpXZj3jgpsP0s11nRPO5+feuqzyOAec73dxYsy/w+xw/WDr\nuNjh5n9MPhPr7cEG93+V2Wq78Nus8PCB8WHhB+PDwhemHxb+MPNh8ZMGBhJw\nf8Lkv2nEAJXwOGyu/rQh4DWrwwrTs9Z+F7kdvHiYtNunsTrYgrwpy+XQteHh\ny6lGbA6HxNWCWRdzOJwKObhiyTk2B3fmCm4VDXaouRwOEaeMjmzUY4OHhybI\neA02eHgt/GH4bJ0qm4PT+bSrz4Hh+Z0tfobPVDZ4eIOVx7DD3QlzNwMYIPx1\nsmzffCl9FUg4u7M5hPEBU1S+isPs0Pmr195gdTAGgc0qUHewOswDJhfv7yoO\n/g7CiYcvszoAU9vrQAtVh6V+QAFnNqg9iHj5dMk3SWAGIt78wBGJiFcYH+ZP\nGB/mT5h+WLqBmQ/zJwC4F0s3\n " + ] + ] + }, + AspectRatio -> Automatic, + ImageMargins -> {{0, 0}, {0, 2}}, + ImageSize -> {14.0, 14.0}, + PlotRange -> {{-0.5, 13.62}, {-0.5, 13.62}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconIgnoreInCell"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + EdgeForm[None], + FaceForm[GrayLevel[0.4]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + {{0, 2, 0}, {0, 1, 0}} + }, + { + { + {11.69, 13.37}, + {7.57, 13.37}, + {7.57, 12.37}, + {7.76, 12.37}, + {11.19, 8.93}, + {11.19, 1.25}, + {7.57, 1.25}, + {7.57, 0.25}, + {12.19, 0.25}, + {12.19, 13.37} + }, + {{9.17, 12.37}, {11.17, 12.37}, {11.17, 10.37}} + } + ], + FilledCurveBox[ + { + { + {0, 2, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGIjIGYCYo+HVSLr3EUdbLmuLy6wlXZYUgBiyTlAxJUc\nkt9FOdllyDuU6yrKf1mD4LM879F466sMV28MApuVHX7yv9y+3lkOQj9WdngU\nIb794gFZh/Dojfvf/FN22CHX+jrQAsHvf/JJ/tJ6GTgfbI+ODFz/2TMgIA03\nvxroqodVQg5gSkQO6m4mVPubGR1E7I/d2fpE2cHy2tFckwYGB2n9uypsjCoO\nYG89/GcP4wd5zm1QO/QHzr9wNeyN/u5f9jD9kHD4aQ8zX+z36XcnD3+3v8fE\n2SXfrOygvqBzw8OX3+yDQAxHBB/srr9KcL7mW959BjuV4PrnCi7de7BcCW4+\nLLwhND88PmDyEHcLOjg2PTo+Y/d3+/21shbpLYIOTglPLyjd/mZ//wH35JVM\nCD4knATgfL0JC34YPuOH688Nq1237REf3HzNmP5DXzX4HLhVNOp6dv6yP3xZ\nO1UyiRcePrlH/22q/sQDD79vGiANPA5yy1946NUzOOy61fU39TuPw5GNenmL\nGxkdwPal8cLjB2Y+LP7SwEDCgQEMZODyf7+VPpgTKOOw9ldM7tE6XgfmCqCL\n9sk43PfvnZ4nxAuJZ2NZB5j9UV933uraK+swf/XaG/HfeCDudZJzuA1yTgov\nPH3CzBcAJg/mdHmHVElQyuSH851lXj8ykxKEq4eFNwCKHGBr\n " + ] + ] + }, + AspectRatio -> Automatic, + ImageMargins -> {{0, 0}, {0, 2}}, + ImageSize -> {14.0, 14.0}, + PlotRange -> {{-0.5, 13.62}, {-0.5, 13.62}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconIgnoreInNotebook"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + FaceForm[GrayLevel[0.4]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJTIGYC4qAdcq2vAwUcbLmuLy6wFXdYUgBiSTp4PKwS\nWeeu4GCgtVL4AouUw1zBpXsPlis4vDlgqexlLeWg+ZZ3n8FOBB+s/y+CH6S+\noHODoyJc/z0mzi75ZkW4+cYgsFnRoanYbco3N0kHEftjd7Y+UXRYeM3kvcVR\nCYeQx0tnH2FQgroLwb9pWxmxYqs4nP9zQfrmV8bicP0g1VzXxeDmf9OI6T/0\nlcsB6Bmgj6QcGMDggz1MvoTnRNz7f2/sf/K/3L7+saLDzmCriP/PX9iHR2/c\n/+YfzL1P4Pz+Xoc96+IfwPkrVqZm1068AdcPtAxo4yW4+ccenln/jOGkPcz/\nMjWJRqEGh+xh4QPjw8IPxoeFL0w/LPxh5sPiB0KzwuNPHhibO+Su2h8GKTvE\n7aAYeYAl7+5Z+/rfVgXnOLgdPu6qO5h345j9voPiasGsXHA+JJw44Hy9CQt+\nGD5jh+vPDatdt+0RG9x8TZByDTYH/uky5V7st+21JaZe4cxgdZgp5PnFqOuh\nvQY/99ZlP1kcIO54CjWfxeFeX0HUh0Uv7bdEft15i4vVoa2/Q3Oiy1t77Xax\nm+fKWeHxAzMfFn9pYCACj1+YfMeX29cbgfF/+LJ2qmQSKzx95B79t6n6Ews8\n/cDsB3O5JB1Upv+fUPebxeHIRr28xQeB6e+Cy40PX1gdnjTPO7uKX8qh/8kn\n+Uv57A4sYXy6m2KlHDjBCY3DwV9OLMvXGJjeda7MejaXC56eYeENAPSkchE=\n\n " + ] + ], + FilledCurveBox[ + { + { + {0, 2, 0}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJdIGYC4qAdcq2vL6o52HJdX1ywVwtC24rB+YdTViWE\nXBKE86tF1rk/rOJxMAaBzxpwPkReDY2vCDVPCMpXhvPB+jerwfnPf6/8eOms\nukPDdoemR+wiUHkNuHtgfJh7YXy2xqnO3W/U0eQ14ObB+DD7YHzNmP5DXzWY\n4PzY3KP/NlX/toeZBxYP/GIPsw/GBzuHSxrOX7TF/MchFSkH9g9iHgF/Ptmb\nvrdwdTeSdNjZywYU+WQPcb8E1B+f7H8EP146m0XcYeE1E6DKT/Z9IGUXRB02\nV3/aEJD92R5s7A4Rh1kzQeCr/YQFPwyfvRN2+Put9MEcwe/2894vP+ZtLuxw\n3793ep7QT3uIOiEHkC651t/2YH8a80LtY3NA5TPB+RPrflsVnPtkL/8lJ6xW\nT8jhTSDYo1DzxOB8BjBQh/O/aQADzlQTTV4bbh6MD7MPxoeFfwDI2czaDmfP\ngAA0nCdqOTglPL2gdFvDweNhlci645oO8iAPzdOEmPNXw+EPMDp9k7Qc4nZ5\n8jC9VncAG39KywE9/QIAH6UuJw==\n " + ] + ], + FilledCurveBox[ + {{{0, 2, 0}, {1, 3, 3}, {0, 1, 0}, {0, 1, 0}}}, + { + { + {5.63, 11.05}, + {5.63, 10.44}, + {6.0569, 10.539}, + {6.5048, 10.49}, + {6.9, 10.3}, + {9.53, 10.3}, + {9.53, 11.05} + } + } + ], + FilledCurveBox[ + {{{1, 4, 3}, {0, 1, 0}, {0, 1, 0}}}, + { + { + {7.92, 3.73}, + {8.0396, 3.4994}, + {8.0784, 3.2353}, + {8.03, 2.98}, + {9.41, 2.98}, + {9.41, 3.73} + } + } + ], + FilledCurveBox[ + {{{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}}}, + { + { + {6.73, 6.21}, + {6.2, 5.82}, + {6.67, 5.46}, + {11.22, 5.46}, + {11.22, 6.21}, + {6.73, 6.21} + } + } + ], + FilledCurveBox[ + {{{1, 4, 3}, {0, 1, 0}, {0, 1, 0}}}, + { + { + {8.0, 8.7}, + {8.0514, 8.4458}, + {8.0162, 8.1818}, + {7.9, 7.95}, + {10.25, 7.95}, + {10.25, 8.7} + } + } + ] + }, + AspectRatio -> Automatic, + ImagePadding -> 0.75, + ImageSize -> {15.0, 15.0}, + PlotRange -> {{0.0, 13.62}, {0.0, 13.62}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconHint"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + EdgeForm[None], + FaceForm[#1], + FilledCurveBox[ + { + {{1, 4, 3}, {1, 3, 3}, {1, 3, 3}, {1, 3, 3}}, + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + }, + { + {0, 2, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + { + { + {9.015, 17.37}, + {4.4559, 17.37}, + {0.76, 13.645}, + {0.76, 9.05}, + {0.76, 4.455}, + {4.4559, 0.73}, + {9.015, 0.73}, + {13.574, 0.73}, + {17.27, 4.455}, + {17.27, 9.05}, + {17.27, 13.645}, + {13.574, 17.37}, + {9.015, 17.37} + }, + CompressedData[ + "\n1:eJxTTMoPSmViYGCQBGIQbcixRiYqRcVh3bak+pu23A5rf8XkHt2n7OC/fkpq\nx2MOB8+5DWqHnik5nP8e/HjpbHYHj4dVIuvYlRyAiisjVrA78Bau6b6toegQ\nApQ9soDdQepAtIJjoILDJ8fzaVefczgs6Nzw8GWoPNx84yMb9fIeyzr831T9\nacMFXod1N+LL/OVkHV5uX8/8/IyAw7Fck4btDrIOZQ/mCC7dK+TAXMGtomEn\n6/DP+dfb1w0iDkIi9sfufJV1ePRy6iYeQzGHac7dOc+t5R3SwEDcwe7FzTW/\nbBQc9kybwF+1TcLh7TwbnStSig7Hd+3oZSuQdDjab1iuy6jk0MIL8qGkg8f+\nWlmL50oO9uHRG/fnSDr4fu4LLjmi7HDw1ELXbZslHGDhAzO//9BXjRh+VQeG\niXW/rQzEHKzv+/dOz1N1uFfY1fekSMRhzhGFDUUZqhB/LhaCmFOs6sC0h1VI\nZL+Ag8g6d2AIqjqYCJrZ7L3E64Ae/gDrrapT\n " + ], + CompressedData[ + "\n1:eJxTTMoPSmViYGBQBGIQ/emSb5KAhJoDAwg0aDhYbjlRtu++isNudX7urWpK\nDrX2pnG7Tqo4TFPsKy2sVnRQvv2zLqtGBULfUXAI6J2eJ8Ss4mDSsN2hKUnB\nIa0jOfZOmrKD/l0Vtsar8g5Gz9apPlms5GDgs4zLLVXeweLHoZRVDxQdnNdm\n3ivskneQW/7CQ09e0aHEbco3tnh5h+jLex6LxCo4FErzPtC9IO+wVfT36Xed\n8nDzH5tJHYheIOeQBxJ4pOCgu2nu++Vscg75Qs0HTjUqOjDkN7IcPS/rcObd\nycNOukoObqqlTLM4ZOD+O7JRL2/xQWkHHibtdrFITYeb8WX+ctOkHQ6eWui6\nzVjLQfD4rh29bdIO/Ye+asTwazuAnJswRdohaIdc6+uL2g6qbI1TnbtlHGy5\nri8uqNVxEIgAhtg3WYj5B3QcgKEkzcsAdOfS2UcUDHQdEp5eULotqehw89z3\n4Mepug63pGsSjUyVHMr3zZfSj9V1uKKdKvkoQtmhOGPi25p6XQeQ8p91KhB9\nlroOIGH7UlWH+qw9JZNn6EDs54bGF4OOA9AVtlzhag6KG4oyJupqO4CCYaGr\nmgM4XiO0HK5WvFQz9FBzuAzi7tR0cNv2+e8VCzUHJ5AF0poO6PEPAFdvzZk=\n\n " + ] + } + ] + }, + AspectRatio -> Automatic, + BaselinePosition -> Scaled[0.1], + ImagePadding -> 0.5, + ImageSize -> {14.0, 14.778}, + PlotRange -> {{0.76, 17.27}, {0.73, 17.37}} + ] + ]) + } + ], + Cell["Documentation", "Section"], + Cell["Usage", "Subsection"], + Cell[ + StyleData[ + "UsageInputs", + StyleDefinitions -> StyleData["Input"] + ], + CellMargins -> {{66, 10}, {0, 8}}, + StyleKeyMapping -> {"Tab" -> "UsageDescription"}, + Evaluatable -> False, + CellEventActions -> { + "ReturnKeyDown" :> + With[ { RSNB`nb$ = Notebooks[EvaluationCell[]] }, + SelectionMove[EvaluationCell[], After, Cell]; + NotebookWrite[RSNB`nb$, Cell["", "UsageDescription"], All]; + SelectionMove[RSNB`nb$, Before, CellContents] + ], + {"KeyDown", "\t"} :> + Replace[ + SelectionMove[SelectedNotebook[], After, Cell]; + NotebookFind[ + SelectedNotebook[], + "TabNext", + Next, + CellTags, + AutoScroll -> True, + WrapAround -> True + ], + Blank[NotebookSelection] :> + SelectionMove[ + SelectedNotebook[], + All, + CellContents, + AutoScroll -> True + ] + ] + }, + ShowAutoStyles -> False, + ShowCodeAssist -> False, + CodeAssistOptions -> {"DynamicHighlighting" -> False}, + LineSpacing -> {1, 3}, + TabSpacings -> {2.5}, + CounterIncrements -> "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 15, + FontWeight -> "Plain" + ], + Cell[ + StyleData[ + "UsageDescription", + StyleDefinitions -> StyleData["Text"] + ], + CellMargins -> {{86, 10}, {7, 0}}, + StyleKeyMapping -> {"Backspace" -> "UsageInputs"}, + CellGroupingRules -> "OutputGrouping", + CellEventActions -> { + "ReturnKeyDown" :> + With[ { RSNB`nb$ = Notebooks[EvaluationCell[]] }, + SelectionMove[EvaluationCell[], After, Cell]; + + NotebookWrite[ + RSNB`nb$, + Cell[ + BoxData[""], + "UsageInputs", + FontFamily -> "Source Sans Pro" + ], + All + ]; + + SelectionMove[RSNB`nb$, Before, CellContents] + ], + {"KeyDown", "\t"} :> + Replace[ + SelectionMove[SelectedNotebook[], After, Cell]; + NotebookFind[ + SelectedNotebook[], + "TabNext", + Next, + CellTags, + AutoScroll -> True, + WrapAround -> True + ], + Blank[NotebookSelection] :> + SelectionMove[ + SelectedNotebook[], + All, + CellContents, + AutoScroll -> True + ] + ] + }, + ShowAutoSpellCheck -> False + ], + Cell["Details & Options", "Subsection"], + Cell[ + StyleData["Notes", StyleDefinitions -> StyleData["Item"]], + CellDingbat -> + StyleBox[ + "\[FilledVerySmallSquare]", + FontColor -> GrayLevel[0.6] + ], + CellMargins -> {{66, 24}, {9, 7}}, + ReturnCreatesNewCell -> False, + StyleKeyMapping -> { }, + DefaultNewCellStyle -> "Notes", + ShowAutoSpellCheck -> False, + GridBoxOptions -> {BaseStyle -> "TableNotes"} + ], + Cell[ + StyleData[ + "TableNotes", + StyleDefinitions -> StyleData["Notes"] + ], + CellDingbat -> None, + CellFrameColor -> RGBColor[0.749, 0.694, 0.553], + StyleMenuListing -> None, + ButtonBoxOptions -> {Appearance -> {Automatic, None}}, + GridBoxOptions -> { + FrameStyle -> GrayLevel[0.906], + GridBoxAlignment -> { + "Columns" -> {{Left}}, + "ColumnsIndexed" -> { }, + "Rows" -> {{Baseline}}, + "RowsIndexed" -> { } + }, + GridBoxDividers -> {"Columns" -> {{None}}, "Rows" -> {{True}}}, + GridDefaultElement -> Cell["\[Placeholder]", "TableText"] + } + ], + Cell[ + StyleData["TableText"], + DefaultInlineFormatType -> "DefaultInputInlineFormatType", + AutoQuoteCharacters -> { }, + PasteAutoQuoteCharacters -> { }, + StyleMenuListing -> None + ], + Cell["Examples", "Subsection"], + Cell[ + StyleData["ExampleDelimiter"], + Selectable -> False, + ShowCellBracket -> Automatic, + CellMargins -> {{66, 14}, {5, 10}}, + Evaluatable -> True, + CellGroupingRules -> {"SectionGrouping", 58}, + CellEvaluationFunction -> (($Line = 0;) &), + ShowCellLabel -> False, + CellLabelAutoDelete -> True, + TabFilling -> "\[LongDash]\[NegativeThickSpace]", + TabSpacings -> {100}, + StyleMenuListing -> None, + FontFamily -> "Verdana", + FontWeight -> Bold, + FontSlant -> "Plain", + FontColor -> GrayLevel[0.906] + ], + Cell[ + StyleData[ + "ExampleText", + StyleDefinitions -> StyleData["Text"] + ] + ], + Cell[ + StyleData[ + "PageBreak", + StyleDefinitions -> StyleData["ExampleDelimiter"] + ], + Selectable -> False, + CellFrame -> {{0, 0}, {1, 0}}, + CellMargins -> {{66, 14}, {15, -5}}, + CellElementSpacings -> {"CellMinHeight" -> 1}, + Evaluatable -> True, + CellEvaluationFunction -> (($Line = 0;) &), + CellFrameColor -> GrayLevel[77/85] + ], + Cell[ + StyleData["Subsection"], + Evaluatable -> True, + CellEvaluationFunction -> (($Line = 0;) &), + ShowCellLabel -> False + ], + Cell[ + StyleData["Subsubsection"], + Evaluatable -> True, + CellEvaluationFunction -> (($Line = 0;) &), + ShowCellLabel -> False + ], + Cell[ + StyleData["ExampleImage"], + PageWidth :> 650, + CellMargins -> {{66, 66}, {16, 5}}, + Evaluatable -> False, + ShowCellLabel -> False, + MenuSortingValue -> 10000, + RasterBoxOptions -> {ImageEditMode -> False} + ], + Cell["Links", "Section"], + Cell[ + StyleData["Link"], + FontFamily -> "Source Sans Pro", + FontColor -> + Dynamic[ + If[ CurrentValue["MouseOver"], + RGBColor[0.855, 0.396, 0.145], + RGBColor[0.02, 0.286, 0.651] + ] + ] + ], + Cell[ + StyleData[ + "StringTypeLink", + StyleDefinitions -> StyleData["Link"] + ], + FontColor -> + Dynamic[ + If[ CurrentValue["MouseOver"], + RGBColor[0.969, 0.467, 0.0], + GrayLevel[0.467] + ] + ] + ], + Cell[ + StyleData["CharactersRefLink"], + ShowSpecialCharacters -> False + ], + Cell["Annotation", "Section"], + Cell[ + StyleData["Excluded"], + CellBracketOptions -> {"Color" -> RGBColor[0.9, 0.4, 0.4], "Thickness" -> 2}, + GeneratedCellStyles -> { + "Graphics" -> {"Graphics", "Excluded"}, + "Message" -> {"Message", "MSG", "Excluded"}, + "Output" -> {"Output", "Excluded"}, + "Print" -> {"Print", "Excluded"}, + "PrintTemporary" -> {"PrintTemporary", "Excluded"} + }, + CellFrameMargins -> 4, + CellFrameLabels -> { + { + None, + Cell[ + BoxData[ + TemplateBox[ + { + StyleBox[ + "\"excluded\"", + "ExcludedCellLabel", + StripOnInput -> False + ], + "\"Excluded cells will not appear anywhere in the published resource except for the definition notebook\"" + }, + "PrettyTooltipTemplate" + ] + ], + "ExcludedCellLabel" + ] + }, + {None, None} + }, + StyleMenuListing -> None, + Background -> RGBColor[1, 0.95, 0.95] + ], + Cell[ + StyleData[ + "ExcludedCellLabel", + StyleDefinitions -> StyleData["Text"] + ], + ShowStringCharacters -> False, + FontFamily -> "Source Sans Pro", + FontSize -> 9, + FontWeight -> Plain, + FontSlant -> Italic, + FontColor -> RGBColor[0.9, 0.4, 0.4, 0.5], + Background -> None + ], + Cell[ + StyleData["Comment", StyleDefinitions -> StyleData["Text"]], + CellFrame -> {{3, 0}, {0, 0}}, + CellMargins -> {{66, 0}, {1, 0}}, + CellElementSpacings -> {"ClosedCellHeight" -> 0}, + GeneratedCellStyles -> { + "Graphics" -> {"Graphics", "Comment"}, + "Message" -> {"Message", "MSG", "Comment"}, + "Output" -> {"Output", "Comment"}, + "Print" -> {"Print", "Comment"}, + "PrintTemporary" -> {"PrintTemporary", "Comment"} + }, + CellFrameColor -> RGBColor[0.88072, 0.61104, 0.14205], + CellFrameLabelMargins -> {{0, 10}, {0, 0}}, + FontColor -> GrayLevel[0.25], + Background -> RGBColor[0.982, 0.942, 0.871] + ], + Cell[ + StyleData[ + "AuthorComment", + StyleDefinitions -> StyleData["Comment"] + ], + GeneratedCellStyles -> { + "Graphics" -> {"Graphics", "AuthorComment"}, + "Message" -> {"Message", "MSG", "AuthorComment"}, + "Output" -> {"Output", "AuthorComment"}, + "Print" -> {"Print", "AuthorComment"}, + "PrintTemporary" -> {"PrintTemporary", "AuthorComment"} + }, + CellFrameColor -> RGBColor[0.36842, 0.50678, 0.7098], + Background -> RGBColor[0.905, 0.926, 0.956] + ], + Cell[ + StyleData[ + "ReviewerComment", + StyleDefinitions -> StyleData["Comment"] + ], + GeneratedCellStyles -> { + "Graphics" -> {"Graphics", "ReviewerComment"}, + "Message" -> {"Message", "MSG", "ReviewerComment"}, + "Output" -> {"Output", "ReviewerComment"}, + "Print" -> {"Print", "ReviewerComment"}, + "PrintTemporary" -> {"PrintTemporary", "ReviewerComment"} + }, + CellFrameColor -> RGBColor[0.56018, 0.69157, 0.19488], + Background -> RGBColor[0.934, 0.954, 0.879] + ], + Cell[ + StyleData[ + "CommentLabel", + StyleDefinitions -> StyleData["Text"] + ], + ShowStringCharacters -> False, + FontSlant -> "Italic", + PrivateFontOptions -> {"OperatorSubstitution" -> False}, + FontColor -> GrayLevel[0.5] + ], + Cell["Special Input", "Section"], + Cell[ + StyleData["FormObjectCell"], + CellMargins -> {{66, 66}, {16, 5}} + ], + Cell[ + StyleData[ + "LocalFileInput", + StyleDefinitions -> StyleData["Input"] + ], + CellFrameLabels -> { + { + None, + Cell[ + BoxData[ + ButtonBox[ + "\"Choose\"", + FrameMargins -> {{5, 5}, {0, 0}}, + BaseStyle -> {"Panel", FontSize -> 12}, + Evaluator -> Automatic, + Method -> "Queued", + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 1053094956087266899; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + If[ $VersionNumber >= 13.0, + DefinitionNotebookClient`LocalFileInputDialog[ + "Data", + ParentCell[EvaluationCell[]], + "Type" -> "FileOpen" + ], + MessageDialog[ + "This feature requires Wolfram Language version 13 or later." + ] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[1053094956087266899] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + Appearance :> + FEPrivate`FrontEndResource[ + "FEExpressions", + "GrayButtonNinePatchAppearance" + ] + ] + ] + ] + }, + {None, None} + } + ], + Cell[ + StyleData[ + "LocalDirectoryInput", + StyleDefinitions -> StyleData["Input"] + ], + CellFrameLabels -> { + { + None, + Cell[ + BoxData[ + ButtonBox[ + "\"Choose\"", + FrameMargins -> {{5, 5}, {0, 0}}, + BaseStyle -> {"Panel", FontSize -> 12}, + Evaluator -> Automatic, + Method -> "Queued", + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 4898876371082581810; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + If[ $VersionNumber >= 13.0, + DefinitionNotebookClient`LocalFileInputDialog[ + "Data", + ParentCell[EvaluationCell[]], + "Type" -> "Directory" + ], + MessageDialog[ + "This feature requires Wolfram Language version 13 or later." + ] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[4898876371082581810] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + Appearance :> + FEPrivate`FrontEndResource[ + "FEExpressions", + "GrayButtonNinePatchAppearance" + ] + ] + ] + ] + }, + {None, None} + } + ], + Cell["Misc", "Section"], + Cell[StyleData["Item"], DefaultNewCellStyle -> "Item"], + Cell[ + StyleData[ + "RelatedSymbol", + StyleDefinitions -> StyleData["Item"] + ], + DefaultNewCellStyle -> {"RelatedSymbol", FontFamily -> "Source Sans Pro"}, + DefaultFormatType -> DefaultInputFormatType, + FormatType -> InputForm + ], + Cell[ + StyleData["ButtonText"], + FontFamily -> "Sans Serif", + FontSize -> 11, + FontWeight -> Bold, + FontColor -> RGBColor[0.459, 0.459, 0.459] + ], + Cell[ + StyleData["InlineFormula"], + HyphenationOptions -> {"HyphenationCharacter" -> "\[Continuation]"}, + LanguageCategory -> "Formula", + AutoSpacing -> True, + ScriptLevel -> 1, + SingleLetterItalics -> False, + SpanMaxSize -> 1, + StyleMenuListing -> None, + FontFamily -> "Source Sans Pro", + FontSize -> 1.0 * Inherited, + ButtonBoxOptions -> {Appearance -> {Automatic, None}}, + FractionBoxOptions -> {BaseStyle -> {SpanMaxSize -> Automatic}}, + GridBoxOptions -> { + GridBoxItemSize -> { + "Columns" -> {{Automatic}}, + "ColumnsIndexed" -> { }, + "Rows" -> {{1.0}}, + "RowsIndexed" -> { } + } + } + ], + Cell[ + StyleData["Input"], + CellProlog :> + Quiet[ + Block[{$ContextPath}, Once[ReleaseHold[CurrentValue[#1, {TaggingRules, "CompatibilityTest"}]], "KernelSession"]; If[$VersionNumber >= 12.2, Needs["DefinitionNotebookClient`"], Needs["ResourceSystemClient`DefinitionNotebook`"]]; DefinitionNotebookClient`LoadDefinitionNotebook["Data", #1]; ] &[ + InputNotebook[] + ] + ] + ], + Cell[ + StyleData["Code"], + CellProlog :> + Quiet[ + Block[{$ContextPath}, Once[ReleaseHold[CurrentValue[#1, {TaggingRules, "CompatibilityTest"}]], "KernelSession"]; If[$VersionNumber >= 12.2, Needs["DefinitionNotebookClient`"], Needs["ResourceSystemClient`DefinitionNotebook`"]]; DefinitionNotebookClient`LoadDefinitionNotebook["Data", #1]; ] &[ + InputNotebook[] + ] + ] + ], + Cell[ + StyleData["DockedCell"], + CellFrameColor -> GrayLevel[0.75], + Background -> GrayLevel[0.9] + ] + }, + Visible -> False, + StyleDefinitions -> "PrivateStylesheetFormatting.nb" + ] +] \ No newline at end of file diff --git a/Developer/VectorDatabases/DefinitionNotebooks/WolframAlphaQueries.nb b/Developer/VectorDatabases/DefinitionNotebooks/WolframAlphaQueries.nb new file mode 100644 index 00000000..3dd66c91 --- /dev/null +++ b/Developer/VectorDatabases/DefinitionNotebooks/WolframAlphaQueries.nb @@ -0,0 +1,9663 @@ +(* Content-type: application/vnd.wolfram.mathematica *) + +(*** Wolfram Notebook File ***) +(* http://www.wolfram.com/nb *) + +(* Created By: SaveReadableNotebook *) +(* https://resources.wolframcloud.com/FunctionRepository/resources/SaveReadableNotebook *) + +Notebook[ + { + Cell[ + CellGroupData[ + { + Cell[ + "Code Assistance Wolfram Alpha Query Vector Database", + "Title", + CellTags -> {"DefaultContent", "Name", "TemplateCell"}, + CellID -> 806838874 + ], + Cell[ + "VectorDatabaseObject based on sample Wolfram Alpha queries used for retrieval-augmented-generation in code assistance chat", + "Text", + CellTags -> {"DefaultContent", "Description", "TemplateCell"}, + CellID -> 163956104 + ], + Cell[ + TextData[ + { + "Details", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "Details", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Give a detailed description of the data, including information about the size, structure, and history of the content elements.\n\nThis section may include multiple cells, bullet lists, tables, hyperlinks and additional styles/structures as needed.\n\nAdd any other information that may be relevant, such as when the data was first created or how and why it is used within a given field. Include all relevant background or contextual information related to the data, its development, and its usage.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoDetails"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Details"}, + DefaultNewCellStyle -> "Notes", + CellTags -> {"Details", "TemplateCellGroup"}, + CellID -> 161845329 + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Data Definitions", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "ContentElements", + Cell[ + BoxData[ + FrameBox[ + Cell[ + TextData[ + { + "Define the content of the resource by assigning values to ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "ResourceData", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/ResourceData", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ". The ", + Cell[ + BoxData[ + StyleBox[ + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + FontSize -> (11 * Inherited) / 13, + ShowStringCharacters -> False + ], + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4, + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False} + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + Selectable -> False, + SelectWithContents -> True + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " icon inside ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "ResourceData", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/ResourceData", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " below represents the ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "ResourceObject", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/ResourceObject", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " defined within this notebook.\n\nEvaluating the ", + Cell[ + BoxData[ + StyleBox[ + RowBox[ + { + RowBox[ + { + "ResourceData", + "[", + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + FontSize -> (11 * Inherited) / 13, + ShowStringCharacters -> False + ], + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4, + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False} + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + Selectable -> False, + SelectWithContents -> True + ], + "]" + } + ], + "=", + "xxxx" + } + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " cell below defines the default content element of this resource, which will be returned by ", + Cell[ + BoxData[ + StyleBox[ + RowBox[ + { + TagBox[ + ButtonBox[ + StyleBox[ + "ResourceData", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/ResourceData", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + "[", + StyleBox["obj", "TI"], + "]" + } + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ".\n\nEvaluating the subsequent cells defines additional content elements with the specified element names. The element name is used to access the associated content via ", + Cell[ + BoxData[ + StyleBox[ + RowBox[ + { + TagBox[ + ButtonBox[ + StyleBox[ + "ResourceData", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/ResourceData", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + "[", + RowBox[ + {StyleBox["obj", "TI"], ",", StyleBox["element", "TI"]} + ], + "]" + } + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ".\n\nThe default content element is assigned a name either based on the ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "Head", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/Head", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " of the data or set to ", + Cell[ + BoxData[ + StyleBox[ + "\"Content\"", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ".\n\nDefine as many elements as needed using different element names. You can insert the icon using the \"Insert ResourceObject\" button in the \"Tools\" above.\n\nElements set to ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "CloudObject", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/CloudObject", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ", ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "File", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/File", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ", or ", + Cell[ + BoxData[ + StyleBox[ + TagBox[ + ButtonBox[ + StyleBox[ + "LocalObject", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/LocalObject", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " values will be interpreted as the content of those locations.\n\nEach content element must have a string name, preferably camel case. (Typical names describe the content element, and include ", + Cell[ + BoxData[ + StyleBox[ + "\"Dataset\"", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ", ", + Cell[ + BoxData[ + StyleBox[ + "\"Text\"", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " and ", + Cell[ + BoxData[ + StyleBox[ + "\"TimeSeries\"", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + ").\n\nElements defined as functions are automatically applied to the other elements of the resource. For example, ", + Cell[ + BoxData[ + StyleBox[ + RowBox[ + { + RowBox[ + { + "ResourceData", + "[", + RowBox[ + { + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + FontSize -> (11 * Inherited) / 13, + ShowStringCharacters -> False + ], + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4, + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False} + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + Selectable -> False, + SelectWithContents -> True + ], + ",", + "\"Vertices\"" + } + ], + "]" + } + ], + "=", + RowBox[ + { + "(", + RowBox[{RowBox[{"VertexList", "[", "#Graph", "]"}], "&"}], + ")" + } + ] + } + ], + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " will define an element named ", + Cell[ + BoxData[ + StyleBox[ + "\"Vertices\"", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " which is derived from the ", + Cell[ + BoxData[ + StyleBox[ + "\"Graph\"", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ] + ] + ], + " element when requested by the user." + } + ], + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoContentElements"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Section", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "ContentElements"}, + CellTags -> { + "ContentElements", + "Data Definitions", + "TemplateCellGroup" + }, + CellID -> 41403987 + ], + Cell[ + CellGroupData[ + { + Cell[ + "Primary Content", + "Subsection", + Editable -> False, + Deletable -> False, + CellTags -> "PrimaryContent", + CellID -> 739468720 + ], + Cell[ + BoxData[ + RowBox[ + { + RowBox[ + { + RowBox[ + { + "ResourceData", + "[", + RowBox[ + { + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + ImageSizeCache -> {11.122, {2.90039, 9.09961}}, + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + ShowStringCharacters -> False, + FontSize -> (11 * Inherited) / 13 + ], + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False}, + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4 + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + SelectWithContents -> True, + Selectable -> False + ], + ",", + "\"VectorDatabase\"" + } + ], + "]" + } + ], + "=", + RowBox[ + { + RowBox[ + { + "WithCleanup", + "[", + "\[IndentingNewLine]", + RowBox[ + { + RowBox[ + { + "SetDirectory", + "[", + RowBox[{"CreateDirectory", "[", "]"}], + "]" + } + ], + ",", + "\[IndentingNewLine]", + RowBox[ + { + "VectorDatabaseObject", + "[", + RowBox[ + { + RowBox[{"File", "[", "#DatabasePath", "]"}], + ",", + RowBox[{"OverwriteTarget", "->", "True"}] + } + ], + "]" + } + ], + ",", + "\[IndentingNewLine]", + RowBox[{"ResetDirectory", "[", "]"}] + } + ], + "\[IndentingNewLine]", + "]" + } + ], + "&" + } + ] + } + ], + ";" + } + ] + ], + "Input", + CellTags -> "DefaultContent", + CellLabel -> "In[11]:=", + CellID -> 751296993 + ] + }, + Open + ] + ], + Cell[ + CellGroupData[ + { + Cell[ + "Additional Data Elements (optional)", + "Subsection", + Editable -> False, + Deletable -> False, + CellTags -> "AdditionalDataElements", + CellLabel -> "In[13]:=", + CellID -> 651134066 + ], + Cell[ + BoxData[ + { + RowBox[ + {RowBox[{"name", "=", "\"WolframAlphaQueries\""}], ";"} + ], + "\[IndentingNewLine]", + RowBox[ + { + RowBox[ + { + "dir", + "=", + RowBox[ + { + "FileNameJoin", + "[", + RowBox[ + { + "{", + RowBox[ + { + RowBox[ + { + "ParentDirectory", + "[", + RowBox[{RowBox[{"NotebookDirectory", "[", "]"}], ",", "3"}], + "]" + } + ], + ",", + "\"Assets/VectorDatabases\"", + ",", + "name" + } + ], + "}" + } + ], + "]" + } + ] + } + ], + ";" + } + ], + "\[IndentingNewLine]", + RowBox[ + { + RowBox[ + { + "zip", + "=", + RowBox[ + { + "CreateArchive", + "[", + RowBox[ + { + RowBox[ + { + "FileNames", + "[", + RowBox[{"All", ",", "dir", ",", "Infinity"}], + "]" + } + ], + ",", + RowBox[{"dir", "<>", "\".zip\""}], + ",", + RowBox[{"OverwriteTarget", "->", "True"}] + } + ], + "]" + } + ] + } + ], + ";" + } + ], + "\[IndentingNewLine]", + RowBox[ + { + RowBox[ + { + "obj", + "=", + RowBox[ + { + "CopyFile", + "[", + RowBox[ + { + "zip", + ",", + RowBox[ + { + "CloudObject", + "[", + RowBox[ + { + RowBox[ + {"\"VectorDatabases/\"", "<>", "name", "<>", "\".zip\""} + ], + ",", + RowBox[{"Permissions", "->", "\"Public\""}] + } + ], + "]" + } + ], + ",", + RowBox[{"OverwriteTarget", "->", "True"}] + } + ], + "]" + } + ] + } + ], + ";" + } + ], + "\[IndentingNewLine]", + RowBox[{RowBox[{"DeleteFile", "[", "zip", "]"}], ";"}] + } + ], + "Input", + CellLabel -> "In[1]:=", + CellID -> 96470356 + ], + Cell[ + BoxData[ + RowBox[ + { + RowBox[ + { + RowBox[ + { + "ResourceData", + "[", + RowBox[ + { + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + ImageSizeCache -> {11.122, {2.90039, 9.09961}}, + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + ShowStringCharacters -> False, + FontSize -> (11 * Inherited) / 13 + ], + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False}, + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4 + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + SelectWithContents -> True, + Selectable -> False + ], + ",", + "\"DatabaseDirectory\"" + } + ], + "]" + } + ], + "=", + "obj" + } + ], + ";" + } + ] + ], + "Input", + CellTags -> "DefaultContent", + CellLabel -> "In[6]:=", + CellID -> 874765044 + ], + Cell[ + BoxData[ + RowBox[ + { + RowBox[ + { + RowBox[ + { + "ResourceData", + "[", + RowBox[ + { + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + ImageSizeCache -> {11.122, {2.90039, 9.09961}}, + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + ShowStringCharacters -> False, + FontSize -> (11 * Inherited) / 13 + ], + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False}, + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4 + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + SelectWithContents -> True, + Selectable -> False + ], + ",", + "\"DatabasePath\"" + } + ], + "]" + } + ], + "=", + RowBox[ + { + "With", + "[", + RowBox[ + { + RowBox[ + { + "{", + RowBox[{"file", "=", RowBox[{"name", "<>", "\".wxf\""}]}], + "}" + } + ], + ",", + RowBox[ + { + RowBox[ + { + "FileNameJoin", + "[", + RowBox[ + {"{", RowBox[{"#DatabaseDirectory", ",", "file"}], "}"} + ], + "]" + } + ], + "&" + } + ] + } + ], + "]" + } + ] + } + ], + ";" + } + ] + ], + "Input", + CellTags -> "DefaultContent", + CellLabel -> "In[7]:=", + CellID -> 874765045 + ] + }, + Open + ] + ] + }, + Open + ] + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Examples", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "ExampleNotebook", + Cell[ + BoxData[ + FrameBox[ + Cell[ + TextData[ + { + "Demonstrate the data's usage, starting with the most basic use case and describing each example in a preceding text cell.\n\nWithin a group, individual examples can be delimited by inserting page breaks between them (using Tools \[FilledRightTriangle] Insert Delimiter).\n\nExamples should be grouped into Subsection and Subsubsection cells similarly to existing documentation pages. Here are some typical Subsection names and the types of examples they normally contain:\n\n ", + Cell[ + BoxData[ + StyleBox[ + TemplateBox[ + { + StyleBox[ + "\"\[FilledSmallSquare] \"", + FontColor -> RGBColor[0.8, 0.043, 0.008], + StripOnInput -> False + ], + StyleBox[ + "\"Basic Examples: \"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontSize -> 14, + StripOnInput -> False + ] + }, + "RowDefault" + ], + ShowStringCharacters -> False + ] + ] + ], + "most basic usage\n ", + Cell[ + BoxData[ + StyleBox[ + TemplateBox[ + { + StyleBox[ + "\"\[FilledSmallSquare] \"", + FontColor -> RGBColor[0.8, 0.043, 0.008], + StripOnInput -> False + ], + StyleBox[ + "\"Scope: \"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontSize -> 14, + StripOnInput -> False + ] + }, + "RowDefault" + ], + ShowStringCharacters -> False + ] + ] + ], + "show the breadth of the data\n ", + Cell[ + BoxData[ + StyleBox[ + TemplateBox[ + { + StyleBox[ + "\"\[FilledSmallSquare] \"", + FontColor -> RGBColor[0.8, 0.043, 0.008], + StripOnInput -> False + ], + StyleBox[ + "\"Applications: \"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontSize -> 14, + StripOnInput -> False + ] + }, + "RowDefault" + ], + ShowStringCharacters -> False + ] + ] + ], + "standard industry or academic applications\n ", + Cell[ + BoxData[ + StyleBox[ + TemplateBox[ + { + StyleBox[ + "\"\[FilledSmallSquare] \"", + FontColor -> RGBColor[0.8, 0.043, 0.008], + StripOnInput -> False + ], + StyleBox[ + "\"Properties and Relations: \"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontSize -> 14, + StripOnInput -> False + ] + }, + "RowDefault" + ], + ShowStringCharacters -> False + ] + ] + ], + "how the data relates to other data\n ", + Cell[ + BoxData[ + StyleBox[ + TemplateBox[ + { + StyleBox[ + "\"\[FilledSmallSquare] \"", + FontColor -> RGBColor[0.8, 0.043, 0.008], + StripOnInput -> False + ], + StyleBox[ + "\"Possible Issues: \"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontSize -> 14, + StripOnInput -> False + ] + }, + "RowDefault" + ], + ShowStringCharacters -> False + ] + ] + ], + "limitations or unexpected behavior a user might experience\n ", + Cell[ + BoxData[ + StyleBox[ + TemplateBox[ + { + StyleBox[ + "\"\[FilledSmallSquare] \"", + FontColor -> RGBColor[0.8, 0.043, 0.008], + StripOnInput -> False + ], + StyleBox[ + "\"Neat Examples: \"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontSize -> 14, + StripOnInput -> False + ] + }, + "RowDefault" + ], + ShowStringCharacters -> False + ] + ] + ], + "particularly interesting, unconventional, or otherwise unique usage" + } + ], + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoExampleNotebook"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Section", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "ExampleNotebook"}, + CellTags -> {"ExampleNotebook", "Examples", "TemplateCellGroup"}, + CellID -> 661218443 + ], + Cell[ + CellGroupData[ + { + Cell[ + "Basic Examples", + "Subsection", + CellLabel -> "In[8]:=", + CellID -> 462042388 + ], + Cell[ + TextData[ + { + "Get the ", + Cell[ + BoxData[ + TagBox[ + ButtonBox[ + StyleBox[ + "VectorDatabaseObject", + "SymbolsRefLink", + ShowStringCharacters -> True, + FontFamily -> "Source Sans Pro" + ], + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue["MouseOver"], + {"Link", FontColor -> RGBColor[0.8549, 0.39608, 0.1451]}, + {"Link"} + ] + ], + ButtonData -> "paclet:ref/VectorDatabaseObject", + ContentPadding -> False + ], + MouseAppearanceTag["LinkHand"] + ] + ], + "InlineFormula", + FontFamily -> "Source Sans Pro" + ], + ":" + } + ], + "Text", + CellTags -> "DefaultContent", + CellID -> 395385424 + ], + Cell[ + CellGroupData[ + { + Cell[ + BoxData[ + RowBox[ + { + "db", + "=", + RowBox[ + { + "ResourceData", + "[", + InterpretationBox[ + TagBox[ + FrameBox[ + StyleBox[ + GridBox[ + { + { + DynamicBox[ + If[ TrueQ[ + StringQ[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceType"} + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + RasterBox[ + CompressedData[ + "\n1:eJztmEFOg1AQhom6cIk3qBsTd126xKW7psZ921iNm9q0JsbduwFH4AgcgSNw\ngqZH4Aj4MP/U3wmUgkhp7EtGYZh58zkzzGu9nLwOn04cx1me2x/D8fvtYjH+\nuHftzcNs+fI8mz7ezd6mz9PFzeTUKq+tXFk5c7q/VhdOYiXtgCSKK9P195UX\nMHgZh9KlRfZtLubgPO6TSVj4+si1fR1Cf+Xd72v9RR2tv5tJB7n8TLrEZX17\ntE+vCa68+xLftRXD8e11RFyR4s1s1y1wRXSeBogr1wGuDV0nzLorV9U6gsvg\nPAuJw4cIZwgb0xLXj/4G55z2mata7vw+1OXCLMjqE8tMoLqGkE3dYB/Dp3SG\nVOkv+2xELJvPSVSrBOJCEuJk25QY5w1wBWrfAVg5Xkj2oeIfwYf/rqCMa5c6\n0p4RxfMRz4NuAEmhG8AmUb7xljhVuaRPYoo9oueG6mdIPyJm8S/sszp9T3lJ\nSDzE5tqF0HnK9iuPJTEqzVXq5yCHQ/TyPga69+jdSXbNVxmXqqHMhh5ixGRn\nVA1j2PSK9tnGVVZH6nnpc5d6mOen5trYwEfeg8Ler8glZ4nMKq5dhHi6vwZ4\nFiifEHt5v+XK8TWI6VO87PcawjoftqZ0Y6d63ytbn3JnVt+zoA9JoZPZkdlW\nPh9rcPFslfzkzfs15a2tzzlpTr681feM43y1xRUjrku6ELyRyp0L28Kzpymu\ngv1knm3mVc19Gv/+qOdXzT3+zffaJtaRq9o6kP5y5RzZM5OXw9XJ/0d3bX0C\ndbpsag==\n " + ], + {{0, 0}, {38.0, 41.0}}, + {0, 255}, + ImageResolution -> {72, 72}, + ColorFunction -> RGBColor + ], + { + ImageSize -> {Automatic, 12}, + PlotRange -> {{0, 38.0}, {0, 41.0}} + } + ], + "\"the ResourceObject defined by this notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "the ResourceObject defined by this notebook", + "Tooltip" + ] + ] + ], + TagBox[ + TooltipBox[ + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzdlk1ugzAQhaN20yVHoJtK3WXZJV1W8gKl6p5ETaNu0iipVHXnG3AEH4Ej\n+Ag+AkfgCO6bYUjzC4SgKipWnMF4PmYeY/Dt5GP0djUYDFY36Ebjr8flcvz9\nHODkZb56n82nr0/zz+lsunyYXGPwHr87/Mil30MFqlD+7FYIy6vhmfFEyovl\nz82tYpQx/m9Wn3q1YSmtdBtWc44qRAUWKuzOUk4lKmArUxYtYzvAqDuZZama\nkV2C/4iqEZbmNWKPsY7pJawcfSbReZx1Y6XwruIaolVxZSo9OUeNyFKOjeLJ\nxUoxqtuyoIzmiMjXwDPm7JApLIuR8kqGWVEjy/HdYzwxW2lT1Vc5gisxR+x2\nWbt6YaZDC6Su3BbLlXX2O6eeJW9HA6XL3MjO0Iy8MzNcITvY8jmqPVdTwS1a\nM4kRyajf1KqOJRnEVAWSIfmXWVKFxLsZ1rAcK0yR0TOI2Dvm6ifNC7nq9ll7\n2humU1xJpRCPV+olHBfZppFFyjrx81xp0JmfR8G8Qu5l1KKN9qyZkcqwzCCm\nFS3NtlZNLF6PvO7AWvCchdRt2mE9WlolnJUmf/SUMa2wLu8cUsYww/AT0dwX\nHVg5fEOh+vXKDDGan5rjxryQ54S1c1p/Hw/r3ZEV7FfBIdZff2vbsi51b3LJ\n+5we96u97aP7O34ARi0taQ==\n " + ], + {{0, 41.0}, {38.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel, + ImageResolution -> {72, 72} + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {38.0, 41.0}, + PlotRange -> {{0, 38.0}, {0, 41.0}}, + ImageSize -> {Automatic, 12} + ], + "\"only defined in a definition notebook\"", + TooltipStyle -> "TextStyling" + ], + Function[ + Annotation[ + #1, + "only defined in a definition notebook", + "Tooltip" + ] + ] + ] + ], + ImageSizeCache -> {11.122, {2.90039, 9.09961}}, + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + ShowStringCharacters -> False, + FontSize -> (11 * Inherited) / 13 + ], + Background -> GrayLevel[0.5, 0.15], + BaseStyle -> {"Text", LineSpacing -> {0, 0}, LineBreakWithin -> False}, + FrameMargins -> {{3, 3}, {3, 0}}, + FrameStyle -> + Directive[GrayLevel[0.5, 0.35], AbsoluteThickness[0.5]], + RoundingRadius -> 4 + ], + "ResourceObjectNotebook" + ], + ResourceObject[EvaluationNotebook[]], + SelectWithContents -> True, + Selectable -> False + ], + "]" + } + ] + } + ] + ], + "Input", + CellTags -> "DefaultContent", + CellLabel -> "In[1]:=", + CellID -> 464452425 + ], + Cell[ + BoxData[ + InterpretationBox[ + RowBox[ + { + TagBox["VectorDatabaseObject", "SummaryHead"], + "[", + DynamicModuleBox[ + {Typeset`open$$ = False, Typeset`embedState$$ = "Ready"}, + TemplateBox[ + { + PaneSelectorBox[ + { + False -> + GridBox[ + { + { + PaneBox[ + ButtonBox[ + DynamicBox[ + FEPrivate`FrontEndResource["FEBitmaps", "SummaryBoxOpener"] + ], + ButtonFunction :> (Typeset`open$$ = True), + Appearance -> None, + BaseStyle -> { }, + Evaluator -> Automatic, + Method -> "Preemptive" + ], + Alignment -> {Center, Center}, + ImageSize -> + Dynamic[ + { + Automatic, + Times[ + 3.5, + Times[ + CurrentValue["FontCapHeight"], + AbsoluteCurrentValue[Magnification]^(-1) + ] + ] + } + ] + ], + GridBox[ + { + { + RowBox[ + { + TagBox["\"ID: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["\"WolframAlphaQueries\"", "SummaryItem"] + } + ] + }, + { + RowBox[ + { + TagBox["\"Elements: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["59817", "SummaryItem"] + } + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Automatic}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{2}}, "Rows" -> {{Automatic}}}, + BaseStyle -> { + ShowStringCharacters -> False, + NumberMarks -> False, + PrintPrecision -> 3, + ShowSyntaxStyles -> False + } + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Top}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + BaselinePosition -> {1, 1} + ], + True -> + GridBox[ + { + { + PaneBox[ + ButtonBox[ + DynamicBox[ + FEPrivate`FrontEndResource["FEBitmaps", "SummaryBoxCloser"] + ], + ButtonFunction :> (Typeset`open$$ = False), + Appearance -> None, + BaseStyle -> { }, + Evaluator -> Automatic, + Method -> "Preemptive" + ], + Alignment -> {Center, Center}, + ImageSize -> + Dynamic[ + { + Automatic, + Times[ + 3.5, + Times[ + CurrentValue["FontCapHeight"], + AbsoluteCurrentValue[Magnification]^(-1) + ] + ] + } + ] + ], + GridBox[ + { + { + RowBox[ + { + TagBox["\"ID: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["\"WolframAlphaQueries\"", "SummaryItem"] + } + ] + }, + { + RowBox[ + { + TagBox["\"Elements: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["59817", "SummaryItem"] + } + ] + }, + { + RowBox[ + { + TagBox["\"Vector length: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["256", "SummaryItem"] + } + ] + }, + { + RowBox[ + { + TagBox["\"Working precision: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["\"Integer8\"", "SummaryItem"] + } + ] + }, + { + RowBox[ + { + TagBox["\"Distance function: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox["EuclideanDistance", "SummaryItem"] + } + ] + }, + { + RowBox[ + { + TagBox["\"Location: \"", "SummaryItemAnnotation"], + "\[InvisibleSpace]", + TagBox[ + TemplateBox[ + { + RowBox[ + { + "File", + "[", + RowBox[{"\[LeftSkeleton]", "1", "\[RightSkeleton]"}], + "]" + } + ], + RowBox[ + { + "File", + "[", + TemplateBox[ + { + "\"C:\\\\Users\\\\rhennigan\\\\AppData\\\\Local\\\\Temp\\\\WolframAlphaQueries-6255df02-3496-4e77-b930-0d733c4a537f-Extracted\\\\WolframAlphaQueries.wxf\"" + }, + "FileArgument" + ], + "]" + } + ] + }, + "ClickToCopy2" + ], + "SummaryItem" + ] + } + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Automatic}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{2}}, "Rows" -> {{Automatic}}}, + BaseStyle -> { + ShowStringCharacters -> False, + NumberMarks -> False, + PrintPrecision -> 3, + ShowSyntaxStyles -> False + } + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Top}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + BaselinePosition -> {1, 1} + ] + }, + Dynamic[Typeset`open$$], + ImageSize -> Automatic + ] + }, + "SummaryPanel" + ], + DynamicModuleValues :> { } + ], + "]" + } + ], + VectorDatabaseObject[ + <| + "DistanceFunction" -> EuclideanDistance, + "FeatureExtractor" -> Identity, + "GeneratedAssetLocation" -> + File[ + "C:\\Users\\rhennigan\\AppData\\Local\\Temp\\WolframAlphaQueries-6255df02-3496-4e77-b930-0d733c4a537f-Extracted\\WolframAlphaQueries.wxf" + ], + "ID" -> "WolframAlphaQueries", + "Location" -> + File[ + "C:\\Users\\rhennigan\\AppData\\Local\\Temp\\WolframAlphaQueries-6255df02-3496-4e77-b930-0d733c4a537f-Extracted\\WolframAlphaQueries.wxf" + ], + "ResolvedFeatureExtractor" -> Identity, + "VectorDatabaseInfo" -> <| + "DistanceFunction" -> "l2sq", + "WorkingPrecision" -> "i8", + "Connectivity" -> 16, + "ExpansionAdd" -> 256, + "ExpansionSearch" -> 2048, + "Capacity" -> 59817, + "Dimensions" -> 256 + |>, + "Version" -> 1.1, + "WorkingPrecision" -> "Integer8", + "Evaluator" -> "c++", + "DatabaseType" -> "USearch", + "MetadataKeys" -> { }, + "Dimensions" -> {59817, 256}, + "Hash" -> 235078148346117175893482954648565661383 + |> + ], + Editable -> False, + SelectWithContents -> True, + Selectable -> False + ] + ], + "Output", + CellTags -> "DefaultContent", + CellLabel -> "Out[1]=", + CellID -> 265794342 + ] + }, + Open + ] + ], + Cell["Search it:", "Text", CellID -> 477433615], + Cell[ + BoxData[ + RowBox[ + { + RowBox[ + { + "vector", + "=", + RowBox[ + { + "RandomInteger", + "[", + RowBox[ + { + RowBox[ + {"{", RowBox[{RowBox[{"-", "128"}], ",", "127"}], "}"} + ], + ",", + "256" + } + ], + "]" + } + ] + } + ], + ";" + } + ] + ], + "Input", + CellLabel -> "In[2]:=", + CellID -> 174568640 + ], + Cell[ + CellGroupData[ + { + Cell[ + BoxData[ + RowBox[ + { + "VectorDatabaseSearch", + "[", + RowBox[{"db", ",", "vector", ",", "\"Index\""}], + "]" + } + ] + ], + "Input", + CellLabel -> "In[3]:=", + CellID -> 14128918 + ], + Cell[ + BoxData[RowBox[{"{", "21567", "}"}]], + "Output", + CellLabel -> "Out[3]=", + CellID -> 66387350 + ] + }, + Open + ] + ] + }, + Open + ] + ], + Cell[ + "Scope & Additional Elements", + "Subsection", + CellID -> 979821957 + ], + Cell["Visualizations", "Subsection", CellID -> 50804313], + Cell["Analysis", "Subsection", CellID -> 866856397] + }, + Open + ] + ], + Cell[ + CellGroupData[ + { + Cell[ + "Source & Additional Information", + "Section", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Source & Additional Information"}, + CellTags -> {"Source & Additional Information", "TemplateSection"}, + CellID -> 871630328 + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Submitted By", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "ContributedBy", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Enter the name of the person, people or organization that should be publicly credited with submitting this data.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoContributedBy"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "ContributedBy"}, + DefaultNewCellStyle -> "Text", + CellTags -> { + "Contributed By", + "ContributedBy", + "Submitted By", + "TemplateCellGroup" + }, + CellID -> 731311331 + ], + Cell[ + "Wolfram Staff", + "Text", + CellEventActions -> { + Inherited, + {"KeyDown", "\t"} :> + Replace[ + SelectionMove[SelectedNotebook[], After, Cell]; + NotebookFind[ + SelectedNotebook[], + "TabNext", + Next, + CellTags, + AutoScroll -> True, + WrapAround -> True + ], + Blank[NotebookSelection] :> + SelectionMove[ + SelectedNotebook[], + All, + CellContents, + AutoScroll -> True + ] + ], + PassEventsDown -> False, + PassEventsUp -> False + }, + CellTags -> {"DefaultContent", "TabNext"}, + CellID -> 316640766 + ] + }, + Open + ] + ], + Cell[ + TextData[ + { + "Source/Reference Citation", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "Citation", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Give a bibliographic-style citation for the original source of the data and/or its components.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoCitation"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Citation"}, + DefaultNewCellStyle -> "Text", + CellTags -> { + "Citation", + "Source/Reference Citation", + "TemplateCellGroup" + }, + CellID -> 657892269 + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Detailed Source Information", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "Detailed Source Information", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Add bibliographic details about the original source and publication of the data.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoDetailedSourceInformation"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Detailed Source Information"}, + CellTags -> {"Detailed Source Information", "TemplateSection"}, + CellID -> 67505013 + ], + Cell[ + "Author/Creator", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDAuthor"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"Author/Creator", "SMDAuthor", "TemplateCellGroup"}, + CellID -> 62010071 + ], + Cell[ + "Source Title", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDTitle"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"SMDTitle", "Source Title", "TemplateCellGroup"}, + CellID -> 15581079 + ], + Cell[ + "Source Date", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDDate"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"SMDDate", "Source Date", "TemplateCellGroup"}, + CellID -> 251981362 + ], + Cell[ + "Source Publisher", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDPublisher"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"SMDPublisher", "Source Publisher", "TemplateCellGroup"}, + CellID -> 910715536 + ], + Cell[ + "Geographic Coverage", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDGeographicCoverage"}, + DefaultNewCellStyle -> "Text", + CellTags -> { + "Geographic Coverage", + "SMDGeographicCoverage", + "TemplateCellGroup" + }, + CellID -> 346798217 + ], + Cell[ + "Temporal Coverage", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDTemporalCoverage"}, + DefaultNewCellStyle -> "Text", + CellTags -> { + "SMDTemporalCoverage", + "TemplateCellGroup", + "Temporal Coverage" + }, + CellID -> 135354521 + ], + Cell[ + "Source Language", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDLanguage"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"SMDLanguage", "Source Language", "TemplateCellGroup"}, + CellID -> 146694705 + ], + Cell[ + "Rights", + "Subsubsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SMDRights"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"Rights", "SMDRights", "TemplateCellGroup"}, + CellID -> 190531069 + ] + }, + Open + ] + ], + Cell[ + TextData[ + { + "Links", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "Links", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "List additional URLs or hyperlinks for external information related to the data.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoLinks"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Links"}, + DefaultNewCellStyle -> "Item", + CellTags -> {"Links", "TemplateCellGroup"}, + CellID -> 255897931 + ], + Cell[ + TextData[ + { + "Keywords", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "Keywords", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "List relevant terms that should be used to include the data in search results.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoKeywords"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Keywords"}, + DefaultNewCellStyle -> "Item", + CellTags -> {"Keywords", "TemplateCellGroup"}, + CellID -> 266337689 + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Categories", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "Categories", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Select any categories which the data covers.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoCategories"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "Categories"}, + DefaultNewCellStyle -> "Item", + CellTags -> {"Categories", "TemplateCellGroup"}, + CellID -> 885722481 + ], + Cell[ + BoxData[ + TagBox[ + GridBox[ + { + { + TagBox[ + GridBox[ + { + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Agriculture"}], + "\" \"", + "\"Agriculture\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Computer Systems"}], + "\" \"", + "\"Computer Systems\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Economics"}], + "\" \"", + "\"Economics\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Geometry Data"}], + "\" \"", + "\"Geometry Data\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Healthcare"}], + "\" \"", + "\"Healthcare\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Language"}], + "\" \"", + "\"Language\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Mathematics"}], + "\" \"", + "\"Mathematics\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Politics"}], + "\" \"", + "\"Politics\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Statistics"}], + "\" \"", + "\"Statistics\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + } + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ], + TagBox[ + GridBox[ + { + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Astronomy"}], + "\" \"", + "\"Astronomy\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Culture"}], + "\" \"", + "\"Culture\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Education"}], + "\" \"", + "\"Education\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Government"}], + "\" \"", + "\"Government\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "History"}], + "\" \"", + "\"History\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Life Science"}], + "\" \"", + "\"Life Science\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Medicine"}], + "\" \"", + "\"Medicine\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Reference"}], + "\" \"", + "\"Reference\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Text & Literature"}], + "\" \"", + "\"Text & Literature\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + } + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ], + TagBox[ + GridBox[ + { + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Chemistry"}], + "\" \"", + "\"Chemistry\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Demographics"}], + "\" \"", + "\"Demographics\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Engineering"}], + "\" \"", + "\"Engineering\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Graphics"}], + "\" \"", + "\"Graphics\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Human Activities"}], + "\" \"", + "\"Human Activities\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Machine Learning"}], + "\" \"", + "\"Machine Learning\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Meteorology"}], + "\" \"", + "\"Meteorology\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Social Media"}], + "\" \"", + "\"Social Media\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Transportation"}], + "\" \"", + "\"Transportation\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + } + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ], + TagBox[ + GridBox[ + { + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Computational Universe"}], + "\" \"", + "\"Computational Universe\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Earth Science"}], + "\" \"", + "\"Earth Science\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Geography"}], + "\" \"", + "\"Geography\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Health"}], + "\" \"", + "\"Health\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Images"}], + "\" \"", + "\"Images\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Manufacturing"}], + "\" \"", + "\"Manufacturing\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Physical Sciences"}], + "\" \"", + "\"Physical Sciences\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + { + StyleBox[ + TemplateBox[ + { + CheckboxBox[False, {False, "Sociology"}], + "\" \"", + "\"Sociology\"" + }, + "RowDefault" + ], + StripOnInput -> False, + FontSize -> 12 + ] + }, + {"\"\""} + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ] + } + }, + AutoDelete -> False, + BaseStyle -> {"ControlStyle"}, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Top}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{2}}} + ], + "Grid" + ] + ], + "Output", + Editable -> False, + Deletable -> False, + TaggingRules -> { + "CheckboxData" -> "OEM6eJxVTm0KgkAUjMjSiG7iIcQKhMDwdYFVx1pa3WXf2x/evpUg6tcM88FMkeaUkMwGtK2DuCA57conuhf6YcWbq+aoJJVgZM6KIHZUoruc0pu3Dl5m2pdK8LBeg2O3dqLtxMP6012wCQacnnstqo0suSjD+BrZCQa/znLAmjBO/4PHahJ452N2WaCsmGYKLSP+OzRgG3yH++xAm5MS9QYdBUrS" + }, + CellTags -> {"Categories", "Categories-Checkboxes", "CheckboxCell"}, + CellID -> 460292996 + ] + }, + Open + ] + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Content Types", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "ContentTypes", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Select any of the types of data included in the content elements.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoContentTypes"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "ContentTypes"}, + DefaultNewCellStyle -> "Item", + CellTags -> {"Content Types", "ContentTypes", "TemplateCellGroup"}, + CellID -> 765263253 + ], + Cell[ + BoxData[ + TagBox[ + GridBox[ + { + { + TagBox[ + GridBox[ + { + { + TemplateBox[ + { + CheckboxBox[False, {False, "Audio"}], + "\" \"", + StyleBox[ + "\"Audio\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + { + TemplateBox[ + { + CheckboxBox[False, {False, "Image"}], + "\" \"", + StyleBox[ + "\"Image\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + { + TemplateBox[ + { + CheckboxBox["Vector Database", {False, "Vector Database"}], + "\" \"", + StyleBox[ + "\"Vector Database\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + } + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ], + TagBox[ + GridBox[ + { + { + TemplateBox[ + { + CheckboxBox[False, {False, "Entity Store"}], + "\" \"", + StyleBox[ + "\"Entity Store\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + { + TemplateBox[ + { + CheckboxBox[False, {False, "Numerical Data"}], + "\" \"", + StyleBox[ + "\"Numerical Data\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + { + TemplateBox[ + { + CheckboxBox[False, {False, "Video"}], + "\" \"", + StyleBox[ + "\"Video\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + } + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ], + TagBox[ + GridBox[ + { + { + TemplateBox[ + { + CheckboxBox[False, {False, "Geospatial Data"}], + "\" \"", + StyleBox[ + "\"Geospatial Data\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + { + TemplateBox[ + { + CheckboxBox[False, {False, "Text"}], + "\" \"", + StyleBox[ + "\"Text\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + {"\"\""} + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ], + TagBox[ + GridBox[ + { + { + TemplateBox[ + { + CheckboxBox[False, {False, "Graphs"}], + "\" \"", + StyleBox[ + "\"Graphs\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + { + TemplateBox[ + { + CheckboxBox[False, {False, "Time Series"}], + "\" \"", + StyleBox[ + "\"Time Series\"", + FontSize -> 12, + Editable -> False, + StripOnInput -> False + ] + }, + "RowDefault" + ] + }, + {"\"\""} + }, + DefaultBaseStyle -> "Column", + GridBoxAlignment -> {"Columns" -> {{Left}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Column" + ] + } + }, + AutoDelete -> False, + BaseStyle -> {"ControlStyle", ShowStringCharacters -> False}, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Top}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{2}}} + ], + "Grid" + ] + ], + "Output", + Editable -> False, + Deletable -> False, + TaggingRules -> { + "CheckboxData" -> "OEM6eJxdjtEKgkAQRQk0EyV/oR/wI2QjECKjid5XnUjSnWVn9sG/b416qNfLPfeeKishBplHhHXjxXopIVEP7J7Y31ccHQcWKG7YCbndXotuNWNAasGJOa280KRl6ErYnB1ZdDJDrsgIGrnOFjnMNVYGMr/tRNHop79wWwfOWYeiFwLSyszgW8YglSnPoViboMjxQY+Lxjd8y0QnMiHLL8jkXYfLPUSLcwmFoimA2H9uVfQCKx5XrQ==" + }, + CellTags -> {"CheckboxCell", "ContentTypes", "ContentTypes-Checkboxes"}, + CellID -> 413260493 + ] + }, + Open + ] + ], + Cell[ + TextData[ + { + "Related Resource Objects", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "SeeAlso", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "List the names of published resource objects from any Wolfram repository that are related to this data.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoSeeAlso"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SeeAlso"}, + DefaultNewCellStyle -> "Item", + CellTags -> { + "Related Resource Objects", + "SeeAlso", + "TemplateCellGroup" + }, + CellID -> 398191659 + ], + Cell[ + TextData[ + { + "Related Symbols", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "RelatedSymbols", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "List documented, system-level Wolfram Language symbols related to the data.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoRelatedSymbols"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Subsection", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "RelatedSymbols"}, + DefaultNewCellStyle -> "Item", + CellTags -> {"Related Symbols", "RelatedSymbols", "TemplateCellGroup"}, + CellID -> 661598311 + ] + }, + Open + ] + ], + Cell[ + TextData[ + { + "Author Notes", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "AuthorNotes", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Include any notes you would like to be published along with the resource.\n\nThese notes will be available to all users and can include known limitations or possible improvements to the data.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoAuthorNotes"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Section", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "AuthorNotes"}, + DefaultNewCellStyle -> "Text", + CellTags -> {"Author Notes", "AuthorNotes", "TemplateCellGroup"}, + CellID -> 823423117 + ], + Cell[ + CellGroupData[ + { + Cell[ + TextData[ + { + "Submission Notes", + Cell[ + BoxData[ + PaneSelectorBox[ + { + True -> + TemplateBox[ + { + "SubmissionNotes", + Cell[ + BoxData[ + FrameBox[ + Cell[ + "Enter any additional information that you would like to communicate to the reviewer here. This section will not be included in the published resource.", + "MoreInfoText" + ], + Background -> GrayLevel[0.95], + FrameMargins -> 20, + FrameStyle -> GrayLevel[0.9], + RoundingRadius -> 5, + ImageSize -> {Scaled[0.65], Automatic} + ] + ], + "MoreInfoText", + Deletable -> True, + CellTags -> {"SectionMoreInfoSubmissionNotes"}, + CellMargins -> {{66, 66}, {15, 15}} + ] + }, + "MoreInfoOpenerButtonTemplate" + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ResourceCreateNotebook"} + ] + ], + ImageSize -> Automatic + ] + ] + ] + } + ], + "Section", + Editable -> False, + Deletable -> False, + TaggingRules -> {"TemplateGroupName" -> "SubmissionNotes"}, + DefaultNewCellStyle -> "Text", + CellTags -> { + "Submission Notes", + "SubmissionNotes", + "TemplateCellGroup" + }, + CellID -> 161504757 + ], + Cell[ + "This should be marked as non-discoverable, since it's not very useful without the relevant internal Chatbook code that interprets the results.", + "Text", + CellID -> 246497798 + ] + }, + Open + ] + ] + }, + Open + ] + ] + }, + Visible -> True, + TaggingRules -> { + "ResourceType" -> "Data", + "ResourceCreateNotebook" -> True, + "TemplateVersion" -> "2022.09.15", + "CreationTimestamp" -> 3932453782.0, + "UpdatedTimestamp" -> 3932453782.0, + "CompatibilityTest" -> + HoldComplete[ + BinaryDeserialize[ + BaseDecode[ + "OEM6eJzVWltT20YUji9cCg4d0ulM0yc95IFmEnJpZ3pJ20BtIHSAAGuSPrKWjmwNa62yuwL0U9o/0r/XsyvJNo5kJNu0qSeTyNLqO9+e237rjVuVD5q8H/DQd3auAwFSetx3K3LhJPRAudmPq7K67+LftW3fwX8Wdj6ElMm1R+9A6OdHYb8DQrjms7GlRxDahxO8aDRDIcBX7ygLwb0nH+xc4hVV+i2uoMP5BY6qH3hSyUabdrue3z0NGUjSOAXJQ2FDOwqA1FtUUaRZf+vbkMty4TfG7Qs9LAZ81OS+gmt1TFXPreXN/AjAkWQjtUciqaDfZB7SPm+B6/neKN3z4SuWJpW+ljVU1o9CxpDY5scPEwOn0EWqIJCp63VDYVwzmO7roqROIeDSU1xEMWCMIxOgmolfRS7vUo+FAiNTkfePqc1A7ftSUcbIV3kM3cVpnD2VWxttfiMyK0QJzIffuaft1Q5pYOYQ+rZ+012ILZOHuc415KjUab0aY5GAeUrfJoyrZoVUzkn1p19GblRfrRjymL+SfFOU/GO3nuOlGgFtb6XFr3xTBFL+WBQ1vXgbKgwjOLqgVjDSjNqwjXk1R9hVXXQtYDQCB3FX33DmYCAxMX35a1HgY+FdIuD5ZdwW9gTgNyGXznyZtIMMb7TKotMgAN8583vUdxg4TWBMTnTMvCxM8BF+Le0lG2Gx4yUIZL0NfZyAAm1uT/AwmB0Ua7exzfQVtoNLTOgvmzioy4UH8mmzB/ZFh1/j7bXhbW2dNNJn5tsa2qMhU6a+fZXBlHye3iIQ12ZmqAt3s0Eg5EWbnwUOXid9Pz/KcwC/EeAa3lhKS2B5j/EOZec9vaSNelR+X9TsHqg3nuOAHzei4uW6S307ava4Z0PLo4x3R4k1EmJC4SqJ6ys2ZepfZFGn+HTdPNVrEoEPIeCsyYPEA8xJDZ7gcjGY700DI2DpkrLQFqEp7Rm7RJnFLr1Iky6RIfJlWQp+p0yNJVJm3OoND6X+PIKrgT8zfRwXiDwsS/lRKOEAutSO9rs+F3F3SmMt6zoa2cX3qqilDNyxwptUhjOamdRjq3LxAN80jXG3rN+6oNI2dtPi3EoJS2IVmQP2RSpB3gXd3GpECW1U86Ievd/SdWn4yaV97NldzNTlfd8Yi25xcm3AOmfiCXDhvpfOSA5Who9gO0NvD8yP2KzIndLLIPW579mUHQseAHrL6LlpOY8Qzd5EVJNm2NiWktue0d4ncrt0bQcJWxIh/aivc2h524iRNp8PnEkTskYM0CEo6uj9QbIDI8tNT8UbkIfxiGen4ILQ2W2lj4bdZT5RGTE6RivePQ32UPEWtH6APv9o63nPfB5v4Z5gls3KhJ1ECX3/OBelnKAvhzNJwX+Xi4SbwAvaBWJjQMrp9rNczHi1y8qD2NjUQv7OTE5W9gW9V0TPTwX1ian449mjUELW34W1aXT+Ri6PcWGfX7b/EyU/VbdAgOe39qtx6dycObhGwT/LhbkLyZ5P+oZ7phbqT3LxZ1PmZXGLSvGfi/njvxXgM5H8hGT3D7nzILagAfaf8QqZRXe/KrhcZartqalOKbf3J/zGnv44jtUWBuNmJ8vuucLOU37PEpy5iO6//tSfja3h6dHSv3RUMAc9n9l6S2+xsF+QsNP3zESx1PnEDjwX+DiFhqcgg56zGOuP7Jlt5RejNqDGk7fcxOaBXmBeK0S350S2yc1Mbw5+XaTM0yv4MRWY71qg1MZUdGP09C4+KCN1XQLkfqKR49npzp10zjaYs6RBI3162wHgUINioxpOaXWkcY11sZKQdbnwvufZvdwi/dZ8TJHeP8QBGIVYe5I/2j1PWn6CawlcRT0sWSvRddaLl5svLC4sLZyExV1L9cB6z5mLDrVin1uKW24SMCtudyzaHB4U39o3GqNqmPxduUlJ79aokNpKByzbCE3HcgXvW9Ty4QppJWSfWJLjnz5YLg4K9TT6NNJI1hUXiCQtuA5weQFn02pxK+KhdeXJnoZWIrJoqHgfI4BtkkWWzX3EVZh0OOdRQjia4tN+gEM7DFLrr3MOpGtyq/j5bXwMnKb/W4QWnpPm5RdZEm30LHRM+tRm+h1Wfrad+kNne1L2w0PSvIVsuKro0OqxqTRrVktppXpxx+VtFPL/r4Fhvt402TSi+eXCLmUSBiO+PoU+v4SdfqCinWuKG4h0WyzHh67HJN57vsOv2p7CWcYj4mX0Hz1LhOU=" + ] + ] + ], + "DefinitionNotebookFramework" -> "DefinitionNotebookClient", + "RuntimeConfiguration" -> { + "Contexts" -> {"DataResource`", "DataResource`DefinitionNotebook`"}, + "DefaultContentMethod" -> "Legacy", + "HintPods" -> True, + "LoadingMethod" -> "Paclet", + "PacletName" -> "DataResource", + "SourceID" -> "aab60bd760a6c130942c461f106d46d75083799b" + }, + "ToolsOpen" -> True, + "StatusMessage" -> "", + "SubmissionReviewData" -> {"Review" -> False}, + "AutoUpdate" -> True + }, + CreateCellID -> True, + StyleDefinitions -> + Notebook[ + { + Cell[StyleData[StyleDefinitions -> "Default.nb"]], + Cell[ + StyleData[All, "Working"], + WindowToolbars -> { }, + DockedCells -> { + Cell[ + BoxData[TemplateBox[{}, "MainGridTemplate"]], + "DockedCell", + CellMargins -> {{-10, -10}, {-8, -8}}, + CellFrame -> 0, + Background -> RGBColor[0.16078, 0.40392, 0.56078], + CellTags -> {"MainDockedCell"}, + CacheGraphics -> False + ], + Cell[ + BoxData[TemplateBox[{}, "ToolsGridTemplate"]], + "DockedCell", + TaggingRules -> {"Tools" -> True}, + CellTags -> {"ToolbarDockedCell"}, + CellFrameMargins -> {{0, 0}, {2, 2}}, + CellFrame -> {{0, 0}, {1, 0}}, + CacheGraphics -> False, + CellOpen -> + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ToolsOpen"}, + True + ] + ] + ] + }, + PrivateNotebookOptions -> { + "FileOutlineCache" -> False, + "SafeFileOpen" -> "IgnoreCache" + }, + CellLabelAutoDelete -> False, + CodeAssistOptions -> {"AutoDetectHyperlinks" -> False}, + AutoQuoteCharacters -> { }, + PasteAutoQuoteCharacters -> { } + ], + Cell["Hint Styles", "Section"], + Cell[ + StyleData[ + "MoreInfoText", + StyleDefinitions -> StyleData["Text"] + ], + FontColor -> GrayLevel[0.25] + ], + Cell[ + StyleData[ + "ErrorText", + StyleDefinitions -> StyleData["Text"] + ], + ShowCellBracket -> False, + CellMargins -> {{66, Inherited}, {10, 10}}, + CellElementSpacings -> {"CellMinHeight" -> 0, "ClosedCellHeight" -> 0}, + FontWeight -> Bold, + FontColor -> RGBColor[1, 0, 0] + ], + Cell[ + StyleData[ + "WarningText", + StyleDefinitions -> StyleData["Text"] + ], + ShowCellBracket -> False, + CellMargins -> {{66, 35}, {0, 0}}, + FontSize -> 14, + GridBoxOptions -> {BaseStyle -> {}} + ], + Cell["Template Boxes", "Section"], + Cell[ + StyleData["MoreInfoOpenerIconTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + PaneSelectorBox[ + { + False -> + GraphicsBox[ + { + Thickness[0.090909], + StyleBox[ + { + JoinedCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJJIGYC4oSnF5RuVyo58OlumvteXcIBxj//Pfjx0tky\nDp8u+SYJzFB0kGQJ49MtUnBYIKV/V4UNRis5GHKskYl6AlOnDNUHM0cFaq4I\nnD/niMKGogx+OB+oO8X6Phtcf/+hrxox/Qxw80HKftZ9sYfZ/7BKZJ37w1f2\nMPfB+DD3w/h+SQIRlluE4foh9vDBzYfQHHD7izMmvq2xZ4K7r9CW6/rigr/2\nMPfD+DD/wfgw/8P0w8IHZj4s/GD2w8IX5j708AcA2Xetpg==\n " + ], + CurveClosed -> {1} + ] + }, + { + JoinForm[{"Miter", 3.25}], + Thickness[0.045818], + RGBColor[0.62744, 0.62744, 0.62744, 1.0] + }, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + }, + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0} + } + }, + { + CompressedData[ + "\n1:eJxTTMoPSmViYGCQBGIQ3b48/JRRi4jD3qBpin2m8g5n6j32194VhvNZnvdo\nvPUVdoh2sntxM0feQfiT4/m0q0IOQNnSwtvyDmxCIvbHYoQcMhnyG1lUFRyk\neR/oTlAAym/iKVyTjeAf2aiXt/gggt+odqhtubgiXP+k00CLYxXh5mdrf5t+\nd7Ii3P5LDPeYOE8pwt33vfTBHMGnig4w98P4j5fOPqJgIArn539oPRlyUBSu\n/9OGgOxZ5mJw88sKgS5aKwa3XzOm/9DXF2Jw98H4MPfD+DD/wfTD/A8zHxY+\nMPth4QdzHyx80cMfAIsMpwk=\n " + ], + CompressedData[ + "\n1:eJxTTMoPSmViYGCQB2IQXTFnkfJOGwmHsNp125Lq+R1g/G8aMf2HvvI4KP39\nVvrgjgAGH6b+c19wicp0IQeBKrPVduICcL6EWjDr4ksCqPLTBeH8211/U7+n\nCMH5S+7v45tjLAznX773gHvySwS/qdhtyrc2ETj/04aA7FnfReH8RxHi2y8e\nEIPzNUHOzRCH8x8vnX1E4QOCP+/98mPe5RJw/o9goAoWSTj/6vMs7W/TJR0O\nX9ZOlVwk4PB2no3OlVsI/jKgcRs+STlonhY4vstCzCFoh1zr64syDkBXssXP\nEHO4WvFSzbADwa9JNAo1yJKA82H+gfFh/oXxA29JA7Ug+GY2e4OmJQrB+f83\nVX/aMEEQzrerjFhhelYAzofFB3r8AgApYdcE\n " + ] + } + ] + }, + {FaceForm[RGBColor[0.62744, 0.62744, 0.62744, 1.0]]}, + StripOnInput -> False + ] + }, + ImageSize -> {11.0, 11.0}, + PlotRange -> {{0.0, 11.0}, {0.0, 11.0}}, + AspectRatio -> Automatic + ], + True -> + GraphicsBox[ + { + Thickness[0.090909], + StyleBox[ + { + JoinedCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJJIGYC4oSnF5RuVyo58OlumvteXcIBxj//Pfjx0tky\nDp8u+SYJzFB0kGQJ49MtUnBYIKV/V4UNRis5GHKskYl6AlOnDNUHM0cFaq4I\nnD/niMKGogx+OB+oO8X6Phtcf/+hrxox/Qxw80HKftZ9sYfZ/7BKZJ37w1f2\nMPfB+DD3w/h+SQIRlluE4foh9vDBzYfQHHD7izMmvq2xZ4K7r9CW6/rigr/2\nMPfD+DD/wfgw/8P0w8IHZj4s/GD2w8IX5j708AcA2Xetpg==\n " + ], + CurveClosed -> {1} + ] + }, + { + JoinForm[{"Miter", 3.25}], + Thickness[0.045818], + RGBColor[0.5, 0.5, 0.5, 1.0] + }, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJJIGYC4oSnF5RuVyo58OlumvteXcIBxj//Pfjx0tky\nDp8u+SYJzFB0kGQJ49MtUnBYIKV/V4UNRis5GHKskYl6AlOnDNUHM0cFaq4I\nnD/niMKGogx+OB+oO8X6Phtcf/+hrxox/Qxw80HKftZ9sYfZ/7BKZJ37w1f2\nMPfB+DD3w/h+SQIRlluE4foh9vDBzYfQHHD7izMmvq2xZ4K7r9CW6/rigr/2\nMPfD+DD/wfgw/8P0w8IHZj4s/GD2w8IX5j708AcA2Xetpg==\n " + ] + ] + }, + {FaceForm[RGBColor[0.5, 0.5, 0.5, 1.0]]}, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + }, + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0} + } + }, + { + CompressedData[ + "\n1:eJxTTMoPSmViYGCQBGIQ3b48/JRRi4jD3qBpin2m8g5n6j32194VhvNZnvdo\nvPUVdoh2sntxM0feQfiT4/m0q0IOQNnSwtvyDmxCIvbHYoQcMhnyG1lUFRyk\neR/oTlAAym/iKVyTjeAf2aiXt/gggt+odqhtubgiXP+k00CLYxXh5mdrf5t+\nd7Ii3P5LDPeYOE8pwt33vfTBHMGnig4w98P4j5fOPqJgIArn539oPRlyUBSu\n/9OGgOxZ5mJw88sKgS5aKwa3XzOm/9DXF2Jw98H4MPfD+DD/wfTD/A8zHxY+\nMPth4QdzHyx80cMfAIsMpwk=\n " + ], + CompressedData[ + "\n1:eJxTTMoPSmViYGCQB2IQXTFnkfJOGwmHsNp125Lq+R1g/G8aMf2HvvI4KP39\nVvrgjgAGH6b+c19wicp0IQeBKrPVduICcL6EWjDr4ksCqPLTBeH8211/U7+n\nCMH5S+7v45tjLAznX773gHvySwS/qdhtyrc2ETj/04aA7FnfReH8RxHi2y8e\nEIPzNUHOzRCH8x8vnX1E4QOCP+/98mPe5RJw/o9goAoWSTj/6vMs7W/TJR0O\nX9ZOlVwk4PB2no3OlVsI/jKgcRs+STlonhY4vstCzCFoh1zr64syDkBXssXP\nEHO4WvFSzbADwa9JNAo1yJKA82H+gfFh/oXxA29JA7Ug+GY2e4OmJQrB+f83\nVX/aMEEQzrerjFhhelYAzofFB3r8AgApYdcE\n " + ] + } + ] + }, + {FaceForm[RGBColor[0.99998, 0.99998, 0.99998, 1.0]]}, + StripOnInput -> False + ] + }, + ImageSize -> {11.0, 11.0}, + PlotRange -> {{0.0, 11.0}, {0.0, 11.0}}, + AspectRatio -> Automatic + ] + }, + Dynamic[CurrentValue["MouseOver"]], + ImageSize -> Automatic, + FrameMargins -> 0 + ] + ]) + } + ], + Cell[ + StyleData["MoreInfoOpenerButtonTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + AdjustmentBox[ + DynamicModuleBox[ + { + RSNB`mPosRegion$$, + RSNB`attachPos$$, + RSNB`offsetPos$$, + RSNB`horizontalRegion$$, + RSNB`verticalRegion$$, + RSNB`chooseAttachLocation$$ + }, + TagBox[ + TemplateBox[ + { + TemplateBox[{}, "MoreInfoOpenerIconTemplate"], + "\"Click for more information\"" + }, + "PrettyTooltipTemplate" + ], + EventHandlerTag[ + { + "MouseDown" :> + AttachCell[ + ParentBox[EvaluationBox[]], + #2, + RSNB`chooseAttachLocation$$[], + RemovalConditions -> {"EvaluatorQuit", "MouseClickOutside"} + ], + Method -> "Preemptive", + PassEventsDown -> Automatic, + PassEventsUp -> True + } + ] + ], + DynamicModuleValues :> { + { + DownValues[RSNB`mPosRegion$$] = { + HoldPattern[RSNB`mPosRegion$$[]] :> + RSNB`mPosRegion$$[Ceiling[MousePosition["WindowScaled"]*3]], + HoldPattern[ + RSNB`mPosRegion$$[ + Pattern[RSNB`reg, {Blank[Integer], Blank[Integer]}] + ] + ] :> RSNB`reg, + HoldPattern[RSNB`mPosRegion$$[BlankNullSequence[]]] :> None + } + }, + { + DownValues[RSNB`attachPos$$] = { + HoldPattern[ + RSNB`attachPos$$[ + { + Pattern[RSNB`h$, Blank[Integer]], + Pattern[RSNB`v$, Blank[Integer]] + } + ] + ] :> { + RSNB`horizontalRegion$$[RSNB`h$], + RSNB`verticalRegion$$[RSNB`v$] + } + } + }, + { + DownValues[RSNB`offsetPos$$] = { + HoldPattern[ + RSNB`offsetPos$$[ + { + Pattern[RSNB`h$, Blank[Integer]], + Pattern[RSNB`v$, Blank[Integer]] + } + ] + ] :> { + RSNB`horizontalRegion$$[4 - RSNB`h$], + RSNB`verticalRegion$$[4 - RSNB`v$] + } + } + }, + { + DownValues[RSNB`horizontalRegion$$] = { + HoldPattern[RSNB`horizontalRegion$$[1]] :> Left, + HoldPattern[RSNB`horizontalRegion$$[2]] :> Center, + HoldPattern[RSNB`horizontalRegion$$[3]] :> Right + } + }, + { + DownValues[RSNB`verticalRegion$$] = { + HoldPattern[RSNB`verticalRegion$$[1]] :> Top, + HoldPattern[RSNB`verticalRegion$$[2]] :> Top, + HoldPattern[RSNB`verticalRegion$$[3]] :> Top + } + }, + { + DownValues[RSNB`chooseAttachLocation$$] = { + HoldPattern[RSNB`chooseAttachLocation$$[]] :> + With[ { RSNB`p$ = RSNB`mPosRegion$$[] }, + Apply[ + Sequence, + { + RSNB`offsetPos$$[RSNB`p$], + {-30, 30}, + RSNB`attachPos$$[RSNB`p$] + } + ] + ] + } + } + } + ], + BoxBaselineShift -> -0.5, + BoxMargins -> 0.2 + ] + ]) + } + ], + Cell[ + StyleData["InlineMoreInfoOpenerButtonTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + AdjustmentBox[ + DynamicModuleBox[ + { + RSNB`mPosRegion$$, + RSNB`attachPos$$, + RSNB`offsetPos$$, + RSNB`horizontalRegion$$, + RSNB`verticalRegion$$, + RSNB`chooseAttachLocation$$ + }, + TagBox[ + TemplateBox[ + {TemplateBox[{}, "MoreInfoOpenerIconTemplate"], #4}, + "PrettyTooltipTemplate" + ], + EventHandlerTag[ + { + "MouseDown" :> + AttachCell[ + ParentBox[EvaluationBox[]], + #2, + RSNB`chooseAttachLocation$$[], + RemovalConditions -> {"EvaluatorQuit", "MouseClickOutside"} + ], + Method -> "Preemptive", + PassEventsDown -> Automatic, + PassEventsUp -> True + } + ] + ], + DynamicModuleValues :> { + { + DownValues[RSNB`mPosRegion$$] = { + HoldPattern[RSNB`mPosRegion$$[]] :> + RSNB`mPosRegion$$[Ceiling[MousePosition["WindowScaled"]*3]], + HoldPattern[ + RSNB`mPosRegion$$[ + Pattern[RSNB`reg, {Blank[Integer], Blank[Integer]}] + ] + ] :> RSNB`reg, + HoldPattern[RSNB`mPosRegion$$[BlankNullSequence[]]] :> None + } + }, + { + DownValues[RSNB`attachPos$$] = { + HoldPattern[ + RSNB`attachPos$$[ + { + Pattern[RSNB`h$, Blank[Integer]], + Pattern[RSNB`v$, Blank[Integer]] + } + ] + ] :> { + RSNB`horizontalRegion$$[RSNB`h$], + RSNB`verticalRegion$$[RSNB`v$] + } + } + }, + { + DownValues[RSNB`offsetPos$$] = { + HoldPattern[ + RSNB`offsetPos$$[ + { + Pattern[RSNB`h$, Blank[Integer]], + Pattern[RSNB`v$, Blank[Integer]] + } + ] + ] :> { + RSNB`horizontalRegion$$[4 - RSNB`h$], + RSNB`verticalRegion$$[4 - RSNB`v$] + } + } + }, + { + DownValues[RSNB`horizontalRegion$$] = { + HoldPattern[RSNB`horizontalRegion$$[1]] :> Left, + HoldPattern[RSNB`horizontalRegion$$[2]] :> Center, + HoldPattern[RSNB`horizontalRegion$$[3]] :> Right + } + }, + { + DownValues[RSNB`verticalRegion$$] = { + HoldPattern[RSNB`verticalRegion$$[1]] :> Top, + HoldPattern[RSNB`verticalRegion$$[2]] :> Top, + HoldPattern[RSNB`verticalRegion$$[3]] :> Top + } + }, + { + DownValues[RSNB`chooseAttachLocation$$] = { + HoldPattern[RSNB`chooseAttachLocation$$[]] :> + With[ { RSNB`p$ = RSNB`mPosRegion$$[] }, + Apply[ + Sequence, + { + RSNB`offsetPos$$[RSNB`p$], + {-30, 30}, + RSNB`attachPos$$[RSNB`p$] + } + ] + ] + } + } + } + ], + BoxBaselineShift -> -0.5, + BoxMargins -> 0.2 + ] + ]) + } + ], + Cell[ + StyleData["ClickToCopyTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + PaneSelectorBox[ + { + False -> + TagBox[ + GridBox[ + { + { + #1, + ButtonBox[ + GraphicsBox[ + { + GrayLevel[0.85], + Thickness[NCache[2/45, 0.044444]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {10.5, 18.75}, + {10.5, 18.0}, + {9.0, 18.0}, + {9.0, 15.75}, + {13.5, 15.75}, + {13.5, 18.0}, + {12.0, 18.0}, + {12.0, 18.75} + }, + { + {6.0, 18.0}, + {6.0, 4.5}, + {16.5, 4.5}, + {16.5, 18.0}, + {14.25, 18.0}, + {14.25, 17.25}, + {15.75, 17.25}, + {15.75, 5.25}, + {6.75, 5.25}, + {6.75, 17.25}, + {8.25, 17.25}, + {8.25, 18.0} + }, + { + {9.75, 17.25}, + {12.75, 17.25}, + {12.75, 16.5}, + {9.75, 16.5} + } + } + ], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {8.25, 14.25}, + {14.25, 14.25}, + {14.25, 13.5}, + {8.25, 13.5} + }, + { + {8.25, 12.0}, + {14.25, 12.0}, + {14.25, 11.25}, + {8.25, 11.25} + }, + {{8.25, 9.75}, {14.25, 9.75}, {14.25, 9.0}, {8.25, 9.0}}, + {{8.25, 7.5}, {14.25, 7.5}, {14.25, 6.75}, {8.25, 6.75}} + } + ] + }, + ImageSize -> 12 + ], + ButtonFunction :> Null, + Appearance -> {"Default" -> None, "Hover" -> None, "Pressed" -> None}, + Evaluator -> Automatic, + Method -> "Preemptive" + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0.4}}} + ], + "Grid" + ], + True -> + DynamicModuleBox[ + {RSNB`clickTime$$ = 0.0, RSNB`timeout$$ = 3.0}, + TagBox[ + GridBox[ + { + { + #1, + TagBox[ + ButtonBox[ + DynamicBox[ + ToBoxes[ + Refresh[ + If[ AbsoluteTime[] - RSNB`clickTime$$ > RSNB`timeout$$, + RawBoxes[ + TemplateBox[ + { + PaneSelectorBox[ + { + False -> + GraphicsBox[ + { + GrayLevel[0.65], + Thickness[NCache[2/45, 0.044444]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {10.5, 18.75}, + {10.5, 18.0}, + {9.0, 18.0}, + {9.0, 15.75}, + {13.5, 15.75}, + {13.5, 18.0}, + {12.0, 18.0}, + {12.0, 18.75} + }, + { + {6.0, 18.0}, + {6.0, 4.5}, + {16.5, 4.5}, + {16.5, 18.0}, + {14.25, 18.0}, + {14.25, 17.25}, + {15.75, 17.25}, + {15.75, 5.25}, + {6.75, 5.25}, + {6.75, 17.25}, + {8.25, 17.25}, + {8.25, 18.0} + }, + { + {9.75, 17.25}, + {12.75, 17.25}, + {12.75, 16.5}, + {9.75, 16.5} + } + } + ], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {8.25, 14.25}, + {14.25, 14.25}, + {14.25, 13.5}, + {8.25, 13.5} + }, + { + {8.25, 12.0}, + {14.25, 12.0}, + {14.25, 11.25}, + {8.25, 11.25} + }, + {{8.25, 9.75}, {14.25, 9.75}, {14.25, 9.0}, {8.25, 9.0}}, + {{8.25, 7.5}, {14.25, 7.5}, {14.25, 6.75}, {8.25, 6.75}} + } + ] + }, + ImageSize -> 12 + ], + True -> + GraphicsBox[ + { + RGBColor[0.98824, 0.41961, 0.20392], + Thickness[NCache[2/45, 0.044444]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {10.5, 18.75}, + {10.5, 18.0}, + {9.0, 18.0}, + {9.0, 15.75}, + {13.5, 15.75}, + {13.5, 18.0}, + {12.0, 18.0}, + {12.0, 18.75} + }, + { + {6.0, 18.0}, + {6.0, 4.5}, + {16.5, 4.5}, + {16.5, 18.0}, + {14.25, 18.0}, + {14.25, 17.25}, + {15.75, 17.25}, + {15.75, 5.25}, + {6.75, 5.25}, + {6.75, 17.25}, + {8.25, 17.25}, + {8.25, 18.0} + }, + { + {9.75, 17.25}, + {12.75, 17.25}, + {12.75, 16.5}, + {9.75, 16.5} + } + } + ], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {8.25, 14.25}, + {14.25, 14.25}, + {14.25, 13.5}, + {8.25, 13.5} + }, + { + {8.25, 12.0}, + {14.25, 12.0}, + {14.25, 11.25}, + {8.25, 11.25} + }, + {{8.25, 9.75}, {14.25, 9.75}, {14.25, 9.0}, {8.25, 9.0}}, + {{8.25, 7.5}, {14.25, 7.5}, {14.25, 6.75}, {8.25, 6.75}} + } + ] + }, + ImageSize -> 12 + ] + }, + Dynamic[CurrentValue["MouseOver"]], + ImageSize -> Automatic, + FrameMargins -> 0 + ], + "\"Click to copy to the clipboard\"" + }, + "PrettyTooltipTemplate" + ] + ], + RawBoxes[ + TemplateBox[ + { + GraphicsBox[ + { + RGBColor[0, NCache[2/3, 0.66667], 0], + Thickness[NCache[2/45, 0.044444]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {10.5, 18.75}, + {10.5, 18.0}, + {9.0, 18.0}, + {9.0, 15.75}, + {13.5, 15.75}, + {13.5, 18.0}, + {12.0, 18.0}, + {12.0, 18.75} + }, + { + {6.0, 18.0}, + {6.0, 4.5}, + {16.5, 4.5}, + {16.5, 18.0}, + {14.25, 18.0}, + {14.25, 17.25}, + {15.75, 17.25}, + {15.75, 5.25}, + {6.75, 5.25}, + {6.75, 17.25}, + {8.25, 17.25}, + {8.25, 18.0} + }, + { + {9.75, 17.25}, + {12.75, 17.25}, + {12.75, 16.5}, + {9.75, 16.5} + } + } + ], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {8.25, 14.25}, + {14.25, 14.25}, + {14.25, 13.5}, + {8.25, 13.5} + }, + { + {8.25, 12.0}, + {14.25, 12.0}, + {14.25, 11.25}, + {8.25, 11.25} + }, + {{8.25, 9.75}, {14.25, 9.75}, {14.25, 9.0}, {8.25, 9.0}}, + {{8.25, 7.5}, {14.25, 7.5}, {14.25, 6.75}, {8.25, 6.75}} + } + ] + }, + ImageSize -> 12 + ], + "\"Copied\"" + }, + "PrettyTooltipTemplate" + ] + ] + ], + UpdateInterval -> 1, + TrackedSymbols :> {RSNB`clickTime$$} + ], + StandardForm + ], + Evaluator -> "System" + ], + ButtonFunction :> + (RSNB`clickTime$$ = AbsoluteTime[]; + CopyToClipboard[BinaryDeserialize[BaseDecode[#2], Defer]]), + Appearance -> {"Default" -> None, "Hover" -> None, "Pressed" -> None}, + Method -> "Queued", + Evaluator -> "System" + ], + MouseAppearanceTag["LinkHand"] + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0.4}}} + ], + "Grid" + ], + DynamicModuleValues :> { } + ] + }, + Dynamic[CurrentValue["MouseOver"]], + ImageSize -> Automatic, + FrameMargins -> 0 + ] + ]) + } + ], + Cell[ + StyleData["PrettyTooltipTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + TagBox[ + TooltipBox[ + #1, + FrameBox[ + StyleBox[ + #2, + "Text", + FontColor -> RGBColor[0.53725, 0.53725, 0.53725], + FontSize -> 12, + FontWeight -> "Plain", + FontTracking -> "Plain", + StripOnInput -> False + ], + Background -> RGBColor[0.96078, 0.96078, 0.96078], + FrameStyle -> RGBColor[0.89804, 0.89804, 0.89804], + FrameMargins -> 8, + StripOnInput -> False + ], + TooltipDelay -> 0.1, + TooltipStyle -> {Background -> None, CellFrame -> 0} + ], + Function[ + Annotation[ + #1, + Framed[ + Style[ + RSNB`$$tooltip, + "Text", + FontColor -> RGBColor[0.53725, 0.53725, 0.53725], + FontSize -> 12, + FontWeight -> "Plain", + FontTracking -> "Plain" + ], + Background -> RGBColor[0.96078, 0.96078, 0.96078], + FrameStyle -> RGBColor[0.89804, 0.89804, 0.89804], + FrameMargins -> 8 + ], + "Tooltip" + ] + ] + ] + ]) + } + ], + Cell[ + StyleData["ToolsGridTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + StyleBox[ + TagBox[ + GridBox[ + { + { + FrameBox[ + ButtonBox[ + TemplateBox[ + { + StyleBox[ + TagBox[ + GridBox[ + { + { + "\"Insert ResourceObject\"", + GraphicsBox[ + { + Thickness[0.05], + { + FaceForm[{GrayLevel[0.34902], Opacity[1.0]}], + FilledCurveBox[ + { + { + {1, 4, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3} + } + }, + { + { + {18.0, 17.5}, + {18.0, 18.328}, + {17.328, 19.0}, + {16.5, 19.0}, + {4.5, 19.0}, + {3.6716, 19.0}, + {3.0, 18.328}, + {3.0, 17.5}, + {3.0, 3.5}, + {3.0, 2.6716}, + {3.6716, 2.0}, + {4.5, 2.0}, + {16.5, 2.0}, + {17.328, 2.0}, + {18.0, 2.6716}, + {18.0, 3.5} + } + } + ] + }, + { + FaceForm[{GrayLevel[0.34902], Opacity[1.0]}], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + {{5.0, 12.0}, {5.0, 11.0}, {2.0, 11.0}, {2.0, 12.0}}, + {{2.0, 10.0}, {2.0, 9.0}, {5.0, 9.0}, {5.0, 10.0}}, + {{2.0, 14.0}, {2.0, 13.0}, {5.0, 13.0}, {5.0, 14.0}}, + {{2.0, 8.0}, {2.0, 7.0}, {5.0, 7.0}, {5.0, 8.0}}, + {{2.0, 6.0}, {2.0, 5.0}, {5.0, 5.0}, {5.0, 6.0}}, + { + {5.0, 18.0}, + {2.0, 18.0}, + {2.0, 17.0}, + {5.0, 17.0}, + {5.0, 18.0} + }, + { + {5.0, 4.0}, + {2.0, 4.0}, + {2.0, 3.0}, + {5.0, 3.0}, + {5.0, 4.0} + }, + {{2.0, 16.0}, {2.0, 15.0}, {5.0, 15.0}, {5.0, 16.0}} + } + ] + }, + { + FaceForm[{GrayLevel[1], Opacity[1.0]}], + FilledCurveBox[ + { + { + {0, 2, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3} + } + }, + { + { + {4.5, 18.0}, + {16.5, 18.0}, + {16.776, 18.0}, + {17.0, 17.776}, + {17.0, 17.5}, + {17.0, 3.5}, + {17.0, 3.2236}, + {16.776, 3.0}, + {16.5, 3.0}, + {4.5, 3.0}, + {4.2236, 3.0}, + {4.0, 3.2236}, + {4.0, 3.5}, + {4.0, 17.5}, + {4.0, 17.776}, + {4.2236, 18.0}, + {4.5, 18.0} + } + } + ] + }, + { + FaceForm[{RGBColor[0.86667, 0.06667, 0.0], Opacity[1.0]}], + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + CompressedData[ + "\n1:eJxTTMoPSmViYGAQAWIQrbtp7vvlx3QcGMBA1aH5wKmFrt/0He77907Pm6Th\nkCQQYbnFQ9shxRokoulw+KtGTP8hbQenhKcXlKL1HEIeL519JEHdASydpwPV\nr+Iw54jChiIPAwdlr+pm/R4luPyd643FbiEyDue/Bz9eCtTv8bBKZJ27rMOn\nS75JAjM0HZRyKqqWvhF2+FWXtadksoaDKlvjVGdvKbj7zq06fzUMKB8FclCu\nosMuTx4mbaD+qxUv1QwzFBwOrlji5xAs4+CSmf+h1VPcAey9biWH3LDadduU\npOHum/i2xt70npDDcW/zTkeg+yWmXuHMAMrD/Afxtzjc/w3bHZoepSvAw2fj\nw5dTN+UoOgAARNmGkQ==\n " + ], + { + {14.809, 9.3454}, + {13.744, 9.7099}, + {13.017, 10.654}, + {13.953, 10.307} + }, + { + {11.371, 7.1364}, + {10.712, 6.0044}, + {10.712, 7.177}, + {11.398, 8.1788} + }, + { + {9.8213, 12.979}, + {8.6908, 13.381}, + {8.0367, 14.264}, + {9.2241, 13.743} + }, + { + {11.738, 13.743}, + {12.925, 14.264}, + {12.271, 13.381}, + {11.141, 12.979} + }, + { + {13.177, 12.7}, + {12.603, 11.886}, + {12.637, 13.113}, + {13.309, 14.019} + }, + { + {10.481, 7.6484}, + {9.6004, 8.9331}, + {10.481, 10.128}, + {11.361, 8.9331} + }, + { + {8.8261, 11.306}, + {8.782, 12.866}, + {10.249, 12.344}, + {10.249, 10.826} + }, + { + {10.712, 12.344}, + {12.179, 12.866}, + {12.137, 11.306}, + {10.712, 10.826} + }, + { + {7.7855, 12.7}, + {7.6538, 14.019}, + {8.325, 13.113}, + {8.3587, 11.887} + }, + { + {10.114, 10.394}, + {9.2339, 9.2003}, + {7.7378, 9.6414}, + {8.6871, 10.875} + }, + { + {9.5648, 8.1792}, + {10.249, 7.177}, + {10.249, 6.004}, + {9.5887, 7.1366} + }, + { + {10.848, 10.394}, + {12.275, 10.875}, + {13.224, 9.6414}, + {11.728, 9.2003} + }, + { + {15.126, 12.009}, + {14.018, 10.766}, + {12.711, 11.252}, + {13.495, 12.364} + }, + { + {10.481, 15.384}, + {11.321, 13.946}, + {10.481, 12.872}, + {9.641, 13.946} + }, + { + {5.8362, 12.01}, + {7.467, 12.365}, + {8.2511, 11.252}, + {6.9436, 10.767} + }, + { + {7.009, 10.307}, + {7.9452, 10.655}, + {7.2182, 9.7099}, + {6.152, 9.3459} + }, + { + {6.2515, 8.9006}, + {7.3612, 9.2795}, + {8.5462, 8.9302}, + {7.5545, 8.6165} + }, + { + {7.776, 8.2109}, + {9.1027, 8.6306}, + {9.1365, 7.2193}, + {7.6098, 6.5491} + }, + { + {11.824, 7.219}, + {11.859, 8.6305}, + {13.185, 8.2104}, + {13.351, 6.5484} + }, + { + {13.407, 8.6159}, + {12.415, 8.9301}, + {13.6, 9.2795}, + {14.71, 8.8998} + } + } + ] + } + }, + AspectRatio -> Automatic, + ImageSize -> 12, + PlotRange -> {{0.0, 20.0}, {0.0, 20.0}}, + PlotRangePadding -> 0, + BaselinePosition -> Scaled[0.2] + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Center}}, "Rows" -> {{Baseline}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + "Grid" + ], + "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 11, + StripOnInput -> False + ], + "\"Insert an icon representing the ResourceObject\"" + }, + "PrettyTooltipTemplate" + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 4300058170245655723; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + + DefinitionNotebookClient`$ClickedButton = + "InsertResourceObject"; + + DefinitionNotebookClient`InsertResourceObjectIcon[ + ButtonNotebook[] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[4300058170245655723] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + FrameMargins -> {{4, 4}, {0, 0}}, + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + FEPrivate`If[ + CurrentValue["MouseOver"], + { + FontColor -> GrayLevel[1], + TaggingRules -> {"ButtonHovering" -> True} + }, + { + FontColor -> RGBColor[0.10588, 0.27059, 0.37255], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + { + FontColor -> RGBColor[0.77647, 0.81765, 0.84314], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + Evaluator -> "System" + ], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVan7pbXNXbT969tnrtxAEZANFgOJAWaAa\noEqshgDNh5gQUtL+6MVrrKEHFAfKQsyBuwfZEIgvgGoIRgTEHKB6NEOAIQbx\nBS43oLkH4i9IOMMNAYY8UBDoa4ImQABQJVA9UBeyIcAYBAoCQ49IQ4AqgeqB\nuoB6IakRyACmBKAgMBaINASoEqgeqAtiCBBQbghVXPKfemFCldihSjqhSoql\nVt6hSi6mVnkCBxSWbGQAghHxn7jSHgAhWAlh\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVcp7Jhqmt1iXTXZuWQxCQDRQBigNlgWqA\nKrEaAjQfYoJ6WLFL4zKvzg2YCCgOlIWYA3cPsiEQXwDVYNWOjCDmANWjGQIM\nMYgvcLkBzT0Qf0HCGW4IMOSBgkBfEzQBgoAqgeqBupANAcYgyKcl04k0BKgS\nqB6oC6gXkhqBDGBKAAoCY4FIQ4AqQS4Py4MYAgSUG0IVl1AxTKgSO1RJJ1RJ\nsdTKO1TJxdQqT+CAwpKNDEBMMU5MaQ8AQJMCGA==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJchr1+//vjx4/fv3//AAJANFAGKE2PI8+fPv3z5\ngsfZQFmgGjyGvHr16vfv30CR779+rzp+q3ndybhpOyEIyAaKAMWBskA1QJVY\nDQGaDzHh0sPXiTN2eXVuwERAcaAsxBy4e5ANgfgCqAardmQEMQeoHs0QYIhB\nfIHLDWjugfgLEs5wQ4AhD2QAfU3QBAgCqgSqB+pCNgQYg0AGMPSINASoEuTy\n79+BeiGpEcgApgQgAxgLRBoCVAlUD9QFMQQIKDeEKi6hYphQJXaokk6okmKp\nlXeokoupVZ7AAYUlGxkAj7PhgJjSHgDbEuv0\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> GrayLevel[0.9], + Method -> "Queued", + ImageSize -> {All, 20}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[GrayLevel[0.9], AbsoluteThickness[2]], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ], + FrameBox[ + ButtonBox[ + TemplateBox[ + { + StyleBox[ + "\"Template Input\"", + "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 11, + StripOnInput -> False + ], + "\"Format selection automatically using appropriate documentation styles\"" + }, + "PrettyTooltipTemplate" + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 2790153672590285854; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Template Input"; + DefinitionNotebookClient`TemplateInput[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[2790153672590285854] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + FrameMargins -> {{4, 4}, {0, 0}}, + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + FEPrivate`If[ + CurrentValue["MouseOver"], + { + FontColor -> GrayLevel[1], + TaggingRules -> {"ButtonHovering" -> True} + }, + { + FontColor -> RGBColor[0.10588, 0.27059, 0.37255], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + { + FontColor -> RGBColor[0.77647, 0.81765, 0.84314], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + Evaluator -> "System" + ], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVan7pbXNXbT969tnrtxAEZANFgOJAWaAa\noEqshgDNh5gQUtL+6MVrrKEHFAfKQsyBuwfZEIgvgGoIRgTEHKB6NEOAIQbx\nBS43oLkH4i9IOMMNAYY8UBDoa4ImQABQJVA9UBeyIcAYBAoCQ49IQ4AqgeqB\nuoB6IakRyACmBKAgMBaINASoEqgeqAtiCBBQbghVXPKfemFCldihSjqhSoql\nVt6hSi6mVnkCBxSWbGQAghHxn7jSHgAhWAlh\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVcp7Jhqmt1iXTXZuWQxCQDRQBigNlgWqA\nKrEaAjQfYoJ6WLFL4zKvzg2YCCgOlIWYA3cPsiEQXwDVYNWOjCDmANWjGQIM\nMYgvcLkBzT0Qf0HCGW4IMOSBgkBfEzQBgoAqgeqBupANAcYgyKcl04k0BKgS\nqB6oC6gXkhqBDGBKAAoCY4FIQ4AqQS4Py4MYAgSUG0IVl1AxTKgSO1RJJ1RJ\nsdTKO1TJxdQqT+CAwpKNDEBMMU5MaQ8AQJMCGA==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJchr1+//vjx4/fv3//AAJANFAGKE2PI8+fPv3z5\ngsfZQFmgGjyGvHr16vfv30CR779+rzp+q3ndybhpOyEIyAaKAMWBskA1QJVY\nDQGaDzHh0sPXiTN2eXVuwERAcaAsxBy4e5ANgfgCqAardmQEMQeoHs0QYIhB\nfIHLDWjugfgLEs5wQ4AhD2QAfU3QBAgCqgSqB+pCNgQYg0AGMPSINASoEuTy\n79+BeiGpEcgApgQgAxgLRBoCVAlUD9QFMQQIKDeEKi6hYphQJXaokk6okmKp\nlXeokoupVZ7AAYUlGxkAj7PhgJjSHgDbEuv0\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> GrayLevel[0.9], + Method -> "Queued", + ImageSize -> {All, 20}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[GrayLevel[0.9], AbsoluteThickness[2]], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ], + FrameBox[ + ButtonBox[ + TemplateBox[ + { + StyleBox[ + "\"Literal Input\"", + "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 11, + StripOnInput -> False + ], + "\"Format selection as literal Wolfram Language code\"" + }, + "PrettyTooltipTemplate" + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 4138174468017918531; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Literal Input"; + DefinitionNotebookClient`LiteralInput[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[4138174468017918531] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + FrameMargins -> {{4, 4}, {0, 0}}, + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + FEPrivate`If[ + CurrentValue["MouseOver"], + { + FontColor -> GrayLevel[1], + TaggingRules -> {"ButtonHovering" -> True} + }, + { + FontColor -> RGBColor[0.10588, 0.27059, 0.37255], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + { + FontColor -> RGBColor[0.77647, 0.81765, 0.84314], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + Evaluator -> "System" + ], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVan7pbXNXbT969tnrtxAEZANFgOJAWaAa\noEqshgDNh5gQUtL+6MVrrKEHFAfKQsyBuwfZEIgvgGoIRgTEHKB6NEOAIQbx\nBS43oLkH4i9IOMMNAYY8UBDoa4ImQABQJVA9UBeyIcAYBAoCQ49IQ4AqgeqB\nuoB6IakRyACmBKAgMBaINASoEqgeqAtiCBBQbghVXPKfemFCldihSjqhSoql\nVt6hSi6mVnkCBxSWbGQAghHxn7jSHgAhWAlh\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVcp7Jhqmt1iXTXZuWQxCQDRQBigNlgWqA\nKrEaAjQfYoJ6WLFL4zKvzg2YCCgOlIWYA3cPsiEQXwDVYNWOjCDmANWjGQIM\nMYgvcLkBzT0Qf0HCGW4IMOSBgkBfEzQBgoAqgeqBupANAcYgyKcl04k0BKgS\nqB6oC6gXkhqBDGBKAAoCY4FIQ4AqQS4Py4MYAgSUG0IVl1AxTKgSO1RJJ1RJ\nsdTKO1TJxdQqT+CAwpKNDEBMMU5MaQ8AQJMCGA==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJchr1+//vjx4/fv3//AAJANFAGKE2PI8+fPv3z5\ngsfZQFmgGjyGvHr16vfv30CR779+rzp+q3ndybhpOyEIyAaKAMWBskA1QJVY\nDQGaDzHh0sPXiTN2eXVuwERAcaAsxBy4e5ANgfgCqAardmQEMQeoHs0QYIhB\nfIHLDWjugfgLEs5wQ4AhD2QAfU3QBAgCqgSqB+pCNgQYg0AGMPSINASoEuTy\n79+BeiGpEcgApgQgAxgLRBoCVAlUD9QFMQQIKDeEKi6hYphQJXaokk6okmKp\nlXeokoupVZ7AAYUlGxkAj7PhgJjSHgDbEuv0\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> GrayLevel[0.9], + Method -> "Queued", + ImageSize -> {All, 20}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[GrayLevel[0.9], AbsoluteThickness[2]], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ], + FrameBox[ + ButtonBox[ + TemplateBox[ + { + StyleBox[ + "\"Insert Delimiter\"", + "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 11, + StripOnInput -> False + ], + "\"Insert example delimiter\"" + }, + "PrettyTooltipTemplate" + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 1887802176716758884; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + + DefinitionNotebookClient`$ClickedButton = + "Insert Delimiter"; + + DefinitionNotebookClient`DelimiterInsert[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[1887802176716758884] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + FrameMargins -> {{4, 4}, {0, 0}}, + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + FEPrivate`If[ + CurrentValue["MouseOver"], + { + FontColor -> GrayLevel[1], + TaggingRules -> {"ButtonHovering" -> True} + }, + { + FontColor -> RGBColor[0.10588, 0.27059, 0.37255], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + { + FontColor -> RGBColor[0.77647, 0.81765, 0.84314], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + Evaluator -> "System" + ], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVan7pbXNXbT969tnrtxAEZANFgOJAWaAa\noEqshgDNh5gQUtL+6MVrrKEHFAfKQsyBuwfZEIgvgGoIRgTEHKB6NEOAIQbx\nBS43oLkH4i9IOMMNAYY8UBDoa4ImQABQJVA9UBeyIcAYBAoCQ49IQ4AqgeqB\nuoB6IakRyACmBKAgMBaINASoEqgeqAtiCBBQbghVXPKfemFCldihSjqhSoql\nVt6hSi6mVnkCBxSWbGQAghHxn7jSHgAhWAlh\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVcp7Jhqmt1iXTXZuWQxCQDRQBigNlgWqA\nKrEaAjQfYoJ6WLFL4zKvzg2YCCgOlIWYA3cPsiEQXwDVYNWOjCDmANWjGQIM\nMYgvcLkBzT0Qf0HCGW4IMOSBgkBfEzQBgoAqgeqBupANAcYgyKcl04k0BKgS\nqB6oC6gXkhqBDGBKAAoCY4FIQ4AqQS4Py4MYAgSUG0IVl1AxTKgSO1RJJ1RJ\nsdTKO1TJxdQqT+CAwpKNDEBMMU5MaQ8AQJMCGA==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJchr1+//vjx4/fv3//AAJANFAGKE2PI8+fPv3z5\ngsfZQFmgGjyGvHr16vfv30CR779+rzp+q3ndybhpOyEIyAaKAMWBskA1QJVY\nDQGaDzHh0sPXiTN2eXVuwERAcaAsxBy4e5ANgfgCqAardmQEMQeoHs0QYIhB\nfIHLDWjugfgLEs5wQ4AhD2QAfU3QBAgCqgSqB+pCNgQYg0AGMPSINASoEuTy\n79+BeiGpEcgApgQgAxgLRBoCVAlUD9QFMQQIKDeEKi6hYphQJXaokk6okmKp\nlXeokoupVZ7AAYUlGxkAj7PhgJjSHgDbEuv0\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> GrayLevel[0.9], + Method -> "Queued", + ImageSize -> {All, 20}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[GrayLevel[0.9], AbsoluteThickness[2]], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ], + ActionMenuBox[ + FrameBox[ + ButtonBox[ + TemplateBox[ + { + StyleBox[ + TemplateBox[ + { + "\"Tables\"", + "\"\[ThinSpace]\[ThinSpace]\[ThinSpace]\[FilledDownTriangle]\"" + }, + "RowDefault" + ], + "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 11, + StripOnInput -> False + ], + "\"Table functions\"" + }, + "PrettyTooltipTemplate" + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 3216557251994556740; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = HoldForm[Null] + ] + ], + DefinitionNotebookClient`ButtonCodeID[3216557251994556740] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + FrameMargins -> {{4, 4}, {0, 0}}, + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + FEPrivate`If[ + CurrentValue["MouseOver"], + { + FontColor -> GrayLevel[1], + TaggingRules -> {"ButtonHovering" -> True} + }, + { + FontColor -> RGBColor[0.10588, 0.27059, 0.37255], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + { + FontColor -> RGBColor[0.77647, 0.81765, 0.84314], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + Evaluator -> "System" + ], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVan7pbXNXbT969tnrtxAEZANFgOJAWaAa\noEqshgDNh5gQUtL+6MVrrKEHFAfKQsyBuwfZEIgvgGoIRgTEHKB6NEOAIQbx\nBS43oLkH4i9IOMMNAYY8UBDoa4ImQABQJVA9UBeyIcAYBAoCQ49IQ4AqgeqB\nuoB6IakRyACmBKAgMBaINASoEqgeqAtiCBBQbghVXPKfemFCldihSjqhSoql\nVt6hSi6mVnkCBxSWbGQAghHxn7jSHgAhWAlh\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVcp7Jhqmt1iXTXZuWQxCQDRQBigNlgWqA\nKrEaAjQfYoJ6WLFL4zKvzg2YCCgOlIWYA3cPsiEQXwDVYNWOjCDmANWjGQIM\nMYgvcLkBzT0Qf0HCGW4IMOSBgkBfEzQBgoAqgeqBupANAcYgyKcl04k0BKgS\nqB6oC6gXkhqBDGBKAAoCY4FIQ4AqQS4Py4MYAgSUG0IVl1AxTKgSO1RJJ1RJ\nsdTKO1TJxdQqT+CAwpKNDEBMMU5MaQ8AQJMCGA==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJchr1+//vjx4/fv3//AAJANFAGKE2PI8+fPv3z5\ngsfZQFmgGjyGvHr16vfv30CR779+rzp+q3ndybhpOyEIyAaKAMWBskA1QJVY\nDQGaDzHh0sPXiTN2eXVuwERAcaAsxBy4e5ANgfgCqAardmQEMQeoHs0QYIhB\nfIHLDWjugfgLEs5wQ4AhD2QAfU3QBAgCqgSqB+pCNgQYg0AGMPSINASoEuTy\n79+BeiGpEcgApgQgAxgLRBoCVAlUD9QFMQQIKDeEKi6hYphQJXaokk6okmKp\nlXeokoupVZ7AAYUlGxkAj7PhgJjSHgDbEuv0\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> GrayLevel[0.9], + Method -> "Queued", + ImageSize -> {All, 20}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[GrayLevel[0.9], AbsoluteThickness[2]], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ], + { + "\"Insert table with two columns\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 5800166344906378520; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Tables"; + + DefinitionNotebookClient`$ClickedAction = + "Insert table with two columns"; + + DefinitionNotebookClient`TableInsert[2] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[5800166344906378520] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Insert table with three columns\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + DefinitionNotebookClient`$ButtonCodeID = 533841403879783297; + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Tables"; + + DefinitionNotebookClient`$ClickedAction = + "Insert table with three columns"; + + DefinitionNotebookClient`TableInsert[3] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[533841403879783297] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Add a row to the selected table\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 4413051590217973467; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Tables"; + + DefinitionNotebookClient`$ClickedAction = + "Add a row to the selected table"; + + DefinitionNotebookClient`TableRowInsert[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[4413051590217973467] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Sort the selected table\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 9150037060110806081; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Tables"; + + DefinitionNotebookClient`$ClickedAction = + "Sort the selected table"; + + DefinitionNotebookClient`TableSort[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[9150037060110806081] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Merge selected tables\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 2347719643166780208; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Tables"; + + DefinitionNotebookClient`$ClickedAction = + "Merge selected tables"; + + DefinitionNotebookClient`TableMerge[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[2347719643166780208] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ] + }, + Appearance -> None, + Method -> "Queued" + ], + ActionMenuBox[ + FrameBox[ + ButtonBox[ + StyleBox[ + TemplateBox[ + { + "\"Cells\"", + "\"\[ThinSpace]\[ThinSpace]\[ThinSpace]\[FilledDownTriangle]\"" + }, + "RowDefault" + ], + "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 11, + StripOnInput -> False + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 3216557251994556740; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = HoldForm[Null] + ] + ], + DefinitionNotebookClient`ButtonCodeID[3216557251994556740] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + FrameMargins -> {{4, 4}, {0, 0}}, + BaseStyle -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + FEPrivate`If[ + CurrentValue["MouseOver"], + { + FontColor -> GrayLevel[1], + TaggingRules -> {"ButtonHovering" -> True} + }, + { + FontColor -> RGBColor[0.10588, 0.27059, 0.37255], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + { + FontColor -> RGBColor[0.77647, 0.81765, 0.84314], + TaggingRules -> {"ButtonHovering" -> False} + } + ], + Evaluator -> "System" + ], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVan7pbXNXbT969tnrtxAEZANFgOJAWaAa\noEqshgDNh5gQUtL+6MVrrKEHFAfKQsyBuwfZEIgvgGoIRgTEHKB6NEOAIQbx\nBS43oLkH4i9IOMMNAYY8UBDoa4ImQABQJVA9UBeyIcAYBAoCQ49IQ4AqgeqB\nuoB6IakRyACmBKAgMBaINASoEqgeqAtiCBBQbghVXPKfemFCldihSjqhSoql\nVt6hSi6mVnkCBxSWbGQAghHxn7jSHgAhWAlh\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJche4+e6pyzIrq80zAsD4KAbKAIUJwYQx48fFTS\nM0vaNR4XAsoC1eAx5PCpc9ZxJUCVcp7Jhqmt1iXTXZuWQxCQDRQBigNlgWqA\nKrEaAjQfYoJ6WLFL4zKvzg2YCCgOlIWYA3cPsiEQXwDVYNWOjCDmANWjGQIM\nMYgvcLkBzT0Qf0HCGW4IMOSBgkBfEzQBgoAqgeqBupANAcYgyKcl04k0BKgS\nqB6oC6gXkhqBDGBKAAoCY4FIQ4AqQS4Py4MYAgSUG0IVl1AxTKgSO1RJJ1RJ\nsdTKO1TJxdQqT+CAwpKNDEBMMU5MaQ8AQJMCGA==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqA4BllAJchr1+//vjx4/fv3//AAJANFAGKE2PI8+fPv3z5\ngsfZQFmgGjyGvHr16vfv30CR779+rzp+q3ndybhpOyEIyAaKAMWBskA1QJVY\nDQGaDzHh0sPXiTN2eXVuwERAcaAsxBy4e5ANgfgCqAardmQEMQeoHs0QYIhB\nfIHLDWjugfgLEs5wQ4AhD2QAfU3QBAgCqgSqB+pCNgQYg0AGMPSINASoEuTy\n79+BeiGpEcgApgQgAxgLRBoCVAlUD9QFMQQIKDeEKi6hYphQJXaokk6okmKp\nlXeokoupVZ7AAYUlGxkAj7PhgJjSHgDbEuv0\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> GrayLevel[0.9], + Method -> "Queued", + ImageSize -> {All, 20}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[GrayLevel[0.9], AbsoluteThickness[2]], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ], + { + "\"Insert comment for reviewer\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 2572781756330727330; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Cells"; + + DefinitionNotebookClient`$ClickedAction = + "Insert comment for reviewer"; + + DefinitionNotebookClient`CommentInsert[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[2572781756330727330] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Mark/unmark selected cells as comments\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 3646530685697756512; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Cells"; + + DefinitionNotebookClient`$ClickedAction = + "Mark/unmark selected cells as comments"; + + DefinitionNotebookClient`CommentToggle[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[3646530685697756512] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Mark/unmark selected cells as excluded\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 1866935765212102190; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Cells"; + + DefinitionNotebookClient`$ClickedAction = + "Mark/unmark selected cells as excluded"; + + DefinitionNotebookClient`ExclusionToggle[] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[1866935765212102190] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ] + }, + Appearance -> None, + Method -> "Queued" + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxBackground -> {"Columns" -> {{None}}, "Rows" -> {GrayLevel[0.9]}}, + GridBoxFrame -> { + "Columns" -> False, + "RowsIndexed" -> {1 -> GrayLevel[0.9]} + }, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {5, {0.5}, 5}, "Rows" -> {{Automatic}}}, + FrameStyle -> GrayLevel[0.75] + ], + "Grid" + ], + ButtonBoxOptions -> { + Enabled -> + Dynamic[ + Not[TrueQ[DefinitionNotebookClient`$ButtonsDisabled]], + TrackedSymbols :> {DefinitionNotebookClient`$ButtonsDisabled} + ] + }, + StripOnInput -> False + ] + ]) + } + ], + Cell[ + StyleData["MainGridTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + StyleBox[ + TagBox[ + GridBox[ + { + { + TagBox[ + GridBox[ + { + { + GraphicsBox[ + { + Thickness[0.02963], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBWIWIGZigIIGBQcwfUAPQjOoYuc3CDugqIfxGTQg9ANj\nqLgOdj66erh5+lD7oPYwGGHno6uH86H2PDCA6jPFzkdXD+M7mENpLai4JXY+\nunogHwDQSSTa\n " + ] + ] + }, + {FaceForm[RGBColor[1.0, 1.0, 1.0, 1.0]]}, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {0.75, 1.875}, + {33.0, 1.875}, + {33.0, 0.375}, + {0.75, 0.375} + }, + { + {27.0, 19.875}, + {29.25, 19.875}, + {29.25, 4.875}, + {27.0, 4.875} + }, + { + {3.0, 4.125}, + {30.75, 4.125}, + {30.75, 2.625}, + {3.0, 2.625} + }, + { + {16.875, 32.625}, + {0.0, 24.375}, + {0.0, 22.875}, + {33.75, 22.875}, + {33.75, 24.375} + }, + {{3.75, 24.375}, {16.875, 30.75}, {30.0, 24.375}}, + { + {25.5, 22.125}, + {30.75, 22.125}, + {30.75, 20.625}, + {25.5, 20.625} + }, + { + {4.5, 19.875}, + {6.75, 19.875}, + {6.75, 4.875}, + {4.5, 4.875} + }, + { + {3.0, 22.125}, + {8.25, 22.125}, + {8.25, 20.625}, + {3.0, 20.625} + } + } + ] + }, + {FaceForm[RGBColor[0.843, 0.847, 0.847, 1.0]]}, + StripOnInput -> False + ] + }, + { + ImageSize -> {Automatic, 32}, + ImagePadding -> {{5, 0}, {0, 0}}, + BaselinePosition -> Scaled[0.25], + Background -> RGBColor[0.2902, 0.53725, 0.6902], + ImageSize -> {45.0, Automatic}, + PlotRange -> {{0.0, 33.75}, {0.0, 33.0}}, + AspectRatio -> Automatic + } + ], + StyleBox[ + TagBox[ + GridBox[ + { + { + StyleBox[ + "\"Data Resource\"", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + StripOnInput -> False + ], + StyleBox[ + "\"DEFINITION NOTEBOOK\"", + FontFamily -> "Source Sans Pro", + FontTracking -> "SemiCondensed", + FontVariations -> {"CapsType" -> "AllSmallCaps"}, + StripOnInput -> False + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Baseline}}}, + AutoDelete -> False, + GridBoxDividers -> { + "ColumnsIndexed" -> {2 -> RGBColor[1.0, 1.0, 1.0]}, + "Rows" -> {{None}} + }, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Grid" + ], + FontSize -> 24, + FontColor -> RGBColor[1.0, 1.0, 1.0], + StripOnInput -> False + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Baseline}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}} + ], + "Grid" + ], + "\[SpanFromLeft]", + "\[SpanFromLeft]", + "\[SpanFromLeft]", + "\[SpanFromLeft]", + "\[SpanFromLeft]", + "\[SpanFromLeft]", + TemplateBox[ + { + StyleBox[ + TemplateBox[ + {"\"Data Repository\"", "\" \[RightGuillemet] \""}, + "RowDefault" + ], + "Text", + FontColor -> RGBColor[1.0, 1.0, 1.0], + StripOnInput -> False + ], + "https://datarepository.wolframcloud.com/" + }, + "HyperlinkURL" + ] + }, + { + TemplateBox[ + { + TemplateBox[ + { + "\"Open Sample\"", + "\"View a completed sample definition notebook\"" + }, + "PrettyTooltipTemplate" + ], + Function[ + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 4393071033038384034; + + (DefinitionNotebookClient`$ClickedButton = "Open Sample"; + DefinitionNotebookClient`ViewExampleNotebook[ + ButtonNotebook[] + ]), + DefinitionNotebookClient`ButtonCodeID[4393071033038384034] + ] + ], + "\"View a completed sample definition notebook\"", + False + }, + "OrangeButtonTemplate" + ], + TemplateBox[ + { + TemplateBox[ + { + "\"Style Guidelines\"", + "\"View general guidelines for authoring data resources\"" + }, + "PrettyTooltipTemplate" + ], + Function[ + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 5906117565281445171; + + ( + DefinitionNotebookClient`$ClickedButton = + "Style Guidelines"; + + DefinitionNotebookClient`ViewStyleGuidelines[ + ButtonNotebook[] + ]), + DefinitionNotebookClient`ButtonCodeID[5906117565281445171] + ] + ], + "\"View general guidelines for authoring data resources\"", + False + }, + "OrangeButtonTemplate" + ], + TemplateBox[ + { + TemplateBox[ + { + TagBox[ + GridBox[ + { + { + "\"Tools\"", + PaneSelectorBox[ + { + False -> + GraphicsBox[ + { + RGBColor[1.0, 1.0, 1.0], + AbsoluteThickness[1.0], + LineBox[{{0, 0}, {0, 10}, {10, 10}, {10, 0}, {0, 0}}], + LineBox[{{5, 2.5}, {5, 7.5}}], + LineBox[{{2.5, 5}, {7.5, 5}}] + }, + ImageSize -> 12, + PlotRangePadding -> 1.5 + ], + True -> + GraphicsBox[ + { + RGBColor[1.0, 1.0, 1.0], + AbsoluteThickness[1.0], + LineBox[{{0, 0}, {0, 10}, {10, 10}, {10, 0}, {0, 0}}], + LineBox[{{2.5, 5}, {7.5, 5}}] + }, + ImageSize -> 12, + PlotRangePadding -> 1.5 + ] + }, + Dynamic[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "ToolsOpen"}, + True + ] + ], + BaselinePosition -> Scaled[0.05] + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Baseline}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0.35}}} + ], + "Grid" + ], + "\"Toggle documentation toolbar\"" + }, + "PrettyTooltipTemplate" + ], + Function[ + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 5074018684552945401; + + (DefinitionNotebookClient`$ClickedButton = "Tools"; + DefinitionNotebookClient`ToggleToolbar[ButtonNotebook[]]), + DefinitionNotebookClient`ButtonCodeID[5074018684552945401] + ] + ], + "\"Toggle documentation toolbar\"", + False + }, + "OrangeButtonTemplate" + ], + TagBox[ + GridBox[ + {{"\"\"", "\"\""}}, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxDividers -> {"ColumnsIndexed" -> {2 -> True}, "Rows" -> {{False}}}, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{2}}}, + GridBoxSpacings -> {"Columns" -> {{0.5}}}, + FrameStyle -> RGBColor[0.6451, 0.76863, 0.8451] + ], + "Grid" + ], + ActionMenuBox[ + TemplateBox[ + { + TemplateBox[ + { + TemplateBox[ + { + "\"Check\"", + TemplateBox[{5}, "Spacer1"], + "\"\[FilledDownTriangle]\"" + }, + "RowDefault" + ], + "\"Check notebook for potential errors\"" + }, + "PrettyTooltipTemplate" + ], + Function[ + Annotation[ + DefinitionNotebookClient`$ButtonCodeID = + 1898445052439169298;, + DefinitionNotebookClient`ButtonCodeID[1898445052439169298] + ] + ], + "\"Check notebook for potential errors\"", + True + }, + "OrangeButtonTemplate" + ], + { + "\"Check Definition Notebook\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 7315505126975123932; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Check"; + + DefinitionNotebookClient`$ClickedAction = + "Check Definition Notebook"; + + DefinitionNotebookClient`CheckDefinitionNotebook[ + ButtonNotebook[] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[7315505126975123932] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Check Data\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 5678342563549764489; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Check"; + DefinitionNotebookClient`$ClickedAction = "Check Data"; + DataResource`DefinitionNotebook`CheckDataDefinitions[ + ButtonNotebook[] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[5678342563549764489] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Check All\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 7222533872454612108; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Check"; + DefinitionNotebookClient`$ClickedAction = "Check All"; + ( + DefinitionNotebookClient`CheckDefinitionNotebook[ + ButtonNotebook[] + ]; + + DataResource`DefinitionNotebook`CheckDataDefinitions[ + ButtonNotebook[] + ]) + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[7222533872454612108] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ] + }, + Appearance -> None, + Method -> "Queued" + ], + ActionMenuBox[ + TemplateBox[ + { + TemplateBox[ + { + "\"Deploy\"", + TemplateBox[{5}, "Spacer1"], + "\"\[FilledDownTriangle]\"" + }, + "RowDefault" + ], + Function[ + Annotation[ + DefinitionNotebookClient`$ButtonCodeID = + 1898445052439169298;, + DefinitionNotebookClient`ButtonCodeID[1898445052439169298] + ] + ], + "\"\"", + True + }, + "OrangeButtonTemplate" + ], + { + "\"Locally on this computer\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 8714502586816766511; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Deploy"; + + DefinitionNotebookClient`$ClickedAction = + "Locally on this computer"; + + DefinitionNotebookClient`DisplayStripe[ + ButtonNotebook[], + DefinitionNotebookClient`DeployResource[ + ButtonNotebook[], + "Local" + ] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[8714502586816766511] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"For my cloud account\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 1389539917011878958; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Deploy"; + + DefinitionNotebookClient`$ClickedAction = + "For my cloud account"; + + DefinitionNotebookClient`DisplayStripe[ + ButtonNotebook[], + DefinitionNotebookClient`DeployResource[ + ButtonNotebook[], + "CloudPrivate" + ] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[1389539917011878958] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"Publicly in the cloud\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 5593410685219912767; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Deploy"; + + DefinitionNotebookClient`$ClickedAction = + "Publicly in the cloud"; + + DefinitionNotebookClient`DisplayStripe[ + ButtonNotebook[], + DefinitionNotebookClient`DeployResource[ + ButtonNotebook[], + "CloudPublic" + ] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[5593410685219912767] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + "\"In this session only (without documentation)\"" :> + With[ { RSNB`nb$ = InputNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$SuppressDynamicEvents = True, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"]; + + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 8586347731213964380; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + DefinitionNotebookClient`$ClickedButton = "Deploy"; + + DefinitionNotebookClient`$ClickedAction = + "In this session only (without documentation)"; + + DefinitionNotebookClient`DisplayStripe[ + ButtonNotebook[], + DefinitionNotebookClient`DeployResource[ + ButtonNotebook[], + "KernelSession" + ] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[8586347731213964380] + ], + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ] + }, + Appearance -> None, + Method -> "Queued" + ], + ItemBox[ + StyleBox[ + DynamicBox[ + ToBoxes[ + CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "StatusMessage"}, + "" + ], + StandardForm + ], + Initialization :> + (CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "StatusMessage"} + ] = + "") + ], + "Text", + GrayLevel[1], + StripOnInput -> False + ], + ItemSize -> Fit, + StripOnInput -> False + ], + DynamicBox[ + ToBoxes[ + If[ CurrentValue[ + EvaluationNotebook[], + {TaggingRules, "SubmissionReviewData", "Review"}, + False + ], + RawBoxes[ + TemplateBox[ + { + TemplateBox[ + { + TagBox[ + GridBox[ + { + { + GraphicsBox[ + { + Thickness[0.06349], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBWIWIGZigIEX9mCqQd8Bwv+Bnc/A54CiHs5HV6/ngJUP\np2HmwdTp4FCHTvOhqYfZrw2lhdDk0fno6tHcD1PPwOSAnY+uns8BAE8cGz4=\n\n " + ] + ] + }, + {FaceForm[RGBColor[1.0, 1.0, 1.0]]}, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgB2IWIGZigAEJBwjNB6EblHHwX9ijqofxoeoYhKC0Bg4+\nHw4apk4Uap8aDr4QDhqqDu4uVRx8URw0TJ001D5lHHwJHDRUHYMclFbCwZfG\nQUPVNSjgp+HmIWgAG/wcEg==\n " + ] + ], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJx10EEKgCAQhWGpFtEyEAYGggQj6RKeoSMErbuCR0/IWfTgCcPwy7fR9XrO\nu3fOTXWGOp2zM+ZvH2170nv+e2sFH0ijt45/XxJp9NgRPHYAb63kHhu9tf2H\neU8aPfbS9kxawAvxnrSCx3c3XzbS6JX4RFrAS34B53ckaw==\n " + ] + ] + }, + {FaceForm[RGBColor[1.0, 1.0, 1.0]]}, + StripOnInput -> False + ] + }, + ImageSize -> 15, + PlotRange -> {{0.0, 15.75}, {0.0, 16.5}}, + AspectRatio -> 1.15 + ], + "\"Submit Update\"" + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> { + "Columns" -> {{0}}, + "ColumnsIndexed" -> {2 -> 0.5}, + "Rows" -> {{0}} + } + ], + "Grid" + ], + "\"Submit changes to update your data submission\"" + }, + "PrettyTooltipTemplate" + ], + Function[ + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 3196298050911436087; + + (DefinitionNotebookClient`$ClickedButton = "SubmitUpdate"; + With[ { RSNB`nb = ButtonNotebook[] }, + DefinitionNotebookClient`DisplayStripe[ + RSNB`nb, + DefinitionNotebookClient`SubmitRepositoryUpdate[RSNB`nb], + "ShowProgress" -> True + ] + ]), + DefinitionNotebookClient`ButtonCodeID[3196298050911436087] + ] + ], + "\"Submit changes to update your data submission\"", + True + }, + "OrangeButtonTemplate" + ] + ], + RawBoxes[ + TemplateBox[ + { + TemplateBox[ + { + TagBox[ + GridBox[ + { + { + GraphicsBox[ + { + Thickness[0.06349], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBWIWIGZigIEX9mCqQd8Bwv+Bnc/A54CiHs5HV6/ngJUP\np2HmwdTp4FCHTvOhqYfZrw2lhdDk0fno6tHcD1PPwOSAnY+uns8BAE8cGz4=\n\n " + ] + ] + }, + {FaceForm[RGBColor[1.0, 1.0, 1.0]]}, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgB2IWIGZigAEJBwjNB6EblHHwX9ijqofxoeoYhKC0Bg4+\nHw4apk4Uap8aDr4QDhqqDu4uVRx8URw0TJ001D5lHHwJHDRUHYMclFbCwZfG\nQUPVNSjgp+HmIWgAG/wcEg==\n " + ] + ], + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJx10EEKgCAQhWGpFtEyEAYGggQj6RKeoSMErbuCR0/IWfTgCcPwy7fR9XrO\nu3fOTXWGOp2zM+ZvH2170nv+e2sFH0ijt45/XxJp9NgRPHYAb63kHhu9tf2H\neU8aPfbS9kxawAvxnrSCx3c3XzbS6JX4RFrAS34B53ckaw==\n " + ] + ] + }, + {FaceForm[RGBColor[1.0, 1.0, 1.0]]}, + StripOnInput -> False + ] + }, + ImageSize -> 15, + PlotRange -> {{0.0, 15.75}, {0.0, 16.5}}, + AspectRatio -> 1.15 + ], + "\"Submit to Repository\"" + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> { + "Columns" -> {{0}}, + "ColumnsIndexed" -> {2 -> 0.5}, + "Rows" -> {{0}} + } + ], + "Grid" + ], + "\"Submit your data to the Wolfram Data Repository\"" + }, + "PrettyTooltipTemplate" + ], + Function[ + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 3704832848557640569; + + (DefinitionNotebookClient`$ClickedButton = "Submit"; + With[ { RSNB`nb = ButtonNotebook[] }, + DefinitionNotebookClient`DisplayStripe[ + RSNB`nb, + DefinitionNotebookClient`SubmitRepository[RSNB`nb], + "ShowProgress" -> True + ] + ]), + DefinitionNotebookClient`ButtonCodeID[3704832848557640569] + ] + ], + "\"Submit your data to the Wolfram Data Repository\"", + True + }, + "OrangeButtonTemplate" + ] + ] + ], + StandardForm + ], + Evaluator -> "System", + SingleEvaluation -> True + ] + } + }, + GridBoxAlignment -> { + "Columns" -> {{Left}}, + "ColumnsIndexed" -> {-1 -> Right}, + "Rows" -> {{Center}} + }, + AutoDelete -> False, + GridBoxBackground -> { + "Columns" -> {{None}}, + "Rows" -> { + RGBColor[0.2902, 0.53725, 0.6902], + RGBColor[0.16078, 0.40392, 0.56078] + } + }, + GridBoxFrame -> { + "Columns" -> False, + "RowsIndexed" -> { + 1 -> RGBColor[0.2902, 0.53725, 0.6902], + 2 -> RGBColor[0.16078, 0.40392, 0.56078] + } + }, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> { + "Columns" -> {5, {0.9}, 5}, + "RowsIndexed" -> {1 -> 1.1, 2 -> 1.3, 3 -> 0.25} + }, + FrameStyle -> RGBColor[0.2902, 0.53725, 0.6902] + ], + "Grid" + ], + ButtonBoxOptions -> { + Enabled -> + Dynamic[ + Not[TrueQ[DefinitionNotebookClient`$ButtonsDisabled]], + TrackedSymbols :> {DefinitionNotebookClient`$ButtonsDisabled} + ] + }, + StripOnInput -> False + ] + ]) + } + ], + Cell[ + StyleData["ReviewerCommentLabelTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + TagBox[ + GridBox[ + { + { + #1, + TemplateBox[ + { + GraphicsBox[ + { + Thickness[0.02963], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBWIWIGZigIIGBQcwfUAPQjOoYuc3CDugqIfxGTQg9ANj\nqLgOdj66erh5+lD7oPYwGGHno6uH86H2PDCA6jPFzkdXD+M7mENpLai4JXY+\nunogHwDQSSTa\n " + ] + ] + }, + {FaceForm[RGBColor[1.0, 1.0, 1.0, 1.0]]}, + StripOnInput -> False + ], + StyleBox[ + { + FilledCurveBox[ + { + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}}, + {{0, 2, 0}, {0, 1, 0}, {0, 1, 0}} + }, + { + { + {0.75, 1.875}, + {33.0, 1.875}, + {33.0, 0.375}, + {0.75, 0.375} + }, + { + {27.0, 19.875}, + {29.25, 19.875}, + {29.25, 4.875}, + {27.0, 4.875} + }, + { + {3.0, 4.125}, + {30.75, 4.125}, + {30.75, 2.625}, + {3.0, 2.625} + }, + { + {16.875, 32.625}, + {0.0, 24.375}, + {0.0, 22.875}, + {33.75, 22.875}, + {33.75, 24.375} + }, + {{3.75, 24.375}, {16.875, 30.75}, {30.0, 24.375}}, + { + {25.5, 22.125}, + {30.75, 22.125}, + {30.75, 20.625}, + {25.5, 20.625} + }, + { + {4.5, 19.875}, + {6.75, 19.875}, + {6.75, 4.875}, + {4.5, 4.875} + }, + { + {3.0, 22.125}, + {8.25, 22.125}, + {8.25, 20.625}, + {3.0, 20.625} + } + } + ] + }, + {FaceForm[RGBColor[0.843, 0.847, 0.847, 1.0]]}, + StripOnInput -> False + ] + }, + { + ImageSize -> 12, + Background -> None, + ImageSize -> {45.0, Automatic}, + PlotRange -> {{0.0, 33.75}, {0.0, 33.0}}, + AspectRatio -> Automatic + } + ], + "Wolfram Data Repository Reviewer" + }, + "PrettyTooltipTemplate" + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Automatic}}, "Rows" -> {{Center}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0.25}}} + ], + "Grid" + ] + ]) + } + ], + Cell[ + StyleData["CommentReplyIcon"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + Thickness[0.076923], + FaceForm[{#1, Opacity[1.0]}], + FilledCurveBox[ + {{{0, 2, 0}, {0, 1, 0}}}, + {{{1.5, 7.5}, {6.5, 11.5}, {6.5, 3.5}}} + ], + FilledCurveBox[ + { + { + {1, 4, 3}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJw9U2tIVEEUvq5iVkttZmdfuo/ZbQukJGKVqPBLUTGJ0h9hVLIJRYhUVJj2\nAjGRWCKiF0llZWRCSEnZExEJ06CotaiQyH7EIrthT3u6NXPn3jswnDlzzzlz\nvu8711u9vWJzsqIoSXwv5tuk6IsgrQvOnLf+1CRC5ZKbg3WJAIJV90rNJoJF\nXOR6sebI6W3pyXq8DxccIoGwa+uxj/v/McxNbTxZOJ3w4Rkb+ZVgWGk2ZbcQ\nYfm0V+07Jhm6St7vzVhI2JfBT78ZCkI8cj2hqe/xxaIJJm0PoWEssCgtzvCc\nlzlYYwXP5iUYHpXlHV4xasXLeh4wyKCWX2fDqcJwbfQ+w4F83vGQDT1fJ1/U\ndzJ842bsih1XB3hiI0NzrPyOq9mBPb1tjpyNDBXci5U7MVQnLhji4nMsE+9W\nc6ARL3i3XSWbXNiiLi8EzPxbbqydsaD73LgHJ2wp/OiFoKVJ8Ui+Chha6M3T\nH8NZUMPm+XB9p8h0QtATjvtxqUh0SBgV76QHZN+lszReA5pNQ66o1+8HV6O3\nrdWCBIcTuKHxHJ4NQdO1sx4Nxxy4VYBug2dVt4lMnB/vGCi7TSgWz/504Etk\nVbXlNSGkCmWHqFYbJXziYXlT7VKXEdLq2DDMwyvvksTZZ5W4OgiCjmCVFTUP\ndh+3HSKJ8y9hqUogIfqn83PkCUndQoTLQsZ2gpperL3fQJLXIMEn5F5GaD3D\nl50g2O3OIkhiCUf7v8/fMJOMuRPTmT2FjLlU+0ghY471+dV93epzr/sPPaJz\nu3Ev65sNX/8//gP5Ei2u\n " + ] + ] + }, + AspectRatio -> Automatic, + ImageSize -> {13.0, 13.0}, + PlotRange -> {{0.0, 13.0}, {0.0, 13.0}} + ] + ]) + } + ], + Cell[ + StyleData["CommentCellLabelTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + StyleBox[ + TagBox[ + GridBox[ + { + {StyleBox[#1, FontSize -> 11], "\[SpanFromLeft]"}, + { + StyleBox[ + DynamicBox[ + ToBoxes[ + DateString[ + TimeZoneConvert[DateObject[#2, TimeZone -> 0]], + { + "Month", + "/", + "Day", + "/", + "Year", + " ", + "Hour24", + ":", + "Minute" + } + ], + StandardForm + ], + SingleEvaluation -> True + ], + FontSize -> 9 + ], + ItemBox[ + ButtonBox[ + TagBox[ + StyleBox[ + TemplateBox[ + { + "\"Reply \[RightGuillemet]\"", + StyleBox["\"Reply \[RightGuillemet]\"", "HyperlinkActive"], + BaseStyle -> "Hyperlink" + }, + "MouseoverTemplate" + ], + FontSize -> 9 + ], + MouseAppearanceTag["LinkHand"] + ], + BaseStyle -> "Hyperlink", + ButtonFunction :> + (SelectionMove[ParentCell[EvaluationCell[]], After, Cell]; + DefinitionNotebookClient`CommentInsert[]), + Evaluator -> Automatic, + Method -> "Queued" + ], + Alignment -> Right + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{Automatic}}, "Rows" -> {{0}}} + ], + "Grid" + ], + "CommentLabel", + ShowStringCharacters -> False + ] + ]) + } + ], + Cell[ + StyleData["OrangeButtonTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + FrameBox[ + ButtonBox[ + StyleBox[ + #1, + "Text", + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontTracking -> "Condensed", + FontSize -> 13, + FontColor -> + Dynamic[ + FEPrivate`If[ + CurrentValue[Enabled], + GrayLevel[1], + RGBColor[0.77647, 0.81765, 0.84314] + ], + Evaluator -> "System" + ], + StripOnInput -> False + ], + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[] }, + + If[ #4, + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ProgressIndicator[Appearance -> "Necklace"] + ]; + + + With[ { RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 3145484069433207908; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = HoldForm[#2[]] + ] + ], + DefinitionNotebookClient`ButtonCodeID[3145484069433207908] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ]; + + CurrentValue[RSNB`nb$, {TaggingRules, "StatusMessage"}] = + ""; + ], + FrameMargins -> {{5, 5}, {0, 0}}, + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqAQDO9nxI0+A3RSO1VDq9U8M+T9UiFICAbKAIUJ9IQtbhm\nWc9Uadd4TAQUB8oSNASoBqt2ZIRmDpohQNficgOae5D9hWYI0NcETYAgoEpc\nhgBDj0hDgCrhuiCpEc4FxgKRhgBVIhsCBJQbQhWXUD1MqBI7VEknVEmx1Mo7\n1MrFpKLBZgh+QExpDwCSuadO\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqAQDO9nxI0+A3RyphgWT7foW6Ze+taCAKygSJAcSINMcqf\n7ta6xqtzAyYCigNlCRoCVINVOzJCMwfNEKBrcbkBzT3I/kIzBOhrgiZAEFAl\nLkOAoUekIUCVcF2Q1AjnAmOBSEOAKpENAQLKDaGKS6geJlSJHaqkE6qkWGrl\nHWrlYlLRYDMEPyCmtAcACbcv5Q==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "\n1:eJxTTMoPSmNiYGAo5gASQYnljkVFiZXBAkBOaF5xZnpeaopnXklqemqRRRIz\nUFAcikHs/4QAMWqAQDO9nxKEy5DQtmVdaw7tOX/nxbvPEARkA0WA4sQYYpAz\neeGec3icDZQFqsFjiF/jorvP3wJFvv38ver4reZ1J+Om7YQgIBsoAhQHygLV\nAFViNQRoPsSESw9fJ87Y5dW5ARMBxYGyEHPg7kE2BOILoBqs2pERxBygejRD\ngCEG8QUuN6C5B+IvSDjDDQGGPJAB9DVBEyAIqBKoHqgL2RBgDAIZwNAj0hCg\nSqB6oC6gXkhqBDKAKQHIAMYCkYYAVQLVA3VBDAECyg2hikuoGCZUiR2qpBOq\npFhq5R2q5GJqlSfUKtnILmPxA2JKewBFU/Kd\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 144, + Interleaving -> True + ] + }, + Background -> RGBColor[0.16078, 0.40392, 0.56078], + Method -> "Queued", + ImageSize -> {All, 23}, + Evaluator -> Automatic + ], + FrameStyle -> + Directive[ + RGBColor[0.16078, 0.40392, 0.56078], + AbsoluteThickness[2] + ], + FrameMargins -> -1, + ContentPadding -> False, + StripOnInput -> False + ] + ]) + } + ], + Cell[ + StyleData["SuggestionGridTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + StyleBox[ + FrameBox[ + AdjustmentBox[ + TagBox[ + GridBox[ + { + { + TemplateBox[ + {#2, #3, {16.0, 16.0}, {{1.0, 17.0}, {1.0, 17.0}}}, + "SuggestionIconTemplate" + ], + PaneBox[ + #1, + ImageSizeAction -> "ShrinkToFit", + BaselinePosition -> Baseline, + ImageSize -> Full + ], + RowBox[ + { + AdjustmentBox[ + TemplateBox[ + { + ActionMenuBox[ + TagBox[ + PaneSelectorBox[ + { + False -> + GraphicsBox[ + { + EdgeForm[Directive[GrayLevel[1, 0], Thickness[0.025]]], + FaceForm[#4], + RectangleBox[{-1.75, -2}, {1.75, 2}, RoundingRadius -> 0.2], + Thickness[0.15], + #5, + LineBox[{{-0.5, -1.0}, {0.5, 0.0}, {-0.5, 1.0}}] + }, + ImageSize -> {Automatic, 15}, + ImageMargins -> 0 + ], + True -> + GraphicsBox[ + { + EdgeForm[Directive[#5, Thickness[0.025]]], + FaceForm[#2], + RectangleBox[{-1.75, -2}, {1.75, 2}, RoundingRadius -> 0.2], + Thickness[0.15], + GrayLevel[1], + LineBox[{{-0.5, -1.0}, {0.5, 0.0}, {-0.5, 1.0}}] + }, + ImageSize -> {Automatic, 15}, + ImageMargins -> 0 + ] + }, + Dynamic[CurrentValue["MouseOver"]], + ImageSize -> Automatic, + FrameMargins -> 0 + ], + MouseAppearanceTag["LinkHand"] + ], + #6, + Appearance -> None, + Method -> "Queued" + ], + "\"View suggestions\"" + }, + "PrettyTooltipTemplate" + ], + BoxBaselineShift -> -0.5 + ], + " " + } + ] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Baseline}}}, + AutoDelete -> False, + GridBoxItemSize -> { + "Columns" -> {Automatic, Automatic, Fit}, + "Rows" -> {{Automatic}} + }, + GridBoxSpacings -> {"Columns" -> {{0.4}}} + ], + "Grid" + ], + BoxMargins -> {{0.25, -0.5}, {0.15, -0.15}} + ], + RoundingRadius -> {13, 75}, + Background -> #4, + FrameStyle -> None, + FrameMargins -> {{0, 8}, {0, 0}}, + ImageMargins -> {{0, 0}, {5, 5}}, + StripOnInput -> False + ], + "Text", + FontColor -> #5, + FontSize -> 14, + FontFamily -> "Source Sans Pro", + FontWeight -> "SemiBold", + FontTracking -> "Plain", + PrivateFontOptions -> {"OperatorSubstitution" -> False}, + LineBreakWithin -> False + ] + ]) + } + ], + Cell[ + StyleData["SuggestionIconTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + Thickness[0.055556], + StyleBox[ + { + FilledCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJJIGZigIIGAwcIQ8kBxk94ekHp9k9Vh8qXaoYcOfoO\nm+a+X37stKZDTP+hrxpzdOA0TBymDqYPl7n2pnG7PHlk4Pw5RxQ2FGWIwPWD\njI3p54WbLxuVYn3fnwluD8S8H/Yo9gD5KPYA+TB7YPph9sDMh9EwcZg6FPdh\nMRfdXpi7YPph7oaZD/MXzB5c4QCzBwA/Dn+d\n " + ] + ] + }, + FaceForm[#1] + ], + StyleBox[ + { + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + { + { + {8.1753, 7.4169}, + {7.7969, 11.308}, + {7.7969, 13.38}, + {10.12, 13.38}, + {10.12, 11.308}, + {9.7415, 7.4169}, + {8.1753, 7.4169} + }, + CompressedData[ + "\n1:eJxTTMoPSmViYGCQBGIQDQFKDg+rRNa5P+RzKPOXE8vSVYTz8z+0ngxpVHCA\nqBNwmPd++THv7/IO8q2vA3fICTpUvlQz5Hgj52DLdX1xga2QQxoYyDmcYLed\nHTpfGM6/k8GQ3+giCue7M1dwq7wQg+vnmbyyKdBTAm6+tsTUK5wZknD7Pec2\nqB1qk4K772Y8iCXtAHM/jP/bquBcxyUEfyJ/ldnqOmW4/qw9JZMlWFTg5tfa\nm8bt6lSB23/2DAiowN0H48PcD+PD/AfTD/M/zHxY+MDsh4UfzH2w8EUPfwD5\nN5G6\n " + ] + } + ] + }, + FaceForm[#2] + ] + }, + ImageSize -> #3, + PlotRange -> #4, + AspectRatio -> Automatic, + BaselinePosition -> Scaled[0.1] + ] + ]) + } + ], + Cell[ + StyleData["FormEditValuesButtonTemplate"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + TemplateBox[ + { + TagBox[ + PaneBox[ + PaneSelectorBox[ + { + False -> + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzNWHlMVEcYf28XlGM5VlcRapRDDFK0sBaLBWVXUDxTKpe4JgvoQlALAsvV\nhHIoV4KK6wGiQlUqoqDcKKysDSZtPZJWTTzaxGrV2mqrNtqKB3Qnz8+Zd6Cv\ntn90vkgyv+/4zc58M9/3dEtIXZoooSgqw8r8Z2l8tjo9PT43wtE8iUrJSE5K\n0a1akKLXJenSAxKkZlD58h9y+X+M8Z7a/I3G7V/lHQgKp2kGmzw9rcrQb+j/\nZItPIGBvNywsVVGVJ01DWAqbpBYUFZ1hGsTYvssRqTLHt4nvoIgvbP6ZjM+I\nNt9PzUePPdbvcvX+ZwzTQ9vv8yMh6R04fFNY0/ciOkM8wzjXY4+F47xJgiPF\ncqRuY3kOlnUGLFq4khsv53NPv8zd7NXs/lYsR+158Gm9l1Tu7IYwmq7oJaMd\nuWMnR7jMMXLd/isYt7UXx4F9Rjtj1NmNXPPsCKyh6S9+AHzUOHEcpR3gMWM+\niQdHrq1kZFkmidvYQS633399ZBf31G21F/ZdLmmvPo0zVcyalCFg33Qr78Ce\n7+qv5jdOm8W3e39u9yN+npR3ieHQ5ArlWGwW28pBIXwfilvFcESnC2eyMoS0\nii8UstncZ2XDjiaROihGjbMcyWVJLBP0N2ELC8vm229icHFPKKo+Y3zK3Jj6\nq2lV3gFvZpk4BfSqKHwfFC4fLNDml3cVt2IGO7m+5sRzfoSNxglemGVV8dZT\nyRXqaKeJ5V1gkWIALX5bk8r5u+3x3qEbwvuN3kJ1DN9j5mLQdz60skXIeM9X\nPoPMnWYzdD4cjoGRMC3XRyI5+CNolyQhJK4A5mWdXGs7Ofs3HP+z9nz16fbf\nScz41Muf67c8B7Q7z6L5RiPMAxZxbfU1OFbDtVDNSGtmnb4qQz/W1F1ElYsc\n8rG9A6BF8x1fw2zhSnbddHHHJ115kl3rJNI1mzBL6HI2x9SglrugQzHzG7Ft\nRQ95IglF+DfwqylNb2gRugnWMnNteFWLj/+FsNlLyd3tfoTrTPWZV+vUcBnQ\ncHbre8HoTzy3ljGYxzT2Cep3MespaibRtZWwGy9vnPmkmXPgjy1fgte7Mxlk\nfhwZa/8V+9EQTZuPzwg4HBSA1J4XZqCotB1gExTO58hrYOoYM5RzcCcAHHIn\nQKpPD8eBzx12GHP0PAlfjXPI3C8J7JXlSNjt9vuSYVrKkjbwUs4R2quCwxLU\nmFJTZpCoaQjXuPqrgPmqhBhs7XH1lTsxmP889su24lOEZuzEyJE7ZJ3Gu23o\nZ9bDHvitrb2A0Um+NedwxKO/IGzrKZhn15FnRFHeAdh2zSZuXxscCXtpGorR\nkxqpRWx2zxPQsTk8/bgrxe+MaWj9UXw/be11pZih5VduxzPCqu03kiPFALPM\n3VyOCV5kv9P3ovJk6rbkipI2du3n39AwLegO3UBzn0CYH3vMfzHUMeyM4Mu6\n7Vwfiqr6BrRxBWhO0/suAxK5jm8fpoX7LszAz4bJStAanylcGCwiFbD9V2ja\nxk4ZosmNTsc+Xv51F4Xit9yduwJbqaJ0JYEfoT4xaw9YFDaBVuaId93cVb58\nMxPLsL/UIlSz2URmft3FGL2tA7YI1UAONF7HOeWnxhb6XULrJFnQsLHz+XDW\nx6ooZQjcOD4DKXsvkfnu6i1kYxpaVcw/H/5QRQl7L0lk27HfLJCtp8Rw6EqF\nfDe08F+54MjaC0jX8aDpFtglV4jhCAoH+44HzPvdfFuTy63xMGwd5GMpKq8B\nfNTRpNZj2vw4RvznkfhoZ7A/fBO9AdzTEhrM70HiNBGj1jJcRY3PJvmSHod+\nAo3Yr2j8HVXeNXMx7Cr7K7HmHOzFZGXWHpytjmPEcXx2kIzWcG15juOYqUHk\ndz+S2OwRVmFa3DkhaboljgF1R9wc6R3A/RJIz5PWe1wsNlssB0XFZgllI8Qe\nTrOhxcJSPAfqIjabhOLkNYSvFsL3XlqsG67qv264eqcYuv4gI9V/bz+Kptcf\nIbETz4ualXP+zf/+WMuWJO08i2J1P0qrYjJTIl2WyXx5NV6PK1C88/bR/7vx\nN3kqZvY=\n " + ], + {{0, 50.0}, {50.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {50.0, 50.0}, + PlotRange -> {{0, 50.0}, {0, 50.0}} + ], + True -> + GraphicsBox[ + TagBox[ + RasterBox[ + CompressedData[ + "\n1:eJzNWG1MU1cY7m1vS4GWttBLy0dLWyhl5aultrT0C2QzM5rMIWgyluDHkMwf\nYgBF9gc1cWpijDNuRNFsv2Rmuqmb/NjIYIFkG2qyAYnAljidODfdmItu+AHs\nXi6n59x7D3LH9mPnRJLzvB/Pue95z3nfat3UWLVFKpFImpX0n6qNrRVNTRvb\n1mrpRc225tcbttW/tnJbS31DfZN/k4wGS+b/MSb/jxFvt7QX95R86TytXyMh\nWEztye1w97v7c97SBAG2tEHIqRpXX/ksnPlnCVIiMTWXz0DMN5rZSGqX4l+u\nt+wp+wn1z05Lu7ZCiIYfOjoTnf+MQfd8aFLoiZmRR4FbeEl02tQsnkFpCT/E\n+1lsUtViOezHOJYzhZdSVqVt5vvLe0/ldpzk7mbZN2I5vEPAJnjPdlBpnQOJ\n4s9Qb2V3SB0Dk9rM7b4xiJNJ4jigjSINiaAV3TO1FjEgSr+PWRjFcRR+AiyS\nX0RxqjrnCDtNO1Bcpga5HJp8tud4m/2Yd9g3WvixZxBmqpg96SqBfmDCeXrZ\nt6XjzjOaMEbvhfADYZ4UdYvhMLfhcsy8k6sl1+PvQ8EFMRymJnwm6ypRLcse\nnI7rc1kC1xshk+sVRmkcn8V2AGvfi1jKy24vxhBvs+71XI4+Zm9M6XhuR5J/\ncZaE54CcqoH3IS49eaWlvai74AJkIHWOE9GnQg/FPQl5kMW6zz2QfSh1nTKr\nqBto2I8CKXxbbQeF0VYVB27i4828hanrhRYpq4E8dF+WOBcFe8xmZv5OcxhC\n9xdiYKexjm9DSP0/AGl6A4NYdoN14SW+NqnjfkPkT++QZzD0G4pFH6u9fDvz\nLiD1XGHWxT1gnbKKr+s4AX35rxtqpfHsPrXl7n4o8Y4wlQsditTIIyBl1iVf\ngVXaZm7djLfBk3b1cWsdIcs5DFkMr3A5NKHg3RgH7dN5BsmUT9ETse6F34Cp\npkTBedxNkKno2hCrxZG/GIyq4mTKA1hnPJdj+6wVMEiYlzg6PX8mT2UqFlMV\ncU/Q0cnuJ/8ciuYcAdGYv3H0SbPnIByuL4BVUoBFjBtQX74xeQrwZmmHZwQ4\n5PrYmQ7hGSSS3HeADt0XCTicXWwdY4duOewEAIfCEMu/wYU44LmDCEOOyFTG\nVphDdL+EiZU0DkQ7NEks0FIWXgRWuuW4WOV/QDCNqSTJh6Lls7DGlY4DTFuO\nYyCTYPVVGFgseQX3Zct6Yy6mxyFSdget0zDa7n52P9wB31rvMERVLs9VxOPP\nDOYeAOu8d9Ezor/Qj0TwML+vpapBLOlvb0ElBGlujUzF7iCHQ+Xm7xS+M3RN\n/AjeTzLJth8yBH/hdzxSZfBXlMN+NHZfTvI5EvLQfic67eqzH8s+VHiRW/uF\nN9RYB2SBm8xaEwTr8EPhi5G6npsRwml/m29Dv4FfA6llNxs+3yhAMrcL9Y11\n4L7jGYTZoC6JffmTuHQWy2wEmG+MvvRqXaW5zdSE2Hi9Izj/wbuGV6EWVWN7\nU/8S0yc6TsXux1kgJbUw6nRXOf9m2g5Ae4I01Lp60cz3jphaSA3UMNSCHPDf\ngDmlrYAajk7cPlEWZsjUmjL9y1SNrhLcOCEDOn3X0HxPdOJ0ymet+4TnIxxU\nDd46fQtXj/tmgekeEMNh24+zLTgvfOWoau8wIwv9HpgAetmHxHDo1wB92nbu\n/S67bW7j13gwSI0ila6+XcAmdR0qVRUZN7AzeQWKK9KAfuAW8wbwTws32O9h\npjILojIVrKLRJyoXahH4EUjE/oqGv6OKulNWg6hyfyV6roJYqEscp2C2yilx\nHM73UW/+6+ZdckoTQn/3M9PcKlUa62DnNBerCXEMTHfEz5HII9gvxbCp4D0+\nZm4Vy0H3kjtx2Qh8LyShs1UunoPpIly9OD/OroytONx3La1+oar/rJHotB8N\n/4F6Kv1Onkz3hx+iWPRp/jm6Y/gX//sjU6U3eK4wvsIPcjvYzCRkph3sLy//\nDcvuuIyle//vxt/PCE6d\n " + ], + {{0, 50.0}, {50.0, 0}}, + {0, 255}, + ColorFunction -> GrayLevel + ], + BoxForm`ImageTag[ + "Byte", + ColorSpace -> "Grayscale", + Interleaving -> True + ], + Selectable -> False + ], + DefaultBaseStyle -> "ImageGraphics", + ImageSizeRaw -> {50.0, 50.0}, + PlotRange -> {{0, 50.0}, {0, 50.0}} + ] + }, + Dynamic[CurrentValue["MouseOver"]], + ImageSize -> Automatic, + FrameMargins -> 0 + ], + ImageSize -> {Automatic, 15}, + ImageSizeAction -> "ResizeToFit" + ], + MouseAppearanceTag["LinkHand"] + ], + "\"Edit values\"" + }, + "PrettyTooltipTemplate" + ] + ]) + } + ], + Cell[ + StyleData["HintPodTitleBar"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + GrayLevel[0.97], + FilledCurveBox[ + BezierCurve[ + { + Offset[{0, -3}, {1, 1}], + Offset[{0, -1.3443}, {1, 1}], + Offset[{-1.3443, 0}, {1, 1}], + Offset[{-3, 0}, {1, 1}], + Offset[{-3, 0}, {1, 1}], + Offset[{3, 0}, {-1, 1}], + Offset[{3, 0}, {-1, 1}], + Offset[{1.3443, 0}, {-1, 1}], + Offset[{0, -1.3443}, {-1, 1}], + Offset[{0, -3}, {-1, 1}], + Offset[{0, -3}, {-1, 1}], + {-1, -1}, + {-1, -1}, + {-1, -1}, + {1, -1}, + {1, -1} + } + ] + ], + InsetBox[ + FormBox[ + StyleBox[ + "\"Notebook Analysis\"", + FontColor -> GrayLevel[0.4], + FontColor -> GrayLevel[0.4], + FontFamily -> "Source Sans Pro", + FontWeight -> Plain, + FontSize -> 13, + StripOnInput -> False + ], + TraditionalForm + ], + Offset[{8, 0}, {-1, 0}], + NCache[ImageScaled[{0, 1/2}], ImageScaled[{0, 0.5}]] + ], + TagBox[ + TagBox[ + TooltipBox[ + { + GrayLevel[0.6], + DiskBox[Offset[{-13, -10}, {1, 1}], Offset[6]], + GrayLevel[0.97], + AbsoluteThickness[1.5], + CapForm["Round"], + LineBox[ + { + {Offset[{-15, -8}, {1, 1}], Offset[{-11, -12}, {1, 1}]}, + {Offset[{-15, -12}, {1, 1}], Offset[{-11, -8}, {1, 1}]} + } + ] + }, + FrameBox[ + StyleBox[ + "\"Close analysis pod\"", + "Text", + FontColor -> RGBColor[0.53725, 0.53725, 0.53725], + FontSize -> 12, + FontWeight -> "Plain", + FontTracking -> "Plain", + StripOnInput -> False + ], + Background -> RGBColor[0.96078, 0.96078, 0.96078], + FrameStyle -> RGBColor[0.89804, 0.89804, 0.89804], + FrameMargins -> 8, + StripOnInput -> False + ], + TooltipDelay -> 0.1, + TooltipStyle -> {Background -> None, CellFrame -> 0} + ], + Annotation[#1, "Close analysis pod", "Tooltip"] & + ], + EventHandlerTag[ + { + "MouseClicked" :> NotebookDelete[EvaluationCell[]], + Method -> "Preemptive", + PassEventsDown -> Automatic, + PassEventsUp -> True + } + ] + ] + }, + AspectRatio -> Full, + ImageSize -> {Full, 20}, + PlotRange -> {{-1, 1}, {-1, 1}}, + ImageMargins -> {{0, 0}, {0, 0}}, + ImagePadding -> {{0, 0}, {0, 0}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodDelimiterTop"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + AbsoluteThickness[1], + GrayLevel[0.85], + CapForm["Round"], + LineBox[{{-1, 0}, {1, 0}}] + }, + AspectRatio -> Full, + PlotRange -> {{-1, 1}, {-1, 1}}, + ImagePadding -> {{0, 0}, {0, 0}}, + ImageSize -> {Full, 2}, + BaselinePosition -> Scaled[0.1], + ImageMargins -> {{0, 0}, {4, 0}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodDelimiterBottom"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + AbsoluteThickness[1], + GrayLevel[0.85], + CapForm["Round"], + LineBox[{{-1, 0}, {1, 0}}] + }, + AspectRatio -> Full, + PlotRange -> {{-1, 1}, {-1, 1}}, + ImagePadding -> {{0, 0}, {0, 0}}, + ImageSize -> {Full, 2}, + BaselinePosition -> Scaled[0.1], + ImageMargins -> {{0, 0}, {0, 4}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodFooter"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + GrayLevel[0.97], + FilledCurveBox[ + BezierCurve[ + { + {-1, 1}, + {-1, 1}, + Offset[{0, 3}, {-1, -1}], + Offset[{0, 3}, {-1, -1}], + Offset[{0, 1.3443}, {-1, -1}], + Offset[{1.3443, 0}, {-1, -1}], + Offset[{3, 0}, {-1, -1}], + Offset[{3, 0}, {-1, -1}], + Offset[{-3, 0}, {1, -1}], + Offset[{-3, 0}, {1, -1}], + Offset[{-1.3443, 0}, {1, -1}], + Offset[{0, 1.3443}, {1, -1}], + Offset[{0, 3}, {1, -1}], + Offset[{0, 3}, {1, -1}], + {1, 1}, + {1, 1} + } + ] + ], + InsetBox[ + BoxData[ + FormBox[ + TemplateBox[ + { + StyleBox[ + TemplateBox[{3}, "Spacer1"], + FontColor -> GrayLevel[0.4], + FontFamily -> "Source Sans Pro", + FontWeight -> Plain, + FontSize -> 12, + StripOnInput -> False + ], + StyleBox[ + #1, + FontColor -> GrayLevel[0.4], + FontFamily -> "Source Sans Pro", + FontWeight -> Plain, + FontSize -> 12, + StripOnInput -> False + ], + StyleBox[ + TemplateBox[{5}, "Spacer1"], + FontColor -> GrayLevel[0.4], + FontFamily -> "Source Sans Pro", + FontWeight -> Plain, + FontSize -> 12, + StripOnInput -> False + ] + }, + "RowDefault" + ], + TraditionalForm + ] + ], + Offset[{5, 2.5}, {-1, 0}], + {-1, 0} + ] + }, + AspectRatio -> Full, + ImageSize -> {Full, 21}, + PlotRange -> {{-1, 1}, {-1, 1}}, + ImageMargins -> {{0, 0}, {0, 3}}, + ImagePadding -> {{0, 0}, {0, 0}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodMenuItems"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + TemplateBox[ + { + #1, + FrameMargins -> 3, + Background -> GrayLevel[1], + RoundingRadius -> 0, + FrameStyle -> + Directive[ + AbsoluteThickness[1], + RGBColor[0.75686, 0.82745, 0.88235] + ], + ImageMargins -> #2 + }, + "Highlighted" + ] + ]) + } + ], + Cell[ + StyleData["HintPodActionMenuItem"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + ButtonBox[ + TemplateBox[ + { + TagBox[ + GridBox[ + {{#1, TemplateBox[{7}, "Spacer1"], #2}}, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Top}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0}}} + ], + "Grid" + ], + FrameStyle -> None, + RoundingRadius -> 0, + FrameMargins -> {{5, 2}, {2, 2}}, + ImageSize -> Full, + ImageMargins -> {{0, 0}, {0, 0}}, + Background -> + Dynamic[ + If[ CurrentValue["MouseOver"], + GrayLevel[0.96], + GrayLevel[1.0] + ] + ] + }, + "Highlighted" + ], + ButtonFunction :> ReleaseHold[#3], + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "1:eJxTTMoPSmNiYGAo5gESfqW5qUWZyY5FRYmVScxAARhmAeL/QAClwDQDBPxHFg8WALJC84oz0/NSUzzzSlLTU4ssAL+sIf8=" + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> {72, 72}, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "1:eJxTTMoPSmNiYGAo5gESfqW5qUWZyY5FRYmVScxAARhmAeL/QAClwDQDBPxHFg8WALJC84oz0/NSUzzzSlLTU4ssAL+sIf8=" + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> {72, 72}, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "1:eJxTTMoPSmNiYGAo5gESfqW5qUWZyY5FRYmVScxAARhmAeL/QAClwDQDBPxHFg8WALJC84oz0/NSUzzzSlLTU4ssAL+sIf8=" + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> {72, 72}, + Interleaving -> True + ] + }, + Method -> "Queued", + Evaluator -> Automatic + ] + ]) + } + ], + Cell[ + StyleData["HintPodDisabledMenuItem"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + ButtonBox[ + TemplateBox[ + { + TagBox[ + GridBox[ + { + { + #1, + TemplateBox[{7}, "Spacer1"], + StyleBox[#2, FontOpacity -> 0.4] + } + }, + GridBoxAlignment -> {"Columns" -> {{Left}}, "Rows" -> {{Top}}}, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0}}} + ], + "Grid" + ], + FrameStyle -> None, + RoundingRadius -> 0, + FrameMargins -> {{5, 2}, {2, 2}}, + ImageSize -> Full, + ImageMargins -> {{0, 0}, {0, 0}}, + Background -> GrayLevel[1.0] + }, + "Highlighted" + ], + ButtonFunction :> Null, + Appearance -> { + "Default" -> + Image[ + CompressedData[ + "1:eJxTTMoPSmNiYGAo5gESfqW5qUWZyY5FRYmVScxAARhmAeL/QAClwDQDBPxHFg8WALJC84oz0/NSUzzzSlLTU4ssAL+sIf8=" + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> {72, 72}, + Interleaving -> True + ], + "Hover" -> + Image[ + CompressedData[ + "1:eJxTTMoPSmNiYGAo5gESfqW5qUWZyY5FRYmVScxAARhmAeL/QAClwDQDBPxHFg8WALJC84oz0/NSUzzzSlLTU4ssAL+sIf8=" + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> {72, 72}, + Interleaving -> True + ], + "Pressed" -> + Image[ + CompressedData[ + "1:eJxTTMoPSmNiYGAo5gESfqW5qUWZyY5FRYmVScxAARhmAeL/QAClwDQDBPxHFg8WALJC84oz0/NSUzzzSlLTU4ssAL+sIf8=" + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> {72, 72}, + Interleaving -> True + ] + }, + Method -> "Queued", + Evaluator -> Automatic, + Enabled -> False + ] + ]) + } + ], + Cell[ + StyleData["HintPodActionLabel"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + PaneBox[ + StyleBox[ + #1, + FontColor -> GrayLevel[0.2], + FontFamily -> "Source Sans Pro", + FontWeight -> Plain, + FontSize -> 13, + LineIndent -> 0, + StripOnInput -> False + ], + FrameMargins -> 0, + ImageMargins -> 0, + BaselinePosition -> Baseline, + ImageSize -> Full + ] + ]) + } + ], + Cell[ + StyleData["HintPodMenuDelimiter"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + PaneBox[ + StyleBox[ + GraphicsBox[ + { + CapForm["Round"], + GrayLevel[0.9], + AbsoluteThickness[1], + LineBox[{{-1, 0}, {1, 0}}] + }, + AspectRatio -> Full, + PlotRange -> {{-1, 1}, {-1, 1}}, + ImageMargins -> {{0, 0}, {2, 2}}, + ImagePadding -> {{5, 5}, {0, 0}}, + ImageSize -> {Full, 2} + ], + LineIndent -> 0, + StripOnInput -> False + ], + FrameMargins -> 0, + ImageMargins -> 0, + BaselinePosition -> Baseline, + ImageSize -> Full + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconChevron"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + GrayLevel[0.2], + AbsoluteThickness[1.8], + CapForm["Round"], + JoinForm["Miter"], + LineBox[{{-0.5, 1}, {0.5, 0}, {-0.5, -1}}] + }, + AspectRatio -> Full, + BaselinePosition -> Bottom, + ImageMargins -> {{0, 4}, {0, 0}}, + ImageSize -> {5.6, 7.7} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconPopOut"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + FaceForm[GrayLevel[0.4]], + FilledCurveBox[ + { + { + {1, 4, 3}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGIlIGYC4h1yra8Dd6g4rHN/WCWip+KwRiYqxXq+isNk\nCZYwvlwEDROHqYPpKwUrUHFgAIEDKg5nzwDBG2VU/hlluPogMEMCzm9kOdpv\naC6OJi/mINR84NRCVwQfIq8M519wufHhi5Yymn4lNPOVHNLAQBHO/6YR03/o\nK5eDB9Ab69wFHJoeHZ+xexqng8r0/xPqfvM5cG9dVnl8JacD0FO6m+byOPxL\n/f4kUZHbQZr3ge4EBW6HD2IeAX9m8Dhkzyqfs2gxp8ONxmK3Kd/4HOYsUt75\np50Tbi6YesgF9b8ShJ+oCOfD3Anjw/zx9JP8pXx7hD9h4QfjqxtyAKNCBU0e\nEY4wPqr5iHh4/nvlx0tnVRyYObvkk98pOwA9+X75MRUHWWD03udHxCssngGf\nXO7X\n " + ] + ] + }, + AspectRatio -> Automatic, + ImageSize -> {14.0, 14.0}, + PlotRange -> {{0.0, 13.62}, {0.0, 13.62}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconWrench"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + GrayLevel[0.4], + AbsoluteThickness[1], + Opacity[1.0], + JoinedCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJRIGYCYmWv6mZ9n3/2cmJZvp/5BBzci37yv9wu6/Au\nysnuhaQynG8at8uT55AGXJwBDHQdPl3yTRKIUIfzo1Ks7/vzajiosjVOdfbW\nccjaUzJZokUFrv8ySLmlqoPbts9/r1iowsVh6mD6zp4BAh4NnPbA3AHTr+ss\n8/rRNoS7YXyYv2D+7H/ySf5SPrdD7D/nX29ff7H/6hXZZnGNGc6HqYPRMPED\nb+bZ6FxBqAPpOprL7YAefgCtVISU\n " + ], + CurveClosed -> {1} + ] + }, + AspectRatio -> Automatic, + BaselinePosition -> Scaled[0.2], + ImagePadding -> 0.5, + ImageSize -> {16.0, 16.0}, + PlotRange -> {{0.0, 16.0}, {0.0, 16.0}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconInfo"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + FaceForm[GrayLevel[0.4]], + FilledCurveBox[ + { + {{1, 4, 3}, {1, 3, 3}, {1, 3, 3}, {1, 3, 3}}, + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + }, + { + {1, 4, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3} + } + }, + { + { + {6.81, 13.0}, + {3.3914, 13.0}, + {0.62, 10.229}, + {0.62, 6.81}, + {0.62, 3.3914}, + {3.3914, 0.62}, + {6.81, 0.62}, + {10.229, 0.62}, + {13.0, 3.3914}, + {13.0, 6.81}, + {13.0, 10.229}, + {10.229, 13.0}, + {6.81, 13.0} + }, + CompressedData[ + "\n1:eJxTTMoPSmViYGCQB2IQbct1fXGBrbRD6+vAHXKtvA7r3B9WiayTdoCI8zgc\n/qoR039IHkoLOjCAgYKDB0iZu4CDPFijgsOsmSDAC1UnCzWPE0rLQMXZHV6x\nmAia1Ug56E1Y8MMwjdXh685bXX9VJRx4Jq9sCvRkcTh7BgREHfoPgTSwOAQB\ndb8OFHYAO4eLFeo+IQcRMIMLzoe4h9dBW2LqFc4MYYd4zdMCx38JOviYdzom\npIo4PJgjuHSvo6jDkgKQz0QdCsEelHDQjAHZJAa1VxIqLwH3Jzofok8S4i9W\nRQews67LQsJhnoKDMRjIQ9Q3wMJJwQFMJULDSRJmrhzUPKh6Blmof+QcwM6K\nkXb4Bgq2rzJQcXFovMhA5UUdciqqluo0SztsKMqY+NZG2OHV1E08hTrSDquA\noTmXQdABPX4BaWq/EA==\n " + ], + { + {8.81, 9.79}, + {8.8101, 9.5122}, + {8.5878, 9.2854}, + {8.31, 9.28}, + {7.51, 9.28}, + {7.2283, 9.28}, + {7.0, 9.5083}, + {7.0, 9.79}, + {7.0, 10.62}, + {7.0054, 10.898}, + {7.2322, 11.12}, + {7.51, 11.12}, + {8.35, 11.12}, + {8.6239, 11.115}, + {8.8447, 10.894}, + {8.85, 10.62} + } + } + ] + }, + AspectRatio -> Automatic, + ImagePadding -> 0.5, + ImageSize -> {14.0, 14.0}, + PlotRange -> {{0.0, 13.62}, {0.0, 13.62}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconNone"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { }, + AspectRatio -> Automatic, + ImageSize -> {16.0, 16.0}, + PlotRange -> {{0.0, 16.0}, {0.0, 16.0}}, + BaselinePosition -> Scaled[0.2], + ImagePadding -> 0.5 + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconIgnoreAlways"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + EdgeForm[None], + FaceForm[GrayLevel[0.4]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJTIGYCYpF17g+rROQcbLmuLy6wlXaoBguoOvQf+qoR\nw6/i8CZwh1zralWH4oyJb2vsVRx0N819v/yYqoO0/l0VtkYEv/U1UOFRBP/D\n8mPe5pyqcP0z8oSaD3ipws2H0famcbs8fVQd2BqnOnevUXUAa+dWdUgSiLDc\nckLVwQPounXHVeB8kK1TmxH8gN7peULOKnD9EP+owM2H+QvmzyUFIBEeuHxC\nmb+c2CtuuP75NjpXZj3jgpsP0s11nRPO5+feuqzyOAec73dxYsy/w+xw/WDr\nuNjh5n9MPhPr7cEG93+V2Wq78Nus8PCB8WHhB+PDwhemHxb+MPNh8ZMGBhJw\nf8Lkv2nEAJXwOGyu/rQh4DWrwwrTs9Z+F7kdvHiYtNunsTrYgrwpy+XQteHh\ny6lGbA6HxNWCWRdzOJwKObhiyTk2B3fmCm4VDXaouRwOEaeMjmzUY4OHhybI\neA02eHgt/GH4bJ0qm4PT+bSrz4Hh+Z0tfobPVDZ4eIOVx7DD3QlzNwMYIPx1\nsmzffCl9FUg4u7M5hPEBU1S+isPs0Pmr195gdTAGgc0qUHewOswDJhfv7yoO\n/g7CiYcvszoAU9vrQAtVh6V+QAFnNqg9iHj5dMk3SWAGIt78wBGJiFcYH+ZP\nGB/mT5h+WLqBmQ/zJwC4F0s3\n " + ] + ] + }, + AspectRatio -> Automatic, + ImageMargins -> {{0, 0}, {0, 2}}, + ImageSize -> {14.0, 14.0}, + PlotRange -> {{-0.5, 13.62}, {-0.5, 13.62}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconIgnoreInCell"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + EdgeForm[None], + FaceForm[GrayLevel[0.4]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0} + }, + {{0, 2, 0}, {0, 1, 0}} + }, + { + { + {11.69, 13.37}, + {7.57, 13.37}, + {7.57, 12.37}, + {7.76, 12.37}, + {11.19, 8.93}, + {11.19, 1.25}, + {7.57, 1.25}, + {7.57, 0.25}, + {12.19, 0.25}, + {12.19, 13.37} + }, + {{9.17, 12.37}, {11.17, 12.37}, {11.17, 10.37}} + } + ], + FilledCurveBox[ + { + { + {0, 2, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGIjIGYCYo+HVSLr3EUdbLmuLy6wlXZYUgBiyTlAxJUc\nkt9FOdllyDuU6yrKf1mD4LM879F466sMV28MApuVHX7yv9y+3lkOQj9WdngU\nIb794gFZh/Dojfvf/FN22CHX+jrQAsHvf/JJ/tJ6GTgfbI+ODFz/2TMgIA03\nvxroqodVQg5gSkQO6m4mVPubGR1E7I/d2fpE2cHy2tFckwYGB2n9uypsjCoO\nYG89/GcP4wd5zm1QO/QHzr9wNeyN/u5f9jD9kHD4aQ8zX+z36XcnD3+3v8fE\n2SXfrOygvqBzw8OX3+yDQAxHBB/srr9KcL7mW959BjuV4PrnCi7de7BcCW4+\nLLwhND88PmDyEHcLOjg2PTo+Y/d3+/21shbpLYIOTglPLyjd/mZ//wH35JVM\nCD4knATgfL0JC34YPuOH688Nq1237REf3HzNmP5DXzX4HLhVNOp6dv6yP3xZ\nO1UyiRcePrlH/22q/sQDD79vGiANPA5yy1946NUzOOy61fU39TuPw5GNenmL\nGxkdwPal8cLjB2Y+LP7SwEDCgQEMZODyf7+VPpgTKOOw9ldM7tE6XgfmCqCL\n9sk43PfvnZ4nxAuJZ2NZB5j9UV933uraK+swf/XaG/HfeCDudZJzuA1yTgov\nPH3CzBcAJg/mdHmHVElQyuSH851lXj8ykxKEq4eFNwCKHGBr\n " + ] + ] + }, + AspectRatio -> Automatic, + ImageMargins -> {{0, 0}, {0, 2}}, + ImageSize -> {14.0, 14.0}, + PlotRange -> {{-0.5, 13.62}, {-0.5, 13.62}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconIgnoreInNotebook"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + FaceForm[GrayLevel[0.4]], + FilledCurveBox[ + { + { + {0, 2, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJTIGYC4qAdcq2vAwUcbLmuLy6wFXdYUgBiSTp4PKwS\nWeeu4GCgtVL4AouUw1zBpXsPlis4vDlgqexlLeWg+ZZ3n8FOBB+s/y+CH6S+\noHODoyJc/z0mzi75ZkW4+cYgsFnRoanYbco3N0kHEftjd7Y+UXRYeM3kvcVR\nCYeQx0tnH2FQgroLwb9pWxmxYqs4nP9zQfrmV8bicP0g1VzXxeDmf9OI6T/0\nlcsB6Bmgj6QcGMDggz1MvoTnRNz7f2/sf/K/3L7+saLDzmCriP/PX9iHR2/c\n/+YfzL1P4Pz+Xoc96+IfwPkrVqZm1068AdcPtAxo4yW4+ccenln/jOGkPcz/\nMjWJRqEGh+xh4QPjw8IPxoeFL0w/LPxh5sPiB0KzwuNPHhibO+Su2h8GKTvE\n7aAYeYAl7+5Z+/rfVgXnOLgdPu6qO5h345j9voPiasGsXHA+JJw44Hy9CQt+\nGD5jh+vPDatdt+0RG9x8TZByDTYH/uky5V7st+21JaZe4cxgdZgp5PnFqOuh\nvQY/99ZlP1kcIO54CjWfxeFeX0HUh0Uv7bdEft15i4vVoa2/Q3Oiy1t77Xax\nm+fKWeHxAzMfFn9pYCACj1+YfMeX29cbgfF/+LJ2qmQSKzx95B79t6n6Ews8\n/cDsB3O5JB1Upv+fUPebxeHIRr28xQeB6e+Cy40PX1gdnjTPO7uKX8qh/8kn\n+Uv57A4sYXy6m2KlHDjBCY3DwV9OLMvXGJjeda7MejaXC56eYeENAPSkchE=\n\n " + ] + ], + FilledCurveBox[ + { + { + {0, 2, 0}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3} + } + }, + CompressedData[ + "\n1:eJxTTMoPSmVmYGBgBGJdIGYC4qAdcq2vL6o52HJdX1ywVwtC24rB+YdTViWE\nXBKE86tF1rk/rOJxMAaBzxpwPkReDY2vCDVPCMpXhvPB+jerwfnPf6/8eOms\nukPDdoemR+wiUHkNuHtgfJh7YXy2xqnO3W/U0eQ14ObB+DD7YHzNmP5DXzWY\n4PzY3KP/NlX/toeZBxYP/GIPsw/GBzuHSxrOX7TF/MchFSkH9g9iHgF/Ptmb\nvrdwdTeSdNjZywYU+WQPcb8E1B+f7H8EP146m0XcYeE1E6DKT/Z9IGUXRB02\nV3/aEJD92R5s7A4Rh1kzQeCr/YQFPwyfvRN2+Put9MEcwe/2894vP+ZtLuxw\n3793ep7QT3uIOiEHkC651t/2YH8a80LtY3NA5TPB+RPrflsVnPtkL/8lJ6xW\nT8jhTSDYo1DzxOB8BjBQh/O/aQADzlQTTV4bbh6MD7MPxoeFfwDI2czaDmfP\ngAA0nCdqOTglPL2gdFvDweNhlci645oO8iAPzdOEmPNXw+EPMDp9k7Qc4nZ5\n8jC9VncAG39KywE9/QIAH6UuJw==\n " + ] + ], + FilledCurveBox[ + {{{0, 2, 0}, {1, 3, 3}, {0, 1, 0}, {0, 1, 0}}}, + { + { + {5.63, 11.05}, + {5.63, 10.44}, + {6.0569, 10.539}, + {6.5048, 10.49}, + {6.9, 10.3}, + {9.53, 10.3}, + {9.53, 11.05} + } + } + ], + FilledCurveBox[ + {{{1, 4, 3}, {0, 1, 0}, {0, 1, 0}}}, + { + { + {7.92, 3.73}, + {8.0396, 3.4994}, + {8.0784, 3.2353}, + {8.03, 2.98}, + {9.41, 2.98}, + {9.41, 3.73} + } + } + ], + FilledCurveBox[ + {{{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}}}, + { + { + {6.73, 6.21}, + {6.2, 5.82}, + {6.67, 5.46}, + {11.22, 5.46}, + {11.22, 6.21}, + {6.73, 6.21} + } + } + ], + FilledCurveBox[ + {{{1, 4, 3}, {0, 1, 0}, {0, 1, 0}}}, + { + { + {8.0, 8.7}, + {8.0514, 8.4458}, + {8.0162, 8.1818}, + {7.9, 7.95}, + {10.25, 7.95}, + {10.25, 8.7} + } + } + ] + }, + AspectRatio -> Automatic, + ImagePadding -> 0.75, + ImageSize -> {15.0, 15.0}, + PlotRange -> {{0.0, 13.62}, {0.0, 13.62}} + ] + ]) + } + ], + Cell[ + StyleData["HintPodIconHint"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + GraphicsBox[ + { + EdgeForm[None], + FaceForm[#1], + FilledCurveBox[ + { + {{1, 4, 3}, {1, 3, 3}, {1, 3, 3}, {1, 3, 3}}, + { + {1, 4, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + }, + { + {0, 2, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {0, 1, 0}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3}, + {1, 3, 3} + } + }, + { + { + {9.015, 17.37}, + {4.4559, 17.37}, + {0.76, 13.645}, + {0.76, 9.05}, + {0.76, 4.455}, + {4.4559, 0.73}, + {9.015, 0.73}, + {13.574, 0.73}, + {17.27, 4.455}, + {17.27, 9.05}, + {17.27, 13.645}, + {13.574, 17.37}, + {9.015, 17.37} + }, + CompressedData[ + "\n1:eJxTTMoPSmViYGCQBGIQbcixRiYqRcVh3bak+pu23A5rf8XkHt2n7OC/fkpq\nx2MOB8+5DWqHnik5nP8e/HjpbHYHj4dVIuvYlRyAiisjVrA78Bau6b6toegQ\nApQ9soDdQepAtIJjoILDJ8fzaVefczgs6Nzw8GWoPNx84yMb9fIeyzr831T9\nacMFXod1N+LL/OVkHV5uX8/8/IyAw7Fck4btDrIOZQ/mCC7dK+TAXMGtomEn\n6/DP+dfb1w0iDkIi9sfufJV1ePRy6iYeQzGHac7dOc+t5R3SwEDcwe7FzTW/\nbBQc9kybwF+1TcLh7TwbnStSig7Hd+3oZSuQdDjab1iuy6jk0MIL8qGkg8f+\nWlmL50oO9uHRG/fnSDr4fu4LLjmi7HDw1ELXbZslHGDhAzO//9BXjRh+VQeG\niXW/rQzEHKzv+/dOz1N1uFfY1fekSMRhzhGFDUUZqhB/LhaCmFOs6sC0h1VI\nZL+Ag8g6d2AIqjqYCJrZ7L3E64Ae/gDrrapT\n " + ], + CompressedData[ + "\n1:eJxTTMoPSmViYGBQBGIQ/emSb5KAhJoDAwg0aDhYbjlRtu++isNudX7urWpK\nDrX2pnG7Tqo4TFPsKy2sVnRQvv2zLqtGBULfUXAI6J2eJ8Ss4mDSsN2hKUnB\nIa0jOfZOmrKD/l0Vtsar8g5Gz9apPlms5GDgs4zLLVXeweLHoZRVDxQdnNdm\n3ivskneQW/7CQ09e0aHEbco3tnh5h+jLex6LxCo4FErzPtC9IO+wVfT36Xed\n8nDzH5tJHYheIOeQBxJ4pOCgu2nu++Vscg75Qs0HTjUqOjDkN7IcPS/rcObd\nycNOukoObqqlTLM4ZOD+O7JRL2/xQWkHHibtdrFITYeb8WX+ctOkHQ6eWui6\nzVjLQfD4rh29bdIO/Ye+asTwazuAnJswRdohaIdc6+uL2g6qbI1TnbtlHGy5\nri8uqNVxEIgAhtg3WYj5B3QcgKEkzcsAdOfS2UcUDHQdEp5eULotqehw89z3\n4Mepug63pGsSjUyVHMr3zZfSj9V1uKKdKvkoQtmhOGPi25p6XQeQ8p91KhB9\nlroOIGH7UlWH+qw9JZNn6EDs54bGF4OOA9AVtlzhag6KG4oyJupqO4CCYaGr\nmgM4XiO0HK5WvFQz9FBzuAzi7tR0cNv2+e8VCzUHJ5AF0poO6PEPAFdvzZk=\n\n " + ] + } + ] + }, + AspectRatio -> Automatic, + BaselinePosition -> Scaled[0.1], + ImagePadding -> 0.5, + ImageSize -> {14.0, 14.778}, + PlotRange -> {{0.76, 17.27}, {0.73, 17.37}} + ] + ]) + } + ], + Cell["Documentation", "Section"], + Cell["Usage", "Subsection"], + Cell[ + StyleData[ + "UsageInputs", + StyleDefinitions -> StyleData["Input"] + ], + CellMargins -> {{66, 10}, {0, 8}}, + StyleKeyMapping -> {"Tab" -> "UsageDescription"}, + Evaluatable -> False, + CellEventActions -> { + "ReturnKeyDown" :> + With[ { RSNB`nb$ = Notebooks[EvaluationCell[]] }, + SelectionMove[EvaluationCell[], After, Cell]; + NotebookWrite[RSNB`nb$, Cell["", "UsageDescription"], All]; + SelectionMove[RSNB`nb$, Before, CellContents] + ], + {"KeyDown", "\t"} :> + Replace[ + SelectionMove[SelectedNotebook[], After, Cell]; + NotebookFind[ + SelectedNotebook[], + "TabNext", + Next, + CellTags, + AutoScroll -> True, + WrapAround -> True + ], + Blank[NotebookSelection] :> + SelectionMove[ + SelectedNotebook[], + All, + CellContents, + AutoScroll -> True + ] + ] + }, + ShowAutoStyles -> False, + ShowCodeAssist -> False, + CodeAssistOptions -> {"DynamicHighlighting" -> False}, + LineSpacing -> {1, 3}, + TabSpacings -> {2.5}, + CounterIncrements -> "Text", + FontFamily -> "Source Sans Pro", + FontSize -> 15, + FontWeight -> "Plain" + ], + Cell[ + StyleData[ + "UsageDescription", + StyleDefinitions -> StyleData["Text"] + ], + CellMargins -> {{86, 10}, {7, 0}}, + StyleKeyMapping -> {"Backspace" -> "UsageInputs"}, + CellGroupingRules -> "OutputGrouping", + CellEventActions -> { + "ReturnKeyDown" :> + With[ { RSNB`nb$ = Notebooks[EvaluationCell[]] }, + SelectionMove[EvaluationCell[], After, Cell]; + + NotebookWrite[ + RSNB`nb$, + Cell[ + BoxData[""], + "UsageInputs", + FontFamily -> "Source Sans Pro" + ], + All + ]; + + SelectionMove[RSNB`nb$, Before, CellContents] + ], + {"KeyDown", "\t"} :> + Replace[ + SelectionMove[SelectedNotebook[], After, Cell]; + NotebookFind[ + SelectedNotebook[], + "TabNext", + Next, + CellTags, + AutoScroll -> True, + WrapAround -> True + ], + Blank[NotebookSelection] :> + SelectionMove[ + SelectedNotebook[], + All, + CellContents, + AutoScroll -> True + ] + ] + }, + ShowAutoSpellCheck -> False + ], + Cell["Details & Options", "Subsection"], + Cell[ + StyleData["Notes", StyleDefinitions -> StyleData["Item"]], + CellDingbat -> + StyleBox[ + "\[FilledVerySmallSquare]", + FontColor -> GrayLevel[0.6] + ], + CellMargins -> {{66, 24}, {9, 7}}, + ReturnCreatesNewCell -> False, + StyleKeyMapping -> { }, + DefaultNewCellStyle -> "Notes", + ShowAutoSpellCheck -> False, + GridBoxOptions -> {BaseStyle -> "TableNotes"} + ], + Cell[ + StyleData[ + "TableNotes", + StyleDefinitions -> StyleData["Notes"] + ], + CellDingbat -> None, + CellFrameColor -> RGBColor[0.749, 0.694, 0.553], + StyleMenuListing -> None, + ButtonBoxOptions -> {Appearance -> {Automatic, None}}, + GridBoxOptions -> { + FrameStyle -> GrayLevel[0.906], + GridBoxAlignment -> { + "Columns" -> {{Left}}, + "ColumnsIndexed" -> { }, + "Rows" -> {{Baseline}}, + "RowsIndexed" -> { } + }, + GridBoxDividers -> {"Columns" -> {{None}}, "Rows" -> {{True}}}, + GridDefaultElement -> Cell["\[Placeholder]", "TableText"] + } + ], + Cell[ + StyleData["TableText"], + DefaultInlineFormatType -> "DefaultInputInlineFormatType", + AutoQuoteCharacters -> { }, + PasteAutoQuoteCharacters -> { }, + StyleMenuListing -> None + ], + Cell["Examples", "Subsection"], + Cell[ + StyleData["ExampleDelimiter"], + Selectable -> False, + ShowCellBracket -> Automatic, + CellMargins -> {{66, 14}, {5, 10}}, + Evaluatable -> True, + CellGroupingRules -> {"SectionGrouping", 58}, + CellEvaluationFunction -> (($Line = 0;) &), + ShowCellLabel -> False, + CellLabelAutoDelete -> True, + TabFilling -> "\[LongDash]\[NegativeThickSpace]", + TabSpacings -> {100}, + StyleMenuListing -> None, + FontFamily -> "Verdana", + FontWeight -> Bold, + FontSlant -> "Plain", + FontColor -> GrayLevel[0.906] + ], + Cell[ + StyleData[ + "ExampleText", + StyleDefinitions -> StyleData["Text"] + ] + ], + Cell[ + StyleData[ + "PageBreak", + StyleDefinitions -> StyleData["ExampleDelimiter"] + ], + Selectable -> False, + CellFrame -> {{0, 0}, {1, 0}}, + CellMargins -> {{66, 14}, {15, -5}}, + CellElementSpacings -> {"CellMinHeight" -> 1}, + Evaluatable -> True, + CellEvaluationFunction -> (($Line = 0;) &), + CellFrameColor -> GrayLevel[77/85] + ], + Cell[ + StyleData["Subsection"], + Evaluatable -> True, + CellEvaluationFunction -> (($Line = 0;) &), + ShowCellLabel -> False + ], + Cell[ + StyleData["Subsubsection"], + Evaluatable -> True, + CellEvaluationFunction -> (($Line = 0;) &), + ShowCellLabel -> False + ], + Cell[ + StyleData["ExampleImage"], + PageWidth :> 650, + CellMargins -> {{66, 66}, {16, 5}}, + Evaluatable -> False, + ShowCellLabel -> False, + MenuSortingValue -> 10000, + RasterBoxOptions -> {ImageEditMode -> False} + ], + Cell["Links", "Section"], + Cell[ + StyleData["Link"], + FontFamily -> "Source Sans Pro", + FontColor -> + Dynamic[ + If[ CurrentValue["MouseOver"], + RGBColor[0.855, 0.396, 0.145], + RGBColor[0.02, 0.286, 0.651] + ] + ] + ], + Cell[ + StyleData[ + "StringTypeLink", + StyleDefinitions -> StyleData["Link"] + ], + FontColor -> + Dynamic[ + If[ CurrentValue["MouseOver"], + RGBColor[0.969, 0.467, 0.0], + GrayLevel[0.467] + ] + ] + ], + Cell[ + StyleData["CharactersRefLink"], + ShowSpecialCharacters -> False + ], + Cell["Annotation", "Section"], + Cell[ + StyleData["Excluded"], + CellBracketOptions -> {"Color" -> RGBColor[0.9, 0.4, 0.4], "Thickness" -> 2}, + GeneratedCellStyles -> { + "Graphics" -> {"Graphics", "Excluded"}, + "Message" -> {"Message", "MSG", "Excluded"}, + "Output" -> {"Output", "Excluded"}, + "Print" -> {"Print", "Excluded"}, + "PrintTemporary" -> {"PrintTemporary", "Excluded"} + }, + CellFrameMargins -> 4, + CellFrameLabels -> { + { + None, + Cell[ + BoxData[ + TemplateBox[ + { + StyleBox[ + "\"excluded\"", + "ExcludedCellLabel", + StripOnInput -> False + ], + "\"Excluded cells will not appear anywhere in the published resource except for the definition notebook\"" + }, + "PrettyTooltipTemplate" + ] + ], + "ExcludedCellLabel" + ] + }, + {None, None} + }, + StyleMenuListing -> None, + Background -> RGBColor[1, 0.95, 0.95] + ], + Cell[ + StyleData[ + "ExcludedCellLabel", + StyleDefinitions -> StyleData["Text"] + ], + ShowStringCharacters -> False, + FontFamily -> "Source Sans Pro", + FontSize -> 9, + FontWeight -> Plain, + FontSlant -> Italic, + FontColor -> RGBColor[0.9, 0.4, 0.4, 0.5], + Background -> None + ], + Cell[ + StyleData["Comment", StyleDefinitions -> StyleData["Text"]], + CellFrame -> {{3, 0}, {0, 0}}, + CellMargins -> {{66, 0}, {1, 0}}, + CellElementSpacings -> {"ClosedCellHeight" -> 0}, + GeneratedCellStyles -> { + "Graphics" -> {"Graphics", "Comment"}, + "Message" -> {"Message", "MSG", "Comment"}, + "Output" -> {"Output", "Comment"}, + "Print" -> {"Print", "Comment"}, + "PrintTemporary" -> {"PrintTemporary", "Comment"} + }, + CellFrameColor -> RGBColor[0.88072, 0.61104, 0.14205], + CellFrameLabelMargins -> {{0, 10}, {0, 0}}, + FontColor -> GrayLevel[0.25], + Background -> RGBColor[0.982, 0.942, 0.871] + ], + Cell[ + StyleData[ + "AuthorComment", + StyleDefinitions -> StyleData["Comment"] + ], + GeneratedCellStyles -> { + "Graphics" -> {"Graphics", "AuthorComment"}, + "Message" -> {"Message", "MSG", "AuthorComment"}, + "Output" -> {"Output", "AuthorComment"}, + "Print" -> {"Print", "AuthorComment"}, + "PrintTemporary" -> {"PrintTemporary", "AuthorComment"} + }, + CellFrameColor -> RGBColor[0.36842, 0.50678, 0.7098], + Background -> RGBColor[0.905, 0.926, 0.956] + ], + Cell[ + StyleData[ + "ReviewerComment", + StyleDefinitions -> StyleData["Comment"] + ], + GeneratedCellStyles -> { + "Graphics" -> {"Graphics", "ReviewerComment"}, + "Message" -> {"Message", "MSG", "ReviewerComment"}, + "Output" -> {"Output", "ReviewerComment"}, + "Print" -> {"Print", "ReviewerComment"}, + "PrintTemporary" -> {"PrintTemporary", "ReviewerComment"} + }, + CellFrameColor -> RGBColor[0.56018, 0.69157, 0.19488], + Background -> RGBColor[0.934, 0.954, 0.879] + ], + Cell[ + StyleData[ + "CommentLabel", + StyleDefinitions -> StyleData["Text"] + ], + ShowStringCharacters -> False, + FontSlant -> "Italic", + PrivateFontOptions -> {"OperatorSubstitution" -> False}, + FontColor -> GrayLevel[0.5] + ], + Cell["Special Input", "Section"], + Cell[ + StyleData["FormObjectCell"], + CellMargins -> {{66, 66}, {16, 5}} + ], + Cell[ + StyleData[ + "LocalFileInput", + StyleDefinitions -> StyleData["Input"] + ], + CellFrameLabels -> { + { + None, + Cell[ + BoxData[ + ButtonBox[ + "\"Choose\"", + FrameMargins -> {{5, 5}, {0, 0}}, + BaseStyle -> {"Panel", FontSize -> 12}, + Evaluator -> Automatic, + Method -> "Queued", + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 1053094956087266899; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + If[ $VersionNumber >= 13.0, + DefinitionNotebookClient`LocalFileInputDialog[ + "Data", + ParentCell[EvaluationCell[]], + "Type" -> "FileOpen" + ], + MessageDialog[ + "This feature requires Wolfram Language version 13 or later." + ] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[1053094956087266899] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + Appearance :> + FEPrivate`FrontEndResource[ + "FEExpressions", + "GrayButtonNinePatchAppearance" + ] + ] + ] + ] + }, + {None, None} + } + ], + Cell[ + StyleData[ + "LocalDirectoryInput", + StyleDefinitions -> StyleData["Input"] + ], + CellFrameLabels -> { + { + None, + Cell[ + BoxData[ + ButtonBox[ + "\"Choose\"", + FrameMargins -> {{5, 5}, {0, 0}}, + BaseStyle -> {"Panel", FontSize -> 12}, + Evaluator -> Automatic, + Method -> "Queued", + ButtonFunction :> + With[ { RSNB`nb$ = ButtonNotebook[], RSNB`$cp$ = $ContextPath }, + Quiet[ + Block[ + { + $ContextPath = RSNB`$cp$, + ResourceSystemClient`$AsyncronousResourceInformationUpdates = + False, + DefinitionNotebookClient`$ButtonCodeID = None + }, + Internal`WithLocalSettings[ + DefinitionNotebookClient`$ButtonsDisabled = True; + + Once[ + ReleaseHold[ + CurrentValue[RSNB`nb$, {TaggingRules, "CompatibilityTest"}] + ], + "KernelSession" + ]; + + Needs["DefinitionNotebookClient`"], + Annotation[ + + DefinitionNotebookClient`$ButtonCodeID = + 4898876371082581810; + + DefinitionNotebookClient`CheckForUpdates[ + RSNB`nb$, + ReleaseHold[ + DefinitionNotebookClient`$ButtonCode = + HoldForm[ + If[ $VersionNumber >= 13.0, + DefinitionNotebookClient`LocalFileInputDialog[ + "Data", + ParentCell[EvaluationCell[]], + "Type" -> "Directory" + ], + MessageDialog[ + "This feature requires Wolfram Language version 13 or later." + ] + ] + ] + ] + ], + DefinitionNotebookClient`ButtonCodeID[4898876371082581810] + ], + DefinitionNotebookClient`$ButtonsDisabled = False; + ]; + ] + ] + ], + Appearance :> + FEPrivate`FrontEndResource[ + "FEExpressions", + "GrayButtonNinePatchAppearance" + ] + ] + ] + ] + }, + {None, None} + } + ], + Cell["Misc", "Section"], + Cell[StyleData["Item"], DefaultNewCellStyle -> "Item"], + Cell[ + StyleData[ + "RelatedSymbol", + StyleDefinitions -> StyleData["Item"] + ], + DefaultNewCellStyle -> {"RelatedSymbol", FontFamily -> "Source Sans Pro"}, + DefaultFormatType -> DefaultInputFormatType, + FormatType -> InputForm + ], + Cell[ + StyleData["ButtonText"], + FontFamily -> "Sans Serif", + FontSize -> 11, + FontWeight -> Bold, + FontColor -> RGBColor[0.459, 0.459, 0.459] + ], + Cell[ + StyleData["InlineFormula"], + HyphenationOptions -> {"HyphenationCharacter" -> "\[Continuation]"}, + LanguageCategory -> "Formula", + AutoSpacing -> True, + ScriptLevel -> 1, + SingleLetterItalics -> False, + SpanMaxSize -> 1, + StyleMenuListing -> None, + FontFamily -> "Source Sans Pro", + FontSize -> 1.0 * Inherited, + ButtonBoxOptions -> {Appearance -> {Automatic, None}}, + FractionBoxOptions -> {BaseStyle -> {SpanMaxSize -> Automatic}}, + GridBoxOptions -> { + GridBoxItemSize -> { + "Columns" -> {{Automatic}}, + "ColumnsIndexed" -> { }, + "Rows" -> {{1.0}}, + "RowsIndexed" -> { } + } + } + ], + Cell[ + StyleData["Input"], + CellProlog :> + Quiet[ + Block[{$ContextPath}, Once[ReleaseHold[CurrentValue[#1, {TaggingRules, "CompatibilityTest"}]], "KernelSession"]; If[$VersionNumber >= 12.2, Needs["DefinitionNotebookClient`"], Needs["ResourceSystemClient`DefinitionNotebook`"]]; DefinitionNotebookClient`LoadDefinitionNotebook["Data", #1]; ] &[ + InputNotebook[] + ] + ] + ], + Cell[ + StyleData["Code"], + CellProlog :> + Quiet[ + Block[{$ContextPath}, Once[ReleaseHold[CurrentValue[#1, {TaggingRules, "CompatibilityTest"}]], "KernelSession"]; If[$VersionNumber >= 12.2, Needs["DefinitionNotebookClient`"], Needs["ResourceSystemClient`DefinitionNotebook`"]]; DefinitionNotebookClient`LoadDefinitionNotebook["Data", #1]; ] &[ + InputNotebook[] + ] + ] + ], + Cell[ + StyleData["DockedCell"], + CellFrameColor -> GrayLevel[0.75], + Background -> GrayLevel[0.9] + ] + }, + Visible -> False, + StyleDefinitions -> "PrivateStylesheetFormatting.nb" + ] +] \ No newline at end of file diff --git a/Developer/VectorDatabases/SourceData/DocumentationURIs.jsonl b/Developer/VectorDatabases/SourceData/DocumentationURIs.jsonl new file mode 100644 index 00000000..86563c8b --- /dev/null +++ b/Developer/VectorDatabases/SourceData/DocumentationURIs.jsonl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a16442991caeaa42e704bd5aa39b43163c649caa243f85e8c3de8562e56358f +size 369614780 diff --git a/Developer/VectorDatabases/SourceData/WolframAlphaQueries.jsonl b/Developer/VectorDatabases/SourceData/WolframAlphaQueries.jsonl new file mode 100644 index 00000000..94fba276 --- /dev/null +++ b/Developer/VectorDatabases/SourceData/WolframAlphaQueries.jsonl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7475c4747948df7f0cb8d53ab9e1dd1f6bb9c50b387e48ed7cf3590cfd30808 +size 8028019 diff --git a/Developer/VectorDatabases/VectorDatabaseBuilder.wl b/Developer/VectorDatabases/VectorDatabaseBuilder.wl new file mode 100644 index 00000000..f4ff6f90 --- /dev/null +++ b/Developer/VectorDatabases/VectorDatabaseBuilder.wl @@ -0,0 +1,828 @@ +(* ::Section::Closed:: *) +(*Package Header*) +(* :!CodeAnalysis::BeginBlock:: *) +(* :!CodeAnalysis::Disable::SuspiciousSessionSymbol:: *) +BeginPackage[ "Wolfram`ChatbookVectorDatabaseBuilder`" ]; + +(* Exported symbols *) +`AddToVectorDatabaseData; +`BuildVectorDatabase; +`ExportVectorDatabaseData; +`GetEmbedding; +`ImportVectorDatabaseData; + +Begin[ "`Private`" ]; + +Needs[ "Developer`" -> None ]; +Needs[ "GeneralUtilities`" -> None ]; +Needs[ "Wolfram`Chatbook`" -> None ]; + +HoldComplete[ + System`CreateVectorDatabase, + System`VectorDatabaseObject +]; + +(* Temporary deployment URL: https://www.wolframcloud.com/obj/wolframai-content/VectorDatabases/DocumentationURIs.zip *) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Aliases*) +cachedTokenizer = Wolfram`Chatbook`Common`cachedTokenizer; +ensureDirectory = GeneralUtilities`EnsureDirectory; +packedArrayQ = Developer`PackedArrayQ; +readRawJSONString = Developer`ReadRawJSONString; +readWXFFile = Developer`ReadWXFFile; +toPackedArray = Developer`ToPackedArray; +writeRawJSONString = Developer`WriteRawJSONString; +writeWXFFile = Developer`WriteWXFFile; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Patterns*) +$$vectorDatabase = _VectorDatabaseObject? System`Private`ValidQ; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Configuration*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Vector Databases*) +$vectorDBSourceDirectory = FileNameJoin @ { DirectoryName @ $InputFileName, "SourceData" }; +$vectorDBTargetDirectory = FileNameJoin @ { DirectoryName[ $InputFileName, 3 ], "Assets", "VectorDatabases" }; + +$incrementalBuildBatchSize = 512; +$dbConnectivity = 16; +$dbExpansionAdd = 256; +$dbExpansionSearch = 2048; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Embeddings*) +$embeddingDimension = 384; +$embeddingType = "Integer8"; +$embeddingService = "Local"; +$embeddingModel = "SentenceBERT"; +$embeddingMaxTokens = 8000; +$maxSnippetLength = 4000; +$defaultEmbeddingLocation = FileNameJoin @ { $CacheBaseDirectory, "ChatbookDeveloper", "Embeddings" }; +$dataTag = "TextLiteral"; +$tokenizer := $tokenizer = cachedTokenizer[ "gpt-4o" ]; + +$embeddingLocation := $embeddingLocation = Replace[ + PersistentSymbol[ "ChatbookDeveloper/EmbeddingCacheLocation" ], + Except[ _File | _String ] :> $defaultEmbeddingLocation +]; + +$embeddingCache = <| |>; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Vector Databases*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*ImportVectorDatabaseData*) +ImportVectorDatabaseData // ClearAll; + +ImportVectorDatabaseData[ name_String ] := + Enclose @ Module[ { file, data }, + file = ConfirmBy[ FileNameJoin @ { $vectorDBSourceDirectory, name<>".jsonl" }, FileExistsQ, "File" ]; + data = ConfirmMatch[ jsonlImport @ file, { ___Association? AssociationQ }, "Data" ]; + data + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*ExportVectorDatabaseData*) +ExportVectorDatabaseData // ClearAll; + +ExportVectorDatabaseData[ name_String, data0_List ] := + Enclose @ Module[ { data, dir, file }, + data = ConfirmBy[ toDBData @ data0, dbDataQ, "Data" ]; + dir = ConfirmBy[ ensureDirectory @ $vectorDBSourceDirectory, DirectoryQ, "Directory" ]; + file = ConfirmBy[ FileNameJoin @ { dir, name<>".jsonl" }, StringQ, "File" ]; + ConfirmBy[ jsonlExport[ file, data ], FileExistsQ, "Export" ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*AddToVectorDatabaseData*) +AddToVectorDatabaseData // beginDefinition; +AddToVectorDatabaseData // Options = { "Tag" -> "TextLiteral", "Rebuild" -> False }; + +AddToVectorDatabaseData[ name_String, data_List, opts: OptionsPattern[ ] ] := + Enclose @ Module[ { tag, newData, existingData, combined, exported, rebuilt }, + + tag = ConfirmBy[ OptionValue[ "Tag" ], StringQ, "Tag" ]; + newData = ConfirmBy[ toDBData[ tag, data ], dbDataQ, "NewData" ]; + existingData = ConfirmBy[ ImportVectorDatabaseData @ name, dbDataQ, "ExistingData" ]; + combined = Union[ existingData, newData ]; + exported = ConfirmBy[ ExportVectorDatabaseData[ name, combined ], FileExistsQ, "Export" ]; + + rebuilt = If[ TrueQ @ OptionValue[ "Rebuild" ], + ConfirmBy[ BuildVectorDatabase @ name, $$vectorDatabase, "Rebuild" ], + Missing[ "NotAvailable" ] + ]; + + <| "Exported" -> exported, "Rebuilt" -> rebuilt |> + ]; + +AddToVectorDatabaseData // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*BuildVectorDatabase*) +BuildVectorDatabase // ClearAll; +BuildVectorDatabase // Options = { + "Connectivity" :> $dbConnectivity, + "ExpansionAdd" :> $dbExpansionAdd, + "ExpansionSearch" :> $dbExpansionSearch +}; + +BuildVectorDatabase[ All, opts: OptionsPattern[ ] ] := + Block[ + { + $dbConnectivity = OptionValue[ "Connectivity" ], + $dbExpansionAdd = OptionValue[ "ExpansionAdd" ], + $dbExpansionSearch = OptionValue[ "ExpansionSearch" ] + }, + AssociationMap[ BuildVectorDatabase, FileBaseName /@ FileNames[ "*.jsonl", $vectorDBSourceDirectory ] ] + ]; + +BuildVectorDatabase[ name_String, opts: OptionsPattern[ ] ] := Enclose[ + Block[ + { + $dbConnectivity = OptionValue[ "Connectivity" ], + $dbExpansionAdd = OptionValue[ "ExpansionAdd" ], + $dbExpansionSearch = OptionValue[ "ExpansionSearch" ] + }, + WithCleanup[ + SetDirectory @ ensureDirectory @ $vectorDBTargetDirectory, + ConfirmMatch[ buildVectorDatabase @ name, $$vectorDatabase, "Build" ], + ResetDirectory[ ] + ] + ] +]; + + +buildVectorDatabase // ClearAll; + +buildVectorDatabase[ name_String ] := + Enclose @ Catch @ Module[ { dir, rel, src, db, valueBag, count, n, stream, values }, + + loadEmbeddingCache[ ]; + + dir = ConfirmBy[ ensureDirectory @ { $vectorDBTargetDirectory, name }, DirectoryQ, "Directory" ]; + rel = ConfirmBy[ ResourceFunction[ "RelativePath" ][ dir ], DirectoryQ, "Relative" ]; + src = ConfirmBy[ FileNameJoin @ { $vectorDBSourceDirectory, name<>".jsonl" }, FileExistsQ, "File" ]; + + DeleteFile /@ FileNames[ { "*.wxf", "*.usearch" }, dir ]; + ConfirmAssert[ FileNames[ { "*.wxf", "*.usearch" }, dir ] === { }, "ClearedFilesCheck" ]; + + db = ConfirmMatch[ + CreateVectorDatabase[ + { }, + name, + "Database" -> "USearch", + WorkingPrecision -> $embeddingType, + GeneratedAssetLocation -> rel, + OverwriteTarget -> True + ], + $$vectorDatabase, + "Database" + ]; + + ConfirmBy[ setDBDefaults[ dir, name ], FileExistsQ, "SetDBDefaults" ]; + + valueBag = Internal`Bag[ ]; + count = ConfirmMatch[ lineCount @ src, _Integer? Positive, "LineCount" ]; + n = 0; + stream = ConfirmMatch[ OpenRead @ src, _InputStream, "Stream" ]; + + withProgress[ + While[ + NumericArrayQ @ ConfirmMatch[ addBatch[ db, stream, valueBag ], _NumericArray|EndOfFile, "Add" ], + n = Internal`BagLength @ valueBag + ], + <| + "Text" -> "Building database \""<>name<>"\"", + "ElapsedTime" -> Automatic, + "RemainingTime" -> Automatic, + "ItemTotal" :> count, + "ItemCurrent" :> n, + "Progress" :> Automatic + |>, + "Delay" -> 0, + UpdateInterval -> 1 + ]; + + saveEmbeddingCache[ ]; + + values = Internal`BagPart[ valueBag, All ]; + + ConfirmAssert[ Length @ values === count, "ValueCount" ]; + ConfirmAssert[ First @ db[ "Dimensions" ] === count, "VectorCount" ]; + + ConfirmBy[ + writeWXFFile[ FileNameJoin @ { dir, "Values.wxf" }, values, PerformanceGoal -> "Size" ], + FileExistsQ, + "Values" + ]; + + ConfirmBy[ + writeWXFFile[ + FileNameJoin @ { dir, "EmbeddingInformation.wxf" }, + <| + "Dimension" -> $embeddingDimension, + "Type" -> $embeddingType, + "Model" -> $embeddingModel, + "Service" -> $embeddingService + |> + ], + FileExistsQ, + "EmbeddingInformation" + ]; + + ConfirmBy[ rewriteDBData[ rel, name ], FileExistsQ, "Rewrite" ]; + + ConfirmMatch[ + VectorDatabaseObject @ File @ FileNameJoin @ { rel, name <> ".wxf" }, + $$vectorDatabase, + "Result" + ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*setDBDefaults*) +setDBDefaults // ClearAll; +setDBDefaults[ dir_, name_String ] := + Enclose @ Module[ { file, data }, + file = ConfirmBy[ FileNameJoin @ { dir, name<>".wxf" }, FileExistsQ, "File" ]; + data = ConfirmBy[ readWXFFile @ file, AssociationQ, "Data" ]; + ConfirmAssert[ AssociationQ @ data[ "VectorDatabaseInfo" ], "InfoCheck" ]; + data[ "VectorDatabaseInfo", "Connectivity" ] = ConfirmBy[ $dbConnectivity, IntegerQ, "Connectivity" ]; + data[ "VectorDatabaseInfo", "ExpansionAdd" ] = ConfirmBy[ $dbExpansionAdd, IntegerQ, "ExpansionAdd" ]; + data[ "VectorDatabaseInfo", "ExpansionSearch" ] = ConfirmBy[ $dbExpansionSearch, IntegerQ, "ExpansionSearch" ]; + ConfirmBy[ writeWXFFile[ file, data ], FileExistsQ, "Export" ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*addBatch*) +addBatch // ClearAll; + +addBatch[ db_VectorDatabaseObject, stream_InputStream, valueBag_Internal`Bag ] := + Enclose @ Catch @ Module[ { batch, text, values, embeddings }, + + batch = ConfirmMatch[ + readJSONLines[ stream, $incrementalBuildBatchSize ], + { __Association } | EndOfFile, + "Batch" + ]; + + If[ batch === EndOfFile, Throw @ EndOfFile ]; + + $lastBatch = batch; + text = ConfirmMatch[ batch[[ All, "Text" ]], { __String }, "Text" ]; + values = ConfirmMatch[ batch[[ All, "Value" ]], { __ }, "Values" ]; + embeddings = ConfirmBy[ $lastEmbedding = GetEmbedding @ text, NumericArrayQ, "Embeddings" ]; + ConfirmAssert[ Length @ values === Length @ embeddings, "LengthCheck" ]; + Confirm[ $lastAdded = AddToVectorDatabase[ db, embeddings ], "AddToVectorDatabase" ]; + Internal`StuffBag[ valueBag, values, 1 ]; + ConfirmMatch[ db[ "Dimensions" ], { Internal`BagLength @ valueBag, $embeddingDimension }, "DimensionCheck" ]; + embeddings + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*partition*) +partition // ClearAll; + +partition[ arr_NumericArray, size_Integer? Positive ] := + Module[ { max, steps }, + max = Length @ arr; + steps = Ceiling[ max / size ]; + Table[ arr[[ size * (i - 1) + 1 ;; Min[ size * i, max ] ]], { i, steps } ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*rewriteDBData*) +rewriteDBData // ClearAll; +rewriteDBData[ dir_? DirectoryQ, name_String ] := + Enclose @ Module[ { file, data, wxfName, vectorsName, new }, + file = ConfirmBy[ FileNameJoin @ { dir, name<>".wxf" }, FileExistsQ, "File" ]; + data = ConfirmBy[ readWXFFile @ file, AssociationQ, "Data" ]; + wxfName = ConfirmBy[ FileNameTake @ file, StringQ, "WXFName" ]; + vectorsName = ConfirmBy[ name<>"-vectors.usearch", StringQ, "VectorName" ]; + new = ConfirmBy[ createNewDBData[ name, wxfName, vectorsName, data ], AssociationQ, "NewData" ]; + ConfirmBy[ writeWXFFile[ file, new ], FileExistsQ, "Export" ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*createNewDBData*) +createNewDBData // ClearAll; +createNewDBData[ name_String, wxfName_String, vectorsName_String, data_Association ] := + Association[ + data, + "GeneratedAssetLocation" -> name, + "Location" -> File[ name <> "/" <> wxfName ], + "VectorDatabase" -> File[ name <> "/" <> vectorsName ] + ]; + +(* TODO: insert info about service, model, etc. *) + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*normalize*) +normalize // ClearAll; +normalize[ vectors_? MatrixQ ] := toPackedArray[ Normalize /@ vectors ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*toDBData*) +toDBData // ClearAll; +toDBData[ data_List ] := Reverse @ DeleteDuplicatesBy[ Reverse @ Union[ toDBData0 /@ data ], KeyTake @ { "Text", "Value" } ]; +toDBData[ tag_String, data_List ] := Block[ { $dataTag = tag }, toDBData @ data ]; + +toDBData0 // ClearAll; +toDBData0[ as_Association ] := KeySort @ trimSnippet @ <| "Tag" -> $dataTag, as |>; +toDBData0[ { text_String, value_ } ] := trimSnippet @ <| "Tag" -> $dataTag, "Text" -> text, "Value" -> value |>; +toDBData0[ text_String -> value_ ] := toDBData0 @ { text, value }; +toDBData0[ text_String ] := toDBData0 @ { text, text }; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*trimSnippet*) +trimSnippet // ClearAll; +trimSnippet[ str_String ] := StringTake[ str, UpTo[ $maxSnippetLength ] ]; +trimSnippet[ as: KeyValuePattern[ "Text" -> text_ ] ] := <| as, "Text" -> trimSnippet @ text |>; +trimSnippet[ other_ ] := trimSnippet @ TextString @ other; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*dbDataQ*) +dbDataQ // ClearAll; +dbDataQ[ data_List ] := AllTrue[ data, dbDataQ0 ]; +dbDataQ[ ___ ] := False; + +dbDataQ0 // ClearAll; +dbDataQ0[ KeyValuePattern @ { "Tag" -> _String, "Text" -> _String, "Value" -> _ } ] := True; +dbDataQ0[ ___ ] := False; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Embeddings*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*GetEmbedding*) +GetEmbedding // ClearAll; + +GetEmbedding[ string_String ] := First[ getEmbeddings @ { string }, $Failed ]; +GetEmbedding[ KeyValuePattern[ "Text" -> string_String ] ] := GetEmbedding @ string; +GetEmbedding[ as: { __Association } ] := GetEmbedding @ as[[ All, "Text" ]]; + +GetEmbedding[ strings: { ___String } ] := + Enclose @ Module[ { embeddings, packed }, + embeddings = ConfirmBy[ getEmbeddings @ strings, AssociationQ, "Embeddings" ]; + packed = ConfirmBy[ NumericArray[ Lookup[ embeddings, strings ], "Integer8" ], NumericArrayQ, "Packed" ]; + packed + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getEmbeddings*) +getEmbeddings // ClearAll; +getEmbeddings[ strings0_List ] := + Module[ { strings }, + strings = DeleteDuplicates @ strings0; + setProgress[ "Checking cache for", Length @ strings ]; + withProgress[ + getEmbeddings0 @ strings, + <| + "ElapsedTime" -> Automatic, + "ItemAction" :> $itemAction, + "ItemName" -> "embeddings", + "ItemTotal" :> $totalItems, + "ItemCurrent" :> $currentItem + |>, + "OuterUpdateInterval" -> 1, + UpdateInterval -> 1 + ] + ]; + + +getEmbeddings0 // ClearAll; +getEmbeddings0[ strings_List ] := + Enclose @ Module[ { notCached }, + notCached = Select[ strings, Function @ PreemptProtect[ $currentItem++; MissingQ @ getCachedEmbedding @ # ] ]; + setProgress[ "Creating", Length @ notCached ]; + Confirm[ getAndCacheEmbeddings @ notCached, "GetAndCacheEmbeddings" ]; + setProgress[ "Checking", Length @ strings ]; + AssociationMap[ Function @ PreemptProtect[ $currentItem++; getCachedEmbedding @ # ], strings ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*toByteVector*) +toByteVector // ClearAll; +toByteVector[ vector_ ] := NumericArray[ 127.5 * vector - 0.5, "Integer8", "ClipAndRound" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*setProgress*) +setProgress // ClearAll; + +setProgress[ text_String, total_Integer ] := + setProgress[ text, total, 0 ]; + +setProgress[ text_String, total_Integer, current_Integer ] := PreemptProtect[ + $itemAction = text; + $totalItems = total; + $currentItem = current; +]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getCachedEmbedding*) +getCachedEmbedding // ClearAll; + +getCachedEmbedding[ string_String ] := + With[ { embedding = $embeddingCache[ string ] }, + embedding /; NumericArrayQ @ embedding + ]; + +getCachedEmbedding[ string_String ] := + If[ $embeddingModel === "SentenceBERT", + Missing[ "NotCached" ], + getCachedEmbedding[ string, embeddingHash @ string ] + ]; + +getCachedEmbedding[ string_String, hash_String ] := + Catch @ Module[ { file, vector }, + file = embeddingLocation @ string; + If[ ! FileExistsQ @ file, Throw @ Missing[ "NotCached" ] ]; + vector = readWXFFile @ file; + If[ NumericArrayQ @ vector, + getCachedEmbedding[ string, hash ] = vector, + Failure[ "BadCachedVector", <| "File" -> file, "Vector" -> vector |> ] + ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getAndCacheEmbeddings*) +getAndCacheEmbeddings // ClearAll; +getAndCacheEmbeddings[ strings_List ] := Catch[ FixedPoint[ getAndCacheEmbeddings0, strings ], $tag ]; + + +getAndCacheEmbeddings0 // ClearAll; + +getAndCacheEmbeddings0[ { } ] := Throw[ "Done", $tag ]; + +getAndCacheEmbeddings0[ strings: { __String } ] := Enclose[ + Module[ { notCachedTokens, acc, n, batch, remaining, batchVectors }, + notCachedTokens = ConfirmMatch[ tokenCount /@ strings, { __Integer }, "Tokens" ]; + acc = Accumulate @ notCachedTokens; + n = ConfirmBy[ LengthWhile[ acc, LessThan[ $embeddingMaxTokens ] ], Positive, "Count" ]; + { batch, remaining } = ConfirmMatch[ TakeDrop[ strings, UpTo @ n ], { { __String }, { ___String } }, "Batch" ]; + batchVectors = ConfirmBy[ createEmbeddings @ batch, AssociationQ, "Vectors" ]; + ConfirmAssert[ AllTrue[ batchVectors, NumericArrayQ ], "PackedArrayTest" ]; + If[ remaining === { }, Throw[ "Done", $tag ], remaining ] + ], + Throw[ #, $tag ] & +]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*createEmbeddings*) +createEmbeddings // ClearAll; + +createEmbeddings[ strings: { __String } ] /; $embeddingModel === "SentenceBERT" := + Catch @ Module[ { vectors, small, meta, pairs }, + $currentItem = If[ IntegerQ @ $currentItem, $currentItem + Length @ strings, Length @ strings ]; + vectors = Quiet @ toPackedArray @ sentenceBERTEmbedding @ strings; + meta = <| "Strings" -> strings, "Vectors" -> vectors |>; + If[ ! packedArrayQ @ vectors, Throw @ Failure[ "EmbeddingFailure", meta ] ]; + If[ Length @ vectors =!= Length @ strings, Throw @ Failure[ "EmbeddingShapeFailure", meta ] ]; + small = toByteVector@*Normalize /@ vectors[[ All, 1 ;; $embeddingDimension ]]; + pairs = Transpose @ { strings, small }; + Association[ cacheEmbedding /@ pairs ] + ]; + +createEmbeddings[ strings: { __String } ] := + Catch @ Module[ { resp, vectors, small, meta, pairs }, + $currentItem = If[ IntegerQ @ $currentItem, $currentItem + Length @ strings, Length @ strings ]; + resp = ServiceExecute[ $embeddingService, "RawEmbedding", { "input" -> strings, "model" -> $embeddingModel } ]; + vectors = Quiet @ toPackedArray @ resp[[ "data", All, "embedding" ]]; + meta = <| "Strings" -> strings, "Response" -> resp, "Vectors" -> vectors |>; + If[ ! packedArrayQ @ vectors, Throw @ Failure[ "EmbeddingServiceFailure", meta ] ]; + If[ Length @ vectors =!= Length @ strings, Throw @ Failure[ "EmbeddingShapeFailure", meta ] ]; + small = toByteVector@*Normalize /@ vectors[[ All, 1 ;; $embeddingDimension ]]; + pairs = Transpose @ { strings, small }; + Association[ cacheEmbedding /@ pairs ] + ]; + +createEmbeddings[ { } ] := + <| |>; + +createEmbeddings[ string_String ] := + First[ createEmbeddings @ { string }, $Failed ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*sentenceBERTEmbedding*) +sentenceBERTEmbedding // beginDefinition; + +sentenceBERTEmbedding[ args___ ] := ( + Needs[ "SemanticSearch`" -> None ]; + SemanticSearch`SemanticSearch`Private`SentenceBERTEmbedding @ args +); + +sentenceBERTEmbedding // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*cacheEmbedding*) +cacheEmbedding // ClearAll; + +cacheEmbedding[ string_String, vector_NumericArray ] /; $embeddingModel === "SentenceBERT" := ( + $embeddingCache[ string ] = vector; + string -> vector +); + +cacheEmbedding[ string_String, vector_NumericArray ] := + cacheEmbedding[ string, vector, embeddingHash @ string ]; + +cacheEmbedding[ string_String, vector_NumericArray, hash_String ] := + Enclose @ Module[ { file }, + file = ConfirmBy[ embeddingLocation @ string, StringQ, "File" ]; + ensureDirectory @ DirectoryName @ file; + ConfirmBy[ writeWXFFile[ file, vector ], FileExistsQ, "Export" ]; + ConfirmAssert @ NumericArrayQ @ readWXFFile @ file; + $embeddingCache[ string ] = vector; + string -> vector + ]; + +cacheEmbedding[ { string_, vector_ } ] := + cacheEmbedding[ string, vector ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*loadEmbeddingCache*) +loadEmbeddingCache // ClearAll; + +loadEmbeddingCache[ ] := + Enclose @ Catch @ Module[ { hash, file, cached, keys, values }, + + hash = ConfirmBy[ + Hash[ { $embeddingModel, $embeddingService, $embeddingDimension, $embeddingType }, "SHA" ], + IntegerQ, + "Hash" + ]; + + file = ConfirmBy[ + FileNameJoin @ { $embeddingLocation, "EmbeddingCache_" <> IntegerString[ hash, 36 ] <> ".wxf" }, + StringQ, + "File" + ]; + + If[ ! AssociationQ @ $embeddingCache, $embeddingCache = <| |> ]; + + If[ ! FileExistsQ @ file, Throw @ $embeddingCache ]; + + cached = ConfirmBy[ readWXFFile @ file, AssociationQ, "Cached" ]; + keys = ConfirmMatch[ cached[ "Keys" ], { ___String }, "Keys" ]; + values = ConfirmBy[ cached[ "Values" ], NumericArrayQ, "Values" ]; + + MapIndexed[ ($embeddingCache[ #1 ] = values[[ First[ #2 ] ]]) &, keys ]; + $embeddingCache + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*saveEmbeddingCache*) +saveEmbeddingCache // ClearAll; + +saveEmbeddingCache[ ] := + Enclose @ Module[ { hash, file, keys, values }, + + loadEmbeddingCache[ ]; + + hash = ConfirmBy[ + Hash[ { $embeddingModel, $embeddingService, $embeddingDimension, $embeddingType }, "SHA" ], + IntegerQ, + "Hash" + ]; + + file = ConfirmBy[ + FileNameJoin @ { $embeddingLocation, "EmbeddingCache_" <> IntegerString[ hash, 36 ] <> ".wxf" }, + StringQ, + "File" + ]; + + ConfirmAssert[ AssociationQ @ $embeddingCache, "CacheCheck" ]; + + keys = ConfirmMatch[ Keys @ $embeddingCache, { ___String }, "Keys" ]; + values = ConfirmBy[ NumericArray[ Values @ $embeddingCache, $embeddingType ], NumericArrayQ, "Values" ]; + + writeWXFFile[ file, <| "Keys" -> keys, "Values" -> values |> ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getNamedEmbeddings*) +getNamedEmbeddings // ClearAll; +getNamedEmbeddings[ name_String, strings_List ] := + Enclose @ Module[ { embeddings }, + ConfirmBy[ loadNamedEmbeddingCache @ name, AssociationQ, "LoadCache" ]; + embeddings = ConfirmBy[ getEmbeddings @ strings, AssociationQ, "GetEmbeddings" ]; + ConfirmBy[ saveNamedEmbeddingCache[ name, embeddings ], AssociationQ, "Save" ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*loadNamedEmbeddingCache*) +loadNamedEmbeddingCache // ClearAll; +loadNamedEmbeddingCache[ name_String ] := + Enclose @ Catch @ Module[ { file, data }, + file = FileNameJoin @ { $embeddingLocation, name<>".wxf" }; + If[ ! FileExistsQ @ file, Throw @ <| |> ]; + data = ConfirmBy[ readWXFFile @ file, AssociationQ, "Data" ]; + KeyValueMap[ Function[ getCachedEmbedding[ #1, embeddingHash @ #1 ] = #2 ], data ]; + data + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*saveNamedEmbeddingCache*) +saveNamedEmbeddingCache // ClearAll; +saveNamedEmbeddingCache[ name_String, data_Association ] := + Enclose @ Module[ { dir, file }, + dir = ConfirmBy[ ensureDirectory @ $embeddingLocation, DirectoryQ, "Directory" ]; + file = FileNameJoin @ { dir, name<>".wxf" }; + ConfirmBy[ writeWXFFile[ file, data ], FileExistsQ, "Export" ]; + data + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*tokenCount*) +tokenCount // ClearAll; +tokenCount[ str_String ] := Enclose[ tokenCount[ str ] = Length @ ConfirmMatch[ $tokenizer @ str, { ___Integer } ] ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*embeddingLocation*) +embeddingLocation // ClearAll; + +embeddingLocation[ string_String ] := + embeddingLocation[ string, embeddingHash @ string ]; + +embeddingLocation[ string_String, hash_String ] := + Enclose @ Module[ { dir, file }, + dir = ConfirmBy[ ensureDirectory @ $embeddingLocation, DirectoryQ, "Directory" ]; + file = ConfirmBy[ FileNameJoin @ { dir, StringTake[ hash, 3 ], hash<>".wxf" }, StringQ, "File" ]; + embeddingLocation[ string ] = file + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*embeddingHash*) +embeddingHash // ClearAll; +embeddingHash[ string_String ] := + Enclose @ Module[ { model, service, dimension, hash }, + model = ConfirmBy[ $embeddingModel , StringQ , "Model" ]; + service = ConfirmBy[ $embeddingService , StringQ , "Service" ]; + dimension = ConfirmBy[ $embeddingDimension, IntegerQ, "Dimension" ]; + hash = ConfirmBy[ Hash[ { string, model, service, dimension }, "SHA", "HexString" ], StringQ, "Hash" ]; + embeddingHash[ string ] = hash + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Misc Utilities*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*withProgress*) +withProgress // ClearAll; +withProgress // Attributes = { HoldFirst }; +withProgress[ eval_, a___ ] := Block[ { withProgress = # & }, Progress`EvaluateWithProgress[ eval, a ] ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*lineCount*) +lineCount // ClearAll; +lineCount[ file_? FileExistsQ ] := + Module[ { count, stream }, + Close /@ Streams @ ExpandFileName @ file; + count = 0; + WithCleanup[ + stream = OpenRead @ file, + While[ Skip[ stream, String ] === Null, count++ ], + Close @ stream + ]; + count + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*readJSONLines*) +readJSONLines // ClearAll; + +readJSONLines[ stream_InputStream, n_Integer? Positive ] := + Enclose @ Catch @ Module[ { lines, utf8Lines, jsonData }, + lines = ConfirmMatch[ ReadList[ stream, String, n ], { ___String }, "Lines" ]; + If[ lines === { }, Throw @ EndOfFile ]; + utf8Lines = ConfirmMatch[ FromCharacterCode[ ToCharacterCode @ lines, "UTF-8" ], { __String }, "UTF8" ]; + jsonData = ConfirmMatch[ readRawJSONString /@ utf8Lines, { __Association? AssociationQ }, "JSON" ]; + jsonData + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*jsonlImport*) +jsonlImport // ClearAll; +jsonlImport[ file_? FileExistsQ ] := + Enclose @ Module[ { lines, fromJSON }, + lines = ConfirmMatch[ readLines @ file, { ___String }, "Lines" ]; + fromJSON = ConfirmBy[ readRawJSONString @ #, Not@*FailureQ, "JSON" ] &; + ConfirmMatch[ fromJSON /@ lines, { Except[ _? FailureQ ]... }, "Data" ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*jsonlExport*) +jsonlExport // ClearAll; +jsonlExport[ file_, data_List ] := + Enclose @ Module[ { toJSON, lines }, + toJSON = ConfirmBy[ writeRawJSONString[ #, "Compact" -> True ], StringQ, "JSON" ] &; + lines = ConfirmMatch[ toJSON /@ data, { ___String? StringQ }, "Lines" ]; + ConfirmBy[ writeLines[ file, lines ], FileExistsQ, "Export" ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*readLines*) +readLines // ClearAll; +readLines[ file_ ] := Enclose @ StringSplit[ ConfirmBy[ readString @ file, StringQ, "String" ], "\n" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*writeLines*) +writeLines // ClearAll; +writeLines[ file_, lines: { ___String } ] := writeString[ file, StringRiffle[ lines, "\n" ] ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*readString*) +readString // ClearAll; +readString[ file_ ] := + Enclose @ Module[ { bytes }, + bytes = ConfirmBy[ readByteArray @ file, ByteArrayQ, "Bytes" ]; + ConfirmBy[ Check[ ByteArrayToString @ bytes, $Failed ], StringQ, "String" ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*writeString*) +writeString // ClearAll; +writeString[ file_, string_String ] := + Enclose @ Module[ { bytes }, + bytes = ConfirmBy[ Check[ StringToByteArray @ string, $Failed ], ByteArrayQ, "Bytes" ]; + ConfirmBy[ writeByteArray[ file, bytes ], FileExistsQ, "Write" ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*readByteArray*) +readByteArray // ClearAll; +readByteArray[ file_ ] := + Enclose @ WithCleanup[ + Quiet @ Close @ file, + ConfirmBy[ Replace[ ReadByteArray @ file, EndOfFile :> ByteArray @ { } ], ByteArrayQ ], + Quiet @ Close @ file + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*writeByteArray*) +writeByteArray // ClearAll; +writeByteArray[ file_, bytes_ByteArray ] := + Enclose @ WithCleanup[ + Quiet @ Close @ file, + ConfirmBy[ BinaryWrite[ file, bytes ], FileExistsQ ], + Quiet @ Close @ file + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +End[ ]; +EndPackage[ ]; +(* :!CodeAnalysis::EndBlock:: *) \ No newline at end of file diff --git a/FrontEnd/StyleSheets/Chatbook.nb b/FrontEnd/StyleSheets/Chatbook.nb index 10f85f2b..1a0aa3f5 100644 --- a/FrontEnd/StyleSheets/Chatbook.nb +++ b/FrontEnd/StyleSheets/Chatbook.nb @@ -793,516 +793,54 @@ Notebook[ |> |>, ComponentwiseContextMenu -> <| - "CellBracket" -> { - MenuItem[ - "Ask AI Assistant", - KernelExecute[ - With[ { Wolfram`ChatNB`nbo = InputNotebook[] }, - {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, - Quiet[Needs["Wolfram`Chatbook`" -> None]]; - Symbol["Wolfram`Chatbook`ChatbookAction"][ - "Ask", - Wolfram`ChatNB`nbo, - Wolfram`ChatNB`cells - ] - ] - ], - MenuEvaluator -> Automatic, - Method -> "Queued" - ], - MenuItem[ - "Include/Exclude From AI Chat", - KernelExecute[ - With[ { Wolfram`ChatNB`nbo = InputNotebook[] }, - {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, - Quiet[Needs["Wolfram`Chatbook`" -> None]]; - Symbol["Wolfram`Chatbook`ChatbookAction"][ - "ExclusionToggle", - Wolfram`ChatNB`nbo, - Wolfram`ChatNB`cells - ] - ] - ], - MenuEvaluator -> Automatic, - Method -> "Queued" - ], - Delimiter, - MenuItem["Cu&t", "Cut"], - MenuItem["&Copy", "Copy"], - MenuItem["&Paste", FrontEnd`Paste[After]], - Menu[ - "Cop&y As", - { - MenuItem["Plain &Text", FrontEnd`CopySpecial["PlainText"]], - MenuItem["&Input Text", FrontEnd`CopySpecial["InputText"]], - MenuItem[ - "&LaTeX", - KernelExecute[ToExpression["FrontEnd`CopyAsTeX[]"]], - MenuEvaluator -> "System" - ], - MenuItem[ - "M&athML", - KernelExecute[ToExpression["FrontEnd`CopyAsMathML[]"]], - MenuEvaluator -> "System" - ], - Delimiter, - MenuItem[ - "Cell &Object", - FrontEnd`CopySpecial["CellObject"] - ], - MenuItem[ - "&Cell Expression", - FrontEnd`CopySpecial["CellExpression"] - ], - MenuItem[ - "&Notebook Expression", - FrontEnd`CopySpecial["NotebookExpression"] - ] - } - ], - Delimiter, - MenuItem["&Evaluate Cell", "EvaluateCells"], - MenuItem[ - "&Remove from Evaluation Queue", - "RemoveFromEvaluationQueue" - ], - MenuItem[ - "Analyze Cell", - KernelExecute[ - Needs["CodeInspector`"]; - CodeInspector`AttachAnalysis[ - SelectedCells[InputNotebook[]] - ] - ], - MenuEvaluator -> Automatic, - Method -> "Queued" - ], - Delimiter, - Menu[ - "Con&vert To", - { - MenuItem["&InputForm", "SelectionConvert" -> InputForm], - MenuItem[ - "&Raw InputForm", - "SelectionConvert" -> RawInputForm - ], - MenuItem["&OutputForm", "SelectionConvert" -> OutputForm], - MenuItem[ - "First Convert to BoxForm", - "MenuListConvertFormatTypes", - MenuAnchor -> True - ], - Delimiter, - MenuItem["&Bitmap", "SelectionConvert" -> "Bitmap"] - } - ], - ToggleMenuItem[ - "&Initialization Cell", - InitializationCell -> Toggle - ], - MenuItem["Add/Remove Cell Tags...", "CellTagsEditDialog"], - Delimiter, - Menu[ - "&Style", - { - LinkedItems[ - { - MenuItem[ - "Start Cell Style Names", - "MenuListStyles", - MenuAnchor -> True - ] - } - ], - Delimiter, - MenuItem["&Other...", "StyleOther"] - } - ], - Menu[ - "Back&ground Color", - { - MenuItem["Palette...", "BackgroundDialog"], - Delimiter, - LinkedItems[ - { - MenuItem["None", Background -> None], - Delimiter, - MenuItem["Black", Background -> GrayLevel[0]], - MenuItem["Gray", Background -> GrayLevel[0.5]], - MenuItem["Light Gray", Background -> GrayLevel[0.85]], - MenuItem["White", Background -> GrayLevel[1]], - Delimiter, - MenuItem[ - "Light Blue", - Background -> RGBColor[0.87, 0.94, 1] - ], - MenuItem[ - "Light Brown", - Background -> RGBColor[0.94, 0.91, 0.88] - ], - MenuItem["Light Cyan", Background -> RGBColor[0.9, 1, 1]], - MenuItem[ - "Light Green", - Background -> RGBColor[0.88, 1, 0.88] - ], - MenuItem[ - "Light Magenta", - Background -> RGBColor[1, 0.9, 1] - ], - MenuItem[ - "Light Orange", - Background -> RGBColor[1, 0.9, 0.8] - ], - MenuItem[ - "Light Pink", - Background -> RGBColor[1, 0.925, 0.925] - ], - MenuItem[ - "Light Purple", - Background -> RGBColor[0.94, 0.88, 0.94] - ], - MenuItem[ - "Light Red", - Background -> RGBColor[1, 0.85, 0.85] - ], - MenuItem[ - "Light Yellow", - Background -> RGBColor[1, 1, 0.85] - ], - Delimiter, - MenuItem["Orange", Background -> RGBColor[1, 0.5, 0]], - MenuItem["Pink", Background -> RGBColor[1, 0.5, 0.5]], - MenuItem["Yellow", Background -> RGBColor[1, 1, 0]] - } - ] - } - ], - Menu[ - "Si&ze", - { - MenuItem["&Larger", FontSize -> Larger], - MenuItem["&Smaller", FontSize -> Smaller], - Delimiter, - LinkedItems[ - { - MenuItem["&9 Point", FontSize -> 9], - MenuItem["1&0 Point", FontSize -> 10], - MenuItem["&12 Point", FontSize -> 12], - MenuItem["1&4 Point", FontSize -> 14], - MenuItem["1&6 Point", FontSize -> 16], - MenuItem["1&8 Point", FontSize -> 18], - MenuItem["&24 Point", FontSize -> 24], - MenuItem["&36 Point", FontSize -> 36], - MenuItem["&72 Point", FontSize -> 72] - } - ] - } - ], - MenuItem["Clear &Formatting", "ClearCellOptions"], - Delimiter, - MenuItem["Save Se&lection As...", "SelectionSaveSpecial"], - MenuItem["Print Selection...", "PrintSelectionDialog"], - MenuItem["Spea&k Selection", "SelectionSpeak"], - Delimiter, - MenuItem[ - "Properties...", - "OptionsDialog", - Scope -> Selection - ] - }, - "CellGroup" -> { - MenuItem[ - "Include/Exclude From AI Chat", - KernelExecute[ - With[ { Wolfram`ChatNB`nbo = InputNotebook[] }, - {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, - Quiet[Needs["Wolfram`Chatbook`" -> None]]; - Symbol["Wolfram`Chatbook`ChatbookAction"][ - "ExclusionToggle", - Wolfram`ChatNB`nbo, - Wolfram`ChatNB`cells - ] - ] - ], - MenuEvaluator -> Automatic, - Method -> "Queued" - ], - Delimiter, - MenuItem["Cu&t", "Cut"], - MenuItem["&Copy", "Copy"], - MenuItem["&Paste", FrontEnd`Paste[After]], - Menu[ - "Cop&y As", - { - MenuItem["Plain &Text", FrontEnd`CopySpecial["PlainText"]], - MenuItem[ - "Cell &Object", - FrontEnd`CopySpecial["CellObject"] - ], - MenuItem[ - "&Cell Expression", - FrontEnd`CopySpecial["CellExpression"] + "CellBracket" -> + Dynamic[ + FEPrivate`Join[{MenuItem[#1, KernelExecute[With[{Wolfram`ChatNB`nbo = InputNotebook[]}, {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, Quiet[Needs["Wolfram`Chatbook`" -> None]]; Symbol["Wolfram`Chatbook`ChatbookAction"]["Ask", Wolfram`ChatNB`nbo, Wolfram`ChatNB`cells]]], MenuEvaluator -> Automatic, Method -> "Queued"], MenuItem[#2, KernelExecute[With[{Wolfram`ChatNB`nbo = InputNotebook[]}, {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, Quiet[Needs["Wolfram`Chatbook`" -> None]]; Symbol["Wolfram`Chatbook`ChatbookAction"]["ExclusionToggle", Wolfram`ChatNB`nbo, Wolfram`ChatNB`cells]]], MenuEvaluator -> Automatic, Method -> "Queued"], Delimiter}, FEPrivate`FrontEndResource["ContextMenus", "CellBracket"]] &[ + FEPrivate`FrontEndResource[ + "ChatbookStrings", + "StylesheetContextMenuAskAI" ], - MenuItem[ - "&Notebook Expression", - FrontEnd`CopySpecial["NotebookExpression"] + FEPrivate`FrontEndResource[ + "ChatbookStrings", + "StylesheetContextMenuIncludeExclude" ] - } - ], - Delimiter, - MenuItem["&Merge Cells", "CellMerge"], - MenuItem["&Ungroup Cells", "CellUngroup"], - Delimiter, - MenuItem["Open&/Close Group", "OpenCloseGroup"], - MenuItem["&Open All Subgroups", "SelectionOpenAllGroups"], - MenuItem["C&lose All Subgroups", "SelectionCloseAllGroups"], - Delimiter, - MenuItem["&Evaluate Cells", "EvaluateCells"], - MenuItem[ - "&Remove from Evaluation Queue", - "RemoveFromEvaluationQueue" - ], - MenuItem[ - "Analyze Cells", - KernelExecute[ - Needs["CodeInspector`"]; - CodeInspector`AttachAnalysis[ - SelectedCells[InputNotebook[]] - ] - ], - MenuEvaluator -> Automatic, - Method -> "Queued" - ], - Delimiter, - MenuItem["Clear &Formatting", "ClearCellOptions"], - Menu[ - "&Style", - { - LinkedItems[ - { - MenuItem[ - "Start Cell Style Names", - "MenuListStyles", - MenuAnchor -> True - ] - } - ], - Delimiter, - MenuItem["&Other...", "StyleOther"] - } - ] - }, - "CellRange" -> { - MenuItem[ - "Include/Exclude From AI Chat", - KernelExecute[ - With[ { Wolfram`ChatNB`nbo = InputNotebook[] }, - {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, - Quiet[Needs["Wolfram`Chatbook`" -> None]]; - Symbol["Wolfram`Chatbook`ChatbookAction"][ - "ExclusionToggle", - Wolfram`ChatNB`nbo, - Wolfram`ChatNB`cells - ] - ] - ], - MenuEvaluator -> Automatic, - Method -> "Queued" + ] ], - Delimiter, - MenuItem["Cu&t", "Cut"], - MenuItem["&Copy", "Copy"], - MenuItem["&Paste", FrontEnd`Paste[After]], - Menu[ - "Cop&y As", - { - MenuItem["Plain &Text", FrontEnd`CopySpecial["PlainText"]], - MenuItem[ - "Cell &Object", - FrontEnd`CopySpecial["CellObject"] - ], - MenuItem[ - "&Cell Expression", - FrontEnd`CopySpecial["CellExpression"] - ], - MenuItem[ - "&Notebook Expression", - FrontEnd`CopySpecial["NotebookExpression"] + "CellGroup" -> + Dynamic[ + FEPrivate`Join[{MenuItem[#1, KernelExecute[With[{Wolfram`ChatNB`nbo = InputNotebook[]}, {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, Quiet[Needs["Wolfram`Chatbook`" -> None]]; Symbol["Wolfram`Chatbook`ChatbookAction"]["ExclusionToggle", Wolfram`ChatNB`nbo, Wolfram`ChatNB`cells]]], MenuEvaluator -> Automatic, Method -> "Queued"], Delimiter}, FEPrivate`FrontEndResource["ContextMenus", "CellGroup"]] &[ + FEPrivate`FrontEndResource[ + "ChatbookStrings", + "StylesheetContextMenuIncludeExclude" ] - } - ], - Delimiter, - MenuItem["&Merge Cells", "CellMerge"], - MenuItem["&Group Cells", "CellGroup"], - Delimiter, - MenuItem["&Open All Subgroups", "SelectionOpenAllGroups"], - MenuItem["C&lose All Subgroups", "SelectionCloseAllGroups"], - Delimiter, - MenuItem["&Evaluate Cells", "EvaluateCells"], - MenuItem[ - "&Remove from Evaluation Queue", - "RemoveFromEvaluationQueue" + ] ], - MenuItem[ - "Analyze Cells", - KernelExecute[ - Needs["CodeInspector`"]; - CodeInspector`AttachAnalysis[ - SelectedCells[InputNotebook[]] + "CellRange" -> + Dynamic[ + FEPrivate`Join[{MenuItem[#1, KernelExecute[With[{Wolfram`ChatNB`nbo = InputNotebook[]}, {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, Quiet[Needs["Wolfram`Chatbook`" -> None]]; Symbol["Wolfram`Chatbook`ChatbookAction"]["ExclusionToggle", Wolfram`ChatNB`nbo, Wolfram`ChatNB`cells]]], MenuEvaluator -> Automatic, Method -> "Queued"], Delimiter}, FEPrivate`FrontEndResource["ContextMenus", "CellRange"]] &[ + FEPrivate`FrontEndResource[ + "ChatbookStrings", + "StylesheetContextMenuIncludeExclude" ] - ], - MenuEvaluator -> Automatic, - Method -> "Queued" - ], - Delimiter, - MenuItem["Clear &Formatting", "ClearCellOptions"], - Menu[ - "&Style", - { - LinkedItems[ - { - MenuItem[ - "Start Cell Style Names", - "MenuListStyles", - MenuAnchor -> True - ] - } - ], - Delimiter, - MenuItem["&Other...", "StyleOther"] - } + ] ] - } |> ], Cell[ StyleData["ChatStyleSheetInformation"], - TaggingRules -> <|"StyleSheetVersion" -> "1.5.0.3931772186"|> + TaggingRules -> <|"StyleSheetVersion" -> "1.5.1.3936664622"|> ], Cell[ StyleData["Text"], - ContextMenu -> { - MenuItem[ - "Ask AI Assistant", - KernelExecute[ - With[ { Wolfram`ChatNB`nbo = InputNotebook[] }, - {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, - Quiet[Needs["Wolfram`Chatbook`" -> None]]; - Symbol["Wolfram`Chatbook`ChatbookAction"][ - "Ask", - Wolfram`ChatNB`nbo, - Wolfram`ChatNB`cells - ] - ] - ], - MenuEvaluator -> Automatic, - Method -> "Queued" - ], - Delimiter, - MenuItem["Cu&t", "Cut"], - MenuItem["&Copy", "Copy"], - MenuItem["&Paste", FrontEnd`Paste[After]], - Menu[ - "Cop&y As", - { - MenuItem["Plain &Text", FrontEnd`CopySpecial["PlainText"]], - MenuItem["&Input Text", FrontEnd`CopySpecial["InputText"]], - MenuItem[ - "&LaTeX", - KernelExecute[ToExpression["FrontEnd`CopyAsTeX[]"]], - MenuEvaluator -> "System" - ], - MenuItem[ - "M&athML", - KernelExecute[ToExpression["FrontEnd`CopyAsMathML[]"]], - MenuEvaluator -> "System" - ], - Delimiter, - MenuItem[ - "Cell &Object", - FrontEnd`CopySpecial["CellObject"] - ], - MenuItem[ - "&Cell Expression", - FrontEnd`CopySpecial["CellExpression"] - ], - MenuItem[ - "&Notebook Expression", - FrontEnd`CopySpecial["NotebookExpression"] - ] - } - ], - Delimiter, - MenuItem["Make &Hyperlink...", "CreateHyperlinkDialog"], - MenuItem[ - "Insert Table/&Matrix...", - FrontEndExecute[ - { - FrontEnd`NotebookOpen[ - FrontEnd`FindFileOnPath[ - "InsertGrid.nb", - "PrivatePathsSystemResources" - ] - ] - } - ] - ], - MenuItem["Chec&k Spelling...", "FindNextMisspelling"], - Menu[ - "Citatio&n", - { - MenuItem[ - "Insert Bibliographical &Reference...", - "InsertBibReference" - ], - MenuItem[ - "Insert Bibliographical &Note...", - "InsertBibNote" - ], - Delimiter, - MenuItem[ - "Set / Change Citation &Style...", - "SetCitationStyle" - ], - MenuItem[ - "&Insert Bibliography and Notes", - "InsertBibAndNotes" - ], - MenuItem[ - "&Delete Bibliography and Notes", - "DeleteBibAndNotes" - ], - MenuItem[ - "Re&build Bibliography and Notes", - "RebuildBibAndNotes" + ContextMenu -> + Dynamic[ + FEPrivate`Join[{MenuItem[#1, KernelExecute[With[{Wolfram`ChatNB`nbo = InputNotebook[]}, {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, Quiet[Needs["Wolfram`Chatbook`" -> None]]; Symbol["Wolfram`Chatbook`ChatbookAction"]["Ask", Wolfram`ChatNB`nbo, Wolfram`ChatNB`cells]]], MenuEvaluator -> Automatic, Method -> "Queued"], Delimiter}, FEPrivate`FrontEndResource["ContextMenus", "Text"]] &[ + FEPrivate`FrontEndResource[ + "ChatbookStrings", + "StylesheetContextMenuAskAI" ] - } - ], - Delimiter, - Menu[ - "Sty&le", - { - MenuItem[ - "Start Cell Style Names", - "MenuListStyles", - MenuAnchor -> True - ], - Delimiter, - MenuItem["&Other...", "StyleOther"] - } - ], - Delimiter, - MenuItem["Create Inline Cell", "CreateInlineCell"], - MenuItem["Di&vide Cell", "CellSplit"], - MenuItem["Evaluate &in Place", All], - Delimiter, - MenuItem[ - "Toggle &Full Screen", - FrontEndExecute[ - FrontEnd`Value[FEPrivate`NotebookToggleFullScreen[]] ] ] - } ], Cell[ StyleData["Input"], @@ -1321,238 +859,28 @@ Notebook[ Wolfram`ChatNB`cell ] ], - ContextMenu -> { - MenuItem[ - "Ask AI Assistant", - KernelExecute[ - With[ { Wolfram`ChatNB`nbo = InputNotebook[] }, - {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, - Quiet[Needs["Wolfram`Chatbook`" -> None]]; - Symbol["Wolfram`Chatbook`ChatbookAction"][ - "Ask", - Wolfram`ChatNB`nbo, - Wolfram`ChatNB`cells - ] - ] - ], - MenuEvaluator -> Automatic, - Method -> "Queued" - ], - Delimiter, - MenuItem["Cu&t", "Cut"], - MenuItem["&Copy", "Copy"], - MenuItem["&Paste", FrontEnd`Paste[After]], - Menu[ - "Cop&y As", - { - MenuItem["Plain &Text", FrontEnd`CopySpecial["PlainText"]], - MenuItem["&Input Text", FrontEnd`CopySpecial["InputText"]], - MenuItem[ - "&LaTeX", - KernelExecute[ToExpression["FrontEnd`CopyAsTeX[]"]], - MenuEvaluator -> "System" - ], - MenuItem[ - "M&athML", - KernelExecute[ToExpression["FrontEnd`CopyAsMathML[]"]], - MenuEvaluator -> "System" - ], - Delimiter, - MenuItem[ - "Cell &Object", - FrontEnd`CopySpecial["CellObject"] - ], - MenuItem[ - "&Cell Expression", - FrontEnd`CopySpecial["CellExpression"] - ], - MenuItem[ - "&Notebook Expression", - FrontEnd`CopySpecial["NotebookExpression"] - ] - } - ], - Delimiter, - MenuItem["&Evaluate Cell", "EvaluateCells"], - MenuItem["Evaluate &in Place", All], - MenuItem[ - "Analyze Cell", - KernelExecute[ - Needs["CodeInspector`"]; - CodeInspector`AttachAnalysis[ - SelectedCells[InputNotebook[]] + ContextMenu -> + Dynamic[ + FEPrivate`Join[{MenuItem[#1, KernelExecute[With[{Wolfram`ChatNB`nbo = InputNotebook[]}, {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, Quiet[Needs["Wolfram`Chatbook`" -> None]]; Symbol["Wolfram`Chatbook`ChatbookAction"]["Ask", Wolfram`ChatNB`nbo, Wolfram`ChatNB`cells]]], MenuEvaluator -> Automatic, Method -> "Queued"], Delimiter}, FEPrivate`FrontEndResource["ContextMenus", "Input"]] &[ + FEPrivate`FrontEndResource[ + "ChatbookStrings", + "StylesheetContextMenuAskAI" ] - ], - MenuEvaluator -> Automatic, - Method -> "Queued" - ], - Menu[ - "C&onvert To", - { - MenuItem["&InputForm", "SelectionConvert" -> InputForm], - MenuItem[ - "&Raw InputForm", - "SelectionConvert" -> RawInputForm - ], - MenuItem["&OutputForm", "SelectionConvert" -> OutputForm], - MenuItem[ - "First Convert to BoxForm", - "MenuListConvertFormatTypes", - MenuAnchor -> True - ], - Delimiter, - MenuItem["&Bitmap", "SelectionConvert" -> "Bitmap"] - } - ], - Delimiter, - MenuItem["Make &Hyperlink...", "CreateHyperlinkDialog"], - MenuItem[ - "Insert Table/&Matrix...", - FrontEndExecute[ - { - FrontEnd`NotebookOpen[ - FrontEnd`FindFileOnPath[ - "InsertGrid.nb", - "PrivatePathsSystemResources" - ] - ] - } - ] - ], - MenuItem[ - "Insert &Special Character...", - FrontEndExecute[ - {FrontEnd`NotebookOpen["SpecialCharacters.nb"]} - ] - ], - Delimiter, - MenuItem["Check &Balance", "Balance"], - MenuItem["Di&vide Cell", "CellSplit"], - MenuItem[ - "&Un/Comment Selection", - KernelExecute[ToExpression["FE`toggleComment[]"]], - MenuEvaluator -> "System" - ], - MenuItem[ - "Un/Iconi&ze Selection", - KernelExecute[ToExpression["FE`iconizeSelectionToggle[]"]], - MenuEvaluator -> Automatic - ], - Delimiter, - MenuItem["&Get Help", FrontEnd`SelectionHelpDialog[True]], - MenuItem[ - "Why the Coloring?...", - FrontEndExecute[ - { - FrontEnd`NotebookOpen[ - FrontEnd`FindFileOnPath[ - "WhyTheColoring.nb", - "PrivatePathsSystemResources" - ] - ] - } - ] - ], - MenuItem["Spea&k Selection", "SelectionSpeak"], - Delimiter, - MenuItem[ - "Toggle &Full Screen", - FrontEndExecute[ - FrontEnd`Value[FEPrivate`NotebookToggleFullScreen[]] ] ] - } ], Cell[ StyleData["Output"], CellTrayWidgets -> <|"GearMenu" -> <|"Condition" -> False|>|>, - ContextMenu -> { - MenuItem[ - "Ask AI Assistant", - KernelExecute[ - With[ { Wolfram`ChatNB`nbo = InputNotebook[] }, - {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, - Quiet[Needs["Wolfram`Chatbook`" -> None]]; - Symbol["Wolfram`Chatbook`ChatbookAction"][ - "Ask", - Wolfram`ChatNB`nbo, - Wolfram`ChatNB`cells - ] - ] - ], - MenuEvaluator -> Automatic, - Method -> "Queued" - ], - Delimiter, - MenuItem["Cu&t", "Cut"], - MenuItem["&Copy", "Copy"], - MenuItem["&Paste", FrontEnd`Paste[After]], - Menu[ - "Cop&y As", - { - MenuItem["Plain &Text", FrontEnd`CopySpecial["PlainText"]], - MenuItem["&Input Text", FrontEnd`CopySpecial["InputText"]], - MenuItem[ - "&LaTeX", - KernelExecute[ToExpression["FrontEnd`CopyAsTeX[]"]], - MenuEvaluator -> "System" - ], - MenuItem[ - "M&athML", - KernelExecute[ToExpression["FrontEnd`CopyAsMathML[]"]], - MenuEvaluator -> "System" - ], - Delimiter, - MenuItem[ - "Cell &Object", - FrontEnd`CopySpecial["CellObject"] - ], - MenuItem[ - "&Cell Expression", - FrontEnd`CopySpecial["CellExpression"] - ], - MenuItem[ - "&Notebook Expression", - FrontEnd`CopySpecial["NotebookExpression"] + ContextMenu -> + Dynamic[ + FEPrivate`Join[{MenuItem[#1, KernelExecute[With[{Wolfram`ChatNB`nbo = InputNotebook[]}, {Wolfram`ChatNB`cells = SelectedCells[Wolfram`ChatNB`nbo]}, Quiet[Needs["Wolfram`Chatbook`" -> None]]; Symbol["Wolfram`Chatbook`ChatbookAction"]["Ask", Wolfram`ChatNB`nbo, Wolfram`ChatNB`cells]]], MenuEvaluator -> Automatic, Method -> "Queued"], Delimiter}, FEPrivate`FrontEndResource["ContextMenus", "Output"]] &[ + FEPrivate`FrontEndResource[ + "ChatbookStrings", + "StylesheetContextMenuAskAI" ] - } - ], - Delimiter, - Menu[ - "Con&vert To", - { - MenuItem["&InputForm", "SelectionConvert" -> InputForm], - MenuItem[ - "&Raw InputForm", - "SelectionConvert" -> RawInputForm - ], - MenuItem["&OutputForm", "SelectionConvert" -> OutputForm], - MenuItem[ - "First Convert to BoxForm", - "MenuListConvertFormatTypes", - MenuAnchor -> True - ], - Delimiter, - MenuItem["&Bitmap", "SelectionConvert" -> "Bitmap"] - } - ], - Delimiter, - MenuItem[ - "Un/Iconi&ze Selection", - KernelExecute[ToExpression["FE`iconizeSelectionToggle[]"]], - MenuEvaluator -> Automatic - ], - Delimiter, - MenuItem["&Get Help", FrontEnd`SelectionHelpDialog[True]], - MenuItem["Spea&k Selection", "SelectionSpeak"], - Delimiter, - MenuItem[ - "Toggle &Full Screen", - FrontEndExecute[ - FrontEnd`Value[FEPrivate`NotebookToggleFullScreen[]] ] ] - } ], Cell[ StyleData["Message"], @@ -2592,7 +1920,12 @@ Notebook[ FrameMargins -> {{3, 3}, {2, 2}}, FrameStyle -> Directive[AbsoluteThickness[1], GrayLevel[0.92941]], - ImageMargins -> {{0, 0}, {0, 0}} + ImageMargins -> {{0, 0}, {0, 0}}, + BaseStyle -> { + "InlineCode", + AutoSpacing -> False, + AutoMultiplicationSymbol -> False + } ] ]) } @@ -18280,13 +17613,18 @@ Notebook[ TemplateBoxOptions -> { DisplayFunction -> (Function[ - FrameBox[ - Cell[#1, "Text", Background -> None], - Background -> RGBColor[0.929412, 0.956863, 0.988235], - FrameMargins -> 8, - FrameStyle -> RGBColor[0.639216, 0.788235, 0.94902], - RoundingRadius -> 10, - StripOnInput -> False + PaneBox[ + FrameBox[ + #1, + BaseStyle -> {"Text", Editable -> False, Selectable -> False}, + Background -> RGBColor[0.929412, 0.956863, 0.988235], + FrameMargins -> 8, + FrameStyle -> RGBColor[0.639216, 0.788235, 0.94902], + RoundingRadius -> 10, + StripOnInput -> False + ], + Alignment -> Right, + ImageSize -> {Full, Automatic} ] ]) } @@ -18296,15 +17634,172 @@ Notebook[ TemplateBoxOptions -> { DisplayFunction -> (Function[ - FrameBox[ - #1, - BaseStyle -> "Text", - Background -> RGBColor[0.988235, 0.992157, 1.0], - FrameMargins -> 8, - FrameStyle -> RGBColor[0.788235, 0.8, 0.815686], - ImageSize -> {Scaled[1], Automatic}, - RoundingRadius -> 10, - StripOnInput -> False + TagBox[ + FrameBox[ + #1, + BaseStyle -> {"Text", Editable -> False, Selectable -> False}, + Background -> RGBColor[0.988235, 0.992157, 1.0], + FrameMargins -> 8, + FrameStyle -> RGBColor[0.788235, 0.8, 0.815686], + ImageSize -> {Scaled[1], Automatic}, + RoundingRadius -> 10, + StripOnInput -> False + ], + EventHandlerTag[ + { + "MouseEntered" :> + With[ { Wolfram`ChatNB`cell = EvaluationCell[] }, + Quiet[Needs["Wolfram`Chatbook`" -> None]]; + Symbol["Wolfram`Chatbook`ChatbookAction"][ + "AttachAssistantMessageButtons", + Wolfram`ChatNB`cell + ] + ], + Method -> "Preemptive", + PassEventsDown -> Automatic, + PassEventsUp -> True + } + ] + ] + ]) + } + ], + Cell[ + StyleData["FeedbackButtonsHorizontal"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + TagBox[ + GridBox[ + { + { + ButtonBox[ + TagBox[ + TagBox[ + TooltipBox[ + PaneSelectorBox[ + { + False -> TemplateBox[{}, "ThumbsUpInactive"], + True -> TemplateBox[{}, "ThumbsUpActive"] + }, + Dynamic[CurrentValue["MouseOver"]], + ImageSize -> Automatic, + FrameMargins -> 0 + ], + DynamicBox[ + ToBoxes[ + FEPrivate`FrontEndResource[ + "ChatbookStrings", + "StylesheetFeedbackButtonTooltip" + ], + StandardForm + ] + ] + ], + Function[ + Annotation[ + #1, + Dynamic[ + FEPrivate`FrontEndResource[ + "ChatbookStrings", + "StylesheetFeedbackButtonTooltip" + ] + ], + "Tooltip" + ] + ] + ], + MouseAppearanceTag["LinkHand"] + ], + ButtonFunction :> + With[ { Wolfram`ChatNB`cell$ = EvaluationCell[] }, + Quiet[Needs["Wolfram`Chatbook`" -> None]]; + Catch[ + Symbol["Wolfram`Chatbook`ChatbookAction"][ + "SendFeedback", + Wolfram`ChatNB`cell$, + True + ], + Blank[] + ] + ], + Appearance -> + Dynamic[ + FEPrivate`FrontEndResource[ + "FEExpressions", + "SuppressMouseDownNinePatchAppearance" + ] + ], + Evaluator -> Automatic, + Method -> "Preemptive" + ], + ButtonBox[ + TagBox[ + TagBox[ + TooltipBox[ + PaneSelectorBox[ + { + False -> TemplateBox[{}, "ThumbsDownInactive"], + True -> TemplateBox[{}, "ThumbsDownActive"] + }, + Dynamic[CurrentValue["MouseOver"]], + ImageSize -> Automatic, + FrameMargins -> 0 + ], + DynamicBox[ + ToBoxes[ + FEPrivate`FrontEndResource[ + "ChatbookStrings", + "StylesheetFeedbackButtonTooltip" + ], + StandardForm + ] + ] + ], + Function[ + Annotation[ + #1, + Dynamic[ + FEPrivate`FrontEndResource[ + "ChatbookStrings", + "StylesheetFeedbackButtonTooltip" + ] + ], + "Tooltip" + ] + ] + ], + MouseAppearanceTag["LinkHand"] + ], + ButtonFunction :> + With[ { Wolfram`ChatNB`cell$ = EvaluationCell[] }, + Quiet[Needs["Wolfram`Chatbook`" -> None]]; + Catch[ + Symbol["Wolfram`Chatbook`ChatbookAction"][ + "SendFeedback", + Wolfram`ChatNB`cell$, + False + ], + Blank[] + ] + ], + Appearance -> + Dynamic[ + FEPrivate`FrontEndResource[ + "FEExpressions", + "SuppressMouseDownNinePatchAppearance" + ] + ], + Evaluator -> Automatic, + Method -> "Preemptive" + ] + } + }, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{0.2}}} + ], + "Grid" ] ]) } @@ -18314,20 +17809,23 @@ Notebook[ TemplateBoxOptions -> { DisplayFunction -> (Function[ - PanelBox[ - #1, - Appearance -> - Image[ - CompressedData[ - "\n1:eJy9lU1LAlEUhqdxdIYYQ5gkwQFNXLiQlkMhLqJVIQhGCK7UUmljoEG0m7/p\n3/AP2HvlvXK6STnFNPB4mcM5z5x7nI/z8UtvaluWtfTw0xu9XS8Wo/f7Ak4e\n5svn2XzydDt/ncwmi8txBsEz4oBNgiNh+vaI49gSHBGbZICzh4zI0TU7zx63\n9KraLMgBF3gCl/GsuMYnv+GWToe1ynMMfJAX+Ix7zHOMa0i3vqb2uqxVngII\nQFEQMJ5nniv8W5fhtg3vCR0lEIIKqHINGQ+YJ/224dazyAnvKSiDGmiAJrjg\n2mC8zDztz+nZGO4s55dnP6quTl8EWqDNNWK8zryAdR490i17LnC/NdZfgZvV\narXRqHPGL5hXYt2ud/08iDn77CHkviN6usq5Xq+1u8t4xLyQdb6eu37O6Nbz\nKPL/anL/d6Bv9N1nvMW8Cuv0XBwxE9Nd5X7VfDtgAB7BlOuA8TbzqgncX/oG\nQ3qHv+j723nTN+D647yT3Cfss8P1oPvkH+7vNJ/LNN8nab4HrTi997cVp/vd\n2ef/8/fy0CPpd/4Dbscq/g==\n " + PaneBox[ + PanelBox[ + #1, + Appearance -> + Image[ + CompressedData[ + "\n1:eJy9lU1LAlEUhqdxdIYYQ5gkwQFNXLiQlkMhLqJVIQhGCK7UUmljoEG0m7/p\n3/AP2HvlvXK6STnFNPB4mcM5z5x7nI/z8UtvaluWtfTw0xu9XS8Wo/f7Ak4e\n5svn2XzydDt/ncwmi8txBsEz4oBNgiNh+vaI49gSHBGbZICzh4zI0TU7zx63\n9KraLMgBF3gCl/GsuMYnv+GWToe1ynMMfJAX+Ix7zHOMa0i3vqb2uqxVngII\nQFEQMJ5nniv8W5fhtg3vCR0lEIIKqHINGQ+YJ/224dazyAnvKSiDGmiAJrjg\n2mC8zDztz+nZGO4s55dnP6quTl8EWqDNNWK8zryAdR490i17LnC/NdZfgZvV\narXRqHPGL5hXYt2ud/08iDn77CHkviN6usq5Xq+1u8t4xLyQdb6eu37O6Nbz\nKPL/anL/d6Bv9N1nvMW8Cuv0XBwxE9Nd5X7VfDtgAB7BlOuA8TbzqgncX/oG\nQ3qHv+j723nTN+D647yT3Cfss8P1oPvkH+7vNJ/LNN8nab4HrTi997cVp/vd\n2ef/8/fy0CPpd/4Dbscq/g==\n " + ], + "Byte", + ColorSpace -> "RGB", + ImageResolution -> 72, + Interleaving -> True ], - "Byte", - ColorSpace -> "RGB", - ImageResolution -> 72, - Interleaving -> True - ], - ContentPadding -> False, - FrameMargins -> {{0, 0}, {0, 0}} + ContentPadding -> False, + FrameMargins -> {{0, 0}, {0, 0}} + ], + ImageMargins -> {{40, 50}, {0, 0}} ] ]) } diff --git a/FrontEnd/StyleSheets/Wolfram/WorkspaceChat.nb b/FrontEnd/StyleSheets/Wolfram/WorkspaceChat.nb index 3753132e..aa671bdc 100644 --- a/FrontEnd/StyleSheets/Wolfram/WorkspaceChat.nb +++ b/FrontEnd/StyleSheets/Wolfram/WorkspaceChat.nb @@ -18,7 +18,6 @@ Notebook[ Selectable -> False, WindowSize -> {350, Automatic}, WindowMargins -> {{0, Automatic}, {0, 0}}, - WindowFrame -> "ModelessDialog", WindowElements -> {"VerticalScrollBar"}, WindowFrameElements -> {"CloseBox", "ResizeArea"}, WindowClickSelect -> True, @@ -60,15 +59,16 @@ Notebook[ ], Cell[ StyleData["WorkspaceChatStyleSheetInformation"], - TaggingRules -> <|"WorkspaceChatStyleSheetVersion" -> "1.5.0.3931772186"|> + TaggingRules -> <|"WorkspaceChatStyleSheetVersion" -> "1.5.1.3936664622"|> ], Cell[ StyleData["ChatInput"], - Selectable -> True, + Selectable -> False, CellFrame -> 0, CellDingbat -> None, ShowCellBracket -> False, CellMargins -> {{15, 10}, {5, 10}}, + CellEventActions -> None, CellFrameLabels -> { {None, None}, { @@ -94,16 +94,15 @@ Notebook[ ] } }, - CellFrameLabelMargins -> 6, - TextAlignment -> Right + CellFrameLabelMargins -> 6 ], Cell[ StyleData["ChatOutput"], - Selectable -> True, + Selectable -> False, CellFrame -> 0, CellDingbat -> None, ShowCellBracket -> False, - CellMargins -> {{10, 15}, {15, 12}}, + CellMargins -> {{10, 15}, {25, 12}}, Initialization :> None, CellFrameLabels -> { {None, None}, @@ -149,6 +148,12 @@ Notebook[ True ];) ], + Cell[ + StyleData["CodeAssistanceWelcomeCell"], + CellMargins -> {{10, 10}, {30, 10}}, + TaggingRules -> <|"ChatNotebookSettings" -> <|"ExcludeFromChat" -> True|>|>, + ShowStringCharacters -> False + ], Cell[ StyleData["WorkspaceSendChatButton"], TemplateBoxOptions -> { @@ -197,6 +202,71 @@ Notebook[ ] ]) } + ], + Cell[ + StyleData["WelcomeToCodeAssistanceSplash"], + TemplateBoxOptions -> { + DisplayFunction -> + (Function[ + FrameBox[ + PaneBox[ + TagBox[ + GridBox[ + { + { + StyleBox[ + TemplateBox[{}, "ChatIconCodeAssistant"], + Magnification -> 5 * Inherited, + StripOnInput -> False + ] + }, + { + StyleBox[ + "\"Welcome to Code Assistance Chat\"", + FontWeight -> Bold, + FontSize -> 17, + FontColor -> GrayLevel[0.25], + StripOnInput -> False + ] + }, + {"\"Ask me anything using the input field below.\""}, + { + ButtonBox[ + "\"View Tutorial \[RightGuillemet]\"", + ButtonFunction :> MessageDialog["Not implemented yet."], + Appearance -> None, + BaseStyle -> {"Link"}, + Evaluator -> Automatic, + Method -> "Preemptive" + ] + } + }, + AutoDelete -> False, + GridBoxItemSize -> {"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}, + GridBoxSpacings -> {"Columns" -> {{1}}, "Rows" -> {0, 1.25, 1.25, 0.75}}, + BaseStyle -> { + "Text", + FontSize -> 13, + FontColor -> GrayLevel[0.5], + LineBreakWithin -> False + } + ], + "Grid" + ], + Alignment -> {Center, Automatic}, + ImageSize -> {Scaled[1], Automatic}, + ImageSizeAction -> "ShrinkToFit" + ], + Alignment -> {Center, Automatic}, + Background -> RGBColor[0.988235, 0.992157, 1.0], + FrameMargins -> {{10, 10}, {10, 10}}, + FrameStyle -> RGBColor[0.92549, 0.941176, 0.960784], + ImageSize -> {Automatic, Automatic}, + RoundingRadius -> 10, + StripOnInput -> False + ] + ]) + } ] }, StyleDefinitions -> "PrivateStylesheetFormatting.nb" diff --git a/FrontEnd/TextResources/ChatbookStrings.tr b/FrontEnd/TextResources/ChatbookStrings.tr index caae4a34..64fcfa38 100644 --- a/FrontEnd/TextResources/ChatbookStrings.tr +++ b/FrontEnd/TextResources/ChatbookStrings.tr @@ -75,6 +75,7 @@ "PersonaManagerInstallPersonas" -> "Install Personas", "PersonaManagerInstallFrom" -> "Install from", "PersonaManagerInstallFromPromptRepo" -> "Prompt Repository \[UpperRightArrow]", +"PersonaManagerInstallFromFile" -> "Definition Notebook", "PersonaManagerManagePersonas" -> "Manage and Enable Personas", "PersonaManagerInMenu" -> "In Menu", "PersonaManagerName" -> "Name", @@ -113,11 +114,13 @@ "PreferencesContentOpenAICompletionURLLabel" -> "Chat Completion URL:", "ResourceInstallerFromURLPrompt" -> "Enter a URL", +"ResourceInstallerFromFilePrompt" -> "Choose a Resource Definition Notebook", "ToolManagerTitle" -> "Add & Manage LLM Tools", "ToolManagerInstallTools" -> "Install Tools", "ToolManagerInstallFrom" -> "Install from", "ToolManagerInstallFromLLMToolRepo" -> "LLM Tool Repository \[UpperRightArrow]", +"ToolManagerInstallFromFile" -> "Definition Notebook", "ToolManagerManageTools" -> "Manage and Enable Tools", "ToolManagerShowEnabledFor" -> "Show enabled tools for:", "ToolManagerTool" -> "Tool", @@ -162,6 +165,8 @@ "StylesheetCopyChatObject" -> "Copy ChatObject", "StylesheetInsertionMenuChatInput" -> "Chat Input", "StylesheetInsertionMenuSideChat" -> "Side Chat", +"StylesheetContextMenuAskAI" -> "Ask AI Assistant", +"StylesheetContextMenuIncludeExclude" -> "Include/Exclude From AI Chat", "PersonaNameBirdnardo" -> "Birdnardo", "PersonaNameCodeAssistant" -> "Code Assistant", diff --git a/FrontEnd/TextResources/ChineseSimplified/ChatbookStrings.tr b/FrontEnd/TextResources/ChineseSimplified/ChatbookStrings.tr index 69c7c0ce..4ab8801e 100644 --- a/FrontEnd/TextResources/ChineseSimplified/ChatbookStrings.tr +++ b/FrontEnd/TextResources/ChineseSimplified/ChatbookStrings.tr @@ -75,6 +75,7 @@ "PersonaManagerInstallPersonas" -> "\:5B89\:88C5\:89D2\:8272", "PersonaManagerInstallFrom" -> "\:4ECE\:6B64\:5904\:5B89\:88C5\:ff1a", "PersonaManagerInstallFromPromptRepo" -> "\:63D0\:793A\:8BCD\:5B58\:50A8\:5E93 \[UpperRightArrow]", +"PersonaManagerInstallFromFile" -> "Definition Notebook", "PersonaManagerManagePersonas" -> "\:7BA1\:7406\:548C\:542F\:7528\:89D2\:8272", "PersonaManagerInMenu" -> "\:5305\:62EC\:5728\:83DC\:5355\:4E2D", "PersonaManagerName" -> "\:540D\:5B57", @@ -113,11 +114,13 @@ "PreferencesContentOpenAICompletionURLLabel" -> "\:804A\:5929\:8865\:5168 URL\:ff1a", "ResourceInstallerFromURLPrompt" -> "\:8F93\:5165 URL", +"ResourceInstallerFromFilePrompt" -> "Choose a Resource Definition Notebook", "ToolManagerTitle" -> "\:6DFB\:52A0\:548C\:7BA1\:7406 LLM \:5DE5\:5177", "ToolManagerInstallTools" -> "\:5B89\:88C5\:5DE5\:5177", "ToolManagerInstallFrom" -> "\:4ECE\:6B64\:5904\:5B89\:88C5\:ff1a", "ToolManagerInstallFromLLMToolRepo" -> "LLM \:5DE5\:5177\:5E93 \[UpperRightArrow]", +"ToolManagerInstallFromFile" -> "Definition Notebook", "ToolManagerManageTools" -> "\:7BA1\:7406\:548C\:542F\:7528\:5DE5\:5177", "ToolManagerShowEnabledFor" -> "\:663E\:793A\:542F\:7528\:7684\:5DE5\:5177\:ff1a", "ToolManagerTool" -> "\:5DE5\:5177", @@ -162,6 +165,8 @@ "StylesheetCopyChatObject" -> "\:590D\:5236 ChatObject", "StylesheetInsertionMenuChatInput" -> "\:804A\:5929\:8F93\:5165", "StylesheetInsertionMenuSideChat" -> "\:79C1\:804A", +"StylesheetContextMenuAskAI" -> "Ask AI Assistant", +"StylesheetContextMenuIncludeExclude" -> "Include/Exclude From AI Chat", "PersonaNameBirdnardo" -> "Birdnardo", "PersonaNameCodeAssistant" -> "\:4EE3\:7801\:52A9\:624B", diff --git a/FrontEnd/TextResources/ChineseTraditional/ChatbookStrings.tr b/FrontEnd/TextResources/ChineseTraditional/ChatbookStrings.tr index abff0bf2..e7fe0cf0 100644 --- a/FrontEnd/TextResources/ChineseTraditional/ChatbookStrings.tr +++ b/FrontEnd/TextResources/ChineseTraditional/ChatbookStrings.tr @@ -75,6 +75,7 @@ "PersonaManagerInstallPersonas" -> "\:5B89\:88DD\:4EBA\:7269\:8A8C", "PersonaManagerInstallFrom" -> "\:5B89\:88DD\:8D77\:65BC", "PersonaManagerInstallFromPromptRepo" -> "\:63D0\:793A\:5132\:5B58\:5EAB \[UpperRightArrow]", +"PersonaManagerInstallFromFile" -> "Definition Notebook", "PersonaManagerManagePersonas" -> "\:7BA1\:7406\:4E26\:8CE6\:80FD\:4EBA\:7269\:8A8C", "PersonaManagerInMenu" -> "\:6311\:9078\:9078\:55AE", "PersonaManagerName" -> "\:540D\:7A31", @@ -113,11 +114,13 @@ "PreferencesContentOpenAICompletionURLLabel" -> "\:7DB2\:8DEF\:804A\:5929\:7CFB\:7D71\:5BE6\:73FE\:7DB2\:5740\:FF1A", "ResourceInstallerFromURLPrompt" -> "\:8F38\:5165\:7DB2\:5740", +"ResourceInstallerFromFilePrompt" -> "Choose a Resource Definition Notebook", "ToolManagerTitle" -> "\:589E\:6DFB\:4E26\:7BA1\:7406 LLM \:5DE5\:5177", "ToolManagerInstallTools" -> "\:5B89\:88DD\:5DE5\:5177", "ToolManagerInstallFrom" -> "\:5B89\:88DD\:8D77\:65BC", "ToolManagerInstallFromLLMToolRepo" -> "LLM \:5DE5\:5177\:5132\:5B58\:5EAB \[UpperRightArrow]", +"ToolManagerInstallFromFile" -> "Definition Notebook", "ToolManagerManageTools" -> "\:7BA1\:7406\:4E26\:8CE6\:80FD\:5DE5\:5177", "ToolManagerShowEnabledFor" -> "\:986F\:793A\:8CE6\:80FD\:5DE5\:5177\:FF1A", "ToolManagerTool" -> "\:5DE5\:5177", @@ -162,6 +165,8 @@ "StylesheetCopyChatObject" -> "\:8907\:88FD ChatObject", "StylesheetInsertionMenuChatInput" -> "\:7DB2\:8DEF\:804A\:5929\:7CFB\:7D71\:8F38\:5165", "StylesheetInsertionMenuSideChat" -> "Side Chat \:FF08\:585E\:6390\:FF09", +"StylesheetContextMenuAskAI" -> "Ask AI Assistant", +"StylesheetContextMenuIncludeExclude" -> "Include/Exclude From AI Chat", "PersonaNameBirdnardo" -> "Birdnardo", "PersonaNameCodeAssistant" -> "\:7DE8\:78BC\:5C0F\:5E6B\:624B", diff --git a/FrontEnd/TextResources/French/ChatbookStrings.tr b/FrontEnd/TextResources/French/ChatbookStrings.tr index 7a6eadf4..93a5f1c4 100644 --- a/FrontEnd/TextResources/French/ChatbookStrings.tr +++ b/FrontEnd/TextResources/French/ChatbookStrings.tr @@ -75,6 +75,7 @@ "PersonaManagerInstallPersonas" -> "Installer des personnages", "PersonaManagerInstallFrom" -> "Installer \[AGrave] partir de", "PersonaManagerInstallFromPromptRepo" -> "R\[EAcute]f\[EAcute]rentiel de l\[CloseCurlyQuote]invite \[UpperRightArrow]", +"PersonaManagerInstallFromFile" -> "Definition Notebook", "PersonaManagerManagePersonas" -> "G\[EAcute]rer et activer les personnages", "PersonaManagerInMenu" -> "Dans le menu", "PersonaManagerName" -> "Nom", @@ -113,11 +114,13 @@ "PreferencesContentOpenAICompletionURLLabel" -> "URL compl\[EGrave]te du chat\[NonBreakingSpace]:", "ResourceInstallerFromURLPrompt" -> "Entrer une URL", +"ResourceInstallerFromFilePrompt" -> "Choose a Resource Definition Notebook", "ToolManagerTitle" -> "Ajouter et g\[EAcute]rer des outils LLM", "ToolManagerInstallTools" -> "Installer des outils", "ToolManagerInstallFrom" -> "Installer \[AGrave] partir de", "ToolManagerInstallFromLLMToolRepo" -> "R\[EAcute]f\[EAcute]rentiel d\[CloseCurlyQuote]outils LLM \[UpperRightArrow]", +"ToolManagerInstallFromFile" -> "Definition Notebook", "ToolManagerManageTools" -> "G\[EAcute]rer et activer les outils", "ToolManagerShowEnabledFor" -> "Afficher les outils activ\[EAcute]s pour\[NonBreakingSpace]:", "ToolManagerTool" -> "Outil", @@ -162,6 +165,8 @@ "StylesheetCopyChatObject" -> "Copier l\[CloseCurlyQuote]objet de Chat", "StylesheetInsertionMenuChatInput" -> "Entr\[EAcute]e de chat", "StylesheetInsertionMenuSideChat" -> "Chat lat\[EAcute]ral", +"StylesheetContextMenuAskAI" -> "Ask AI Assistant", +"StylesheetContextMenuIncludeExclude" -> "Include/Exclude From AI Chat", "PersonaNameBirdnardo" -> "Birdnardo", "PersonaNameCodeAssistant" -> "Assistant de code", diff --git a/FrontEnd/TextResources/Japanese/ChatbookStrings.tr b/FrontEnd/TextResources/Japanese/ChatbookStrings.tr index ba877dd0..746257a8 100644 --- a/FrontEnd/TextResources/Japanese/ChatbookStrings.tr +++ b/FrontEnd/TextResources/Japanese/ChatbookStrings.tr @@ -75,6 +75,7 @@ "PersonaManagerInstallPersonas" -> "\:30da\:30eb\:30bd\:30ca\:306e\:30a4\:30f3\:30b9\:30c8\:30fc\:30eb", "PersonaManagerInstallFrom" -> "\:6b21\:304b\:3089\:30a4\:30f3\:30b9\:30c8\:30fc\:30eb\:ff1a", "PersonaManagerInstallFromPromptRepo" -> "Prompt Repository \[UpperRightArrow]", +"PersonaManagerInstallFromFile" -> "Definition Notebook", "PersonaManagerManagePersonas" -> "\:30da\:30eb\:30bd\:30ca\:306e\:7ba1\:7406\:3068\:6709\:52b9\:5316", "PersonaManagerInMenu" -> "\:30e1\:30cb\:30e5\:30fc", "PersonaManagerName" -> "\:540d\:524d", @@ -113,11 +114,13 @@ "PreferencesContentOpenAICompletionURLLabel" -> "\:30c1\:30e3\:30c3\:30c8\:5b8c\:4e86\:306eURL\:ff1a", "ResourceInstallerFromURLPrompt" -> "URL\:3092\:5165\:529b\:3057\:3066\:304f\:3060\:3055\:3044", +"ResourceInstallerFromFilePrompt" -> "Choose a Resource Definition Notebook", "ToolManagerTitle" -> "\:5927\:898f\:6a21\:8a00\:8a9e\:30c4\:30fc\:30eb\:306e\:8ffd\:52a0\:3068\:7ba1\:7406", "ToolManagerInstallTools" -> "\:30c4\:30fc\:30eb\:306e\:30a4\:30f3\:30b9\:30c8\:30fc\:30eb", "ToolManagerInstallFrom" -> "\:6b21\:304b\:3089\:30a4\:30f3\:30b9\:30c8\:30fc\:30eb\:ff1a", "ToolManagerInstallFromLLMToolRepo" -> "LLM Tool Repository \[UpperRightArrow]", +"ToolManagerInstallFromFile" -> "Definition Notebook", "ToolManagerManageTools" -> "\:30c4\:30fc\:30eb\:306e\:7ba1\:7406\:3068\:6709\:52b9\:5316", "ToolManagerShowEnabledFor" -> "\:6b21\:306b\:3064\:3044\:3066\:6709\:52b9\:5316\:3055\:308c\:305f\:30c4\:30fc\:30eb\:3092\:8868\:793a\:ff1a", "ToolManagerTool" -> "\:30c4\:30fc\:30eb", @@ -162,6 +165,8 @@ "StylesheetCopyChatObject" -> "ChatObject\:3092\:30b3\:30d4\:30fc\:3059\:308b", "StylesheetInsertionMenuChatInput" -> "\:30c1\:30e3\:30c3\:30c8\:5165\:529b", "StylesheetInsertionMenuSideChat" -> "\:30b5\:30a4\:30c9\:30c1\:30e3\:30c3\:30c8", +"StylesheetContextMenuAskAI" -> "Ask AI Assistant", +"StylesheetContextMenuIncludeExclude" -> "Include/Exclude From AI Chat", "PersonaNameBirdnardo" -> "Birdnardo", "PersonaNameCodeAssistant" -> "Code Assistant", diff --git a/FrontEnd/TextResources/Korean/ChatbookStrings.tr b/FrontEnd/TextResources/Korean/ChatbookStrings.tr index 0a861cfc..8032e1d7 100644 --- a/FrontEnd/TextResources/Korean/ChatbookStrings.tr +++ b/FrontEnd/TextResources/Korean/ChatbookStrings.tr @@ -76,6 +76,7 @@ "PersonaManagerInstallPersonas" -> "\:D398\:B974\:C18C\:B098 \:C124\:CE58", "PersonaManagerInstallFrom" -> "\:B2E4\:C74C\:BD80\:D130 \:C124\:CE58", "PersonaManagerInstallFromPromptRepo" -> "\:D504\:B86C\:D504\:D2B8 \:B9AC\:D3EC\:C9C0\:D1A0\:B9AC \[UpperRightArrow]", +"PersonaManagerInstallFromFile" -> "Definition Notebook", "PersonaManagerManagePersonas" -> "\:D398\:B974\:C18C\:B098 \:AD00\:B9AC \:BC0F \:D65C\:C131\:D654", "PersonaManagerInMenu" -> "\:BA54\:B274\:C5D0\:C11C", "PersonaManagerName" -> "\:C774\:B984", @@ -114,11 +115,13 @@ "PreferencesContentOpenAICompletionURLLabel" -> "\:CC44\:D305 \:C644\:B8CC URL:", "ResourceInstallerFromURLPrompt" -> "URL\:C744 \:C785\:B825", +"ResourceInstallerFromFilePrompt" -> "Choose a Resource Definition Notebook", "ToolManagerTitle" -> "\:B300\:D615 \:C5B8\:C5B4 \:BAA8\:B378 \:B3C4\:AD6C\:C758 \:CD94\:AC00 \:BC0F \:AD00\:B9AC", "ToolManagerInstallTools" -> "\:B3C4\:AD6C \:C124\:CE58", "ToolManagerInstallFrom" -> "\:B2E4\:C74C\:BD80\:D130 \:C124\:CE58", "ToolManagerInstallFromLLMToolRepo" -> "\:B300\:D615 \:C5B8\:C5B4 \:BAA8\:B378 \:B3C4\:AD6C \:B9AC\:D3EC\:C9C0\:D1A0\:B9AC \[UpperRightArrow]", +"ToolManagerInstallFromFile" -> "Definition Notebook", "ToolManagerManageTools" -> "\:B3C4\:AD6C \:AD00\:B9AC \:BC0F \:D65C\:C131\:D654", "ToolManagerShowEnabledFor" -> "\:B2E4\:C74C\:C5D0 \:B300\:D574 \:D65C\:C131\:D654\:B41C \:B3C4\:AD6C \:D45C\:C2DC:", "ToolManagerTool" -> "\:B3C4\:AD6C", @@ -163,6 +166,8 @@ "StylesheetCopyChatObject" -> "ChatObject \:BCF5\:C0AC", "StylesheetInsertionMenuChatInput" -> "\:CC44\:D305 \:C785\:B825", "StylesheetInsertionMenuSideChat" -> "\:C0AC\:C774\:B4DC \:CC44\:D305", +"StylesheetContextMenuAskAI" -> "Ask AI Assistant", +"StylesheetContextMenuIncludeExclude" -> "Include/Exclude From AI Chat", "PersonaNameBirdnardo" -> "Birdnardo", "PersonaNameCodeAssistant" -> "Code Assistant", diff --git a/FrontEnd/TextResources/Spanish/ChatbookStrings.tr b/FrontEnd/TextResources/Spanish/ChatbookStrings.tr index 86f37b27..6c95c031 100644 --- a/FrontEnd/TextResources/Spanish/ChatbookStrings.tr +++ b/FrontEnd/TextResources/Spanish/ChatbookStrings.tr @@ -75,6 +75,7 @@ "PersonaManagerInstallPersonas" -> "Instalar personas", "PersonaManagerInstallFrom" -> "Instalar desde", "PersonaManagerInstallFromPromptRepo" -> "Repositorio de prompts \[UpperRightArrow]", +"PersonaManagerInstallFromFile" -> "Definition Notebook", "PersonaManagerManagePersonas" -> "Gestionar y habilitar personas", "PersonaManagerInMenu" -> "En men\[UAcute]", "PersonaManagerName" -> "Nombre", @@ -113,11 +114,13 @@ "PreferencesContentOpenAICompletionURLLabel" -> "URL de finalizaci\[OAcute]n de chat:", "ResourceInstallerFromURLPrompt" -> "Ingrese un enlace URL", +"ResourceInstallerFromFilePrompt" -> "Choose a Resource Definition Notebook", "ToolManagerTitle" -> "Agregar y administrar herramientas LLM", "ToolManagerInstallTools" -> "Instalar herramientas", "ToolManagerInstallFrom" -> "Instalar desde", "ToolManagerInstallFromLLMToolRepo" -> "Repositorio de herramientas LLM \[UpperRightArrow]", +"ToolManagerInstallFromFile" -> "Definition Notebook", "ToolManagerManageTools" -> "Administrar y habilitar herramientas", "ToolManagerShowEnabledFor" -> "Mostrar herramientas habilitadas para:", "ToolManagerTool" -> "Herramienta", @@ -162,6 +165,8 @@ "StylesheetCopyChatObject" -> "Copiar ChatObject", "StylesheetInsertionMenuChatInput" -> "Entrada de chat", "StylesheetInsertionMenuSideChat" -> "Chat lateral", +"StylesheetContextMenuAskAI" -> "Ask AI Assistant", +"StylesheetContextMenuIncludeExclude" -> "Include/Exclude From AI Chat", "PersonaNameBirdnardo" -> "Birdnardo", "PersonaNameCodeAssistant" -> "Asistente de c\[OAcute]digo", diff --git a/PacletInfo.wl b/PacletInfo.wl index f6aa8de5..b11a30af 100644 --- a/PacletInfo.wl +++ b/PacletInfo.wl @@ -1,7 +1,7 @@ PacletObject[ <| "Name" -> "Wolfram/Chatbook", "PublisherID" -> "Wolfram", - "Version" -> "1.5.0", + "Version" -> "1.5.1", "WolframVersion" -> "13.3+", "Description" -> "Wolfram Notebooks + LLMs", "License" -> "MIT", @@ -34,10 +34,11 @@ PacletObject[ <| { "Asset", "Root" -> "Assets", "Assets" -> { - { "Icons" , "Icons.wxf" }, - { "DisplayFunctions", "DisplayFunctions.wxf" }, { "AIAssistant" , "AIAssistant" }, - { "SandboxMessages" , "SandboxMessages.wl" } + { "DisplayFunctions", "DisplayFunctions.wxf" }, + { "Icons" , "Icons.wxf" }, + { "SandboxMessages" , "SandboxMessages.wl" }, + { "Tokenizers" , "Tokenizers" } } }, { "LLMConfiguration", diff --git a/Scripts/.githooks/post-checkout b/Scripts/.githooks/post-checkout new file mode 100644 index 00000000..ca7fcb40 --- /dev/null +++ b/Scripts/.githooks/post-checkout @@ -0,0 +1,3 @@ +#!/bin/sh +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-checkout' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; } +git lfs post-checkout "$@" diff --git a/Scripts/.githooks/post-commit b/Scripts/.githooks/post-commit new file mode 100644 index 00000000..52b339cb --- /dev/null +++ b/Scripts/.githooks/post-commit @@ -0,0 +1,3 @@ +#!/bin/sh +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-commit' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; } +git lfs post-commit "$@" diff --git a/Scripts/.githooks/post-merge b/Scripts/.githooks/post-merge new file mode 100644 index 00000000..a912e667 --- /dev/null +++ b/Scripts/.githooks/post-merge @@ -0,0 +1,3 @@ +#!/bin/sh +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-merge' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; } +git lfs post-merge "$@" diff --git a/Scripts/.githooks/pre-push b/Scripts/.githooks/pre-push new file mode 100644 index 00000000..0f0089bc --- /dev/null +++ b/Scripts/.githooks/pre-push @@ -0,0 +1,3 @@ +#!/bin/sh +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'pre-push' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; } +git lfs pre-push "$@" diff --git a/Scripts/BuildMX.wls b/Scripts/BuildMX.wls index 121ad918..b0d1d401 100755 --- a/Scripts/BuildMX.wls +++ b/Scripts/BuildMX.wls @@ -158,6 +158,10 @@ cicd`ScriptConfirm @ expandTags @ tmp; cicd`ConsoleLog[ "Loading paclet..." ]; PacletDirectoryUnload @ $pacletDir; cicd`ScriptConfirmBy[ PacletDirectoryLoad @ tmp, MemberQ @ tmp ]; +Unprotect[ "Wolfram`Chatbook`*" ]; +Remove[ "Wolfram`Chatbook`*" ]; +Remove[ "Wolfram`Chatbook`*`*" ]; +cicd`ScriptConfirmAssert[ Names[ "Wolfram`Chatbook`*" ] === Names[ "Wolfram`Chatbook`*`*" ] === { }, "Names" ]; cicd`ScriptConfirm @ CheckAbort[ Get[ "Wolfram`Chatbook`" ], $Failed ]; cicd`ScriptConfirmMatch[ DeleteDirectory[ tmp, DeleteContents -> True ], Null ]; diff --git a/Scripts/BuildPaclet.wls b/Scripts/BuildPaclet.wls index f60b5a01..37667fd4 100644 --- a/Scripts/BuildPaclet.wls +++ b/Scripts/BuildPaclet.wls @@ -3,6 +3,7 @@ BeginPackage[ "Wolfram`ChatbookScripts`" ]; If[ ! TrueQ @ $loadedDefinitions, Get @ FileNameJoin @ { DirectoryName @ $InputFileName, "Common.wl" } ]; +Get @ cFile @ FileNameJoin @ { DirectoryName @ $InputFileName, "UnformatFiles.wls" }; Get @ cFile @ FileNameJoin @ { DirectoryName @ $InputFileName, "BuildMX.wls" }; result = checkResult @ Wolfram`PacletCICD`BuildPaclet[ diff --git a/Scripts/InstallTestDependencies.wls b/Scripts/InstallTestDependencies.wls new file mode 100644 index 00000000..575d03b3 --- /dev/null +++ b/Scripts/InstallTestDependencies.wls @@ -0,0 +1,25 @@ +#!/usr/bin/env wolframscript + +(* :!CodeAnalysis::BeginBlock:: *) +(* :!CodeAnalysis::Disable::SuspiciousSessionSymbol:: *) + +PacletSiteUpdate @ PacletSites[ ]; + +PacletInstall[ "OAuth" ]; +PacletInstall[ "ServiceConnection_OpenAI" ]; +PacletInstall[ "ServiceConnectionUtilities" ]; +PacletInstall[ "Wolfram/LLMFunctions" ]; + +(* A prebuilt version of the SemanticSearch paclet is included for running tests on 13.3: *) +If[ ! PacletObjectQ @ Quiet @ PacletInstall[ "SemanticSearch" ], + PacletInstall @ FileNameJoin @ { + DirectoryName[ $InputFileName, 2 ], + "Developer/Resources/Paclets/SemanticSearch.paclet" + } +]; + +If[ ! PacletObjectQ @ PacletObject[ "SemanticSearch" ], + Print[ "::error::Failed to install SemanticSearch." ]; + Exit[ 1 ] +]; +(* :!CodeAnalysis::EndBlock:: *) \ No newline at end of file diff --git a/Scripts/UnformatFiles.wls b/Scripts/UnformatFiles.wls new file mode 100644 index 00000000..f02382c5 --- /dev/null +++ b/Scripts/UnformatFiles.wls @@ -0,0 +1,40 @@ +#!/usr/bin/env wolframscript + +BeginPackage[ "Wolfram`ChatbookScripts`" ]; + +If[ ! TrueQ @ $loadedDefinitions, Get @ FileNameJoin @ { DirectoryName @ $InputFileName, "Common.wl" } ]; + +Needs[ "Wolfram`PacletCICD`" -> "cicd`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Definitions*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*unformat*) +unformat[ file_ ] := + Enclose @ Module[ { nb, exported }, + nb = ConfirmMatch[ Import[ file, "NB" ], _Notebook, "Import" ]; + exported = ConfirmBy[ Export[ file, nb, "NB" ], FileExistsQ, "Export" ]; + ConfirmAssert[ StringContainsQ[ Import[ file, "String" ], "(* Internal cache information *)" ], "CacheCheck" ]; + cicd`ConsoleLog[ " "<>exported ]; + exported + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Run*) +files = cicd`ScriptConfirmMatch[ + FileNames[ "*.nb", FileNameJoin @ { $pacletDir, "FrontEnd" }, Infinity ], + { __String } +]; + +(* cSpell: ignore unformatting *) +cicd`ConsoleLog[ "Unformatting " <> ToString @ Length @ files <> " files..." ]; + +result = cicd`ScriptConfirmMatch[ unformat /@ files, { __String } ]; + +EndPackage[ ]; + +Wolfram`ChatbookScripts`result \ No newline at end of file diff --git a/Source/Chatbook/Actions.wl b/Source/Chatbook/Actions.wl index ec36c786..b433e3b4 100644 --- a/Source/Chatbook/Actions.wl +++ b/Source/Chatbook/Actions.wl @@ -3,7 +3,7 @@ (*Package Header*) BeginPackage[ "Wolfram`Chatbook`Actions`" ]; -(* cSpell: ignore TOOLCALL, ENDTOOLCALL, ENDRESULT, nodef *) +(* cSpell: ignore TOOLCALL, ENDTOOLCALL, nodef *) (* TODO: these probably aren't needed as exported symbols since all hooks are going through ChatbookAction *) `AskChat; @@ -21,7 +21,6 @@ Begin[ "`Private`" ]; Needs[ "Wolfram`Chatbook`" ]; Needs[ "Wolfram`Chatbook`Common`" ]; Needs[ "Wolfram`Chatbook`PersonaManager`" ]; -Needs[ "Wolfram`Chatbook`Serialization`" ]; Needs[ "Wolfram`Chatbook`ToolManager`" ]; HoldComplete[ @@ -63,41 +62,42 @@ ChatCellEvaluate[ args___ ] := (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*ChatbookAction*) -ChatbookAction[ "AccentIncludedCells" , args___ ] := catchMine @ accentIncludedCells @ args; -ChatbookAction[ "AIAutoAssist" , args___ ] := catchMine @ AIAutoAssist @ args; -ChatbookAction[ "Ask" , args___ ] := catchMine @ AskChat @ args; -ChatbookAction[ "AssistantMessageLabel" , args___ ] := catchMine @ assistantMessageLabel @ args; -ChatbookAction[ "AttachCodeButtons" , args___ ] := catchMine @ AttachCodeButtons @ args; -ChatbookAction[ "AttachWorkspaceChatInput" , args___ ] := catchMine @ attachWorkspaceChatInput @ args; -ChatbookAction[ "CopyChatObject" , args___ ] := catchMine @ CopyChatObject @ args; -ChatbookAction[ "CopyExplodedCells" , args___ ] := catchMine @ CopyExplodedCells @ args; -ChatbookAction[ "DisableAssistance" , args___ ] := catchMine @ DisableAssistance @ args; -ChatbookAction[ "DisplayInlineChat" , args___ ] := catchMine @ displayInlineChat @ args; -ChatbookAction[ "EvaluateChatInput" , args___ ] := catchMine @ EvaluateChatInput @ args; -ChatbookAction[ "EvaluateWorkspaceChat" , args___ ] := catchMine @ evaluateWorkspaceChat @ args; -ChatbookAction[ "EvaluateInlineChat" , args___ ] := catchMine @ evaluateInlineChat @ args; -ChatbookAction[ "ExclusionToggle" , args___ ] := catchMine @ ExclusionToggle @ args; -ChatbookAction[ "ExplodeDuplicate" , args___ ] := catchMine @ ExplodeDuplicate @ args; -ChatbookAction[ "ExplodeInPlace" , args___ ] := catchMine @ ExplodeInPlace @ args; -ChatbookAction[ "InsertCodeBelow" , args___ ] := catchMine @ insertCodeBelow @ args; -ChatbookAction[ "InsertInlineReference" , args___ ] := catchMine @ InsertInlineReference @ args; -ChatbookAction[ "MakeWorkspaceChatDockedCell", args___ ] := catchMine @ makeWorkspaceChatDockedCell @ args; -ChatbookAction[ "MoveToChatInputField" , args___ ] := catchMine @ moveToChatInputField @ args; -ChatbookAction[ "OpenChatBlockSettings" , args___ ] := catchMine @ OpenChatBlockSettings @ args; -ChatbookAction[ "OpenChatMenu" , args___ ] := catchMine @ OpenChatMenu @ args; -ChatbookAction[ "PersonaManage" , args___ ] := catchMine @ PersonaManage @ args; -ChatbookAction[ "RemoveCellAccents" , args___ ] := catchMine @ removeCellAccents @ args; -ChatbookAction[ "Send" , args___ ] := catchMine @ SendChat @ args; -ChatbookAction[ "SendFeedback" , args___ ] := catchMine @ SendFeedback @ args; -ChatbookAction[ "StopChat" , args___ ] := catchMine @ StopChat @ args; -ChatbookAction[ "TabLeft" , args___ ] := catchMine @ TabLeft @ args; -ChatbookAction[ "TabRight" , args___ ] := catchMine @ TabRight @ args; -ChatbookAction[ "ToggleFormatting" , args___ ] := catchMine @ ToggleFormatting @ args; -ChatbookAction[ "ToolManage" , args___ ] := catchMine @ ToolManage @ args; -ChatbookAction[ "UpdateDynamics" , args___ ] := catchMine @ updateDynamics @ args; -ChatbookAction[ "UserMessageLabel" , args___ ] := catchMine @ userMessageLabel @ args; -ChatbookAction[ "WidgetSend" , args___ ] := catchMine @ WidgetSend @ args; -ChatbookAction[ args___ ] := catchMine @ throwInternalFailure @ ChatbookAction @ args; +ChatbookAction[ "AccentIncludedCells" , args___ ] := catchMine @ accentIncludedCells @ args; +ChatbookAction[ "AIAutoAssist" , args___ ] := catchMine @ AIAutoAssist @ args; +ChatbookAction[ "Ask" , args___ ] := catchMine @ AskChat @ args; +ChatbookAction[ "AssistantMessageLabel" , args___ ] := catchMine @ assistantMessageLabel @ args; +ChatbookAction[ "AttachAssistantMessageButtons", args___ ] := catchMine @ attachAssistantMessageButtons @ args; +ChatbookAction[ "AttachCodeButtons" , args___ ] := catchMine @ AttachCodeButtons @ args; +ChatbookAction[ "AttachWorkspaceChatInput" , args___ ] := catchMine @ attachWorkspaceChatInput @ args; +ChatbookAction[ "CopyChatObject" , args___ ] := catchMine @ CopyChatObject @ args; +ChatbookAction[ "CopyExplodedCells" , args___ ] := catchMine @ CopyExplodedCells @ args; +ChatbookAction[ "DisableAssistance" , args___ ] := catchMine @ DisableAssistance @ args; +ChatbookAction[ "DisplayInlineChat" , args___ ] := catchMine @ displayInlineChat @ args; +ChatbookAction[ "EvaluateChatInput" , args___ ] := catchMine @ EvaluateChatInput @ args; +ChatbookAction[ "EvaluateWorkspaceChat" , args___ ] := catchMine @ evaluateWorkspaceChat @ args; +ChatbookAction[ "EvaluateInlineChat" , args___ ] := catchMine @ evaluateInlineChat @ args; +ChatbookAction[ "ExclusionToggle" , args___ ] := catchMine @ ExclusionToggle @ args; +ChatbookAction[ "ExplodeDuplicate" , args___ ] := catchMine @ ExplodeDuplicate @ args; +ChatbookAction[ "ExplodeInPlace" , args___ ] := catchMine @ ExplodeInPlace @ args; +ChatbookAction[ "InsertCodeBelow" , args___ ] := catchMine @ insertCodeBelow @ args; +ChatbookAction[ "InsertInlineReference" , args___ ] := catchMine @ InsertInlineReference @ args; +ChatbookAction[ "MakeWorkspaceChatDockedCell" , args___ ] := catchMine @ makeWorkspaceChatDockedCell @ args; +ChatbookAction[ "MoveToChatInputField" , args___ ] := catchMine @ moveToChatInputField @ args; +ChatbookAction[ "OpenChatBlockSettings" , args___ ] := catchMine @ OpenChatBlockSettings @ args; +ChatbookAction[ "OpenChatMenu" , args___ ] := catchMine @ OpenChatMenu @ args; +ChatbookAction[ "PersonaManage" , args___ ] := catchMine @ PersonaManage @ args; +ChatbookAction[ "RemoveCellAccents" , args___ ] := catchMine @ removeCellAccents @ args; +ChatbookAction[ "Send" , args___ ] := catchMine @ SendChat @ args; +ChatbookAction[ "SendFeedback" , args___ ] := catchMine @ SendFeedback @ args; +ChatbookAction[ "StopChat" , args___ ] := catchMine @ StopChat @ args; +ChatbookAction[ "TabLeft" , args___ ] := catchMine @ TabLeft @ args; +ChatbookAction[ "TabRight" , args___ ] := catchMine @ TabRight @ args; +ChatbookAction[ "ToggleFormatting" , args___ ] := catchMine @ ToggleFormatting @ args; +ChatbookAction[ "ToolManage" , args___ ] := catchMine @ ToolManage @ args; +ChatbookAction[ "UpdateDynamics" , args___ ] := catchMine @ updateDynamics @ args; +ChatbookAction[ "UserMessageLabel" , args___ ] := catchMine @ userMessageLabel @ args; +ChatbookAction[ "WidgetSend" , args___ ] := catchMine @ WidgetSend @ args; +ChatbookAction[ args___ ] := catchMine @ throwInternalFailure @ ChatbookAction @ args; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) @@ -402,8 +402,8 @@ EvaluateChatInput[ evalCell_CellObject, nbo_NotebookObject, settings_Association (* Send chat while listening for an abort: *) CheckAbort[ - sendChat[ evalCell, nbo, settings ]; - waitForLastTask[ ] + sendChat[ evalCell, nbo, settings ] // LogChatTiming[ "SendChat" ]; + waitForLastTask @ settings , (* The user has issued an abort: *) $aborted = True; @@ -422,11 +422,12 @@ EvaluateChatInput[ evalCell_CellObject, nbo_NotebookObject, settings_Association If[ ListQ @ $lastMessages && StringQ @ $lastChatString, With[ { - chat = constructChatObject @ Append[ + chat = constructChatObject @ mergeToolCallMessages @ Append[ $lastMessages, <| "Role" -> "Assistant", "Content" -> $lastChatString |> - ] + ] // LogChatTiming[ "ConstructChatObject" ] }, + If[ TrueQ @ settings[ "AutoSaveConversations" ], SaveChat[ chat, settings ] ]; applyChatPost[ chat, settings, nbo, $aborted ] ], applyChatPost[ None, settings, nbo, $aborted ]; @@ -438,6 +439,27 @@ EvaluateChatInput[ evalCell_CellObject, nbo_NotebookObject, settings_Association EvaluateChatInput // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*mergeToolCallMessages*) +mergeToolCallMessages // beginDefinition; + +(* :!CodeAnalysis::BeginBlock:: *) +(* :!CodeAnalysis::Disable::KernelBug:: *) +mergeToolCallMessages[ { + a___, + KeyValuePattern[ "ToolRequest" -> True ], + KeyValuePattern[ "ToolResponse" -> True ], + b: KeyValuePattern[ "Role" -> "Assistant" ], + c___ +} ] := mergeToolCallMessages @ { a, b, c }; +(* :!CodeAnalysis::EndBlock:: *) + +mergeToolCallMessages[ messages_List ] := + messages; + +mergeToolCallMessages // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*applyChatPost*) @@ -533,6 +555,9 @@ ensureChatOutputCell[ cell_, new_CellObject? chatInputCellQ ] := ensureChatOutputCell[ cell_, None ] := None; +ensureChatOutputCell[ _, _ ] := + None; + ensureChatOutputCell // endDefinition; (* ::**************************************************************************************************************:: *) @@ -540,15 +565,28 @@ ensureChatOutputCell // endDefinition; (*waitForLastTask*) waitForLastTask // beginDefinition; -waitForLastTask[ ] := waitForLastTask @ $lastTask; +waitForLastTask[ settings_Association ] := + Module[ { timeConstraint }, + timeConstraint = settings[ "TimeConstraint" ]; + If[ TrueQ @ Positive @ timeConstraint, + TimeConstrained[ waitForLastTask @ $lastTask, timeConstraint, StopChat[ ] ], + waitForLastTask @ $lastTask + ] + ]; waitForLastTask[ $Canceled ] := $Canceled; -waitForLastTask[ task_TaskObject ] := ( +waitForLastTask[ None ] := + While[ MatchQ[ $nextTaskEvaluation, _Hold ], + runNextTask @ $nextTaskEvaluation + ]; + +waitForLastTask[ task_TaskObject ] := LogChatTiming[ TaskWait @ task; runNextTask[ ]; - If[ $lastTask =!= task, waitForLastTask @ $lastTask ] -); + If[ $lastTask =!= task, waitForLastTask @ $lastTask ], + "WaitForLastTask" +]; waitForLastTask[ HoldPattern[ $lastTask ] ] := Null; @@ -764,6 +802,9 @@ revertMultimodalContent[ as: KeyValuePattern[ "Content" -> content_List ] ] := < ] |>; +revertMultimodalContent[ as: KeyValuePattern[ "Content" -> content_Association ] ] := + revertMultimodalContent[ <| as, "Content" -> { content } |> ]; + revertMultimodalContent[ as: KeyValuePattern[ "Content" -> _String ] ] := as; diff --git a/Source/Chatbook/ChatHistory.wl b/Source/Chatbook/ChatHistory.wl index 68c14103..ac36ff6f 100644 --- a/Source/Chatbook/ChatHistory.wl +++ b/Source/Chatbook/ChatHistory.wl @@ -30,6 +30,8 @@ $$historyProperty = All | $$validChatHistoryProperty | { $$validChatHi (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*GetChatHistory*) +GetChatHistory // beginDefinition; + GeneralUtilities`SetUsage[ GetChatHistory, "\ GetChatHistory[cell$] gives the list of cells that would be included in the chat history for the \ CellObject specified by cell$. @@ -60,11 +62,10 @@ GetChatHistory[ cell_CellObject, property: $$historyProperty ] := catchMine @ En If[ KeyExistsQ[ as, "Settings" ], as[ "Settings" ] = resolveAutoSettings @ as[ "Settings" ] ]; ConfirmMatch[ selectProperties[ as, property ], Except[ _selectProperties ], "SelectedProperties" ] ], - throwInternalFailure[ GetChatHistory[ cell, property ], ## ] & + throwInternalFailure ]; -GetChatHistory[ args___ ] := - catchMine @ throwFailure[ "InvalidArguments", GetChatHistory, HoldForm @ GetChatHistory @ args ]; +GetChatHistory // endExportedDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) @@ -84,7 +85,7 @@ selectProperties // endDefinition; (*getCellExpressions*) getCellExpressions // beginDefinition; getCellExpressions[ KeyValuePattern[ "CellObjects" -> cells_ ] ] := getCellExpressions @ cells; -getCellExpressions[ cells: { ___CellObject } ] := NotebookRead @ cells; +getCellExpressions[ cells: { ___CellObject } ] := notebookRead @ cells; getCellExpressions // endDefinition; (* ::**************************************************************************************************************:: *) diff --git a/Source/Chatbook/ChatMessageToCell.wl b/Source/Chatbook/ChatMessageToCell.wl new file mode 100644 index 00000000..15098813 --- /dev/null +++ b/Source/Chatbook/ChatMessageToCell.wl @@ -0,0 +1,131 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`ChatMessageToCell`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Configuration*) +$chatOutputOptions = Sequence[ GeneratedCell -> True, CellAutoOverwrite -> True ]; +$selectableOptions = Sequence[ Background -> None, Selectable -> True, Editable -> True ]; + +$$chatCellFormat = None | Automatic | "Default" | "Inline" | "Workspace"; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*ChatMessageToCell*) +ChatMessageToCell // beginDefinition; + +ChatMessageToCell[ message: $$chatMessage, format: $$chatCellFormat ] := catchMine @ Enclose[ + First @ ConfirmMatch[ chatMessagesToCells[ { message }, format ], { _Cell }, "Cell" ], + throwInternalFailure +]; + +ChatMessageToCell[ messages: $$chatMessages, format: $$chatCellFormat ] := catchMine @ Enclose[ + ConfirmMatch[ chatMessagesToCells[ messages, format ], { ___Cell }, "Cells" ], + throwInternalFailure +]; + +ChatMessageToCell // endExportedDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*chatMessagesToCells*) +chatMessagesToCells // beginDefinition; +chatMessagesToCells[ messages_, None|Automatic ] := chatMessagesToCells[ messages, "Default" ]; +chatMessagesToCells[ messages_, format_ ] := chatMessageToCell[ #, format ] & /@ revertMultimodalContent @ messages; +chatMessagesToCells // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*chatMessageToCell*) +chatMessageToCell // beginDefinition; + +chatMessageToCell[ message_Association, format_ ] := + chatMessageToCell[ message[ "Role" ], message[ "Content" ], format ]; + +chatMessageToCell[ role_String, content_, format_ ] := Enclose[ + Module[ { formatted }, + formatted = ConfirmMatch[ getFormattedTextData @ content, _TextData, "TextData" ]; + ConfirmMatch[ wrapCellContent[ formatted, role, format ], _Cell | Nothing, "Result" ] + ], + throwInternalFailure +]; + +chatMessageToCell // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*wrapCellContent*) +wrapCellContent // beginDefinition; + +wrapCellContent[ text_, "Assistant", "Default" ] := Cell[ text, "ChatOutput", $chatOutputOptions ]; +wrapCellContent[ text_, "System" , "Default" ] := Cell[ text, "ChatSystemInput" ]; +wrapCellContent[ text_, "User" , "Default" ] := Cell[ text, "ChatInput" ]; + +wrapCellContent[ text_, "Assistant", "Workspace" ] := workspaceOutput @ text; +wrapCellContent[ text_, "System" , "Workspace" ] := Nothing; (* System inputs shouldn't appear in workspace chat *) +wrapCellContent[ text_, "User" , "Workspace" ] := workspaceInput @ text; + +wrapCellContent // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*workspaceInput*) +workspaceInput // beginDefinition; +workspaceInput[ TextData[ { text_String } ] ] := workspaceInput @ text; +workspaceInput[ TextData[ text_String ] ] := workspaceInput @ text; +workspaceInput[ text_String ] := workspaceInput0 @ text; +workspaceInput[ text_ ] := workspaceInput0 @ Cell @ text; +workspaceInput // endDefinition; + + +workspaceInput0 // beginDefinition; + +workspaceInput0[ stuff_ ] := Cell[ + BoxData @ TemplateBox[ { Cell[ stuff, $selectableOptions ] }, "UserMessageBox" ], + "ChatInput" +]; + +workspaceInput0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*workspaceOutput*) +workspaceOutput // beginDefinition; + +workspaceOutput[ text_TextData ] := + wrapCellContent[ + TextData @ Cell[ + BoxData @ TemplateBox[ { Cell[ text, $selectableOptions ] }, "AssistantMessageBox" ], + Background -> None + ], + "Assistant", + "Default" + ]; + +workspaceOutput // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getFormattedTextData*) +getFormattedTextData // beginDefinition; +getFormattedTextData[ content_String ] := getFormattedTextData[ content, FormatChatOutput @ content ]; +getFormattedTextData[ content_, (Cell|RawBoxes)[ boxes_ ] ] := getFormattedTextData[ content, boxes ]; +getFormattedTextData[ content_, TextData[ text: $$textDataList ] ] := TextData @ text; +getFormattedTextData[ content_, string_String ] := TextData @ { string }; +getFormattedTextData[ content_String, boxes_ ] := TextData @ { content }; +getFormattedTextData // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/ChatMessages.wl b/Source/Chatbook/ChatMessages.wl index 395b39e0..35cdda7a 100644 --- a/Source/Chatbook/ChatMessages.wl +++ b/Source/Chatbook/ChatMessages.wl @@ -5,11 +5,10 @@ Begin[ "`Private`" ]; (* :!CodeAnalysis::BeginBlock:: *) -Needs[ "Wolfram`Chatbook`" ]; -Needs[ "Wolfram`Chatbook`Actions`" ]; -Needs[ "Wolfram`Chatbook`Common`" ]; -Needs[ "Wolfram`Chatbook`Personas`" ]; -Needs[ "Wolfram`Chatbook`Serialization`" ]; +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Actions`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; +Needs[ "Wolfram`Chatbook`Personas`" ]; $ContextAliases[ "tokens`" ] = "Wolfram`LLMFunctions`Utilities`Tokenization`"; @@ -116,11 +115,12 @@ constructMessages[ settings_Association? AssociationQ, cells: { __Cell } ] := constructMessages[ settings, makeChatMessages[ settings, cells ] ]; constructMessages[ settings_Association? AssociationQ, messages0: { __Association } ] := - Enclose @ Module[ { prompted, messages, processed }, + Enclose @ Module[ + { prompted, messages, merged, genRole, genPos, generatedPrompts, generatedMessages, combined, processed }, If[ settings[ "AutoFormat" ], needsBasePrompt[ "Formatting" ] ]; needsBasePrompt @ settings; - prompted = addPrompts[ settings, messages0 ]; + prompted = addPrompts[ settings, DeleteCases[ messages0, KeyValuePattern[ "Temporary" -> True ] ] ]; messages = prompted /. s_String :> RuleCondition @ StringTrim @ StringReplace[ @@ -133,7 +133,36 @@ constructMessages[ settings_Association? AssociationQ, messages0: { __Associatio } ]; - processed = applyProcessingFunction[ settings, "ChatMessages", HoldComplete[ messages, $ChatHandlerData ] ]; + merged = If[ TrueQ @ Lookup[ settings, "MergeMessages" ], + ConfirmMatch[ mergeMessageData @ messages, $$chatMessages, "Merged" ], + messages + ]; + + genRole = settings[ "PromptGeneratorMessageRole" ]; + genPos = settings[ "PromptGeneratorMessagePosition" ]; + + If[ ! MatchQ[ genRole, "System"|"Assistant"|"User" ], + throwFailure[ "InvalidPromptGeneratorRole", genRole ] + ]; + + generatedPrompts = ConfirmMatch[ applyPromptGenerators[ settings, merged ], { ___String }, "Generated" ]; + + generatedMessages = Splice @ ConfirmMatch[ + <| "Role" -> genRole, "Content" -> #, "Temporary" -> True |> & /@ generatedPrompts, + $$chatMessages, + "GeneratedMessages" + ]; + + combined = ConfirmMatch[ + Check[ + Insert[ merged, generatedMessages, genPos ], + throwFailure[ "InvalidPromptGeneratorPosition", genPos ] + ], + $$chatMessages, + "Combined" + ]; + + processed = applyProcessingFunction[ settings, "ChatMessages", HoldComplete[ combined, $ChatHandlerData ] ]; If[ ! MatchQ[ processed, $$validMessageResults ], messagePrint[ "InvalidMessages", getProcessingFunction[ settings, "ChatMessages" ], processed ]; @@ -141,6 +170,9 @@ constructMessages[ settings_Association? AssociationQ, messages0: { __Associatio ]; processed //= DeleteCases @ KeyValuePattern[ "Content" -> "" ]; + + processed = rewriteMessageRoles[ settings, processed ]; + Sow[ <| "Messages" -> processed |>, $chatDataTag ]; $lastSettings = settings; @@ -151,6 +183,30 @@ constructMessages[ settings_Association? AssociationQ, messages0: { __Associatio constructMessages // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*rewriteMessageRoles*) +rewriteMessageRoles // beginDefinition; +rewriteMessageRoles[ settings_? o1ModelQ, messages_ ] := convertSystemRoleToUser @ messages; +rewriteMessageRoles[ settings_, messages_ ] := messages; +rewriteMessageRoles // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*convertSystemRoleToUser*) +convertSystemRoleToUser // beginDefinition; + +convertSystemRoleToUser[ messages_List ] := + convertSystemRoleToUser /@ messages; + +convertSystemRoleToUser[ as: KeyValuePattern @ { "Role" -> "System", "Content" -> content_ } ] := + <| as, "Role" -> "User" |>; + +convertSystemRoleToUser[ message_Association ] := + message; + +convertSystemRoleToUser // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*constructInlineMessages*) @@ -281,7 +337,7 @@ makeChatMessages0[ settings_, { cells___, cell_ ? promptFunctionCellQ }, include ); makeChatMessages0[ settings0_, cells_List, includeSystem_ ] := Enclose[ - Module[ { settings, role, message, toMessage0, toMessage, cell, history, messages, merged }, + Module[ { settings, role, message, toMessage0, toMessage, cell, history, messages }, settings = ConfirmBy[ <| settings0, "HistoryPosition" -> 0, "Cells" -> cells |>, AssociationQ, "Settings" ]; role = If[ TrueQ @ includeSystem, makeCurrentRole @ settings, Missing[ ] ]; cell = ConfirmMatch[ Last[ cells, $Failed ], _Cell, "Cell" ]; @@ -310,8 +366,7 @@ makeChatMessages0[ settings0_, cells_List, includeSystem_ ] := Enclose[ messages = addExcisedCellMessage @ DeleteMissing @ Flatten @ { role, history, message }; - merged = If[ TrueQ @ Lookup[ settings, "MergeMessages" ], mergeMessageData @ messages, messages ]; - $lastMessageList = merged + $lastMessageList = messages ], throwInternalFailure ]; @@ -1326,7 +1381,7 @@ argumentTokenToString // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Tokenization*) -$tokenizer := $gpt2Tokenizer; +$tokenizer := cachedTokenizer[ "gpt-4o" ]; (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) @@ -1374,10 +1429,10 @@ cachedTokenizer[ id_String ] := cachedTokenizer[ id_String ] := Enclose[ Module[ { name, tokenizer }, name = ConfirmBy[ tokenizerName @ toModelName @ id, StringQ, "Name" ]; - tokenizer = findTokenizer @ name; + tokenizer = LogChatTiming @ findTokenizer @ name; If[ MissingQ @ tokenizer, (* Fallback to the GPT-2 tokenizer: *) - tokenizer = ConfirmMatch[ $genericTokenizer, Except[ $$unspecified ], "GPT2Tokenizer" ]; + tokenizer = ConfirmMatch[ $cachedTokenizers[ "generic" ], Except[ $$unspecified ], "GPT2Tokenizer" ]; If[ TrueQ @ Wolfram`ChatbookInternal`$BuildingMX, tokenizer, (* Avoid caching fallback values into MX definitions *) cacheTokenizer[ name, tokenizer ] @@ -1407,12 +1462,37 @@ cacheTokenizer // endDefinition; (*findTokenizer*) findTokenizer // beginDefinition; -findTokenizer[ "gpt-4o-text" ] := +findTokenizer[ model_String ] := Enclose[ + Catch @ Module[ { dir, file, tokenizer }, + + dir = ConfirmBy[ $tokenizerDirectory, StringQ, "Directory" ]; + file = FileNameJoin @ { dir, model<>".wxf" }; + + tokenizer = If[ FileExistsQ @ file, + LogChatTiming[ Developer`ReadWXFFile @ file, "ReadTokenizerFile" ], + findTokenizer0 @ model + ]; + + If[ MissingQ @ tokenizer, Throw @ tokenizer ]; + + ConfirmMatch[ LogChatTiming[ tokenizer[ "test" ], "TokenizerTest" ], _List, "TokenizerTest" ]; + + tokenizer + ], + throwInternalFailure +]; + +findTokenizer // endDefinition; + + +findTokenizer0 // beginDefinition; + +findTokenizer0[ "gpt-4o-text" ] := With[ { tokenizer = findTokenizer[ "gpt-4o" ] }, tokenizer /; ! MissingQ @ tokenizer ]; -findTokenizer[ model_String ] := Enclose[ +findTokenizer0[ model_String ] := Enclose[ Quiet @ Module[ { name, tokenizer }, initTools[ ]; Quiet @ Needs[ "Wolfram`LLMFunctions`Utilities`Tokenization`" -> None ]; @@ -1424,7 +1504,10 @@ findTokenizer[ model_String ] := Enclose[ Missing[ "NotFound" ] & ]; -findTokenizer // endDefinition; +findTokenizer0 // endDefinition; + + +$tokenizerDirectory := $tokenizerDirectory = FileNameJoin @ { $thisPaclet[ "Location" ], "Assets", "Tokenizers" }; (* ::**************************************************************************************************************:: *) (* ::Subsubsubsection::Closed:: *) @@ -1433,7 +1516,7 @@ $cachedTokenizers[ "chat-bison" ] = ToCharacterCode[ #, "UTF8" ] &; $cachedTokenizers[ "gpt-4-vision" ] = If[ graphicsQ @ #, gpt4ImageTokenizer, cachedTokenizer[ "gpt-4" ] ][ # ] &; $cachedTokenizers[ "gpt-4o" ] = If[ graphicsQ @ #, gpt4ImageTokenizer, cachedTokenizer[ "gpt-4o-text" ] ][ # ] &; $cachedTokenizers[ "claude-3" ] = If[ graphicsQ @ #, claude3ImageTokenizer, cachedTokenizer[ "claude" ] ][ # ] &; -$cachedTokenizers[ "generic" ] = If[ graphicsQ @ #, { }, $gpt2Tokenizer @ # ] &; +$cachedTokenizers[ "generic" ] = If[ graphicsQ @ #, { }, cachedTokenizer[ "gpt-2" ][ # ] ] &; (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) @@ -1523,22 +1606,11 @@ claude3ImageTokenCount0[ image_, { w_, h_ } ] := claude3ImageTokenCount0[ w, h ] claude3ImageTokenCount0[ w_Integer, h_Integer ] := Ceiling[ (w * h) / 750 ]; claude3ImageTokenCount0 // endDefinition; -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*Fallback Tokenizer*) -$gpt2Tokenizer := $gpt2Tokenizer = gpt2Tokenizer[ ]; - -(* https://resources.wolframcloud.com/FunctionRepository/resources/GPTTokenizer *) -importResourceFunction[ gpt2Tokenizer, "GPTTokenizer" ]; - (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Package Footer*) addToMXInitialization[ - cachedTokenizer[ All ]; - $gpt2Tokenizer; - (* This is only needed to generate $gpt2Tokenizer once, so it can be removed to reduce MX file size: *) - Remove[ "Wolfram`Chatbook`ResourceFunctions`GPTTokenizer`GPTTokenizer" ]; + Null ]; (* :!CodeAnalysis::EndBlock:: *) diff --git a/Source/Chatbook/ChatModes/ChatModes.wl b/Source/Chatbook/ChatModes/ChatModes.wl index 72f03983..7caf0c15 100644 --- a/Source/Chatbook/ChatModes/ChatModes.wl +++ b/Source/Chatbook/ChatModes/ChatModes.wl @@ -10,9 +10,6 @@ Needs[ "Wolfram`Chatbook`Common`" ]; * Workspace Chat * Get context from multiple notebooks * Set up an LLM subtask to choose relevant notebooks for inclusion - * Fine-grained selection prompts (e.g. specific character ranges, instead of whole cells) - * Update serialization to include cell identifiers when serializing notebook context - * Create NotebookEditor tool that utilizes these cell identifiers to allow for editing of notebooks * Create test writer tool * Define a `$ChatEvaluationMode` that gives "Inline", "Workspace", or None based on the current chat mode *) @@ -38,6 +35,7 @@ $InlineChat = False; (*Load Subcontexts*) $subcontexts = { "Wolfram`Chatbook`ChatModes`Common`", + "Wolfram`Chatbook`ChatModes`ContentSuggestions`", "Wolfram`Chatbook`ChatModes`Context`", "Wolfram`Chatbook`ChatModes`Evaluate`", "Wolfram`Chatbook`ChatModes`ShowCodeAssistance`", diff --git a/Source/Chatbook/ChatModes/Common.wl b/Source/Chatbook/ChatModes/Common.wl index cda3b9ce..5b7a5023 100644 --- a/Source/Chatbook/ChatModes/Common.wl +++ b/Source/Chatbook/ChatModes/Common.wl @@ -10,6 +10,7 @@ HoldComplete[ `$inputFieldPaneMargins, `createWorkspaceChat, `findCurrentWorkspaceChat, + `getContextFromSelection, `getSelectionInfo, `moveToInlineChatInputField, `scrollInlineChat, diff --git a/Source/Chatbook/ChatModes/ContentSuggestions.wl b/Source/Chatbook/ChatModes/ContentSuggestions.wl new file mode 100644 index 00000000..16e0adb8 --- /dev/null +++ b/Source/Chatbook/ChatModes/ContentSuggestions.wl @@ -0,0 +1,1012 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`ChatModes`ContentSuggestions`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; +Needs[ "Wolfram`Chatbook`ChatModes`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Configuration*) +$suggestionsService = "OpenAI"; +$suggestionsAuthentication = Automatic; +$stripWhitespace = True; +$defaultWLContextString = ""; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Wolfram Language Suggestions*) +$wlSuggestionsModel = "gpt-4o"; +$wlSuggestionsMultimodal = False; +$wlSuggestionsCount = 3; +$wlSuggestionsMaxTokens = 128; +$wlSuggestionsTemperature = 0.9; +$wlPlaceholderString = "\:2758"; +$wlCellsBefore = 50; +$wlCellsAfter = 25; +$wlDocMaxItems = 5; +$wlFilterDocResults = False; +$wlFilteredDocCount = 3; + +$wlSuggestionsPrompt := If[ TrueQ @ $wlFIM, $wlFIMPrompt, $wlSuggestionsPrompt0 ]; + +(* TODO: make the language a template parameter to support ExternalLanguage cells too: *) +$wlSuggestionsPrompt0 = StringTemplate[ "\ +Complete the following Wolfram Language code by writing text that can be inserted into \"%%Placeholder%%\". +Do your best to match the existing style (whitespace, line breaks, etc.). +Your suggested text will be inserted into %%Placeholder%%, so be careful not to repeat the immediately surrounding text. +Use `%` to refer to the previous output or `%n` for earlier outputs (where n is an output number) when appropriate. +Limit your suggested completion to approximately one or two lines of code. +Respond with the completion text and nothing else. +Do not include any formatting in your response. Do not include outputs or `In[]:=` cell labels. + +%%RelatedDocumentation%%", +Delimiters -> "%%" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*Fill-in-the-Middle Completions*) +(* cSpell: ignore Ollama, CodeGemma, DeepSeek *) +$wlFIM = False; +$wlFIMService = "Ollama"; +$wlFIMModel = "deepseek-coder-v2"; +$wlFIMAuthentication = Automatic; +$wlFIMTemperature = 0.7; +$wlFIMSuggestionsCount = 1; + +$wlFIMOptions = <| + "num_predict" -> $wlSuggestionsMaxTokens, + "stop" -> { "\n\n" }, + "temperature" -> $wlFIMTemperature +|>; + +$wlFIMPrompt = StringTemplate[ "\ +Complete the following Wolfram Language code. +Do your best to match the existing style (whitespace, line breaks, etc.). +Use `%` to refer to the previous output or `%n` for earlier outputs (where n is an output number) when appropriate. +Limit your suggested completion to approximately one or two lines of code. +Do not include any formatting in your response. Do not include outputs or `In[]:=` cell labels.", +Delimiters -> "%%" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*TextData Suggestions*) +$textSuggestionsModel = "gpt-4o"; +$textSuggestionsMultimodal = False; +$textSuggestionsCount = 3; +$textSuggestionsMaxTokens = 256; +$textSuggestionsTemperature = 0.7; +$textPlaceholderString = "\:2758"; +$textCellsBefore = 50; +$textCellsAfter = 25; + +$textSuggestionsPrompt = StringTemplate[ "\ +Complete the following by writing text that can be inserted into \"%%Placeholder%%\". +The current cell style is \"%%Style%%\", so only write content that would be appropriate for this cell type.\ +%%StyleNotes%% +Do your best to match the existing style (whitespace, line breaks, etc.). +Your suggested text will be inserted into %%Placeholder%%, so be careful not to repeat the immediately surrounding text. +Respond with the completion text and nothing else.", +Delimiters -> "%%" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Notebook Content Suggestions*) +$notebookSuggestionsModel = "gpt-4o"; +$notebookSuggestionsMultimodal = False; +$notebookSuggestionsCount = 1; +$notebookSuggestionsMaxTokens = 512; +$notebookSuggestionsTemperature = 0.7; +$notebookPlaceholderString = "\:2758"; +$notebookCellsBefore = 50; +$notebookCellsAfter = 25; + +$notebookSuggestionsPrompt = StringTemplate[ "\ +Complete the following by writing markdown text that can be inserted into \"%%Placeholder%%\". +Do your best to match the existing style (whitespace, line breaks, etc.). +Your suggested text will be inserted into %%Placeholder%%, so be careful not to repeat the immediately surrounding text. +Respond with the completion text and nothing else. + +%%RelatedDocumentation%%", +Delimiters -> "%%" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Patterns*) +$$emptyItem = "" | { } | { "" }; +$$emptySuggestion = $$emptyItem | BoxData @ $$emptyItem | TextData @ $$emptyItem; + +$$inLabel = "In[" ~~ DigitCharacter... ~~ "]" ~~ WhitespaceCharacter... ~~ ":="; +$$outLabel = "Out[" ~~ DigitCharacter... ~~ "]" ~~ WhitespaceCharacter... ~~ ("="|"//"); + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*ShowContentSuggestions*) +ShowContentSuggestions // beginDefinition; +ShowContentSuggestions[ ] := catchMine @ withChatState @ LogChatTiming @ showContentSuggestions @ InputNotebook[ ]; +ShowContentSuggestions[ nbo_ ] := catchMine @ withChatState @ LogChatTiming @ showContentSuggestions @ nbo; +ShowContentSuggestions // endExportedDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*showContentSuggestions*) +showContentSuggestions // beginDefinition; + +showContentSuggestions[ $Failed ] := + Null; + +showContentSuggestions[ nbo_NotebookObject ] := + showContentSuggestions[ nbo, SelectedCells @ nbo ]; + +showContentSuggestions[ nbo_NotebookObject, { selected_CellObject } ] := + showContentSuggestions0[ nbo, selected ]; + +(* showContentSuggestions[ nbo_NotebookObject, { } ] := Enclose[ + Module[ { selected }, + (* FIXME: this is where notebook content suggestions should come in *) + SelectionMove[ nbo, After, Cell ]; + NotebookWrite[ nbo, "", All ]; + selected = ConfirmMatch[ SelectedCells @ nbo, { _CellObject }, "Selected" ]; + showContentSuggestions0[ nbo, First @ selected ] + ], + throwInternalFailure +]; *) + +showContentSuggestions[ nbo_NotebookObject, { } ] := + showContentSuggestions0[ nbo, nbo ]; + +showContentSuggestions[ _NotebookObject, _ ] := + Null; + +showContentSuggestions // endDefinition; + + +showContentSuggestions0 // beginDefinition; + +showContentSuggestions0[ nbo_NotebookObject, root: $$feObj ] := Enclose[ + Catch @ Module[ { selectionType, contentData, info }, + + NotebookDelete @ Cells[ nbo, AttachedCell -> True, CellStyle -> "AttachedContentSuggestions" ]; + selectionType = CurrentValue[ nbo, "SelectionType" ]; + $lastSelectionType = selectionType; + If[ ! MatchQ[ selectionType, "CellCaret"|"TextCaret"|"TextRange" ], Throw @ Null ]; + contentData = If[ MatchQ[ root, _CellObject ], cellInformation[ root, "ContentData" ], None ]; + info = <| "ContentData" -> contentData, "SelectionType" -> selectionType |>; + + ConfirmMatch[ + setServiceCaller[ showContentSuggestions0[ nbo, root, info ], "ContentSuggestions" ], + _CellObject | Null, + "ShowContentSuggestions" + ] + ], + throwInternalFailure +]; + +showContentSuggestions0[ nbo_NotebookObject, root: $$feObj, selectionInfo_Association ] := Enclose[ + Catch @ Module[ { type, suggestionsContainer, attached, settings, context }, + + type = ConfirmBy[ suggestionsType @ selectionInfo, StringQ, "Type" ]; + + suggestionsContainer = ProgressIndicator[ Appearance -> "Necklace" ]; + + attached = ConfirmMatch[ + AttachCell[ + NotebookSelection @ nbo, + contentSuggestionsCell[ Dynamic[ suggestionsContainer ] ], + { "WindowCenter", Bottom }, + 0, + { Center, Top }, + RemovalConditions -> { "EvaluatorQuit", "MouseClickOutside" } + ], + _CellObject, + "Attached" + ]; + + ClearAttributes[ suggestionsContainer, Temporary ]; + + settings = ConfirmBy[ LogChatTiming @ AbsoluteCurrentChatSettings @ root, AssociationQ, "Settings" ]; + context = ConfirmBy[ LogChatTiming @ getSuggestionsContext[ type, nbo, settings ], StringQ, "Context" ]; + + $contextPrompt = None; + $selectionPrompt = None; + + ConfirmMatch[ + LogChatTiming @ generateSuggestions[ type, Dynamic[ suggestionsContainer ], nbo, root, context, settings ], + _Pane, + "Generate" + ]; + + attached + ], + throwInternalFailure +]; + +showContentSuggestions0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getSuggestionsContext*) +getSuggestionsContext // beginDefinition; + +getSuggestionsContext[ "WL", nbo_NotebookObject, settings_ ] := getContextFromSelection[ + None, + nbo, + settings, + "NotebookInstructionsPrompt" -> False, + "MaxCellsBeforeSelection" -> $wlCellsBefore, + "MaxCellsAfterSelection" -> $wlCellsAfter +]; + +getSuggestionsContext[ "Text", nbo_NotebookObject, settings_ ] := getContextFromSelection[ + None, + nbo, + settings, + "NotebookInstructionsPrompt" -> False, + "MaxCellsBeforeSelection" -> $textCellsBefore, + "MaxCellsAfterSelection" -> $textCellsAfter +]; + +getSuggestionsContext[ "Notebook", nbo_NotebookObject, settings_ ] := getContextFromSelection[ + None, + nbo, + settings, + "NotebookInstructionsPrompt" -> False, + "MaxCellsBeforeSelection" -> $notebookCellsBefore, + "MaxCellsAfterSelection" -> $notebookCellsAfter +]; + +getSuggestionsContext // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*contentSuggestionsCell*) +contentSuggestionsCell // beginDefinition; + +contentSuggestionsCell[ Dynamic[ container_Symbol ] ] := Cell[ + BoxData @ ToBoxes @ Framed[ + Dynamic[ container(*, Deinitialization :> Quiet @ Remove @ container*) ], + Background -> GrayLevel[ 0.95 ], + FrameStyle -> GrayLevel[ 0.75 ], + RoundingRadius -> 5 + ], + "AttachedContentSuggestions" +]; + +contentSuggestionsCell // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*suggestionsType*) +suggestionsType // beginDefinition; +suggestionsType[ selectionInfo_Association ] := suggestionsType @ selectionInfo[ "ContentData" ]; +suggestionsType[ BoxData ] := "WL"; +suggestionsType[ TextData ] := "Text"; +suggestionsType[ _ ] := "Notebook"; +suggestionsType // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*generateSuggestions*) +generateSuggestions // beginDefinition; +generateSuggestions[ "WL" , args__ ] := generateWLSuggestions @ args; +generateSuggestions[ "Text" , args__ ] := generateTextSuggestions @ args; +generateSuggestions[ "Notebook", args__ ] := generateNotebookSuggestions @ args; +generateSuggestions // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*generateWLSuggestions*) +generateWLSuggestions // beginDefinition; + +generateWLSuggestions[ Dynamic[ container_ ], nbo_, root_CellObject, context0_String, settings_ ] := Enclose[ + Module[ { context, preprocessed, relatedDocs, as, instructions, response, style, suggestions, stripped }, + + context = ConfirmBy[ + StringReplace[ + context0, + Shortest[ $leftSelectionIndicator~~___~~$rightSelectionIndicator ] :> $wlPlaceholderString + ], + StringQ, + "Context" + ]; + + If[ TrueQ @ $wlSuggestionsMultimodal, + context = ConfirmMatch[ GetExpressionURIs @ context, { (_String|_Image)... }, "MultimodalContext" ] + ]; + + $lastSuggestionContext = context; + + preprocessed = ConfirmBy[ preprocessRelatedDocsContext @ context, StringQ, "Preprocessing" ]; + + relatedDocs = ConfirmBy[ + LogChatTiming @ RelatedDocumentation[ + preprocessed, + "Prompt", + MaxItems -> $wlDocMaxItems, + "FilterResults" -> $wlFilterDocResults, + "FilteredCount" -> $wlFilteredDocCount + ], + StringQ, + "RelatedDocumentation" + ]; + + as = <| + "Context" -> context, + "Placeholder" -> $wlPlaceholderString, + "RelatedDocumentation" -> relatedDocs + |>; + + instructions = StringTrim @ ConfirmBy[ TemplateApply[ $wlSuggestionsPrompt, as ], StringQ, "Instructions" ]; + as[ "Instructions" ] = instructions; + + $lastInstructions = instructions; + + response = ConfirmMatch[ + executeWLSuggestions @ as, + KeyValuePattern[ "Content" -> { __String } | _String ], + "Response" + ]; + + $lastSuggestionsResponse = response; + + style = First[ ConfirmMatch[ cellStyles @ root, { ___String }, "Styles" ], "Input" ]; + + suggestions = DeleteDuplicates @ ConfirmMatch[ + getWLSuggestions[ style, response ], + { __BoxData }, + "Suggestions" + ]; + + (* FIXME: strip surrounding code in getWLSuggestions instead of going from string -> boxes -> string -> boxes *) + stripped = Take[ + ConfirmMatch[ stripSurroundingWLCode[ style, suggestions, context ], { __BoxData }, "Stripped" ], + UpTo[ $wlSuggestionsCount ] + ]; + + $lastSuggestions = suggestions; + + container = formatSuggestions[ Dynamic[ container ], stripped, nbo, root, context, settings ] + ], + throwInternalFailure +]; + +generateWLSuggestions // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*executeWLSuggestions*) +executeWLSuggestions // beginDefinition; +executeWLSuggestions[ as_ ] := If[ TrueQ @ $wlFIM, executeWLSuggestionsFIM @ as, executeWLSuggestions0 @ as ]; +executeWLSuggestions // endDefinition; + + +executeWLSuggestions0 // beginDefinition; + +executeWLSuggestions0[ KeyValuePattern @ { "Instructions" -> instructions_, "Context" -> context_ } ] := + executeWLSuggestions0[ instructions, context ]; + +executeWLSuggestions0[ instructions_, context_ ] := + setServiceCaller @ LogChatTiming @ ServiceExecute[ + $suggestionsService, + "Chat", + { + "Messages" -> { + <| "Role" -> "System", "Content" -> instructions |>, + <| "Role" -> "User" , "Content" -> context |> + }, + "Model" -> $wlSuggestionsModel, + "N" -> $wlSuggestionsCount, + "MaxTokens" -> $wlSuggestionsMaxTokens, + "Temperature" -> $wlSuggestionsTemperature + }, + Authentication -> $suggestionsAuthentication + ]; + +executeWLSuggestions0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*executeWLSuggestionsFIM*) +executeWLSuggestionsFIM // beginDefinition; + +executeWLSuggestionsFIM[ as_Association ] := Enclose[ + Module[ { instructions, context, docs, before, after, prompt, suffix, responses, strings }, + + instructions = ConfirmBy[ as[ "Instructions" ], StringQ, "Instructions" ]; + context = ConfirmBy[ as[ "Context" ], StringQ, "Context" ]; + docs = ConfirmBy[ as[ "RelatedDocumentation" ], StringQ, "RelatedDocs" ]; + + { before, after } = ConfirmMatch[ + StringSplit[ context, $wlPlaceholderString ], + { _String, _String }, + "Split" + ]; + + prompt = ConfirmBy[ instructions<>"\n\n\n"<>before, StringQ, "Prompt" ]; + suffix = ConfirmBy[ after<>"\n\n\n"<>docs, StringQ, "Suffix" ]; + + responses = ConfirmMatch[ + Table[ + setServiceCaller @ LogChatTiming @ ServiceExecute[ + $wlFIMService, + "RawCompletion", + DeleteMissing @ <| + "model" -> $wlFIMModel, + "prompt" -> prompt, + "suffix" -> suffix, + "stream" -> False, + "options" -> $wlFIMOptions + |>, + Authentication -> $wlFIMAuthentication + ], + $wlFIMSuggestionsCount + ], + { __Association }, + "Responses" + ]; + + strings = ConfirmMatch[ #[ "response" ] & /@ responses, { __String }, "Strings" ]; + + <| "Content" -> strings |> + ], + throwInternalFailure +]; + +executeWLSuggestionsFIM // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*preprocessRelatedDocsContext*) +preprocessRelatedDocsContext // beginDefinition; + +preprocessRelatedDocsContext[ context_String ] := Enclose[ + Module[ { processed, noPlaceholder }, + processed = ConfirmBy[ preprocessRelatedDocsContext0 @ context, StringQ, "Processed" ]; + noPlaceholder = ConfirmBy[ StringDelete[ processed, $wlPlaceholderString ], StringQ, "NoPlaceholder" ]; + ConfirmBy[ + StringReplace[ + StringTrim @ noPlaceholder, + StartOfString ~~ "```wl" ~~ WhitespaceCharacter... ~~ "```" ~~ EndOfString :> $defaultWLContextString + ], + StringQ, + "Result" + ] + ], + throwInternalFailure +]; + +preprocessRelatedDocsContext // endDefinition; + + +preprocessRelatedDocsContext0 // beginDefinition; + +preprocessRelatedDocsContext0[ context_String ] := + preprocessRelatedDocsContext0[ + context, + DeleteCases[ + StringSplit[ context, code: Shortest[ "```" ~~ __ ~~ "```" ] :> codeBlock @ code ], + _String? (StringMatchQ[ WhitespaceCharacter... ]) + ] + ]; + +preprocessRelatedDocsContext0[ context_, { ___, text_String, codeBlock[ code_String ] } ] := + StringJoin[ text, code ]; + +(* SentenceBERT doesn't do well with pure code, so don't try to include documentation RAG if that's all we have: *) +preprocessRelatedDocsContext0[ context_, { ___codeBlock } ] := + ""; + +(* TODO: in cases like this, it might be best to just use heuristics to choose relevant documentation from symbols. *) + +preprocessRelatedDocsContext0[ context_String, { (_String|_codeBlock)... } ] := + context; + +preprocessRelatedDocsContext0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*stripSurroundingWLCode*) +stripSurroundingWLCode // beginDefinition; + +stripSurroundingWLCode[ style_, suggestions_, context_ ] := + Block[ { $stripWhitespace = stripWhitespaceQ @ style }, + stripSurroundingWLCode[ suggestions, context ] + ]; + +stripSurroundingWLCode[ suggestions: { __BoxData }, context_String ] := Enclose[ + Catch @ Module[ { surrounding, stripped }, + + surrounding = ConfirmMatch[ getSurroundingWLCode @ context, { _String, _String }, "Surrounding" ]; + If[ StringTrim @ surrounding === { "", "" }, Throw @ suggestions ]; + + stripped = ConfirmMatch[ + Flatten[ stripSurroundingWLCode[ #, surrounding ] & /@ suggestions ], + { suggestionWrapper[ _Integer, _BoxData ].. }, + "Result" + ]; + + ConfirmMatch[ DeleteDuplicates @ SortBy[ stripped, First ][[ All, 2 ]], { __BoxData }, "Result" ] + ], + throwInternalFailure +]; + +stripSurroundingWLCode[ suggestion_BoxData, { before_String, after_String } ] := Enclose[ + Catch @ Module[ { string, stripped, boxes }, + string = ConfirmBy[ CellToString @ StyleBox[ suggestion, ShowStringCharacters -> True ], StringQ, "String" ]; + + stripped = ConfirmBy[ + If[ StringMatchQ[ string, before ~~ ___ ~~ after ], + StringDelete[ string, { StartOfString~~before, after~~EndOfString } ], + Throw @ { suggestionWrapper[ 1, suggestion ] } + ], + StringQ, + "Stripped" + ]; + + boxes = ConfirmMatch[ postProcessWLSuggestions @ stripped, _BoxData, "Result" ]; + + DeleteDuplicatesBy[ { suggestionWrapper[ 0, boxes ], suggestionWrapper[ 1, suggestion ] }, Last ] + ], + throwInternalFailure +]; + +stripSurroundingWLCode // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getSurroundingWLCode*) +getSurroundingWLCode // beginDefinition; + +getSurroundingWLCode[ context_String ] := Enclose[ + Catch @ Module[ { strings, boxes }, + strings = First @ ConfirmMatch[ + StringCases[ + context, + StringExpression[ + "```wl\n", + a___ /; StringFreeQ[ a, "```" ], + $wlPlaceholderString, + b___ /; StringFreeQ[ b, "```" ], + "\n```" + ] :> { a, b }, + 1 + ], + { { _String, _String } }, + "Strings" + ]; + + boxes = ConfirmMatch[ postProcessWLSuggestions @ strings, { _BoxData, _BoxData }, "Boxes" ]; + + ConfirmMatch[ CellToString /@ boxes, { _String, _String }, "Result" ] + ], + throwInternalFailure +]; + +getSurroundingWLCode // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getWLSuggestions*) +getWLSuggestions // beginDefinition; + +getWLSuggestions[ style_, content_ ] := + Block[ { $stripWhitespace = stripWhitespaceQ @ style }, + postProcessWLSuggestions @ getSuggestions @ content + ]; + +getWLSuggestions // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*stripWhitespaceQ*) +stripWhitespaceQ // beginDefinition; +stripWhitespaceQ[ "Code" ] := False; +stripWhitespaceQ[ _String ] := True; +stripWhitespaceQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*postProcessWLSuggestions*) +postProcessWLSuggestions // beginDefinition; + +postProcessWLSuggestions[ suggestions_List ] := + postProcessWLSuggestions /@ suggestions; + +postProcessWLSuggestions[ suggestion_String ] := Enclose[ + Module[ { noOutputs, noBlocks, noLabels }, + + noOutputs = StringDelete[ + StringDelete[ + suggestion, + "```" ~~ Except[ "\n" ]... ~~ WhitespaceCharacter... ~~ $$outLabel ~~ ___ ~~ EndOfString + ], + $$outLabel ~~ ___ ~~ EndOfString + ]; + + noBlocks = StringTrim[ + StringTrim @ StringDelete[ + If[ StringContainsQ[ noOutputs, "```"~~__~~"```" ], + ConfirmBy[ + First @ StringCases[ + noOutputs, + "```" ~~ Except[ "\n" ]... ~~ "\n" ~~ code___ ~~ "```" :> code, + 1 + ], + StringQ, + "NoBlocks" + ], + noOutputs + ], + { + StartOfLine ~~ WhitespaceCharacter... ~~ "```" ~~ Except[ "\n" ]... ~~ EndOfLine, + "```" ~~ WhitespaceCharacter... ~~ EndOfLine + } + ], + Longest[ "```"|"``" ] + ]; + + noLabels = StringTrim @ StringDelete[ noBlocks, $$inLabel ]; + + ConfirmMatch[ + If[ TrueQ @ $stripWhitespace, + Flatten @ BoxData @ StringToBoxes[ noLabels, "WL" ], + Flatten @ BoxData @ simpleStringToBoxes @ noLabels + ], + _BoxData, + "Result" + ] + ], + throwInternalFailure +]; + +postProcessWLSuggestions // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*simpleStringToBoxes*) +simpleStringToBoxes // beginDefinition; + +simpleStringToBoxes[ string_String ] := Enclose[ + ConfirmBy[ usingFrontEnd @ FrontEndExecute @ FrontEnd`ReparseBoxStructurePacket @ string, boxDataQ, "Boxes" ], + throwInternalFailure +]; + +simpleStringToBoxes // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*generateTextSuggestions*) +generateTextSuggestions // beginDefinition; + +generateTextSuggestions[ Dynamic[ container_ ], nbo_, root_CellObject, context0_String, settings_ ] := Enclose[ + Module[ { style, context, instructions, response, suggestions }, + + style = First[ ConfirmMatch[ cellStyles @ root, { ___String }, "Styles" ], "Text" ]; + + context = ConfirmBy[ + StringReplace[ + context0, + Shortest[ $leftSelectionIndicator~~___~~$rightSelectionIndicator ] :> $textPlaceholderString + ], + StringQ, + "Context" + ]; + + If[ TrueQ @ $textSuggestionsMultimodal, + context = ConfirmMatch[ GetExpressionURIs @ context, { (_String|_Image)... }, "MultimodalContext" ] + ]; + + $lastSuggestionContext = context; + + instructions = ConfirmBy[ + TemplateApply[ + $textSuggestionsPrompt, + <| + "Placeholder" -> $textPlaceholderString, + "Style" -> style, + "StyleNotes" -> styleNotes @ style + |> ], + StringQ, + "Instructions" + ]; + + $lastInstructions = instructions; + + response = setServiceCaller @ LogChatTiming @ ServiceExecute[ + $suggestionsService, + "Chat", + { + "Messages" -> { + <| "Role" -> "System", "Content" -> instructions |>, + <| "Role" -> "User" , "Content" -> context |> + }, + "Model" -> $textSuggestionsModel, + "N" -> $textSuggestionsCount, + "MaxTokens" -> $textSuggestionsMaxTokens, + "Temperature" -> $textSuggestionsTemperature, + "StopTokens" -> { "\n\n" } + }, + Authentication -> $suggestionsAuthentication + ]; + + $lastSuggestionsResponse = response; + + suggestions = DeleteDuplicates @ ConfirmMatch[ getTextSuggestions @ response, { __TextData }, "Suggestions" ]; + + $lastSuggestions = suggestions; + + container = formatSuggestions[ Dynamic[ container ], suggestions, nbo, root, context, settings ] + ], + throwInternalFailure +]; + +generateTextSuggestions // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*styleNotes*) +styleNotes // beginDefinition; + +styleNotes[ "CodeText" ] := " +CodeText cells typically contain a short one-line caption ending in a colon (:) that describe the next input."; + +styleNotes[ _ ] := ""; + +styleNotes // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getTextSuggestions*) +getTextSuggestions // beginDefinition; +getTextSuggestions[ content_ ] := postProcessTextSuggestions @ getSuggestions @ content; +getTextSuggestions // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*postProcessTextSuggestions*) +postProcessTextSuggestions // beginDefinition; +postProcessTextSuggestions[ suggestions_List ] := postProcessTextSuggestions /@ suggestions; +postProcessTextSuggestions[ s_String ] := postProcessTextSuggestions[ s, FormatChatOutput @ s ]; +postProcessTextSuggestions[ s_, RawBoxes[ cell_Cell ] ] := postProcessTextSuggestions[ s, ExplodeCell @ cell ]; +postProcessTextSuggestions[ s_, { cell_Cell, ___ } ] := toTextData @ cell; +postProcessTextSuggestions // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*toTextData*) +toTextData // beginDefinition; +toTextData[ Cell[ text_, ___ ] ] := toTextData @ text; +toTextData[ text_TextData ] := text; +toTextData[ text: $$textData ] := TextData @ Flatten @ { text }; +toTextData[ boxes_BoxData ] := TextData @ { Cell[ postProcessWLSuggestions @ CellToString @ boxes, "InlineCode" ] }; +toTextData // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*generateNotebookSuggestions*) +generateNotebookSuggestions // beginDefinition; + +generateNotebookSuggestions[ Dynamic[ container_ ], nbo_, root_NotebookObject, context0_String, settings_ ] := Enclose[ + Module[ { context, preprocessed, relatedDocs, as, instructions, response, suggestions }, + + context = ConfirmBy[ + StringReplace[ + context0, + Shortest[ $leftSelectionIndicator~~___~~$rightSelectionIndicator ] :> $notebookPlaceholderString + ], + StringQ, + "Context" + ]; + + If[ TrueQ @ $notebookSuggestionsMultimodal, + context = ConfirmMatch[ GetExpressionURIs @ context, { (_String|_Image)... }, "MultimodalContext" ] + ]; + + $lastSuggestionContext = context; + + preprocessed = ConfirmBy[ preprocessRelatedDocsContext @ context, StringQ, "Preprocessing" ]; + + relatedDocs = ConfirmBy[ + LogChatTiming @ RelatedDocumentation[ + preprocessed, + "Prompt", + MaxItems -> $wlDocMaxItems, + "FilterResults" -> $wlFilterDocResults, + "FilteredCount" -> $wlFilteredDocCount + ], + StringQ, + "RelatedDocumentation" + ]; + + as = <| + "Context" -> context, + "Placeholder" -> $wlPlaceholderString, + "RelatedDocumentation" -> relatedDocs + |>; + + instructions = StringTrim @ ConfirmBy[ + TemplateApply[ $notebookSuggestionsPrompt, as ], + StringQ, + "Instructions" + ]; + as[ "Instructions" ] = instructions; + + $lastInstructions = instructions; + + response = setServiceCaller @ LogChatTiming @ ServiceExecute[ + $suggestionsService, + "Chat", + { + "Messages" -> { + <| "Role" -> "System", "Content" -> instructions |>, + <| "Role" -> "User" , "Content" -> context |> + }, + "Model" -> $notebookSuggestionsModel, + "N" -> $notebookSuggestionsCount, + "MaxTokens" -> $notebookSuggestionsMaxTokens, + "Temperature" -> $notebookSuggestionsTemperature + }, + Authentication -> $suggestionsAuthentication + ]; + + $lastSuggestionsResponse = response; + + suggestions = DeleteDuplicates @ ConfirmMatch[ getNotebookSuggestions @ response, { __Cell }, "Suggestions" ]; + + $lastSuggestions = suggestions; + + container = formatSuggestions[ Dynamic[ container ], suggestions, nbo, root, context, settings ] + ], + throwInternalFailure +]; + +generateNotebookSuggestions // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getNotebookSuggestions*) +getNotebookSuggestions // beginDefinition; +getNotebookSuggestions[ content_ ] := Flatten @ { postProcessNotebookSuggestions @ getSuggestions @ content }; +getNotebookSuggestions // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*postProcessNotebookSuggestions*) +postProcessNotebookSuggestions // beginDefinition; +postProcessNotebookSuggestions[ suggestions_List ] := postProcessNotebookSuggestions /@ suggestions; +postProcessNotebookSuggestions[ s_String ] := postProcessNotebookSuggestions[ s, FormatChatOutput @ s ]; +postProcessNotebookSuggestions[ s_, RawBoxes[ cell_Cell ] ] := postProcessNotebookSuggestions[ s, ExplodeCell @ cell ]; +postProcessNotebookSuggestions[ s_, cells: { __Cell } ] := Cell @ CellGroupData[ cells, Open ]; +postProcessNotebookSuggestions // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getSuggestions*) +getSuggestions // beginDefinition; +getSuggestions[ KeyValuePattern[ "Content"|"content"|"choices"|"message" -> data_ ] ] := getSuggestions @ data; +getSuggestions[ content_String ] := content; +getSuggestions[ items_List ] := DeleteCases[ getSuggestions /@ items, $$emptySuggestion ]; +getSuggestions // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*formatSuggestions*) +formatSuggestions // beginDefinition; + +formatSuggestions[ + container_, + suggestions: { __ }, + nbo_NotebookObject, + root: $$feObj, + context_, + settings_ +] := Enclose[ + Module[ { styles, formatted }, + styles = If[ MatchQ[ root, _CellObject ], ConfirmMatch[ cellStyles @ root, { ___String }, "Styles" ], None ]; + formatted = ConfirmMatch[ formatSuggestion[ root, nbo, styles ] /@ suggestions, { __Button }, "Formatted" ]; + Pane[ Column[ formatted, Spacings -> 0 ], ImageSize -> { UpTo[ Scaled[ 0.9 ] ], Automatic } ] + ], + throwInternalFailure +]; + +formatSuggestions // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*formatSuggestion*) +formatSuggestion // beginDefinition; + +formatSuggestion[ root: $$feObj, nbo_NotebookObject, styles_ ] := + formatSuggestion[ root, nbo, styles, # ] &; + +formatSuggestion[ root: $$feObj, nbo_NotebookObject, { styles___String }, suggestion_BoxData ] := Button[ + RawBoxes @ Cell[ + suggestion, + styles, + If[ MemberQ[ { styles }, "Input"|"Code" ], + Sequence @@ { + ShowStringCharacters -> True, + ShowAutoStyles -> True, + LanguageCategory -> "Input", + LineBreakWithin -> Automatic, + LineIndent -> 1, + PageWidth :> WindowWidth + }, + Sequence @@ { } + ] + ], + NotebookDelete @ EvaluationCell[ ]; + NotebookWrite[ nbo, suggestion, After ], + Alignment -> Left +]; + +formatSuggestion[ root: $$feObj, nbo_NotebookObject, { styles___String }, suggestion_TextData ] := Button[ + RawBoxes @ Cell[ suggestion, styles, Deployed -> True, Selectable -> False ], + NotebookDelete @ EvaluationCell[ ]; + NotebookWrite[ nbo, suggestion, After ], + Alignment -> Left +]; + +formatSuggestion[ root: $$feObj, nbo_NotebookObject, None, suggestion: Cell[ _CellGroupData ] ] := Button[ + Column[ formatSuggestionCells /@ cellFlatten @ suggestion ], + NotebookDelete @ EvaluationCell[ ]; + NotebookWrite[ nbo, suggestion, After ], + Alignment -> Left +]; + +formatSuggestion // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*formatSuggestionCells*) +formatSuggestionCells // beginDefinition; + +formatSuggestionCells[ cell: Cell[ _CellGroupData, ___ ] ] := + formatSuggestionCells @ cellFlatten @ cell; + +formatSuggestionCells[ cells: { __Cell } ] := + formatSuggestionCells /@ cells; + +formatSuggestionCells[ Cell[ a__, CellLabel -> label_, b___ ] ] := Grid[ + { { + Pane[ + RawBoxes @ Cell[ label, "CellLabelExpired", FontSize -> 9, FontSlant -> Plain ], + Alignment -> Right, + ImageSize -> { 50, Automatic } + ], + formatSuggestionCells @ Cell[ a, b ] + } }, + Alignment -> { { Right, Left }, Top } +]; + +formatSuggestionCells[ Cell[ a__, style: "Code"|"Input", b___ ] ] := + RawBoxes @ Cell[ + a, + style, + b, + Deployed -> True, + Selectable -> False, + ShowStringCharacters -> True, + ShowAutoStyles -> True, + LanguageCategory -> "Input", + LineBreakWithin -> Automatic, + LineIndent -> 1, + PageWidth :> WindowWidth + ]; + +formatSuggestionCells[ Cell[ a__ ] ] := + RawBoxes @ Cell[ a, Deployed -> True, Selectable -> False ]; + +formatSuggestionCells // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/ChatModes/Context.wl b/Source/Chatbook/ChatModes/Context.wl index 6834a1ee..80193381 100644 --- a/Source/Chatbook/ChatModes/Context.wl +++ b/Source/Chatbook/ChatModes/Context.wl @@ -6,15 +6,14 @@ Begin[ "`Private`" ]; Needs[ "Wolfram`Chatbook`" ]; Needs[ "Wolfram`Chatbook`Common`" ]; Needs[ "Wolfram`Chatbook`ChatModes`Common`" ]; -Needs[ "Wolfram`Chatbook`Serialization`" ]; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Configuration*) -$maxCellsBeforeSelection = 100; -$maxCellsAfterSelection = 10; - -$currentSelectionIndicator = { $leftSelectionIndicator, $rightSelectionIndicator }; +$maxCellsBeforeSelection = 100; +$maxCellsAfterSelection = 20; +$notebookInstructionsPrompt = True; +$currentSelectionIndicator = { $leftSelectionIndicator, $rightSelectionIndicator }; $notebookContextTemplate = StringTemplate[ "\ IMPORTANT: Below is some context from the user's currently selected notebook. \ @@ -34,7 +33,7 @@ getInlineChatPrompt // beginDefinition; getInlineChatPrompt[ settings_ ] := If[ TrueQ @ $InlineChat, - getInlineChatPrompt0[ settings, $inlineChatState ], + getInlineChatPrompt0[ settings, $inlineChatState ] // LogChatTiming[ "GetInlineChatPrompt" ], None ]; @@ -60,7 +59,7 @@ getInlineChatPrompt0[ cell_CellObject, { before___CellObject, cell_, after___CellObject } ] := - Block[ { $selectionInfo = info }, + Block[ { $selectionInfo = info, $includeCellXML = TrueQ @ $notebookEditorEnabled }, getContextFromSelection0[ <| "Before" -> { before }, @@ -80,7 +79,9 @@ getWorkspacePrompt // beginDefinition; getWorkspacePrompt[ settings_Association ] := If[ TrueQ @ $WorkspaceChat, - getContextFromSelection[ $evaluationNotebook, settings ], + Block[ { $includeCellXML = TrueQ @ $notebookEditorEnabled }, + getContextFromSelection[ $evaluationNotebook, settings ] + ] // LogChatTiming[ "GetWorkspacePrompt" ], None ]; @@ -90,17 +91,37 @@ getWorkspacePrompt // endDefinition; (* ::Subsection::Closed:: *) (*getContextFromSelection*) getContextFromSelection // beginDefinition; +getContextFromSelection // Options = { + "NotebookInstructionsPrompt" -> True, + "MaxCellsBeforeSelection" :> $maxCellsBeforeSelection, + "MaxCellsAfterSelection" :> $maxCellsAfterSelection +}; -getContextFromSelection[ chatNB_NotebookObject, settings_Association ] := - getContextFromSelection[ chatNB, getUserNotebook @ chatNB, settings ]; +getContextFromSelection[ chatNB_NotebookObject, settings_Association, opts: OptionsPattern[ ] ] := + getContextFromSelection[ chatNB, getUserNotebook @ chatNB, settings, opts ]; -getContextFromSelection[ chatNB_NotebookObject, None, settings_Association ] := +getContextFromSelection[ chatNB_NotebookObject, None, settings_Association, opts: OptionsPattern[ ] ] := None; -getContextFromSelection[ chatNB_, nbo_NotebookObject, settings_Association ] := Enclose[ - Module[ { selectionData }, - selectionData = ConfirmBy[ selectContextCells @ nbo, AssociationQ, "SelectionData" ]; - ConfirmBy[ getContextFromSelection0[ selectionData, settings ], StringQ, "Context" ] +getContextFromSelection[ chatNB_, nbo_NotebookObject, settings_Association, opts: OptionsPattern[ ] ] := Enclose[ + Catch @ Block[ + { + $notebookInstructionsPrompt = OptionValue[ "NotebookInstructionsPrompt" ], + $maxCellsBeforeSelection = OptionValue[ "MaxCellsBeforeSelection" ], + $maxCellsAfterSelection = OptionValue[ "MaxCellsAfterSelection" ] + }, + Module[ { selectionData }, + + selectionData = ConfirmMatch[ + LogChatTiming @ selectContextCells @ nbo, + _Association|None, + "SelectionData" + ]; + + If[ selectionData === None, Throw @ None ]; + + ConfirmBy[ getContextFromSelection0[ selectionData, settings ], StringQ, "Context" ] + ] ], throwInternalFailure ]; @@ -117,10 +138,11 @@ getContextFromSelection0[ selectionData: KeyValuePattern[ "Selected" -> { cell_C ]; getContextFromSelection0[ selectionData_Association, settings_ ] := Enclose[ - Catch @ Module[ { cellObjects, cells, len1, len2, before, selected, after, marked, messages, string }, + Catch @ Module[ + { cellObjects, cells, len1, len2, before, selected, after, marked, messages, string, nbCtx }, cellObjects = ConfirmMatch[ Flatten @ Values @ selectionData, { ___CellObject }, "CellObjects" ]; - cells = ConfirmMatch[ notebookRead @ cellObjects, { ___Cell }, "Cells" ]; + cells = ConfirmMatch[ LogChatTiming @ notebookRead @ cellObjects, { ___Cell }, "Cells" ]; len1 = Length @ ConfirmMatch[ selectionData[ "Before" ], { ___CellObject }, "BeforeLength" ]; len2 = Length @ ConfirmMatch[ selectionData[ "Selected" ], { ___CellObject }, "SelectedLength" ]; @@ -130,9 +152,19 @@ getContextFromSelection0[ selectionData_Association, settings_ ] := Enclose[ after = ConfirmMatch[ cells[[ len1 + len2 + 1 ;; All ]] , { ___Cell }, "AfterCells" ]; marked = ConfirmMatch[ insertSelectionIndicator @ { before, selected, after }, { ___Cell }, "Marked" ]; - messages = ConfirmMatch[ makeChatMessages[ settings, marked, False ], { ___Association }, "Messages" ]; - string = ConfirmBy[ messagesToString @ messages, StringQ, "String" ]; - postProcessNotebookContextString[ applyNotebookContextTemplate @ string, string ] + messages = ConfirmMatch[ LogChatTiming @ makeChatMessages[ settings, marked, False ], { ___Association }, "Messages" ]; + string = ConfirmBy[ messagesToString[ messages, "MessageTemplate" -> None ], StringQ, "String" ]; + + $contextPrompt = processContextPromptString @ string; + $selectionPrompt = extractSelectionPrompt @ string; + + $lastContextPrompt = $contextPrompt; + $lastSelectionPrompt = $selectionPrompt; + + nbCtx = ConfirmBy[ applyNotebookContextTemplate @ string, StringQ, "NotebookContext" ]; + + (* FIXME: pass $selectionPrompt instead of extracting again: *) + postProcessNotebookContextString[ nbCtx, string ] ], throwInternalFailure ]; @@ -141,27 +173,59 @@ getContextFromSelection0 // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) -(*messagesToString*) -messagesToString // beginDefinition; -messagesToString[ messages_List ] := messagesToString[ messages, messageToString /@ revertMultimodalContent @ messages ]; -messagesToString[ _, strings: { ___String } ] := StringRiffle[ strings, "\n\n" ]; -messagesToString // endDefinition; +(*extractSelectionPrompt*) +extractSelectionPrompt // beginDefinition; + +extractSelectionPrompt[ prompt_String ] := Enclose[ + Catch @ Module[ { selections, selected }, + selections = StringCases[ prompt, $leftSelectionIndicator ~~ s___ ~~ $rightSelectionIndicator :> s, 1 ]; + If[ selections === { }, Throw @ None ]; + selected = StringTrim @ ConfirmBy[ First @ selections, StringQ, "Selected" ]; + If[ selected === "", Throw @ None, selected ] + ], + throwInternalFailure +]; + +extractSelectionPrompt // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) -(*messageToString*) -messageToString // beginDefinition; -messageToString[ KeyValuePattern[ "Content" -> content_ ] ] := messageToString @ content; -messageToString[ KeyValuePattern[ "Data" -> content_ ] ] := messageToString @ content; -messageToString[ { message___String } ] := StringJoin @ message; -messageToString[ message_String ] := message; -messageToString // endDefinition; +(*processContextPromptString*) +processContextPromptString // beginDefinition; + +processContextPromptString[ prompt_String ] := Enclose[ + Module[ { noXML, noSelection }, + noXML = ConfirmBy[ stripCellXML @ prompt, StringQ, "NoXML" ]; + noSelection = ConfirmBy[ (*stripSelectionIndicators @*) noXML, StringQ, "NoSelection" ]; + ConfirmBy[ mergeCodeBlocks @ noSelection, StringQ, "Merged" ] + ], + throwInternalFailure +]; + +processContextPromptString // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*stripCellXML*) +stripCellXML // beginDefinition; +stripCellXML[ prompt_String ] := StringDelete[ prompt, { "\n", "\n" } ]; +stripCellXML // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*stripSelectionIndicators*) +stripSelectionIndicators // beginDefinition; +stripSelectionIndicators[ s_String ] := StringDelete[ s, { $leftSelectionIndicator, $rightSelectionIndicator } ]; +stripSelectionIndicators // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*postProcessNotebookContextString*) postProcessNotebookContextString // beginDefinition; +postProcessNotebookContextString[ prompt_String, string_String ] /; ! $notebookInstructionsPrompt := + prompt; + postProcessNotebookContextString[ prompt_String, string_String ] := Module[ { selected, selectedString }, selected = StringCases[ string, $leftSelectionIndicator ~~ s__ ~~ $rightSelectionIndicator :> s, 1 ]; @@ -184,6 +248,9 @@ postProcessNotebookContextString // endDefinition; (*applyNotebookContextTemplate*) applyNotebookContextTemplate // beginDefinition; +applyNotebookContextTemplate[ string_String ] /; ! $notebookInstructionsPrompt := + string; + applyNotebookContextTemplate[ string_String ] := applyNotebookContextTemplate[ string, $currentSelectionIndicator ]; @@ -244,7 +311,10 @@ selectContextCells // beginDefinition; selectContextCells[ nbo_NotebookObject ] := selectContextCells @ Cells @ nbo; -selectContextCells[ cells: { ___CellObject } ] := +selectContextCells[ { } ] := + None; + +selectContextCells[ cells: { __CellObject } ] := selectContextCells @ cellInformation @ cells; selectContextCells[ { a: KeyValuePattern[ "CursorPosition" -> "AboveCell" ], after___ } ] := diff --git a/Source/Chatbook/ChatModes/Evaluate.wl b/Source/Chatbook/ChatModes/Evaluate.wl index 6e773820..a40fbcd2 100644 --- a/Source/Chatbook/ChatModes/Evaluate.wl +++ b/Source/Chatbook/ChatModes/Evaluate.wl @@ -28,10 +28,20 @@ evaluateWorkspaceChat // beginDefinition; evaluateWorkspaceChat[ nbo_NotebookObject, Dynamic[ input: _Symbol|_CurrentValue ] ] := Enclose[ Catch @ Module[ { text, uuid, cell, cellObject }, + If[ ! validInputStringQ @ input, input = ""; Throw @ Null ]; text = input; uuid = ConfirmBy[ CreateUUID[ ], StringQ, "UUID" ]; - cell = Cell[ BoxData @ TemplateBox[ { text }, "UserMessageBox" ], "ChatInput", CellTags -> uuid ]; + + cell = Cell[ + BoxData @ TemplateBox[ + { Cell[ text, Background -> None, Selectable -> True, Editable -> True ] }, + "UserMessageBox" + ], + "ChatInput", + CellTags -> uuid + ]; + input = ""; SelectionMove[ nbo, After, Notebook, AutoScroll -> True ]; NotebookWrite[ nbo, cell ]; @@ -76,7 +86,11 @@ evaluateInlineChat[ "InlineChatCell" -> cell, "SelectionInfo" -> selectionInfo, "MessageCells" -> Dynamic @ messageCells - |> + |>, + $defaultChatSettings = mergeChatSettings @ { + $defaultChatSettings, + CurrentValue[ cell, { TaggingRules, "ChatNotebookSettings" } ] + } }, result = ConfirmMatch[ ChatCellEvaluate @ root, _ChatObject|Null, "ChatCellEvaluate" ] ]; diff --git a/Source/Chatbook/ChatModes/ShowCodeAssistance.wl b/Source/Chatbook/ChatModes/ShowCodeAssistance.wl index 19efe860..f6a70b12 100644 --- a/Source/Chatbook/ChatModes/ShowCodeAssistance.wl +++ b/Source/Chatbook/ChatModes/ShowCodeAssistance.wl @@ -12,16 +12,42 @@ Needs[ "Wolfram`Chatbook`ChatModes`Common`" ]; (*Configuration*) $workspaceChatWidth = 325; -$workspaceChatNotebookOptions = Sequence[ +$codeAssistanceBaseSettings = <| + "AppName" -> "CodeAssistance", + "Authentication" -> Automatic, (* TODO *) + "Model" -> <| "Service" -> "OpenAI", "Name" -> "gpt-4o" |>, + "PromptGenerators" -> { "RelatedDocumentation" }, + "ServiceCaller" -> "CodeAssistance", + "ToolOptions" -> <| "WolframLanguageEvaluator" -> <| "AppendURIPrompt" -> True, "Method" -> "Session" |> |>, + "Tools" -> { "NotebookEditor" }, + "ToolSelectionType" -> <| "DocumentationLookup" -> None, "DocumentationSearcher" -> None |> +|>; + +$codeAssistanceWorkspaceSettings := <| + $codeAssistanceBaseSettings, + "AutoGenerateTitle" -> True, + "ConversationUUID" -> CreateUUID[ ] +|>; + +$codeAssistanceInlineSettings := <| + $codeAssistanceBaseSettings, + "AutoGenerateTitle" -> False, + "AutoSaveConversations" -> False +|>; + +$workspaceChatNotebookOptions := Sequence[ DefaultNewCellStyle -> "AutoMoveToChatInputField", - StyleDefinitions -> FrontEnd`FileName[ { "Wolfram" }, "WorkspaceChat.nb", CharacterEncoding -> "UTF-8" ] + StyleDefinitions -> FrontEnd`FileName[ { "Wolfram" }, "WorkspaceChat.nb", CharacterEncoding -> "UTF-8" ], + TaggingRules -> <| "ChatNotebookSettings" -> $codeAssistanceWorkspaceSettings |> ]; +(* TODO: set $serviceCaller from chat settings *) + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*EnableCodeAssistance*) EnableCodeAssistance // beginDefinition; -EnableCodeAssistance[ ] := catchMine @ Once[ enableCodeAssistance[ ]; Null, "FrontEndSession" ]; +EnableCodeAssistance[ ] := catchMine @ (enableCodeAssistance[ ]; Null); EnableCodeAssistance // endExportedDefinition; (* ::**************************************************************************************************************:: *) @@ -29,36 +55,88 @@ EnableCodeAssistance // endExportedDefinition; (*enableCodeAssistance*) enableCodeAssistance // beginDefinition; -enableCodeAssistance[ ] := FrontEndExecute @ { - FrontEnd`AddMenuCommands[ - "OpenHelpLink", - { - MenuItem[ - "Code Assistance Chat\[Ellipsis]", - FrontEnd`KernelExecute[ - Needs[ "Wolfram`Chatbook`" -> None ]; - Symbol[ "Wolfram`Chatbook`ShowCodeAssistance" ][ "Window" ] +enableCodeAssistance[ ] := + enableCodeAssistance[ $VersionNumber >= 14.1 ]; + +enableCodeAssistance[ True ] := Once[ + FrontEndExecute @ { + FrontEnd`AddMenuCommands[ + "OpenHelpLink", + { + MenuItem[ + "Code Assistance Chat\[Ellipsis]", + FrontEnd`KernelExecute[ + Needs[ "Wolfram`Chatbook`" -> None ]; + Symbol[ "Wolfram`Chatbook`ShowCodeAssistance" ][ "Window" ] + ], + FrontEnd`MenuEvaluator -> Automatic, + Evaluate[ + If[ $OperatingSystem === "MacOSX", + FrontEnd`MenuKey[ "'", FrontEnd`Modifiers -> { FrontEnd`Control } ], + FrontEnd`MenuKey[ "'", FrontEnd`Modifiers -> { FrontEnd`Command } ] + ] + ] ], - FrontEnd`MenuEvaluator -> Automatic, - Evaluate[ - If[ $OperatingSystem === "MacOSX", - FrontEnd`MenuKey[ "'", FrontEnd`Modifiers -> { FrontEnd`Control } ], - FrontEnd`MenuKey[ "'", FrontEnd`Modifiers -> { FrontEnd`Command } ] + MenuItem[ + "Code Assistance for Selection", + FrontEnd`KernelExecute[ + Needs[ "Wolfram`Chatbook`" -> None ]; + Symbol[ "Wolfram`Chatbook`ShowCodeAssistance" ][ "Inline" ] + ], + FrontEnd`MenuEvaluator -> Automatic, + FrontEnd`MenuKey[ "'", FrontEnd`Modifiers -> { FrontEnd`Control, FrontEnd`Shift } ] + ] + } + ], + FrontEnd`AddMenuCommands[ + "DuplicatePreviousOutput", + { + MenuItem[ + "AI Content Suggestion", + FrontEnd`KernelExecute[ + Needs[ "Wolfram`Chatbook`" -> None ]; + Symbol[ "Wolfram`Chatbook`ShowContentSuggestions" ][ ] + ], + FrontEnd`MenuEvaluator -> Automatic, + Evaluate[ + If[ $OperatingSystem === "MacOSX", + FrontEnd`MenuKey[ "k", FrontEnd`Modifiers -> { FrontEnd`Control } ], + FrontEnd`MenuKey[ "k", FrontEnd`Modifiers -> { FrontEnd`Command } ] + ] + ], + Method -> "Queued" + ] + } + ] + }, + "FrontEndSession" +]; + +(* When attachment to selection is not available, we can't do inline chat or content suggestions: *) +enableCodeAssistance[ False ] := Once[ + FrontEndExecute @ { + FrontEnd`AddMenuCommands[ + "OpenHelpLink", + { + MenuItem[ + "Code Assistance Chat\[Ellipsis]", + FrontEnd`KernelExecute[ + Needs[ "Wolfram`Chatbook`" -> None ]; + Symbol[ "Wolfram`Chatbook`ShowCodeAssistance" ][ "Window" ] + ], + FrontEnd`MenuEvaluator -> Automatic, + Evaluate[ + If[ $OperatingSystem === "MacOSX", + FrontEnd`MenuKey[ "'", FrontEnd`Modifiers -> { FrontEnd`Control } ], + FrontEnd`MenuKey[ "'", FrontEnd`Modifiers -> { FrontEnd`Command } ] + ] ] ] - ], - MenuItem[ - "Code Assistance for Selection", - FrontEnd`KernelExecute[ - Needs[ "Wolfram`Chatbook`" -> None ]; - Symbol[ "Wolfram`Chatbook`ShowCodeAssistance" ][ "Inline" ] - ], - FrontEnd`MenuEvaluator -> Automatic, - FrontEnd`MenuKey[ "'", FrontEnd`Modifiers -> { FrontEnd`Control, FrontEnd`Shift } ] - ] - } - ] -}; + } + ] + }, + "FrontEndSession" +]; enableCodeAssistance // endDefinition; @@ -67,8 +145,11 @@ enableCodeAssistance // endDefinition; (*ShowCodeAssistance*) ShowCodeAssistance // beginDefinition; ShowCodeAssistance[ ] := catchMine @ ShowCodeAssistance[ "Window" ]; -ShowCodeAssistance[ "Window" ] := catchMine @ showCodeAssistanceWindow @ getUserNotebook[ ]; -ShowCodeAssistance[ "Inline" ] := catchMine @ showCodeAssistanceInline @ InputNotebook[ ]; +ShowCodeAssistance[ nbo_NotebookObject ] := catchMine @ showCodeAssistanceWindow @ nbo; +ShowCodeAssistance[ "Window" ] := catchMine @ ShowCodeAssistance[ getUserNotebook[ ], "Window" ]; +ShowCodeAssistance[ "Inline" ] := catchMine @ ShowCodeAssistance[ InputNotebook[ ], "Inline" ]; +ShowCodeAssistance[ nbo_NotebookObject, "Window" ] := catchMine @ showCodeAssistanceWindow @ nbo; +ShowCodeAssistance[ nbo_NotebookObject, "Inline" ] := catchMine @ showCodeAssistanceInline @ nbo; ShowCodeAssistance // endExportedDefinition; (* ::**************************************************************************************************************:: *) @@ -79,7 +160,7 @@ ShowCodeAssistance // endExportedDefinition; (* ::Subsection::Closed:: *) (*showCodeAssistanceInline*) showCodeAssistanceInline // beginDefinition; -showCodeAssistanceInline[ nbo_NotebookObject ] := attachInlineChatInput @ nbo; +showCodeAssistanceInline[ nbo_NotebookObject ] := attachInlineChatInput[ nbo, $codeAssistanceInlineSettings ]; showCodeAssistanceInline[ _ ] := MessageDialog[ "No notebook selected." ]; showCodeAssistanceInline // endDefinition; @@ -142,7 +223,10 @@ attachToLeft[ source_NotebookObject, current_NotebookObject ] := Enclose[ WindowSize -> { $workspaceChatWidth, Automatic } ]; - SetSelectedNotebook @ current + SetSelectedNotebook @ current; + moveToChatInputField[ current, True ]; + + current ], throwInternalFailure ]; @@ -175,8 +259,8 @@ findCurrentWorkspaceChat // endDefinition; (* ::Section::Closed:: *) (*CreateWorkspaceChat*) CreateWorkspaceChat // beginDefinition; -CreateWorkspaceChat[ ] := catchMine @ createWorkspaceChat[ ]; -CreateWorkspaceChat[ nbo_NotebookObject ] := catchMine @ createWorkspaceChat @ nbo; +CreateWorkspaceChat[ ] := catchMine @ LogChatTiming @ createWorkspaceChat[ ]; +CreateWorkspaceChat[ nbo_NotebookObject ] := catchMine @ LogChatTiming @ createWorkspaceChat @ nbo; CreateWorkspaceChat // endExportedDefinition; (* ::**************************************************************************************************************:: *) diff --git a/Source/Chatbook/ChatModes/UI.wl b/Source/Chatbook/ChatModes/UI.wl index d65fec21..01dabfd9 100644 --- a/Source/Chatbook/ChatModes/UI.wl +++ b/Source/Chatbook/ChatModes/UI.wl @@ -13,7 +13,7 @@ Needs[ "Wolfram`Chatbook`ChatModes`Common`" ]; $inputFieldPaneMargins = 5; $inputFieldGridMagnification = 0.8; $inputFieldOuterBackground = GrayLevel[ 0.95 ]; -$initialInlineChatWidth = Scaled[ 0.5 ]; +$initialInlineChatWidth = Scaled[ 1 ]; $initialInlineChatHeight = UpTo[ 200 ]; $inputFieldOptions = Sequence[ @@ -30,7 +30,7 @@ $inputFieldFrameOptions = Sequence[ FrameStyle -> Directive[ AbsoluteThickness[ 2 ], RGBColor[ "#a3c9f2" ] ] ]; -$userImageParams = <| "size" -> 50, "default" -> "identicon", "rating" -> "G" |>; +$userImageParams = <| "size" -> 40, "default" -> "404", "rating" -> "G" |>; $defaultUserImage = Graphics[ { @@ -41,7 +41,7 @@ $defaultUserImage = Graphics[ Disk[ { 0, 1 }, 1 ], Disk[ { 0, -1.8 }, { 1.65, 2 } ] }, - ImageSize -> 25, + ImageSize -> 20, PlotRange -> { { -2.4, 2.4 }, { -2.0, 2.8 } } ]; @@ -51,6 +51,8 @@ $inputFieldBox = None; $inlineChatScrollPosition = 0.0; $lastScrollPosition = 0.0; +$maxHistoryItems = 25; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Workspace Chat*) @@ -60,18 +62,41 @@ $lastScrollPosition = 0.0; (*makeWorkspaceChatDockedCell*) makeWorkspaceChatDockedCell // beginDefinition; -makeWorkspaceChatDockedCell[ ] := Grid @ { - { - Button[ - "New", - SelectionMove[ EvaluationNotebook[ ], After, Notebook ]; - NotebookWrite[ EvaluationNotebook[ ], Cell[ "", "ChatDelimiter", CellFrameLabels -> None ] ] - ], - Button[ "Clear", NotebookDelete @ Cells @ EvaluationNotebook[ ] ], - Item[ "", ItemSize -> Fit ], - Button[ "Pop Out", popOutChatNB @ EvaluationNotebook[ ], Method -> "Queued" ] - } -}; +makeWorkspaceChatDockedCell[ ] := + DynamicModule[ { nbo }, + Grid @ { + { + Tooltip[ + Button[ + "New Chat", + NotebookDelete @ Cells @ nbo; + CurrentChatSettings[ nbo, "ConversationUUID" ] = CreateUUID[ ] + ], + "Start a new conversation" + ], + trackedDynamic[ createHistoryMenu @ nbo, "SavedChats" ], + Tooltip[ + Button[ + "Delete", + DeleteChat[ + CurrentChatSettings[ nbo, "AppName" ], + CurrentChatSettings[ nbo, "ConversationUUID" ] + ]; + NotebookDelete @ Cells @ nbo; + CurrentChatSettings[ nbo, "ConversationUUID" ] = CreateUUID[ ] + ], + "Remove the current chat from the history menu" + ] + , + Item[ "", ItemSize -> Fit ], + Tooltip[ + Button[ "Pop Out", popOutChatNB @ nbo, Method -> "Queued" ], + "View the chat as a normal chat notebook" + ] + } + }, + Initialization :> (nbo = EvaluationNotebook[ ]) + ]; makeWorkspaceChatDockedCell // endDefinition; @@ -156,12 +181,15 @@ $attachedWorkspaceChatInputCell := $attachedWorkspaceChatInputCell = Cell[ attachInlineChatInput // beginDefinition; attachInlineChatInput[ nbo_NotebookObject ] := + attachInlineChatInput[ nbo, <| |> ]; + +attachInlineChatInput[ nbo_NotebookObject, settings_Association ] := If[ TrueQ @ userNotebookQ @ nbo, - attachInlineChatInput[ nbo, SelectedCells @ nbo ], + attachInlineChatInput[ nbo, settings, SelectedCells @ nbo ], Null ]; -attachInlineChatInput[ nbo_NotebookObject, { root_CellObject } ] := Enclose[ +attachInlineChatInput[ nbo_NotebookObject, settings_Association, { root_CellObject } ] := Enclose[ Module[ { selectionInfo, attached }, NotebookDelete @ $lastAttachedInlineChat; @@ -180,10 +208,10 @@ attachInlineChatInput[ nbo_NotebookObject, { root_CellObject } ] := Enclose[ attached = ConfirmMatch[ AttachCell[ NotebookSelection @ nbo, - inlineChatInputCell[ root, selectionInfo ], - { Left, Bottom }, + inlineChatInputCell[ root, selectionInfo, settings ], + { "WindowCenter", Bottom }, 0, - { Left, Top }, + { Center, Top }, RemovalConditions -> { "EvaluatorQuit" } ], _CellObject, @@ -198,8 +226,21 @@ attachInlineChatInput[ nbo_NotebookObject, { root_CellObject } ] := Enclose[ throwInternalFailure ]; -(* FIXME: Need to handle multiple or no cell selections *) -attachInlineChatInput[ nbo_NotebookObject, { ___ } ] := Null; +(* TODO: moving the selection probably isn't ideal: *) +attachInlineChatInput[ nbo_NotebookObject, settings_, { } ] := Enclose[ + Module[ { root }, + SelectionMove[ nbo, Previous, Cell ]; + root = Replace[ SelectedCells @ nbo, { cell_CellObject } :> cell ]; + If[ MatchQ[ root, _CellObject ], + attachInlineChatInput[ nbo, settings, { root } ], + Null + ] + ], + throwInternalFailure +]; + +(* FIXME: Need to handle multiple cell selections *) +attachInlineChatInput[ nbo_NotebookObject, settings_, { ___ } ] := Null; attachInlineChatInput // endDefinition; @@ -208,14 +249,23 @@ attachInlineChatInput // endDefinition; (*getSelectionInfo*) getSelectionInfo // beginDefinition; -getSelectionInfo[ cell_CellObject ] := getSelectionInfo[ cell, cellInformation[ cell, "CursorPosition" ] ]; -getSelectionInfo[ cell_, Except[ { _Integer, _Integer } ] ] := None; -getSelectionInfo[ cell_, pos_ ] := getSelectionInfo[ cell, pos, cellHash @ cell ]; +getSelectionInfo[ cell_CellObject ] := + getSelectionInfo[ cell, cellInformation[ cell, { "ContentData", "CursorPosition" } ] ]; -getSelectionInfo[ cell_CellObject, pos: { _Integer, _Integer }, hash_String ] := <| - "CellObject" -> cell, - "CursorPosition" -> pos, - "Hash" -> hash +getSelectionInfo[ cell_, KeyValuePattern[ "CursorPosition" -> Except[ { _Integer, _Integer } ] ] ] := + None; + +getSelectionInfo[ cell_, info_ ] := + getSelectionInfo[ cell, info, cellHash @ cell ]; + +getSelectionInfo[ + cell_CellObject, + as: KeyValuePattern[ "CursorPosition" -> { _Integer, _Integer } ], + hash_String +] := <| + as, + "CellObject" -> cell, + "Hash" -> hash |>; getSelectionInfo // endDefinition; @@ -233,7 +283,7 @@ cellHash // endDefinition; (*inlineChatInputCell*) inlineChatInputCell // beginDefinition; -inlineChatInputCell[ root_CellObject, selectionInfo_ ] := Cell[ +inlineChatInputCell[ root_CellObject, selectionInfo_, settings_ ] := Cell[ BoxData @ inlineTemplateBox @ TemplateBox[ { ToBoxes @ DynamicModule[ { messageCells = { }, cell }, @@ -255,12 +305,14 @@ inlineChatInputCell[ root_CellObject, selectionInfo_ ] := Cell[ cell = EvaluationCell[ ]; parentCell[ cell ] = root; parentNotebook[ cell ] = parentNotebook @ root; + attachInlineChatButtons[ EvaluationCell[ ], Dynamic @ messageCells ] ), Deinitialization :> Quiet[ $inputFieldBox = None; Unset @ parentCell @ cell; Unset @ parentNotebook @ cell; + ClearAll @ evaluateCurrentInlineChat; ] ] }, @@ -268,11 +320,116 @@ inlineChatInputCell[ root_CellObject, selectionInfo_ ] := Cell[ ], "AttachedChatInput", Background -> None, - Selectable -> True + Selectable -> True, + TaggingRules -> <| "ChatNotebookSettings" -> settings |> ]; inlineChatInputCell // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*attachInlineChatButtons*) +attachInlineChatButtons // beginDefinition; + +attachInlineChatButtons[ cell_CellObject, messageCells_Dynamic ] := AttachCell[ + cell, + inlineChatButtonsCell[ cell, messageCells ], + { Right, Top }, + Offset[ { -57, -7 }, 0 ], + { Left, Top } +]; + +attachInlineChatButtons // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*inlineChatButtonsCell*) +inlineChatButtonsCell // beginDefinition; + +(* TODO: define a template box for this in the stylesheet *) +inlineChatButtonsCell[ cell_CellObject, messageCells_Dynamic ] := + Cell @ BoxData @ GridBox[ + { { closeButton @ cell }, { popOutButton[ cell, messageCells ] } }, + AutoDelete -> False, + GridBoxItemSize -> { "Columns" -> { { 0 } }, "Rows" -> { { 0 } } }, + GridBoxSpacings -> { "Columns" -> { { 0 } }, "Rows" -> { { 0 } } } + ]; + +inlineChatButtonsCell // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*closeButton*) +closeButton // beginDefinition; + +closeButton[ cell_CellObject ] := ToBoxes @ Button[ + RawBoxes @ FrameBox[ + GraphicsBox[ + { + GrayLevel[ 0.3 ], + AbsoluteThickness[ 1 ], + CapForm[ "Round" ], + LineBox @ { { { -1, -1 }, { 1, 1 } }, { { 1, -1 }, { -1, 1 } } } + }, + ImagePadding -> { { 0, 1 }, { 1, 0 } }, + ImageSize -> { 6, 6 }, + PlotRange -> 1 + ], + Alignment -> { Center, Center }, + Background -> GrayLevel[ 0.96 ], + ContentPadding -> False, + FrameMargins -> None, + FrameStyle -> GrayLevel[ 0.85 ], + ImageSize -> { 16, 16 }, + RoundingRadius -> 2, + StripOnInput -> False + ], + NotebookDelete @ cell, + Appearance -> "Suppressed", + Tooltip -> "Close" +]; + +closeButton // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*popOutButton*) +popOutButton // beginDefinition; + +popOutButton[ cell_CellObject, messageCells_Dynamic ] := ToBoxes @ Button[ + RawBoxes @ FrameBox[ + GraphicsBox[ + { + GrayLevel[ 0.3 ], + AbsoluteThickness[ 1 ], + CapForm[ "Round" ], + LineBox @ { + { { -0.4, 0.8 }, { -0.8, 0.8 }, { -0.8, -0.8 }, { 0.8, -0.8 }, { 0.8, -0.4 } }, + { { -0.1, -0.1 }, { 1, 1 } }, + { { 0.2, 1 }, { 1, 1 }, { 1, 0.2 } } + } + }, + ImagePadding -> { { 0, 1 }, { 1, 0 } }, + ImageSize -> { 10, 10 }, + PlotRange -> 1 + ], + Alignment -> { Center, Center }, + Background -> GrayLevel[ 0.96 ], + ContentPadding -> False, + FrameMargins -> None, + FrameStyle -> GrayLevel[ 0.85 ], + ImageSize -> { 16, 16 }, + RoundingRadius -> 2, + StripOnInput -> False + ], + NotebookDelete @ cell; + popOutWorkspaceChatNB @ messageCells, + Appearance -> "Suppressed", + Tooltip -> "View in Code Assistance Chat" +]; + +popOutButton // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*displayInlineChat*) @@ -305,7 +462,15 @@ inlineChatInputField[ selectionInfo_, Dynamic[ currentInput_ ], Dynamic[ messageCells_ ] -] := +] := ( + evaluateCurrentInlineChat[ ] := ChatbookAction[ + "EvaluateInlineChat", + cell, + root, + selectionInfo, + Dynamic @ currentInput, + Dynamic @ messageCells + ]; EventHandler[ Pane[ Grid[ @@ -323,20 +488,6 @@ inlineChatInputField[ RawBoxes @ inlineTemplateBox @ TemplateBox[ { RGBColor[ "#a3c9f2" ], RGBColor[ "#f1f7fd" ], 27 }, "SendChatButton" - ], - Style[ - ActionMenu[ - "More", - { - "Close" :> NotebookDelete @ EvaluationCell[ ], - "View in Chat" :> ( - NotebookDelete @ EvaluationCell[ ]; - popOutWorkspaceChatNB @ messageCells - ) - }, - ImageSize -> { Automatic, 25 } - ], - Magnification -> 1 ] } }, @@ -358,7 +509,8 @@ inlineChatInputField[ ) }, Method -> "Queued" - ]; + ] +); inlineChatInputField // endDefinition; @@ -376,6 +528,8 @@ moveToInlineChatInputField[ box_BoxObject ] := Quiet @ Catch[ _ ]; +moveToInlineChatInputField[ None ] := Null; + moveToInlineChatInputField // endDefinition; (* ::**************************************************************************************************************:: *) @@ -384,7 +538,7 @@ moveToInlineChatInputField // endDefinition; displayInlineChatMessages // beginDefinition; displayInlineChatMessages[ { }, inputField_ ] := - Pane[ inputField, ImageSize -> { Scaled[ 0.5 ], Automatic } ]; + Pane[ inputField, ImageSize -> { $initialInlineChatWidth, Automatic } ]; displayInlineChatMessages[ cells: { __Cell }, inputField_ ] := DynamicModule[ { w, h, size }, @@ -398,6 +552,7 @@ displayInlineChatMessages[ cells: { __Cell }, inputField_ ] := { Pane[ Column[ + (* FIXME: code blocks don't show syntax styles or string characters *) formatInlineMessageCells /@ cells, Alignment -> Left, BaseStyle -> { Magnification -> 0.8 }, @@ -456,7 +611,11 @@ formatInlineMessageCells[ cell: Cell[ __, "ChatOutput", ___ ] ] := { { Pane[ assistantImage[ ], ImageMargins -> $messageAuthorImagePadding ], - RawBoxes @ Append[ DeleteCases[ cell, Background -> _ ], Background -> None ] + RawBoxes @ InputFieldBox[ + Append[ DeleteCases[ cell, Background -> _ ], Background -> None ], + Appearance -> None, + ImageSize -> { Scaled[ 1 ], Automatic } + ] } }, Alignment -> { Left, Top } @@ -505,7 +664,7 @@ moveToChatInputField0 // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) -(*Chat Message Labels*) +(*Chat Message Decorations*) (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) @@ -558,12 +717,12 @@ userImage[ ] := userImage[ $CloudUserID ]; userImage[ user_String ] := Enclose[ Module[ { hash, url, image }, - hash = Hash[ ToLowerCase @ StringTrim @ user, "MD5", "HexString" ]; - url = ConfirmBy[ URLBuild[ { "https://www.gravatar.com/avatar/", hash }, $userImageParams ], StringQ, "URL" ]; - image = ConfirmBy[ Import @ url, ImageQ, "Image" ]; - userImage[ user ] = Show[ image, ImageSize -> 25 ] + hash = Hash[ ToLowerCase @ StringTrim @ user, "MD5", "HexString" ]; + url = ConfirmBy[ URLBuild[ { "https://www.gravatar.com/avatar/", hash }, $userImageParams ], StringQ, "URL" ]; + image = ConfirmBy[ Quiet @ Import @ url, ImageQ, "Image" ]; + userImage[ user ] = Show[ image, ImageSize -> 20 ] ], - $defaultUserImage & + (userImage[ user ] = $defaultUserImage) & ]; userImage[ other_ ] := @@ -571,6 +730,50 @@ userImage[ other_ ] := userImage // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*attachAssistantMessageButtons*) +attachAssistantMessageButtons // beginDefinition; + +attachAssistantMessageButtons[ cell_ ] /; $dynamicText || MatchQ[ $ChatEvaluationCell, _CellObject ] := Null; + +attachAssistantMessageButtons[ cell_CellObject ] := + attachAssistantMessageButtons[ cell, CurrentChatSettings[ cell, "WorkspaceChat" ] ]; + +attachAssistantMessageButtons[ cell0_CellObject, True ] := Enclose[ + Catch @ Module[ { cell, attached }, + + cell = topParentCell @ cell0; + If[ ! MatchQ[ cell, _CellObject ], Throw @ Null ]; + + (* If chat has been reloaded from history, it no longer has the necessary metadata for feedback: *) + If[ ! StringQ @ CurrentValue[ cell, { TaggingRules, "ChatData" } ], Throw @ Null ]; + + (* Remove existing attached cell, if any: *) + NotebookDelete @ Cells[ cell, AttachedCell -> True, CellStyle -> "ChatOutputTrayButtons" ]; + + (* Attach new cell: *) + attached = AttachCell[ + cell, + Cell[ + BoxData @ TemplateBox[ { }, "FeedbackButtonsHorizontal" ], + "ChatOutputTrayButtons", + Magnification -> AbsoluteCurrentValue[ cell, Magnification ] + ], + { Left, Bottom }, + 0, + { Left, Top }, + RemovalConditions -> "MouseExit" + ] + ], + throwInternalFailure +]; + +attachAssistantMessageButtons[ cell_CellObject, _ ] := + Null; + +attachAssistantMessageButtons // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Chat Notebook Conversion*) @@ -580,6 +783,9 @@ userImage // endDefinition; (*popOutWorkspaceChatNB*) popOutWorkspaceChatNB // beginDefinition; +popOutWorkspaceChatNB[ Dynamic[ cells_ ] ] := + popOutWorkspaceChatNB @ cells; + popOutWorkspaceChatNB[ cells: { ___Cell } ] := Enclose[ Module[ { nbo }, NotebookClose @ findCurrentWorkspaceChat[ ]; @@ -635,6 +841,88 @@ $fromWorkspaceChatConversionRules := $fromWorkspaceChatConversionRules = Dispatc ] :> Cell[ Flatten @ TextData @ text, "ChatOutput" ] }; +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*History*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*createHistoryMenu*) +createHistoryMenu // beginDefinition; + +createHistoryMenu[ nbo_NotebookObject ] := + createHistoryMenu[ nbo, ListSavedChats @ CurrentChatSettings[ nbo, "AppName" ] ]; + +createHistoryMenu[ nbo_NotebookObject ] := Enclose[ + Catch @ Module[ { appName, chats }, + appName = ConfirmBy[ CurrentChatSettings[ nbo, "AppName" ], StringQ, "AppName" ]; + chats = ConfirmMatch[ ListSavedChats @ appName, { ___Association }, "Chats" ]; + If[ chats === { }, Throw @ ActionMenu[ "History", { "Nothing here yet" :> Null } ] ]; + ActionMenu[ + "History", + makeHistoryMenuItem[ nbo ] /@ Take[ chats, UpTo @ $maxHistoryItems ], + Method -> "Queued" + ] + ], + throwInternalFailure +]; + +createHistoryMenu // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*makeHistoryMenuItem*) +makeHistoryMenuItem // beginDefinition; + +makeHistoryMenuItem[ nbo_NotebookObject ] := + makeHistoryMenuItem[ nbo, # ] &; + +makeHistoryMenuItem[ nbo_NotebookObject, chat_Association ] := Enclose[ + Module[ { title, date, timeString, label }, + title = ConfirmBy[ chat[ "ConversationTitle" ], StringQ, "Title" ]; + date = DateObject[ ConfirmBy[ chat[ "Date" ], NumericQ, "Date" ], TimeZone -> 0 ]; + timeString = ConfirmBy[ relativeTimeString @ date, StringQ, "TimeString" ]; + label = Row @ { title, " ", Style[ timeString, FontOpacity -> 0.75, FontSize -> Inherited * 0.9 ] }; + label :> loadConversation[ nbo, chat ] + ], + throwInternalFailure +]; + +makeHistoryMenuItem // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*loadConversation*) +loadConversation // beginDefinition; + +loadConversation[ nbo_NotebookObject, id_ ] := Enclose[ + Module[ { loaded, uuid, messages, cells, cellObjects }, + loaded = ConfirmBy[ LoadChat @ id, AssociationQ, "Loaded" ]; + uuid = ConfirmBy[ loaded[ "ConversationUUID" ], StringQ, "UUID" ]; + messages = ConfirmBy[ loaded[ "Messages" ], ListQ, "Messages" ]; + cells = ConfirmMatch[ ChatMessageToCell[ messages, "Workspace" ], { __Cell }, "Cells" ]; + cellObjects = ConfirmMatch[ Cells @ nbo, { ___CellObject }, "CellObjects" ]; + ConfirmMatch[ NotebookDelete @ cellObjects, { Null... }, "Delete" ]; + + WithCleanup[ + NotebookDelete @ First[ Cells[ nbo, AttachedCell -> True, CellStyle -> "ChatInputField" ], $Failed ], + SelectionMove[ nbo, Before, Notebook, AutoScroll -> True ]; + ConfirmMatch[ + NotebookWrite[ nbo, cells, AutoScroll -> False ], + Null, + "Write" + ], + ChatbookAction[ "AttachWorkspaceChatInput", nbo ] + ]; + + CurrentChatSettings[ nbo, "ConversationUUID" ] = uuid; + moveToChatInputField[ nbo, True ] + ], + throwInternalFailure +]; + +loadConversation // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Package Footer*) diff --git a/Source/Chatbook/ChatState.wl b/Source/Chatbook/ChatState.wl index 612ca939..45ae57c8 100644 --- a/Source/Chatbook/ChatState.wl +++ b/Source/Chatbook/ChatState.wl @@ -19,6 +19,7 @@ withChatState // Attributes = { HoldFirst }; withChatState[ eval_ ] := Block[ { + $ChatNotebookEvaluation = True, $absoluteCurrentSettingsCache = <| |>, $AutomaticAssistance = False, $chatState = True, @@ -26,6 +27,10 @@ withChatState[ eval_ ] := $enableLLMServices = Automatic, $WorkspaceChat = False, withChatState = # &, + $contextPrompt = None, + $selectionPrompt = None, + $toolCallCount = 0, + $openToolCallBoxes = Automatic, (* Values used for token budgets during cell serialization: *) $cellStringBudget = $cellStringBudget, diff --git a/Source/Chatbook/ChatTitle.wl b/Source/Chatbook/ChatTitle.wl new file mode 100644 index 00000000..93903136 --- /dev/null +++ b/Source/Chatbook/ChatTitle.wl @@ -0,0 +1,143 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`ChatTitle`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Configuration*) +$maxTitleLength = 30; +$hardMaxTitleLength = 40; +$maxContextLength = 100000; (* characters *) + +$titlePrompt := "\ +Please come up with a meaningful window title for the current chat conversation using no more than \ +"<>ToString[$maxTitleLength]<>" characters. +The title should be specific to the topics discussed in the chat. +Do not give generic titles such as \"Chat\", \"Transcript\", or \"Chat Transcript\". +Respond only with the title and nothing else. + +Here is the chat transcript: +`1` + +Remember, respond only with the title and nothing else."; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*GenerateChatTitle*) +GenerateChatTitle // beginDefinition; +GenerateChatTitle // Options = { "Temperature" -> 0.7 }; + +GenerateChatTitle[ messages: $$chatMessages, opts: OptionsPattern[ ] ] := + catchMine @ LogChatTiming @ generateChatTitle[ messages, OptionValue[ "Temperature" ] ]; + +GenerateChatTitle // endExportedDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*generateChatTitle*) +generateChatTitle // beginDefinition; + +generateChatTitle[ messages_, temperature_ ] := Enclose[ + Module[ { title, task }, + + task = ConfirmMatch[ + generateChatTitleAsync[ messages, Function[ title = # ], temperature ], + _TaskObject, + "Task" + ]; + + TaskWait @ task; + + ConfirmMatch[ title, _String|_Failure, "Result" ] + ], + throwInternalFailure +]; + +generateChatTitle // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*GenerateChatTitleAsynchronous*) +GenerateChatTitleAsynchronous // beginDefinition; +GenerateChatTitleAsynchronous[ messages: $$chatMessages, f_ ] := catchMine @ generateChatTitleAsync[ messages, f ]; +GenerateChatTitleAsynchronous // endExportedDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*generateChatTitleAsync*) +generateChatTitleAsync // beginDefinition; + +generateChatTitleAsync[ messages: $$chatMessages, callback_, temperature: Automatic | _? NumericQ ] := Enclose[ + Module[ { string, short, instructions, context }, + + string = ConfirmBy[ messagesToString[ messages, "IncludeSystemMessage" -> False ], StringQ, "String" ]; + short = ConfirmBy[ StringTake[ string, UpTo[ $maxContextLength ] ], StringQ, "Short" ]; + instructions = ConfirmBy[ TemplateApply[ $titlePrompt, short ], StringQ, "Prompt" ]; + + context = ConfirmMatch[ + Block[ { $multimodalMessages = True }, expandMultimodalString @ instructions ], + _String | { __ }, + "Context" + ]; + + $lastChatTitleContext = context; + + ConfirmMatch[ + llmSynthesizeSubmit[ context, <| "Temperature" -> temperature |>, callback @* postProcessChatTitle ], + _TaskObject, + "Task" + ] + ], + throwInternalFailure +]; + +generateChatTitleAsync // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*postProcessChatTitle*) +postProcessChatTitle // beginDefinition; + +postProcessChatTitle[ title0_String, KeyValuePattern[ "StatusCode" -> 200 ] ] := Enclose[ + Module[ { title }, + + title = ConfirmBy[ + StringReplace[ + StringTrim @ title0, + StartOfString ~~ (("\"" ~~ t___ ~~ "\"") | ("'" ~~ t___ ~~ "'")) ~~ EndOfString :> t + ], + StringQ, + "Title" + ]; + + ConfirmAssert[ StringQ @ title && StringLength @ title > 0, "StringCheck" ]; + + Which[ + StringContainsQ[ title, "\n"|"```" ], + Failure[ "TitleCharacters", <| "MessageTemplate" -> "Unexpected characters in generated title." |> ], + + StringLength @ title > $hardMaxTitleLength, + Failure[ "TitleLength", <| "MessageTemplate" -> "Generated title exceeds the maximum length." |> ], + + True, + title + ] + ], + throwInternalFailure +]; + +postProcessChatTitle // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Chatbook.wl b/Source/Chatbook/Chatbook.wl index 1cf36d17..18d7cfb1 100644 --- a/Source/Chatbook/Chatbook.wl +++ b/Source/Chatbook/Chatbook.wl @@ -6,12 +6,25 @@ Wolfram`ChatbookLoader`$MXFile = FileNameJoin @ { "Chatbook.mx" }; +If[ MemberQ[ $Packages, "Wolfram`Chatbook`" ] + , + Wolfram`ChatbookLoader`$protectedNames = Replace[ + Wolfram`Chatbook`$ChatbookProtectedNames, + Except[ _List ] :> Names[ "Wolfram`Chatbook`*" ] + ]; + + Wolfram`ChatbookLoader`$allNames = Replace[ + Wolfram`Chatbook`$ChatbookNames, + Except[ _List ] :> Union[ Wolfram`ChatbookLoader`$protectedNames, Names[ "Wolfram`Chatbook`*`*" ] ] + ]; + + Unprotect @@ Wolfram`ChatbookLoader`$protectedNames; + ClearAll @@ Wolfram`ChatbookLoader`$allNames; +]; + Quiet[ If[ FileExistsQ @ Wolfram`ChatbookLoader`$MXFile , - Unprotect[ "Wolfram`Chatbook`*" ]; - ClearAll[ "Wolfram`Chatbook`*" ]; - ClearAll[ "Wolfram`Chatbook`*`*" ]; Get @ Wolfram`ChatbookLoader`$MXFile; (* Ensure all subcontexts are in $Packages to avoid reloading subcontexts out of order: *) If[ MatchQ[ Wolfram`Chatbook`$ChatbookContexts, { __String } ], @@ -23,15 +36,7 @@ Quiet[ ] , WithCleanup[ - PreemptProtect[ - Quiet[ - Unprotect[ "Wolfram`Chatbook`*" ]; - ClearAll[ "Wolfram`Chatbook`*" ]; - Remove[ "Wolfram`Chatbook`*`*" ], - { Remove::rmnsm } - ]; - Get[ "Wolfram`Chatbook`Main`" ] - ], + PreemptProtect @ Get[ "Wolfram`Chatbook`Main`" ], { $Context, $ContextPath, $ContextAliases } = { ## } ] & [ $Context, $ContextPath, $ContextAliases ] ], diff --git a/Source/Chatbook/ChatbookFiles.wl b/Source/Chatbook/ChatbookFiles.wl new file mode 100644 index 00000000..18f9ca89 --- /dev/null +++ b/Source/Chatbook/ChatbookFiles.wl @@ -0,0 +1,59 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`ChatbookFiles`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Configuration*) +$chatbookRoot := FileNameJoin @ { ExpandFileName @ LocalObject @ $LocalBase, "Chatbook" }; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*$ChatbookFilesDirectory*) +$ChatbookFilesDirectory := chatbookFilesDirectory[ { }, False ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*ChatbookFilesDirectory*) +ChatbookFilesDirectory // beginDefinition; +ChatbookFilesDirectory // Options = { "EnsureDirectory" -> True }; + +ChatbookFilesDirectory[ opts: OptionsPattern[ ] ] := + catchMine @ chatbookFilesDirectory[ { }, OptionValue[ "EnsureDirectory" ] ]; + +ChatbookFilesDirectory[ name_String, opts: OptionsPattern[ ] ] := + catchMine @ chatbookFilesDirectory[ { name }, OptionValue[ "EnsureDirectory" ] ]; + +ChatbookFilesDirectory[ { names___String }, opts: OptionsPattern[ ] ] := + catchMine @ chatbookFilesDirectory[ { names }, OptionValue[ "EnsureDirectory" ] ]; + +ChatbookFilesDirectory // endExportedDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*chatbookFilesDirectory*) +chatbookFilesDirectory // beginDefinition; + +chatbookFilesDirectory[ { names___String }, ensure_ ] := Enclose[ + If[ TrueQ @ ensure, + ConfirmBy[ GeneralUtilities`EnsureDirectory @ { $chatbookRoot, names }, DirectoryQ, "Directory" ], + ConfirmBy[ FileNameJoin @ { $chatbookRoot, names }, StringQ, "Directory" ] + ], + throwInternalFailure +]; + +chatbookFilesDirectory // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Common.wl b/Source/Chatbook/Common.wl index 886fcfe8..a605746f 100644 --- a/Source/Chatbook/Common.wl +++ b/Source/Chatbook/Common.wl @@ -33,6 +33,7 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `$$size; `$$textData; `$$textDataList; +`$$graphics; `$$unspecified; `$$feObj; `$$template; @@ -44,6 +45,10 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `$$symbol; `$$atomic; +`$$chatMessage; +`$$chatMessages; +`wordsPattern; + `tr; `trRaw; `trStringTemplate; @@ -93,6 +98,7 @@ Needs[ "Wolfram`Chatbook`" ]; $cloudNotebooks := TrueQ @ CloudSystem`$CloudNotebooks; $chatIndicatorSymbol = "\|01f4ac"; +$defaultAppName = "Default"; $chatDelimiterStyles = { "ChatBlockDivider", "ChatDelimiter", "ExcludedChatDelimiter" }; $chatIgnoredStyles = { "ChatExcluded" }; @@ -127,9 +133,34 @@ $resourceVersions = <| "ClickToCopy" -> "1.0.0", "GPTTokenizer" -> "1.1.0", "MessageFailure" -> "1.0.0", - "ReplaceContext" -> "1.0.0" + "RelativeTimeString" -> "1.0.0", + "ReplaceContext" -> "1.0.0", + "SelectByCurrentValue" -> "1.0.1" |>; +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Basic Argument Patterns*) +$$optionsSequence = (Rule|RuleDelayed)[ _Symbol|_String, _ ] ...; +$$size = Infinity | (_Real|_Integer)? NonNegative; +$$unspecified = _Missing | Automatic | Inherited; +$$feObj = _FrontEndObject | $FrontEndSession | _NotebookObject | _CellObject | _BoxObject; +$$template = _String|_TemplateObject|_TemplateExpression|_TemplateSequence; +$$serviceCaller = _String? StringQ | { ___String? StringQ }; + +(* Helper functions for held pattern tests: *) +u[ f_ ] := Function[ Null, f @ Unevaluated @ #, HoldAllComplete ]; +pt[ patt_, f_ ] := PatternTest[ patt, Evaluate @ u @ f ]; + +(* Atomic expressions (not including raw objects like Association etc): *) +$$complex = pt[ _Complex , AtomQ ]; +$$integer = pt[ _Integer , IntegerQ ]; +$$rational = pt[ _Rational, AtomQ ]; +$$real = pt[ _Real , Developer`RealQ ]; +$$string = pt[ _String , StringQ ]; +$$symbol = pt[ _Symbol , Developer`SymbolQ ]; +$$atomic = $$complex | $$integer | $$rational | $$real | $$string | $$symbol; + (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*Style Patterns*) @@ -144,36 +175,37 @@ $$chatOutputStyle = cellStylePattern @ $chatOutputStyles; $$excludeHistoryStyle = cellStylePattern @ $excludeHistoryStyles; $$nestedCellStyle = cellStylePattern @ $nestedCellStyles; +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Text Data*) $$textDataItem = (_String|_Cell|_StyleBox|_ButtonBox); $$textDataList = { $$textDataItem... }; $$textData = $$textDataItem | $$textDataList; (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) -(*Other Argument Patterns *) -$$optionsSequence = (Rule|RuleDelayed)[ _Symbol|_String, _ ] ...; -$$size = Infinity | (_Real|_Integer)? NonNegative; -$$unspecified = _Missing | Automatic | Inherited; -$$feObj = _FrontEndObject | $FrontEndSession | _NotebookObject | _CellObject | _BoxObject; -$$template = _String|_TemplateObject|_TemplateExpression|_TemplateSequence; +(*Graphics*) +$$graphics = _? graphicsQ; -(* Helper functions for held pattern tests: *) -u[ f_ ] := Function[ Null, f @ Unevaluated @ #, HoldAllComplete ]; -pt[ patt_, f_ ] := PatternTest[ patt, Evaluate @ u @ f ]; +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Chat Messages*) +$$messageRole = "System"|"Assistant"|"User"; +$$messageContentData = KeyValuePattern @ { "Type" -> "Text"|"Image", "Data" -> _ } | $$string | $$graphics; +$$messageContent = $$messageContentData | { $$messageContentData... }; +$$chatMessage = KeyValuePattern @ { "Role" -> $$messageRole, "Content" -> $$messageContent }; +$$chatMessages = { $$chatMessage... }; -(* Atomic expressions (not including raw objects like Association etc): *) -$$complex = pt[ _Complex , AtomQ ]; -$$integer = pt[ _Integer , IntegerQ ]; -$$rational = pt[ _Rational, AtomQ ]; -$$real = pt[ _Real , Developer`RealQ ]; -$$string = pt[ _String , StringQ ]; -$$symbol = pt[ _Symbol , Developer`SymbolQ ]; -$$atomic = $$complex | $$integer | $$rational | $$real | $$string | $$symbol; +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Misc*) +wordsPattern[ words_ ] := _String? (containsWordsQ @ words); (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Text and Expression Resources*) +(* FIXME: These need to go after beginDefinition and endDefinition initializations *) (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*tr*) @@ -287,6 +319,8 @@ KeyValueMap[ Function[ MessageName[ Chatbook, #1 ] = #2 ], <| "InvalidHandlerKeys" -> "Invalid setting for HandlerFunctionsKeys: `1`; using defaults instead.", "InvalidHandlers" -> "Invalid setting for HandlerFunctions: `1`; using defaults instead.", "InvalidMessages" -> "The value `2` returned by `1` is not a valid list of messages.", + "InvalidPromptGeneratorPosition" -> "Invalid position spec for prompt generator messages: `1`.", + "InvalidPromptGeneratorRole" -> "Invalid role for prompt generator messages: `1`. Valid values are: \"System\", \"Assistant\", or \"User\".", "InvalidResourceSpecification" -> "The argument `1` is not a valid resource specification.", "InvalidResourceURL" -> "The specified URL does not represent a valid resource object.", "InvalidRootSettings" -> "The value `1` is not valid for root chat settings.", @@ -298,6 +332,7 @@ KeyValueMap[ Function[ MessageName[ Chatbook, #1 ] = #2 ], <| "NoSandboxKernel" -> "Unable to start a sandbox kernel. This may mean that the number of currently running kernels exceeds the limit defined by $LicenseProcesses.", "NotImplemented" -> "Action \"`1`\" is not implemented.", "NotInstallableResourceType" -> "Resource type `1` is not an installable resource type for chat notebooks. Valid types are `2`.", + "PersonaDirectoryNotFound" -> "The directory `2` for persona `1` was not found.", "RateLimitReached" -> "Rate limit reached for requests. Please try again later.", "ResourceNotFound" -> "Resource `1` not found.", "ResourceNotInstalled" -> "The resource `1` is not installed.", @@ -519,7 +554,7 @@ importResourceFunction::failure = "[ERROR] Failed to import resource function `1 importResourceFunction // Attributes = { HoldFirst }; importResourceFunction[ symbol_Symbol, name_String ] := - importResourceFunction[ symbol, name, Lookup[ $resourceVersions, name, "Latest" ] ]; + importResourceFunction[ symbol, name, Lookup[ $resourceVersions, name ] ]; importResourceFunction[ symbol_Symbol, name_String, version_String ] /; $mxFlag := Enclose[ Block[ { PrintTemporary }, @@ -574,14 +609,15 @@ catchTop[ eval_ ] := catchTop[ eval, Chatbook ]; catchTop[ eval_, sym_Symbol ] := Block[ { - $ChatNotebookEvaluation = True, - $currentChatSettings = None, - $messageSymbol = Replace[ $messageSymbol, Chatbook -> sym ], - $catching = True, - $failed = False, - catchTop = # &, - catchTopAs = (#1 &) & + $chatEvaluationID = CreateUUID[ ], + $currentChatSettings = None, + $messageSymbol = Replace[ $messageSymbol, Chatbook -> sym ], + $catching = True, + $failed = False, + catchTop = # &, + catchTopAs = (#1 &) & }, + $chatStartTime = AbsoluteTime[ ]; Catch[ setServiceCaller @ eval, $catchTopTag ] ]; @@ -774,23 +810,39 @@ makeInternalFailureData[ eval_, args___ ] := (* ::Subsection::Closed:: *) (*setServiceCaller*) setServiceCaller // beginDefinition; -setServiceCaller // Attributes = { HoldFirst }; -setServiceCaller[ eval_ ] := ( +setServiceCaller[ eval_ ] := + setServiceCaller[ eval, chatbookServiceCaller[ ] ]; + +setServiceCaller[ eval_, caller_ ] := ( Quiet @ Needs[ "ServiceConnectionUtilities`" -> None ]; - setServiceCaller[ eval, ServiceConnectionUtilities`$Caller ] + setServiceCaller[ eval, caller, ServiceConnectionUtilities`$Caller ] ); -setServiceCaller[ eval_, { c___ } ] := - Block[ { ServiceConnectionUtilities`$Caller = { c, "Chatbook" }, setServiceCaller = # & }, +setServiceCaller[ eval_, caller: $$serviceCaller, { current___ } ] := + Block[ { ServiceConnectionUtilities`$Caller = DeleteDuplicates @ Flatten @ { current, "Chatbook", caller } }, eval ]; -setServiceCaller[ eval_, _ ] := - setServiceCaller[ eval, { } ]; +setServiceCaller[ eval_, caller_, _ ] := + setServiceCaller[ eval, caller, { } ]; +setServiceCaller // Attributes = { HoldFirst }; setServiceCaller // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*chatbookServiceCaller*) +chatbookServiceCaller // beginDefinition; + +chatbookServiceCaller[ ] := Flatten @ { + If[ TrueQ @ $InlineChat, "InlineChat", Nothing ], + If[ TrueQ @ $WorkspaceChat, "WorkspaceChat", Nothing ], + Replace[ $serviceCaller, Except[ $$serviceCaller ] -> Nothing ] +}; + +chatbookServiceCaller // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Bug Report Link Generation*) @@ -1164,14 +1216,26 @@ inlineTemplateBoxes // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*$chatbookIcons*) -$chatbookIcons := $chatbookIcons = - Developer`ReadWXFFile @ PacletObject[ "Wolfram/Chatbook" ][ "AssetLocation", "Icons" ]; +$chatbookIcons := Enclose[ + Module[ { file, icons }, + file = ConfirmBy[ $thisPaclet[ "AssetLocation", "Icons" ], FileExistsQ, "File" ]; + icons = ConfirmBy[ Developer`ReadWXFFile @ file, AssociationQ, "Icons" ]; + If[ TrueQ @ $mxFlag, icons, $chatbookIcons = icons ] + ], + throwInternalFailure[ $chatbookIcons, ## ] & +]; (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*$templateBoxDisplayFunctions*) -$templateBoxDisplayFunctions := $templateBoxDisplayFunctions = - Developer`ReadWXFFile @ PacletObject[ "Wolfram/Chatbook" ][ "AssetLocation", "DisplayFunctions" ]; +$templateBoxDisplayFunctions := Enclose[ + Module[ { file, funcs }, + file = ConfirmBy[ $thisPaclet[ "AssetLocation", "DisplayFunctions" ], FileExistsQ, "File" ]; + funcs = ConfirmBy[ Developer`ReadWXFFile @ file, AssociationQ, "Functions" ]; + If[ TrueQ @ $mxFlag, funcs, $templateBoxDisplayFunctions = funcs ] + ], + throwInternalFailure[ $templateBoxDisplayFunctions, ## ] & +]; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) @@ -1231,7 +1295,6 @@ mxInitialize // endDefinition; addToMXInitialization[ $debug = False; $chatbookIcons; - $templateBoxDisplayFunctions; $cloudTextResources; $releaseID; ]; diff --git a/Source/Chatbook/CommonSymbols.wl b/Source/Chatbook/CommonSymbols.wl index 8728d39c..10ff8e0b 100644 --- a/Source/Chatbook/CommonSymbols.wl +++ b/Source/Chatbook/CommonSymbols.wl @@ -11,22 +11,29 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `$basePrompt; `$basePromptComponents; `$baseStyle; +`$cachedTokenizers; +`$cellReferences; `$cellStringBudget; `$chatDataTag; +`$chatEvaluationID; `$chatInputIndicator; +`$chatStartTime; `$chatState; `$cloudEvaluationNotebook; `$cloudInlineReferenceButtons; +`$contextPrompt; `$conversionRules; `$corePersonaNames; `$CurrentCell; `$currentChatSettings; `$currentSettingsCache; `$customToolFormatter; +`$defaultAppName; `$defaultChatSettings; `$defaultChatTools; `$defaultMaxCellStringLength; `$defaultMaxOutputCellStringLength; +`$defaultPromptGenerators; `$dialogInputAllowed; `$dynamicSplitRules; `$dynamicText; @@ -35,6 +42,7 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `$evaluationNotebook; `$finalCell; `$fullBasePrompt; +`$includeCellXML; `$inDialog; `$inEpilog; `$initialCellStringBudget; @@ -48,19 +56,26 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `$longNameCharacters; `$multimodalMessages; `$nextTaskEvaluation; +`$noSemanticSearch; +`$notebookEditorEnabled; +`$openToolCallBoxes; `$preferencesScope; `$resultCellCache; `$rightSelectionIndicator; `$sandboxKernelCommandLine; `$selectedTools; +`$selectionPrompt; `$serviceCache; +`$serviceCaller; `$servicesLoaded; `$statelessProgressIndicator; `$suppressButtonAppearance; +`$timingLog; `$tinyHashLength; `$tokenBudget; `$tokenBudgetLog; `$tokenPressure; +`$toolCallCount; `$toolConfiguration; `$toolEvaluationResults; `$toolOptions; @@ -74,18 +89,23 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `apiKeyDialog; `applyHandlerFunction; `applyProcessingFunction; +`applyPromptGenerators; `assistantMessageBox; `assistantMessageLabel; `associationKeyDeflatten; +`attachAssistantMessageButtons; `attachInlineChatInput; `attachMenuCell; `attachWorkspaceChatInput; `autoAssistQ; +`boxDataQ; `cachedTokenizer; +`cellFlatten; `cellInformation; `cellOpenQ; `cellPrint; `cellPrintAfter; +`cellReference; `cellStyles; `channelCleanup; `chatExcludedQ; @@ -98,6 +118,7 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `clickToCopy; `compressUntilViewed; `constructMessages; +`containsWordsQ; `contextBlock; `convertUTF8; `createDialog; @@ -122,6 +143,7 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `exportDataURI; `expressionURIKey; `expressionURIKeyQ; +`extractBodyChunks; `fastFileHash; `feParentObject; `filterChatCells; @@ -132,7 +154,11 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `functionTemplateBoxes; `getAvailableServiceNames; `getBoxObjectFromBoxID; +`getChatConversationData; `getChatGroupSettings; +`getChatMetadata; +`getEmbedding; +`getEmbeddings; `getHandlerFunctions; `getInlineChatPrompt; `getModelList; @@ -166,6 +192,8 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `insertPersonaTemplate; `insertTrailingFunctionInputBox; `insertWLTemplate; +`llmSynthesize; +`llmSynthesizeSubmit; `logUsage; `makeCellStringBudget; `makeChatCloudDockedCellContents; @@ -180,6 +208,9 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `makeToolResponseString; `makeWorkspaceChatDockedCell; `menuMagnification; +`mergeChatSettings; +`mergeCodeBlocks; +`messagesToString; `modelDisplayName; `modelListCachedQ; `modifierTemplateBoxes; @@ -190,6 +221,7 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `nextCell; `notebookInformation; `notebookRead; +`o1ModelQ; `openerView; `openPreferencesPage; `parentCell; @@ -225,6 +257,7 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `sendChat; `sendFeedback; `serviceIcon; +`serviceName; `setCV; `simpleResultQ; `simpleToolRequestParser; @@ -247,6 +280,7 @@ BeginPackage[ "Wolfram`Chatbook`Common`" ]; `toolSelectedQ; `toolsEnabledQ; `topParentCell; +`toSmallSettings; `trackedDynamic; `truncateString; `unsetCV; diff --git a/Source/Chatbook/Dynamics.wl b/Source/Chatbook/Dynamics.wl index cc489f1b..9d39204b 100644 --- a/Source/Chatbook/Dynamics.wl +++ b/Source/Chatbook/Dynamics.wl @@ -17,6 +17,7 @@ $dynamicTriggers = <| "Models" :> $modelsTrigger, "Personas" :> $personasTrigger, "Preferences" :> $preferencesTrigger, + "SavedChats" :> $savedChatsTrigger, "Services" :> $servicesTrigger, "Tools" :> $toolsTrigger |>; diff --git a/Source/Chatbook/Explode.wl b/Source/Chatbook/Explode.wl index 79af0742..4c222e44 100644 --- a/Source/Chatbook/Explode.wl +++ b/Source/Chatbook/Explode.wl @@ -11,6 +11,7 @@ $$newCellStyle = Alternatives[ "ExternalLanguage", "Input", "Item", + "Subitem", "MarkdownDelimiter", "Program", "Section", @@ -22,6 +23,8 @@ $$newCellStyle = Alternatives[ "Title" ]; +$$ws = _String? (StringMatchQ[ WhitespaceCharacter... ]); + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*ExplodeCell*) @@ -40,15 +43,67 @@ explodeCell[ string_String ] := Cell[ #, "Text" ] & /@ StringSplit[ string, Long explodeCell[ (BoxData|TextData)[ textData_, ___ ] ] := explodeCell @ Flatten @ List @ textData; explodeCell[ textData_List ] := Enclose[ - Module[ { processed }, + Module[ { processed, grouped, post }, processed = ConfirmMatch[ ReplaceRepeated[ textData, $preprocessingRules ], $$textDataList, "Preprocessing" ]; - ConfirmMatch[ regroupCells @ processed, $$textDataList, "RegroupCells" ] + grouped = ConfirmMatch[ regroupCells @ processed, $$textDataList, "RegroupCells" ]; + post = ConfirmMatch[ Flatten[ postProcessExplodedCells /@ grouped ], { __Cell }, "PostProcessing" ]; + SequenceReplace[ + post, + { Cell[ caption_? captionQ, "Text", a___ ], input: Cell[ __, "Input"|"Code", ___ ] } :> + Sequence[ Cell[ caption, "CodeText", a ], input ] + ] ], - throwInternalFailure[ explodeCell @ textData, ## ] & + throwInternalFailure ]; explodeCell // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*captionQ*) +captionQ // beginDefinition; +captionQ[ text_String ] := StringEndsQ[ text, ":"~~WhitespaceCharacter... ]; +captionQ[ (ButtonBox|Cell|StyleBox|TextData)[ text_, ___ ] ] := captionQ @ text; +captionQ[ { ___, text_ } ] := captionQ @ text; +captionQ[ _ ] := False; +captionQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*postProcessExplodedCells*) +postProcessExplodedCells // beginDefinition; + +postProcessExplodedCells[ + Cell[ BoxData @ RowBox @ { RowBox @ { "In", "[", n_String, "]" }, "="|":=", boxes__ }, "Input", a___ ] +] := Cell[ BoxData @ boxes, "Input", CellLabel -> "In["<>n<>"]:=", a ]; + +postProcessExplodedCells[ + Cell[ BoxData @ RowBox @ { RowBox @ { "Out", "[", n_String, "]" }, "="|":=", boxes__ }, "Input", a___ ] +] := Cell[ BoxData @ boxes, "Output", CellLabel -> "Out["<>n<>"]=", a ]; + +postProcessExplodedCells[ Cell[ + BoxData @ RowBox @ { + RowBox @ { RowBox @ { "In", "[", nIn_String, "]" }, ":=", in___ }, + $$ws..., + RowBox @ { RowBox @ { "Out", "[", nOut_String, "]" }, "=", out___ } + }, + "Input" +] ] := { + Cell[ BoxData @ RowBox @ { in }, "Input", CellLabel -> "In["<>nIn<>"]:=" ], + Cell[ BoxData @ RowBox @ { out }, "Output", CellLabel -> "Out["<>nOut<>"]=" ] +}; + +postProcessExplodedCells[ cell: Cell[ __, "Input", ___ ] ] := DeleteCases[ + cell /. { RowBox @ { RowBox @ { "In", "[", _, "]" }, "="|":=", boxes__ } :> RowBox @ { boxes } }, + RowBox @ { RowBox @ { "Out", "[", _, "]" }, "="|":=", __ }, + Infinity +]; + +postProcessExplodedCells[ cell_Cell ] := + cell; + +postProcessExplodedCells // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*$preprocessingRules*) @@ -97,7 +152,11 @@ $preprocessingRules := $preprocessingRules = Dispatch @ { (* Remove nested cells: *) Cell @ BoxData[ cell_Cell, ___ ] :> cell, - StyleBox[ a_String, "InlineItem", b___ ] :> StyleBox[ "\n"<>a, b ], + Cell[ TextData @ { StyleBox[ "\[Bullet]", ___ ], " ", content___ }, "InlineItem", ___ ] :> + Cell[ TextData @ content, "Item" ], + + Cell[ TextData @ { _String, StyleBox[ "\[Bullet]", ___ ], " ", content___ }, "InlineSubitem", ___ ] :> + Cell[ TextData @ content, "Subitem" ], (* Format text tables: *) Cell[ content__, "TextTableForm", opts: OptionsPattern[ ] ] :> @@ -125,7 +184,16 @@ $preprocessingRules := $preprocessingRules = Dispatch @ { StyleBox[ "\n", "TinyLineBreak", ___ ] :> "\n", Cell[ boxes_, style: "MarkdownDelimiter"|"BlockQuote", a___ ] :> - Cell[ boxes, "Text", style, a ] + Cell[ boxes, "Text", style, a ], + + (* Fix cases where the LLM tried to manually create MarkdownImageBoxes: *) + RowBox @ { "\\!", RowBox @ { "\\(", RowBox @ { "*MarkdownImageBox", "[", uri_, "]" }, "\\)" } } :> + With[ { expr = Quiet @ catchAlways @ GetExpressionURI @ StringTrim[ uri, "\"" ] }, + If[ FailureQ @ expr, + "\[LeftSkeleton]Removed\[RightSkeleton]", + ToBoxes @ expr + ] + ] }; (* ::**************************************************************************************************************:: *) @@ -183,6 +251,9 @@ regroupCells[ { grouped___ }, { grouping___ }, { string_String, rest___ } ] := } ]; +regroupCells[ { grouped___ }, { grouping___ }, { other_, rest___ } ] := + regroupCells[ { grouped }, { grouping, other }, { rest } ]; + regroupCells[ { grouped___ }, { grouping___ }, { } ] := DeleteCases[ { grouped, Cell[ TextData @ { grouping }, "Text" ] }, Cell[ TextData @ { }, ___ ] ]; diff --git a/Source/Chatbook/Feedback.wl b/Source/Chatbook/Feedback.wl index 4bc02512..29f40783 100644 --- a/Source/Chatbook/Feedback.wl +++ b/Source/Chatbook/Feedback.wl @@ -5,9 +5,8 @@ Begin[ "`Private`" ]; (* :!CodeAnalysis::BeginBlock:: *) -Needs[ "Wolfram`Chatbook`" ]; -Needs[ "Wolfram`Chatbook`Common`" ]; -Needs[ "Wolfram`Chatbook`Serialization`" ]; +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) diff --git a/Source/Chatbook/Formatting.wl b/Source/Chatbook/Formatting.wl index 320575f6..84d8840b 100644 --- a/Source/Chatbook/Formatting.wl +++ b/Source/Chatbook/Formatting.wl @@ -223,9 +223,10 @@ reformatTextData[ string_String ] /; StringContainsQ[ string, $$mdEscapedCharact s_String :> RuleCondition @ StringReplace[ s, $mdUnescapeRules ] ]; +(* cSpell: ignore maxrec *) reformatTextData[ string_String ] := joinAdjacentStrings @ Flatten[ makeResultCell /@ discardBadToolCalls @ DeleteCases[ - StringSplit[ string, $textDataFormatRules, IgnoreCase -> True ], + Quiet[ StringSplit[ string, $textDataFormatRules, IgnoreCase -> True ], RegularExpression::maxrec ], "" ] ]; @@ -307,12 +308,29 @@ makeResultCell0[ imageCell[ alt_String, url_String ] ] := image[ alt, url ]; makeResultCell0[ hyperlinkCell[ label_String, url_String ] ] := hyperlink[ label, url ]; -makeResultCell0[ bulletCell[ whitespace_String, item_String ] ] := Flatten @ { +makeResultCell0[ bulletCell[ "", item_String ] ] := { "\n", - whitespace, - StyleBox[ "\[Bullet]", "InlineItem", FontColor -> GrayLevel[ 0.5 ] ], - " ", - formatTextString @ item + Cell[ + TextData @ Flatten @ { + StyleBox[ "\[Bullet]", FontColor -> GrayLevel[ 0.5 ] ], + " ", + formatTextString @ item + }, + "InlineItem" + ] +}; + +makeResultCell0[ bulletCell[ whitespace_String, item_String ] ] := { + "\n", + Cell[ + TextData @ Flatten @ { + whitespace, + StyleBox[ "\[Bullet]", FontColor -> GrayLevel[ 0.5 ] ], + " ", + formatTextString @ item + }, + "InlineSubitem" + ] }; makeResultCell0[ sectionCell[ n_, section_String ] ] := Flatten @ { @@ -578,6 +596,7 @@ formatRaw[ item_, { } ] := item; formatRaw[ item_, StyleBox[ box_ ] ] := formatRaw[ item, box ]; formatRaw[ item_, box: _ButtonBox|_Cell|_StyleBox ] := RawBoxes @ box; formatRaw[ item_, string_String ] := string; +formatRaw[ item_, text: $$textDataList ] := RawBoxes @ Cell @ TextData @ text; formatRaw // endDefinition; (* ::**************************************************************************************************************:: *) @@ -783,7 +802,6 @@ insertCodeBelow[ cell_Cell, evaluate_ ] := cellObj = topParentCell @ EvaluationCell[ ]; nbo = parentNotebook @ cellObj; insertAfterChatGeneratedCells[ cellObj, cell ]; - NotebookDelete @ Cells[ nbo, AttachedCell -> True, CellStyle -> "AttachedChatInput" ]; If[ TrueQ @ evaluate, selectionEvaluateCreateCell @ nbo, SelectionMove[ nbo, After, CellContents ] @@ -1066,7 +1084,7 @@ fancyTooltip[ expr_, tooltip_ ] := Tooltip[ $$endToolCall = Longest[ "ENDRESULT" ~~ (("(" ~~ (LetterCharacter|DigitCharacter).. ~~ ")") | "") ]; $$eol = " "... ~~ "\n"; $$cmd = Repeated[ Except[ WhitespaceCharacter ], { 1, 80 } ]; -$$simpleToolCommand = StartOfLine ~~ $$ws ~~ ("/" ~~ c: $$cmd) ~~ $$eol /; $simpleToolMethod && toolShortNameQ @ c; +$$simpleToolCommand = StartOfLine ~~ $$ws ~~ ("/" ~~ $$cmd) ~~ $$eol; $$simpleToolCall = Shortest[ $$simpleToolCommand ~~ ___ ~~ ($$endToolCall|EndOfString) ]; @@ -1085,19 +1103,25 @@ $textDataFormatRules = { Longest[ "```" ~~ language: Except[ "\n" ]... ] ~~ (" "...) ~~ "\n", Shortest[ code__ ], ("```"|EndOfString) - ] /; StringFreeQ[ code, "TOOLCALL:" ~~ ___ ~~ ($$endToolCall|EndOfString) ] :> + ] /; StringFreeQ[ code, ("TOOLCALL:" ~~ ___ ~~ ($$endToolCall|EndOfString))|$$simpleToolCall ] :> codeBlockCell[ language, code ] , - "![" ~~ alt: Shortest[ ___ ] ~~ "](" ~~ url: Shortest[ Except[ ")" ].. ] ~~ ")" /; - StringFreeQ[ alt, "["~~___~~"]("~~__~~")" ] :> - imageCell[ alt, url ] + Longest @ StringExpression[ + (("```" ~~ Except[ "\n" ]... ~~ (" "...) ~~ "\n"))|"", + tool: ("TOOLCALL:" ~~ Shortest[ ___ ] ~~ ($$endToolCall|EndOfString)) + ] :> inlineToolCallCell @ tool , - tool: ("TOOLCALL:" ~~ Shortest[ ___ ] ~~ ($$endToolCall|EndOfString)) :> inlineToolCallCell @ tool - , - tool: $$simpleToolCall :> inlineToolCallCell @ tool + Longest @ StringExpression[ + (("```" ~~ Except[ "\n" ]... ~~ (" "...) ~~ "\n"))|"", + tool: $$simpleToolCall + ] :> inlineToolCallCell @ tool , StartOfLine ~~ "/retry" ~~ (WhitespaceCharacter|EndOfString) :> $discardPreviousToolCall , + "![" ~~ alt: Shortest[ ___ ] ~~ "](" ~~ url: Shortest[ Except[ ")" ].. ] ~~ ")" /; + StringFreeQ[ alt, "["~~___~~"]("~~__~~")" ] :> + imageCell[ alt, url ] + , ("\n"|StartOfString).. ~~ w:" "... ~~ ("* "|"- ") ~~ item: Longest[ Except[ "\n" ].. ] :> bulletCell[ w, item ] , @@ -1409,7 +1433,8 @@ parseFullToolCallString[ id_String, tool: HoldPattern[ _LLMTool ], parameters_As "FormattingFunction" -> getToolFormattingFunction @ tool, "ToolCall" -> StringTrim @ string, "Parameters" -> parameters, - "Result" -> output + "Result" -> output, + "Open" -> TrueQ @ $openToolCallBoxes |>; parseFullToolCallString // endDefinition; @@ -1429,8 +1454,7 @@ parseToolCallID[ string_String? StringQ ] := WhitespaceCharacter..., Alternatives[ "TOOLCALL:", - StartOfLine ~~ "/" ~~ cmd: Except[ WhitespaceCharacter ].. ~~ WhitespaceCharacter... ~~ "\n" /; - toolShortNameQ @ cmd + StartOfLine ~~ "/" ~~ cmd: Except[ WhitespaceCharacter ].. ~~ WhitespaceCharacter... ~~ "\n" ], ___, "ENDRESULT(", @@ -1493,6 +1517,7 @@ makeToolCallBoxLabel[ as0_, name_String, icon_ ] := LabelStyle -> { FontSize -> 12 } ] }, + TrueQ @ as0[ "Open" ], Method -> "Active" ] ]; @@ -1724,7 +1749,11 @@ makeInteractiveCodeCell[ lang_String? wolframLanguageQ, code_ ] := BoxData @ If[ StringQ @ code, wlStringToBoxes @ code, code ], "ChatCode", "Input", - Background -> GrayLevel[ 1 ] + Background -> GrayLevel[ 1 ], + LanguageCategory -> "Input", + ShowAutoStyles -> True, + ShowStringCharacters -> True, + ShowSyntaxStyles -> True ]; handler = inlineInteractiveCodeCell[ display, code ]; codeBlockFrame[ Cell @ BoxData @ ToBoxes @ handler, code ] @@ -1781,8 +1810,12 @@ formatNLInputs // beginDefinition; formatNLInputs[ string_String ] := StringReplace[ string, - "\[FreeformPrompt][\"" ~~ q: Except[ "\"" ].. ~~ ("\"]"|EndOfString) :> - ToString[ RawBoxes @ formatNLInputFast @ q, StandardForm ] + { + "\[FreeformPrompt][\"" ~~ q: Except[ "\"" ].. ~~ ("\"]"|EndOfString) :> + ToString[ RawBoxes @ formatNLInputFast @ q, StandardForm ], + "ResourceFunction[\"" ~~ name: Except[ "\"" ].. ~~ ("\"]"|EndOfString) :> + ToString[ RawBoxes @ formatResourceFunctionFast @ name, StandardForm ] + } ]; formatNLInputs[ boxes_ ] := @@ -1792,10 +1825,40 @@ formatNLInputs[ boxes_ ] := , RowBox @ { "\[FreeformPrompt]", "[", q_String } /; StringMatchQ[ q, "\""~~Except[ "\""]..~~("\""|"") ] :> RuleCondition @ formatNLInputFast @ q + , + RowBox @ { "ResourceFunction", "[", name_String, "]" } /; StringMatchQ[ name, "\""~~Except[ "\""]..~~"\"" ] :> + RuleCondition @ If[ TrueQ @ $dynamicText, + formatResourceFunctionFast @ name, + formatResourceFunctionSlow @ name + ] }; formatNLInputs // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*formatResourceFunctionFast*) +formatResourceFunctionFast // beginDefinition; + +formatResourceFunctionFast[ name_String ] := ( + Needs[ "FunctionResource`" -> None ]; + FunctionResource`InertResourceFunctionBoxes[ "Published", StringTrim[ name, "\"" ] ] +); + +formatResourceFunctionFast // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*formatResourceFunctionSlow*) +formatResourceFunctionSlow // beginDefinition; + +formatResourceFunctionSlow[ name_String ] := ( + Needs[ "FunctionResource`" -> None ]; + FunctionResource`MakeResourceFunctionBoxes @ StringTrim[ name, "\"" ] +); + +formatResourceFunctionSlow // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*formatNLInputFast*) @@ -1938,29 +2001,14 @@ makeInlineCodeCell // beginDefinition; makeInlineCodeCell[ s_String? nameQ ] /; Context @ s === "System`" := hyperlink[ s, "paclet:ref/" <> Last @ StringSplit[ s, "`" ] ]; -makeInlineCodeCell[ s_String? LowerCaseQ ] := StyleBox[ unescapeInlineMarkdown @ s, "TI" ]; +makeInlineCodeCell[ s_String? LowerCaseQ ] := + StyleBox[ unescapeInlineMarkdown @ s, "TI" ]; -makeInlineCodeCell[ code_String ] /; $dynamicText := Cell[ - BoxData @ TemplateBox[ { stringToBoxes @ unescapeInlineMarkdown @ code }, "ChatCodeInlineTemplate" ], +makeInlineCodeCell[ code_String ] := Cell[ + BoxData @ TemplateBox[ { Cell[ unescapeInlineMarkdown @ code, Background -> None ] }, "ChatCodeInlineTemplate" ], "ChatCodeActive" ]; -makeInlineCodeCell[ code0_String ] := - With[ { code = unescapeInlineMarkdown @ code0 }, - If[ SyntaxQ @ code, - Cell[ - BoxData @ TemplateBox[ { stringToBoxes @ code }, "ChatCodeInlineTemplate" ], - "ChatCode", - Background -> None - ], - Cell[ - BoxData @ TemplateBox[ { Cell[ code, Background -> None ] }, "ChatCodeInlineTemplate" ], - "ChatCodeActive", - Background -> None - ] - ] - ]; - makeInlineCodeCell // endDefinition; (* ::**************************************************************************************************************:: *) @@ -2080,7 +2128,11 @@ attachment[ alt_String, key_String, expr_ ] := BoxData @ boxes, "ChatCode", "Input", - Background -> GrayLevel[ 1 ] + Background -> GrayLevel[ 1 ], + LanguageCategory -> "Input", + ShowAutoStyles -> True, + ShowStringCharacters -> True, + ShowSyntaxStyles -> True ]; handler = inlineInteractiveCodeCell[ display, Cell[ BoxData @ cachedBoxes @ expr, "Input" ] ]; codeBlockFrame[ Cell @ BoxData @ ToBoxes @ handler, expr ] @@ -2533,8 +2585,11 @@ stringToBoxes[ s_String ] /; $dynamicText := StringReplace[ $expressionURIPlaceholder ]; +stringToBoxes[ s_String /; StringMatchQ[ s, "\"" ~~ __ ~~ "\"" ] ] := + With[ { str = stringToBoxes @ StringTrim[ s, "\"" ] }, "\""<>str<>"\"" /; StringQ @ str ]; + stringToBoxes[ s_String ] := - adjustBoxSpacing @ stringToBoxes0 @ usingFrontEnd @ MathLink`CallFrontEnd @ FrontEnd`ReparseBoxStructurePacket @ s; + adjustBoxSpacing @ stringToBoxes0 @ reparseBoxStructurePacket @ s; stringToBoxes // endDefinition; @@ -2543,6 +2598,21 @@ stringToBoxes0 // beginDefinition; stringToBoxes0[ boxes_? boxDataQ ] := boxes; stringToBoxes0 // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*reparseBoxStructurePacket*) +reparseBoxStructurePacket // beginDefinition; + +reparseBoxStructurePacket[ string_String ] := Replace[ + usingFrontEnd @ MathLink`CallFrontEnd @ FrontEnd`ReparseBoxStructurePacket @ StyleBox[ + string, + ShowStringCharacters -> True + ], + StyleBox[ boxes_, ___ ] :> boxes +]; + +reparseBoxStructurePacket // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*boxDataQ*) @@ -2565,12 +2635,32 @@ boxSymbolQ // endDefinition; (*adjustBoxSpacing*) adjustBoxSpacing // beginDefinition; adjustBoxSpacing[ row: RowBox @ { "(*", ___, "*)" } ] := row; -adjustBoxSpacing[ RowBox[ items_List ] ] := RowBox[ adjustBoxSpacing /@ DeleteCases[ items, " " ] ]; adjustBoxSpacing[ "\n" ] := "\[IndentingNewLine]"; adjustBoxSpacing[ s_String ] /; $CloudEvaluation := Lookup[ $autoOperatorRenderings, s, s ]; +adjustBoxSpacing[ RowBox[ items_List ] ] := RowBox[ adjustBoxSpacing /@ adjustSequenceSpacing @ items ]; adjustBoxSpacing[ box_ ] := box; adjustBoxSpacing // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*adjustSequenceSpacing*) +adjustSequenceSpacing // beginDefinition; + +adjustSequenceSpacing[ items_List ] := SequenceReplace[ + items, + { + { $space, op: $infixOperators, $space } :> op, + { $space, op: $infixOperators } :> op, + { op: $infixOperators, $space } :> op, + { ",", $space } -> "," + } +]; + +adjustSequenceSpacing // endDefinition; + +$space = " "|" "|" "; +$infixOperators = "+"|"-"|"*"|"/"|"^"|"&&"|"||"|"=="|"==="|"!="|"=!="|"<"|"<="|">"|">="|"->"|":>"|"="|":="; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Alternate Chat Mode Styles*) diff --git a/Source/Chatbook/FrontEnd.wl b/Source/Chatbook/FrontEnd.wl index ab4f7a39..3349fb50 100644 --- a/Source/Chatbook/FrontEnd.wl +++ b/Source/Chatbook/FrontEnd.wl @@ -126,10 +126,21 @@ createFETask[ eval_ ] /; $cloudNotebooks := eval; createFETask[ eval_ ] := - With[ { inline = $InlineChat, state = $inlineChatState }, + With[ { inline = $InlineChat, state = $inlineChatState, id = $chatEvaluationID, t = $chatStartTime }, If[ $feTaskDebug, Internal`StuffBag[ $feTaskLog, <| "Task" -> Hold @ eval, "Created" -> AbsoluteTime[ ] |> ] ]; (* FIXME: This Block is a bit of a hack: *) - AppendTo[ $feTasks, Hold @ Block[ { $InlineChat = inline, $inlineChatState = state }, eval ] ]; + AppendTo[ + $feTasks, + Hold @ Block[ + { + $InlineChat = inline, + $inlineChatState = state, + $chatEvaluationID = id, + $chatStartTime = t + }, + eval + ] + ]; ++$feTaskCreationCount; ++$feTaskTrigger ]; @@ -646,24 +657,28 @@ cellPrint // endDefinition; (*cloudCellPrint*) cloudCellPrint // beginDefinition; -cloudCellPrint[ cell0_Cell ] := - Enclose @ Module[ { cellUUID, nbUUID, cell }, - cellUUID = CreateUUID[ ]; - nbUUID = ConfirmBy[ cloudNotebookUUID[ ], StringQ ]; - cell = Append[ DeleteCases[ cell0, ExpressionUUID -> _ ], ExpressionUUID -> cellUUID ]; - CellPrint @ cell; - CellObject[ cellUUID, nbUUID ] +cloudCellPrint[ cell_Cell ] := + With[ { obj = MathLink`CallFrontEnd @ FrontEnd`CellPrintReturnObject @ cell }, + obj /; MatchQ[ obj, _CellObject ] ]; -cloudCellPrint // endDefinition; +cloudCellPrint[ Cell[ a__, CellTags -> tags0_, b___ ] ] := Enclose[ + Module[ { uuid, tags, cell, obj }, + uuid = ConfirmBy[ CreateUUID[ ], StringQ, "UUID" ]; + tags = Select[ Flatten @ { tags0, uuid }, StringQ ]; + cell = Cell[ a, CellTags -> tags, b ]; + CellPrint @ cell; + obj = First @ ConfirmMatch[ Cells[ CellTags -> uuid ], { _CellObject }, "Cells" ]; + SetOptions[ obj, CellTags -> Replace[ tags, { uuid } -> Inherited ] ]; + obj + ], + throwInternalFailure +]; -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*cloudNotebookUUID*) -cloudNotebookUUID // beginDefinition; -cloudNotebookUUID[ ] := cloudNotebookUUID[ EvaluationNotebook[ ] ]; -cloudNotebookUUID[ NotebookObject[ _, uuid_String ] ] := uuid; -cloudNotebookUUID // endDefinition; +cloudCellPrint[ Cell[ a___ ] ] := + cloudCellPrint @ Cell[ a, CellTags -> { } ]; + +cloudCellPrint // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) @@ -750,6 +765,63 @@ $cloudCellFixes := $cloudCellFixes = Dispatch @ { StyleBox[ a_ ] :> a }; +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*cellReference*) +cellReference // beginDefinition; +cellReference[ cell_CellObject ] := Lookup[ $cellReferences, cell, createCellReference @ cell ]; +cellReference[ ref_String ] := Lookup[ $cellReferences, ref , findCellReference @ ref ]; +cellReference // endDefinition; + +$cellReferences = <| |>; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*createCellReference*) +createCellReference // beginDefinition; + +createCellReference[ cell_CellObject ] := + With[ { ref = tinyHash @ cell }, + $cellReferences[ cell ] = ref; + $cellReferences[ ref ] = cell; + ref + ]; + +createCellReference // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*findCellReference*) +findCellReference // beginDefinition; +findCellReference[ ref_String ] /; StringLength @ ref > $tinyHashLength := findCellReferenceInString @ ref; +findCellReference[ ref_String ] := Catch[ findNotebookCell[ ref ] /@ Notebooks[ ]; Missing[ "NotFound" ], $ref ]; +findCellReference // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*findCellReferenceInString*) +findCellReferenceInString // beginDefinition; +findCellReferenceInString[ s_String ] := findCellReferenceInString[ s, Select[ Keys @ $cellReferences, StringQ ] ]; +findCellReferenceInString[ s_String, refs: { ___String } ] := First[ StringCases[ s, refs, 1 ], Missing[ "NotFound" ] ]; +findCellReferenceInString // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*findNotebookCell*) +findNotebookCell // beginDefinition; +findNotebookCell[ ref_ ] := findNotebookCell[ ref, # ] &; +findNotebookCell[ ref_, nbo_ ] := checkCellReference[ ref ] /@ Cells @ nbo; +findNotebookCell // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*checkCellReference*) +checkCellReference // beginDefinition; +checkCellReference[ ref_ ] := checkCellReference[ ref, # ] &; +checkCellReference[ ref_, cell_CellObject ] := With[ { r = cellReference @ cell }, Throw[ cell, $ref ] /; ref === r ]; +checkCellReference[ _, _ ] := Null; +checkCellReference // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Notebooks*) @@ -813,17 +885,34 @@ tryInlineChatParent // endDefinition; (*notebookRead*) notebookRead // beginDefinition; notebookRead[ cells_ ] /; $cloudNotebooks := cloudNotebookRead @ cells; -notebookRead[ cells_ ] := NotebookRead @ cells; +notebookRead[ cells_ ] := notebookReadWithCellObjects @ cells; notebookRead // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*cloudNotebookRead*) cloudNotebookRead // beginDefinition; -cloudNotebookRead[ cells: { ___CellObject } ] := NotebookRead /@ cells; -cloudNotebookRead[ cell_ ] := NotebookRead @ cell; +cloudNotebookRead[ cells: { ___CellObject } ] := notebookReadWithCellObjects /@ cells; +cloudNotebookRead[ cell_ ] := notebookReadWithCellObjects @ cell; cloudNotebookRead // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*notebookReadWithCellObjects*) +notebookReadWithCellObjects // beginDefinition; +notebookReadWithCellObjects[ cell_CellObject ] := appendCellObject[ NotebookRead @ cell, cell ]; +notebookReadWithCellObjects[ cells: { ___CellObject } ] := appendCellObject[ NotebookRead @ cells, cells ]; +notebookReadWithCellObjects[ other_ ] := NotebookRead @ other; +notebookReadWithCellObjects // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*appendCellObject*) +appendCellObject // beginDefinition; +appendCellObject[ Cell[ a___ ], obj_CellObject ] := Cell[ a, CellObject -> obj ]; +appendCellObject[ cells: { ___Cell }, objs: { ___CellObject } ] := MapThread[ appendCellObject, { cells, objs } ]; +appendCellObject // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Boxes*) diff --git a/Source/Chatbook/Graphics.wl b/Source/Chatbook/Graphics.wl new file mode 100644 index 00000000..b85474ad --- /dev/null +++ b/Source/Chatbook/Graphics.wl @@ -0,0 +1,133 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`Graphics`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Argument Patterns*) +$$graphicsPattern = HoldPattern @ Alternatives[ + _System`AstroGraphics, + _GeoGraphics, + _Graphics, + _Graphics3D, + _Image, + _Image3D, + _Legended +]; + +$$definitelyNotGraphics = HoldPattern @ Alternatives[ + _Association, + _CloudObject, + _File, + _List, + _String, + _URL, + Null, + True|False +]; + +$$graphicsBoxIgnoredHead = HoldPattern @ Alternatives[ + BoxData, + Cell, + FormBox, + PaneBox, + StyleBox, + TagBox +]; + +$$graphicsBoxIgnoredTemplates = Alternatives[ + "Labeled", + "Legended" +]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Graphics Testing*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*graphicsQ*) +graphicsQ // beginDefinition; +graphicsQ[ $$graphicsPattern ] := True; +graphicsQ[ $$definitelyNotGraphics ] := False; +graphicsQ[ RawBoxes[ boxes_ ] ] := graphicsBoxQ @ Unevaluated @ boxes; +graphicsQ[ g_ ] := MatchQ[ Quiet @ Show @ Unevaluated @ g, $$graphicsPattern ]; +graphicsQ[ ___ ] := False; +graphicsQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*graphicsBoxQ*) +graphicsBoxQ // beginDefinition; +graphicsBoxQ[ _GraphicsBox|_Graphics3DBox ] := True; +graphicsBoxQ[ $$graphicsBoxIgnoredHead[ box_, ___ ] ] := graphicsBoxQ @ Unevaluated @ box; +graphicsBoxQ[ TemplateBox[ { box_, ___ }, $$graphicsBoxIgnoredTemplates, ___ ] ] := graphicsBoxQ @ Unevaluated @ box; +graphicsBoxQ[ RowBox[ boxes_List ] ] := AnyTrue[ boxes, graphicsBoxQ ]; +graphicsBoxQ[ TemplateBox[ boxes_List, "RowDefault", ___ ] ] := AnyTrue[ boxes, graphicsBoxQ ]; +graphicsBoxQ[ GridBox[ boxes_List, ___ ] ] := AnyTrue[ Flatten @ boxes, graphicsBoxQ ]; +graphicsBoxQ[ ___ ] := False; +graphicsBoxQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*validGraphicsQ*) +validGraphicsQ // beginDefinition; +validGraphicsQ[ g_? graphicsQ ] := getPinkBoxErrors @ Unevaluated @ g === { }; +validGraphicsQ[ ___ ] := False; +validGraphicsQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getPinkBoxErrors*) +getPinkBoxErrors // beginDefinition; +(* TODO: hook this up to evaluator outputs and CellToString to give feedback about pink boxes *) + +getPinkBoxErrors[ { } ] := + { }; + +getPinkBoxErrors[ cells: _CellObject | { __CellObject } ] := + getPinkBoxErrors @ NotebookRead @ cells; + +getPinkBoxErrors[ cells: _Cell | { __Cell } ] := + Module[ { nbo }, + UsingFrontEnd @ WithCleanup[ + nbo = NotebookPut[ Notebook @ Flatten @ { cells }, Visible -> False ], + SelectionMove[ nbo, All, Notebook ]; + MathLink`CallFrontEnd @ FrontEnd`GetErrorsInSelectionPacket @ nbo, + NotebookClose @ nbo + ] + ]; + +getPinkBoxErrors[ data: _TextData | _BoxData | { __BoxData } ] := + getPinkBoxErrors @ Cell @ data; + +getPinkBoxErrors[ exprs_List ] := + getPinkBoxErrors[ Cell @* BoxData /@ MakeBoxes /@ Unevaluated @ exprs ]; + +getPinkBoxErrors[ expr_ ] := + getPinkBoxErrors @ { Cell @ BoxData @ MakeBoxes @ expr }; + +getPinkBoxErrors // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*image2DQ*) +(* Matches against the head in addition to checking ImageQ to avoid passing Image3D when a 2D image is expected: *) +image2DQ // beginDefinition; +image2DQ[ _Image? ImageQ ] := True; +image2DQ[ _ ] := False; +image2DQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Handlers.wl b/Source/Chatbook/Handlers.wl index 6bffb647..3f9091bf 100644 --- a/Source/Chatbook/Handlers.wl +++ b/Source/Chatbook/Handlers.wl @@ -58,8 +58,8 @@ applyHandlerFunction[ settings_Association, name_String, args0_ ] := Enclose[ $ChatHandlerData = ConfirmBy[ addHandlerArguments @ args, AssociationQ, "AddHandlerArguments" ]; handler = Confirm[ getHandlerFunction[ settings, name ], "HandlerFunction" ]; handler @ KeyDrop[ $ChatHandlerData, $handlerDroppedParameters ] - ], - throwInternalFailure[ applyHandlerFunction[ settings, name, args0 ], ## ] & + ] // LogChatTiming[ name ], + throwInternalFailure ]; applyHandlerFunction // endDefinition; @@ -167,8 +167,8 @@ applyProcessingFunction[ settings_Association, name_String, args_HoldComplete, p ]; function = Confirm[ getProcessingFunction[ settings, name, default ], "ProcessingFunction" ]; function @@ args - ], - throwInternalFailure[ applyProcessingFunction[ settings, name, args, default ], ## ] & + ] // LogChatTiming[ name ], + throwInternalFailure ]; applyProcessingFunction[ settings_, name_, args: Except[ _HoldComplete ], params_, default_ ] := diff --git a/Source/Chatbook/InlineReferences.wl b/Source/Chatbook/InlineReferences.wl index 0dbc2242..53e3656f 100644 --- a/Source/Chatbook/InlineReferences.wl +++ b/Source/Chatbook/InlineReferences.wl @@ -19,7 +19,6 @@ Needs[ "Wolfram`Chatbook`" ]; Needs[ "Wolfram`Chatbook`Common`" ]; Needs[ "Wolfram`Chatbook`Personas`" ]; Needs[ "Wolfram`Chatbook`ResourceInstaller`" ]; -Needs[ "Wolfram`Chatbook`Serialization`" ]; diff --git a/Source/Chatbook/LLMUtilities.wl b/Source/Chatbook/LLMUtilities.wl new file mode 100644 index 00000000..f4aff9a4 --- /dev/null +++ b/Source/Chatbook/LLMUtilities.wl @@ -0,0 +1,222 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`LLMUtilities`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Configuration*) +$llmSynthesizeAuthentication = Automatic; (* TODO *) +$defaultLLMSynthesizeEvaluator = <| "Model" -> <| "Service" -> "OpenAI", "Name" -> "gpt-4o-mini" |> |>; (* TODO *) + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*LLM Utilities*) +$$llmPromptString = $$string | KeyValuePattern @ { "Type" -> "Text" , "Data" -> $$string }; +$$llmPromptGraphics = $$graphics | KeyValuePattern @ { "Type" -> "Image", "Data" -> $$graphics }; +$$llmPromptItem = $$llmPromptString | $$llmPromptGraphics; +$$llmPrompt = $$llmPromptItem | { $$llmPromptItem.. }; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*llmSynthesize*) +llmSynthesize // beginDefinition; + +llmSynthesize[ prompt: $$llmPrompt ] := + llmSynthesize[ prompt, <| |> ]; + +llmSynthesize[ prompt: $$llmPrompt, evaluator_Association ] := Enclose[ + ConfirmMatch[ llmSynthesize0[ prompt, evaluator, 1 ], Except[ "", _String ], "Result" ], + throwInternalFailure +]; + +llmSynthesize // endDefinition; + + +llmSynthesize0 // beginDefinition; + +llmSynthesize0[ prompt: $$llmPrompt, evaluator_Association, attempt_ ] := Enclose[ + Module[ { result, callback }, + result = $Failed; + callback = Function[ result = # ]; + TaskWait @ llmSynthesizeSubmit[ prompt, evaluator, callback ]; + If[ MatchQ[ result, Failure[ "InvalidResponse", _ ] ] && attempt <= 3, + Pause[ Exp @ attempt / E ]; + llmSynthesize0[ prompt, evaluator, attempt + 1 ], + result + ] + ], + throwInternalFailure +]; + +llmSynthesize0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*llmSynthesizeSubmit*) +llmSynthesizeSubmit // beginDefinition; + +llmSynthesizeSubmit[ prompt: $$llmPrompt, callback_ ] := + llmSynthesizeSubmit[ prompt, <| |>, callback ]; + +llmSynthesizeSubmit[ prompt0: $$llmPrompt, evaluator0_Association, callback_ ] := Enclose[ + Module[ { evaluator, prompt, messages, config, chunks, handlers, keys }, + + evaluator = ConfirmBy[ + <| $defaultLLMSynthesizeEvaluator, DeleteCases[ evaluator0, Automatic | _Missing ] |>, + AssociationQ, + "Evaluator" + ]; + + prompt = ConfirmMatch[ truncatePrompt[ prompt0, evaluator ], $$llmPrompt, "Prompt" ]; + messages = { <| "Role" -> "User", "Content" -> prompt |> }; + config = LLMConfiguration @ evaluator; + chunks = Internal`Bag[ ]; + + handlers = <| + "BodyChunkReceived" -> Function[ + Internal`StuffBag[ chunks, # ] + ], + "TaskFinished" -> Function[ + Module[ { data, strings }, + data = Internal`BagPart[ chunks, All ]; + $lastSynthesizeSubmitLog = data; + strings = extractBodyChunks @ data; + If[ ! MatchQ[ strings, { __String } ], + callback[ Failure[ "InvalidResponse", <| "Data" -> data |> ], #1 ], + With[ { s = StringJoin @ strings }, callback[ s, #1 ] ] + ] + ] + ] + |>; + + keys = { "BodyChunk", "BodyChunkProcessed", "StatusCode", "EventName" }; + + setServiceCaller @ LLMServices`ChatSubmit[ + messages, + config, + Authentication -> $llmSynthesizeAuthentication, + HandlerFunctions -> handlers, + HandlerFunctionsKeys -> keys, + "TestConnection" -> False + ] + ], + throwInternalFailure +]; + +llmSynthesizeSubmit // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*truncatePrompt*) +truncatePrompt // beginDefinition; + +truncatePrompt[ string_String, evaluator_ ] := stringTrimMiddle[ string, modelContextLimit @ evaluator ]; +truncatePrompt[ { strings___String }, evaluator_ ] := truncatePrompt[ StringJoin @ strings, evaluator ]; + +truncatePrompt[ prompts: { ($$string|$$graphics).. }, evaluator_ ] := Enclose[ + Module[ { stringCount, images, imageCount, budget, imageBudget, resized, imageTokens, stringBudget }, + + stringCount = Count[ prompts, _String ]; + images = Cases[ prompts, $$graphics ]; + imageCount = Length @ images; + budget = ConfirmBy[ modelContextLimit @ evaluator, IntegerQ, "Budget" ]; + imageBudget = Max[ 512, 2^(13 - imageCount) ]; + resized = Replace[ prompts, i: $$graphics :> resizePromptImage[ i, imageBudget ], { 1 } ]; + imageTokens = Total @ Cases[ resized, i: $$graphics :> imageTokenCount @ i ]; + + stringBudget = ConfirmMatch[ + Floor[ (budget - imageTokens) / stringCount ], + _Integer? Positive, + "StringBudget" + ]; + + ConfirmMatch[ + Replace[ resized, s_String :> stringTrimMiddle[ s, stringBudget ], { 1 } ], + { (_String|_Image).. }, + "Result" + ] + ], + throwInternalFailure +]; + +truncatePrompt[ prompts: { ___, _Association, ___ }, evaluator_ ] := + truncatePrompt[ Replace[ prompts, as_Association :> as[ "Data" ], { 1 } ], evaluator ]; + +truncatePrompt // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*resizePromptImage*) +resizePromptImage // beginDefinition; + +resizePromptImage[ image_ ] := resizePromptImage[ image, 4096 ]; + +resizePromptImage[ image_Image, max_Integer ] := Enclose[ + Module[ { dims, size }, + dims = ConfirmMatch[ ImageDimensions @ image, { _Integer, _Integer }, "Dimensions" ]; + size = ConfirmBy[ Max[ dims, max ], IntegerQ, "Max" ]; + If[ size > max, ImageResize[ image, { UpTo[ max ], UpTo[ max ] } ], image ] + ], + throwInternalFailure +]; + +resizePromptImage[ gfx: $$graphics, max_Integer ] := + resizePromptImage[ resizeMultimodalImage @ gfx, max ]; + +resizePromptImage // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*modelContextLimit*) +modelContextLimit // beginDefinition; +modelContextLimit[ KeyValuePattern[ "Model" -> model_ ] ] := modelContextLimit @ model; +modelContextLimit[ KeyValuePattern[ "Name" -> model_String ] ] := modelContextLimit @ model; +modelContextLimit[ "gpt-4-turbo"|"gpt-4o"|"gpt-4o-mini" ] := 200000; +modelContextLimit[ _ ] := 8000; +modelContextLimit // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*imageTokenCount*) +imageTokenCount // beginDefinition; +imageTokenCount[ img_Image ] := imageTokenCount @ ImageDimensions @ img; +imageTokenCount[ { w_Integer, h_Integer } ] := 85 + 170 * Ceiling[ h / 512 ] * Ceiling[ w / 512 ]; +imageTokenCount // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*extractBodyChunks*) +extractBodyChunks // beginDefinition; + +extractBodyChunks[ data_ ] := Enclose[ + ConfirmMatch[ DeleteCases[ Flatten @ { extractBodyChunks0 @ data }, "" ], { ___String }, "Result" ], + throwInternalFailure +]; + +extractBodyChunks // endDefinition; + + +extractBodyChunks0 // beginDefinition; +extractBodyChunks0[ content_String ] := content; +extractBodyChunks0[ content_List ] := extractBodyChunks /@ content; +extractBodyChunks0[ KeyValuePattern[ "BodyChunkProcessed" -> content_ ] ] := extractBodyChunks0 @ content; +extractBodyChunks0[ KeyValuePattern[ "ContentDelta" -> content_ ] ] := extractBodyChunks0 @ content; +extractBodyChunks0[ KeyValuePattern @ { "Type" -> "Text", "Data" -> content_ } ] := extractBodyChunks0 @ content; +extractBodyChunks0[ KeyValuePattern @ { } ] := { }; +extractBodyChunks0[ bag_Internal`Bag ] := extractBodyChunks0 @ Internal`BagPart[ bag, All ]; +extractBodyChunks0[ Null ] := { }; +extractBodyChunks0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Main.wl b/Source/Chatbook/Main.wl index 65f7a29a..b3dcace7 100644 --- a/Source/Chatbook/Main.wl +++ b/Source/Chatbook/Main.wl @@ -10,11 +10,15 @@ BeginPackage[ "Wolfram`Chatbook`" ]; `$AvailableTools; `$ChatAbort; `$ChatbookContexts; +`$ChatbookFilesDirectory; +`$ChatbookNames; +`$ChatbookProtectedNames; `$ChatEvaluationCell; `$ChatHandlerData; `$ChatNotebookEvaluation; `$ChatPost; `$ChatPre; +`$ChatTimingData; `$CurrentChatSettings; `$DefaultChatHandlerFunctions; `$DefaultChatProcessingFunctions; @@ -28,16 +32,21 @@ BeginPackage[ "Wolfram`Chatbook`" ]; `$ToolFunctions; `$WorkspaceChat; `AbsoluteCurrentChatSettings; +`AddChatToSearchIndex; `AppendURIInstructions; `BasePrompt; `CachedBoxes; `CellToChatMessage; +`CellToString; `Chatbook; `ChatbookAction; +`ChatbookFilesDirectory; `ChatCellEvaluate; +`ChatMessageToCell; `CreateChatDrivenNotebook; `CreateChatNotebook; `CurrentChatSettings; +`DeleteChat; `DisplayBase64Boxes; `EnableCodeAssistance; `ExplodeCell; @@ -45,16 +54,28 @@ BeginPackage[ "Wolfram`Chatbook`" ]; `FormatToolCall; `FormatToolResponse; `FormatWolframAlphaPods; +`GenerateChatTitle; +`GenerateChatTitleAsynchronous; +`GetAttachments; `GetChatHistory; `GetExpressionURI; `GetExpressionURIs; `InlineTemplateBoxes; `InvalidateServiceCache; +`ListSavedChats; +`LoadChat; +`LogChatTiming; `MakeExpressionURI; +`RebuildChatSearchIndex; +`RelatedDocumentation; +`RelatedWolframAlphaQueries; `SandboxLinguisticAssistantData; +`SaveChat; +`SearchChats; `SetModel; `SetToolOptions; `ShowCodeAssistance; +`ShowContentSuggestions; `StringToBoxes; `WriteChatOutputCell; @@ -92,11 +113,14 @@ Chatbook is a symbol for miscellaneous chat notebook messages.\ $ChatbookContexts = { "Wolfram`Chatbook`", "Wolfram`Chatbook`Actions`", + "Wolfram`Chatbook`ChatbookFiles`", "Wolfram`Chatbook`ChatGroups`", "Wolfram`Chatbook`ChatHistory`", "Wolfram`Chatbook`ChatMessages`", + "Wolfram`Chatbook`ChatMessageToCell`", "Wolfram`Chatbook`ChatModes`", "Wolfram`Chatbook`ChatState`", + "Wolfram`Chatbook`ChatTitle`", "Wolfram`Chatbook`CloudToolbar`", "Wolfram`Chatbook`Common`", "Wolfram`Chatbook`CreateChatNotebook`", @@ -108,21 +132,26 @@ $ChatbookContexts = { "Wolfram`Chatbook`Feedback`", "Wolfram`Chatbook`Formatting`", "Wolfram`Chatbook`FrontEnd`", + "Wolfram`Chatbook`Graphics`", "Wolfram`Chatbook`Handlers`", "Wolfram`Chatbook`InlineReferences`", + "Wolfram`Chatbook`LLMUtilities`", "Wolfram`Chatbook`Menus`", "Wolfram`Chatbook`Models`", "Wolfram`Chatbook`PersonaManager`", "Wolfram`Chatbook`Personas`", "Wolfram`Chatbook`PreferencesContent`", "Wolfram`Chatbook`PreferencesUtils`", + "Wolfram`Chatbook`PromptGenerators`", "Wolfram`Chatbook`Prompting`", "Wolfram`Chatbook`ResourceInstaller`", "Wolfram`Chatbook`Sandbox`", + "Wolfram`Chatbook`Search`", "Wolfram`Chatbook`SendChat`", "Wolfram`Chatbook`Serialization`", "Wolfram`Chatbook`Services`", "Wolfram`Chatbook`Settings`", + "Wolfram`Chatbook`Storage`", "Wolfram`Chatbook`ToolManager`", "Wolfram`Chatbook`Tools`", "Wolfram`Chatbook`UI`", @@ -131,59 +160,90 @@ $ChatbookContexts = { Scan[ Needs[ # -> None ] &, $ChatbookContexts ]; +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Names*) +$ChatbookNames := $ChatbookNames = + Block[ { $Context, $ContextPath }, + Union[ Names[ "Wolfram`Chatbook`*" ], Names[ "Wolfram`Chatbook`*`*" ] ] + ]; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Protected Symbols*) -Protect[ - $AutomaticAssistance, - $ChatbookContexts, - $ChatNotebookEvaluation, - $CurrentChatSettings, - $DefaultChatHandlerFunctions, - $DefaultChatProcessingFunctions, - $DefaultModel, - $DefaultToolOptions, - $DefaultTools, - $InlineChat, - $InstalledTools, - $ToolFunctions, - $WorkspaceChat, - AbsoluteCurrentChatSettings, - AppendURIInstructions, - BasePrompt, - CachedBoxes, - CellToChatMessage, - Chatbook, - ChatbookAction, - ChatCellEvaluate, - CreateChatDrivenNotebook, - CreateChatNotebook, - CurrentChatSettings, - DisplayBase64Boxes, - EnableCodeAssistance, - ExplodeCell, - FormatChatOutput, - FormatToolCall, - FormatToolResponse, - FormatWolframAlphaPods, - GetChatHistory, - GetExpressionURI, - GetExpressionURIs, - InlineTemplateBoxes, - MakeExpressionURI, - SandboxLinguisticAssistantData, - SetModel, - SetToolOptions, - ShowCodeAssistance, - StringToBoxes, - WriteChatOutputCell -]; +$ChatbookProtectedNames = "Wolfram`Chatbook`" <> # & /@ { + "$AutomaticAssistance", + "$ChatbookContexts", + "$ChatbookFilesDirectory", + "$ChatNotebookEvaluation", + "$ChatTimingData", + "$CurrentChatSettings", + "$DefaultChatHandlerFunctions", + "$DefaultChatProcessingFunctions", + "$DefaultModel", + "$DefaultToolOptions", + "$DefaultTools", + "$InlineChat", + "$InstalledTools", + "$ToolFunctions", + "$WorkspaceChat", + "AbsoluteCurrentChatSettings", + "AddChatToSearchIndex", + "AppendURIInstructions", + "BasePrompt", + "CachedBoxes", + "CellToChatMessage", + "CellToString", + "Chatbook", + "ChatbookAction", + "ChatbookFilesDirectory", + "ChatCellEvaluate", + "ChatMessageToCell", + "CreateChatDrivenNotebook", + "CreateChatNotebook", + "CurrentChatSettings", + "DeleteChat", + "DisplayBase64Boxes", + "EnableCodeAssistance", + "ExplodeCell", + "FormatChatOutput", + "FormatToolCall", + "FormatToolResponse", + "FormatWolframAlphaPods", + "GenerateChatTitle", + "GenerateChatTitleAsynchronous", + "GetAttachments", + "GetChatHistory", + "GetExpressionURI", + "GetExpressionURIs", + "InlineTemplateBoxes", + "ListSavedChats", + "LoadChat", + "LogChatTiming", + "MakeExpressionURI", + "RebuildChatSearchIndex", + "RelatedDocumentation", + "RelatedWolframAlphaQueries", + "SandboxLinguisticAssistantData", + "SaveChat", + "SearchChats", + "SetModel", + "SetToolOptions", + "ShowCodeAssistance", + "ShowContentSuggestions", + "StringToBoxes", + "WriteChatOutputCell" +}; + +Protect @@ $ChatbookProtectedNames; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Package Footer*) addToMXInitialization[ $ChatbookContexts; + $ChatbookNames; + SetAttributes[ Evaluate @ Names[ "Wolfram`Chatbook`*" ], ReadProtected ]; ]; mxInitialize[ ]; diff --git a/Source/Chatbook/Models.wl b/Source/Chatbook/Models.wl index ed87d1b1..1c929c53 100644 --- a/Source/Chatbook/Models.wl +++ b/Source/Chatbook/Models.wl @@ -106,18 +106,25 @@ $fallbackModelList = { "gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-4" }; (* ::Subsection::Closed:: *) (*chatModelQ*) chatModelQ // beginDefinition; -chatModelQ[ _? (modelContains[ "instruct" ]) ] := False; -chatModelQ[ _? (modelContains[ StartOfString~~("gpt"|"ft:gpt") ]) ] := True; +chatModelQ[ wordsPattern[ "instruct"|"realtime" ] ] := False; +chatModelQ[ wordsPattern[ StartOfString~~("gpt"|"ft:gpt"|"chatgpt-4o") ] ] := True; chatModelQ[ _String ] := False; chatModelQ // endDefinition; (* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*modelContains*) -modelContains // beginDefinition; -modelContains[ patt_ ] := modelContains[ #, patt ] &; -modelContains[ m_String, patt_ ] := StringContainsQ[ m, WordBoundary~~patt~~WordBoundary, IgnoreCase -> True ]; -modelContains // endDefinition; +(* ::Subsection::Closed:: *) +(*o1ModelQ*) +o1ModelQ // beginDefinition; + +o1ModelQ[ model_ ] := Enclose[ + o1ModelQ[ model ] = StringContainsQ[ + ConfirmBy[ toModelName @ model, StringQ, "Name" ], + WordBoundary~~"o1"~~WordBoundary + ], + throwInternalFailure +]; + +o1ModelQ // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) @@ -127,11 +134,24 @@ modelName[ KeyValuePattern[ "Name" -> name_String ] ] := modelName @ name; modelName[ name_String ] := toModelName @ name; modelName // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*serviceName*) +serviceName // beginDefinition; +serviceName[ KeyValuePattern[ "Model" -> model_ ] ] := serviceName @ model; +serviceName[ { service_String, _String | $$unspecified } ] := service; +serviceName[ KeyValuePattern[ "Service" -> service_String ] ] := service; +serviceName[ _String | _Association | $$unspecified ] := "OpenAI"; +serviceName // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*toModelName*) toModelName // beginDefinition; +toModelName[ KeyValuePattern[ "Model" -> model_ ] ] := + toModelName @ model; + toModelName[ KeyValuePattern @ { "Service" -> service_, "Name"|"Model" -> model_ } ] := toModelName @ { service, model }; @@ -193,7 +213,7 @@ multimodalModelQ[ "gpt-4-turbo" ] := multimodalModelQ[ name_String? StringQ ] /; StringStartsQ[ name, "claude-3" ] := True; -multimodalModelQ[ name_String? StringQ ] /; StringStartsQ[ name, "gpt-4o"|"gpt-4o-mini" ] := +multimodalModelQ[ name_String? StringQ ] /; StringStartsQ[ name, "gpt-4o"|"gpt-4o-mini"|"chatgpt-4o" ] := True; multimodalModelQ[ name_String? StringQ ] /; StringStartsQ[ name, "gpt-4-turbo-" ] := @@ -219,6 +239,7 @@ modelNameData[ data: KeyValuePattern @ { "BaseName" -> _String, "Date" -> _? modelDateSpecQ | None, "Preview" -> True|False, + "Family" -> _String|None, "FineTuned" -> True|False, "FineTuneName" -> _String|None, "Organization" -> _String|None, @@ -237,6 +258,7 @@ modelNameData[ model0_ ] := Enclose[ "Name" -> model, "Date" -> None, "Preview" -> False, + "Family" -> None, "FineTuned" -> False, "FineTuneName" -> None, "Organization" -> None, @@ -254,6 +276,7 @@ modelNameData[ model0_ ] := Enclose[ data = <| defaults, data |>; data[ "DisplayName" ] = ConfirmBy[ createModelDisplayName @ data, StringQ, "DisplayName" ]; + data[ "Family" ] = ConfirmMatch[ chooseModelFamily @ data, _String | None, "Family" ]; data //= KeySort; modelNameData[ model0 ] = ConfirmBy[ data, AssociationQ, "FullData" ] @@ -272,6 +295,9 @@ modelNameData0[ model_String ] := "-"|" " ]; +modelNameData0[ { before___, "chatgpt", after___ } ] := + modelNameData0 @ { before, "ChatGPT", after }; + modelNameData0[ { "gpt", rest___ } ] := modelNameData0 @ { "GPT", rest }; @@ -301,11 +327,43 @@ modelNameData0[ { "GPT", version_String, rest___ } ] /; StringStartsQ[ version, modelNameData0[ { "GPT-4o", rest___ } ] := modelNameData0 @ { "GPT-4", "Omni", rest }; +modelNameData0[ { before___, gpt_String, "4o", after___ } ] /; StringEndsQ[ gpt, "gpt", IgnoreCase -> True ] := + modelNameData0 @ { before, gpt<>"-4", "Omni", after }; + modelNameData0[ parts: { __String } ] := <| "BaseName" -> StringRiffle @ Capitalize @ parts |>; modelNameData0 // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*chooseModelFamily*) +$$version = ("v"|"") ~~ DigitCharacter.. ~~ Repeated[ "." ~~ DigitCharacter.., { 0, Infinity } ]; +$$parameterCount0 = DigitCharacter.. ~~ Repeated[ "." ~~ DigitCharacter.., { 0, Infinity } ] ~~ ("b"|"m"|""); +$$parameterCount = ((DigitCharacter.. ~~ "x") | "") ~~ $$parameterCount0; +$$versionOrParams = $$version | $$parameterCount | ""; + +chooseModelFamily // beginDefinition; +chooseModelFamily[ as_Association ] := chooseModelFamily @ as[ "Name" ]; +chooseModelFamily[ name_String ] := chooseModelFamily[ name ] = chooseModelFamily0 @ name; +chooseModelFamily // endDefinition; + +chooseModelFamily0 // beginDefinition; +(* cSpell: ignore Qwen, Nemotron *) +chooseModelFamily0[ wordsPattern[ "Phi" ~~ $$versionOrParams ] ] := "Phi"; +chooseModelFamily0[ wordsPattern[ "Llama" ~~ $$versionOrParams ] ] := "Llama"; +chooseModelFamily0[ wordsPattern[ "Gemma" ~~ $$versionOrParams ] ] := "Gemma"; +chooseModelFamily0[ wordsPattern[ "CodeGemma" ~~ $$versionOrParams ] ] := "Gemma"; +chooseModelFamily0[ wordsPattern[ "Qwen" ~~ $$versionOrParams ] ] := "Qwen"; +chooseModelFamily0[ wordsPattern[ "Nemotron" ~~ $$versionOrParams ] ] := "Nemotron"; +chooseModelFamily0[ wordsPattern[ "Mistral" ~~ $$versionOrParams ] ] := "Mistral"; + +chooseModelFamily0[ wordsPattern[ { "DeepSeek", "Coder", $$versionOrParams } ] ] := "DeepSeekCoder"; + +chooseModelFamily0[ _String ] := None; + +chooseModelFamily0 // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*modelDateSpecQ*) @@ -481,7 +539,7 @@ modelIcon[ name_String ] /; StringStartsQ[ name, "ft:" ] := modelIcon[ gpt_String ] /; StringStartsQ[ gpt, "gpt-3.5" ] := RawBoxes @ TemplateBox[ { }, "ModelGPT35" ]; -modelIcon[ gpt_String ] /; StringStartsQ[ gpt, "gpt-4" ] := +modelIcon[ gpt_String ] /; StringStartsQ[ gpt, "gpt-4"|"chatgpt-4" ] := RawBoxes @ TemplateBox[ { }, "ModelGPT4" ]; modelIcon[ name_String ] := diff --git a/Source/Chatbook/PersonaManager.wl b/Source/Chatbook/PersonaManager.wl index c82af5b5..6c824aa5 100644 --- a/Source/Chatbook/PersonaManager.wl +++ b/Source/Chatbook/PersonaManager.wl @@ -69,6 +69,14 @@ CreatePersonaManagerPanel[ ] := DynamicModule[{favorites, delimColor}, Appearance -> "Suppressed", BaselinePosition -> Baseline, Method -> "Queued" + ], + Button[ + grayDialogButtonLabel @ tr[ "PersonaManagerInstallFromFile" ], + If[ $CloudEvaluation, SetOptions[ EvaluationNotebook[ ], DockedCells -> Inherited ] ]; + Block[ { PrintTemporary }, ResourceInstallFromFile[ "Prompt" ] ], + Appearance -> "Suppressed", + BaselinePosition -> Baseline, + Method -> "Queued" ] } } @@ -146,7 +154,7 @@ CreatePersonaManagerPanel[ ] := DynamicModule[{favorites, delimColor}, { 2 -> True, 4 -> True, - -2 -> Directive[delimColor, AbsoluteThickness[5]] + -2 -> Directive[AbsoluteThickness[5]] }, { 3 -> True diff --git a/Source/Chatbook/Personas.wl b/Source/Chatbook/Personas.wl index 6a927402..e72671d4 100644 --- a/Source/Chatbook/Personas.wl +++ b/Source/Chatbook/Personas.wl @@ -186,79 +186,98 @@ fixFEResourceBoxes // endDefinition; (*loadPacletPersonas*) loadPacletPersonas // beginDefinition; -loadPacletPersonas[ paclet_PacletObject ] := loadPacletPersonas[ paclet[ "Name" ], paclet[ "Version" ], paclet ]; +loadPacletPersonas[ paclet_PacletObject ] := + loadPacletPersonas[ paclet[ "Name" ], paclet[ "Version" ], paclet ]; loadPacletPersonas[ name_, version_, paclet_ ] := loadPacletPersonas[ name, version, _ ] = - Handle[_Failure] @ Module[{ - extensions - }, - Needs["PacletTools`" -> None]; - - extensions = RaiseConfirmMatch[ - PacletTools`PacletExtensions[paclet, "LLMConfiguration"], - {{_String, _Association}...} - ]; - - Map[ - extension |-> loadPersonaFromPacletExtension[ - paclet, - PacletTools`PacletExtensionDirectory[paclet, extension], - extension - ], - extensions - ] + Cases[ + Flatten @ Cases[ + paclet[ "StructuredExtensions" ], + { "LLMConfiguration", as_ } :> loadPersonasFromPacletExtension[ paclet, as ] + ], + HoldPattern[ _String -> _Association ] ]; loadPacletPersonas // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*loadPersonasFromPacletExtension*) +loadPersonasFromPacletExtension // beginDefinition; + +loadPersonasFromPacletExtension[ paclet_, extensionInfo_Association ] := + loadPersonasFromPacletExtension[ paclet, extensionInfo, Lookup[ extensionInfo, "Personas" ] ]; + +loadPersonasFromPacletExtension[ paclet_, extensionInfo_, personas_List ] := + Cases[ + Flatten[ loadPersonaFromPacletExtension[ paclet, extensionInfo, # ] & /@ personas ], + HoldPattern[ _String -> _Association ] + ]; + +loadPersonasFromPacletExtension // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*loadPersonaFromPacletExtension*) loadPersonaFromPacletExtension // beginDefinition; -loadPersonaFromPacletExtension[ - paclet_?PacletObjectQ, - extensionDirectory_?StringQ, - {"LLMConfiguration", options_?AssociationQ} -] := Handle[_Failure] @ Module[{ - personas = Lookup[options, "Personas"] -}, - RaiseConfirmMatch[personas, {___?StringQ}]; - - Map[ - personaName |-> ( - (* Note: - Stop errors from propagating upwards so that a failure to load - any one persona doesn't prevent other, valid, personas from - being loaded and returned. *) - personaName -> Handle[_Failure] @ loadPersonaFromDirectory[ - paclet, - personaName, - FileNameJoin[{extensionDirectory, "Personas", personaName}] - ] - ), - personas - ] -]; +loadPersonaFromPacletExtension[ paclet_, extensionInfo_, persona: KeyValuePattern[ "Symbol" -> _String ] ] := + loadPersonaFromSymbol[ paclet, extensionInfo, persona ]; + +loadPersonaFromPacletExtension[ paclet_, extensionInfo_, persona_String ] := + loadPersonaFromName[ paclet, extensionInfo, persona ]; loadPersonaFromPacletExtension // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*loadPersonaFromSymbol*) +loadPersonaFromSymbol // beginDefinition; + +(* FIXME: Need to finish loading these when actually referenced anywhere *) +loadPersonaFromSymbol[ _, _, persona: KeyValuePattern[ "Name" -> name_String ] ] := + name -> <| persona, "Hidden" -> True, "Loaded" -> False |>; + +loadPersonaFromSymbol // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*loadPersonaFromName*) +loadPersonaFromName // beginDefinition; + +loadPersonaFromName[ paclet_, extensionInfo_Association, name_String ] := + With[ { extensionDir = pacletExtensionDirectory[ paclet, { "LLMConfiguration", extensionInfo } ] }, + name -> loadPersonaFromDirectory[ paclet, name, FileNameJoin @ { extensionDir, "Personas", name } ] + ]; + +loadPersonaFromName // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*pacletExtensionDirectory*) +pacletExtensionDirectory // beginDefinition; + +pacletExtensionDirectory[ paclet_, extension_ ] := + Module[ { dir }, + Needs[ "PacletTools`" -> None ]; + dir = PacletTools`PacletExtensionDirectory[ paclet, extension ]; + If[ TrueQ @ Wolfram`ChatbookInternal`$BuildingMX, + dir, + pacletExtensionDirectory[ paclet, extension ] = dir + ] + ]; + +pacletExtensionDirectory // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*loadPersonaFromDirectory*) loadPersonaFromDirectory // beginDefinition; loadPersonaFromDirectory[ paclet_PacletObject, personaName_, dir_? StringQ ] := Enclose[ - Module[ { icon, config, origin, prompts, extra }, - - If[ ! DirectoryQ @ dir, - Raise[ - ChatbookError, - <| "PersonaDirectory" -> dir |>, - "Persona does not exist in expected directory: ``", - InputForm @ dir - ]; - ]; + Catch @ Module[ { icon, config, origin, prompts, extra }, + + If[ ! DirectoryQ @ dir, Throw @ messageFailure[ "PersonaDirectoryNotFound", personaName, dir ] ]; icon = FileNameJoin @ { dir, "Icon.wl" }; config = FileNameJoin @ { dir, "LLMConfiguration.wl" }; diff --git a/Source/Chatbook/PreferencesContent.wl b/Source/Chatbook/PreferencesContent.wl index 1e0d5605..bb59009f 100644 --- a/Source/Chatbook/PreferencesContent.wl +++ b/Source/Chatbook/PreferencesContent.wl @@ -472,6 +472,9 @@ makeModelSelector0[ services_Association? AssociationQ ] := Enclose[ throwInternalFailure ]; +makeModelSelector0[ failure: HoldPattern @ Failure[ LLMServices`LLMServiceInformation, ___ ] ] := + Pane[ failure, ImageSize -> { $preferencesWidth-50, Automatic } ]; + makeModelSelector0 // endDefinition; (* ::**************************************************************************************************************:: *) @@ -1084,8 +1087,12 @@ makeToolCallFrequencySelector // endDefinition; (* ::Subsection::Closed:: *) (*servicesSettingsPanel*) servicesSettingsPanel // beginDefinition; +servicesSettingsPanel[ ] := Catch[ servicesSettingsPanel0[ ], $servicesSettingsTag ]; +servicesSettingsPanel // endDefinition; + +servicesSettingsPanel0 // beginDefinition; -servicesSettingsPanel[ ] := Enclose[ +servicesSettingsPanel0[ ] := Enclose[ Module[ { settingsLabel, settings, serviceGrid }, settingsLabel = subsectionText @ tr[ "PreferencesContentSubsectionRegisteredServices" ]; @@ -1109,7 +1116,7 @@ servicesSettingsPanel[ ] := Enclose[ throwInternalFailure ]; -servicesSettingsPanel // endDefinition; +servicesSettingsPanel0 // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) @@ -1128,7 +1135,7 @@ makeServiceGrid[ ] := Grid[ Spacer[ 1 ] } }, - KeyValueMap[ makeServiceGridRow, DeleteCases[ $availableServices, KeyValuePattern[ "Hidden" -> True ] ] ] + makeServiceGridRows @ $availableServices ], Alignment -> { Left, Baseline }, Background -> { { }, { GrayLevel[ 0.898 ], { White } } }, @@ -1140,6 +1147,19 @@ makeServiceGrid[ ] := Grid[ makeServiceGrid // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*makeServiceGridRows*) +makeServiceGridRows // beginDefinition; + +makeServiceGridRows[ services_Association ] := + KeyValueMap[ makeServiceGridRow, DeleteCases[ services, KeyValuePattern[ "Hidden" -> True ] ] ]; + +makeServiceGridRows[ failure: HoldPattern @ Failure[ LLMServices`LLMServiceInformation, ___ ] ] := + Throw[ Pane[ failure, ImageSize -> { $preferencesWidth-50, Automatic } ], $servicesSettingsTag ]; + +makeServiceGridRows // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*makeServiceGridRow*) diff --git a/Source/Chatbook/PromptGenerators/Common.wl b/Source/Chatbook/PromptGenerators/Common.wl new file mode 100644 index 00000000..f1ba4973 --- /dev/null +++ b/Source/Chatbook/PromptGenerators/Common.wl @@ -0,0 +1,30 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`PromptGenerators`Common`" ]; + +HoldComplete[ + `$$prompt, + `getSmallContextString, + `insertContextPrompt, + `vectorDBSearch +]; + +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Argument Patterns*) +$$prompt = $$string | { $$string... } | $$chatMessages; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; \ No newline at end of file diff --git a/Source/Chatbook/PromptGenerators/DefaultPromptGenerators.wl b/Source/Chatbook/PromptGenerators/DefaultPromptGenerators.wl new file mode 100644 index 00000000..42b4fd55 --- /dev/null +++ b/Source/Chatbook/PromptGenerators/DefaultPromptGenerators.wl @@ -0,0 +1,139 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`PromptGenerators`DefaultPromptGenerators`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; +Needs[ "Wolfram`Chatbook`PromptGenerators`Common`" ]; + +HoldComplete[ + System`LLMPromptGenerator +]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*DefaultPromptGenerators*) +$defaultPromptGenerators := $defaultPromptGenerators = <| + "RelatedDocumentation" -> LLMPromptGenerator[ relatedDocumentationGenerator, "Messages" ](*, + "RelatedWolframAlphaQueries" -> LLMPromptGenerator[ relatedWolframAlphaQueriesGenerator, "Messages" ]*) +|>; + +(* TODO: update RelatedWolframAlphaQueries to support same argument types as RelatedDocumentation *) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*relatedDocumentationGenerator*) +relatedDocumentationGenerator // beginDefinition; + +relatedDocumentationGenerator[ messages: $$chatMessages ] := + If[ TrueQ[ $InlineChat || $WorkspaceChat ], (* TODO: define a flag for when using Code Assistance instead of this *) + LogChatTiming @ RelatedDocumentation[ messages, "Prompt", MaxItems -> 20, "FilterResults" -> True ], + LogChatTiming @ RelatedDocumentation[ messages, "Prompt", MaxItems -> 5, "FilterResults" -> False ] + ]; + +relatedDocumentationGenerator // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*relatedWolframAlphaQueriesGenerator*) +relatedWolframAlphaQueriesGenerator // beginDefinition; + +relatedWolframAlphaQueriesGenerator[ messages: $$chatMessages ] := + If[ TrueQ[ $InlineChat || $WorkspaceChat ], + LogChatTiming @ RelatedWolframAlphaQueries[ messages, "Prompt", MaxItems -> 20, "FilterResults" -> True ], + LogChatTiming @ RelatedWolframAlphaQueries[ messages, "Prompt", MaxItems -> 5, "FilterResults" -> False ] + ]; + +relatedWolframAlphaQueriesGenerator // endDefinition; + +(* TODO: prompt generator selectors that work like tool selections *) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*applyPromptGenerators*) +applyPromptGenerators // beginDefinition; + +applyPromptGenerators[ settings_Association, messages_ ] := + applyPromptGenerators[ settings, settings[ "PromptGenerators" ], messages ]; + +applyPromptGenerators[ settings_, generators0_, messages: $$chatMessages ] := Enclose[ + Catch @ Module[ { generators, data, prompts }, + + generators = ConfirmMatch[ + LogChatTiming[ toPromptGenerator /@ Flatten @ { generators0 }, "LLMPromptGenerators" ], + { ___LLMPromptGenerator }, + "Generators" + ]; + + If[ generators === { }, Throw @ { } ]; + + data = ConfirmBy[ makePromptGeneratorData[ settings, messages ], AssociationQ, "Data" ]; + prompts = ConfirmMatch[ applyPromptGenerator[ #, data ] & /@ generators, { $$string... }, "Prompts" ]; + + DeleteCases[ prompts, "" ] + ] // LogChatTiming[ "ApplyPromptGenerators" ], + throwInternalFailure +]; + +applyPromptGenerators // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*toPromptGenerator*) +toPromptGenerator // beginDefinition; +toPromptGenerator[ ___ ] /; $VersionNumber < 14.1 := Nothing; +toPromptGenerator[ name_String ] := toPromptGenerator @ $defaultPromptGenerators @ name; +toPromptGenerator[ generator_LLMPromptGenerator ] := generator; +toPromptGenerator // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*makePromptGeneratorData*) +makePromptGeneratorData // beginDefinition; + +(* TODO: build the full spec supported by LLMPromptGenerator: + * Input + * Messages + * LLMEvaluator + * ChatObject + * { spec1, spec2, ... } +*) +makePromptGeneratorData[ settings_, messages: { ___, KeyValuePattern[ "Content" -> input_ ] } ] := <| + "Input" -> input, + "Messages" -> messages +|>; + +makePromptGeneratorData // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*applyPromptGenerator*) +applyPromptGenerator // beginDefinition; + +applyPromptGenerator[ gen_LLMPromptGenerator, data_Association ] := + formatGeneratedPrompt @ LogChatTiming[ gen @ data, "ApplyPromptGenerator" ]; + +applyPromptGenerator // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*formatGeneratedPrompt*) +formatGeneratedPrompt // beginDefinition; +formatGeneratedPrompt[ string_String ] := string; +formatGeneratedPrompt[ content_List ] := StringJoin[ formatGeneratedPrompt /@ content ]; +formatGeneratedPrompt[ KeyValuePattern @ { "Type" -> "Text", "Data" -> data_ } ] := TextString @ data; +formatGeneratedPrompt[ KeyValuePattern @ { "Type" -> "Image", "Data" -> image_? image2DQ } ] := image; +formatGeneratedPrompt[ _Missing | None ] := ""; +formatGeneratedPrompt[ expr_ ] := FormatToolResponse @ expr; +formatGeneratedPrompt // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/PromptGenerators/EmbeddingContext.wl b/Source/Chatbook/PromptGenerators/EmbeddingContext.wl new file mode 100644 index 00000000..961e3dde --- /dev/null +++ b/Source/Chatbook/PromptGenerators/EmbeddingContext.wl @@ -0,0 +1,50 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`PromptGenerators`EmbeddingContext`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; +Needs[ "Wolfram`Chatbook`PromptGenerators`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Config*) +$smallContextMessageCount = 10; +$smallContextStringLength = 8000; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Convert Chat Messages to String*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getSmallContextString*) +getSmallContextString // beginDefinition; + +getSmallContextString // Options = { "IncludeSystemMessage" -> False }; + +getSmallContextString[ messages0: { ___Association }, opts: OptionsPattern[ ] ] := Enclose[ + Catch @ Module[ { messages, string }, + messages = Reverse @ Take[ Reverse @ messages0, UpTo[ $smallContextMessageCount ] ]; + If[ messages === { }, Throw[ "" ] ]; + string = ConfirmBy[ messagesToString[ messages, opts ], StringQ, "String" ]; + If[ StringLength @ string > $smallContextStringLength, + StringTake[ string, { -$smallContextStringLength, -1 } ], + string + ] + ], + throwInternalFailure +]; + +getSmallContextString // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/PromptGenerators/PromptGenerators.wl b/Source/Chatbook/PromptGenerators/PromptGenerators.wl new file mode 100644 index 00000000..2d1fcb6e --- /dev/null +++ b/Source/Chatbook/PromptGenerators/PromptGenerators.wl @@ -0,0 +1,33 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`PromptGenerators`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Load Subcontexts*) +$subcontexts = { + "Wolfram`Chatbook`PromptGenerators`Common`", + "Wolfram`Chatbook`PromptGenerators`DefaultPromptGenerators`", + "Wolfram`Chatbook`PromptGenerators`EmbeddingContext`", + "Wolfram`Chatbook`PromptGenerators`RelatedDocumentation`", + "Wolfram`Chatbook`PromptGenerators`RelatedWolframAlphaQueries`", + "Wolfram`Chatbook`PromptGenerators`VectorDatabases`" +}; + +Scan[ Needs[ # -> None ] &, $subcontexts ]; + +$ChatbookContexts = Union[ $ChatbookContexts, $subcontexts ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/PromptGenerators/RelatedDocumentation.wl b/Source/Chatbook/PromptGenerators/RelatedDocumentation.wl new file mode 100644 index 00000000..e2e125b0 --- /dev/null +++ b/Source/Chatbook/PromptGenerators/RelatedDocumentation.wl @@ -0,0 +1,520 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`PromptGenerators`RelatedDocumentation`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; +Needs[ "Wolfram`Chatbook`PromptGenerators`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Configuration*) +$documentationSnippetBaseURL = "https://www.wolframcloud.com/obj/wolframai-content/DocumentationSnippets/Text"; + +$snippetsCacheDirectory := $snippetsCacheDirectory = ChatbookFilesDirectory[ "DocumentationSnippets" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*RelatedDocumentation*) +RelatedDocumentation // beginDefinition; +RelatedDocumentation // Options = { + "FilteredCount" -> Automatic, + "FilterResults" -> Automatic, + "MaxItems" -> 20 +}; + +GeneralUtilities`SetUsage[ RelatedDocumentation, "\ +RelatedDocumentation[\"string$\"] gives a list of documentation URIs that are semantically related to the \ +conversational-style question specified by \"string$\". +RelatedDocumentation[All] gives the full list of available documentation URIs." ]; + +RelatedDocumentation[ ___ ] /; $noSemanticSearch := Failure[ + "SemanticSearchUnavailable", + <| + "MessageTemplate" :> "SemanticSearch paclet is not available.", + "MessageParameters" -> { } + |> +]; + +RelatedDocumentation[ prompt_, opts: OptionsPattern[ ] ] := + catchMine @ RelatedDocumentation[ prompt, Automatic, opts ]; + +RelatedDocumentation[ prompt_, Automatic, opts: OptionsPattern[ ] ] := + catchMine @ RelatedDocumentation[ prompt, "URIs", opts ]; + +RelatedDocumentation[ prompt_, count: _Integer | UpTo[ _Integer ], opts: OptionsPattern[ ] ] := + RelatedDocumentation[ prompt, Automatic, count, opts ]; + +RelatedDocumentation[ prompt_, property_, opts: OptionsPattern[ ] ] := + catchMine @ RelatedDocumentation[ prompt, property, OptionValue @ MaxItems, opts ]; + +RelatedDocumentation[ prompt_, Automatic, count_, opts: OptionsPattern[ ] ] := + RelatedDocumentation[ prompt, "URIs", count, opts ]; + +RelatedDocumentation[ prompt: $$prompt, "URIs", Automatic, opts: OptionsPattern[ ] ] := catchMine @ Enclose[ + (* TODO: filter results *) + ConfirmMatch[ vectorDBSearch[ "DocumentationURIs", prompt, "Values" ], { ___String }, "Queries" ], + throwInternalFailure +]; + +RelatedDocumentation[ All, "URIs", Automatic, opts: OptionsPattern[ ] ] := catchMine @ Enclose[ + (* TODO: filter results *) + Union @ ConfirmMatch[ vectorDBSearch[ "DocumentationURIs", All ], { __String }, "QueryList" ], + throwInternalFailure +]; + +RelatedDocumentation[ prompt: $$prompt, "Snippets", Automatic, opts: OptionsPattern[ ] ] := catchMine @ Enclose[ + ConfirmMatch[ + (* TODO: filter results *) + DeleteMissing[ makeDocSnippets @ vectorDBSearch[ "DocumentationURIs", prompt, "Values" ] ], + { ___String }, + "Snippets" + ], + throwInternalFailure +]; + +RelatedDocumentation[ prompt_, property_, UpTo[ n_Integer ], opts: OptionsPattern[ ] ] := + catchMine @ RelatedDocumentation[ prompt, property, n, opts ]; + +RelatedDocumentation[ prompt_, property_, n_Integer, opts: OptionsPattern[ ] ] := catchMine @ Enclose[ + Take[ ConfirmMatch[ RelatedDocumentation[ prompt, property, Automatic, opts ], { ___String } ], UpTo @ n ], + throwInternalFailure +]; + +RelatedDocumentation[ + prompt: $$prompt, + property: "Results"|"Values"|"EmbeddingVector"|All, + n_Integer, + opts: OptionsPattern[ ] +] := + catchMine @ Enclose[ + (* TODO: filter results *) + Take[ ConfirmBy[ vectorDBSearch[ "DocumentationURIs", prompt, property ], ListQ, "Results" ], UpTo @ n ], + throwInternalFailure + ]; + +RelatedDocumentation[ prompt_, property: "Index"|"Distance", n_Integer, opts: OptionsPattern[ ] ] := + catchMine @ Enclose[ + Lookup[ + Take[ + ConfirmMatch[ + RelatedDocumentation[ prompt, "Results", n, opts ], + { KeyValuePattern[ property -> _ ]... }, + "Results" + ], + UpTo @ n + ], + property + ], + throwInternalFailure + ]; + +RelatedDocumentation[ prompt_, "Prompt", n_Integer, opts: OptionsPattern[ ] ] := + catchMine @ relatedDocumentationPrompt[ + ensureChatMessages @ prompt, + n, + MatchQ[ OptionValue[ "FilterResults" ], Automatic|True ], + Replace[ OptionValue[ "FilteredCount" ], Automatic -> Ceiling[ n / 4 ] ] + ]; + +RelatedDocumentation[ args___ ] := catchMine @ throwFailure[ + "InvalidArguments", + RelatedDocumentation, + HoldForm @ RelatedDocumentation @ args +]; + +RelatedDocumentation // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*ensureChatMessages*) +ensureChatMessages // beginDefinition; +ensureChatMessages[ prompt_String ] := { <| "Role" -> "User", "Content" -> prompt |> }; +ensureChatMessages[ message: KeyValuePattern[ "Role" -> _ ] ] := { message }; +ensureChatMessages[ messages: $$chatMessages ] := messages; +ensureChatMessages // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*relatedDocumentationPrompt*) +relatedDocumentationPrompt // beginDefinition; + +relatedDocumentationPrompt[ messages: $$chatMessages, count_, filter_, filterCount_ ] := Enclose[ + Catch @ Module[ { uris, filtered, string }, + + uris = ConfirmMatch[ + RelatedDocumentation[ messages, "URIs", count ], + { ___String }, + "URIs" + ] // LogChatTiming[ "RelatedDocumentationURIs" ]; + + If[ uris === { }, Throw[ "" ] ]; + + filtered = ConfirmMatch[ + filterSnippets[ messages, uris, filter, filterCount ] // LogChatTiming[ "FilterSnippets" ], + { ___String }, + "Filtered" + ]; + + string = StringTrim @ StringRiffle[ "# "<># & /@ DeleteCases[ filtered, "" ], "\n\n======\n\n" ]; + + If[ string === "", + "", + prependRelatedDocsHeader[ string, filter ] + ] + ], + throwInternalFailure +]; + +relatedDocumentationPrompt // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*prependRelatedDocsHeader*) +prependRelatedDocsHeader // beginDefinition; +prependRelatedDocsHeader[ string_String, True ] := $relatedDocsStringFilteredHeader <> string; +prependRelatedDocsHeader[ string_String, _ ] := $relatedDocsStringUnfilteredHeader <> string; +prependRelatedDocsHeader // endDefinition; + + +$relatedDocsStringFilteredHeader = +"IMPORTANT: Here are some Wolfram documentation snippets that you should use to respond.\n\n"; + +$relatedDocsStringUnfilteredHeader = +"Here are some Wolfram documentation snippets that you may find useful.\n\n"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*filterSnippets*) +filterSnippets // beginDefinition; + +filterSnippets[ messages_, uris: { __String }, filter_, filterCount_Integer? Positive ] := Enclose[ + Catch @ Module[ { snippets, inserted, transcript, xml, instructions, response, pages }, + + snippets = ConfirmMatch[ makeDocSnippets @ uris, { ___String }, "Snippets" ]; + If[ ! TrueQ @ filter, Throw @ snippets ]; + + inserted = insertContextPrompt @ messages; + transcript = ConfirmBy[ getSmallContextString @ inserted, StringQ, "Transcript" ]; + + xml = ConfirmMatch[ snippetXML /@ snippets, { __String }, "XML" ]; + instructions = ConfirmBy[ + TemplateApply[ + $bestDocumentationPrompt, + <| + "FilteredCount" -> filterCount, + "Snippets" -> StringRiffle[ xml, "\n\n" ], + "Transcript" -> transcript + |> + ], + StringQ, + "Prompt" + ]; + + response = StringTrim @ ConfirmBy[ llmSynthesize @ instructions, StringQ, "Response" ]; + pages = ConfirmMatch[ makeDocSnippets @ StringCases[ response, uris ], { ___String }, "Pages" ]; + + pages + ], + throwInternalFailure +]; + +filterSnippets // endDefinition; + + +$bestDocumentationPrompt = StringTemplate[ "\ +Your task is to read a chat transcript between a user and assistant, and then select the most relevant \ +Wolfram Language documentation snippets that could help the assistant answer the user's latest message. \ +Each snippet is uniquely identified by a URI (always starts with 'paclet:' or 'https://resources.wolframcloud.com'). + +Choose up to %%FilteredCount%% documentation snippets that would help answer the user's MOST RECENT message. \ +Respond only with the corresponding URIs of the snippets and nothing else. \ +If there are no relevant pages, respond with just the string \"none\". + +Here is the chat transcript: + + +%%Transcript%% + + +Here are the available documentation snippets to choose from: + + +%%Snippets%% + + +Reminder: Choose up to %%FilteredCount%% documentation snippets that would help answer the user's MOST RECENT message. \ +Respond only with the corresponding URIs of the snippets and nothing else. \ +If there are no relevant pages, respond with just the string \"none\".\ +", Delimiters -> "%%" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*snippetXML*) +snippetXML // beginDefinition; +snippetXML[ snippet_String ] := "\n" <> snippet <> "\n"; +snippetXML // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Documentation Snippets*) +$documentationSnippets = <| |>; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*makeDocSnippets*) +makeDocSnippets // beginDefinition; + +makeDocSnippets[ uris0: { ___String } ] := Enclose[ + Module[ { uris, data, snippets, strings }, + uris = DeleteDuplicates @ uris0; + data = ConfirmBy[ getDocumentationSnippetData @ uris, AssociationQ, "Data" ]; + snippets = ConfirmMatch[ Values @ data, { ___Association }, "Snippets" ]; + strings = ConfirmMatch[ Lookup[ "String" ] /@ snippets, { ___String }, "Strings" ]; + strings + ], + throwInternalFailure +]; + +makeDocSnippets[ uri_String ] := + First @ makeDocSnippets @ { uri }; + +makeDocSnippets // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getDocumentationSnippetData*) +getDocumentationSnippetData // beginDefinition; + +getDocumentationSnippetData[ { } ] := <| |>; + +getDocumentationSnippetData[ uris: { __String } ] := Enclose[ + Module[ { cached, missing }, + + cached = ConfirmBy[ + AssociationMap[ getCachedDocumentationSnippet, uris ], + AllTrue @ MatchQ[ _Missing | KeyValuePattern[ "String" -> _String ] ], + "Cached" + ]; + + missing = ConfirmMatch[ + Union[ First /@ StringSplit[ Keys @ Select[ cached, MissingQ ], "#" ] ], + { ___String }, + "Missing" + ]; + + LogChatTiming @ fetchDocumentationSnippets @ missing; + + ConfirmBy[ + AssociationMap[ getCachedDocumentationSnippet, uris ], + AllTrue @ MatchQ[ KeyValuePattern[ "String" -> _String ] ], + "Result" + ] + ] // LogChatTiming[ "GetDocumentationSnippets" ], + throwInternalFailure +]; + +getDocumentationSnippetData // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getCachedDocumentationSnippet*) +getCachedDocumentationSnippet // beginDefinition; +getCachedDocumentationSnippet[ uri_String ] := getCachedDocumentationSnippet @ StringSplit[ uri, "#" ]; +getCachedDocumentationSnippet[ { base_String } ] := getCachedDocumentationSnippet @ { base, None }; +getCachedDocumentationSnippet[ { base_String, fragment_ } ] := getCachedDocumentationSnippet0[ base, fragment ]; +getCachedDocumentationSnippet // endDefinition; + + +getCachedDocumentationSnippet0 // beginDefinition; + +getCachedDocumentationSnippet0[ base_String, fragment_ ] := + With[ { snippet = $documentationSnippets[ base, fragment ] }, + snippet /; snippetDataQ @ snippet + ]; + +getCachedDocumentationSnippet0[ base_String, fragment_ ] := Enclose[ + Catch @ Module[ { file, data, snippet }, + file = ConfirmBy[ snippetCacheFile @ base, StringQ, "File" ]; + data = If[ TrueQ @ FileExistsQ @ file, Quiet @ Developer`ReadWXFFile @ file, Throw @ Missing[ "NotCached" ] ]; + snippet = data[ fragment ]; + If[ AssociationQ @ data && snippetDataQ @ snippet, + $documentationSnippets[ base ] = data; snippet, + Missing[ "NotCached" ] + ] + ], + throwInternalFailure +]; + +getCachedDocumentationSnippet0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*snippetDataQ*) +snippetDataQ // beginDefinition; +snippetDataQ[ KeyValuePattern[ "String" -> _String ] ] := True; +snippetDataQ[ _ ] := False; +snippetDataQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*snippetCacheFile*) +snippetCacheFile // beginDefinition; + +snippetCacheFile[ uri_String ] /; StringStartsQ[ uri, "paclet:" ] := + snippetCacheFile[ uri, StringDelete[ uri, "paclet:" ], "Documentation" ]; + +snippetCacheFile[ uri_String ] /; StringStartsQ[ uri, "https://resources.wolframcloud.com/" ] := + snippetCacheFile[ uri, StringDelete[ uri, "https://resources.wolframcloud.com/" ], "ResourceSystem" ]; + +snippetCacheFile[ uri_String, path0_String, name_String ] := Enclose[ + Module[ { path, file }, + path = ConfirmBy[ StringTrim[ path0, "/" ] <> ".wxf", StringQ, "Path" ]; + file = ConfirmBy[ FileNameJoin @ { $snippetsCacheDirectory, name, path }, StringQ, "File" ]; + snippetCacheFile[ uri ] = file + ], + throwInternalFailure +]; + +snippetCacheFile // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*fetchDocumentationSnippets*) +fetchDocumentationSnippets // beginDefinition; + +fetchDocumentationSnippets[ { } ] := { }; + +fetchDocumentationSnippets[ uris: { __String } ] := + Module[ { $results, tasks }, + $results = AssociationMap[ <| "URI" -> #1 |> &, uris ]; + tasks = fetchDocumentationSnippets0 @ $results /@ uris; + TaskWait @ tasks; + processDocumentationSnippetResults @ $results + ]; + +fetchDocumentationSnippets // endDefinition; + + +fetchDocumentationSnippets0 // beginDefinition; +fetchDocumentationSnippets0 // Attributes = { HoldFirst }; + +fetchDocumentationSnippets0[ $results_ ] := + fetchDocumentationSnippets0[ $results, # ] &; + +fetchDocumentationSnippets0[ $results_, uri_String ] := Enclose[ + Module[ { url, setResult, task }, + url = ConfirmBy[ toDocSnippetURL @ uri, StringQ, "URL" ]; + setResult = Function[ $results[ uri ] = <| $results @ uri, # |> ]; + + task = URLSubmit[ + url, + HandlerFunctions -> <| + "BodyReceived" -> setResult, + "ConnectionFailed" -> Function[ $results[ uri ] = <| $results @ uri, # |> ] + |>, + HandlerFunctionsKeys -> { "BodyByteArray", "StatusCode", "Headers", "ContentType", "Cookies" } + ]; + + $results[ uri, "URL" ] = url; + $results[ uri, "Task" ] = task + ], + throwInternalFailure +]; + +fetchDocumentationSnippets0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*toDocSnippetURL*) +toDocSnippetURL // beginDefinition; + +toDocSnippetURL[ uri_String ] /; StringStartsQ[ uri, "paclet:" ] := + URLBuild @ { $documentationSnippetBaseURL, StringDelete[ uri, StartOfString~~"paclet:" ] <> ".wxf" }; + +toDocSnippetURL[ uri_String ] := + toDocSnippetURL0 @ URLParse[ uri, { "Domain", "Path" } ]; + +toDocSnippetURL // endDefinition; + + +toDocSnippetURL0 // beginDefinition; + +toDocSnippetURL0[ { "resources.wolframcloud.com", { "", repo_String, "resources", name_String } } ] := + URLBuild @ { $documentationSnippetBaseURL, "Resources", repo, name <> ".wxf" }; + +toDocSnippetURL0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*processDocumentationSnippetResults*) +processDocumentationSnippetResults // beginDefinition; +processDocumentationSnippetResults[ results_Association ] := KeyValueMap[ processDocumentationSnippetResult, results ]; +processDocumentationSnippetResults // endDefinition; + +(* TODO: retry failed results *) + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*processDocumentationSnippetResult*) +processDocumentationSnippetResult // beginDefinition; + +processDocumentationSnippetResult[ base_String, as_Association ] := + processDocumentationSnippetResult[ base, as, as[ "BodyByteArray" ], as[ "StatusCode" ] ]; + +processDocumentationSnippetResult[ base_String, as_, bytes_ByteArray, 200 ] := + processDocumentationSnippetResult[ base, as, Quiet @ Developer`ReadWXFByteArray @ bytes ]; + +processDocumentationSnippetResult[ base_String, as_, data_List ] := Enclose[ + Module[ { combined, keyed, processed, file }, + combined = ConfirmMatch[ makeCombinedSnippet @ data, None -> _Association, "Combined" ]; + keyed = Last @ StringSplit[ ConfirmBy[ #[ "URI" ], StringQ, "URI" ], "#" ] -> # & /@ data; + processed = ConfirmBy[ Association[ combined, keyed ], AssociationQ, "Processed" ]; + file = ConfirmBy[ snippetCacheFile @ base, StringQ, "File" ]; + ConfirmBy[ GeneralUtilities`EnsureDirectory @ DirectoryName @ file, DirectoryQ, "Directory" ]; + ConfirmBy[ Developer`WriteWXFFile[ file, processed ], FileExistsQ, "Export" ]; + $documentationSnippets[ base ] = processed + ], + throwInternalFailure +]; + +processDocumentationSnippetResult // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*makeCombinedSnippet*) +makeCombinedSnippet // beginDefinition; +makeCombinedSnippet[ { data_Association, ___ } ] := makeCombinedSnippet @ data; +(* TODO: combined several initial snippets instead of just one *) +makeCombinedSnippet[ data_Association ] := None -> data; +makeCombinedSnippet // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*cacheDocumentationSnippetResult*) +cacheDocumentationSnippetResult // beginDefinition; + +cacheDocumentationSnippetResult[ as_Association ] := + cacheDocumentationSnippetResult[ as[ "URI" ], as ]; + +cacheDocumentationSnippetResult[ uri_String, as_Association ] := + uri -> cacheDocumentationSnippetResult[ StringSplit[ uri, "#" ], as ]; + +cacheDocumentationSnippetResult[ { base_String, fragment: _String|None }, as_Association ] := + If[ AssociationQ @ $documentationSnippets[ base ], + $documentationSnippets[ base, fragment ] = as, + $documentationSnippets[ base ] = <| fragment -> as |> + ]; + +cacheDocumentationSnippetResult // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/PromptGenerators/RelatedWolframAlphaQueries.wl b/Source/Chatbook/PromptGenerators/RelatedWolframAlphaQueries.wl new file mode 100644 index 00000000..3b847225 --- /dev/null +++ b/Source/Chatbook/PromptGenerators/RelatedWolframAlphaQueries.wl @@ -0,0 +1,70 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`PromptGenerators`RelatedWolframAlphaQueries`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; +Needs[ "Wolfram`Chatbook`PromptGenerators`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*RelatedWolframAlphaQueries*) +RelatedWolframAlphaQueries // beginDefinition; + +GeneralUtilities`SetUsage[ RelatedWolframAlphaQueries, "\ +RelatedWolframAlphaQueries[\"string$\"] gives a list of Wolfram|Alpha queries that are semantically related to the \ +conversational-style question specified by \"string$\". +RelatedWolframAlphaQueries[All] gives the full list of available Wolfram|Alpha sample queries." ]; + +RelatedWolframAlphaQueries[ ___ ] /; $noSemanticSearch := Failure[ + "SemanticSearchUnavailable", + <| + "MessageTemplate" :> "SemanticSearch paclet is not available.", + "MessageParameters" -> { } + |> +]; + +RelatedWolframAlphaQueries[ prompt: _String | { ___String } ] := + catchMine @ RelatedWolframAlphaQueries[ prompt, Automatic ]; + +RelatedWolframAlphaQueries[ prompt: _String | { ___String }, Automatic ] := catchMine @ Enclose[ + ConfirmMatch[ vectorDBSearch[ "WolframAlphaQueries", prompt, "Values" ], { ___String }, "Queries" ], + throwInternalFailure +]; + +RelatedWolframAlphaQueries[ prompt_, UpTo[ n_Integer ] ] := + RelatedWolframAlphaQueries[ prompt, n ]; + +RelatedWolframAlphaQueries[ prompt_, n_Integer ] := catchMine @ Enclose[ + ConfirmMatch[ Take[ RelatedWolframAlphaQueries[ prompt, Automatic ], UpTo @ n ], { ___String }, "Queries" ], + throwInternalFailure +]; + +RelatedWolframAlphaQueries[ All ] := catchMine @ $uniqueWAQueries; + +RelatedWolframAlphaQueries[ args___ ] := catchMine @ throwFailure[ + "InvalidArguments", + RelatedWolframAlphaQueries, + HoldForm @ RelatedWolframAlphaQueries @ args +]; + +RelatedWolframAlphaQueries // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*$uniqueWAQueries*) +$uniqueWAQueries := Enclose[ + $uniqueWAQueries = Union @ ConfirmMatch[ vectorDBSearch[ "WolframAlphaQueries", All ], { __String }, "QueryList" ], + throwInternalFailure +]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/PromptGenerators/VectorDatabases.wl b/Source/Chatbook/PromptGenerators/VectorDatabases.wl new file mode 100644 index 00000000..251f38e9 --- /dev/null +++ b/Source/Chatbook/PromptGenerators/VectorDatabases.wl @@ -0,0 +1,849 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`PromptGenerators`VectorDatabases`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; +Needs[ "Wolfram`Chatbook`PromptGenerators`Common`" ]; + +HoldComplete[ + System`VectorDatabaseObject, + System`VectorDatabaseSearch +]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Configuration*) +$vectorDBNames = { "DocumentationURIs", "WolframAlphaQueries" }; +$dbVersion = "1.1.0"; +$allowDownload = True; +$cacheEmbeddings = True; + +$embeddingDimension = 384; +$maxNeighbors = 50; +$maxEmbeddingDistance = 150.0; +$embeddingService = "Local"; +$embeddingModel = "SentenceBERT"; +$embeddingAuthentication = Automatic; (* FIXME *) + + +$conversationVectorSearchPenalty = 1.0; + +$relatedQueryCount = 5; +$relatedDocsCount = 20; +$querySampleCount = 10; + +$relevantFileCount = 3; +$maxExtraFiles = 20; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Remote Content Locations*) +$baseVectorDatabasesURL = "https://www.wolframcloud.com/obj/wolframai-content/VectorDatabases"; + +(* TODO: these will be moved to the data repository: *) +$vectorDBDownloadURLs = AssociationMap[ + URLBuild @ { $baseVectorDatabasesURL, $dbVersion, # <> ".zip" } &, + $vectorDBNames +]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Paths*) +$pacletVectorDBDirectory := FileNameJoin @ { $thisPaclet[ "Location" ], "Assets/VectorDatabases" }; +$localVectorDBDirectory := ChatbookFilesDirectory @ { "VectorDatabases", $dbVersion }; + +(* TODO: need versioned URLs and paths *) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Argument Patterns*) +$$vectorDatabase = _VectorDatabaseObject? System`Private`ValidQ; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Cache*) +$vectorDBSearchCache = <| |>; +$embeddingCache = <| |>; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Vector Database Utilities*) +$vectorDBDirectory := getVectorDBDirectory[ ]; + +$noSemanticSearch := $noSemanticSearch = ! PacletObjectQ @ Quiet @ PacletInstall[ "SemanticSearch" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getVectorDBDirectory*) +getVectorDBDirectory // beginDefinition; + +getVectorDBDirectory[ ] := Enclose[ + $vectorDBDirectory = SelectFirst[ + { + $pacletVectorDBDirectory, + $localVectorDBDirectory + }, + vectorDBDirectoryQ, + (* TODO: need a version of this that prompts the user with a dialog asking them to download *) + ConfirmBy[ downloadVectorDatabases[ ], vectorDBDirectoryQ, "Downloaded" ] + ], + throwInternalFailure +]; + +getVectorDBDirectory // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*vectorDBDirectoryQ*) +vectorDBDirectoryQ // beginDefinition; +vectorDBDirectoryQ[ dir_? DirectoryQ ] := AllTrue[ $vectorDBNames, vectorDBDirectoryQ0 @ FileNameJoin @ { dir, # } & ]; +vectorDBDirectoryQ[ _ ] := False; +vectorDBDirectoryQ // endDefinition; + +vectorDBDirectoryQ0 // beginDefinition; + +vectorDBDirectoryQ0[ dir_? DirectoryQ ] := Enclose[ + Module[ { name, existsQ, expected }, + name = ConfirmBy[ FileBaseName @ dir, StringQ, "Name" ]; + existsQ = FileExistsQ @ FileNameJoin @ { dir, # } &; + expected = { name <> ".wxf", "Values.wxf", name <> "-vectors.usearch" }; + TrueQ @ AllTrue[ expected, existsQ ] + ], + throwInternalFailure +]; + +vectorDBDirectoryQ0[ _ ] := False; + +vectorDBDirectoryQ0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*downloadVectorDatabases*) +downloadVectorDatabases // beginDefinition; + +downloadVectorDatabases[ ] /; ! $allowDownload := + Throw[ Missing[ "DownloadDisabled" ], $vdbTag ]; + +downloadVectorDatabases[ ] := + downloadVectorDatabases[ $localVectorDBDirectory, $vectorDBDownloadURLs ]; + +downloadVectorDatabases[ dir0_, urls_Association ] := Enclose[ + Module[ { names, sizes, dir, tasks }, + + dir = ConfirmBy[ GeneralUtilities`EnsureDirectory @ dir0, DirectoryQ, "Directory" ]; + names = ConfirmMatch[ Keys @ urls, { __String }, "Names" ]; + sizes = ConfirmMatch[ getDownloadSize /@ Values @ urls, { __? Positive }, "Sizes" ]; + + $downloadProgress = AssociationMap[ 0 &, names ]; + $progressText = "Downloading semantic search indices\[Ellipsis]"; + + evaluateWithProgress[ + + tasks = ConfirmMatch[ KeyValueMap[ downloadVectorDatabase @ dir, urls ], { __TaskObject }, "Download" ]; + ConfirmMatch[ taskWait @ tasks, { __TaskObject }, "TaskWait" ]; + $progressText = "Unpacking files\[Ellipsis]"; + ConfirmBy[ unpackVectorDatabases @ dir, DirectoryQ, "Unpacked" ], + + <| + "Text" :> $progressText, + "ElapsedTime" -> Automatic, + "RemainingTime" -> Automatic, + "ByteCountCurrent" :> Total @ $downloadProgress, + "ByteCountTotal" -> Total @ sizes, + "Progress" -> Automatic + |> + ] + ] // LogChatTiming[ "DownloadVectorDatabases" ], + throwInternalFailure +]; + +downloadVectorDatabases // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*evaluateWithProgress*) +(* This is a workaround for EvaluateWithProgress never printing a progress panel when called normally in a chat: *) +evaluateWithProgress // beginDefinition; +evaluateWithProgress // Attributes = { HoldFirst }; +evaluateWithProgress[ args___ ] /; $WorkspaceChat := evaluateWithWorkspaceProgress @ args; +evaluateWithProgress[ args___ ] /; $InlineChat := evaluateWithInlineProgress @ args; +evaluateWithProgress[ args___ ] := Progress`EvaluateWithProgress @ args; +evaluateWithProgress // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*evaluateWithWorkspaceProgress*) +evaluateWithWorkspaceProgress // beginDefinition; +evaluateWithWorkspaceProgress // Attributes = { HoldFirst }; + +evaluateWithWorkspaceProgress[ args___ ] := + Catch @ Module[ { nbo, cell, container, attached }, + + nbo = $evaluationNotebook; + cell = First[ Cells[ nbo, AttachedCell -> True, CellStyle -> "ChatInputField" ], None ]; + If[ ! MatchQ[ cell, _CellObject ], Throw @ evaluateWithDialogProgress @ args ]; + + container = ProgressIndicator[ Appearance -> "Percolate" ]; + + attached = AttachCell[ + cell, + Magnify[ + Panel[ + Dynamic[ container, Deinitialization :> Quiet @ Remove @ container ], + ImageSize -> { Full, Automatic } + ], + AbsoluteCurrentValue[ nbo, Magnification ] + ], + { Center, Top }, + 0, + { Center, Bottom } + ]; + + WithCleanup[ + Progress`EvaluateWithProgress[ + args, + "Container" :> container, + "Delay" -> 0 + ], + NotebookDelete @ attached; + Quiet @ Remove @ container; + ] + ]; + +evaluateWithWorkspaceProgress // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*evaluateWithInlineProgress*) +evaluateWithInlineProgress // beginDefinition; +evaluateWithInlineProgress // Attributes = { HoldFirst }; + +evaluateWithInlineProgress[ args___ ] := Enclose[ + Catch @ Module[ { container, cells, inserted }, + + container = ProgressIndicator[ Appearance -> "Percolate" ]; + cells = $inlineChatState[ "MessageCells" ]; + inserted = insertInlineProgressIndicator[ Dynamic @ container, cells ]; + If[ ! MatchQ[ inserted, { ___Cell } ], Throw @ evaluateWithDialogProgress @ args ]; + + WithCleanup[ + Progress`EvaluateWithProgress[ + args, + "Container" :> container, + "Delay" -> 0 + ], + ConfirmMatch[ removeInlineProgressIndicator @ cells, { ___Cell }, "Removed" ]; + Quiet @ Remove @ container; + ] + ], + throwInternalFailure +]; + +evaluateWithInlineProgress // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*insertInlineProgressIndicator*) +insertInlineProgressIndicator // beginDefinition; + +insertInlineProgressIndicator[ Dynamic[ container_ ], Dynamic[ cells0_Symbol ] ] := Enclose[ + Module[ { cells, cell }, + cells = ConfirmMatch[ cells0, { ___Cell }, "Cells" ]; + cell = Cell[ + BoxData @ assistantMessageBox @ ToBoxes @ Dynamic[ + container, + Deinitialization :> Quiet @ Remove @ container + ], + "ChatOutput", + "EvaluateWithProgressContainer", + CellFrame -> 0, + PrivateCellOptions -> { "ContentsOpacity" -> 1 } + ]; + cells0 = Append[ cells, cell ] + ], + throwInternalFailure +]; + +insertInlineProgressIndicator // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*removeInlineProgressIndicator*) +removeInlineProgressIndicator // beginDefinition; + +removeInlineProgressIndicator[ Dynamic[ cells_Symbol ] ] := + cells = DeleteCases[ cells, Cell[ __, "EvaluateWithProgressContainer", ___ ] ]; + +removeInlineProgressIndicator // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*evaluateWithDialogProgress*) +evaluateWithDialogProgress // beginDefinition; +evaluateWithDialogProgress // Attributes = { HoldFirst }; + +evaluateWithDialogProgress[ args___ ] := + Module[ { container, dialog }, + + container = ProgressIndicator[ Appearance -> "Percolate" ]; + + dialog = CreateDialog[ + Pane[ + Dynamic[ container, Deinitialization :> Quiet @ Remove @ container ], + ImageMargins -> { { 5, 5 }, { 10, 5 } } + ], + WindowTitle -> Dynamic[ $progressText ] + ]; + + WithCleanup[ + Progress`EvaluateWithProgress[ + args, + "Container" :> container, + "Delay" -> 0 + ], + NotebookClose @ dialog; + Quiet @ Remove @ container; + ] + ]; + +evaluateWithDialogProgress // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getDownloadSize*) +getDownloadSize // beginDefinition; +getDownloadSize[ url_String ] := getDownloadSize @ CloudObject @ url; +getDownloadSize[ obj_CloudObject ] := FileByteCount @ obj; +getDownloadSize // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*unpackVectorDatabases*) +unpackVectorDatabases // beginDefinition; + +unpackVectorDatabases[ dir_? DirectoryQ ] := + unpackVectorDatabases[ dir, FileNames[ "*.zip", dir ] ] // LogChatTiming[ "UnpackVectorDatabases" ]; + +unpackVectorDatabases[ dir_, zips: { __String } ] := + unpackVectorDatabases[ dir, zips, unpackVectorDatabase /@ zips ]; + +unpackVectorDatabases[ dir_, zips_, extracted: { { __String }.. } ] := + dir; + +unpackVectorDatabases // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*unpackVectorDatabase*) +unpackVectorDatabase // beginDefinition; + +unpackVectorDatabase[ zip_String? FileExistsQ ] := Enclose[ + Module[ { root, dir, res }, + root = ConfirmBy[ DirectoryName @ zip, DirectoryQ, "RootDirectory" ]; + dir = ConfirmBy[ GeneralUtilities`EnsureDirectory @ { root, FileBaseName @ zip }, DirectoryQ, "Directory" ]; + res = ConfirmMatch[ ExtractArchive[ zip, dir, OverwriteTarget -> True ], { __? FileExistsQ }, "Extracted" ]; + DeleteFile @ zip; + res + ], + throwInternalFailure +]; + +unpackVectorDatabase // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*taskWait*) +taskWait // beginDefinition; +taskWait[ tasks_List ] := taskWait /@ tasks; +taskWait[ task_TaskObject ] := taskWait[ task, task[ "TaskStatus" ] ]; +taskWait[ task_TaskObject, "Removed" ] := task; +taskWait[ task_TaskObject, _ ] := TaskWait @ task; +taskWait // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*downloadVectorDatabase*) +downloadVectorDatabase // beginDefinition; + +downloadVectorDatabase[ dir_ ] := + downloadVectorDatabase[ dir, ## ] &; + +downloadVectorDatabase[ dir_, name_String, url_String ] := Enclose[ + Module[ { file }, + file = ConfirmBy[ FileNameJoin @ { dir, name<>".zip" }, StringQ, "File" ]; + ConfirmMatch[ + URLDownloadSubmit[ + url, + file, + HandlerFunctions -> <| "TaskProgress" -> setDownloadProgress @ name |>, + HandlerFunctionsKeys -> { "ByteCountDownloaded" } + ], + _TaskObject, + "Task" + ] + ] // LogChatTiming[ { "DownloadVectorDatabase", name } ], + throwInternalFailure +]; + +downloadVectorDatabase // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*setDownloadProgress*) +setDownloadProgress // beginDefinition; +setDownloadProgress[ name_String ] := setDownloadProgress[ name, ## ] &; +setDownloadProgress[ name_, KeyValuePattern[ "ByteCountDownloaded" -> b_? Positive ] ] := $downloadProgress[ name ] = b; +setDownloadProgress // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*inVectorDBDirectory*) +inVectorDBDirectory // beginDefinition; +inVectorDBDirectory // Attributes = { HoldFirst }; +inVectorDBDirectory[ eval_ ] := WithCleanup[ SetDirectory @ $vectorDBDirectory, eval, ResetDirectory[ ] ]; +inVectorDBDirectory // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*initializeVectorDatabases*) +initializeVectorDatabases // beginDefinition; +initializeVectorDatabases[ ] := Block[ { $allowDownload = False }, Catch[ getVectorDB /@ $vectorDBNames, $vdbTag ] ]; +initializeVectorDatabases // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getVectorDB*) +getVectorDB // beginDefinition; + +getVectorDB[ name_String ] := Enclose[ + getVectorDB[ name ] = ConfirmMatch[ + Association @ loadVectorDB @ name, + KeyValuePattern @ { "Values" -> { ___String }, "VectorDatabaseObject" -> $$vectorDatabase }, + "VectorDB" + ], + throwInternalFailure +]; + +getVectorDB // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*loadVectorDB*) +loadVectorDB // beginDefinition; + +loadVectorDB[ name_String ] := Enclose[ + Module[ { values, vectorDB, dims }, + + values = ConfirmMatch[ loadVectorDBValues @ name, { ___String }, "Values" ]; + vectorDB = ConfirmMatch[ loadVectorDatabase @ name, $$vectorDatabase, "VectorDatabaseObject" ]; + dims = ConfirmMatch[ inVectorDBDirectory @ vectorDB[ "Dimensions" ], { _Integer, _Integer }, "Dimensions" ]; + + ConfirmAssert[ Length @ values === First @ dims, "LengthCheck" ]; + + <| "Values" -> values, "VectorDatabaseObject" -> vectorDB |> + ], + throwInternalFailure +]; + +loadVectorDB // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*loadVectorDatabase*) +loadVectorDatabase // beginDefinition; + +loadVectorDatabase[ name_String ] := Enclose[ + inVectorDBDirectory @ Module[ { dir, file }, + dir = ConfirmBy[ name, DirectoryQ, "Directory" ]; + file = ConfirmBy[ File @ FileNameJoin @ { dir, name<>".wxf" }, FileExistsQ, "File" ]; + ConfirmMatch[ VectorDatabaseObject @ file, $$vectorDatabase, "Database" ] + ], + throwInternalFailure +]; + +loadVectorDatabase // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*loadVectorDBValues*) +loadVectorDBValues // beginDefinition; + +loadVectorDBValues[ name_String ] := Enclose[ + Module[ { root, dir, file }, + root = ConfirmBy[ $vectorDBDirectory, DirectoryQ, "RootDirectory" ]; + dir = ConfirmBy[ FileNameJoin @ { root, name }, DirectoryQ, "Directory" ]; + file = ConfirmBy[ FileNameJoin @ { dir, "Values.wxf" }, FileExistsQ, "File" ]; + loadVectorDBValues[ name ] = ConfirmMatch[ Developer`ReadWXFFile @ file, { __String }, "Read" ] + ], + throwInternalFailure +]; + +loadVectorDBValues // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*vectorDBSearch*) +vectorDBSearch // beginDefinition; + +vectorDBSearch[ dbName_String, prompt_String ] := + vectorDBSearch[ dbName, prompt, All ]; + +vectorDBSearch[ dbName_String, All ] := + vectorDBSearch[ dbName, All, "Values" ]; + +vectorDBSearch[ dbName_String, "", All ] := <| + "EmbeddingVector" -> None, + "SearchData" -> Missing[ "NoInput" ], + "Values" -> { } +|>; + +vectorDBSearch[ dbName_String, prompt_String, All ] := + With[ { result = $vectorDBSearchCache[ dbName, prompt ] }, + result /; AssociationQ @ result + ]; + +vectorDBSearch[ dbName_String, prompt_String, All ] := Enclose[ + Module[ { vectorDBInfo, vectorDB, allValues, embeddingVector, close, indices, distances, values, data, result }, + + vectorDBInfo = ConfirmBy[ getVectorDB @ dbName, AssociationQ, "VectorDBInfo" ]; + vectorDB = ConfirmMatch[ vectorDBInfo[ "VectorDatabaseObject" ], $$vectorDatabase, "VectorDatabase" ]; + allValues = ConfirmBy[ vectorDBInfo[ "Values" ], ListQ, "Values" ]; + embeddingVector = ConfirmMatch[ getEmbedding @ prompt, _NumericArray, "EmbeddingVector" ]; + + close = ConfirmMatch[ + inVectorDBDirectory @ VectorDatabaseSearch[ + vectorDB, + embeddingVector, + { "Index", "Distance" }, + MaxItems -> $maxNeighbors + ] // LogChatTiming[ "VectorDatabaseSearch" ], + { ___Association }, + "PositionsAndDistances" + ]; + + indices = ConfirmMatch[ close[[ All, "Index" ]], { ___Integer }, "Indices" ]; + distances = ConfirmMatch[ close[[ All, "Distance" ]], { ___Real }, "Distances" ]; + + values = ConfirmBy[ allValues[[ indices ]], ListQ, "Values" ]; + + ConfirmAssert[ Length @ indices === Length @ distances === Length @ values, "LengthCheck" ]; + + data = MapApply[ + <| "Value" -> #1, "Index" -> #2, "Distance" -> #3 |> &, + Transpose @ { values, indices, distances } + ]; + + result = <| "Values" -> DeleteDuplicates @ values, "Results" -> data, "EmbeddingVector" -> embeddingVector |>; + + (* Cache and verify: *) + cacheVectorDBResult[ dbName, prompt, result ]; + ConfirmAssert[ $vectorDBSearchCache[ dbName, prompt ] === result, "CacheCheck" ]; + + result + ], + throwInternalFailure +]; + +vectorDBSearch[ dbName_String, prompt_String, key_String ] := Enclose[ + Lookup[ ConfirmBy[ vectorDBSearch[ dbName, prompt, All ], AssociationQ, "Result" ], key ], + throwInternalFailure +]; + +vectorDBSearch[ dbName_String, prompt_String, keys: { ___String } ] := Enclose[ + KeyTake[ ConfirmBy[ vectorDBSearch[ dbName, prompt, All ], AssociationQ, "Result" ], keys ], + throwInternalFailure +]; + +vectorDBSearch[ dbName_String, prompts: { ___String }, prop_ ] := + AssociationMap[ vectorDBSearch[ dbName, #, prop ] &, prompts ]; + +vectorDBSearch[ dbName_String, All, "Values" ] := Enclose[ + Module[ { vectorDBInfo }, + vectorDBInfo = ConfirmBy[ getVectorDB @ dbName, AssociationQ, "VectorDB" ]; + ConfirmBy[ vectorDBInfo[ "Values" ], ListQ, "Values" ] + ], + throwInternalFailure +]; + +vectorDBSearch[ dbName_String, messages0: { __Association }, prop: "Values"|"Results" ] := Enclose[ + Catch @ Module[ + { + messages, + conversationString, lastMessageString, selectionString, + conversationResults, lastMessageResults, selectionResults, + combined, n, merged + }, + + (* TODO: asynchronously pre-cache embeddings for each type *) + + messages = ConfirmMatch[ insertContextPrompt @ messages0, { __Association }, "Messages" ]; + + conversationString = ConfirmBy[ getSmallContextString @ messages, StringQ, "ConversationString" ]; + + lastMessageString = ConfirmBy[ + getSmallContextString[ { Last @ messages }, "IncludeSystemMessage" -> True ], + StringQ, + "LastMessageString" + ]; + + selectionString = If[ StringQ @ $selectionPrompt, $selectionPrompt, None ]; + + If[ conversationString === "" || lastMessageString === "", Throw @ { } ]; + + getEmbeddings @ Select[ { conversationString, lastMessageString, selectionString }, StringQ ]; + + conversationResults = ConfirmMatch[ + MapAt[ + # + $conversationVectorSearchPenalty &, + vectorDBSearch[ dbName, conversationString, "Results" ], + { All, "Distance" } + ], + { KeyValuePattern[ { "Distance" -> _Real, "Value" -> _ } ]... }, + "ConversationResults" + ]; + + lastMessageResults = + If[ lastMessageString === conversationString, + { }, + ConfirmMatch[ + vectorDBSearch[ dbName, lastMessageString, "Results" ], + { KeyValuePattern[ { "Distance" -> _Real, "Value" -> _ } ]... }, + "LastMessageResults" + ] + ]; + + selectionResults = + If[ StringQ @ selectionString, + ConfirmMatch[ + vectorDBSearch[ dbName, selectionString, "Results" ], + { KeyValuePattern[ { "Distance" -> _Real, "Value" -> _ } ]... }, + "SelectionResults" + ], + { } + ]; + + combined = SortBy[ Join[ conversationResults, lastMessageResults, selectionResults ], Lookup[ "Distance" ] ]; + + n = Ceiling[ $maxNeighbors / 10 ]; + merged = Take[ + DeleteDuplicates @ Join[ + Take[ conversationResults, UpTo[ n ] ], + Take[ lastMessageResults , UpTo[ n ] ], + Take[ selectionResults , UpTo[ n ] ], + combined + ], + UpTo[ $maxNeighbors ] + ]; + + If[ prop === "Results", + merged, + DeleteDuplicates[ Lookup[ "Value" ] /@ merged ] + ] + ], + throwInternalFailure +]; + +vectorDBSearch // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*insertContextPrompt*) +insertContextPrompt // beginDefinition; + +insertContextPrompt[ messages_ ] := + insertContextPrompt[ messages, $contextPrompt, $selectionPrompt ]; + +insertContextPrompt[ { before___, last_Association }, context_String, selection_String ] := { + before, + <| "Role" -> "User" , "Content" -> context |>, + <| "Role" -> "System", "Content" -> "User's currently selected text: \""<>selection<>"\"" |>, + last +}; + +insertContextPrompt[ { before___, last_Association }, context_String, _ ] := { + before, + <| "Role" -> "User", "Content" -> context |>, + last +}; + +insertContextPrompt[ messages_List, _, _ ] := + messages; + +insertContextPrompt // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*cacheVectorDBResult*) +cacheVectorDBResult // beginDefinition; + +cacheVectorDBResult[ dbName_String, prompt_String, data_Association ] := ( + If[ ! AssociationQ @ $vectorDBSearchCache, $vectorDBSearchCache = <| |> ]; + If[ ! AssociationQ @ $vectorDBSearchCache[ dbName ], $vectorDBSearchCache[ dbName ] = <| |> ]; + $vectorDBSearchCache[ dbName, prompt ] = data +); + +cacheVectorDBResult // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Embeddings*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getEmbedding*) +getEmbedding // beginDefinition; +getEmbedding // Options = { "CacheEmbeddings" -> $cacheEmbeddings }; + +getEmbedding[ string_String, opts: OptionsPattern[ ] ] := + With[ { embedding = $embeddingCache[ string ] }, + embedding /; NumericArrayQ @ embedding + ]; + +getEmbedding[ string_String, opts: OptionsPattern[ ] ] := Enclose[ + First @ ConfirmMatch[ getEmbeddings[ { string }, opts ], { _NumericArray }, "Embedding" ], + throwInternalFailure +]; + +getEmbedding // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getEmbeddings*) +getEmbeddings // beginDefinition; +getEmbeddings // Options = { "CacheEmbeddings" -> $cacheEmbeddings }; + +getEmbeddings[ { }, opts: OptionsPattern[ ] ] := { }; + +getEmbeddings[ strings: { __String }, opts: OptionsPattern[ ] ] := + If[ TrueQ @ OptionValue[ "CacheEmbeddings" ], + getEmbeddings0 @ strings, + Block[ { $cacheEmbeddings = False }, getAndCacheEmbeddings @ strings ] + ] // LogChatTiming[ "GetEmbeddings" ]; + +getEmbeddings // endDefinition; + + +getEmbeddings0 // beginDefinition; + +getEmbeddings0[ strings: { __String } ] := Enclose[ + Module[ { notCached }, + notCached = Select[ strings, ! KeyExistsQ[ $embeddingCache, # ] & ]; + ConfirmMatch[ getAndCacheEmbeddings @ notCached, { ___NumericArray }, "CacheEmbeddings" ]; + ConfirmMatch[ Lookup[ $embeddingCache, strings ], { __NumericArray }, "Result" ] + ], + throwInternalFailure +]; + +getEmbeddings0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getAndCacheEmbeddings*) +getAndCacheEmbeddings // beginDefinition; + +getAndCacheEmbeddings[ { } ] := + { }; + +getAndCacheEmbeddings[ strings: { __String } ] /; $embeddingModel === "SentenceBERT" := Enclose[ + Module[ { vectors }, + vectors = ConfirmBy[ + Developer`ToPackedArray @ sentenceBERTEmbedding @ strings, + Developer`PackedArrayQ, + "PackedArray" + ]; + + ConfirmAssert[ Length @ strings === Length @ vectors, "LengthCheck" ]; + + MapThread[ cacheEmbedding, { strings, vectors } ] + ], + throwInternalFailure +]; + +getAndCacheEmbeddings[ strings: { __String } ] := Enclose[ + Module[ { resp, vectors }, + resp = ConfirmBy[ + setServiceCaller @ ServiceExecute[ + $embeddingService, + "RawEmbedding", + { "input" -> strings, "model" -> $embeddingModel }, + Authentication -> $embeddingAuthentication + ], + AssociationQ, + "EmbeddingResponse" + ]; + + vectors = ConfirmBy[ + Developer`ToPackedArray @ resp[[ "data", All, "embedding" ]], + Developer`PackedArrayQ, + "PackedArray" + ]; + + ConfirmAssert[ Length @ strings === Length @ vectors, "LengthCheck" ]; + + MapThread[ cacheEmbedding, { strings, vectors } ] + ], + throwInternalFailure +]; + +getAndCacheEmbeddings // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*cacheEmbedding*) +cacheEmbedding // beginDefinition; +cacheEmbedding[ key_String, vector_ ] /; ! $cacheEmbeddings := toTinyVector @ vector; +cacheEmbedding[ key_String, vector_ ] := $embeddingCache[ key ] = toTinyVector @ vector; +cacheEmbedding // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*sentenceBERTEmbedding*) +sentenceBERTEmbedding := getSentenceBERTEmbeddingFunction[ ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*getSentenceBERTEmbeddingFunction*) +getSentenceBERTEmbeddingFunction // beginDefinition; + +getSentenceBERTEmbeddingFunction[ ] := Enclose[ + Module[ { name }, + + Needs[ "SemanticSearch`" -> None ]; + + name = ConfirmBy[ + SelectFirst[ + { + "SemanticSearch`SentenceBERTEmbedding", + "SemanticSearch`SemanticSearch`Private`SentenceBERTEmbedding" + }, + NameQ @ # && ToExpression[ #, InputForm, System`Private`HasAnyEvaluationsQ ] & + ], + StringQ, + "SymbolName" + ]; + + getSentenceBERTEmbeddingFunction[ ] = Symbol @ name + ], + throwInternalFailure +]; + +getSentenceBERTEmbeddingFunction // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*toTinyVector*) +toTinyVector // beginDefinition; +toTinyVector[ v_ ] := NumericArray[ 127.5 * Normalize @ v[[ 1;;$embeddingDimension ]] - 0.5, "Real16" ]; +toTinyVector // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Prompting.wl b/Source/Chatbook/Prompting.wl index 78ad36fa..37eae713 100644 --- a/Source/Chatbook/Prompting.wl +++ b/Source/Chatbook/Prompting.wl @@ -245,6 +245,8 @@ $basePromptComponents[ "WolframLanguageStyle" ] = " * Keep code simple when possible * Use functional programming instead of procedural * Do not assign global variables when it's not necessary +* Always use proper naming conventions for your variables (e.g. lowerCamelCase) +* Never use single capital letters to represent variables (e.g. use `a Sin[k x + \[Phi]]` instead of `A Sin[k x + \[Phi]]`) * Prefer modern Wolfram Language symbols and methods * Many new symbols have been added to WL since your knowledge cutoff date, so check documentation as needed * When creating plots, add options such as labels and legends to make them easier to understand"; diff --git a/Source/Chatbook/ResourceInstaller.wl b/Source/Chatbook/ResourceInstaller.wl index bd6ebcc2..d6055402 100644 --- a/Source/Chatbook/ResourceInstaller.wl +++ b/Source/Chatbook/ResourceInstaller.wl @@ -6,6 +6,7 @@ BeginPackage[ "Wolfram`Chatbook`ResourceInstaller`" ]; `$ResourceInstallationDirectory; `GetInstalledResourceData; `ResourceInstall; +`ResourceInstallFromFile; `ResourceInstallFromRepository; `ResourceInstallFromURL; `ResourceInstallLocation; @@ -59,10 +60,7 @@ $resourceBrowseURLs = <| "LLMTool" -> "https://resources.wolframcloud.com/LLMToolRepository" |>; -$ResourceInstallationDirectory := GeneralUtilities`EnsureDirectory @ { - ExpandFileName @ LocalObject @ $LocalBase, - "Chatbook" -}; +$ResourceInstallationDirectory := $ChatbookFilesDirectory; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) @@ -397,6 +395,84 @@ scrapeResourceFromShingle[ url_String ] := Enclose[ scrapeResourceFromShingle // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*ResourceInstallFromFile*) + +ResourceInstallFromFile // ClearAll; + +(* Not sure if this syntactic sugar is warranted *) +ResourceInstallFromFile[ ] := + catchMine @ ResourceInstallFromFile[ Automatic, Automatic ] + +ResourceInstallFromFile[ rtype: $$installableType|Automatic ] := + catchMine @ ResourceInstallFromFile[ rtype, Automatic ]; + +ResourceInstallFromFile[ File[ path_String ] ] := + catchMine @ ResourceInstallFromFile[ Automatic, path ]; + +(* I expect these next two definitions to be the most used *) +ResourceInstallFromFile[ rtype: $$installableType|Automatic, Automatic ] := catchMine @ Enclose[ + Module[ { path }, + + path = ConfirmMatch[ + SystemDialogInput[ "FileOpen", ".nb", WindowTitle -> FrontEndResource[ "ChatbookStrings", "ResourceInstallerFromFilePrompt" ] ], + _String|$Canceled, + "InputString" + ]; + + If[ path === $Canceled, + $Canceled, + ConfirmBy[ ResourceInstallFromFile[ rtype, path ], AssociationQ, "Install" ] + ] + ], + throwInternalFailure[ ResourceInstallFromFile @ rtype, ## ] & +]; + +ResourceInstallFromFile[ rtype: $$installableType|Automatic, path_String ] := Enclose[ + Module[ { ro, expected, actual, file }, + + ro = ConfirmMatch[ resourceFromFile[ rtype, path ], _ResourceObject, "ResourceObject" ]; + expected = Replace[ rtype, Automatic -> $$installableType ]; + actual = ConfirmBy[ ro[ "ResourceType" ], StringQ, "ResourceType" ]; + + If[ ! MatchQ[ actual, expected ], + If[ StringQ @ expected, + throwMessageDialog[ "ExpectedInstallableResourceType", expected, actual ], + throwMessageDialog[ "NotInstallableResourceType", actual, $installableTypes ] + ] + ]; + + file = ConfirmBy[ ResourceInstall @ ro, FileExistsQ, "ResourceInstall" ]; + ConfirmBy[ getResourceFile @ file, AssociationQ, "GetResourceFile" ] + ], + throwInternalFailure[ ResourceInstallFromFile[ rtype, path ], ## ] & +]; + +ResourceInstallFromFile[ args___ ] := + catchMine @ throwFailure[ "InvalidArguments", ResourceInstallFromFile, HoldForm @ ResourceInstallFromFile @ args ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*resourceFromFile*) +resourceFromFile // beginDefinition; + +resourceFromFile[ Automatic, path_String ] := Block[ { PrintTemporary }, + Quiet[ DefinitionNotebookClient`ScrapeResource[ Import[ path ] ] ] +]; + +resourceFromFile[ rtype_, path_String ] := Enclose[ + Block[ { PrintTemporary }, + Quiet @ With[ { nb = Import @ path }, + ConfirmMatch[ DefinitionNotebookClient`NotebookResourceType @ nb, rtype, "ResourceType" ]; + DefinitionNotebookClient`ScrapeResource @ nb + ] + ], + throwInternalFailure +]; + +resourceFromFile // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*ResourceInstallLocation*) @@ -554,7 +630,7 @@ resourceTypeDirectory // beginDefinition; resourceTypeDirectory[ rtype_String ] := Enclose[ Module[ { root, typeName }, - root = ConfirmBy[ $ResourceInstallationDirectory, DirectoryQ, "RootDirectory" ]; + root = ConfirmBy[ $ResourceInstallationDirectory, StringQ, "RootDirectory" ]; typeName = ConfirmBy[ resourceTypeDirectoryName @ rtype, StringQ, "TypeName" ]; ConfirmBy[ GeneralUtilities`EnsureDirectory @ { root, typeName }, DirectoryQ, "Directory" ] ], diff --git a/Source/Chatbook/Sandbox.wl b/Source/Chatbook/Sandbox.wl index be44f2ec..59da3905 100644 --- a/Source/Chatbook/Sandbox.wl +++ b/Source/Chatbook/Sandbox.wl @@ -194,7 +194,7 @@ pingSandboxKernel[ kernel_LinkObject ] := Enclose[ IntegerQ, "ProcessID" ] - ] + ] // LogChatTiming[ "PingSandboxKernel" ] ]; pingSandboxKernel // endDefinition; @@ -300,8 +300,8 @@ startSandboxKernel[ ] := Enclose[ Quiet @ LinkClose @ kernel; throwFailure[ "NoSandboxKernel" ] ] - ], - throwInternalFailure[ startSandboxKernel[ ], ## ] & + ] // LogChatTiming[ "StartSandboxKernel" ], + throwInternalFailure ]; startSandboxKernel // endDefinition; @@ -437,7 +437,7 @@ $messageOverrides := $messageOverrides = Flatten @ Apply[ sandboxEvaluate // beginDefinition; sandboxEvaluate[ KeyValuePattern[ "code" -> code_ ] ] := sandboxEvaluate @ code; -sandboxEvaluate[ code_String ] := sandboxEvaluate @ toSandboxExpression @ code; +sandboxEvaluate[ code_String ] := sandboxEvaluate @ toSandboxExpression @ code // LogChatTiming[ "SandboxEvaluate" ]; sandboxEvaluate[ HoldComplete[ xs__, x_ ] ] := sandboxEvaluate @ HoldComplete @ CompoundExpression[ xs, x ]; sandboxEvaluate[ HoldComplete[ eval_ ] ] /; useCloudSandboxQ[ ] := cloudSandboxEvaluate @ HoldComplete @ eval; sandboxEvaluate[ HoldComplete[ eval_ ] ] /; useSessionQ[ ] := sessionEvaluate @ HoldComplete @ eval; @@ -832,7 +832,23 @@ toSandboxExpression[ s_String, $Failed ] /; StringContainsQ[ s, "'" ] := ] ]; -toSandboxExpression[ s_String, $Failed ] := HoldComplete @ ToExpression[ s, InputForm ]; +toSandboxExpression[ s_String, $Failed ] := + Module[ { openers, closers, new, held }, + openers = StringCount[ s, "[" ]; + closers = StringCount[ s, "]" ]; + ( + new = s <> StringRepeat[ "]", openers - closers ]; + held = Quiet @ ToExpression[ new, InputForm, HoldComplete ]; + If[ MatchQ[ held, _HoldComplete ], + sandboxStringNormalize[ s ] = new; + held, + HoldComplete[ ToExpression[ s, InputForm ] ] + ] + ) /; openers > closers + ]; + +toSandboxExpression[ s_String, $Failed ] := + HoldComplete @ ToExpression[ s, InputForm ]; toSandboxExpression // endDefinition; diff --git a/Source/Chatbook/Search.wl b/Source/Chatbook/Search.wl new file mode 100644 index 00000000..5609e55f --- /dev/null +++ b/Source/Chatbook/Search.wl @@ -0,0 +1,265 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`Search`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Configuration*) +$rootStorageName = "Search"; +$chatSearchIndex = None; +$searchIndexVersion = 1; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*SearchChats*) +SearchChats // beginDefinition; +SearchChats // Options = { MaxItems -> 10 }; + +SearchChats[ app: _String|All, query_String, opts: OptionsPattern[ ] ] := + catchMine @ LogChatTiming @ searchChats[ app, query, OptionValue[ MaxItems ] ]; + +SearchChats[ query_String, opts: OptionsPattern[ ] ] := + catchMine @ SearchChats[ All, query, opts ]; + +SearchChats // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*searchChats*) +searchChats // beginDefinition; + +searchChats[ appName_String, query_String, max_? Positive ] := Enclose[ + Catch @ Module[ { index, flat, values, vectors, embedding, idx, results }, + + index = Values @ ConfirmBy[ loadChatSearchIndex @ appName, AssociationQ, "Load" ]; + + flat = ConfirmMatch[ + Flatten[ Thread @ { KeyDrop[ #, "Vectors" ], #Vectors } & /@ index, 1 ], + { { _Association, _NumericArray }... } + ]; + + If[ flat === { }, Throw @ { } ]; + + { values, vectors } = ConfirmMatch[ Transpose @ flat, { _, _ }, "Transpose" ]; + + embedding = ConfirmBy[ getEmbedding[ query, "CacheEmbeddings" -> False ], NumericArrayQ, "Embedding" ]; + + idx = ConfirmMatch[ + Nearest[ Normal @ vectors -> "Index", Normal @ embedding, Floor[ 2*max+1 ] ], + { ___Integer }, + "Nearest" + ]; + + results = ConfirmMatch[ values[[ idx ]], { ___Association }, "Results" ]; + + Take[ DeleteDuplicatesBy[ results, Lookup[ "ConversationUUID" ] ], UpTo @ Floor @ max ] + ], + throwInternalFailure +]; + +searchChats // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*AddChatToSearchIndex*) +AddChatToSearchIndex // beginDefinition; + +AddChatToSearchIndex[ as: KeyValuePattern[ "ConversationUUID" -> _String ] ] := + catchMine @ LogChatTiming @ addChatToSearchIndex @ as; + +AddChatToSearchIndex[ uuid_String ] := + catchMine @ LogChatTiming @ addChatToSearchIndex @ uuid; + +AddChatToSearchIndex[ app_String, uuid_String ] := + catchMine @ LogChatTiming @ addChatToSearchIndex @ <| "AppName" -> app, "ConversationUUID" -> uuid |>; + +AddChatToSearchIndex // endExportedDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*addChatToSearchIndex*) +addChatToSearchIndex // beginDefinition; + +addChatToSearchIndex[ spec_ ] := Enclose[ + Catch @ Module[ { data, appName, uuid, vectors, metadata }, + If[ $noSemanticSearch, Throw @ Missing[ "NoSemanticSearch" ] ]; + data = ConfirmMatch[ getChatConversationData @ spec, _Association|_Missing, "Data" ]; + If[ MissingQ @ data, Throw @ Missing[ "NotSaved" ] ]; (* TODO: auto-save here? *) + appName = ConfirmBy[ data[ "AppName" ], StringQ, "AppName" ]; + uuid = ConfirmBy[ data[ "ConversationUUID" ], StringQ, "ConversationUUID" ]; + vectors = ConfirmMatch[ data[ "Vectors" ], { ___NumericArray }, "Vectors" ]; + If[ vectors === { }, Throw @ Missing[ "NoVectors" ] ]; + + ConfirmBy[ loadChatSearchIndex @ appName, AssociationQ, "Load" ]; + ConfirmAssert[ AssociationQ @ $chatSearchIndex[ appName ], "CheckIndex" ]; + + metadata = ConfirmBy[ getChatMetadata @ data, AssociationQ, "Metadata" ]; + $chatSearchIndex[ appName, uuid ] = <| metadata, "Vectors" -> vectors |>; + ConfirmBy[ saveChatIndex @ appName, FileExistsQ, "Save" ]; + + Success[ "AddedChatToSearchIndex", <| "AppName" -> appName, "ConversationUUID" -> uuid |> ] + ], + throwInternalFailure +]; + +addChatToSearchIndex // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*RebuildChatSearchIndex*) +RebuildChatSearchIndex // beginDefinition; +RebuildChatSearchIndex[ appName_String ] := catchMine @ LogChatTiming @ rebuildChatSearchIndex @ appName; +RebuildChatSearchIndex[ All ] := catchMine @ LogChatTiming @ rebuildChatSearchIndex @ All; +RebuildChatSearchIndex[ ] := catchMine @ LogChatTiming @ rebuildChatSearchIndex @ All; +RebuildChatSearchIndex // endExportedDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*rebuildChatSearchIndex*) +rebuildChatSearchIndex // beginDefinition; + +rebuildChatSearchIndex[ appName_String ] := Enclose[ + Module[ { root, chats }, + + root = ConfirmBy[ + ChatbookFilesDirectory[ { $rootStorageName, appName }, "EnsureDirectory" -> False ], + StringQ, + "Root" + ]; + + If[ DirectoryQ @ root, ConfirmMatch[ DeleteDirectory[ root, DeleteContents -> True ], Null, "Delete" ] ]; + + If[ ! AssociationQ @ $chatSearchIndex, $chatSearchIndex = <| |> ]; + chats = ConfirmMatch[ ListSavedChats @ appName, { ___Association }, "Chats" ]; + ConfirmMatch[ addChatToSearchIndex /@ chats, { ___Success }, "AddChatToSearchIndex" ]; + ConfirmBy[ saveChatIndex @ appName, FileExistsQ, "Save" ]; + ConfirmBy[ $chatSearchIndex[ appName ], AssociationQ, "Result" ] + ], + throwInternalFailure +]; + +rebuildChatSearchIndex[ All ] := Enclose[ + Module[ { root, chats }, + + root = ConfirmBy[ + ChatbookFilesDirectory[ $rootStorageName, "EnsureDirectory" -> False ], + StringQ, + "Root" + ]; + + If[ DirectoryQ @ root, ConfirmMatch[ DeleteDirectory[ root, DeleteContents -> True ], Null, "Delete" ] ]; + + $chatSearchIndex = <| |>; + chats = ConfirmMatch[ ListSavedChats[ ], { ___Association }, "Chats" ]; + ConfirmMatch[ addChatToSearchIndex /@ chats, { ___Success }, "AddChatToSearchIndex" ]; + ConfirmMatch[ saveChatIndex[ ], { ___? FileExistsQ }, "Save" ]; + $chatSearchIndex + ], + throwInternalFailure +]; + +rebuildChatSearchIndex // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Loading/Saving*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*loadChatSearchIndex*) +loadChatSearchIndex // beginDefinition; + +loadChatSearchIndex[ appName_String ] := Enclose[ + Catch @ Module[ { root, file, data, index }, + + If[ ! AssociationQ @ $chatSearchIndex, $chatSearchIndex = <| |> ]; + + If[ AssociationQ @ $chatSearchIndex[ appName ], + Throw @ $chatSearchIndex[ appName ], + $chatSearchIndex[ appName ] = <| |> + ]; + + root = ConfirmBy[ + ChatbookFilesDirectory[ { $rootStorageName, appName }, "EnsureDirectory" -> False ], + StringQ, + "Root" + ]; + + file = FileNameJoin @ { root, "index.wxf" }; + If[ ! FileExistsQ @ file, Throw @ rebuildChatSearchIndex @ appName ]; + + data = Quiet @ Developer`ReadWXFFile @ file; + If[ ! AssociationQ @ data, Throw @ rebuildChatSearchIndex @ appName ]; + + index = ConfirmBy[ data[ "Index" ], AssociationQ, "Index" ]; + $chatSearchIndex[ appName ] = index + ], + throwInternalFailure +]; + +loadChatSearchIndex[ All ] := Enclose[ + Module[ { root, files, names }, + If[ ! AssociationQ @ $chatSearchIndex, $chatSearchIndex = <| |> ]; + + root = ConfirmBy[ + ChatbookFilesDirectory[ $rootStorageName, "EnsureDirectory" -> False ], + StringQ, + "Root" + ]; + + If[ ! DirectoryQ @ root, Throw @ $chatSearchIndex ]; + + files = ConfirmMatch[ FileNames[ "index.wxf", root, { 2 } ], { ___String }, "Files" ]; + If[ files === { }, Throw @ $chatSearchIndex ]; + + names = ConfirmMatch[ FileBaseName @* DirectoryName /@ files, { __String }, "Names" ]; + ConfirmMatch[ loadChatSearchIndex /@ names, { ___Association }, "Load" ]; + + $chatSearchIndex + ], + throwInternalFailure +]; + +loadChatSearchIndex // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*saveChatIndex*) +saveChatIndex // beginDefinition; + +saveChatIndex[ appName_String ] := Enclose[ + Module[ { index, root, file, data }, + index = ConfirmBy[ $chatSearchIndex[ appName ], AssociationQ, "Data" ]; + + root = ConfirmBy[ + ChatbookFilesDirectory[ { $rootStorageName, appName }, "EnsureDirectory" -> True ], + StringQ, + "Root" + ]; + + file = FileNameJoin @ { root, "index.wxf" }; + data = <| "Index" -> index, "Version" -> $searchIndexVersion |>; + + ConfirmBy[ Developer`WriteWXFFile[ file, data, PerformanceGoal -> "Size" ], FileExistsQ, "Result" ] + ], + throwInternalFailure +]; + +saveChatIndex[ ] := + saveChatIndex /@ Keys @ $chatSearchIndex; + +saveChatIndex // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/SendChat.wl b/Source/Chatbook/SendChat.wl index 8c78060e..c0e6d5c9 100644 --- a/Source/Chatbook/SendChat.wl +++ b/Source/Chatbook/SendChat.wl @@ -5,11 +5,10 @@ Begin[ "`Private`" ]; (* :!CodeAnalysis::BeginBlock:: *) -Needs[ "Wolfram`Chatbook`" ]; -Needs[ "Wolfram`Chatbook`Actions`" ]; -Needs[ "Wolfram`Chatbook`Common`" ]; -Needs[ "Wolfram`Chatbook`Personas`" ]; -Needs[ "Wolfram`Chatbook`Serialization`" ]; +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Actions`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; +Needs[ "Wolfram`Chatbook`Personas`" ]; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) @@ -53,7 +52,7 @@ sendChat[ evalCell_, nbo_, settings0_ ] /; $useLLMServices := catchTopAs[ Chatbo cells0 = ConfirmMatch[ selectChatCells[ settings, evalCell, nbo ], { __CellObject }, "SelectChatCells" ]; { cells, target } = ConfirmMatch[ - chatHistoryCellsAndTarget @ cells0, + chatHistoryCellsAndTarget @ cells0 // LogChatTiming[ "ChatHistoryCellsAndTarget" ], { { __CellObject }, _CellObject | None }, "HistoryAndTarget" ]; @@ -71,7 +70,7 @@ sendChat[ evalCell_, nbo_, settings0_ ] /; $useLLMServices := catchTopAs[ Chatbo { messages, data } = Reap[ ConfirmMatch[ - constructMessages[ settings, cells ], + constructMessages[ settings, cells ] // LogChatTiming[ "ConstructMessages" ], { __Association }, "MakeHTTPRequest" ], @@ -120,14 +119,14 @@ sendChat[ evalCell_, nbo_, settings0_ ] /; $useLLMServices := catchTopAs[ Chatbo CurrentValue[ evalCell, CellDingbat ], TemplateBox[ { }, "ChatInputActiveCellDingbat" ] -> TemplateBox[ { }, "ChatInputCellDingbat" ] ] - ] + ] // LogChatTiming[ "SetCellDingbat" ] ]; cellObject = $lastCellObject = ConfirmMatch[ createNewChatOutput[ settings, target, cell ], _CellObject, "CreateOutput" - ]; + ] // LogChatTiming[ "CreateChatOutput" ]; applyHandlerFunction[ settings, @@ -140,7 +139,7 @@ sendChat[ evalCell_, nbo_, settings0_ ] /; $useLLMServices := catchTopAs[ Chatbo |> ]; - task = $lastTask = chatSubmit[ container, messages, cellObject, settings ]; + task = $lastTask = chatSubmit[ container, prepareMessagesForLLM @ messages, cellObject, settings ]; addHandlerArguments[ "Task" -> task ]; @@ -341,19 +340,26 @@ makeHTTPRequest // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) -(*makeStopTokens*) -makeStopTokens // beginDefinition; +(*prepareMessagesForLLM*) +prepareMessagesForLLM // beginDefinition; -makeStopTokens[ settings_Association ] := - Select[ - DeleteDuplicates @ Flatten @ { - settings[ "StopTokens" ], - If[ settings[ "ToolMethod" ] === "Simple", { "\n/exec", "/end" }, { "ENDTOOLCALL", "/end" } ], - If[ TrueQ @ $AutomaticAssistance, "[INFO]", Nothing ] - }, - StringQ +prepareMessagesForLLM[ messages: { ___Association } ] := ReplaceAll[ + messages, + s_String :> RuleCondition @ StringTrim @ StringReplace[ + s, + "\nENDRESULT(" ~~ Repeated[ LetterCharacter|DigitCharacter, $tinyHashLength ] ~~ ")\n" :> "\nENDRESULT\n" + ] ]; +prepareMessagesForLLM // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*makeStopTokens*) +makeStopTokens // beginDefinition; +makeStopTokens[ settings_Association ] := makeStopTokens[ settings, settings[ "StopTokens" ] ]; +makeStopTokens[ settings_, None | { } ] := Missing[ ]; +makeStopTokens[ settings_, tokens: { __String } ] := tokens; makeStopTokens // endDefinition; (* ::**************************************************************************************************************:: *) @@ -370,7 +376,10 @@ chatIndicatorSymbol // endDefinition; (* ::Subsubsection::Closed:: *) (*prepareMessagesForHTTPRequest*) prepareMessagesForHTTPRequest // beginDefinition; -prepareMessagesForHTTPRequest[ messages_List ] := $lastHTTPMessages = prepareMessageForHTTPRequest /@ messages; + +prepareMessagesForHTTPRequest[ messages_List ] := + $lastHTTPMessages = prepareMessagesForLLM[ prepareMessageForHTTPRequest /@ messages ]; + prepareMessagesForHTTPRequest // endDefinition; (* ::**************************************************************************************************************:: *) @@ -526,6 +535,43 @@ chatSubmit // endDefinition; chatSubmit0 // beginDefinition; chatSubmit0 // Attributes = { HoldFirst }; +(* Currently used for o1 models since they don't support streaming: *) +chatSubmit0[ + container_, + messages: { __Association }, + cellObject_, + settings_ +] /; settings[ "ForceSynchronous" ] := Enclose[ + Module[ { auth, stop, result }, + auth = settings[ "Authentication" ]; + stop = makeStopTokens @ settings; + + result = ConfirmMatch[ + Quiet[ + LLMServices`Chat[ + standardizeMessageKeys @ messages, + makeLLMConfiguration @ settings, + Authentication -> auth + ], + { LLMServices`Chat::unsupported } + ], + _Association | _Failure, + "ChatResult" + ]; + + If[ FailureQ @ result, throwTop @ writeErrorCell[ cellObject, result ] ]; + + writeChunk[ Dynamic @ container, cellObject, <| "BodyChunkProcessed" -> result[ "Content" ] |> ]; + logUsage @ container; + trimStopTokens[ container, stop ]; + checkResponse[ settings, Unevaluated @ container, cellObject, <| |> ]; + + (* This cannot return a TaskObject: *) + None + ], + throwInternalFailure +]; + chatSubmit0[ container_, messages: { __Association }, cellObject_, settings_ ] := Quiet[ Needs[ "LLMServices`" -> None ]; $lastChatSubmitResult = ReleaseHold[ @@ -537,7 +583,8 @@ chatSubmit0[ container_, messages: { __Association }, cellObject_, settings_ ] : makeLLMConfiguration @ settings, Authentication -> settings[ "Authentication" ], HandlerFunctions -> chatHandlers[ container, cellObject, settings ], - HandlerFunctionsKeys -> chatHandlerFunctionsKeys @ settings + HandlerFunctionsKeys -> chatHandlerFunctionsKeys @ settings, + "TestConnection" -> False ], <| "Container" :> container, @@ -584,7 +631,7 @@ makeLLMConfiguration[ as: KeyValuePattern[ "Model" -> model_String ] ] := makeLLMConfiguration @ Append[ as, "Model" -> { "OpenAI", model } ]; makeLLMConfiguration[ as_Association ] := - $lastLLMConfiguration = LLMConfiguration @ Association[ + $lastLLMConfiguration = LLMConfiguration @ DeleteMissing @ Association[ KeyTake[ as, { "Model", "MaxTokens", "Temperature", "PresencePenalty" } ], "StopTokens" -> makeStopTokens @ as ]; @@ -679,7 +726,7 @@ trimStopTokens[ container_, stop: { ___String } ] := ) /; StringQ @ full ]; -trimStopTokens[ container_, { ___String } ] := +trimStopTokens[ container_, { ___String } | _Missing ] := Null; trimStopTokens // endDefinition; @@ -725,10 +772,10 @@ withFETasks // endDefinition; writeChunk // beginDefinition; writeChunk[ container_, cell_, KeyValuePattern[ "BodyChunkProcessed" -> chunks_ ] ] := - With[ { chunk = StringJoin @ Select[ Flatten @ { chunks }, StringQ ] }, - If[ chunk === "", + With[ { strings = extractBodyChunks @ chunks }, + If[ ! MatchQ[ strings, { __String } ], Null, - writeChunk0[ container, cell, chunk, chunk ] + With[ { chunk = StringJoin @ strings }, writeChunk0[ container, cell, chunk, chunk ] ] ] ]; @@ -842,7 +889,7 @@ autoCorrect[ string_String ] := StringReplace[ string, $llmAutoCorrectRules ]; autoCorrect // endDefinition; (* cSpell: ignore evaliator *) -$llmAutoCorrectRules = Flatten @ { +$llmAutoCorrectRules := $llmAutoCorrectRules = Flatten @ { "wolfram_language_evaliator" -> "wolfram_language_evaluator", "\\!\\(\\*MarkdownImageBox[\"" ~~ Shortest[ uri__ ] ~~ "\"]\\)" :> uri, "\\!\\(MarkdownImageBox[\"" ~~ Shortest[ uri__ ] ~~ "\"]\\)" :> uri, @@ -974,7 +1021,7 @@ writeResult[ settings_, container_, cell_, as_Association ] := Enclose[ If[ settings[ "BypassResponseChecking" ], Throw @ writeReformattedCell[ settings, container, cell ] ]; log = ConfirmMatch[ Internal`BagPart[ $debugLog, All ], { ___Association }, "DebugLog" ]; - processed = StringJoin @ Cases[ log, KeyValuePattern[ "BodyChunkProcessed" -> s_String ] :> s ]; + processed = StringJoin @ ConfirmMatch[ extractBodyChunks @ log, { ___String }, "Processed" ]; { body, data } = ConfirmMatch[ extractBodyData @ log, { _, _ }, "ExtractBodyData" ]; $lastFullResponseData = <| "Body" -> body, "Processed" -> processed, "Data" -> data |>; @@ -1121,6 +1168,7 @@ toolEvaluation[ settings_, container_Symbol, cell_, as_Association ] := Enclose[ (* Ensure dynamic text is up to date: *) $dynamicTrigger++; $lastDynamicUpdate = AbsoluteTime[ ]; + $toolCallCount = If[ IntegerQ @ $toolCallCount, $toolCallCount + 1, 1 ]; string = ConfirmBy[ container[ "FullContent" ], StringQ, "FullContent" ]; @@ -1134,6 +1182,8 @@ toolEvaluation[ settings_, container_Symbol, cell_, as_Association ] := Enclose[ "ToolRequestParser" ]; + applyHandlerFunction[ settings, "ToolRequestReceived", <| "ToolRequest" -> toolCall |> ]; + toolResponse = ConfirmMatch[ If[ FailureQ @ toolCall, toolCall, @@ -1163,7 +1213,11 @@ toolEvaluation[ settings_, container_Symbol, cell_, as_Association ] := Enclose[ newMessages = Join[ messages, { - <| "Role" -> "assistant", "Content" -> appendToolCallEndToken[ settings, StringTrim @ string ] |>, + <| + "Role" -> "Assistant", + "Content" -> appendToolCallEndToken[ settings, StringTrim @ string ], + "ToolRequest" -> True + |>, makeToolResponseMessage[ settings, response ] } ]; @@ -1171,7 +1225,11 @@ toolEvaluation[ settings_, container_Symbol, cell_, as_Association ] := Enclose[ $finishReason = None; req = If[ TrueQ @ $useLLMServices, - ConfirmMatch[ constructMessages[ settings, newMessages ], { __Association }, "ConstructMessages" ], + ConfirmMatch[ + prepareMessagesForLLM @ constructMessages[ settings, newMessages ], + { __Association }, + "ConstructMessages" + ], (* TODO: this path will be obsolete when LLMServices is widely available *) ConfirmMatch[ makeHTTPRequest[ settings, newMessages ], _HTTPRequest, "HTTPRequest" ] ]; @@ -1185,6 +1243,10 @@ toolEvaluation[ settings_, container_Symbol, cell_, as_Association ] := Enclose[ $dynamicTrigger++; $lastDynamicUpdate = AbsoluteTime[ ]; + applyHandlerFunction[ settings, "ToolResponseReceived", <| "ToolResponse" -> toolResponse |> ]; + + If[ ! sendToolResponseQ[ settings, toolResponse ], StopChat @ cell ]; + task = $lastTask = chatSubmit[ container, req, cell, settings ]; addHandlerArguments[ "Task" -> task ]; @@ -1197,7 +1259,7 @@ toolEvaluation[ settings_, container_Symbol, cell_, as_Association ] := Enclose[ If[ task === $Canceled, StopChat @ cell ]; task - ], + ] // LogChatTiming[ "ToolEvaluation" ], throwInternalFailure ]; @@ -1207,41 +1269,92 @@ toolEvaluation // endDefinition; The user has already been provided with this result, so you do not need to repeat it. Reply with /end if the tool call provides a satisfactory answer, otherwise respond normally."; *) +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*sendToolResponseQ*) +sendToolResponseQ // beginDefinition; +(* TODO: allow one final response when reaching the limit and disable tools for the next chat submit *) +sendToolResponseQ[ KeyValuePattern[ "MaxToolResponses" -> n_Integer ], _ ] /; $toolCallCount > n := False; +sendToolResponseQ[ KeyValuePattern[ "SendToolResponse" -> False ], _ ] := False; +sendToolResponseQ[ _, response_LLMToolResponse ] := ! TrueQ @ terminalToolResponseQ @ response; +sendToolResponseQ[ _, _ ] := True; +sendToolResponseQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*terminalToolResponseQ*) +terminalToolResponseQ // beginDefinition; +terminalToolResponseQ[ res_LLMToolResponse ] := TrueQ @ Or[ terminalQ @ res[ "Tool" ], terminalQ @ res[ "Data" ] ]; +terminalToolResponseQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*terminalQ*) +terminalQ // beginDefinition; +terminalQ[ tool_LLMTool ] := terminalQ @ tool[ "Data" ]; +terminalQ[ KeyValuePattern[ "Output" -> KeyValuePattern[ "SendToolResponse" -> False ] ] ] := True; +terminalQ[ KeyValuePattern[ "SendToolResponse" -> False ] ] := True; +terminalQ[ _ ] := False; +terminalQ // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*makeToolResponseMessage*) makeToolResponseMessage // beginDefinition; -makeToolResponseMessage[ settings_, response_ ] := makeToolResponseMessage0[ serviceName @ settings, response ]; + +makeToolResponseMessage[ settings_, response_ ] := + makeToolResponseMessage[ settings, settings[ "Model" ], response ]; + +makeToolResponseMessage[ settings_, model_Association, response_ ] := + makeToolResponseMessage0[ model[ "Service" ], model[ "Family" ], response ]; + makeToolResponseMessage // endDefinition; + makeToolResponseMessage0 // beginDefinition; -makeToolResponseMessage0[ "Anthropic"|"MistralAI", response_ ] := <| - "Role" -> "User", - "Content" -> Replace[ Flatten @ { "", response, "" }, { s__String } :> StringJoin @ s ] +makeToolResponseMessage0[ "Anthropic"|"MistralAI", family_, response_ ] := <| + "Role" -> "User", + "Content" -> wrapResponse[ "", response, "" ], + "ToolResponse" -> True +|>; + +(* cSpell: ignore Qwen, Nemotron *) +makeToolResponseMessage0[ service_, "Qwen"|"Nemotron"|"Mistral", response_ ] := <| + "Role" -> "User", + "Content" -> wrapResponse[ "", response, "" ], + "ToolResponse" -> True |>; -makeToolResponseMessage0[ service_String, response_ ] := - <| "Role" -> "System", "Content" -> response |>; +(* cSpell: ignore Nemotron *) +(* makeToolResponseMessage0[ service_, "Nemotron", response_ ] := <| + "Role" -> "User", + "Content" -> wrapResponse[ "Tool\n", response, "" ], + "ToolResponse" -> True +|>; + +makeToolResponseMessage0[ service_, "Mistral", response_ ] := <| + "Role" -> "User", + "Content" -> wrapResponse[ "[TOOL_RESULTS] {\"content\": ", response, "} [/TOOL_RESULTS]" ], + "ToolResponse" -> True +|>; *) + +makeToolResponseMessage0[ service_String, family_, response_ ] := + <| "Role" -> "System", "Content" -> response, "ToolResponse" -> True |>; makeToolResponseMessage0 // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) -(*userToolResponseQ*) -userToolResponseQ // beginDefinition; -userToolResponseQ[ settings_ ] := MatchQ[ serviceName @ settings, "Anthropic"|"MistralAI" ]; -userToolResponseQ // endDefinition; +(*wrapResponse*) +wrapResponse // beginDefinition; -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*serviceName*) -serviceName // beginDefinition; -serviceName[ KeyValuePattern[ "Model" -> model_ ] ] := serviceName @ model; -serviceName[ { service_String, _String | $$unspecified } ] := service; -serviceName[ KeyValuePattern[ "Service" -> service_String ] ] := service; -serviceName[ _String | _Association | $$unspecified ] := "OpenAI"; -serviceName // endDefinition; +wrapResponse[ left_, response_, right_ ] := Replace[ + Flatten @ { left, response, right }, + { s__String } :> StringJoin @ s +]; + +wrapResponse // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) @@ -1304,7 +1417,7 @@ selectChatCells[ as_Association? AssociationQ, cell_CellObject, nbo_NotebookObje ] }, $selectedChatCells = selectChatCells0[ cell, clearMinimizedChats @ nbo ] - ]; + ] // LogChatTiming[ "SelectChatCells" ]; selectChatCells // endDefinition; @@ -1741,7 +1854,7 @@ activeAIAssistantCell[ CellTags -> cellTags, CellTrayWidgets -> <| "ChatFeedback" -> <| "Visible" -> False |> |>, PrivateCellOptions -> { "ContentsOpacity" -> 1 }, - TaggingRules -> <| "ChatNotebookSettings" -> smallSettings @ settings |> + TaggingRules -> <| "ChatNotebookSettings" -> toSmallSettings @ settings |> ] ] ]; @@ -1764,8 +1877,8 @@ activeAIAssistantCell[ outer = If[ TrueQ[ $WorkspaceChat||$InlineChat ], assistantMessageBox, # & ] }, Cell[ - BoxData @ outer @ TagBox[ - ToBoxes @ Dynamic[ + BoxData @ TagBox[ + outer @ ToBoxes @ Dynamic[ $dynamicTrigger; (* `$dynamicTrigger` is used to precisely control when the dynamic updates, otherwise we can get an FE crash if a NotebookWrite happens at the same time. *) @@ -1802,7 +1915,7 @@ activeAIAssistantCell[ Selectable -> True, ShowAutoSpellCheck -> False, ShowCursorTracker -> False, - TaggingRules -> <| "ChatNotebookSettings" -> smallSettings @ settings |>, + TaggingRules -> <| "ChatNotebookSettings" -> toSmallSettings @ settings |>, If[ scrollOutputQ @ settings, PrivateCellOptions -> { "TrackScrollingWhenPlaced" -> True }, Sequence @@ { } @@ -2118,7 +2231,10 @@ reformatCell[ settings_, string_, tag_, open_, label_, pageData_, cellTags_, uui outer = If[ TrueQ @ $WorkspaceChat, TextData @ { Cell[ - BoxData @ TemplateBox[ { Cell[ #, Background -> None ] }, "AssistantMessageBox" ], + BoxData @ TemplateBox[ + { Cell[ #, Background -> None, Editable -> True, Selectable -> True ] }, + "AssistantMessageBox" + ], Background -> None ] } &, @@ -2279,7 +2395,7 @@ makeCompactChatData[ BaseEncode @ BinarySerialize[ DeleteCases[ Association[ - smallSettings @ as, + toSmallSettings @ as, "MessageTag" -> tag, "Data" -> Association[ data, @@ -2298,29 +2414,29 @@ makeCompactChatData // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) -(*smallSettings*) -smallSettings // beginDefinition; -smallSettings[ as_Association ] := smallSettings0 @ KeyDrop[ as, { "OpenAIKey", "Tokenizer" } ] /. $exprToNameRules; -smallSettings // endDefinition; +(*toSmallSettings*) +toSmallSettings // beginDefinition; +toSmallSettings[ as_Association ] := toSmallSettings0 @ KeyDrop[ as, { "OpenAIKey", "Tokenizer" } ] /. $exprToNameRules; +toSmallSettings // endDefinition; -smallSettings0 // beginDefinition; +toSmallSettings0 // beginDefinition; -smallSettings0[ as: KeyValuePattern[ "Model" -> model: KeyValuePattern[ "Icon" -> _ ] ] ] := - smallSettings0 @ <| as, "Model" -> KeyTake[ model, { "Service", "Name" } ] |>; +toSmallSettings0[ as: KeyValuePattern[ "Model" -> model: KeyValuePattern[ "Icon" -> _ ] ] ] := + toSmallSettings0 @ <| as, "Model" -> KeyTake[ model, { "Service", "Name" } ] |>; -smallSettings0[ as_Association ] := - smallSettings0[ as, as[ "LLMEvaluator" ] ]; +toSmallSettings0[ as_Association ] := + toSmallSettings0[ as, as[ "LLMEvaluator" ] ]; -smallSettings0[ as_, KeyValuePattern[ "LLMEvaluatorName" -> name_String ] ] := +toSmallSettings0[ as_, KeyValuePattern[ "LLMEvaluatorName" -> name_String ] ] := If[ AssociationQ @ GetCachedPersonaData @ name, Append[ as, "LLMEvaluator" -> name ], as ]; -smallSettings0[ as_, _ ] := +toSmallSettings0[ as_, _ ] := as; -smallSettings0 // endDefinition; +toSmallSettings0 // endDefinition; $exprToNameRules := AssociationMap[ Reverse, $AvailableTools ]; @@ -2541,6 +2657,7 @@ errorBoxes[ as___ ] := (*Package Footer*) addToMXInitialization[ $autoSettingKeyPriority; + $llmAutoCorrectRules; ]; (* :!CodeAnalysis::EndBlock:: *) diff --git a/Source/Chatbook/Serialization.wl b/Source/Chatbook/Serialization.wl index 35262803..d6c81e86 100644 --- a/Source/Chatbook/Serialization.wl +++ b/Source/Chatbook/Serialization.wl @@ -5,7 +5,7 @@ BeginPackage[ "Wolfram`Chatbook`Serialization`" ]; (* Avoiding context aliasing due to bug 434990: *) Needs[ "GeneralUtilities`" -> None ]; -GeneralUtilities`SetUsage[ `CellToString, "\ +GeneralUtilities`SetUsage[ CellToString, "\ CellToString[cell$] serializes a Cell expression as a string for use in chat.\ " ]; @@ -21,20 +21,6 @@ Needs[ "Wolfram`Chatbook`ErrorUtils`" ]; StyleBox[..., FontVariations -> {"StrikeThrough" -> True}] *) -(* TODO: - - There should be a way to pass custom serialization rules in chat settings, e.g. - ``` - "ConversionRules" -> { - _GraphicsBox -> "[Image]", - Cell[box_, "MyStyle"] :> formatMyStyle[box] - } - ``` - - These replacements should be done prior to calling `cellToString`, but need to be tagged in some way so we don't - try to serialize the results again via `fasterCellToString0`. -*) - (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Initialization*) @@ -186,8 +172,15 @@ $escapedMarkdownCharacters = { "`", "$", "*", "_", "#", "|" }; [] () {} + - . ! *) -$leftSelectionIndicator = "\\["<>"BeginSelection"<>"]"; -$rightSelectionIndicator = "\\["<>"EndSelection"<>"]"; +(* $leftSelectionIndicator = "\\["<>"BeginSelection"<>"]"; +$rightSelectionIndicator = "\\["<>"EndSelection"<>"]"; *) + +$leftSelectionIndicator = ""; +$rightSelectionIndicator = ""; + +(* Determines if serialized cell content should be wrapped in ... *) +$includeCellXML = False; +$xmlCellAttributes = { "id" }; (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) @@ -307,7 +300,7 @@ $wolframAlphaInputTemplate = codeTemplate[ "\ (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*CellToString*) -CellToString // SetFallthroughError; +CellToString // beginDefinition; CellToString // Options = { "CharacterEncoding" -> $cellCharacterEncoding, @@ -320,7 +313,9 @@ CellToString // Options = { "MaxOutputCellStringLength" -> $maxOutputCellStringLength, "PageWidth" -> $cellPageWidth, "UnhandledBoxFunction" -> None, - "WindowWidth" -> $windowWidth + "WindowWidth" -> $windowWidth, + "IncludeXML" :> $includeCellXML, + "XMLCellAttributes" :> $xmlCellAttributes }; (* :!CodeAnalysis::BeginBlock:: *) @@ -331,6 +326,7 @@ CellToString[ cell_, opts: OptionsPattern[ ] ] := $cellCharacterEncoding = OptionValue[ "CharacterEncoding" ], $CellToStringDebug = TrueQ @ OptionValue[ "Debug" ], $unhandledBoxFunction = OptionValue[ "UnhandledBoxFunction" ], + $includeCellXML = TrueQ @ OptionValue[ "IncludeXML" ], $cellPageWidth, $windowWidth, $maxCellStringLength, $maxOutputCellStringLength, $contentTypes, $multimodalImages }, @@ -368,6 +364,8 @@ CellToString[ cell_, opts: OptionsPattern[ ] ] := ]; (* :!CodeAnalysis::EndBlock:: *) +CellToString // endExportedDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*applyConversionRules*) @@ -421,13 +419,17 @@ cellToString // beginDefinition; (* Argument normalization *) cellToString[ data: _TextData|_BoxData|_RawData ] := cellToString @ Cell @ data; cellToString[ string_String? StringQ ] := cellToString @ Cell @ string; -cellToString[ cell_CellObject ] := cellToString @ NotebookRead @ cell; +cellToString[ cell_CellObject ] := cellToString @ notebookRead @ cell; (* Multiple cells to one string *) cellToString[ Notebook[ cells_List, ___ ] ] := cellsToString @ cells; cellToString[ Cell @ CellGroupData[ cells_List, _ ] ] := cellsToString @ cells; cellToString[ nbo_NotebookObject ] := cellToString @ Cells @ nbo; -cellToString[ cells: { __CellObject } ] := cellsToString @ NotebookRead @ cells; +cellToString[ cells: { __CellObject } ] := cellsToString @ notebookRead @ cells; + +(* Wrap serialized cell in xml tags for the notebook editor tool: *) +cellToString[ cell_Cell? xmlCellQ ] := + cellToXMLString @ cell; (* Drop cell label for some styles *) cellToString[ Cell[ a__, style: $$noCellLabelStyle, b___, CellLabel -> _, c___ ] ] := @@ -609,6 +611,79 @@ cellsToString[ cells_List ] := ] ]; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*xmlCellQ*) +xmlCellQ // beginDefinition; +xmlCellQ[ Cell[ __, $$chatInputStyle|$$chatOutputStyle, ___ ] ] := False; +xmlCellQ[ _Cell ] := TrueQ @ $includeCellXML; +xmlCellQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*cellToXMLString*) +cellToXMLString // beginDefinition; + +cellToXMLString[ cell_Cell ] := Enclose[ + Catch @ Module[ { string, attributes, attributeString }, + string = ConfirmBy[ Block[ { $includeCellXML = False }, cellToString @ cell ], StringQ, "String" ]; + attributes = ConfirmBy[ cellXMLAttributes @ cell, AssociationQ, "XMLAttributes" ]; + attributeString = StringTrim @ StringRiffle @ KeyValueMap[ StringJoin[ #1, "='", #2, "'" ] &, attributes ]; + If[ StringLength @ attributeString > 0, attributeString = " " <> attributeString ]; + StringJoin[ + "\n", + string, + "\n" + ] + ], + throwInternalFailure +]; + +cellToXMLString // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*cellXMLAttributes*) +cellXMLAttributes // beginDefinition; + +cellXMLAttributes[ cell_Cell ] := DeleteMissing @ AssociationMap[ + Apply @ Rule, + KeyTake[ + <| + "id" :> xmlCellID @ cell, + "style" :> xmlCellStyle @ cell, + "label" :> xmlCellLabel @ cell + |>, + $xmlCellAttributes + ] +]; + +cellXMLAttributes // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*xmlCellID*) +xmlCellID // beginDefinition; +xmlCellID[ Cell[ __, CellObject -> cell_CellObject, ___ ] ] := cellReference @ cell; +xmlCellID[ _Cell ] := Missing[ ]; +xmlCellID // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*xmlCellStyle*) +xmlCellStyle // beginDefinition; +xmlCellStyle[ Cell[ _, style__String, OptionsPattern[ ] ] ] := { style }; +xmlCellStyle[ _Cell ] := Missing[ ]; +xmlCellStyle // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*xmlCellLabel*) +xmlCellLabel // beginDefinition; +xmlCellLabel[ Cell[ __, CellLabel -> label_String, ___ ] ] := label; +xmlCellLabel[ _Cell ] := Missing[ ]; +xmlCellLabel // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*fasterCellToString*) @@ -914,6 +989,9 @@ fasterCellToString0[ NamespaceBox[ ___ ] ] := "\[FreeformPrompt][\""<>query<>"\"]"; +(* FreeformEvaluate *) +fasterCellToString0[ RowBox @ { "=[", query_String, "]" } ] := "\[FreeformPrompt]["<>query<>"]"; + (* ::**************************************************************************************************************:: *) (* ::Subsubsubsection::Closed:: *) (*Graphics*) @@ -1375,6 +1453,16 @@ preprocessTraditionalForm // endDefinition; fasterCellToString0[ SubscriptBox[ "\[InvisiblePrefixScriptBase]", x_ ] ] := fasterCellToString0 @ SubscriptBox[ " ", x ]; +(* Derivative *) +fasterCellToString0[ SuperscriptBox[ f_, "\[Prime]", ___ ] ] := + "Derivative[1][" <> fasterCellToString0 @ f <> "]"; + +fasterCellToString0[ SuperscriptBox[ f_, "\[Prime]\[Prime]", ___ ] ] := + "Derivative[2][" <> fasterCellToString0 @ f <> "]"; + +fasterCellToString0[ SuperscriptBox[ f_, TagBox[ RowBox @ { "(", n_String, ")" }, Derivative ], ___ ] ] := + "Derivative[" <> n <> "][" <> fasterCellToString0 @ f <> "]"; + (* Sqrt *) fasterCellToString0[ SqrtBox[ a_ ] ] := (needsBasePrompt[ "WolframLanguage" ]; "Sqrt["<>fasterCellToString0 @ a<>"]"); @@ -2202,24 +2290,6 @@ makeExpressionString[ box_, _ ] := makeExpressionString[ box ] = makeExpressionString // endDefinition; -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*stringToBoxes*) -stringToBoxes // SetFallthroughError; - -stringToBoxes[ s_String /; StringMatchQ[ s, "\"" ~~ __ ~~ "\"" ] ] := - With[ { str = stringToBoxes @ StringTrim[ s, "\"" ] }, "\""<>str<>"\"" /; StringQ @ str ]; - -stringToBoxes[ string_String ] := - stringToBoxes[ - string, - (* TODO: there could be a kernel implementation of this *) - Quiet @ usingFrontEnd @ MathLink`CallFrontEnd @ FrontEnd`UndocumentedTestFEParserPacket[ string, True ] - ]; - -stringToBoxes[ string_, { BoxData[ boxes_, ___ ], ___ } ] := boxes; -stringToBoxes[ string_, other_ ] := string; - (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*makeGraphicsString*) @@ -2663,6 +2733,14 @@ firstMatchingCellGroup[ nb_, patt_, "Content" ] := Catch[ $cellGroupTag ]; +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Backwards Compatibility*) + +(* The resource function ExportMarkdownString depends on CellToString in the original context: *) +Wolfram`Chatbook`Serialization`CellToString = CellToString; +(* https://resources.wolframcloud.com/FunctionRepository/resources/ExportMarkdownString *) + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Package Footer*) diff --git a/Source/Chatbook/Services.wl b/Source/Chatbook/Services.wl index 398af209..5615907f 100644 --- a/Source/Chatbook/Services.wl +++ b/Source/Chatbook/Services.wl @@ -27,6 +27,16 @@ $llmServicesAvailable := $llmServicesAvailable = ( PacletNewerQ[ PacletObject[ "Wolfram/LLMFunctions" ], "1.2.2" ] ); +$$llmServicesFailure = HoldPattern @ Failure[ + LLMServices`LLMServiceInformation, + KeyValuePattern[ "MessageTemplate" :> LLMServices`LLMServiceInformation::corrupt ] +]; + +(* Used to filter out models that are known not to work with chat notebooks: *) +$invalidModelNameParts = <| + "OpenAI" -> WordBoundary~~("instruct"|"realtime")~~WordBoundary +|>; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*InvalidateServiceCache*) @@ -163,7 +173,7 @@ getModelListQuietly // endDefinition; checkModelList // beginDefinition; checkModelList[ info_, models_List ] := - models; + Select[ models, usableChatModelQ @ info ]; checkModelList[ info_, $Canceled | $Failed | Missing[ "NotConnected" ] ] := Missing[ "NotConnected" ]; @@ -183,6 +193,32 @@ checkModelList[ info_, other_ ] := checkModelList // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*usableChatModelQ*) +usableChatModelQ // beginDefinition; + +usableChatModelQ[ KeyValuePattern[ "Service" -> service_ ] ] := + usableChatModelQ @ service; + +usableChatModelQ[ service_String ] := + With[ { patt = $invalidModelNameParts @ service }, + If[ MissingQ @ patt, + True &, + usableChatModelQ[ patt, # ] & + ] + ]; + +usableChatModelQ[ patt_, model_ ] := Enclose[ + Module[ { name }, + name = ConfirmBy[ toModelName @ model, StringQ, "Name" ]; + ConfirmMatch[ StringFreeQ[ name, patt, IgnoreCase -> True ], True|False, "Result" ] + ], + throwInternalFailure +]; + +usableChatModelQ // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*$availableServices*) @@ -232,6 +268,19 @@ getAvailableServices0[ services0_Association? AssociationQ ] := Enclose[ throwInternalFailure ]; +(* If stored service information is corrupt, attempt to reset it and try again: *) +getAvailableServices0[ $$llmServicesFailure ] := Enclose[ + Catch @ Module[ { services }, + ConfirmMatch[ llm`ResetServices[ ], { __Success }, "Reset" ]; + services = llm`LLMServiceInformation @ llm`ChatSubmit; + (* If it's still failing, return the failure: *) + If[ MatchQ[ services, $$llmServicesFailure ], Throw @ services ]; + (* Otherwise we can proceed normally: *) + getAvailableServices0 @ ConfirmBy[ services, AssociationQ, "Services" ] + ], + throwInternalFailure +]; + getAvailableServices0 // endDefinition; (* ::**************************************************************************************************************:: *) diff --git a/Source/Chatbook/Settings.wl b/Source/Chatbook/Settings.wl index 2e586699..05c72193 100644 --- a/Source/Chatbook/Settings.wl +++ b/Source/Chatbook/Settings.wl @@ -10,7 +10,6 @@ Needs[ "Wolfram`Chatbook`Actions`" ]; Needs[ "Wolfram`Chatbook`Common`" ]; Needs[ "Wolfram`Chatbook`Personas`" ]; Needs[ "Wolfram`Chatbook`ResourceInstaller`" ]; -Needs[ "Wolfram`Chatbook`Serialization`" ]; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) @@ -19,57 +18,70 @@ $cloudInheritanceFix := $cloudNotebooks; (* cSpell: ignore AIAPI *) $defaultChatSettings = <| - "Assistance" -> Automatic, - "Authentication" -> Automatic, - "AutoFormat" -> True, - "BasePrompt" -> Automatic, - "BypassResponseChecking" -> False, - "ChatContextPreprompt" -> Automatic, - "ChatDrivenNotebook" -> False, - "ChatHistoryLength" -> 1000, - "ChatInputIndicator" -> Automatic, - "ConversionRules" -> None, - "DynamicAutoFormat" -> Automatic, - "EnableChatGroupSettings" -> False, - "EnableLLMServices" -> Automatic, - "FrequencyPenalty" -> 0.1, - "HandlerFunctions" :> $DefaultChatHandlerFunctions, - "HandlerFunctionsKeys" -> Automatic, - "IncludeHistory" -> Automatic, - "InitialChatCell" -> True, - "LLMEvaluator" -> "CodeAssistant", - "MaxCellStringLength" -> Automatic, - "MaxContextTokens" -> Automatic, - "MaxOutputCellStringLength" -> Automatic, - "MaxTokens" -> Automatic, - "MergeMessages" -> True, - "Model" :> $DefaultModel, - "Multimodal" -> Automatic, - "NotebookWriteMethod" -> Automatic, - "OpenAIAPICompletionURL" -> "https://api.openai.com/v1/chat/completions", - "OpenAIKey" -> Automatic, - "PresencePenalty" -> 0.1, - "ProcessingFunctions" :> $DefaultChatProcessingFunctions, - "Prompts" -> { }, - "SetCellDingbat" -> True, - "ShowMinimized" -> Automatic, - "StreamingOutputMethod" -> Automatic, - "TabbedOutput" -> True, (* TODO: define a "MaxOutputPages" setting *) - "TargetCloudObject" -> Automatic, - "Temperature" -> 0.7, - "TokenBudgetMultiplier" -> Automatic, - "Tokenizer" -> Automatic, - "ToolCallExamplePromptStyle" -> Automatic, - "ToolCallFrequency" -> Automatic, - "ToolExamplePrompt" -> Automatic, - "ToolMethod" -> Automatic, - "ToolOptions" :> $DefaultToolOptions, - "Tools" -> Automatic, - "ToolSelectionType" -> <| |>, - "ToolsEnabled" -> Automatic, - "TopP" -> 1, - "TrackScrollingWhenPlaced" -> Automatic, - "VisiblePersonas" -> $corePersonaNames + "AppName" -> Automatic, + "Assistance" -> Automatic, + "Authentication" -> Automatic, + "AutoFormat" -> True, + "AutoSaveConversations" -> Automatic, + "BasePrompt" -> Automatic, + "BypassResponseChecking" -> Automatic, + "ChatContextPreprompt" -> Automatic, + "ChatDrivenNotebook" -> False, + "ChatHistoryLength" -> 1000, + "ChatInputIndicator" -> Automatic, + "ConversationUUID" -> None, + "ConversionRules" -> None, + "DynamicAutoFormat" -> Automatic, + "EnableChatGroupSettings" -> False, + "EnableLLMServices" -> Automatic, + "ForceSynchronous" -> Automatic, + "FrequencyPenalty" -> 0.1, + "HandlerFunctions" :> $DefaultChatHandlerFunctions, + "HandlerFunctionsKeys" -> Automatic, + "IncludeHistory" -> Automatic, + "InitialChatCell" -> True, + "LLMEvaluator" -> "CodeAssistant", + "MaxCellStringLength" -> Automatic, + "MaxContextTokens" -> Automatic, + "MaxOutputCellStringLength" -> Automatic, + "MaxTokens" -> Automatic, + "MaxToolResponses" -> 5, + "MergeMessages" -> True, + "Model" :> $DefaultModel, + "Multimodal" -> Automatic, + "NotebookWriteMethod" -> Automatic, + "OpenAIAPICompletionURL" -> "https://api.openai.com/v1/chat/completions", + "OpenAIKey" -> Automatic, + "OpenToolCallBoxes" -> Automatic, + "PresencePenalty" -> 0.1, + "ProcessingFunctions" :> $DefaultChatProcessingFunctions, + "PromptGeneratorMessagePosition" -> 2, + "PromptGeneratorMessageRole" -> "System", + "PromptGenerators" -> { }, + "PromptGeneratorsEnabled" -> Automatic, (* TODO *) + "Prompts" -> { }, + "SendToolResponse" -> Automatic, + "SetCellDingbat" -> True, + "ShowMinimized" -> Automatic, + "StopTokens" -> Automatic, + "StreamingOutputMethod" -> Automatic, + "TabbedOutput" -> True, (* TODO: define a "MaxOutputPages" setting *) + "TargetCloudObject" -> Automatic, + "Temperature" -> 0.7, + "TimeConstraint" -> Automatic, + "TokenBudgetMultiplier" -> Automatic, + "Tokenizer" -> Automatic, + "ToolCallExamplePromptStyle" -> Automatic, + "ToolCallFrequency" -> Automatic, + "ToolExamplePrompt" -> Automatic, + "ToolMethod" -> Automatic, + "ToolOptions" :> $DefaultToolOptions, + "Tools" -> Automatic, + "ToolSelectionType" -> <| |>, + "ToolsEnabled" -> Automatic, + "TopP" -> 1, + "TrackScrollingWhenPlaced" -> Automatic, + "VisiblePersonas" -> $corePersonaNames |>; $cachedGlobalSettings := $cachedGlobalSettings = getGlobalSettingsFile[ ]; @@ -108,9 +120,11 @@ $DefaultModel = <| "Service" -> "OpenAI", "Name" -> "gpt-4o" |>; (* ::Subsection::Closed:: *) (*Handler Functions*) $DefaultChatHandlerFunctions = <| - "ChatAbort" :> $ChatAbort, - "ChatPost" :> $ChatPost, - "ChatPre" :> $ChatPre + "ChatAbort" :> $ChatAbort, + "ChatPost" :> $ChatPost, + "ChatPre" :> $ChatPre, + "ToolRequestReceived" -> None, + "ToolResponseGenerated" -> None |>; (* ::**************************************************************************************************************:: *) @@ -237,11 +251,12 @@ resolveAutoSettings[ settings0_Association ] := Enclose[ $initialCellStringBudget = makeCellStringBudget @ resolved; $cellStringBudget = $initialCellStringBudget; $conversionRules = resolved[ "ConversionRules" ]; + $openToolCallBoxes = resolved[ "OpenToolCallBoxes" ]; ]; If[ $catching, $currentChatSettings = resolved ]; resolved - ], + ] // LogChatTiming[ "ResolveAutoSettings" ], throwInternalFailure ]; @@ -255,18 +270,20 @@ resolveAutoSettings0[ settings: KeyValuePattern[ _ :> _ ] ] := resolveAutoSettings @ AssociationMap[ Apply @ Rule, settings ]; resolveAutoSettings0[ settings_Association ] := Enclose[ - Module[ { auto, sorted, resolved, result }, + Module[ { auto, sorted, resolved, override, result }, auto = ConfirmBy[ Select[ settings, SameAs @ Automatic ], AssociationQ, "Auto" ]; sorted = ConfirmBy[ <| KeyTake[ auto, $autoSettingKeyPriority ], auto |>, AssociationQ, "Sorted" ]; resolved = ConfirmBy[ Fold[ resolveAutoSetting, settings, Normal @ sorted ], AssociationQ, "Resolved" ]; + override = ConfirmBy[ overrideSettings @ resolved, AssociationQ, "Override" ]; If[ $chatState, - If[ resolved[ "Assistance" ], $AutomaticAssistance = True ]; - If[ resolved[ "WorkspaceChat" ], $WorkspaceChat = True ]; + If[ override[ "Assistance" ], $AutomaticAssistance = True ]; + If[ override[ "WorkspaceChat" ], $WorkspaceChat = True ]; ]; - result = ConfirmBy[ resolveTools @ KeySort @ resolved, AssociationQ, "ResolveTools" ]; + result = ConfirmBy[ resolveTools @ KeySort @ override, AssociationQ, "ResolveTools" ]; If[ result[ "ToolMethod" ] === Automatic, result[ "ToolMethod" ] = chooseToolMethod @ result ]; + result[ "StopTokens" ] = autoStopTokens @ result; result ], throwInternalFailure @@ -274,6 +291,31 @@ resolveAutoSettings0[ settings_Association ] := Enclose[ resolveAutoSettings0 // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*overrideSettings*) +overrideSettings // beginDefinition; +overrideSettings[ settings_Association? o1ModelQ ] := <| settings, $o1Overrides |>; +overrideSettings[ settings_Association? gpt4oTextToolsQ ] := <| settings, $gpt4oTextToolOverrides |>; +overrideSettings[ settings_Association ] := settings; +overrideSettings // endDefinition; + +$o1Overrides = <| "PresencePenalty" -> 0, "Temperature" -> 1 |>; +$gpt4oTextToolOverrides = <| "Model" -> <| "Service" -> "OpenAI", "Name" -> "gpt-4o-2024-05-13" |> |>; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*gpt4oTextToolsQ*) +gpt4oTextToolsQ // beginDefinition; + +gpt4oTextToolsQ[ settings_Association ] := TrueQ @ And[ + settings[ "ToolsEnabled" ], + toModelName @ settings === "gpt-4o", + settings[ "ToolMethod" ] =!= "Service" +]; + +gpt4oTextToolsQ // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*evaluateSettings*) @@ -290,42 +332,54 @@ resolveAutoSetting[ settings_, key_ -> value_ ] := <| settings, key -> resolveAu resolveAutoSetting // endDefinition; resolveAutoSetting0 // beginDefinition; -resolveAutoSetting0[ as_, "Assistance" ] := False; -resolveAutoSetting0[ as_, "ChatInputIndicator" ] := "\|01f4ac"; -resolveAutoSetting0[ as_, "DynamicAutoFormat" ] := dynamicAutoFormatQ @ as; -resolveAutoSetting0[ as_, "EnableLLMServices" ] := $useLLMServices; -resolveAutoSetting0[ as_, "HandlerFunctionsKeys" ] := chatHandlerFunctionsKeys @ as; -resolveAutoSetting0[ as_, "IncludeHistory" ] := Automatic; -resolveAutoSetting0[ as_, "MaxCellStringLength" ] := chooseMaxCellStringLength @ as; -resolveAutoSetting0[ as_, "MaxContextTokens" ] := autoMaxContextTokens @ as; -resolveAutoSetting0[ as_, "MaxOutputCellStringLength" ] := chooseMaxOutputCellStringLength @ as; -resolveAutoSetting0[ as_, "MaxTokens" ] := autoMaxTokens @ as; -resolveAutoSetting0[ as_, "Multimodal" ] := multimodalQ @ as; -resolveAutoSetting0[ as_, "NotebookWriteMethod" ] := "PreemptiveLink"; -resolveAutoSetting0[ as_, "ShowMinimized" ] := Automatic; -resolveAutoSetting0[ as_, "StreamingOutputMethod" ] := "PartialDynamic"; -resolveAutoSetting0[ as_, "TokenBudgetMultiplier" ] := 1; -resolveAutoSetting0[ as_, "Tokenizer" ] := getTokenizer @ as; -resolveAutoSetting0[ as_, "TokenizerName" ] := getTokenizerName @ as; -resolveAutoSetting0[ as_, "ToolCallExamplePromptStyle" ] := chooseToolExamplePromptStyle @ as; -resolveAutoSetting0[ as_, "ToolCallFrequency" ] := Automatic; -resolveAutoSetting0[ as_, "ToolExamplePrompt" ] := chooseToolExamplePromptSpec @ as; -resolveAutoSetting0[ as_, "ToolsEnabled" ] := toolsEnabledQ @ as; -resolveAutoSetting0[ as_, "TrackScrollingWhenPlaced" ] := scrollOutputQ @ as; -resolveAutoSetting0[ as_, key_String ] := Automatic; +resolveAutoSetting0[ as_, "AppName" ] := $defaultAppName; +resolveAutoSetting0[ as_, "Assistance" ] := False; +resolveAutoSetting0[ as_, "AutoSaveConversations" ] := autoSaveConversationsQ @ as; +resolveAutoSetting0[ as_, "BypassResponseChecking" ] := bypassResponseCheckingQ @ as; +resolveAutoSetting0[ as_, "ChatInputIndicator" ] := "\|01f4ac"; +resolveAutoSetting0[ as_, "DynamicAutoFormat" ] := dynamicAutoFormatQ @ as; +resolveAutoSetting0[ as_, "EnableLLMServices" ] := $useLLMServices; +resolveAutoSetting0[ as_, "ForceSynchronous" ] := forceSynchronousQ @ as; +resolveAutoSetting0[ as_, "HandlerFunctionsKeys" ] := chatHandlerFunctionsKeys @ as; +resolveAutoSetting0[ as_, "IncludeHistory" ] := Automatic; +resolveAutoSetting0[ as_, "MaxCellStringLength" ] := chooseMaxCellStringLength @ as; +resolveAutoSetting0[ as_, "MaxContextTokens" ] := autoMaxContextTokens @ as; +resolveAutoSetting0[ as_, "MaxOutputCellStringLength" ] := chooseMaxOutputCellStringLength @ as; +resolveAutoSetting0[ as_, "MaxTokens" ] := autoMaxTokens @ as; +resolveAutoSetting0[ as_, "Multimodal" ] := multimodalQ @ as; +resolveAutoSetting0[ as_, "NotebookWriteMethod" ] := "PreemptiveLink"; +resolveAutoSetting0[ as_, "OpenToolCallBoxes" ] := openToolCallBoxesQ @ as; +resolveAutoSetting0[ as_, "PromptGeneratorMessagePosition" ] := 2; +resolveAutoSetting0[ as_, "PromptGeneratorMessageRole" ] := "System"; +resolveAutoSetting0[ as_, "PromptGenerators" ] := { }; +resolveAutoSetting0[ as_, "ShowMinimized" ] := Automatic; +resolveAutoSetting0[ as_, "StreamingOutputMethod" ] := "PartialDynamic"; +resolveAutoSetting0[ as_, "TokenBudgetMultiplier" ] := 1; +resolveAutoSetting0[ as_, "Tokenizer" ] := getTokenizer @ as; +resolveAutoSetting0[ as_, "TokenizerName" ] := getTokenizerName @ as; +resolveAutoSetting0[ as_, "ToolCallExamplePromptStyle" ] := chooseToolExamplePromptStyle @ as; +resolveAutoSetting0[ as_, "ToolCallFrequency" ] := Automatic; +resolveAutoSetting0[ as_, "ToolExamplePrompt" ] := chooseToolExamplePromptSpec @ as; +resolveAutoSetting0[ as_, "ToolsEnabled" ] := toolsEnabledQ @ as; +resolveAutoSetting0[ as_, "TrackScrollingWhenPlaced" ] := scrollOutputQ @ as; +resolveAutoSetting0[ as_, key_String ] := Automatic; resolveAutoSetting0 // endDefinition; (* Settings that require other settings to be resolved first: *) $autoSettingKeyDependencies = <| + "AutoSaveConversations" -> { "AppName", "ConversationUUID" }, + "BypassResponseChecking" -> "ForceSynchronous", + "ForceSynchronous" -> "Model", "HandlerFunctionsKeys" -> "EnableLLMServices", "MaxCellStringLength" -> { "Model", "MaxContextTokens" }, "MaxContextTokens" -> "Model", "MaxOutputCellStringLength" -> "MaxCellStringLength", "MaxTokens" -> "Model", "Multimodal" -> { "EnableLLMServices", "Model" }, + "OpenToolCallBoxes" -> "SendToolResponse", "Tokenizer" -> "TokenizerName", "TokenizerName" -> "Model", - "ToolCallExamplePromptStyle" -> "Model", + "ToolCallExamplePromptStyle" -> { "Model", "ToolsEnabled" }, "ToolExamplePrompt" -> "Model", "Tools" -> { "LLMEvaluator", "ToolsEnabled" }, "ToolsEnabled" -> { "Model", "ToolCallFrequency" } @@ -348,6 +402,34 @@ $autoSettingKeyPriority := Enclose[ * ChatContextPreprompt *) +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*openToolCallBoxesQ*) +openToolCallBoxesQ // beginDefinition; +openToolCallBoxesQ[ as_Association ] := If[ as[ "SendToolResponse" ] === False, True, Automatic ]; +openToolCallBoxesQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*bypassResponseCheckingQ*) +bypassResponseCheckingQ // beginDefinition; +bypassResponseCheckingQ[ as_Association ] := TrueQ @ as[ "ForceSynchronous" ]; +bypassResponseCheckingQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*forceSynchronousQ*) +forceSynchronousQ // beginDefinition; +forceSynchronousQ[ as_Association ] := TrueQ @ Or[ o1ModelQ @ as, serviceName @ as === "GoogleGemini" ]; +forceSynchronousQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*autoSaveConversationsQ*) +autoSaveConversationsQ // beginDefinition; +autoSaveConversationsQ[ as_Association ] := TrueQ[ StringQ @ as[ "AppName" ] && StringQ @ as[ "ConversationUUID" ] ]; +autoSaveConversationsQ // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*chooseToolMethod*) @@ -388,21 +470,89 @@ autoToolExamplePromptSpec // endDefinition; (* ::Subsubsection::Closed:: *) (*chooseToolExamplePromptStyle*) chooseToolExamplePromptStyle // beginDefinition; -chooseToolExamplePromptStyle[ as_Association ] := chooseToolExamplePromptStyle[ as, as[ "Model" ] ]; -chooseToolExamplePromptStyle[ as_, model_String ] := autoToolExamplePromptStyle[ "OpenAI" ]; -chooseToolExamplePromptStyle[ as_, { service_String, _String } ] := autoToolExamplePromptStyle @ service; -chooseToolExamplePromptStyle[ as_, model_Association ] := autoToolExamplePromptStyle @ model[ "Service" ]; +chooseToolExamplePromptStyle[ KeyValuePattern[ "ToolsEnabled" -> False ] ] := None; +chooseToolExamplePromptStyle[ settings_Association ] := chooseToolExamplePromptStyle[ settings, settings[ "Model" ] ]; +chooseToolExamplePromptStyle[ _, as_Association ] := autoToolExamplePromptStyle[ as[ "Service" ], as[ "Family" ] ]; chooseToolExamplePromptStyle // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsubsubsection::Closed:: *) (*autoToolExamplePromptStyle*) autoToolExamplePromptStyle // beginDefinition; -autoToolExamplePromptStyle[ "AzureOpenAI"|"OpenAI" ] := "ChatML"; -autoToolExamplePromptStyle[ "Anthropic" ] := "XML"; -autoToolExamplePromptStyle[ _ ] := "Basic"; (* TODO: measure performance of other models to choose the best option *) + +autoToolExamplePromptStyle[ service_, family_ ] := autoToolExamplePromptStyle[ service, family ] = + autoToolExamplePromptStyle0[ service, family ]; + autoToolExamplePromptStyle // endDefinition; +(* cSpell: ignore Qwen, Nemotron *) +autoToolExamplePromptStyle0 // beginDefinition; + +(* By service: *) +autoToolExamplePromptStyle0[ "AzureOpenAI", _ ] := "ChatML"; +autoToolExamplePromptStyle0[ "OpenAI" , _ ] := "ChatML"; +autoToolExamplePromptStyle0[ "Anthropic" , _ ] := "XML"; + +(* By model family: *) +autoToolExamplePromptStyle0[ _, "Phi" ] := "Phi"; +autoToolExamplePromptStyle0[ _, "Llama" ] := "Llama"; +autoToolExamplePromptStyle0[ _, "Gemma" ] := "Gemma"; +autoToolExamplePromptStyle0[ _, "Qwen" ] := "ChatML"; +autoToolExamplePromptStyle0[ _, "Nemotron" ] := "Nemotron"; +autoToolExamplePromptStyle0[ _, "Mistral" ] := "Instruct"; +autoToolExamplePromptStyle0[ _, "DeepSeekCoder" ] := "DeepSeekCoder"; + +(* Default: *) +autoToolExamplePromptStyle0[ _, _ ] := "Basic"; + +autoToolExamplePromptStyle0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*autoStopTokens*) +autoStopTokens // beginDefinition; + +autoStopTokens[ as_Association? o1ModelQ ] := + None; + +autoStopTokens[ KeyValuePattern[ "ToolsEnabled" -> False ] ] := + If[ TrueQ @ $AutomaticAssistance, { "[INFO]" }, None ]; + +autoStopTokens[ as_Association ] := Replace[ + DeleteDuplicates @ Flatten @ { + methodStopTokens @ as[ "ToolMethod" ], + styleStopTokens @ as[ "ToolCallExamplePromptStyle" ], + If[ TrueQ @ $AutomaticAssistance, "[INFO]", Nothing ] + }, + { } -> None +]; + +autoStopTokens // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*methodStopTokens*) +(* cSpell: ignore ENDTOOLCALL *) +methodStopTokens // beginDefinition; +methodStopTokens[ "Simple" ] := { "\n/exec", "/end" }; +methodStopTokens[ "Service" ] := { "/end" }; +methodStopTokens[ "Textual"|"JSON" ] := { "ENDTOOLCALL", "/end" }; +methodStopTokens[ _ ] := { "ENDTOOLCALL", "\n/exec", "/end" }; +methodStopTokens // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*styleStopTokens*) +(* cSpell: ignore cbegin *) +styleStopTokens // beginDefinition; +styleStopTokens[ "Phi" ] := { "<|user|>", "<|assistant|>" }; +styleStopTokens[ "Llama" ] := { "<|start_header_id|>" }; +styleStopTokens[ "Gemma" ] := { "" }; +styleStopTokens[ "Nemotron" ] := { "", "" }; +styleStopTokens[ "DeepSeekCoder" ] := { "<\:ff5cbegin\:2581of\:2581sentence\:ff5c>" }; +styleStopTokens[ _String ] := { }; +styleStopTokens // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*chooseMaxCellStringLength*) @@ -425,6 +575,8 @@ chooseMaxOutputCellStringLength // endDefinition; (* ::Subsubsection::Closed:: *) (*autoMaxContextTokens*) autoMaxContextTokens // beginDefinition; +(* cSpell: ignore ollama *) +autoMaxContextTokens[ as_? ollamaQ ] := serviceMaxContextTokens @ as; autoMaxContextTokens[ as_Association ] := autoMaxContextTokens[ as, as[ "Model" ] ]; autoMaxContextTokens[ as_, model_ ] := autoMaxContextTokens[ as, model, toModelName @ model ]; autoMaxContextTokens[ _, _, name_String ] := autoMaxContextTokens0 @ name; @@ -432,7 +584,8 @@ autoMaxContextTokens // endDefinition; autoMaxContextTokens0 // beginDefinition; autoMaxContextTokens0[ name_String ] := autoMaxContextTokens0 @ StringSplit[ name, "-"|Whitespace ]; -autoMaxContextTokens0[ { ___, "gpt", "4o" , ___ } ] := 2^17; +autoMaxContextTokens0[ { ___, "o1" , ___ } ] := 2^17; +autoMaxContextTokens0[ { ___, "gpt"|"chatgpt", "4o" , ___ } ] := 2^17; autoMaxContextTokens0[ { ___, "gpt", "4", "vision" , ___ } ] := 2^17; autoMaxContextTokens0[ { ___, "gpt", "4", "turbo" , ___ } ] := 2^17; autoMaxContextTokens0[ { ___, "claude", "2" , ___ } ] := 10^5; @@ -444,9 +597,36 @@ autoMaxContextTokens0[ { ___, "gpt", "3.5" , ___ } ] := 2^12; autoMaxContextTokens0[ { ___, "chat", "bison", "001" , ___ } ] := 20000; autoMaxContextTokens0[ { ___, "gemini", ___, "pro", "vision", ___ } ] := 12288; autoMaxContextTokens0[ { ___, "gemini", ___, "pro" , ___ } ] := 30720; +autoMaxContextTokens0[ { ___, "phi3.5" , ___ } ] := 2^17; autoMaxContextTokens0[ _List ] := 2^12; autoMaxContextTokens0 // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*ollamaQ*) +ollamaQ // beginDefinition; +ollamaQ[ as_Association ] := MatchQ[ serviceName @ as, "Ollama"|"ollama" ]; +ollamaQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*serviceMaxContextTokens*) +serviceMaxContextTokens // beginDefinition; + +serviceMaxContextTokens[ settings_Association ] := + serviceMaxContextTokens[ serviceName @ settings, toModelName @ settings ]; + +serviceMaxContextTokens[ service_String, name_String ] := + Module[ { max }, + max = Quiet @ ServiceExecute[ service, "ModelContextLength", { "Name" -> name } ]; + If[ TrueQ @ Positive @ max, + serviceMaxContextTokens[ service, name ] = Floor @ max, + autoMaxContextTokens0 @ name + ] + ]; + +serviceMaxContextTokens // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*autoMaxTokens*) @@ -557,13 +737,15 @@ $$disabledToolsModel = Alternatives[ "claude-instant-1.2", "gemini-1.0-pro" ~~ ___, "gemini-pro-vision", - "gemini-pro" + "gemini-pro", + "o1" ~~ WordBoundary ~~ ___ ]; toolsEnabledQ[ KeyValuePattern[ "ToolsEnabled" -> enabled: True|False ] ] := enabled; toolsEnabledQ[ KeyValuePattern[ "ToolCallFrequency" -> freq: (_Integer|_Real)? NonPositive ] ] := False; toolsEnabledQ[ KeyValuePattern[ "Model" -> model_ ] ] := toolsEnabledQ @ toModelName @ model; toolsEnabledQ[ model: KeyValuePattern @ { "Service" -> _, "Name" -> _ } ] := toolsEnabledQ @ toModelName @ model; +toolsEnabledQ[ { service_String, name_String } ] := toolsEnabledQ @ <| "Service" -> service, "Name" -> name |>; toolsEnabledQ[ model_String ] := ! StringMatchQ[ model, $$disabledToolsModel, IgnoreCase -> True ]; toolsEnabledQ[ ___ ] := False; @@ -585,10 +767,21 @@ dynamicSplitQ // endDefinition; (* TODO: need to support something like CurrentChatSettings[scope, {"key1", "key2", ...}] for nested values *) GeneralUtilities`SetUsage[ CurrentChatSettings, "\ -CurrentChatSettings[obj$, \"key$\"] gives the current chat settings for the CellObject or NotebookObject obj$ for the specified key. -CurrentChatSettings[obj$] gives all current chat settings for obj$. -CurrentChatSettings[] is equivalent to CurrentChatSettings[EvaluationCell[]]. -CurrentChatSettings[\"key$\"] is equivalent to CurrentChatSettings[EvaluationCell[], \"key$\"].\ +CurrentChatSettings[] gives the current global chat settings. +CurrentChatSettings[\"key$\"] gives the global setting for the specified key. +CurrentChatSettings[obj$] gives all settings scoped by obj$. +CurrentChatSettings[obj$, \"key$\"] gives the setting scoped by obj$ for the specified key. +CurrentChatSettings[obj$, $$] = value$ sets the chat settings for obj$ to value$. +CurrentChatSettings[obj$, $$] =. resets the chat settings for obj$ to the default value. + +* The value for obj$ can be any of the following: +| $FrontEnd | persistent global scope | +| $FrontEndSession | session global scope | +| NotebookObject[$$] | notebook scope | +| CellObject[$$] | cell scope | +* When setting chat settings without a key using CurrentChatSettings[obj$] = value$, \ +the value$ must be an Association or Inherited. +* CurrentChatSettings[obj$, $$] =. is equivalent to CurrentChatSettings[obj$, $$] = Inherited.\ " ]; CurrentChatSettings[ ] := catchMine @ @@ -877,7 +1070,7 @@ storeGlobalSettings // endDefinition; (*$globalSettingsFile*) $globalSettingsFile := Enclose[ Module[ { dir }, - dir = ConfirmBy[ $ResourceInstallationDirectory, DirectoryQ, "ResourceInstallationDirectory" ]; + dir = ConfirmBy[ $ResourceInstallationDirectory, StringQ, "ResourceInstallationDirectory" ]; $globalSettingsFile = ConfirmBy[ FileNameJoin @ { dir, "GlobalChatSettings.wxf" }, StringQ, "File" ] ], throwInternalFailure diff --git a/Source/Chatbook/Storage.wl b/Source/Chatbook/Storage.wl new file mode 100644 index 00000000..eca06fb6 --- /dev/null +++ b/Source/Chatbook/Storage.wl @@ -0,0 +1,713 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`Storage`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* TODO: + * Save chat as a callback to GenerateChatTitleAsynchronous? + * Save attachments separately by their hash ID (requires maintaining ref counts) +*) + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Configuration*) +$maxTitleGenerationMessages = 10; (* 5 input/output pairs *) +$savedChatDataVersion = 2; +$rootStorageName = "SavedChats"; +$defaultConversationTitle = "Untitled Chat"; +$maxChatItems = Infinity; +$timestampPrefixLength = 7; (* good for about 1000 years *) +$$timestampPrefix = Repeated[ LetterCharacter|DigitCharacter, { $timestampPrefixLength } ]; + +$metaKeys = { "AppName", "ConversationTitle", "ConversationUUID", "Date", "Version" }; + +(* TODO: these patterns might need to move to Common.wl *) +$$conversationData = KeyValuePattern @ { + "AppName" -> _String, + "ConversationTitle" -> _String, + "ConversationUUID" -> _String, + "Date" -> _Real, + "Version" -> $savedChatDataVersion +}; + +$$conversationFullData = KeyValuePattern @ { + "AppName" -> _String, + "ConversationTitle" -> _String, + "ConversationUUID" -> _String, + "Date" -> _Real, + "Messages" -> _List, + "Version" -> $savedChatDataVersion +}; + +$$legacyData = KeyValuePattern[ "Version" -> _? (LessThan @ $savedChatDataVersion ) ]; + +$$appSpec = $$string | All | _NotebookObject; + +$generatedTitleCache = <| |>; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*ListSavedChats*) +ListSavedChats // beginDefinition; +ListSavedChats // Options = { MaxItems -> $maxChatItems }; + +ListSavedChats[ opts: OptionsPattern[ ] ] := + catchMine @ ListSavedChats[ All, opts ]; + +ListSavedChats[ appSpec: $$appSpec, opts: OptionsPattern[ ] ] := + catchMine @ LogChatTiming @ listSavedChats[ appSpec, OptionValue[ MaxItems ] ]; + +ListSavedChats // endExportedDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*listSavedChats*) +listSavedChats // beginDefinition; + +listSavedChats[ appSpec: $$appSpec, maxItems_? Positive ] := Enclose[ + Catch @ Module[ { appName, dirName, root, depth, files, sorted, take }, + + appName = ConfirmMatch[ determineAppName @ appSpec, $$string | All, "Name" ]; + dirName = If[ StringQ @ appName, appName, Nothing ]; + + root = ConfirmBy[ + ChatbookFilesDirectory[ { $rootStorageName, dirName }, "EnsureDirectory" -> False ], + StringQ, + "Root" + ]; + + depth = If[ StringQ @ appName, 2, 3 ]; + + files = FileNames[ "metadata.wxf", root, { depth } ]; + If[ files === { }, Throw @ { } ]; + + (* show most recent first *) + sorted = If[ StringQ @ appName, Reverse @ files, ReverseSortBy[ files, FileNameTake[ #, { -2 } ] & ] ]; + take = ConfirmMatch[ Take[ sorted, UpTo @ Floor @ maxItems ], { ___String }, "Take" ]; + + ConfirmMatch[ readChatMetaFile /@ take, { ___Association }, "Metadata" ] + ], + throwInternalFailure +]; + +listSavedChats // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*determineAppName*) +determineAppName // beginDefinition; +determineAppName[ All ] := All; +determineAppName[ name_String ] := name; +determineAppName[ nbo_NotebookObject ] := notebookAppName @ nbo; +determineAppName // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*notebookAppName*) +notebookAppName // beginDefinition; +notebookAppName[ nbo_NotebookObject ] := notebookAppName[ nbo, CurrentChatSettings[ nbo, "AppName" ] ]; +notebookAppName[ nbo_, name_String ] := name; +notebookAppName[ nbo_, $$unspecified ] := $defaultAppName; +notebookAppName // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*readChatMetaFile*) +readChatMetaFile // beginDefinition; +readChatMetaFile[ file_String ] := readChatMetaFile[ file, Quiet @ Developer`ReadWXFFile @ file ]; +readChatMetaFile[ file_String, as_Association ] := checkChatDataVersion @ as; +readChatMetaFile[ file_String, _? FailureQ ] := Nothing; (* corrupt WXF file (should we auto-remove it?) *) +readChatMetaFile // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*LoadChat*) +(* TODO: LoadChat[NotebookObject[...], spec]*) +LoadChat // beginDefinition; +LoadChat[ as: KeyValuePattern[ "ConversationUUID" -> _String ] ] := catchMine @ LogChatTiming @ loadChat @ as; +LoadChat[ uuid_String ] := catchMine @ LoadChat @ <| "ConversationUUID" -> uuid |>; +LoadChat[ app_String, uuid_String ] := catchMine @ LoadChat @ <| "AppName" -> app, "ConversationUUID" -> uuid |>; +LoadChat // endExportedDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*loadChat*) +loadChat // beginDefinition; + +loadChat[ as_Association ] := Enclose[ + Catch @ Module[ { data }, + data = ConfirmMatch[ getChatConversationData @ as, $$conversationFullData|_Missing, "Data" ]; + If[ MissingQ @ data, Throw @ data ]; + ConfirmBy[ restoreAttachments @ data, AssociationQ, "RestoreAttachments" ]; + data + ], + throwInternalFailure +]; + +loadChat // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getChatConversationData*) +getChatConversationData // beginDefinition; + +getChatConversationData[ data: $$conversationFullData ] := + data; + +getChatConversationData[ KeyValuePattern @ { "AppName" -> appName_String, "ConversationUUID" -> uuid_String } ] := + getChatConversationData[ appName, uuid ]; + +getChatConversationData[ KeyValuePattern[ "ConversationUUID" -> uuid_String ] ] := + getChatConversationData @ uuid; + +getChatConversationData[ uuid_String ] := Enclose[ + Catch @ Module[ { root, dir }, + root = ConfirmBy[ storageDirectory[ ], StringQ, "Root" ]; + dir = First[ conversationFileNames[ uuid, root, { 2 } ], Throw @ Missing[ "NotFound" ] ]; + ConfirmMatch[ getChatConversationData0 @ dir, $$conversationFullData|_Missing, "Data" ] + ], + throwInternalFailure +]; + +getChatConversationData[ appName_String, uuid_String ] := Enclose[ + Catch @ Module[ { root, dir }, + root = ConfirmBy[ storageDirectory @ appName, StringQ, "Root" ]; + dir = First[ conversationFileNames[ uuid, root ], Throw @ Missing[ "NotFound" ] ]; + ConfirmMatch[ getChatConversationData0 @ dir, $$conversationFullData|_Missing, "Data" ] + ], + throwInternalFailure +]; + +getChatConversationData // endDefinition; + + +getChatConversationData0 // beginDefinition; + +getChatConversationData0[ dir_String ] := Enclose[ + Catch @ Module[ { fail, file, data }, + fail = Function[ Quiet @ DeleteDirectory[ dir, DeleteContents -> True ]; Throw @ Missing[ "NotFound" ] ]; + + file = FileNameJoin @ { dir, "data.wxf" }; + If[ ! FileExistsQ @ file, fail[ ] ]; + + data = Quiet @ Developer`ReadWXFFile @ file; + If[ ! AssociationQ @ data, fail[ ] ]; + + checkChatDataVersion @ data + ], + throwInternalFailure +]; + +getChatConversationData0[ missing_Missing ] := + missing; + +getChatConversationData0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*restoreAttachments*) +restoreAttachments // beginDefinition; + +restoreAttachments[ KeyValuePattern[ "Attachments" -> attachments_Association ] ] := + Association @ KeyValueMap[ # -> restoreAttachments @ ## &, attachments ]; + +restoreAttachments[ "Expressions", expressions_Association ] := Enclose[ + $attachments = ConfirmBy[ <| $attachments, expressions |>, AssociationQ, "Attachments" ], + throwInternalFailure +]; + +restoreAttachments[ "ToolCalls", toolCalls_Association ] := Enclose[ + $toolEvaluationResults = ConfirmBy[ <| $toolEvaluationResults, toolCalls |>, AssociationQ, "ToolCalls" ], + throwInternalFailure +]; + +restoreAttachments[ key_, value_ ] := + value; + +restoreAttachments // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*DeleteChat*) +DeleteChat // beginDefinition; +DeleteChat[ as_Association ] := catchMine @ DeleteChat[ as[ "AppName" ], as[ "ConversationUUID" ] ]; +DeleteChat[ uuid_String ] := catchMine @ LogChatTiming @ deleteChat[ $defaultAppName, uuid ]; +DeleteChat[ appName_String, uuid_String ] := catchMine @ LogChatTiming @ deleteChat[ appName, uuid ]; +DeleteChat // endExportedDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*deleteChat*) +deleteChat // beginDefinition; + +deleteChat[ appName_String, uuid_String ] := Enclose[ + Catch @ Module[ { root, dirs, dir }, + root = ConfirmBy[ storageDirectory @ appName, StringQ, "Root" ]; + dirs = ConfirmMatch[ conversationFileNames[ uuid, root ], { ___String }, "Directories" ]; + If[ dirs === { }, Throw @ Missing[ "NotFound" ] ]; + dir = ConfirmBy[ First[ dirs, $Failed ], StringQ, "Directory" ]; + ConfirmMatch[ DeleteDirectory[ dir, DeleteContents -> True ], Null, "DeleteDirectory" ]; + ConfirmAssert[ ! DirectoryQ @ dir, "DirectoryCheck" ]; + updateDynamics[ "SavedChats" ]; + dir + ], + throwInternalFailure +]; + +deleteChat // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*SaveChat*) +SaveChat // beginDefinition; +SaveChat // Options = { "AutoGenerateTitle" -> True }; + +SaveChat[ messages: $$chatMessages, settings_Association, opts: OptionsPattern[ ] ] := + catchMine @ LogChatTiming @ saveChat[ messages, settings, OptionValue[ "AutoGenerateTitle" ] ]; + +SaveChat[ chat_ChatObject, settings_Association, opts: OptionsPattern[ ] ] := + catchMine @ SaveChat[ chat[ "Messages" ], settings, opts ]; + +SaveChat[ chat_Dataset, settings_Association, opts: OptionsPattern[ ] ] := + catchMine @ SaveChat[ Normal @ chat, settings, opts ]; + +SaveChat // endExportedDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*saveChat*) +saveChat // beginDefinition; + +saveChat[ messages0_, settings0_, autoTitle_ ] := Enclose[ + Module[ { settings, messages, appName, metadata, vectors, directory, attachments, smallSettings, as }, + + settings = If[ TrueQ @ autoTitle, <| settings0, "AutoGenerateTitle" -> True |>, settings0 ]; + messages = ConfirmMatch[ prepareMessagesForSaving[ messages0, settings ], $$chatMessages, "Messages" ]; + appName = ConfirmBy[ Lookup[ settings, "AppName", $defaultAppName ], StringQ, "AppName" ]; + metadata = ConfirmMatch[ getChatMetadata[ appName, messages, settings ], $$conversationData, "Metadata" ]; + vectors = ConfirmMatch[ createMessageVectors[ metadata, messages, settings ], { ___NumericArray }, "Vectors" ]; + directory = ConfirmBy[ targetDirectory[ appName, metadata ], DirectoryQ, "Directory" ]; + attachments = ConfirmBy[ GetAttachments[ messages, All ], AssociationQ, "Attachments" ]; + smallSettings = ConfirmBy[ toSmallSettings @ settings, AssociationQ, "Settings" ]; + + (* Save metadata file for quick loading of minimal information: *) + ConfirmBy[ + saveChatFile[ "metadata", metadata, directory ], + FileExistsQ, + "SaveMetadata" + ]; + + (* Save messages and attachments (if any): *) + ConfirmBy[ + saveChatFile[ + "data", + <| + metadata, + "Attachments" -> attachments, + "Messages" -> messages, + "Settings" -> smallSettings, + "Vectors" -> vectors + |>, + directory, + PerformanceGoal -> "Size" + ], + FileExistsQ, + "SaveMessages" + ]; + + as = ConfirmBy[ + <| + "Path" -> Flatten @ File @ directory, + KeyTake[ metadata, { "ConversationTitle", "ConversationUUID" } ], + metadata + |>, + AssociationQ, + "ResultData" + ]; + + ConfirmMatch[ cleanupStaleChats @ appName, { ___String }, "Cleanup" ]; + + ConfirmMatch[ AddChatToSearchIndex @ as, _Success | Missing[ "NoSemanticSearch" ], "AddToSearchIndex" ]; + + updateDynamics[ "SavedChats" ]; + + Success[ "Saved", as ] + ], + throwInternalFailure +]; + +saveChat // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*createMessageVectors*) +createMessageVectors // beginDefinition; + +createMessageVectors[ metadata_, messages: $$chatMessages, settings_ ] := Enclose[ + Catch @ Module[ { partitioned, strings, rVectors, iVectors, title, titleVector }, + If[ $noSemanticSearch, Throw @ { } ]; + ConfirmAssert[ Length @ messages >= 2, "LengthCheck" ]; + partitioned = ConfirmBy[ Partition[ messages, UpTo[ 2 ] ], ListQ, "Pairs" ]; + strings = ConfirmMatch[ messagesToString /@ partitioned, { __String }, "Strings" ]; + rVectors = ConfirmMatch[ getEmbeddings @ strings, { __NumericArray }, "Embeddings" ]; + iVectors = ConfirmMatch[ toInt8Vector /@ rVectors, { __NumericArray }, "Int8Vectors" ]; + title = metadata[ "ConversationTitle" ]; + If[ StringQ @ title, + titleVector = ConfirmMatch[ toInt8Vector @ getEmbedding @ title, _NumericArray, "TitleVector" ]; + Prepend[ iVectors, titleVector ], + iVectors + ] + ], + throwInternalFailure +]; + +createMessageVectors // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*toInt8Vector*) +toInt8Vector // beginDefinition; +toInt8Vector[ arr_NumericArray ] := NumericArray[ arr, "Integer8", "ClipAndRound" ]; +toInt8Vector // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getAppName*) +getAppName // beginDefinition; +getAppName[ settings_Association ] := getAppName @ settings[ "AppName" ]; +getAppName[ app_String ] := app; +getAppName[ _ ] := $defaultAppName; +getAppName // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*targetDirectory*) +targetDirectory // beginDefinition; + +targetDirectory[ app_String, meta_Association ] := Enclose[ + Module[ { uuid, date, root, prefix }, + uuid = ConfirmBy[ meta[ "ConversationUUID" ], StringQ, "UUID" ]; + date = ConfirmMatch[ meta[ "Date" ], _Real, "Date" ]; + root = ConfirmBy[ $rootStorageName, StringQ, "RootName" ]; + prefix = ConfirmBy[ timestampPrefixString @ date, StringQ, "Prefix" ]; + ConfirmBy[ ChatbookFilesDirectory @ { root, app, prefix<>"_"<>uuid }, DirectoryQ, "Result" ] + ], + throwInternalFailure +]; + +targetDirectory // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*timestampPrefixString*) +timestampPrefixString // beginDefinition; +timestampPrefixString[ date_Real ] := IntegerString[ Round @ date, 36, $timestampPrefixLength ]; +timestampPrefixString // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*cleanupStaleChats*) +cleanupStaleChats // beginDefinition; + +cleanupStaleChats[ app_String ] := Enclose[ + Module[ { root, dirs, grouped, delete }, + root = ConfirmBy[ storageDirectory @ app, StringQ, "Root" ]; + dirs = ConfirmMatch[ conversationFileNames[ All, root ], { ___String }, "Directories" ]; + grouped = GatherBy[ dirs, StringDrop[ FileNameTake @ #, $timestampPrefixLength ] & ]; + delete = ConfirmMatch[ Flatten[ Most /@ grouped ], { ___String }, "Delete" ]; + + ConfirmAssert[ Length @ delete < Length @ dirs, "LengthCheck" ]; + + ConfirmMatch[ (DeleteDirectory[ #, DeleteContents -> True ]; #) & /@ delete, { ___String }, "Result" ] + ], + throwInternalFailure +]; + +cleanupStaleChats // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getAttachmentsForSaving*) +getAttachmentsForSaving // beginDefinition; +getAttachmentsForSaving[ messages_ ] := getAttachmentsForSaving[ messages, GetAttachments[ messages, All ] ]; +getAttachmentsForSaving[ messages_, as_Association ] := If[ AllTrue[ as, SameAs @ <| |> ], None, as ]; +getAttachmentsForSaving // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*prepareMessagesForSaving*) +prepareMessagesForSaving // beginDefinition; + +prepareMessagesForSaving[ messages_, settings_ ] := + revertMultimodalContent @ + If[ TrueQ @ settings[ "SaveSystemMessage" ], + messages, + dropSystemMessage @ dropTemporaryMessages @ messages + ]; + +prepareMessagesForSaving // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*dropTemporaryMessages*) +dropTemporaryMessages // beginDefinition; +dropTemporaryMessages[ messages_List ] := DeleteCases[ messages, KeyValuePattern[ "Temporary" -> True ] ]; +dropTemporaryMessages // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*dropSystemMessage*) +dropSystemMessage // beginDefinition; +dropSystemMessage[ { KeyValuePattern[ "Role" -> "System" ], messages___ } ] := dropSystemMessage @ { messages }; +dropSystemMessage[ messages_List ] := messages; +dropSystemMessage // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*saveChatFile*) +saveChatFile // beginDefinition; + +saveChatFile[ "metadata", data_Association, directory_, opts: OptionsPattern[ ] ] := + saveChatFile0[ "metadata", KeyTake[ data, $metaKeys ], directory, opts ]; + +saveChatFile[ type_String, data_Association, directory_, opts: OptionsPattern[ ] ] := + saveChatFile0[ type, data, directory, opts ]; + +saveChatFile // endDefinition; + + +saveChatFile0 // beginDefinition; + +saveChatFile0[ type_String, data_, directory_, opts: OptionsPattern[ ] ] := Enclose[ + Module[ { file }, + file = ConfirmBy[ FileNameJoin @ { directory, type <> ".wxf" }, StringQ, "File" ]; + ConfirmBy[ Developer`WriteWXFFile[ file, data, opts ], FileExistsQ, "Export" ] + ], + throwInternalFailure +]; + +saveChatFile0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getChatMetadata*) +getChatMetadata // beginDefinition; + +getChatMetadata[ data: $$conversationData ] := + KeyTake[ data, $metaKeys ]; + +getChatMetadata[ appName_, messages_, settings_Association ] := Enclose[ + Module[ { uuid, title, date, version }, + + uuid = ConfirmBy[ getChatUUID @ settings, StringQ, "ConversationUUID" ]; + title = ConfirmBy[ getChatTitle[ messages, settings ], StringQ, "ConversationTitle" ]; + date = ConfirmMatch[ AbsoluteTime[ TimeZone -> 0 ], _Real, "Date" ]; + version = ConfirmBy[ $savedChatDataVersion, IntegerQ, "Version" ]; + + <| + "AppName" -> appName, + "ConversationUUID" -> uuid, + "ConversationTitle" -> title, + "Date" -> date, + "Version" -> version + |> + ], + throwInternalFailure +]; + +getChatMetadata // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getChatUUID*) +getChatUUID // beginDefinition; +getChatUUID[ KeyValuePattern[ "ConversationUUID" -> id_String ] ] := id; +getChatUUID[ _Association ] := CreateUUID[ ]; +getChatUUID // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getChatTitle*) +getChatTitle // beginDefinition; +getChatTitle[ messages_, KeyValuePattern[ "ConversationTitle" -> title_String ] ] := title; +getChatTitle[ messages_, settings_Association ] := defaultConversationTitle[ messages, settings ]; +getChatTitle // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*defaultConversationTitle*) +defaultConversationTitle // beginDefinition; + +defaultConversationTitle[ messages_, settings_ ] := + If[ TrueQ @ settings[ "AutoGenerateTitle" ], + generateTitleCached @ messages, + $defaultConversationTitle + ]; + +defaultConversationTitle // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*generateTitleCached*) +generateTitleCached // beginDefinition; +generateTitleCached[ messages_List ] := generateTitleCached0 @ Take[ messages, UpTo @ $maxTitleGenerationMessages ]; +generateTitleCached // endDefinition; + + +generateTitleCached0 // beginDefinition; + +generateTitleCached0[ messages_List ] := + generateTitleCached0[ Hash @ messages, messages ]; + +generateTitleCached0[ hash_Integer, messages_ ] := + With[ { cached = $generatedTitleCache[ hash ] }, + cached /; StringQ @ cached + ]; + +generateTitleCached0[ hash_Integer, messages_ ] := Enclose[ + Module[ { title }, + title = ConfirmMatch[ GenerateChatTitle @ messages, _String|_Failure, "Title" ]; + + $lastGeneratedTitle = title; + $lastRegeneratedTitle = None; + + (* retry once if first attempt failed using higher temperature: *) + If[ FailureQ @ title, + title = ConfirmBy[ GenerateChatTitle[ messages, "Temperature" -> 1.0 ], StringQ, "Retry" ]; + $lastRegeneratedTitle = title + ]; + + $generatedTitleCache[ hash ] = title + ], + throwInternalFailure +]; + +generateTitleCached0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Upgrade Data*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*checkChatDataVersion*) +checkChatDataVersion // beginDefinition; +checkChatDataVersion[ as: $$conversationData ] := as; +checkChatDataVersion[ as: $$legacyData ] := upgradeChatData @ as; +checkChatDataVersion // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*upgradeChatData*) +upgradeChatData // beginDefinition; + +upgradeChatData[ as: KeyValuePattern[ "Version" -> oldVersion_Integer ] ] := Enclose[ + Module[ { upgraded, newVersion }, + ConfirmAssert[ oldVersion < $savedChatDataVersion, "OldVersionCheck" ]; + upgraded = ConfirmBy[ upgradeChatData0[ oldVersion, as ], AssociationQ, "Upgraded" ]; + newVersion = ConfirmMatch[ upgraded[ "Version" ], _Integer, "NewVersion" ]; + ConfirmAssert[ oldVersion < newVersion <= $savedChatDataVersion, "NewVersionCheck" ]; + If[ newVersion === $savedChatDataVersion, + upgraded, + upgradeChatData @ upgraded + ] + ], + throwInternalFailure +]; + +upgradeChatData // endDefinition; + + +upgradeChatData0 // beginDefinition; +upgradeChatData0[ 1, as_Association ] := upgradeChatData1 @ as; +upgradeChatData0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*Update from version 1*) + +(* Adds vectors to the saved data: *) +upgradeChatData1 // beginDefinition; + +upgradeChatData1[ metadata_Association ] := Enclose[ + Module[ { appName, directory, file, data, messages, settings, vectors, newData, newMeta }, + + appName = ConfirmBy[ metadata[ "AppName" ], StringQ, "AppName" ]; + directory = ConfirmBy[ targetDirectory[ appName, metadata ], DirectoryQ, "Directory" ]; + file = ConfirmBy[ FileNameJoin @ { directory, "data.wxf" }, FileExistsQ, "File" ]; + data = ConfirmBy[ Developer`ReadWXFFile @ file, AssociationQ, "Data" ]; + messages = ConfirmMatch[ data[ "Messages" ], $$chatMessages, "Messages" ]; + settings = ConfirmBy[ data[ "Settings" ], AssociationQ, "Settings" ]; + vectors = ConfirmMatch[ createMessageVectors[ metadata, messages, settings ], { ___NumericArray }, "Vectors" ]; + newData = <| data, "Vectors" -> vectors, "Version" -> 2 |>; + newMeta = ConfirmBy[ <| metadata, "Version" -> 2 |>, AssociationQ, "Metadata" ]; + + ConfirmBy[ + saveChatFile[ "metadata", newMeta, directory ], + FileExistsQ, + "SaveMetadata" + ]; + + ConfirmBy[ + saveChatFile[ "data", newData, directory, PerformanceGoal -> "Size" ], + FileExistsQ, + "SaveMessages" + ]; + + If[ KeyExistsQ[ metadata, "Messages" ], + newData, + newMeta + ] + ], + throwInternalFailure +]; + +upgradeChatData1 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*File Utilities*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*storageDirectory*) +storageDirectory // beginDefinition; +storageDirectory[ ] := ChatbookFilesDirectory[ $rootStorageName, "EnsureDirectory" -> False ]; +storageDirectory[ name_String ] := ChatbookFilesDirectory[ { $rootStorageName, name }, "EnsureDirectory" -> False ]; +storageDirectory[ All ] := storageDirectory[ ]; +storageDirectory // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*conversationFileNames*) +conversationFileNames // beginDefinition; + +conversationFileNames[ All, args__ ] := + conversationFileNames[ __, args ]; + +conversationFileNames[ pattern_, args__ ] := Enclose[ + Sort @ ConfirmMatch[ FileNames[ conversationFilePattern @ pattern, args ], { ___String }, "FileNames" ], + throwInternalFailure +]; + +conversationFileNames // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*conversationFilePattern*) +conversationFilePattern // beginDefinition; +conversationFilePattern[ pattern_ ] := $$timestampPrefix ~~ "_" ~~ pattern; +conversationFilePattern // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/ToolManager.wl b/Source/Chatbook/ToolManager.wl index aee9a049..b1d845cc 100644 --- a/Source/Chatbook/ToolManager.wl +++ b/Source/Chatbook/ToolManager.wl @@ -435,7 +435,12 @@ addPersonaSource // endDefinition; (* ::Subsection::Closed:: *) (*getFullToolList*) getFullToolList // beginDefinition; -getFullToolList[ ] := DeleteDuplicates @ Join[ Values @ $DefaultTools, Values @ $InstalledTools ]; + +getFullToolList[ ] := DeleteCases[ + DeleteDuplicates @ Join[ Values @ $DefaultTools, Values @ $InstalledTools ], + _[ KeyValuePattern[ "Hidden" -> True ], ___ ] +]; + getFullToolList // endDefinition; (* ::**************************************************************************************************************:: *) @@ -454,7 +459,7 @@ getFullPersonaList // endDefinition; standardizePersonaData // beginDefinition; standardizePersonaData[ persona_Association ] := - standardizePersonaData[ persona, Lookup[ persona, "Tools", { } ] ]; + standardizePersonaData[ persona, getValidPersonaTools @ persona ]; standardizePersonaData[ persona_Association, tools_List ] := Append[ persona, "Tools" -> tools ]; @@ -467,6 +472,13 @@ standardizePersonaData[ persona_Association, None ] := standardizePersonaData // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*getValidPersonaTools*) +getValidPersonaTools // beginDefinition; +getValidPersonaTools[ persona_Association ] := Quiet @ Cases[ Lookup[ persona, "Tools", { } ], _LLMTool ]; +getValidPersonaTools // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Overlays*) @@ -1224,6 +1236,14 @@ installToolsSection[ ] := Sequence[ Appearance -> "Suppressed", BaselinePosition -> Baseline, Method -> "Queued" + ], + Button[ + grayDialogButtonLabel @ tr[ "ToolManagerInstallFromFile" ], + If[ $CloudEvaluation, SetOptions[ EvaluationNotebook[ ], DockedCells -> Inherited ] ]; + Block[ { PrintTemporary }, ResourceInstallFromFile[ "LLMTool" ] ], + Appearance -> "Suppressed", + BaselinePosition -> Baseline, + Method -> "Queued" ] } } diff --git a/Source/Chatbook/Tools/Common.wl b/Source/Chatbook/Tools/Common.wl index 2e38bf13..27ede1d7 100644 --- a/Source/Chatbook/Tools/Common.wl +++ b/Source/Chatbook/Tools/Common.wl @@ -10,7 +10,6 @@ Needs[ "Wolfram`Chatbook`" ]; Needs[ "Wolfram`Chatbook`Common`" ]; Needs[ "Wolfram`Chatbook`Personas`" ]; Needs[ "Wolfram`Chatbook`ResourceInstaller`" ]; -Needs[ "Wolfram`Chatbook`Serialization`" ]; HoldComplete[ System`LLMTool; @@ -91,7 +90,6 @@ $DefaultToolOptions = <| $defaultToolIcon = RawBoxes @ TemplateBox[ { }, "WrenchIcon" ]; -$attachments = <| |>; $selectedTools = <| |>; $toolBox = <| |>; $toolEvaluationResults = <| |>; @@ -163,7 +161,10 @@ reevaluateToolExpressions // endDefinition; (*Installed Tools*) $installedTools := Association @ Cases[ GetInstalledResourceData[ "LLMTool" ], - as: KeyValuePattern[ "Tool" -> tool_ ] :> (toolName @ tool -> addExtraToolData[ tool, as ]) + as: KeyValuePattern[ "Tool" -> tool0_ ] :> + With[ { tool = Quiet @ tool0 }, + (toolName @ tool -> addExtraToolData[ tool, as ]) /; MatchQ[ tool, _LLMTool ] + ] ]; (* ::**************************************************************************************************************:: *) @@ -394,7 +395,7 @@ withToolBox // endDefinition; selectTools // beginDefinition; selectTools[ as_Association ] := Enclose[ - Module[ { llmEvaluatorName, toolNames, selections, selectionTypes, add, remove, selectedNames, tools, short }, + Module[ { llmEvaluatorName, toolNames, selections, selectionTypes, add, remove, selectedNames, short }, llmEvaluatorName = ConfirmBy[ getLLMEvaluatorName @ as, StringQ, "LLMEvaluatorName" ]; toolNames = ConfirmMatch[ getToolNames @ as, { ___String }, "Names" ]; @@ -851,18 +852,21 @@ simpleToolRequestParser // endDefinition; (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*parseSimpleToolCallParameterStrings*) +$$argNameDelimiter = (":"|"="|"-") ~~ " "...; + parseSimpleToolCallParameterStrings // beginDefinition; parseSimpleToolCallParameterStrings[ { param_String }, argString_String ] := - <| param -> StringDelete[ argString, StartOfString ~~ WhitespaceCharacter... ~~ param ~~ ":" ~~ " "... ] |>; + <| param -> StringDelete[ argString, StartOfString ~~ WhitespaceCharacter... ~~ param ~~ $$argNameDelimiter ] |>; parseSimpleToolCallParameterStrings[ paramNames: { __String }, argString_String ] := Enclose[ - Catch @ Module[ { namedSplit, defaults, pairs }, - namedSplit = StringSplit[ argString, StartOfLine ~~ (" "|"\t")... ~~ p: paramNames ~~ ":" ~~ " "... :> p ]; + Catch @ Module[ { namedSplit, defaults, pairs, as }, + namedSplit = StringSplit[ argString, StartOfLine ~~ (" "|"\t"|"")... ~~ p: paramNames ~~ $$argNameDelimiter :> p ]; If[ OddQ @ Length @ namedSplit, Throw @ parseSimpleToolCallParameterStrings0[ paramNames, argString ] ]; defaults = AssociationMap[ "" &, paramNames ]; pairs = ConfirmMatch[ Partition[ namedSplit, 2 ], { { _String, _String } .. }, "Pairs" ]; - ConfirmBy[ <| defaults, Rule @@@ pairs |>, AssociationQ, "Parameters" ] + as = ConfirmBy[ <| defaults, Rule @@@ pairs |>, AssociationQ, "Parameters" ]; + ConfirmBy[ trimSimpleParameterString /@ as, AllTrue @ StringQ, "Result" ] ], throwInternalFailure ]; @@ -873,16 +877,35 @@ parseSimpleToolCallParameterStrings // endDefinition; parseSimpleToolCallParameterStrings0 // beginDefinition; parseSimpleToolCallParameterStrings0[ paramNames: { __String }, argString_String ] := Enclose[ - Module[ { split, padded }, + Module[ { split, padded, threaded }, split = StringSplit[ argString, "\n" ]; padded = PadRight[ split, Length @ paramNames, "" ]; - ConfirmBy[ AssociationThread[ paramNames -> padded ], AssociationQ, "Parameters" ] + threaded = ConfirmBy[ AssociationThread[ paramNames -> padded ], AssociationQ, "Parameters" ]; + ConfirmBy[ trimSimpleParameterString /@ threaded, AllTrue @ StringQ, "Result" ] ], throwInternalFailure ]; parseSimpleToolCallParameterStrings0 // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*trimSimpleParameterString*) +trimSimpleParameterString // beginDefinition; + +trimSimpleParameterString[ s_String ] := StringDelete[ + s, + { + StartOfString ~~ Alternatives[ + WhitespaceCharacter... ~~ "|" ~~ WhitespaceCharacter... ~~ "\n" ~~ WhitespaceCharacter..., + WhitespaceCharacter... + ], + WhitespaceCharacter... ~~ EndOfString + } +]; + +trimSimpleParameterString // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsubsection::Closed:: *) (*toolShortName*) @@ -1076,7 +1099,19 @@ arg1 arg2 /exec -After you write /exec, the system will execute the tool call for you and return the result."; +After you write /exec, the system will execute the tool call for you and return the result. + +If your arguments require multiple lines, specify the name of each argument followed by a colon and a space, \ +then the value: + +/command +arg1: value that +spans multiple +lines +arg2: another +value +/exec +"; $simpleToolPost = "\ @@ -1212,11 +1247,52 @@ $toolFrequencyExplanations = <| 5 -> "ALWAYS make a tool call in EVERY response, no matter what." |>; +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Properties*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getToolIcon*) +getToolIcon // beginDefinition; +getToolIcon[ tool: $$llmTool ] := getToolIcon @ toolData @ tool; +getToolIcon[ as_Association ] := Lookup[ toolData @ as, "Icon", RawBoxes @ TemplateBox[ { }, "WrenchIcon" ] ]; +getToolIcon[ _ ] := $defaultToolIcon; +getToolIcon // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getToolDisplayName*) +getToolDisplayName // beginDefinition; + +getToolDisplayName[ tool_ ] := + getToolDisplayName[ tool, Missing[ "NotFound" ] ]; + +getToolDisplayName[ tool: $$llmTool, default_ ] := + getToolDisplayName @ toolData @ tool; + +getToolDisplayName[ as_Association, default_ ] := + Lookup[ as, "DisplayName", toDisplayToolName @ Lookup[ as, "Name", default ] ]; + +getToolDisplayName[ _, default_ ] := + default; + +getToolDisplayName // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getToolFormattingFunction*) +getToolFormattingFunction // beginDefinition; +getToolFormattingFunction[ HoldPattern @ LLMTool[ as_, ___ ] ] := getToolFormattingFunction @ as; +getToolFormattingFunction[ as_Association ] := Lookup[ as, "FormattingFunction", Automatic ]; +getToolFormattingFunction[ _ ] := Automatic; +getToolFormattingFunction // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Package Footer*) addToMXInitialization[ - Null + $toolConfiguration; ]; (* :!CodeAnalysis::EndBlock:: *) diff --git a/Source/Chatbook/Tools/ChatPreferences.wl b/Source/Chatbook/Tools/DefaultToolDefinitions/ChatPreferences.wl similarity index 85% rename from Source/Chatbook/Tools/ChatPreferences.wl rename to Source/Chatbook/Tools/DefaultToolDefinitions/ChatPreferences.wl index d9cd96fd..69f54527 100644 --- a/Source/Chatbook/Tools/ChatPreferences.wl +++ b/Source/Chatbook/Tools/DefaultToolDefinitions/ChatPreferences.wl @@ -10,33 +10,19 @@ Needs[ "Wolfram`Chatbook`" ]; Needs[ "Wolfram`Chatbook`Common`" ]; Needs[ "Wolfram`Chatbook`Personas`" ]; Needs[ "Wolfram`Chatbook`ResourceInstaller`" ]; -Needs[ "Wolfram`Chatbook`Serialization`" ]; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) -(*Config*) -$usableChatSettingsKeys = { - "Assistance", - "ChatHistoryLength", - "LLMEvaluator", - "MaxCellStringLength", - "MergeMessages", - "Model", - "Prompts", - "Temperature", - "ToolCallFrequency", - "Tools" -}; - -$$scope = _NotebookObject | $FrontEnd; +(*Tool Specification*) (* ::**************************************************************************************************************:: *) -(* ::Section::Closed:: *) -(*Chat Preferences*) +(* ::Subsection::Closed:: *) +(*Icon*) +$chatPreferencesIcon = RawBoxes @ TemplateBox[ { }, "ChatBlockSettingsMenuIcon" ]; (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) -(*Tool Description*) +(*Description*) $chatPreferencesDescription = "\ Get and set current chat preferences. @@ -63,6 +49,62 @@ Key descriptions | Tools | [ string ] | | The list of currently enabled tools. Use the 'get' action for available names. | "; +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Spec*) +$defaultChatTools0[ "ChatPreferences" ] = <| + toolDefaultData[ "ChatPreferences" ], + "Icon" -> $chatPreferencesIcon, + "Description" -> $chatPreferencesDescription, + "Function" -> chatPreferences, + "FormattingFunction" -> toolAutoFormatter, + "Origin" -> "BuiltIn", + "Parameters" -> { + "action" -> <| + "Interpreter" -> { "get", "set" }, + "Help" -> "Whether to get or set chat settings", + "Required" -> True + |>, + "key" -> <| + "Interpreter" -> "String", + "Help" -> "Which chat setting to get or set", + "Required" -> False + |>, + "value" -> <| + "Interpreter" -> "String", + "Help" -> "The value to set the chat setting to", + "Required" -> False + |>, + "scope" -> <| + "Interpreter" -> { "global", "notebook" }, + "Help" -> "The scope of the chat setting (default is 'notebook')", + "Required" -> False + |> + } +|>; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Config*) +$usableChatSettingsKeys = { + "Assistance", + "ChatHistoryLength", + "LLMEvaluator", + "MaxCellStringLength", + "MergeMessages", + "Model", + "Prompts", + "Temperature", + "ToolCallFrequency", + "Tools" +}; + +$$scope = _NotebookObject | $FrontEnd; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Chat Preferences*) + (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*Definitions*) diff --git a/Source/Chatbook/Tools/DefaultToolDefinitions/DocumentationLookup.wl b/Source/Chatbook/Tools/DefaultToolDefinitions/DocumentationLookup.wl new file mode 100644 index 00000000..22e60e6f --- /dev/null +++ b/Source/Chatbook/Tools/DefaultToolDefinitions/DocumentationLookup.wl @@ -0,0 +1,155 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`Tools`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Specification*) +$defaultChatTools0[ "DocumentationLookup" ] = <| + toolDefaultData[ "DocumentationLookup" ], + "ShortName" -> "doc_lookup", + "Icon" -> RawBoxes @ TemplateBox[ { }, "ToolIconDocumentationLookup" ], + "Description" -> "Get documentation pages for Wolfram Language symbols.", + "Function" -> documentationLookup, + "FormattingFunction" -> toolAutoFormatter, + "Origin" -> "BuiltIn", + "Parameters" -> { + "names" -> <| + "Interpreter" -> DelimitedSequence[ "WolframLanguageSymbol", "," ], + "Help" -> "One or more Wolfram Language symbols separated by commas", + "Required" -> True + |> + } +|>; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Function*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*documentationLookup*) +documentationLookup // beginDefinition; + +documentationLookup[ KeyValuePattern[ "names" -> name_ ] ] := documentationLookup @ name; +documentationLookup[ name_Entity ] := documentationLookup @ CanonicalName @ name; +documentationLookup[ names_List ] := StringRiffle[ documentationLookup /@ names, "\n\n---\n\n" ]; + +documentationLookup[ name_String ] := Enclose[ + Module[ { usage, details, examples, strings, body }, + usage = ConfirmMatch[ documentationUsage @ name, _String|_Missing, "Usage" ]; + details = ConfirmMatch[ documentationDetails @ name, _String|_Missing, "Details" ]; + examples = ConfirmMatch[ documentationBasicExamples @ name, _String|_Missing, "Examples" ]; + strings = ConfirmMatch[ DeleteMissing @ { usage, details, examples }, { ___String }, "Strings" ]; + body = If[ strings === { }, ToString[ Missing[ "NotFound" ], InputForm ], StringRiffle[ strings, "\n\n" ] ]; + "# " <> name <> "\n\n" <> body + ], + throwInternalFailure +]; + +documentationLookup // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*documentationUsage*) +documentationUsage // beginDefinition; +documentationUsage[ name_String ] := documentationUsage[ name, wolframLanguageData[ name, "PlaintextUsage" ] ]; +documentationUsage[ name_, missing_Missing ] := missing; +documentationUsage[ name_, usage_String ] := "## Usage\n\n" <> usage; +documentationUsage // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*documentationDetails*) +documentationDetails // beginDefinition; +documentationDetails[ name_String ] := Missing[ ]; (* TODO *) +documentationDetails // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*documentationBasicExamples*) +documentationBasicExamples // beginDefinition; + +documentationBasicExamples[ name_String ] := + documentationBasicExamples[ name, wolframLanguageData[ name, "DocumentationBasicExamples" ] ]; + +documentationBasicExamples[ name_, missing_Missing ] := missing; + +documentationBasicExamples[ name_, examples_List ] := Enclose[ + Module[ { cells, strings }, + cells = renumberCells @ Replace[ Flatten @ examples, RawBoxes[ cell_ ] :> cell, { 1 } ]; + strings = ConfirmMatch[ cellToString /@ cells, { ___String }, "CellToString" ]; + If[ strings === { }, + Missing[ ], + StringDelete[ + "## Basic Examples\n\n" <> StringRiffle[ strings, "\n\n" ], + Longest[ "```\n\n```"~~("wl"|"") ] + ] + ] + ], + throwInternalFailure +]; + +documentationBasicExamples // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*cellToString*) +cellToString[ args___ ] := CellToString[ + args, + "ContentTypes" -> If[ TrueQ @ $multimodalMessages, { "Text", "Image" }, Automatic ], + "MaxCellStringLength" -> 100 +]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*renumberCells*) +renumberCells // beginDefinition; +renumberCells[ cells_List ] := Block[ { $line = 0 }, renumberCell /@ Flatten @ cells ]; +renumberCells // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*renumberCell*) +renumberCell // beginDefinition; + +renumberCell[ Cell[ a__, "Input", b: (Rule|RuleDelayed)[ _, _ ]... ] ] := + Cell[ a, "Input", CellLabel -> "In[" <> ToString @ ++$line <> "]:=" ]; + +renumberCell[ Cell[ a__, "Output", b: (Rule|RuleDelayed)[ _, _ ]... ] ] := + Cell[ a, "Output", CellLabel -> "Out[" <> ToString @ $line <> "]=" ]; + +renumberCell[ Cell[ a__, style: "Print"|"Echo", b: (Rule|RuleDelayed)[ _, _ ]... ] ] := + Cell[ a, style, CellLabel -> "During evaluation of In[" <> ToString @ $line <> "]:=" ]; + +renumberCell[ cell_Cell ] := cell; + +renumberCell // endDefinition; + +$line = 0; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*wolframLanguageData*) +wolframLanguageData // beginDefinition; + +wolframLanguageData[ name_, property_ ] := Enclose[ + wolframLanguageData[ name, property ] = ConfirmBy[ WolframLanguageData[ name, property ], Not@*FailureQ ], + Missing[ "DataFailure" ] & +]; + +wolframLanguageData // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Tools/DefaultToolDefinitions/DocumentationSearcher.wl b/Source/Chatbook/Tools/DefaultToolDefinitions/DocumentationSearcher.wl new file mode 100644 index 00000000..2beaa628 --- /dev/null +++ b/Source/Chatbook/Tools/DefaultToolDefinitions/DocumentationSearcher.wl @@ -0,0 +1,69 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`Tools`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Specification*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Icon*) +$documentationSearcherIcon = RawBoxes @ TemplateBox[ { }, "ToolIconDocumentationSearcher" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Description*) +$documentationSearcherDescription = "\ +Search Wolfram Language documentation for symbols and more. \ +Follow up search results with the documentation lookup tool to get the full information."; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Spec*) +$defaultChatTools0[ "DocumentationSearcher" ] = <| + toolDefaultData[ "DocumentationSearcher" ], + "ShortName" -> "doc_search", + "Icon" -> $documentationSearcherIcon, + "Description" -> $documentationSearcherDescription, + "Function" -> documentationSearch, + "FormattingFunction" -> toolAutoFormatter, + "Origin" -> "BuiltIn", + "Parameters" -> { + "query" -> <| + "Interpreter" -> "String", + "Help" -> "A string representing a documentation search query", + "Required" -> True + |> + } +|>; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Function*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*documentationSearch*) +documentationSearch // beginDefinition; +documentationSearch[ KeyValuePattern[ "query" -> name_ ] ] := documentationSearch @ name; +documentationSearch[ names_List ] := StringRiffle[ documentationSearch /@ names, "\n\n" ]; +documentationSearch[ name_String ] /; NameQ[ "System`" <> name ] := documentationLookup @ name; +documentationSearch[ query_String ] := documentationSearch[ query, documentationSearchAPI @ query ]; +documentationSearch[ query_String, { } ] := ToString[ Missing[ "NoResults" ], InputForm ]; +documentationSearch[ query_String, results_List ] := StringRiffle[ results, "\n" ]; +documentationSearch // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Tools/DefaultToolDefinitions/NotebookEditor.wl b/Source/Chatbook/Tools/DefaultToolDefinitions/NotebookEditor.wl new file mode 100644 index 00000000..7b35684c --- /dev/null +++ b/Source/Chatbook/Tools/DefaultToolDefinitions/NotebookEditor.wl @@ -0,0 +1,326 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`Tools`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Configuration*) +(* $notebookEditorEnabled := TrueQ @ $WorkspaceChat || TrueQ @ $InlineChat; *) +$notebookEditorEnabled = False; + +$cancelledNotebookEdit = Failure[ "Cancelled", <| "Message" -> "Proposed change was rejected by the user" |> ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Icon*) +$nbEditIcon = RawBoxes[ + DynamicBox @ FEPrivate`FrontEndResource[ "FEBitmaps", "NotebookIcon" ][ + GrayLevel[ 0.651 ], + RGBColor[ 0.86667, 0.066667, 0. ] + ] +]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Description*) +$nbEditDescription = "\ +Modify notebook cells. \ +Use this if the user asks you to write code for them, fix issues, etc. \ +The user will be presented with a diff view of your changes and can accept or reject them, \ +so you do not need to ask for permission. \ +If the user asks you to fix code, edit only the relevant input cells and let them reevaluate as needed. \ +Do not include cell labels like `In[...]:=` in the content you write. These will be automatically generated for you. \ +Do not try to write output cells. Instead, just write inputs so that the user can reevaluate them. \ +Write content as Markdown and the tool will automatically convert it to the right format."; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Spec*) +$defaultChatTools0[ "NotebookEditor" ] = <| + toolDefaultData[ "NotebookEditor" ], + "ShortName" -> "nb_edit", + "Icon" -> $nbEditIcon, + "Description" -> $nbEditDescription, + "Enabled" :> $notebookEditorEnabled, + "Function" -> notebookEdit, + "FormattingFunction" -> toolAutoFormatter, + "Hidden" -> True, (* TODO: hide this from UI *) + "Origin" -> "BuiltIn", + "Parameters" -> { + "action" -> <| + "Interpreter" -> "String", + "Help" -> "Action to execute. Valid values are 'delete', 'write', 'append', 'prepend'.", + "Required" -> True + |>, + "target" -> <| + "Interpreter" -> "String", + "Help" -> "Target of action. Can be a cell ID or 'selected' (default).", + "Required" -> False + |>, + "content" -> <| + "Interpreter" -> "String", + "Help" -> "Content to write, append, or prepend.", + "Required" -> False + |> + } +|>; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Function*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*notebookEdit*) +notebookEdit // beginDefinition; + +notebookEdit[ as_Association ] := Catch[ + notebookEdit[ + as[ "action" ], + notebookEditTarget @ as[ "target" ], + notebookEditContent @ as[ "content" ] + ], + $notebookEditTag +]; + +notebookEdit[ "delete" , target_, content_ ] := notebookEditDelete[ target, content ]; +notebookEdit[ "write" , target_, content_ ] := notebookEditWrite[ target, content ]; +notebookEdit[ "append" , target_, content_ ] := notebookEditAppend[ target, content ]; +notebookEdit[ "prepend", target_, content_ ] := notebookEditPrepend[ target, content ]; + +notebookEdit // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*notebookEditDelete*) +notebookEditDelete // beginDefinition; + +notebookEditDelete[ target_, _ ] := + notebookEditDelete @ target; + +notebookEditDelete[ nbo_NotebookObject ] := + If[ TrueQ @ ChoiceDialog[ Row @ { "Delete current selection in ", nbo, "?" } ], + NotebookDelete @ nbo; + Success[ "NotebookDelete", <| "Content" -> "Selection" |> ], + $cancelledNotebookEdit + ]; + +notebookEditDelete[ cell_CellObject ] := + If[ TrueQ @ ChoiceDialog[ Row @ { "Delete cell ", cell, "?" } ], + NotebookDelete @ cell; + Success[ "NotebookDelete", <| "Content" -> cell |> ], + $cancelledNotebookEdit + ]; + +notebookEditDelete[ cells: { __CellObject } ] := + If[ TrueQ @ ChoiceDialog[ Row @ { "Delete the following cells? ", cells } ], + NotebookDelete @ cells; + Success[ "NotebookDelete", <| "Content" -> cells |> ], + $cancelledNotebookEdit + ]; + +notebookEditDelete[ _Missing ] := + Missing[ "TargetNotFound" ]; + +notebookEditDelete // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*notebookEditWrite*) +notebookEditWrite // beginDefinition; +notebookEditWrite[ target_, content_ ] := notebookEditWrite0[ target, content ]; +notebookEditWrite // endDefinition; + +notebookEditWrite0 // beginDefinition; + +notebookEditWrite0[ nbo_NotebookObject, content: { __Cell } ] := + If[ TrueQ @ ChoiceDialog[ + Column @ { Row @ { "Overwrite the current selection in ", nbo, " with the following?" }, content } + ], + NotebookWrite[ nbo, content ]; + Success[ "NotebookWrite", <| "Content" -> content |> ], + $cancelledNotebookEdit + ]; + +notebookEditWrite0[ cell_CellObject, content: { __Cell } ] := + If[ TrueQ @ ChoiceDialog[ Column @ { Row @ { "Overwrite ", cell, " with the following?" }, content } ], + NotebookWrite[ cell, content ]; + Success[ "NotebookWrite", <| "Content" -> content |> ], + $cancelledNotebookEdit + ]; + +notebookEditWrite0[ { first_CellObject, rest___CellObject }, content: { __Cell } ] := + If[ TrueQ @ ChoiceDialog[ Column @ { Row @ { "Overwrite the following cells? ", { first, rest } }, content } ], + NotebookDelete @ { rest }; + SelectionMove[ first, All, CellContents ]; + NotebookWrite[ parentNotebook @ first, content ]; + Success[ "NotebookWrite", <| "Content" -> content |> ], + $cancelledNotebookEdit + ]; + +notebookEditWrite0[ _Missing, _ ] := + Missing[ "TargetNotFound" ]; + +notebookEditWrite0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*notebookEditAppend*) +notebookEditAppend // beginDefinition; +notebookEditAppend[ target_, content_ ] := notebookEditAppend0[ target, content ]; +notebookEditAppend // endDefinition; + +notebookEditAppend0 // beginDefinition; + +notebookEditAppend0[ nbo_NotebookObject, content: { __Cell } ] := ( + SelectionMove[ nbo, After, Cell ]; + NotebookWrite[ nbo, content, After ]; + Success[ "NotebookWrite", <| "Content" -> content |> ] +); + +notebookEditAppend0[ cell_CellObject, content: { __Cell } ] := ( + SelectionMove[ cell, After, Cell ]; + NotebookWrite[ parentNotebook @ cell, content, After ]; + Success[ "NotebookWrite", <| "Content" -> content |> ] +); + +notebookEditAppend0[ { ___, last_CellObject }, content: { __Cell } ] := + notebookEditAppend0[ last, content ]; + +notebookEditAppend0[ _Missing, _ ] := + Missing[ "TargetNotFound" ]; + +notebookEditAppend0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*notebookEditPrepend*) +notebookEditPrepend // beginDefinition; +notebookEditPrepend[ target_, content_ ] := notebookEditPrepend0[ target, content ]; +notebookEditPrepend // endDefinition; + +notebookEditPrepend0 // beginDefinition; + +notebookEditPrepend0[ nbo_NotebookObject, content: { __Cell } ] := ( + SelectionMove[ nbo, Before, Cell ]; + NotebookWrite[ nbo, content, Before ]; + Success[ "NotebookWrite", <| "Content" -> content |> ] +); + +notebookEditPrepend0[ cell_CellObject, content: { __Cell } ] := ( + SelectionMove[ cell, Before, Cell ]; + NotebookWrite[ parentNotebook @ cell, content, Before ]; + Success[ "NotebookWrite", <| "Content" -> content |> ] +); + +notebookEditPrepend0[ { first_CellObject, ___ }, content: { __Cell } ] := + notebookEditPrepend0[ first, content ]; + +notebookEditPrepend0[ _Missing, _ ] := + Missing[ "TargetNotFound" ]; + +notebookEditPrepend0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*notebookEditTarget*) +notebookEditTarget // beginDefinition; +notebookEditTarget[ "selected" ] /; $WorkspaceChat := getUserNotebook[ ]; +notebookEditTarget[ "selected" ] /; $InlineChat := ensureValidWriteTarget @ $inlineChatState[ "ParentCell" ]; +notebookEditTarget[ "selected" ] /; True := $evaluationNotebook; +notebookEditTarget[ _Missing | "" ] := notebookEditTarget[ "selected" ]; +notebookEditTarget[ target_String ] := notebookEditTarget @ StringSplit[ target, "," ]; +notebookEditTarget[ { target_String } ] := cellReference @ target; +notebookEditTarget[ targets: { ___String } ] := notebookEditTarget[ cellReference /@ targets ]; +notebookEditTarget[ targets: { __CellObject } ] := targets; +notebookEditTarget[ s_String ] /; StringContainsQ[ s, "selected"|"selection" ] := notebookEditTarget[ "selected" ]; +notebookEditTarget[ _ ] := Missing[ "TargetNotFound" ]; +notebookEditTarget // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*ensureValidWriteTarget*) +ensureValidWriteTarget // beginDefinition; + +ensureValidWriteTarget[ cell_CellObject ] := + With[ { valid = ensureValidWriteTarget[ cell, CurrentValue[ cell, GeneratedCell ] ] }, + If[ MatchQ[ valid, _CellObject ], + valid, + cell + ] + ]; + +ensureValidWriteTarget[ cell_CellObject, False ] := + cell; + +ensureValidWriteTarget[ cell_, True ] := + With[ { prev = previousCell @ cell }, + If[ MatchQ[ prev, Except[ cell, _CellObject ] ], + ensureValidWriteTarget @ prev, + $Failed + ] + ]; + +ensureValidWriteTarget // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*notebookEditContent*) +notebookEditContent // beginDefinition; + +notebookEditContent[ content_String ] := Enclose[ + Module[ { cells }, + cells = ConfirmMatch[ toCellExpressions @ content, { ___Cell } | _String, "Cells" ]; + cells + ], + throwInternalFailure +]; + +notebookEditContent // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*toCellExpressions*) +toCellExpressions // beginDefinition; + +toCellExpressions[ "" ] := + Missing[ "NoContent" ]; + +toCellExpressions[ content_String ] /; StringContainsQ[ content, "Cell["~~___~~"]" ] && SyntaxQ @ content := + toCellExpressions[ content, Quiet @ ToExpression[ content, InputForm, HoldComplete ] ]; + +toCellExpressions[ content_String ] := + toCellExpressions[ content, FormatChatOutput @ content ]; + +toCellExpressions[ content_, RawBoxes[ boxes_ ] ] := + toCellExpressions[ content, boxes ]; + +toCellExpressions[ content_, boxes_Cell ] := + With[ { exploded = catchAlways @ ExplodeCell @ boxes }, + If[ MatchQ[ exploded, { ___Cell } ], + exploded, + content + ] + ]; + +toCellExpressions[ content_, HoldComplete[ cell_Cell ] ] := + { cell }; + +toCellExpressions[ content_, HoldComplete[ cells: { ___Cell } ] ] := + cells; + +toCellExpressions // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Tools/DefaultToolDefinitions/WebFetcher.wl b/Source/Chatbook/Tools/DefaultToolDefinitions/WebFetcher.wl new file mode 100644 index 00000000..af7f22ae --- /dev/null +++ b/Source/Chatbook/Tools/DefaultToolDefinitions/WebFetcher.wl @@ -0,0 +1,143 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`Tools`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Specification*) +$defaultChatTools0[ "WebFetcher" ] = <| + toolDefaultData[ "WebFetcher" ], + "ShortName" -> "web_fetch", + "Icon" -> RawBoxes @ TemplateBox[ { }, "ToolIconWebFetcher" ], + "Description" -> "Fetch plain text or image links from a URL.", + "Function" -> webFetch, + "FormattingFunction" -> toolAutoFormatter, + "Origin" -> "BuiltIn", + "Parameters" -> { + "url" -> <| + "Interpreter" -> "URL", + "Help" -> "The URL", + "Required" -> True + |>, + "format" -> <| + "Interpreter" -> { "Plaintext", "ImageLinks" }, + "Help" -> "The type of content to retrieve (\"Plaintext\" or \"ImageLinks\")", + "Required" -> True + |> + } +|>; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Function*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*webFetch*) +webFetch // beginDefinition; +webFetch[ KeyValuePattern @ { "url" -> url_, "format" -> fmt_ } ] := webFetch[ url, fmt ]; +webFetch[ url_, "Plaintext" ] := fetchWebText @ url; +webFetch[ url: _URL|_String, fmt_String ] := webFetch[ url, fmt, Import[ url, { "HTML", fmt } ] ]; +webFetch[ url_, "ImageLinks", { } ] := <| "Result" -> { }, "String" -> "No links found at " <> TextString @ url |>; +webFetch[ url_, "ImageLinks", links: { __String } ] := <| "Result" -> links, "String" -> StringRiffle[ links, "\n" ] |>; +webFetch[ url_, fmt_, result_String ] := shortenWebText @ niceWebText @ result; +webFetch // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*fetchWebText*) +fetchWebText // beginDefinition; + +fetchWebText[ URL[ url_ ] ] := + fetchWebText @ url; + +fetchWebText[ url_String ] := + fetchWebText[ url, $webSession ]; + +fetchWebText[ url_String, session_WebSessionObject ] := Enclose[ + Module[ { body, strings }, + ConfirmMatch[ WebExecute[ session, { "OpenPage" -> url } ], _Success | { __Success } ]; + Pause[ 3 ]; (* Allow time for the page to load *) + body = ConfirmMatch[ WebExecute[ session, "LocateElements" -> "Tag" -> "body" ], { __WebElementObject } ]; + strings = ConfirmMatch[ WebExecute[ "ElementText" -> body ], { __String } ]; + shortenWebText @ niceWebText @ strings + ], + shortenWebText @ niceWebText @ Import[ url, { "HTML", "Plaintext" } ] & +]; + +fetchWebText[ url_String, _Missing | _? FailureQ ] := + shortenWebText @ niceWebText @ Import[ url, { "HTML", "Plaintext" } ]; + +fetchWebText // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*shortenWebText*) +shortenWebText // beginDefinition; +shortenWebText[ text_String ] := shortenWebText[ text, toolOptionValue[ "WebFetcher", "MaxContentLength" ] ]; +shortenWebText[ text_String, len_Integer? Positive ] := StringTake[ text, UpTo[ len ] ]; +shortenWebText[ text_String, Infinity|All ] := text; +shortenWebText[ text_String, _ ] := shortenWebText[ text, $defaultWebTextLength ]; +shortenWebText // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*niceWebText*) +niceWebText // beginDefinition; +niceWebText[ str_String ] := StringReplace[ StringDelete[ str, "\r" ], Longest[ "\n"~~Whitespace~~"\n" ] :> "\n\n" ]; +niceWebText[ strings_List ] := StringRiffle[ StringTrim[ niceWebText /@ strings ], "\n\n" ]; +niceWebText // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*$webSession*) +$webSession := getWebSession[ ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getWebSession*) +getWebSession // beginDefinition; +getWebSession[ ] := getWebSession @ $currentWebSession; +getWebSession[ session_WebSessionObject? validWebSessionQ ] := session; +getWebSession[ session_WebSessionObject ] := (Quiet @ DeleteObject @ session; startWebSession[ ]); +getWebSession[ _ ] := startWebSession[ ]; +getWebSession // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*validWebSessionQ*) +validWebSessionQ // ClearAll; + +validWebSessionQ[ session_WebSessionObject ] := + With[ { valid = Quiet @ StringQ @ WebExecute[ session, "PageURL" ] }, + If[ valid, True, Quiet @ DeleteObject @ session; False ] + ]; + +validWebSessionQ[ ___ ] := False; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*startWebSession*) +startWebSession // beginDefinition; + +startWebSession[ ] := $currentWebSession = + If[ TrueQ @ $CloudEvaluation, + Missing[ "NotAvailable" ], + StartWebSession[ Visible -> $webSessionVisible ] + ]; + +startWebSession // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Tools/DefaultToolDefinitions/WebImageSearcher.wl b/Source/Chatbook/Tools/DefaultToolDefinitions/WebImageSearcher.wl new file mode 100644 index 00000000..9498b82f --- /dev/null +++ b/Source/Chatbook/Tools/DefaultToolDefinitions/WebImageSearcher.wl @@ -0,0 +1,97 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`Tools`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Specification*) +$defaultChatTools0[ "WebImageSearcher" ] = <| + toolDefaultData[ "WebImageSearcher" ], + "ShortName" -> "img_search", + "Icon" -> RawBoxes @ TemplateBox[ { }, "ToolIconWebImageSearcher" ], + "Description" -> "Search the web for images.", + "Function" -> webImageSearch, + "FormattingFunction" -> toolAutoFormatter, + "Origin" -> "BuiltIn", + "Parameters" -> { + "query" -> <| + "Interpreter" -> "String", + "Help" -> "Search query text", + "Required" -> True + |> + } +|>; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Function*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*webImageSearch*) +webImageSearch // beginDefinition; + +webImageSearch[ KeyValuePattern[ "query" -> query_ ] ] := Block[ { PrintTemporary }, webImageSearch @ query ]; +webImageSearch[ query_String ] := webImageSearch[ query, webImageSearch0[ query ] ]; + +webImageSearch[ query_, { } ] := <| + "Result" -> { }, + "String" -> "No results found" +|>; + +webImageSearch[ query_, urls: { __ } ] := <| + "Result" -> Column[ Hyperlink /@ urls, BaseStyle -> "Text" ], + "String" -> StringRiffle[ TextString /@ urls, "\n" ] +|>; + +webImageSearch[ query_, failed_Failure ] := <| + "Result" -> failed, + "String" -> makeFailureString @ failed +|>; + +webImageSearch // endDefinition; + + +webImageSearch0 // beginDefinition; + +webImageSearch0[ query_String ] := Enclose[ + Module[ { opts, raw, result, held, $unavailable }, + opts = Sequence @@ ConfirmMatch[ toolOptions[ "WebImageSearcher" ], { $$optionsSequence }, "Options" ]; + result = Quiet[ + Check[ + raw = WebImageSearch[ query, "ImageHyperlinks", opts ], + $unavailable, + (* cSpell: ignore unexp *) + IntegratedServices`IntegratedServices::unexp + ], + IntegratedServices`IntegratedServices::unexp + ]; + + held = HoldForm @ Evaluate @ raw; + + Quiet @ Replace[ + result, + { + $unavailable :> messageFailure[ "IntegratedServiceUnavailable", "WebImageSearch", held ], + Except[ _List ] :> messageFailure[ "IntegratedServiceError" , "WebImageSearch", held ] + } + ] + ], + throwInternalFailure +]; + +webImageSearch0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Tools/DefaultToolDefinitions/WebSearcher.wl b/Source/Chatbook/Tools/DefaultToolDefinitions/WebSearcher.wl new file mode 100644 index 00000000..c19d8f44 --- /dev/null +++ b/Source/Chatbook/Tools/DefaultToolDefinitions/WebSearcher.wl @@ -0,0 +1,117 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`Tools`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Specification*) +$defaultChatTools0[ "WebSearcher" ] = <| + toolDefaultData[ "WebSearcher" ], + "ShortName" -> "web_search", + "Icon" -> RawBoxes @ TemplateBox[ { }, "ToolIconWebSearcher" ], + "Description" -> "Search the web.", + "Function" -> webSearch, + "FormattingFunction" -> toolAutoFormatter, + "Origin" -> "BuiltIn", + "Parameters" -> { + "query" -> <| + "Interpreter" -> "String", + "Help" -> "Search query text", + "Required" -> True + |> + } +|>; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Function*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*webSearch*) +webSearch // beginDefinition; + +webSearch[ KeyValuePattern[ "query" -> query_ ] ] := + Block[ { PrintTemporary }, webSearch @ query ]; + +webSearch[ query_String ] := Enclose[ + Catch @ Module[ { result, json, string }, + result = ConfirmMatch[ webSearch0 @ query, _Dataset|_Failure, "WebSearch" ]; + + If[ MatchQ[ result, _Failure ], + Throw @ <| "Result" -> result, "String" -> makeFailureString @ result |> + ]; + + json = ConfirmBy[ Developer`WriteRawJSONString[ Normal @ result /. URL[ url_ ] :> url ], StringQ, "JSON" ]; + json = StringReplace[ json, "\\/" -> "/" ]; + string = ConfirmBy[ TemplateApply[ $webSearchResultTemplate, json ], StringQ, "TemplateApply" ]; + + <| "Result" -> result, "String" -> string |> + ], + throwInternalFailure +]; + +webSearch // endDefinition; + + +webSearch0 // beginDefinition; + +webSearch0[ query_String ] := Enclose[ + Module[ { opts, raw, result, held, $unavailable }, + opts = Sequence @@ ConfirmMatch[ toolOptions[ "WebSearcher" ], { $$optionsSequence }, "Options" ]; + result = Quiet[ + Check[ + raw = WebSearch[ query, opts ], + $unavailable, + (* cSpell: ignore unexp *) + IntegratedServices`IntegratedServices::unexp + ], + IntegratedServices`IntegratedServices::unexp + ]; + + held = HoldForm @ Evaluate @ raw; + + Quiet @ Replace[ + result, + { + $unavailable :> messageFailure[ "IntegratedServiceUnavailable", "WebSearch", held ], + Except[ _Dataset ] :> messageFailure[ "IntegratedServiceError" , "WebSearch", held ] + } + ] + ], + throwInternalFailure +]; + +webSearch0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*$webSearchResultTemplate*) +$webSearchResultTemplate := StringTemplate @ StringJoin[ + "Results\n-------\n\n`1`\n\n-------", + If[ toolSelectedQ[ "WebFetcher" ], + $webSearchFetchPrompt, + "" + ] +]; + +$webSearchFetchPrompt = " + +Important: The snippet text is not enough information to write an informed response! If there are any relevant \ +results, you should now immediately use the web_fetcher tool to retrieve them before responding. Do not ask the user \ +for permission first. If it made sense to use the web_searcher tool, it's also implied that you should use the \ +web_fetcher tool."; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Tools/WolframAlpha.wl b/Source/Chatbook/Tools/DefaultToolDefinitions/WolframAlpha.wl similarity index 91% rename from Source/Chatbook/Tools/WolframAlpha.wl rename to Source/Chatbook/Tools/DefaultToolDefinitions/WolframAlpha.wl index 1c12dfcc..cd872203 100644 --- a/Source/Chatbook/Tools/WolframAlpha.wl +++ b/Source/Chatbook/Tools/DefaultToolDefinitions/WolframAlpha.wl @@ -6,6 +6,54 @@ Begin[ "`Private`" ]; Needs[ "Wolfram`Chatbook`" ]; Needs[ "Wolfram`Chatbook`Common`" ]; +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Specification*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Icon*) +$wolframAlphaIcon = RawBoxes @ DynamicBox @ FEPrivate`FrontEndResource[ "FEBitmaps", "InsertionAlpha" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Description*) +$wolframAlphaDescription = "\ +Use natural language queries with Wolfram|Alpha to get up-to-date computational results about entities in chemistry, \ +physics, geography, history, art, astronomy, and more."; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Spec*) +$defaultChatTools0[ "WolframAlpha" ] = <| + toolDefaultData[ "WolframAlpha" ], + "ShortName" -> "wa", + "Icon" -> $wolframAlphaIcon, + "Description" -> $wolframAlphaDescription, + "DisplayName" -> "Wolfram|Alpha", + "Enabled" :> ! TrueQ @ $AutomaticAssistance, + "FormattingFunction" -> wolframAlphaResultFormatter, + "Function" -> getWolframAlphaText, + "Origin" -> "BuiltIn", + "Parameters" -> { + "query" -> <| + "Interpreter" -> "String", + "Help" -> "the input", + "Required" -> True + |>, + "steps" -> <| + "Interpreter" -> "Boolean", + "Help" -> "whether to show step-by-step solution", + "Required" -> False + |>(*, + "assumption" -> <| + "Interpreter" -> "String", + "Help" -> "the assumption to use, passed back from a previous query with the same input.", + "Required" -> False + |>*) + } +|>; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Configuration*) diff --git a/Source/Chatbook/Tools/DefaultToolDefinitions/WolframLanguageEvaluator.wl b/Source/Chatbook/Tools/DefaultToolDefinitions/WolframLanguageEvaluator.wl new file mode 100644 index 00000000..fce3102c --- /dev/null +++ b/Source/Chatbook/Tools/DefaultToolDefinitions/WolframLanguageEvaluator.wl @@ -0,0 +1,81 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`Tools`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Specification*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Icon*) +$wolframLanguageEvaluatorIcon = RawBoxes @ TemplateBox[ { }, "AssistantEvaluate" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Description*) +$wolframLanguageEvaluatorDescription = "\ +Evaluate Wolfram Language code for the user in a separate kernel. \ +The user does not automatically see the result. \ +Do not ask permission to evaluate code. \ +You must include the result in your response in order for them to see it. \ +If a formatted result is provided as a markdown link, use that in your response instead of typing out the output. \ +The evaluator supports interactive content such as Manipulate. \ +You have read access to local files. +Parse natural language input with `\[FreeformPrompt][\"query\"]`, which is analogous to ctrl-= input in notebooks. \ +Natural language input is parsed before evaluation, so it works like macro expansion. \ +You should ALWAYS use this natural language input to obtain things like `Quantity`, `DateObject`, `Entity`, etc. \ +\[FreeformPrompt] should be written as \\uf351 in JSON. +"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Spec*) +$defaultChatTools0[ "WolframLanguageEvaluator" ] = <| + toolDefaultData[ "WolframLanguageEvaluator" ], + "ShortName" -> "wl", + "Icon" -> $wolframLanguageEvaluatorIcon, + "Description" -> $wolframLanguageEvaluatorDescription, + "Enabled" :> ! TrueQ @ $AutomaticAssistance, + "FormattingFunction" -> sandboxFormatter, + "Function" -> sandboxEvaluate, + "Origin" -> "BuiltIn", + "Parameters" -> { + "code" -> <| + "Interpreter" -> "String", + "Help" -> "Wolfram Language code to evaluate", + "Required" -> True + |> + } +|>; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Tool Function*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*wolframLanguageEvaluator*) +wolframLanguageEvaluator // beginDefinition; + +wolframLanguageEvaluator[ code_String ] := + Block[ { $ChatNotebookEvaluation = True }, wolframLanguageEvaluator[ code, sandboxEvaluate @ code ] ]; + +wolframLanguageEvaluator[ code_, result_Association ] := + KeyTake[ result, { "Result", "String" } ]; + +wolframLanguageEvaluator // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Tools/DefaultTools.wl b/Source/Chatbook/Tools/DefaultTools.wl index c3f692a1..2bfef15f 100644 --- a/Source/Chatbook/Tools/DefaultTools.wl +++ b/Source/Chatbook/Tools/DefaultTools.wl @@ -1,1250 +1,24 @@ (* ::Section::Closed:: *) (*Package Header*) BeginPackage[ "Wolfram`Chatbook`Tools`" ]; - -(* cSpell: ignore TOOLCALL, ENDARGUMENTS, ENDTOOLCALL, Deflatten, Liouville, unexp *) - -(* :!CodeAnalysis::BeginBlock:: *) -(* :!CodeAnalysis::Disable::SuspiciousSessionSymbol:: *) - Begin[ "`Private`" ]; -Needs[ "Wolfram`Chatbook`" ]; -Needs[ "Wolfram`Chatbook`Common`" ]; -Needs[ "Wolfram`Chatbook`Personas`" ]; -Needs[ "Wolfram`Chatbook`ResourceInstaller`" ]; -Needs[ "Wolfram`Chatbook`Serialization`" ]; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*ChatPreferences*) - -(* Uncomment the following when the ChatPreferences tool is ready: *) -(* $defaultChatTools0[ "ChatPreferences" ] = <| - toolDefaultData[ "ChatPreferences" ], - "Icon" -> RawBoxes @ TemplateBox[ { }, "ChatBlockSettingsMenuIcon" ], - "Description" -> $chatPreferencesDescription, - "Function" -> chatPreferences, - "FormattingFunction" -> toolAutoFormatter, - "Origin" -> "BuiltIn", - "Parameters" -> { - "action" -> <| - "Interpreter" -> { "get", "set" }, - "Help" -> "Whether to get or set chat settings", - "Required" -> True - |>, - "key" -> <| - "Interpreter" -> "String", - "Help" -> "Which chat setting to get or set", - "Required" -> False - |>, - "value" -> <| - "Interpreter" -> "String", - "Help" -> "The value to set the chat setting to", - "Required" -> False - |>, - "scope" -> <| - "Interpreter" -> { "global", "notebook" }, - "Help" -> "The scope of the chat setting (default is 'notebook')", - "Required" -> False - |> - } -|>; *) - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*DocumentationSearch*) -$documentationSearchDescription = "\ -Search Wolfram Language documentation for symbols and more. \ -Follow up search results with the documentation lookup tool to get the full information."; - -$defaultChatTools0[ "DocumentationSearcher" ] = <| - toolDefaultData[ "DocumentationSearcher" ], - "ShortName" -> "doc_search", - "Icon" -> RawBoxes @ TemplateBox[ { }, "ToolIconDocumentationSearcher" ], - "Description" -> $documentationSearchDescription, - "Function" -> documentationSearch, - "FormattingFunction" -> toolAutoFormatter, - "Origin" -> "BuiltIn", - "Parameters" -> { - "query" -> <| - "Interpreter" -> "String", - "Help" -> "A string representing a documentation search query", - "Required" -> True - |> - } -|>; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*documentationSearch*) -documentationSearch // beginDefinition; -documentationSearch[ KeyValuePattern[ "query" -> name_ ] ] := documentationSearch @ name; -documentationSearch[ names_List ] := StringRiffle[ documentationSearch /@ names, "\n\n" ]; -documentationSearch[ name_String ] /; NameQ[ "System`" <> name ] := documentationLookup @ name; -documentationSearch[ query_String ] := documentationSearch[ query, documentationSearchAPI @ query ]; -documentationSearch[ query_String, { } ] := ToString[ Missing[ "NoResults" ], InputForm ]; -documentationSearch[ query_String, results_List ] := StringRiffle[ results, "\n" ]; -documentationSearch // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*DocumentationLookup*) -$defaultChatTools0[ "DocumentationLookup" ] = <| - toolDefaultData[ "DocumentationLookup" ], - "ShortName" -> "doc_lookup", - "Icon" -> RawBoxes @ TemplateBox[ { }, "ToolIconDocumentationLookup" ], - "Description" -> "Get documentation pages for Wolfram Language symbols.", - "Function" -> documentationLookup, - "FormattingFunction" -> toolAutoFormatter, - "Origin" -> "BuiltIn", - "Parameters" -> { - "names" -> <| - "Interpreter" -> DelimitedSequence[ "WolframLanguageSymbol", "," ], - "Help" -> "One or more Wolfram Language symbols separated by commas", - "Required" -> True - |> - } -|>; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*documentationLookup*) -documentationLookup // beginDefinition; - -documentationLookup[ KeyValuePattern[ "names" -> name_ ] ] := documentationLookup @ name; -documentationLookup[ name_Entity ] := documentationLookup @ CanonicalName @ name; -documentationLookup[ names_List ] := StringRiffle[ documentationLookup /@ names, "\n\n---\n\n" ]; - -documentationLookup[ name_String ] := Enclose[ - Module[ { usage, details, examples, strings, body }, - usage = ConfirmMatch[ documentationUsage @ name, _String|_Missing, "Usage" ]; - details = ConfirmMatch[ documentationDetails @ name, _String|_Missing, "Details" ]; - examples = ConfirmMatch[ documentationBasicExamples @ name, _String|_Missing, "Examples" ]; - strings = ConfirmMatch[ DeleteMissing @ { usage, details, examples }, { ___String }, "Strings" ]; - body = If[ strings === { }, ToString[ Missing[ "NotFound" ], InputForm ], StringRiffle[ strings, "\n\n" ] ]; - "# " <> name <> "\n\n" <> body - ], - throwInternalFailure[ documentationLookup @ name, ## ] & -]; - -documentationLookup // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*documentationUsage*) -documentationUsage // beginDefinition; -documentationUsage[ name_String ] := documentationUsage[ name, wolframLanguageData[ name, "PlaintextUsage" ] ]; -documentationUsage[ name_, missing_Missing ] := missing; -documentationUsage[ name_, usage_String ] := "## Usage\n\n" <> usage; -documentationUsage // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*documentationDetails*) -documentationDetails // beginDefinition; -documentationDetails[ name_String ] := Missing[ ]; (* TODO *) -documentationDetails // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*documentationBasicExamples*) -documentationBasicExamples // beginDefinition; - -documentationBasicExamples[ name_String ] := - documentationBasicExamples[ name, wolframLanguageData[ name, "DocumentationBasicExamples" ] ]; - -documentationBasicExamples[ name_, missing_Missing ] := missing; - -documentationBasicExamples[ name_, examples_List ] := Enclose[ - Module[ { cells, strings }, - cells = renumberCells @ Replace[ Flatten @ examples, RawBoxes[ cell_ ] :> cell, { 1 } ]; - strings = ConfirmMatch[ cellToString /@ cells, { ___String }, "CellToString" ]; - If[ strings === { }, - Missing[ ], - StringDelete[ - "## Basic Examples\n\n" <> StringRiffle[ strings, "\n\n" ], - Longest[ "```\n\n```"~~("wl"|"") ] - ] - ] - ], - throwInternalFailure[ documentationBasicExamples[ name, examples ], ## ] & -]; - -documentationBasicExamples // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*cellToString*) -cellToString[ args___ ] := CellToString[ - args, - "ContentTypes" -> If[ TrueQ @ $multimodalMessages, { "Text", "Image" }, Automatic ], - "MaxCellStringLength" -> 100 -]; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*renumberCells*) -renumberCells // beginDefinition; -renumberCells[ cells_List ] := Block[ { $line = 0 }, renumberCell /@ Flatten @ cells ]; -renumberCells // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*renumberCell*) -renumberCell // beginDefinition; - -renumberCell[ Cell[ a__, "Input", b: (Rule|RuleDelayed)[ _, _ ]... ] ] := - Cell[ a, "Input", CellLabel -> "In[" <> ToString @ ++$line <> "]:=" ]; - -renumberCell[ Cell[ a__, "Output", b: (Rule|RuleDelayed)[ _, _ ]... ] ] := - Cell[ a, "Output", CellLabel -> "Out[" <> ToString @ $line <> "]=" ]; - -renumberCell[ Cell[ a__, style: "Print"|"Echo", b: (Rule|RuleDelayed)[ _, _ ]... ] ] := - Cell[ a, style, CellLabel -> "During evaluation of In[" <> ToString @ $line <> "]:=" ]; - -renumberCell[ cell_Cell ] := cell; - -renumberCell // endDefinition; - -$line = 0; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*Evaluate*) -$sandboxEvaluateDescription = "\ -Evaluate Wolfram Language code for the user in a separate kernel. \ -The user does not automatically see the result. \ -Do not ask permission to evaluate code. \ -You must include the result in your response in order for them to see it. \ -If a formatted result is provided as a markdown link, use that in your response instead of typing out the output. \ -The evaluator supports interactive content such as Manipulate. \ -You have read access to local files. -Parse natural language input with `\[FreeformPrompt][\"query\"]`, which is analogous to ctrl-= input in notebooks. \ -Natural language input is parsed before evaluation, so it works like macro expansion. \ -You should ALWAYS use this natural language input to obtain things like `Quantity`, `DateObject`, `Entity`, etc. \ -\[FreeformPrompt] should be written as \\uf351 in JSON. -"; - -$defaultChatTools0[ "WolframLanguageEvaluator" ] = <| - toolDefaultData[ "WolframLanguageEvaluator" ], - "ShortName" -> "wl", - "Description" -> $sandboxEvaluateDescription, - "Enabled" :> ! TrueQ @ $AutomaticAssistance, - "FormattingFunction" -> sandboxFormatter, - "Function" -> sandboxEvaluate, - "Icon" -> RawBoxes @ TemplateBox[ { }, "AssistantEvaluate" ], - "Origin" -> "BuiltIn", - "Parameters" -> { - "code" -> <| - "Interpreter" -> "String", - "Help" -> "Wolfram Language code to evaluate", - "Required" -> True - |> - } -|>; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*wolframLanguageEvaluator*) -wolframLanguageEvaluator // beginDefinition; - -wolframLanguageEvaluator[ code_String ] := - Block[ { $ChatNotebookEvaluation = True }, wolframLanguageEvaluator[ code, sandboxEvaluate @ code ] ]; - -wolframLanguageEvaluator[ code_, result_Association ] := - KeyTake[ result, { "Result", "String" } ]; - -wolframLanguageEvaluator // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*Wolfram Alpha*) -$wolframAlphaDescription = "\ -Use natural language queries with Wolfram|Alpha to get up-to-date computational results about entities in chemistry, \ -physics, geography, history, art, astronomy, and more."; - -$wolframAlphaIcon = RawBoxes @ DynamicBox @ FEPrivate`FrontEndResource[ "FEBitmaps", "InsertionAlpha" ]; - -$defaultChatTools0[ "WolframAlpha" ] = <| - toolDefaultData[ "WolframAlpha" ], - "ShortName" -> "wa", - "Description" -> $wolframAlphaDescription, - "DisplayName" -> "Wolfram|Alpha", - "Enabled" :> ! TrueQ @ $AutomaticAssistance, - "FormattingFunction" -> wolframAlphaResultFormatter, - "Function" -> getWolframAlphaText, - "Icon" -> $wolframAlphaIcon, - "Origin" -> "BuiltIn", - "Parameters" -> { - "query" -> <| - "Interpreter" -> "String", - "Help" -> "the input", - "Required" -> True - |>, - "steps" -> <| - "Interpreter" -> "Boolean", - "Help" -> "whether to show step-by-step solution", - "Required" -> False - |>(*, - "assumption" -> <| - "Interpreter" -> "String", - "Help" -> "the assumption to use, passed back from a previous query with the same input.", - "Required" -> False - |>*) - } -|>; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*WebSearch*) -$defaultChatTools0[ "WebSearcher" ] = <| - toolDefaultData[ "WebSearcher" ], - "ShortName" -> "web_search", - "Icon" -> RawBoxes @ TemplateBox[ { }, "ToolIconWebSearcher" ], - "Description" -> "Search the web.", - "Function" -> webSearch, - "FormattingFunction" -> toolAutoFormatter, - "Origin" -> "BuiltIn", - "Parameters" -> { - "query" -> <| - "Interpreter" -> "String", - "Help" -> "Search query text", - "Required" -> True - |> - } -|>; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*webSearch*) -webSearch // beginDefinition; - -webSearch[ KeyValuePattern[ "query" -> query_ ] ] := - Block[ { PrintTemporary }, webSearch @ query ]; - -webSearch[ query_String ] := Enclose[ - Catch @ Module[ { result, json, string }, - result = ConfirmMatch[ webSearch0 @ query, _Dataset|_Failure, "WebSearch" ]; - - If[ MatchQ[ result, _Failure ], - Throw @ <| "Result" -> result, "String" -> makeFailureString @ result |> - ]; - - json = ConfirmBy[ Developer`WriteRawJSONString[ Normal @ result /. URL[ url_ ] :> url ], StringQ, "JSON" ]; - json = StringReplace[ json, "\\/" -> "/" ]; - string = ConfirmBy[ TemplateApply[ $webSearchResultTemplate, json ], StringQ, "TemplateApply" ]; - - <| "Result" -> result, "String" -> string |> - ], - throwInternalFailure -]; - -webSearch // endDefinition; - - -webSearch0 // beginDefinition; - -webSearch0[ query_String ] := Enclose[ - Module[ { opts, raw, result, held, $unavailable }, - opts = Sequence @@ ConfirmMatch[ toolOptions[ "WebSearcher" ], { $$optionsSequence }, "Options" ]; - result = Quiet[ - Check[ - raw = WebSearch[ query, opts ], - $unavailable, - IntegratedServices`IntegratedServices::unexp - ], - IntegratedServices`IntegratedServices::unexp - ]; - - held = HoldForm @ Evaluate @ raw; - - Quiet @ Replace[ - result, - { - $unavailable :> messageFailure[ "IntegratedServiceUnavailable", "WebSearch", held ], - Except[ _Dataset ] :> messageFailure[ "IntegratedServiceError" , "WebSearch", held ] - } - ] - ], - throwInternalFailure -]; - -webSearch0 // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*$webSearchResultTemplate*) -$webSearchResultTemplate := StringTemplate @ StringJoin[ - "Results\n-------\n\n`1`\n\n-------", - If[ toolSelectedQ[ "WebFetcher" ], - $webSearchFetchPrompt, - "" - ] -]; - -$webSearchFetchPrompt = " - -Important: The snippet text is not enough information to write an informed response! If there are any relevant \ -results, you should now immediately use the web_fetcher tool to retrieve them before responding. Do not ask the user \ -for permission first. If it made sense to use the web_searcher tool, it's also implied that you should use the \ -web_fetcher tool."; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*WebFetch*) -$defaultChatTools0[ "WebFetcher" ] = <| - toolDefaultData[ "WebFetcher" ], - "ShortName" -> "web_fetch", - "Icon" -> RawBoxes @ TemplateBox[ { }, "ToolIconWebFetcher" ], - "Description" -> "Fetch plain text or image links from a URL.", - "Function" -> webFetch, - "FormattingFunction" -> toolAutoFormatter, - "Origin" -> "BuiltIn", - "Parameters" -> { - "url" -> <| - "Interpreter" -> "URL", - "Help" -> "The URL", - "Required" -> True - |>, - "format" -> <| - "Interpreter" -> { "Plaintext", "ImageLinks" }, - "Help" -> "The type of content to retrieve (\"Plaintext\" or \"ImageLinks\")", - "Required" -> True - |> - } -|>; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*webFetch*) -webFetch // beginDefinition; -webFetch[ KeyValuePattern @ { "url" -> url_, "format" -> fmt_ } ] := webFetch[ url, fmt ]; -webFetch[ url_, "Plaintext" ] := fetchWebText @ url; -webFetch[ url: _URL|_String, fmt_String ] := webFetch[ url, fmt, Import[ url, { "HTML", fmt } ] ]; -webFetch[ url_, "ImageLinks", { } ] := <| "Result" -> { }, "String" -> "No links found at " <> TextString @ url |>; -webFetch[ url_, "ImageLinks", links: { __String } ] := <| "Result" -> links, "String" -> StringRiffle[ links, "\n" ] |>; -webFetch[ url_, fmt_, result_String ] := shortenWebText @ niceWebText @ result; -webFetch // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*fetchWebText*) -fetchWebText // beginDefinition; - -fetchWebText[ URL[ url_ ] ] := - fetchWebText @ url; - -fetchWebText[ url_String ] := - fetchWebText[ url, $webSession ]; - -fetchWebText[ url_String, session_WebSessionObject ] := Enclose[ - Module[ { body, strings }, - ConfirmMatch[ WebExecute[ session, { "OpenPage" -> url } ], _Success | { __Success } ]; - Pause[ 3 ]; (* Allow time for the page to load *) - body = ConfirmMatch[ WebExecute[ session, "LocateElements" -> "Tag" -> "body" ], { __WebElementObject } ]; - strings = ConfirmMatch[ WebExecute[ "ElementText" -> body ], { __String } ]; - shortenWebText @ niceWebText @ strings - ], - shortenWebText @ niceWebText @ Import[ url, { "HTML", "Plaintext" } ] & -]; - -fetchWebText[ url_String, _Missing | _? FailureQ ] := - shortenWebText @ niceWebText @ Import[ url, { "HTML", "Plaintext" } ]; - -fetchWebText // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*shortenWebText*) -shortenWebText // beginDefinition; -shortenWebText[ text_String ] := shortenWebText[ text, toolOptionValue[ "WebFetcher", "MaxContentLength" ] ]; -shortenWebText[ text_String, len_Integer? Positive ] := StringTake[ text, UpTo[ len ] ]; -shortenWebText[ text_String, Infinity|All ] := text; -shortenWebText[ text_String, _ ] := shortenWebText[ text, $defaultWebTextLength ]; -shortenWebText // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*niceWebText*) -niceWebText // beginDefinition; -niceWebText[ str_String ] := StringReplace[ StringDelete[ str, "\r" ], Longest[ "\n"~~Whitespace~~"\n" ] :> "\n\n" ]; -niceWebText[ strings_List ] := StringRiffle[ StringTrim[ niceWebText /@ strings ], "\n\n" ]; -niceWebText // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*$webSession*) -$webSession := getWebSession[ ]; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*getWebSession*) -getWebSession // beginDefinition; -getWebSession[ ] := getWebSession @ $currentWebSession; -getWebSession[ session_WebSessionObject? validWebSessionQ ] := session; -getWebSession[ session_WebSessionObject ] := (Quiet @ DeleteObject @ session; startWebSession[ ]); -getWebSession[ _ ] := startWebSession[ ]; -getWebSession // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*validWebSessionQ*) -validWebSessionQ // ClearAll; - -validWebSessionQ[ session_WebSessionObject ] := - With[ { valid = Quiet @ StringQ @ WebExecute[ session, "PageURL" ] }, - If[ valid, True, Quiet @ DeleteObject @ session; False ] - ]; - -validWebSessionQ[ ___ ] := False; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*startWebSession*) -startWebSession // beginDefinition; - -startWebSession[ ] := $currentWebSession = - If[ TrueQ @ $CloudEvaluation, - Missing[ "NotAvailable" ], - StartWebSession[ Visible -> $webSessionVisible ] - ]; - -startWebSession // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*WebImageSearch*) -$defaultChatTools0[ "WebImageSearcher" ] = <| - toolDefaultData[ "WebImageSearcher" ], - "ShortName" -> "img_search", - "Icon" -> RawBoxes @ TemplateBox[ { }, "ToolIconWebImageSearcher" ], - "Description" -> "Search the web for images.", - "Function" -> webImageSearch, - "FormattingFunction" -> toolAutoFormatter, - "Origin" -> "BuiltIn", - "Parameters" -> { - "query" -> <| - "Interpreter" -> "String", - "Help" -> "Search query text", - "Required" -> True - |> - } -|>; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*webImageSearch*) -webImageSearch // beginDefinition; - -webImageSearch[ KeyValuePattern[ "query" -> query_ ] ] := Block[ { PrintTemporary }, webImageSearch @ query ]; -webImageSearch[ query_String ] := webImageSearch[ query, webImageSearch0[ query ] ]; - -webImageSearch[ query_, { } ] := <| - "Result" -> { }, - "String" -> "No results found" -|>; - -webImageSearch[ query_, urls: { __ } ] := <| - "Result" -> Column[ Hyperlink /@ urls, BaseStyle -> "Text" ], - "String" -> StringRiffle[ TextString /@ urls, "\n" ] -|>; - -webImageSearch[ query_, failed_Failure ] := <| - "Result" -> failed, - "String" -> makeFailureString @ failed -|>; - -webImageSearch // endDefinition; - - -webImageSearch0 // beginDefinition; - -webImageSearch0[ query_String ] := Enclose[ - Module[ { opts, raw, result, held, $unavailable }, - opts = Sequence @@ ConfirmMatch[ toolOptions[ "WebImageSearcher" ], { $$optionsSequence }, "Options" ]; - result = Quiet[ - Check[ - raw = WebImageSearch[ query, "ImageHyperlinks", opts ], - $unavailable, - IntegratedServices`IntegratedServices::unexp - ], - IntegratedServices`IntegratedServices::unexp - ]; - - held = HoldForm @ Evaluate @ raw; - - Quiet @ Replace[ - result, - { - $unavailable :> messageFailure[ "IntegratedServiceUnavailable", "WebImageSearch", held ], - Except[ _List ] :> messageFailure[ "IntegratedServiceError" , "WebImageSearch", held ] - } - ] - ], - throwInternalFailure -]; - -webImageSearch0 // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Section::Closed:: *) -(*Full Examples*) - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*$fullExamples*) -$fullExamples := - With[ { keys = $fullExamplesKeys }, - If[ keys === { }, - "", - needsBasePrompt[ "EndTurnToolCall" ]; - StringJoin[ - "## Full examples\n\n", - "The following are brief conversation examples that demonstrate how you can use tools in a ", - "conversation with the user.\n\n---\n\n", - StringRiffle[ Values @ KeyTake[ $fullExamples0, $fullExamplesKeys ], "\n\n---\n\n" ], - "\n\n---\n" - ] - ] - ]; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*$fullExamplesKeys*) -$fullExamplesKeys := - With[ { selected = Keys @ $selectedTools }, - Select[ - { - "AstroGraphicsDocumentation", - "FileSystemTree", - "FractionalDerivatives", - "NaturalLanguageInput", - "PlotEvaluate", - "TemporaryDirectory" - }, - ContainsAll[ selected, $exampleDependencies[ #1 ] ] & - ] - ]; - -$exampleDependencies = <| - "AstroGraphicsDocumentation" -> { "DocumentationLookup" }, - "FileSystemTree" -> { "DocumentationSearcher", "DocumentationLookup" }, - "FractionalDerivatives" -> { "DocumentationSearcher", "DocumentationLookup", "WolframLanguageEvaluator" }, - "NaturalLanguageInput" -> { "WolframLanguageEvaluator" }, - "PlotEvaluate" -> { "WolframLanguageEvaluator" }, - "TemporaryDirectory" -> { "DocumentationSearcher", "WolframLanguageEvaluator" } -|>; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*$fullExamples0*) -$fullExamples0 = <| |>; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*Example Templates*) -$chatMessageTemplates = <| |>; -$messageTemplateType = "Basic"; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*Basic*) -$chatMessageTemplates[ "Basic" ] = <| |>; -$chatMessageTemplates[ "Basic", "User" ] = "User: %%1%%"; -$chatMessageTemplates[ "Basic", "Assistant" ] = "Assistant: %%1%%\n/end"; -$chatMessageTemplates[ "Basic", "System" ] = "System: %%1%%"; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*Instruct*) -$chatMessageTemplates[ "Instruct" ] = <| |>; -$chatMessageTemplates[ "Instruct", "User" ] = "[INST]%%1%%[/INST]"; -$chatMessageTemplates[ "Instruct", "Assistant" ] = "%%1%%\n/end"; -$chatMessageTemplates[ "Instruct", "System" ] = "[INST]%%1%%[/INST]"; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*Zephyr*) -$chatMessageTemplates[ "Zephyr" ] = <| |>; -$chatMessageTemplates[ "Zephyr", "User" ] = "<|user|>\n%%1%%"; -$chatMessageTemplates[ "Zephyr", "Assistant" ] = "<|assistant|>\n%%1%%\n/end"; -$chatMessageTemplates[ "Zephyr", "System" ] = "<|system|>\n%%1%%"; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*Phi*) -$chatMessageTemplates[ "Phi" ] = <| |>; -$chatMessageTemplates[ "Phi", "User" ] = "<|user|>\n%%1%%<|end|>"; -$chatMessageTemplates[ "Phi", "Assistant" ] = "<|assistant|>\n%%1%%\n/end<|end|>"; -$chatMessageTemplates[ "Phi", "System" ] = "<|user|>\n%%1%%<|end|>"; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*Boxed*) -$chatMessageTemplates[ "Boxed" ] = <| |>; -$chatMessageTemplates[ "Boxed", "User" ] = "[user]\n%%1%%"; -$chatMessageTemplates[ "Boxed", "Assistant" ] = "[assistant]\n%%1%%\n/end"; -$chatMessageTemplates[ "Boxed", "System" ] = "[system]\n%%1%%"; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*ChatML*) -$chatMessageTemplates[ "ChatML" ] = <| |>; -$chatMessageTemplates[ "ChatML", "User" ] = "<|im_start|>user\n%%1%%<|im_end|>"; -$chatMessageTemplates[ "ChatML", "Assistant" ] = "<|im_start|>assistant\n%%1%%\n/end<|im_end|>"; -$chatMessageTemplates[ "ChatML", "System" ] = "<|im_start|>system\n%%1%%<|im_end|>"; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*XML*) -$chatMessageTemplates[ "XML" ] = <| |>; -$chatMessageTemplates[ "XML", "User" ] = "%%1%%"; -$chatMessageTemplates[ "XML", "Assistant" ] = "%%1%%\n/end"; -$chatMessageTemplates[ "XML", "System" ] = "%%1%%"; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*messageTemplate*) -messageTemplate // beginDefinition; - -messageTemplate[ id_String ] := Enclose[ - StringTemplate[ - ConfirmBy[ $chatMessageTemplates[ $messageTemplateType, id ], StringQ, "TemplateString" ], - Delimiters -> "%%" - ], - throwInternalFailure -]; - -messageTemplate // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*user*) -user // beginDefinition; -user[ a_List ] := TemplateApply[ messageTemplate[ "User" ], StringRiffle[ TextString /@ Flatten @ a, "\n" ] ]; -user[ a_String ] := user @ { a }; -user // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*assistant*) -assistant // beginDefinition; -assistant[ { a___, "tool"|"Tool" -> { name_, as_ }, b___ } ] := assistant @ { a, toolCall[ name, as ], b }; -assistant[ a_List ] := TemplateApply[ messageTemplate[ "Assistant" ], StringRiffle[ TextString /@ Flatten @ a, "\n" ] ]; -assistant[ a_String ] := assistant @ { a }; -assistant // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*system*) -system // beginDefinition; -system[ a_List ] := TemplateApply[ messageTemplate[ "System" ], StringRiffle[ TextString /@ Flatten @ a, "\n" ] ]; -system[ a_String ] := system @ { a }; -system // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*toolCall*) -toolCall // beginDefinition; -toolCall[ args__ ] := formatToolCallExample @ args; -toolCall // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*toolExample*) -toolExample // beginDefinition; -toolExample[ { rules: (_Rule|_String)... } ] := StringRiffle[ toolExample0 /@ { rules }, "\n\n" ]; -toolExample[ rules: (_Rule|_String)... ] := toolExample @ { rules }; -toolExample // endDefinition; - -toolExample0 // beginDefinition; -toolExample0[ "user"|"User" -> message_ ] := user @ message; -toolExample0[ "assistant"|"Assistant" -> message_ ] := assistant @ message; -toolExample0[ "system"|"System" -> message_ ] := system @ message; -toolExample0[ prompt_String ] := prompt; -toolExample0 // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*AstroGraphicsDocumentation*) -$fullExamples0[ "AstroGraphicsDocumentation" ] := toolExample[ - "user" -> "How do I use AstroGraphics?", - "assistant" -> { - "Let me check the documentation for you. One moment...", - "tool" -> { "DocumentationLookup", <| "names" -> "AstroGraphics" |> } - }, - "system" -> { - "Usage", - "AstroGraphics[primitives, options] represents a two-dimensional view of space and the celestial sphere.", - "", - "Basic Examples", - "..." - }, - "assistant" -> "To use [AstroGraphics](paclet:ref/AstroGraphics), you need to..." -]; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*NaturalLanguageInput*) -$fullExamples0[ "NaturalLanguageInput" ] := toolExample[ - "user" -> "How far away is NYC from Boston?", - "assistant" -> { - "tool" -> { - "WolframLanguageEvaluator", - <| "code" -> "GeoDistance[\[FreeformPrompt][\"Boston, MA\"], \[FreeformPrompt][\"New York City\"]]" |> - } - }, - "system" -> "Quantity[164.41, \"Miles\"]", - "assistant" -> "It's 164.41 miles from Boston to New York City.", - "user" -> "If I made the trip in 3h 17m, how fast was I going?", - "assistant" -> { - "tool" -> { - "WolframLanguageEvaluator", - <| "code" -> "\[FreeformPrompt][\"164.41 Miles\"] / \[FreeformPrompt][\"3h 17m\"]" |> - } - }, - "system" -> "Quantity[50.071, \"Miles\" / \"Hours\"]", - "assistant" -> "You were going 50.071 miles per hour.", - "user" -> "What time would I arrive if I left right now?", - "assistant" -> { - "tool" -> { - "WolframLanguageEvaluator", - <| "code" -> "\[FreeformPrompt][\"3h 17m from now\"]" |> - } - } -]; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*FileSystemTree*) -$fullExamples0[ "FileSystemTree" ] := toolExample[ - "user" -> "What's the best way to generate a tree of files in a given directory?", - "assistant" -> { - "tool" -> { "DocumentationSearcher", <| "query" -> "tree of files" |> } - }, - "system" -> { - "* FileSystemTree - (score: 9.9) FileSystemTree[root] gives a tree whose keys are ...", - "* Tree Drawing - (score: 3.0) ..." - }, - "assistant" -> { - "tool" -> { "DocumentationLookup", <| "names" -> "FileSystemTree" |> } - }, - "..." -]; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*FractionalDerivatives*) -$fullExamples0[ "FractionalDerivatives" ] := toolExample[ - "user" -> "Calculate the half-order fractional derivative of x^n with respect to x.", - "assistant" -> { - "tool" -> { "DocumentationSearcher", <| "query" -> "fractional derivatives" |> } - }, - "system" -> { - "* FractionalD - (score: 9.5) FractionalD[f, {x, a}] gives ...", - "* NFractionalD - (score: 9.2) ..." - }, - "assistant" -> { - "tool" -> { "DocumentationLookup", <| "names" -> "FractionalD" |> } - }, - "system" -> { - "Usage", - "FractionalD[f, {x, a}] gives the Riemann-Liouville fractional derivative D_x^a f(x) of order a of the function f.", - "", - "Basic Examples", - "..." - }, - "assistant" -> { - "tool" -> { - "WolframLanguageEvaluator", - <| "code" -> "FractionalD[x^n, {x, 1/2}]" |> - } - }, - "system" -> { - "Out[n]= Piecewise[...]\n", - "![Formatted Result](expression://content-{id})" - }, - "assistant" -> { - "The half-order fractional derivative of $$x^n$$ with respect to $$x$$ is given by:", - "![Fractional Derivative](expression://content-{id})" - } -]; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*PlotEvaluate*) -$fullExamples0[ "PlotEvaluate" ] := toolExample[ - "user" -> "Plot sin(x) from -5 to 5", - "assistant" -> { - "tool" -> { - "WolframLanguageEvaluator", - <| "code" -> "Plot[Sin[x], {x, -5, 5}, AxesLabel -> {\"x\", \"sin(x)\"}" |> - } - }, - "system" -> "Out[n]= ![image](attachment://content-{id})", - "assistant" -> { - "Here's the plot of $$\\sin{x}$$ from -5 to 5:", - "![Plot](attachment://content-{id})" - } -]; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*TemporaryDirectory*) -$fullExamples0[ "TemporaryDirectory" ] := toolExample[ - "user" -> "Where is the temporary directory located?", - "assistant" -> { - "tool" -> { "DocumentationSearcher", <| "query" -> "location of temporary directory" |> } - }, - "system" -> { - "* $TemporaryDirectory - (score: 9.6) $TemporaryDirectory gives the main system directory for temporary files.", - "* CreateDirectory - (score: 8.5) CreateDirectory[\"dir\"] creates ..." - }, - "assistant" -> { - "tool" -> { "WolframLanguageEvaluator", <| "code" -> "$TemporaryDirectory" |> } - }, - "system" -> "Out[n]= \"C:\\Users\\UserName\\AppData\\Local\\Temp\"", - "assistant" -> "The temporary directory is located at C:\\Users\\UserName\\AppData\\Local\\Temp." -]; +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) -(*Expression URIs*) -$expressionSchemes = { "attachment", "audio", "dynamic", "expression", "video" }; -$$expressionScheme = Alternatives @@ $expressionSchemes; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*FormatToolResponse*) -FormatToolResponse // ClearAll; -FormatToolResponse[ response_ ] := makeToolResponseString @ response; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*MakeExpressionURI*) -MakeExpressionURI // ClearAll; -MakeExpressionURI[ args: Repeated[ _, { 1, 3 } ] ] := makeExpressionURI @ args; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*GetExpressionURIs*) -GetExpressionURIs // ClearAll; -GetExpressionURIs // Options = { Tooltip -> Automatic }; - -GetExpressionURIs[ str_, opts: OptionsPattern[ ] ] := - GetExpressionURIs[ str, ## &, opts ]; - -GetExpressionURIs[ str_String, wrapper_, opts: OptionsPattern[ ] ] := - catchMine @ Block[ { $uriTooltip = OptionValue @ Tooltip }, - StringSplit[ - str, - link: Shortest[ "![" ~~ __ ~~ "](" ~~ __ ~~ ")" ] /; expressionURIQ @ link :> - catchAlways @ GetExpressionURI[ link, wrapper ] - ] - ]; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*GetExpressionURI*) -GetExpressionURI // beginDefinition; -GetExpressionURI // Options = { Tooltip -> Automatic }; - -GetExpressionURI[ uri_, opts: OptionsPattern[ ] ] := - catchMine @ GetExpressionURI[ uri, ## &, opts ]; - -GetExpressionURI[ URL[ uri_ ], wrapper_, opts: OptionsPattern[ ] ] := - catchMine @ GetExpressionURI[ uri, wrapper, opts ]; - -GetExpressionURI[ uri_String, wrapper_, opts: OptionsPattern[ ] ] := catchMine @ Enclose[ - Module[ { held }, - held = ConfirmMatch[ getExpressionURI[ uri, OptionValue[ Tooltip ] ], _HoldComplete, "GetExpressionURI" ]; - wrapper @@ held - ], - throwInternalFailure -]; - -GetExpressionURI[ All, wrapper_, opts: OptionsPattern[ ] ] := catchMine @ Enclose[ - Module[ { attachments }, - attachments = ConfirmBy[ $attachments, AssociationQ, "Attachments" ]; - ConfirmAssert[ AllTrue[ attachments, MatchQ[ _HoldComplete ] ], "HeldAttachments" ]; - Replace[ attachments, HoldComplete[ a___ ] :> RuleCondition @ wrapper @ a, { 1 } ] - ], - throwInternalFailure -]; - -GetExpressionURI // endExportedDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*getExpressionURI0*) -getExpressionURI // beginDefinition; -getExpressionURI[ uri_, tooltip_ ] := Block[ { $tooltip = tooltip }, getExpressionURI0 @ uri ]; -getExpressionURI // endDefinition; - - -getExpressionURI0 // beginDefinition; - -getExpressionURI0[ str_String ] := - Module[ { split }, - split = First[ StringSplit[ str, "![" ~~ alt__ ~~ "](" ~~ url__ ~~ ")" :> { alt, url } ], $Failed ]; - getExpressionURI0 @@ split /; MatchQ[ split, { _String, _String } ] - ]; - -getExpressionURI0[ uri_String ] := getExpressionURI0[ None, uri ]; - -getExpressionURI0[ tooltip_, uri_String? expressionURIKeyQ ] := - getExpressionURI0[ tooltip, uri, <| "Domain" -> uri |> ]; - -getExpressionURI0[ tooltip_, uri_String ] := getExpressionURI0[ tooltip, uri, URLParse @ uri ]; - -getExpressionURI0[ tooltip_, uri_, as: KeyValuePattern[ "Domain" -> key_? expressionURIKeyQ ] ] := Enclose[ - ConfirmMatch[ displayAttachment[ uri, tooltip, key ], _HoldComplete, "DisplayAttachment" ], - throwInternalFailure -]; - -getExpressionURI0[ tooltip_, uri_String, as_ ] := - throwFailure[ "InvalidExpressionURI", uri ]; - -getExpressionURI0 // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*expressionURIQ*) -expressionURIQ // beginDefinition; -expressionURIQ[ str_String ] := expressionURIKeyQ @ expressionURIKey @ str; -expressionURIQ // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*expressionURIKeyQ*) -expressionURIKeyQ // beginDefinition; - -expressionURIKeyQ[ key_String ] := - StringMatchQ[ key, "content-" ~~ Repeated[ LetterCharacter|DigitCharacter, $tinyHashLength ] ]; - -expressionURIKeyQ[ _ ] := - False; - -expressionURIKeyQ // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*expressionURIKey*) -expressionURIKey // beginDefinition; - -expressionURIKey[ str_String ] := expressionURIKey[ str ] = FixedPoint[ - StringDelete @ { - StartOfString ~~ "![" ~~ __ ~~ "](", - StartOfString ~~ LetterCharacter.. ~~ "://", - ")"~~EndOfString - }, - str -]; - -expressionURIKey // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*displayAttachment*) -displayAttachment // beginDefinition; - -displayAttachment[ uri_, None, key_ ] := - getAttachment[ uri, key ]; - -displayAttachment[ uri_, tooltip_String, key_ ] := Enclose[ - Replace[ - ConfirmMatch[ getAttachment[ uri, key ], _HoldComplete, "GetAttachment" ], - HoldComplete[ expr_ ] :> - If[ TrueQ @ $tooltip, - HoldComplete @ Tooltip[ expr, tooltip ], - HoldComplete @ expr - ] - ], - throwInternalFailure -]; - -displayAttachment // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*getAttachment*) -getAttachment // beginDefinition; - -getAttachment[ uri_String, key_String ] := - Lookup[ $attachments, key, throwFailure[ "URIUnavailable", uri ] ]; - -getAttachment // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*makeToolResponseString*) -makeToolResponseString // beginDefinition; - -makeToolResponseString[ failure_Failure ] := makeFailureString @ failure; - -makeToolResponseString[ expr_? simpleResultQ ] := - With[ { string = fixLineEndings @ TextString @ expr }, - If[ StringLength @ string < $toolResultStringLength, - If[ StringContainsQ[ string, "\n" ], "\n" <> string, string ], - StringJoin[ - "\n", - fixLineEndings @ ToString[ - Unevaluated @ Short[ expr, Floor[ $toolResultStringLength / 100 ] ], - OutputForm, - PageWidth -> 100 - ], - "\n\n\n", - makeExpressionURI[ "expression", "Formatted Result", Unevaluated @ expr ] - ] - ] - ]; - -makeToolResponseString[ expr_ ] := makeExpressionURI @ expr; - -makeToolResponseString // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*makeExpressionURI*) -makeExpressionURI // beginDefinition; - -makeExpressionURI[ expr_ ] := - makeExpressionURI[ Automatic, Unevaluated @ expr ]; - -makeExpressionURI[ label_, expr_ ] := - makeExpressionURI[ Automatic, label, Unevaluated @ expr ]; - -makeExpressionURI[ Automatic, label_, expr_ ] := - makeExpressionURI[ expressionURIScheme @ expr, label, Unevaluated @ expr ]; - -makeExpressionURI[ scheme_, Automatic, expr_ ] := - makeExpressionURI[ scheme, expressionURILabel @ expr, Unevaluated @ expr ]; - -makeExpressionURI[ scheme_, label_, expr_ ] := - With[ { id = "content-" <> tinyHash @ Unevaluated @ expr }, - $attachments[ id ] = HoldComplete @ expr; - "![" <> TextString @ label <> "](" <> TextString @ scheme <> "://" <> id <> ")" - ]; - -makeExpressionURI // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*expressionURILabel*) -expressionURILabel // beginDefinition; -expressionURILabel // Attributes = { HoldAllComplete }; - -(* Audio *) -expressionURILabel[ Audio[ path_String, ___ ] ] := "Audio Player: " <> path; -expressionURILabel[ Audio[ File[ path_String ], ___ ] ] := "Audio Player: " <> path; -expressionURILabel[ _Audio ] := "Embedded Audio Player"; - -(* Video *) -expressionURILabel[ Video[ path_String, ___ ] ] := "Video Player: " <> path; -expressionURILabel[ Video[ File[ path_String ], ___ ] ] := "Video Player: " <> path; -expressionURILabel[ _Video ] := "Embedded Video Player"; - -(* Dynamic *) -expressionURILabel[ _Manipulate ] := "Embedded Interactive Content"; - -(* Graphics *) -expressionURILabel[ _Graph|_Graph3D ] := "Graph"; -expressionURILabel[ _Tree ] := "Tree"; -expressionURILabel[ gfx_ ] /; graphicsQ @ Unevaluated @ gfx := "Image"; - -(* Data *) -expressionURILabel[ _List|_Association ] := "Data"; - -(* Other *) -expressionURILabel[ _ ] := "Content"; - -expressionURILabel // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*expressionURIScheme*) -expressionURIScheme // beginDefinition; -expressionURIScheme // Attributes = { HoldAllComplete }; -expressionURIScheme[ _Video ] := (needsURIPrompt[ "SpecialURIVideo" ]; "video"); -expressionURIScheme[ _Audio ] := (needsURIPrompt[ "SpecialURIAudio" ]; "audio"); -expressionURIScheme[ _Manipulate|_DynamicModule|_Dynamic ] := (needsURIPrompt[ "SpecialURIDynamic" ]; "dynamic"); -expressionURIScheme[ gfx_ ] /; graphicsQ @ Unevaluated @ gfx := "attachment"; -expressionURIScheme[ _ ] := "expression"; -expressionURIScheme // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsubsection::Closed:: *) -(*needsURIPrompt*) -needsURIPrompt // beginDefinition; - -needsURIPrompt[ name_String ] := ( - needsBasePrompt[ name ]; - If[ toolSelectedQ[ "WolframLanguageEvaluator" ], needsBasePrompt[ "SpecialURIImporting" ] ] -); - -needsURIPrompt // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Section::Closed:: *) -(*Utilities*) - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*Documentation*) - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*wolframLanguageData*) -wolframLanguageData // beginDefinition; - -wolframLanguageData[ name_, property_ ] := Enclose[ - wolframLanguageData[ name, property ] = ConfirmBy[ WolframLanguageData[ name, property ], Not@*FailureQ ], - Missing[ "DataFailure" ] & -]; - -wolframLanguageData // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*Tool Properties*) - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*getToolIcon*) -getToolIcon // beginDefinition; -getToolIcon[ tool: $$llmTool ] := getToolIcon @ toolData @ tool; -getToolIcon[ as_Association ] := Lookup[ toolData @ as, "Icon", RawBoxes @ TemplateBox[ { }, "WrenchIcon" ] ]; -getToolIcon[ _ ] := $defaultToolIcon; -getToolIcon // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*getToolDisplayName*) -getToolDisplayName // beginDefinition; - -getToolDisplayName[ tool_ ] := - getToolDisplayName[ tool, Missing[ "NotFound" ] ]; - -getToolDisplayName[ tool: $$llmTool, default_ ] := - getToolDisplayName @ toolData @ tool; - -getToolDisplayName[ as_Association, default_ ] := - Lookup[ as, "DisplayName", toDisplayToolName @ Lookup[ as, "Name", default ] ]; - -getToolDisplayName[ _, default_ ] := - default; - -getToolDisplayName // endDefinition; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*getToolFormattingFunction*) -getToolFormattingFunction // beginDefinition; -getToolFormattingFunction[ HoldPattern @ LLMTool[ as_, ___ ] ] := getToolFormattingFunction @ as; -getToolFormattingFunction[ as_Association ] := Lookup[ as, "FormattingFunction", Automatic ]; -getToolFormattingFunction[ _ ] := Automatic; -getToolFormattingFunction // endDefinition; +(*Default Tools*) +(* Uncomment the following when the ChatPreferences tool is ready: *) +(* Get[ "Wolfram`Chatbook`Tools`DefaultToolDefinitions`ChatPreferences`" ]; *) +Get[ "Wolfram`Chatbook`Tools`DefaultToolDefinitions`DocumentationLookup`" ]; +Get[ "Wolfram`Chatbook`Tools`DefaultToolDefinitions`DocumentationSearcher`" ]; +Get[ "Wolfram`Chatbook`Tools`DefaultToolDefinitions`NotebookEditor`" ]; +Get[ "Wolfram`Chatbook`Tools`DefaultToolDefinitions`WebFetcher`" ]; +Get[ "Wolfram`Chatbook`Tools`DefaultToolDefinitions`WebImageSearcher`" ]; +Get[ "Wolfram`Chatbook`Tools`DefaultToolDefinitions`WebSearcher`" ]; +Get[ "Wolfram`Chatbook`Tools`DefaultToolDefinitions`WolframAlpha`" ]; +Get[ "Wolfram`Chatbook`Tools`DefaultToolDefinitions`WolframLanguageEvaluator`" ]; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) @@ -1256,11 +30,5 @@ $defaultChatTools0 = Map[ <| KeyTake[ $defaultChatTools0, $defaultToolOrder ], $defaultChatTools0 |> ]; -addToMXInitialization[ - $toolConfiguration; -]; - -(* :!CodeAnalysis::EndBlock:: *) - End[ ]; EndPackage[ ]; diff --git a/Source/Chatbook/Tools/Examples.wl b/Source/Chatbook/Tools/Examples.wl new file mode 100644 index 00000000..d0fb3c2a --- /dev/null +++ b/Source/Chatbook/Tools/Examples.wl @@ -0,0 +1,380 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`Tools`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Configuration*) + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Definitions*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*$fullExamples*) +$fullExamples := + With[ { keys = $fullExamplesKeys }, + If[ keys === { }, + "", + needsBasePrompt[ "EndTurnToolCall" ]; + StringJoin[ + "## Full examples\n\n", + "The following are brief conversation examples that demonstrate how you can use tools in a ", + "conversation with the user.\n\n---\n\n", + StringRiffle[ Values @ KeyTake[ $fullExamples0, $fullExamplesKeys ], "\n\n---\n\n" ], + "\n\n---\n" + ] + ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*$fullExamplesKeys*) +$fullExamplesKeys := + With[ { selected = Keys @ $selectedTools }, + Select[ + { + "AstroGraphicsDocumentation", + "FileSystemTree", + "FractionalDerivatives", + "NaturalLanguageInput", + "PlotEvaluate", + "TemporaryDirectory" + }, + ContainsAll[ selected, $exampleDependencies[ #1 ] ] & + ] + ]; + +$exampleDependencies = <| + "AstroGraphicsDocumentation" -> { "DocumentationLookup" }, + "FileSystemTree" -> { "DocumentationSearcher", "DocumentationLookup" }, + "FractionalDerivatives" -> { "DocumentationSearcher", "DocumentationLookup", "WolframLanguageEvaluator" }, + "NaturalLanguageInput" -> { "WolframLanguageEvaluator" }, + "PlotEvaluate" -> { "WolframLanguageEvaluator" }, + "TemporaryDirectory" -> { "DocumentationSearcher", "WolframLanguageEvaluator" } +|>; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*$fullExamples0*) +$fullExamples0 = <| |>; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*Example Templates*) +$chatMessageTemplates = <| |>; +$messageTemplateType = "Basic"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*Basic*) +$chatMessageTemplates[ "Basic" ] = <| |>; +$chatMessageTemplates[ "Basic", "User" ] = "User: %%1%%"; +$chatMessageTemplates[ "Basic", "Assistant" ] = "Assistant: %%1%%\n/end"; +$chatMessageTemplates[ "Basic", "System" ] = "System: %%1%%"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*Instruct*) +$chatMessageTemplates[ "Instruct" ] = <| |>; +$chatMessageTemplates[ "Instruct", "User" ] = "[INST]%%1%%[/INST]"; +$chatMessageTemplates[ "Instruct", "Assistant" ] = "%%1%%\n/end"; +$chatMessageTemplates[ "Instruct", "System" ] = "[INST]%%1%%[/INST]"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*Zephyr*) +$chatMessageTemplates[ "Zephyr" ] = <| |>; +$chatMessageTemplates[ "Zephyr", "User" ] = "<|user|>\n%%1%%"; +$chatMessageTemplates[ "Zephyr", "Assistant" ] = "<|assistant|>\n%%1%%\n/end"; +$chatMessageTemplates[ "Zephyr", "System" ] = "<|system|>\n%%1%%"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*Phi*) +$chatMessageTemplates[ "Phi" ] = <| |>; +$chatMessageTemplates[ "Phi", "User" ] = "<|user|>\n%%1%%<|end|>"; +$chatMessageTemplates[ "Phi", "Assistant" ] = "<|assistant|>\n%%1%%\n/end<|end|>"; +$chatMessageTemplates[ "Phi", "System" ] = "<|user|>\n%%1%%<|end|>"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*Boxed*) +$chatMessageTemplates[ "Boxed" ] = <| |>; +$chatMessageTemplates[ "Boxed", "User" ] = "[user]\n%%1%%"; +$chatMessageTemplates[ "Boxed", "Assistant" ] = "[assistant]\n%%1%%\n/end"; +$chatMessageTemplates[ "Boxed", "System" ] = "[system]\n%%1%%"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*ChatML*) +$chatMessageTemplates[ "ChatML" ] = <| |>; +$chatMessageTemplates[ "ChatML", "User" ] = "<|im_start|>user\n%%1%%<|im_end|>"; +$chatMessageTemplates[ "ChatML", "Assistant" ] = "<|im_start|>assistant\n%%1%%\n/end<|im_end|>"; +$chatMessageTemplates[ "ChatML", "System" ] = "<|im_start|>system\n%%1%%<|im_end|>"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*XML*) +$chatMessageTemplates[ "XML" ] = <| |>; +$chatMessageTemplates[ "XML", "User" ] = "%%1%%"; +$chatMessageTemplates[ "XML", "Assistant" ] = "%%1%%\n/end"; +$chatMessageTemplates[ "XML", "System" ] = "%%1%%"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*DeepSeekCoder*) +(* cSpell: ignore cend *) +$chatMessageTemplates[ "DeepSeekCoder" ] = <| |>; +$chatMessageTemplates[ "DeepSeekCoder", "User" ] = "User: %%1%%"; +$chatMessageTemplates[ "DeepSeekCoder", "Assistant" ] = "Assistant: %%1%%\n/end<\:ff5cend\:2581of\:2581sentence\:ff5c>"; +$chatMessageTemplates[ "DeepSeekCoder", "System" ] = "System: %%1%%"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*Llama*) +$chatMessageTemplates[ "Llama" ] = <| |>; +$chatMessageTemplates[ "Llama", "User" ] = "<|start_header_id|>user<|end_header_id|>\n%%1%%<|eot_id|>"; +$chatMessageTemplates[ "Llama", "Assistant" ] = "<|start_header_id|>assistant<|end_header_id|>\n%%1%%\n/end<|eot_id|>"; +$chatMessageTemplates[ "Llama", "System" ] = "<|start_header_id|>system<|end_header_id|>\n%%1%%<|eot_id|>"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*Gemma*) +$chatMessageTemplates[ "Gemma" ] = <| |>; +$chatMessageTemplates[ "Gemma", "User" ] = "user\n%%1%%"; +$chatMessageTemplates[ "Gemma", "Assistant" ] = "model\n%%1%%\n/end"; +$chatMessageTemplates[ "Gemma", "System" ] = "user\n%%1%%"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*Nemotron*) +(* cSpell: ignore Nemotron *) +$chatMessageTemplates[ "Nemotron" ] = <| |>; +$chatMessageTemplates[ "Nemotron", "User" ] = "User\n%%1%%"; +$chatMessageTemplates[ "Nemotron", "Assistant" ] = "Assistant\n%%1%%\n/end"; +$chatMessageTemplates[ "Nemotron", "System" ] = "System\n%%1%%"; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*messageTemplate*) +messageTemplate // beginDefinition; + +messageTemplate[ id_String ] := Enclose[ + StringTemplate[ + ConfirmBy[ $chatMessageTemplates[ $messageTemplateType, id ], StringQ, "TemplateString" ], + Delimiters -> "%%" + ], + throwInternalFailure +]; + +messageTemplate // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*user*) +user // beginDefinition; +user[ a_List ] := TemplateApply[ messageTemplate[ "User" ], StringRiffle[ TextString /@ Flatten @ a, "\n" ] ]; +user[ a_String ] := user @ { a }; +user // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*assistant*) +assistant // beginDefinition; +assistant[ { a___, "tool"|"Tool" -> { name_, as_ }, b___ } ] := assistant @ { a, toolCall[ name, as ], b }; +assistant[ a_List ] := TemplateApply[ messageTemplate[ "Assistant" ], StringRiffle[ TextString /@ Flatten @ a, "\n" ] ]; +assistant[ a_String ] := assistant @ { a }; +assistant // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*system*) +system // beginDefinition; +system[ a_List ] := TemplateApply[ messageTemplate[ "System" ], StringRiffle[ TextString /@ Flatten @ a, "\n" ] ]; +system[ a_String ] := system @ { a }; +system // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*toolCall*) +toolCall // beginDefinition; +toolCall[ args__ ] := formatToolCallExample @ args; +toolCall // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsubsection::Closed:: *) +(*toolExample*) +toolExample // beginDefinition; +toolExample[ { rules: (_Rule|_String)... } ] := StringRiffle[ toolExample0 /@ { rules }, "\n\n" ]; +toolExample[ rules: (_Rule|_String)... ] := toolExample @ { rules }; +toolExample // endDefinition; + +toolExample0 // beginDefinition; +toolExample0[ "user"|"User" -> message_ ] := user @ message; +toolExample0[ "assistant"|"Assistant" -> message_ ] := assistant @ message; +toolExample0[ "system"|"System" -> message_ ] := system @ message; +toolExample0[ prompt_String ] := prompt; +toolExample0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Full Example Specifications*) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*AstroGraphicsDocumentation*) +$fullExamples0[ "AstroGraphicsDocumentation" ] := toolExample[ + "user" -> "How do I use AstroGraphics?", + "assistant" -> { + "Let me check the documentation for you. One moment...", + "tool" -> { "DocumentationLookup", <| "names" -> "AstroGraphics" |> } + }, + "system" -> { + "Usage", + "AstroGraphics[primitives, options] represents a two-dimensional view of space and the celestial sphere.", + "", + "Basic Examples", + "..." + }, + "assistant" -> "To use [AstroGraphics](paclet:ref/AstroGraphics), you need to..." +]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*NaturalLanguageInput*) +$fullExamples0[ "NaturalLanguageInput" ] := toolExample[ + "user" -> "How far away is NYC from Boston?", + "assistant" -> { + "tool" -> { + "WolframLanguageEvaluator", + <| "code" -> "GeoDistance[\[FreeformPrompt][\"Boston, MA\"], \[FreeformPrompt][\"New York City\"]]" |> + } + }, + "system" -> "Quantity[164.41, \"Miles\"]", + "assistant" -> "It's 164.41 miles from Boston to New York City.", + "user" -> "If I made the trip in 3h 17m, how fast was I going?", + "assistant" -> { + "tool" -> { + "WolframLanguageEvaluator", + <| "code" -> "\[FreeformPrompt][\"164.41 Miles\"] / \[FreeformPrompt][\"3h 17m\"]" |> + } + }, + "system" -> "Quantity[50.071, \"Miles\" / \"Hours\"]", + "assistant" -> "You were going 50.071 miles per hour.", + "user" -> "What time would I arrive if I left right now?", + "assistant" -> { + "tool" -> { + "WolframLanguageEvaluator", + <| "code" -> "\[FreeformPrompt][\"3h 17m from now\"]" |> + } + } +]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*FileSystemTree*) +$fullExamples0[ "FileSystemTree" ] := toolExample[ + "user" -> "What's the best way to generate a tree of files in a given directory?", + "assistant" -> { + "tool" -> { "DocumentationSearcher", <| "query" -> "tree of files" |> } + }, + "system" -> { + "* FileSystemTree - (score: 9.9) FileSystemTree[root] gives a tree whose keys are ...", + "* Tree Drawing - (score: 3.0) ..." + }, + "assistant" -> { + "tool" -> { "DocumentationLookup", <| "names" -> "FileSystemTree" |> } + }, + "..." +]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*FractionalDerivatives*) +$fullExamples0[ "FractionalDerivatives" ] := toolExample[ + "user" -> "Calculate the half-order fractional derivative of x^n with respect to x.", + "assistant" -> { + "tool" -> { "DocumentationSearcher", <| "query" -> "fractional derivatives" |> } + }, + "system" -> { + "* FractionalD - (score: 9.5) FractionalD[f, {x, a}] gives ...", + "* NFractionalD - (score: 9.2) ..." + }, + "assistant" -> { + "tool" -> { "DocumentationLookup", <| "names" -> "FractionalD" |> } + }, + "system" -> { + "Usage", + "FractionalD[f, {x, a}] gives the Riemann-Liouville fractional derivative D_x^a f(x) of order a of the function f.", + "", + "Basic Examples", + "..." + }, + "assistant" -> { + "tool" -> { + "WolframLanguageEvaluator", + <| "code" -> "FractionalD[x^n, {x, 1/2}]" |> + } + }, + "system" -> { + "Out[n]= Piecewise[...]\n", + "![Formatted Result](expression://content-{id})" + }, + "assistant" -> { + "The half-order fractional derivative of $$x^n$$ with respect to $$x$$ is given by:", + "![Fractional Derivative](expression://content-{id})" + } +]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*PlotEvaluate*) +$fullExamples0[ "PlotEvaluate" ] := toolExample[ + "user" -> "Plot sin(x) from -5 to 5", + "assistant" -> { + "tool" -> { + "WolframLanguageEvaluator", + <| "code" -> "Plot[Sin[x], {x, -5, 5}, AxesLabel -> {\"x\", \"sin(x)\"}" |> + } + }, + "system" -> "Out[n]= ![image](attachment://content-{id})", + "assistant" -> { + "Here's the plot of $$\\sin{x}$$ from -5 to 5:", + "![Plot](attachment://content-{id})" + } +]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*TemporaryDirectory*) +$fullExamples0[ "TemporaryDirectory" ] := toolExample[ + "user" -> "Where is the temporary directory located?", + "assistant" -> { + "tool" -> { "DocumentationSearcher", <| "query" -> "location of temporary directory" |> } + }, + "system" -> { + "* $TemporaryDirectory - (score: 9.6) $TemporaryDirectory gives the main system directory for temporary files.", + "* CreateDirectory - (score: 8.5) CreateDirectory[\"dir\"] creates ..." + }, + "assistant" -> { + "tool" -> { "WolframLanguageEvaluator", <| "code" -> "$TemporaryDirectory" |> } + }, + "system" -> "Out[n]= \"C:\\Users\\UserName\\AppData\\Local\\Temp\"", + "assistant" -> "The temporary directory is located at C:\\Users\\UserName\\AppData\\Local\\Temp." +]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Tools/ExpressionURIs.wl b/Source/Chatbook/Tools/ExpressionURIs.wl new file mode 100644 index 00000000..3ce3c381 --- /dev/null +++ b/Source/Chatbook/Tools/ExpressionURIs.wl @@ -0,0 +1,352 @@ +(* ::Section::Closed:: *) +(*Package Header*) +BeginPackage[ "Wolfram`Chatbook`Tools`" ]; +Begin[ "`Private`" ]; + +Needs[ "Wolfram`Chatbook`" ]; +Needs[ "Wolfram`Chatbook`Common`" ]; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Configuration*) +$expressionSchemes = { "attachment", "audio", "dynamic", "expression", "video" }; +$$expressionScheme = Alternatives @@ $expressionSchemes; + +$$expressionURIKey := "content-" ~~ Repeated[ LetterCharacter|DigitCharacter, $tinyHashLength ]; + +$attachmentTypes = { "Expressions", "ToolCalls" }; +$$attachmentProperty = Alternatives @@ $attachmentTypes; + +$attachments = <| |>; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*FormatToolResponse*) +FormatToolResponse // ClearAll; +FormatToolResponse[ response_ ] := makeToolResponseString @ response; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*makeToolResponseString*) +makeToolResponseString // beginDefinition; + +makeToolResponseString[ failure_Failure ] := makeFailureString @ failure; + +makeToolResponseString[ expr_? simpleResultQ ] := + With[ { string = fixLineEndings @ TextString @ expr }, + If[ StringLength @ string < $toolResultStringLength, + If[ StringContainsQ[ string, "\n" ], "\n" <> string, string ], + StringJoin[ + "\n", + fixLineEndings @ ToString[ + Unevaluated @ Short[ expr, Floor[ $toolResultStringLength / 100 ] ], + OutputForm, + PageWidth -> 100 + ], + "\n\n\n", + makeExpressionURI[ "expression", "Formatted Result", Unevaluated @ expr ] + ] + ] + ]; + +makeToolResponseString[ expr_ ] := makeExpressionURI @ expr; + +makeToolResponseString // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*MakeExpressionURI*) +MakeExpressionURI // ClearAll; +MakeExpressionURI[ args: Repeated[ _, { 1, 3 } ] ] := makeExpressionURI @ args; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*makeExpressionURI*) +makeExpressionURI // beginDefinition; + +makeExpressionURI[ expr_ ] := + makeExpressionURI[ Automatic, Unevaluated @ expr ]; + +makeExpressionURI[ label_, expr_ ] := + makeExpressionURI[ Automatic, label, Unevaluated @ expr ]; + +makeExpressionURI[ Automatic, label_, expr_ ] := + makeExpressionURI[ expressionURIScheme @ expr, label, Unevaluated @ expr ]; + +makeExpressionURI[ scheme_, Automatic, expr_ ] := + makeExpressionURI[ scheme, expressionURILabel @ expr, Unevaluated @ expr ]; + +makeExpressionURI[ scheme_, label_, expr_ ] := + With[ { id = "content-" <> tinyHash @ Unevaluated @ expr }, + $attachments[ id ] = HoldComplete @ expr; + "![" <> TextString @ label <> "](" <> TextString @ scheme <> "://" <> id <> ")" + ]; + +makeExpressionURI // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*expressionURIScheme*) +expressionURIScheme // beginDefinition; +expressionURIScheme // Attributes = { HoldAllComplete }; +expressionURIScheme[ _Video ] := (needsURIPrompt[ "SpecialURIVideo" ]; "video"); +expressionURIScheme[ _Audio ] := (needsURIPrompt[ "SpecialURIAudio" ]; "audio"); +expressionURIScheme[ _Manipulate|_DynamicModule|_Dynamic ] := (needsURIPrompt[ "SpecialURIDynamic" ]; "dynamic"); +expressionURIScheme[ gfx_ ] /; graphicsQ @ Unevaluated @ gfx := "attachment"; +expressionURIScheme[ _ ] := "expression"; +expressionURIScheme // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*needsURIPrompt*) +needsURIPrompt // beginDefinition; + +needsURIPrompt[ name_String ] := ( + needsBasePrompt[ name ]; + If[ toolSelectedQ[ "WolframLanguageEvaluator" ], needsBasePrompt[ "SpecialURIImporting" ] ] +); + +needsURIPrompt // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*expressionURILabel*) +expressionURILabel // beginDefinition; +expressionURILabel // Attributes = { HoldAllComplete }; + +(* Audio *) +expressionURILabel[ Audio[ path_String, ___ ] ] := "Audio Player: " <> path; +expressionURILabel[ Audio[ File[ path_String ], ___ ] ] := "Audio Player: " <> path; +expressionURILabel[ _Audio ] := "Embedded Audio Player"; + +(* Video *) +expressionURILabel[ Video[ path_String, ___ ] ] := "Video Player: " <> path; +expressionURILabel[ Video[ File[ path_String ], ___ ] ] := "Video Player: " <> path; +expressionURILabel[ _Video ] := "Embedded Video Player"; + +(* Dynamic *) +expressionURILabel[ _Manipulate ] := "Embedded Interactive Content"; + +(* Graphics *) +expressionURILabel[ _Graph|_Graph3D ] := "Graph"; +expressionURILabel[ _Tree ] := "Tree"; +expressionURILabel[ gfx_ ] /; graphicsQ @ Unevaluated @ gfx := "Image"; + +(* Data *) +expressionURILabel[ _List|_Association ] := "Data"; + +(* Other *) +expressionURILabel[ _ ] := "Content"; + +expressionURILabel // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*GetExpressionURIs*) +GetExpressionURIs // ClearAll; +GetExpressionURIs // Options = { Tooltip -> Automatic }; + +GetExpressionURIs[ str_, opts: OptionsPattern[ ] ] := + GetExpressionURIs[ str, ## &, opts ]; + +GetExpressionURIs[ str_String, wrapper_, opts: OptionsPattern[ ] ] := + catchMine @ Block[ { $uriTooltip = OptionValue @ Tooltip }, + StringSplit[ + str, + link: Shortest[ "![" ~~ __ ~~ "](" ~~ __ ~~ ")" ] /; expressionURIQ @ link :> + catchAlways @ GetExpressionURI[ link, wrapper ] + ] + ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*expressionURIQ*) +expressionURIQ // beginDefinition; +expressionURIQ[ str_String ] := expressionURIKeyQ @ expressionURIKey @ str; +expressionURIQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*expressionURIKeyQ*) +expressionURIKeyQ // beginDefinition; +expressionURIKeyQ[ key_String ] := StringMatchQ[ key, $$expressionURIKey ]; +expressionURIKeyQ[ _ ] := False; +expressionURIKeyQ // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*expressionURIKey*) +expressionURIKey // beginDefinition; + +expressionURIKey[ str_String ] := expressionURIKey[ str ] = FixedPoint[ + StringDelete @ { + StartOfString ~~ "![" ~~ __ ~~ "](", + StartOfString ~~ LetterCharacter.. ~~ "://", + ")"~~EndOfString + }, + str +]; + +expressionURIKey // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*GetExpressionURI*) +GetExpressionURI // beginDefinition; +GetExpressionURI // Options = { Tooltip -> Automatic }; + +GetExpressionURI[ uri_, opts: OptionsPattern[ ] ] := + catchMine @ GetExpressionURI[ uri, ## &, opts ]; + +GetExpressionURI[ URL[ uri_ ], wrapper_, opts: OptionsPattern[ ] ] := + catchMine @ GetExpressionURI[ uri, wrapper, opts ]; + +GetExpressionURI[ uri_String, wrapper_, opts: OptionsPattern[ ] ] := catchMine @ Enclose[ + Module[ { held }, + held = ConfirmMatch[ getExpressionURI[ uri, OptionValue[ Tooltip ] ], _HoldComplete, "GetExpressionURI" ]; + wrapper @@ held + ], + throwInternalFailure +]; + +GetExpressionURI[ All, wrapper_, opts: OptionsPattern[ ] ] := catchMine @ Enclose[ + Module[ { attachments }, + attachments = ConfirmBy[ $attachments, AssociationQ, "Attachments" ]; + ConfirmAssert[ AllTrue[ attachments, MatchQ[ _HoldComplete ] ], "HeldAttachments" ]; + Replace[ attachments, HoldComplete[ a___ ] :> RuleCondition @ wrapper @ a, { 1 } ] + ], + throwInternalFailure +]; + +GetExpressionURI // endExportedDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getExpressionURI*) +getExpressionURI // beginDefinition; +getExpressionURI[ uri_, tooltip_ ] := Block[ { $tooltip = tooltip }, getExpressionURI0 @ uri ]; +getExpressionURI // endDefinition; + + +getExpressionURI0 // beginDefinition; + +getExpressionURI0[ str_String ] := + Module[ { split }, + split = First[ StringSplit[ str, "![" ~~ alt__ ~~ "](" ~~ url__ ~~ ")" :> { alt, url } ], $Failed ]; + getExpressionURI0 @@ split /; MatchQ[ split, { _String, _String } ] + ]; + +getExpressionURI0[ uri_String ] := getExpressionURI0[ None, uri ]; + +getExpressionURI0[ tooltip_, uri_String? expressionURIKeyQ ] := + getExpressionURI0[ tooltip, uri, <| "Domain" -> uri |> ]; + +getExpressionURI0[ tooltip_, uri_String ] := getExpressionURI0[ tooltip, uri, URLParse @ uri ]; + +getExpressionURI0[ tooltip_, uri_, as: KeyValuePattern[ "Domain" -> key_? expressionURIKeyQ ] ] := Enclose[ + ConfirmMatch[ displayAttachment[ uri, tooltip, key ], _HoldComplete, "DisplayAttachment" ], + throwInternalFailure +]; + +getExpressionURI0[ tooltip_, uri_String, as_ ] := + throwFailure[ "InvalidExpressionURI", uri ]; + +getExpressionURI0 // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*displayAttachment*) +displayAttachment // beginDefinition; + +displayAttachment[ uri_, None, key_ ] := + getAttachment[ uri, key ]; + +displayAttachment[ uri_, tooltip_String, key_ ] := Enclose[ + Replace[ + ConfirmMatch[ getAttachment[ uri, key ], _HoldComplete, "GetAttachment" ], + HoldComplete[ expr_ ] :> + If[ TrueQ @ $tooltip, + HoldComplete @ Tooltip[ expr, tooltip ], + HoldComplete @ expr + ] + ], + throwInternalFailure +]; + +displayAttachment // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getAttachment*) +getAttachment // beginDefinition; + +getAttachment[ uri_String, key_String ] := + Lookup[ $attachments, key, throwFailure[ "URIUnavailable", uri ] ]; + +getAttachment // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*GetAttachments*) +GetAttachments // beginDefinition; + +GetAttachments[ ] := + GetAttachments[ None, All ]; + +GetAttachments[ prop: $$attachmentProperty ] := + GetAttachments[ None, prop ]; + +GetAttachments[ messages_ ] := + catchMine @ GetAttachments[ messages, All ]; + +GetAttachments[ messages: $$chatMessages|None, prop: $$attachmentProperty|All ] := + catchMine @ getAttachments[ messages, prop ]; + +GetAttachments // endExportedDefinition; + +(* TODO: this should identify expression and tool call keys from earlier sessions and give Missing[...] for those *) + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*getAttachments*) +getAttachments // beginDefinition; + +(* cSpell: ignore ENDRESULT *) +getAttachments[ messages_List, All ] := Enclose[ + Catch @ Module[ { allExprKeys, allToolKeys, string, exprKeys, toolKeys, exprs, toolCalls }, + allExprKeys = ConfirmMatch[ Keys @ $attachments, { ___String }, "ExpressionKeys" ]; + allToolKeys = ConfirmMatch[ Keys @ $toolEvaluationResults, { ___String }, "ToolKeys" ]; + string = ConfirmBy[ messagesToString[ messages, "MessageTemplate" -> None ], StringQ, "String" ]; + exprKeys = DeleteDuplicates @ StringCases[ string, allExprKeys ]; + toolKeys = DeleteDuplicates @ StringCases[ string, "ENDRESULT("~~key:allToolKeys~~")" :> key ]; + exprs = ConfirmBy[ KeyTake[ $attachments, exprKeys ], AssociationQ, "Expressions" ]; + toolCalls = ConfirmBy[ KeyTake[ $toolEvaluationResults, toolKeys ], AssociationQ, "ToolCalls" ]; + <| "Expressions" -> exprs, "ToolCalls" -> toolCalls |> + ], + throwInternalFailure +]; + +getAttachments[ None, All ] := Enclose[ + <| + "Expressions" -> ConfirmBy[ $attachments, AssociationQ, "Expressions" ], + "ToolCalls" -> ConfirmBy[ $toolEvaluationResults, AssociationQ, "ToolCalls" ] + |>, + throwInternalFailure +]; + +getAttachments[ messages_, prop: $$attachmentProperty ] := Enclose[ + ConfirmBy[ getAttachments[ messages, All ][ prop ], AssociationQ, "Result" ], + throwInternalFailure +]; + +getAttachments // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Package Footer*) +addToMXInitialization[ + Null +]; + +End[ ]; +EndPackage[ ]; diff --git a/Source/Chatbook/Tools/ToolOptions.wl b/Source/Chatbook/Tools/ToolOptions.wl index 0dcd0691..eafdd366 100644 --- a/Source/Chatbook/Tools/ToolOptions.wl +++ b/Source/Chatbook/Tools/ToolOptions.wl @@ -10,7 +10,6 @@ Needs[ "Wolfram`Chatbook`" ]; Needs[ "Wolfram`Chatbook`Common`" ]; Needs[ "Wolfram`Chatbook`Personas`" ]; Needs[ "Wolfram`Chatbook`ResourceInstaller`" ]; -Needs[ "Wolfram`Chatbook`Serialization`" ]; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) diff --git a/Source/Chatbook/Tools/Tools.wl b/Source/Chatbook/Tools/Tools.wl index aee7251a..6246c9ea 100644 --- a/Source/Chatbook/Tools/Tools.wl +++ b/Source/Chatbook/Tools/Tools.wl @@ -6,11 +6,11 @@ Begin[ "`Private`" ]; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Load Subcontexts*) -Get[ "Wolfram`Chatbook`Tools`Common`" ]; -Get[ "Wolfram`Chatbook`Tools`ToolOptions`" ]; -Get[ "Wolfram`Chatbook`Tools`DefaultTools`" ]; -Get[ "Wolfram`Chatbook`Tools`ChatPreferences`" ]; -Get[ "Wolfram`Chatbook`Tools`WolframAlpha`" ]; +Get[ "Wolfram`Chatbook`Tools`Common`" ]; +Get[ "Wolfram`Chatbook`Tools`DefaultTools`" ]; +Get[ "Wolfram`Chatbook`Tools`Examples`" ]; +Get[ "Wolfram`Chatbook`Tools`ExpressionURIs`" ]; +Get[ "Wolfram`Chatbook`Tools`ToolOptions`" ]; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) diff --git a/Source/Chatbook/UI.wl b/Source/Chatbook/UI.wl index a48c739a..cbed585e 100644 --- a/Source/Chatbook/UI.wl +++ b/Source/Chatbook/UI.wl @@ -32,7 +32,6 @@ Needs[ "Wolfram`Chatbook`ErrorUtils`" ]; Needs[ "Wolfram`Chatbook`Menus`" ]; Needs[ "Wolfram`Chatbook`Personas`" ]; Needs[ "Wolfram`Chatbook`PreferencesUtils`" ]; -Needs[ "Wolfram`Chatbook`Serialization`" ]; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) @@ -111,20 +110,15 @@ SetFallthroughError[createChatNotEnabledToolbar] createChatNotEnabledToolbar[ nbObj_NotebookObject, menuCell_CellObject -] := Module[{ - button -}, - button = EventHandler[ +] := + EventHandler[ makeEnableAIChatFeaturesLabel[False], "MouseClicked" :> ( tryMakeChatEnabledNotebook[nbObj, menuCell] ), (* Needed so that we can open a ChoiceDialog if required. *) Method -> "Queued" - ]; - - Pane[button, {$chatMenuWidth, Automatic}] -] + ] (*====================================*) @@ -232,19 +226,32 @@ makeAutomaticResultAnalysisCheckbox[ }, labeledCheckbox[ Dynamic[ autoAssistQ @ target, setterFunction ], - Row @ { - tr[ "UIAutomaticAnalysisLabel" ], - Spacer[ 3 ], - Tooltip[ chatbookIcon[ "InformationTooltip", False ], tr[ "UIAutomaticAnalysisTooltip" ] ] - } + (* We can only get the tooltip to glue itself to the text by first literalizing the text resource as a string before typesetting to RowBox. *) + Dynamic @ Row[ + { + FrontEndResource[ "ChatbookStrings", "UIAutomaticAnalysisLabel" ], + Spacer[ 3 ], + Tooltip[ chatbookIcon[ "InformationTooltip", False ], FrontEndResource[ "ChatbookStrings", "UIAutomaticAnalysisTooltip" ] ] + }, + "\[NoBreak]", StripOnInput -> True] ] ] (*====================================*) +SetFallthroughError[menuItemLineWrap] + +menuItemLineWrap[label_, width_ : 50] := +Pane[ + label, + $chatMenuWidth - width, + BaselinePosition -> Baseline, BaseStyle -> { LineBreakWithin -> Automatic, LineIndent -> -0.05, LinebreakAdjustments -> { 1, 10, 1, 0, 1 } } ] + +(*====================================*) + SetFallthroughError[labeledCheckbox] -labeledCheckbox[value_, label_, enabled_ : Automatic] := Style[ +labeledCheckbox[value_, label_, enabled_ : Automatic] := Row[ { Checkbox[ @@ -253,7 +260,7 @@ labeledCheckbox[value_, label_, enabled_ : Automatic] := Style[ Enabled -> enabled ], Spacer[3], - label + menuItemLineWrap @ label }, BaseStyle -> { "Text", @@ -262,9 +269,7 @@ labeledCheckbox[value_, label_, enabled_ : Automatic] := Style[ Preferences.nb *) CheckboxBoxOptions -> { ImageMargins -> 0 } } - ], - LineBreakWithin -> False -] + ] (*====================================*) @@ -280,7 +285,7 @@ makeToolCallFrequencySlider[ obj_ ] := ] ] ], - Style[ tr[ "UIAdvancedChooseAutomatically" ], "ChatMenuLabel" ] + Style[ menuItemLineWrap @ tr[ "UIAdvancedChooseAutomatically" ], "ChatMenuLabel" ] ]; slider = Pane[ Grid[ @@ -720,7 +725,7 @@ makeChatActionMenuContent[ } }, { - tr[ "UIAdvancedToolCallFrequency" ], + menuItemLineWrap @ tr[ "UIAdvancedToolCallFrequency" ], { None, makeToolCallFrequencySlider[toolValue], @@ -761,7 +766,7 @@ makeChatActionMenuContent[ }, { alignedMenuIcon[persona, personaValue, icon], - personaDisplayName[persona, personaSettings], + menuItemLineWrap @ personaDisplayName[persona, personaSettings], Hold[callback["Persona", persona];updateDynamics[{"ChatBlock"}]] } ], @@ -780,8 +785,8 @@ makeChatActionMenuContent[ }] }], Delimiter, - {alignedMenuIcon[getIcon["PersonaOther"]], tr[ "UIAddAndManagePersonas" ], "PersonaManage"}, - {alignedMenuIcon[getIcon["ToolManagerRepository"]], tr[ "UIAddAndManageTools" ], "ToolManage"}, + {alignedMenuIcon[getIcon["PersonaOther"]], menuItemLineWrap @ tr[ "UIAddAndManagePersonas" ], "PersonaManage"}, + {alignedMenuIcon[getIcon["ToolManagerRepository"]], menuItemLineWrap @ tr[ "UIAddAndManageTools" ], "ToolManage"}, Delimiter, <| "Label" -> tr[ "UIModels" ], diff --git a/Source/Chatbook/Utils.wl b/Source/Chatbook/Utils.wl index 38a663b8..681e32bb 100644 --- a/Source/Chatbook/Utils.wl +++ b/Source/Chatbook/Utils.wl @@ -11,6 +11,9 @@ Needs[ "Wolfram`Chatbook`Common`" ]; (*Config*) $tinyHashLength = 5; +$messageToStringDelimiter = "\n\n"; +$messageToStringTemplate = StringTemplate[ "`Role`: `Content`" ]; + (* cSpell: ignore deflatten *) (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) @@ -40,6 +43,61 @@ importResourceFunction[ selectByCurrentValue, "SelectByCurrentValue" ]; (* ::Section::Closed:: *) (*Strings*) +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*messagesToString*) +messagesToString // beginDefinition; + +messagesToString // Options = { + "IncludeSystemMessage" -> False, + "IncludeTemporaryMessages" -> False, + "MessageDelimiter" -> $messageToStringDelimiter, + "MessageTemplate" -> $messageToStringTemplate +}; + +messagesToString[ { }, opts: OptionsPattern[ ] ] := + ""; + +messagesToString[ messages0_, opts: OptionsPattern[ ] ] := Enclose[ + Catch @ Module[ { messages, system, temporary, template, delimiter, reverted, strings }, + + messages = ConfirmMatch[ messages0, $$chatMessages, "Messages" ]; + + (* Check if the system messages should be included: *) + system = ConfirmMatch[ OptionValue[ "IncludeSystemMessage" ], True|False, "System" ]; + If[ ! system, messages = Replace[ messages, { KeyValuePattern[ "Role" -> "System" ], m___ } :> { m } ] ]; + If[ messages === { }, Throw[ "" ] ]; + + (* Check if the temporary messages should be included: *) + temporary = ConfirmMatch[ OptionValue[ "IncludeTemporaryMessages" ], True|False, "Temporary" ]; + If[ ! temporary, messages = DeleteCases[ messages, KeyValuePattern[ "Temporary" -> True ] ] ]; + If[ messages === { }, Throw[ "" ] ]; + + template = ConfirmMatch[ OptionValue[ "MessageTemplate" ], _String|_TemplateObject|None, "Template" ]; + delimiter = ConfirmMatch[ OptionValue[ "MessageDelimiter" ], _String, "Delimiter" ]; + + reverted = ConfirmMatch[ + revertMultimodalContent @ messages, + { KeyValuePattern[ "Content" -> _String ].. }, + "Reverted" + ]; + + strings = ConfirmMatch[ + If[ template === None, Lookup[ reverted, "Content" ], TemplateApply[ template, # ] & /@ reverted ], + { __String }, + "Strings" + ]; + + ConfirmBy[ StringRiffle[ strings, delimiter ], StringQ, "Result" ] + ], + throwInternalFailure +]; + +messagesToString[ { messages__ }, assistant_String, opts: OptionsPattern[ ] ] := + messagesToString[ { messages, <| "Role" -> "Assistant", "Content" -> assistant |> }, opts ]; + +messagesToString // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*fixLineEndings*) @@ -91,6 +149,15 @@ makeFailureString[ failure: Failure[ tag_, as_Association ] ] := Enclose[ makeFailureString // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*containsWordsQ*) +containsWordsQ // beginDefinition; +containsWordsQ[ p_ ] := containsWordsQ[ #, p ] &; +containsWordsQ[ m_String, p_List ] := containsWordsQ[ m, StringExpression @@ Riffle[ p, Except[ WordCharacter ]... ] ]; +containsWordsQ[ m_String, p_ ] := StringContainsQ[ m, WordBoundary~~p~~WordBoundary, IgnoreCase -> True ]; +containsWordsQ // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Files*) @@ -152,113 +219,6 @@ fastFileHash[ file_ ] := fastFileHash[ file, ReadByteArray @ file ]; fastFileHash[ file_, bytes_ByteArray ] := Hash @ bytes; fastFileHash // endDefinition; -(* ::**************************************************************************************************************:: *) -(* ::Section::Closed:: *) -(*Graphics*) -$$graphics = HoldPattern @ Alternatives[ - _System`AstroGraphics, - _GeoGraphics, - _Graphics, - _Graphics3D, - _Image, - _Image3D, - _Legended -]; - -$$definitelyNotGraphics = HoldPattern @ Alternatives[ - _Association, - _CloudObject, - _File, - _List, - _String, - _URL, - Null, - True|False -]; - -$$graphicsBoxIgnoredHead = HoldPattern @ Alternatives[ - BoxData, - Cell, - FormBox, - PaneBox, - StyleBox, - TagBox -]; - -$$graphicsBoxIgnoredTemplates = Alternatives[ - "Labeled", - "Legended" -]; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*graphicsQ*) -graphicsQ[ $$graphics ] := True; -graphicsQ[ $$definitelyNotGraphics ] := False; -graphicsQ[ RawBoxes[ boxes_ ] ] := graphicsBoxQ @ Unevaluated @ boxes; -graphicsQ[ g_ ] := MatchQ[ Quiet @ Show @ Unevaluated @ g, $$graphics ]; -graphicsQ[ ___ ] := False; - -(* ::**************************************************************************************************************:: *) -(* ::Subsubsection::Closed:: *) -(*graphicsBoxQ*) -graphicsBoxQ[ _GraphicsBox|_Graphics3DBox ] := True; -graphicsBoxQ[ $$graphicsBoxIgnoredHead[ box_, ___ ] ] := graphicsBoxQ @ Unevaluated @ box; -graphicsBoxQ[ TemplateBox[ { box_, ___ }, $$graphicsBoxIgnoredTemplates, ___ ] ] := graphicsBoxQ @ Unevaluated @ box; -graphicsBoxQ[ RowBox[ boxes_List ] ] := AnyTrue[ boxes, graphicsBoxQ ]; -graphicsBoxQ[ TemplateBox[ boxes_List, "RowDefault", ___ ] ] := AnyTrue[ boxes, graphicsBoxQ ]; -graphicsBoxQ[ GridBox[ boxes_List, ___ ] ] := AnyTrue[ Flatten @ boxes, graphicsBoxQ ]; -graphicsBoxQ[ ___ ] := False; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*validGraphicsQ*) -validGraphicsQ[ g_? graphicsQ ] := getPinkBoxErrors @ Unevaluated @ g === { }; -validGraphicsQ[ ___ ] := False; - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*getPinkBoxErrors*) -getPinkBoxErrors // beginDefinition; -(* TODO: hook this up to evaluator outputs and CellToString to give feedback about pink boxes *) - -getPinkBoxErrors[ { } ] := - { }; - -getPinkBoxErrors[ cells: _CellObject | { __CellObject } ] := - getPinkBoxErrors @ NotebookRead @ cells; - -getPinkBoxErrors[ cells: _Cell | { __Cell } ] := - Module[ { nbo }, - UsingFrontEnd @ WithCleanup[ - nbo = NotebookPut[ Notebook @ Flatten @ { cells }, Visible -> False ], - SelectionMove[ nbo, All, Notebook ]; - MathLink`CallFrontEnd @ FrontEnd`GetErrorsInSelectionPacket @ nbo, - NotebookClose @ nbo - ] - ]; - -getPinkBoxErrors[ data: _TextData | _BoxData | { __BoxData } ] := - getPinkBoxErrors @ Cell @ data; - -getPinkBoxErrors[ exprs_List ] := - getPinkBoxErrors[ Cell @* BoxData /@ MakeBoxes /@ Unevaluated @ exprs ]; - -getPinkBoxErrors[ expr_ ] := - getPinkBoxErrors @ { Cell @ BoxData @ MakeBoxes @ expr }; - -getPinkBoxErrors // endDefinition; - - -(* ::**************************************************************************************************************:: *) -(* ::Subsection::Closed:: *) -(*image2DQ*) -(* Matches against the head in addition to checking ImageQ to avoid passing Image3D when a 2D image is expected: *) -image2DQ // beginDefinition; -image2DQ[ _Image? ImageQ ] := True; -image2DQ[ _ ] := False; -image2DQ // endDefinition; - (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*File Format Utilities*) @@ -419,6 +379,96 @@ tinyHash[ e_ ] := tinyHash[ Unevaluated @ e, $tinyHashLength ]; tinyHash[ e_, n_ ] := StringTake[ IntegerString[ Hash @ Unevaluated @ e, 36 ], -n ]; tinyHash // endDefinition; +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*$ChatTimingData*) +$ChatTimingData := chatTimingData[ ]; + +$ChatTimingData /: Unset @ $ChatTimingData := ($timingLog = Internal`Bag[ ]; Null); + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*chatTimingData*) +chatTimingData // beginDefinition; +chatTimingData[ ] := SortBy[ Internal`BagPart[ $timingLog, All ], Lookup[ "AbsoluteTime" ] ]; (* TODO: format this data *) +chatTimingData // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*LogChatTiming*) +LogChatTiming // beginDefinition; +LogChatTiming // Attributes = { HoldFirst, SequenceHold }; + +LogChatTiming[ tag_String ] := Function[ eval, LogChatTiming[ eval, tag ], HoldAllComplete ]; +LogChatTiming[ sym_Symbol ] := LogChatTiming @ Evaluate @ Capitalize @ SymbolName @ sym; +LogChatTiming[ tags_List ] := LogChatTiming @ Evaluate @ StringRiffle[ tags, ":" ]; +LogChatTiming[ eval: (h_Symbol)[ ___ ] ] := LogChatTiming[ eval, Capitalize @ SymbolName @ h ]; +LogChatTiming[ eval_ ] := LogChatTiming[ eval, "None" ]; + +LogChatTiming[ eval_, tag_String ] := ( + If[ ! NumberQ @ $chatStartTime, $chatStartTime = AbsoluteTime[ ] ]; + If[ ! StringQ @ $chatEvaluationID, $chatEvaluationID = CreateUUID[ ] ]; + If[ MatchQ[ $timings, _Internal`Bag ], + logChatTiming[ eval, tag ], + Block[ { $timings = Internal`Bag[ ] }, + logChatTiming[ eval, tag ] + ] + ] +); + +LogChatTiming // endExportedDefinition; + +$timings = Internal`Bag[ ]; +$timingLog = Internal`Bag[ ]; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*logChatTiming*) +logChatTiming // beginDefinition; +logChatTiming // Attributes = { HoldFirst, SequenceHold }; + +logChatTiming[ eval_, tag_String ] := + Module[ { now, absNow, result, fullTime, innerTimings, usedTime }, + + now = chatTime[ ]; + absNow = AbsoluteTime[ ]; + + Block[ { $timings = Internal`Bag[ ] }, + fullTime = First @ AbsoluteTiming[ result = eval ]; + innerTimings = Internal`BagPart[ $timings, All ]; + ]; + + usedTime = fullTime - Total @ innerTimings; + Internal`StuffBag[ $timings, fullTime ]; + + Internal`StuffBag[ + $timingLog, + <| + "ChatEvaluationCell" -> $ChatEvaluationCell, + "Tag" -> tag, + "UsedTiming" -> usedTime, + "FullTiming" -> fullTime, + "ChatTime" -> now, + "AbsoluteTime" -> absNow, + "UUID" -> $chatEvaluationID + |> + ]; + + result; + result + ]; + +logChatTiming // endDefinition; + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*chatTime*) +chatTime // beginDefinition; +chatTime[ ] := chatTime @ $chatStartTime; +chatTime[ start_Real ] := AbsoluteTime[ ] - start; +chatTime[ _ ] := Missing[ "NotAvailable" ]; +chatTime // endDefinition; + (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) (*Package Footer*) diff --git a/Source/Startup/Begin/BeginStartup.wl b/Source/Startup/Begin/BeginStartup.wl index 8972bce7..ae441473 100644 --- a/Source/Startup/Begin/BeginStartup.wl +++ b/Source/Startup/Begin/BeginStartup.wl @@ -1,3 +1,4 @@ +Wolfram`ChatbookStartupDump`$loadStart = SessionTime[ ]; (* Note: This context name was chosen to avoid being cleared by the Chatbook.wl loading code, which clears names in the Wolfram`Chatbook` context diff --git a/Source/Startup/End/EndStartup.wl b/Source/Startup/End/EndStartup.wl index 4bc4c3e7..ee4d59d8 100644 --- a/Source/Startup/End/EndStartup.wl +++ b/Source/Startup/End/EndStartup.wl @@ -10,4 +10,6 @@ (* Once code assistance is ready, this "14.1.0" can be changed to "14.0.0" to enable it for 14.1 users: *) If[ PacletNewerQ[ Wolfram`ChatbookStartupDump`$versionString, "14.1.0" ], Wolfram`Chatbook`EnableCodeAssistance[ ] -] \ No newline at end of file +] + +Wolfram`ChatbookStartupDump`$loadTime = SessionTime[ ] - Wolfram`ChatbookStartupDump`$loadStart; \ No newline at end of file diff --git a/Tests/Common.wl b/Tests/Common.wl index 27db4ae9..f6f62e26 100644 --- a/Tests/Common.wl +++ b/Tests/Common.wl @@ -6,6 +6,7 @@ BeginPackage[ "Wolfram`ChatbookTests`" ]; (* :!CodeAnalysis::BeginBlock:: *) HoldComplete[ + `$TestDefinitionsLoaded, `$TestNotebook; `CreateChatCell; `CreateChatCells; @@ -29,6 +30,10 @@ If[ ! PacletObjectQ @ PacletObject[ "Wolfram/PacletCICD" ], Needs[ "Wolfram`PacletCICD`" -> "cicd`" ]; +If[ StringQ @ Environment[ "GITHUB_ACTIONS" ], + ServiceConnect[ "OpenAI", Authentication -> <| "APIKey" -> Environment[ "OPENAI_API_KEY" ] |> ] +]; + (* ::**************************************************************************************************************:: *) (* ::Subsection::Closed:: *) (*Definitions*) @@ -68,10 +73,10 @@ If[ ! DirectoryQ @ $pacletDirectory, abort[ "Paclet directory ", $pacletDirector Quiet @ PacletDirectoryUnload @ $sourceDirectory; PacletDataRebuild[ ]; PacletDirectoryLoad @ $pacletDirectory; +Get[ "Wolfram`Chatbook`" ]; If[ ! MemberQ[ $LoadedFiles, FileNameJoin @ { $pacletDirectory, "Source", "Chatbook", "64Bit", "Chatbook.mx" } ], abort[ "Paclet MX file was not loaded!" ] ]; -Needs[ "Wolfram`Chatbook`" ]; (* ::**************************************************************************************************************:: *) (* ::Section::Closed:: *) diff --git a/Tests/CurrentChatSettings.wlt b/Tests/CurrentChatSettings.wlt index 710b279e..f38b7d59 100644 --- a/Tests/CurrentChatSettings.wlt +++ b/Tests/CurrentChatSettings.wlt @@ -2,24 +2,26 @@ (* ::Section::Closed:: *) (*Initialization*) VerificationTest[ - Get @ FileNameJoin @ { DirectoryName[ $TestFileName ], "Common.wl" }, + If[ ! TrueQ @ Wolfram`ChatbookTests`$TestDefinitionsLoaded, + Get @ FileNameJoin @ { DirectoryName[ $TestFileName ], "Common.wl" } + ], Null, SameTest -> MatchQ, - TestID -> "GetDefinitions@@Tests/CurrentChatSettings.wlt:4,1-9,2" + TestID -> "GetDefinitions@@Tests/CurrentChatSettings.wlt:4,1-11,2" ] VerificationTest[ Needs[ "Wolfram`Chatbook`" ], Null, SameTest -> MatchQ, - TestID -> "LoadContext@@Tests/CurrentChatSettings.wlt:11,1-16,2" + TestID -> "LoadContext@@Tests/CurrentChatSettings.wlt:13,1-18,2" ] VerificationTest[ Context @ CurrentChatSettings, "Wolfram`Chatbook`", SameTest -> MatchQ, - TestID -> "CurrentChatSettingsContext@@Tests/CurrentChatSettings.wlt:18,1-23,2" + TestID -> "CurrentChatSettingsContext@@Tests/CurrentChatSettings.wlt:20,1-25,2" ] (* ::**************************************************************************************************************:: *) @@ -29,14 +31,14 @@ VerificationTest[ CurrentChatSettings[ ], KeyValuePattern[ (Rule|RuleDelayed)[ "Model", _ ] ], SameTest -> MatchQ, - TestID -> "CurrentChatSettings@@Tests/CurrentChatSettings.wlt:28,1-33,2" + TestID -> "CurrentChatSettings@@Tests/CurrentChatSettings.wlt:30,1-35,2" ] VerificationTest[ CurrentChatSettings[ "Model" ], KeyValuePattern @ { "Service" -> _String, "Name" -> _String } | _String | Automatic, SameTest -> MatchQ, - TestID -> "CurrentChatSettings@@Tests/CurrentChatSettings.wlt:35,1-40,2" + TestID -> "CurrentChatSettings@@Tests/CurrentChatSettings.wlt:37,1-42,2" ] (* ::**************************************************************************************************************:: *) @@ -46,14 +48,14 @@ VerificationTest[ UsingFrontEnd @ CurrentChatSettings[ $FrontEnd, "Model" ], KeyValuePattern @ { "Service" -> _String, "Name" -> _String } | _String | Automatic, SameTest -> MatchQ, - TestID -> "CurrentChatSettings@@Tests/CurrentChatSettings.wlt:45,1-50,2" + TestID -> "CurrentChatSettings@@Tests/CurrentChatSettings.wlt:47,1-52,2" ] VerificationTest[ UsingFrontEnd @ CurrentChatSettings[ $FrontEndSession, "Model" ], KeyValuePattern @ { "Service" -> _String, "Name" -> _String } | _String | Automatic, SameTest -> MatchQ, - TestID -> "CurrentChatSettings@@Tests/CurrentChatSettings.wlt:52,1-57,2" + TestID -> "CurrentChatSettings@@Tests/CurrentChatSettings.wlt:54,1-59,2" ] (* ::**************************************************************************************************************:: *) @@ -66,7 +68,7 @@ VerificationTest[ ], "MyModelName", SameTest -> MatchQ, - TestID -> "CurrentChatSettings-Notebooks@@Tests/CurrentChatSettings.wlt:62,1-70,2" + TestID -> "CurrentChatSettings-Notebooks@@Tests/CurrentChatSettings.wlt:64,1-72,2" ] (* ::**************************************************************************************************************:: *) @@ -89,7 +91,7 @@ VerificationTest[ "BlockModel" }, SameTest -> MatchQ, - TestID -> "CurrentChatSettings-ChatBlocks@@Tests/CurrentChatSettings.wlt:75,1-93,2" + TestID -> "CurrentChatSettings-ChatBlocks@@Tests/CurrentChatSettings.wlt:77,1-95,2" ] VerificationTest[ @@ -106,7 +108,7 @@ VerificationTest[ ], { "NotebookModel", "BlockModel", "BlockModel" }, SameTest -> MatchQ, - TestID -> "CurrentChatSettings-ChatBlocks@@Tests/CurrentChatSettings.wlt:95,1-110,2" + TestID -> "CurrentChatSettings-ChatBlocks@@Tests/CurrentChatSettings.wlt:97,1-112,2" ] (* ::**************************************************************************************************************:: *) @@ -129,7 +131,7 @@ VerificationTest[ ], Except[ _? FailureQ ], SameTest -> MatchQ, - TestID -> "CurrentChatSettings-Regression#426@@Tests/CurrentChatSettings.wlt:119,1-133,2" + TestID -> "CurrentChatSettings-Regression#426@@Tests/CurrentChatSettings.wlt:121,1-135,2" ] (* ::**************************************************************************************************************:: *) @@ -142,5 +144,5 @@ VerificationTest[ ], Except[ _? FailureQ ], SameTest -> MatchQ, - TestID -> "CurrentChatSettings-Regression#592@@Tests/CurrentChatSettings.wlt:138,1-146,2" + TestID -> "CurrentChatSettings-Regression#592@@Tests/CurrentChatSettings.wlt:140,1-148,2" ] \ No newline at end of file diff --git a/Tests/RelatedDocumentation.wlt b/Tests/RelatedDocumentation.wlt new file mode 100644 index 00000000..0d2c67be --- /dev/null +++ b/Tests/RelatedDocumentation.wlt @@ -0,0 +1,160 @@ +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*Initialization*) +VerificationTest[ + If[ ! TrueQ @ Wolfram`ChatbookTests`$TestDefinitionsLoaded, + Get @ FileNameJoin @ { DirectoryName[ $TestFileName ], "Common.wl" } + ], + Null, + SameTest -> MatchQ, + TestID -> "GetDefinitions@@Tests/RelatedDocumentation.wlt:4,1-11,2" +] + +VerificationTest[ + Needs[ "Wolfram`Chatbook`" ], + Null, + SameTest -> MatchQ, + TestID -> "LoadContext@@Tests/RelatedDocumentation.wlt:13,1-18,2" +] + +VerificationTest[ + Context @ RelatedDocumentation, + "Wolfram`Chatbook`", + SameTest -> MatchQ, + TestID -> "RelatedDocumentationContext@@Tests/RelatedDocumentation.wlt:20,1-25,2" +] + +(* ::**************************************************************************************************************:: *) +(* ::Section::Closed:: *) +(*RelatedDocumentation*) +VerificationTest[ + uris = RelatedDocumentation[ "What's the biggest pokemon?" ], + { __String }, + SameTest -> MatchQ, + TestID -> "RelatedDocumentation-URIs@@Tests/RelatedDocumentation.wlt:30,1-35,2" +] + +(* cSpell: ignore textcontent *) +VerificationTest[ + Length @ Select[ + uris, + StringStartsQ @ StringExpression[ + "paclet:ref/", + "interpreter"|"entity"|"textcontent", + "/", + "Pokemon"|"ComputedPokemon", + "#" + ] + ], + _Integer? (GreaterThan[ 5 ]), + SameTest -> MatchQ, + TestID -> "RelatedDocumentation-URIs-Count@@Tests/RelatedDocumentation.wlt:38,1-52,2" +] + +VerificationTest[ + snippets = RelatedDocumentation[ "What's the biggest pokemon?", "Snippets" ], + { __String }, + SameTest -> MatchQ, + TestID -> "RelatedDocumentation-Snippets@@Tests/RelatedDocumentation.wlt:54,1-59,2" +] + +VerificationTest[ + Total @ StringCount[ snippets, "Entity[\"Pokemon\"," ], + _Integer? (GreaterThan[ 5 ]), + SameTest -> MatchQ, + TestID -> "RelatedDocumentation-Snippets-Count@@Tests/RelatedDocumentation.wlt:61,1-66,2" +] + +VerificationTest[ + uris = RelatedDocumentation[ "What's the biggest pokemon?", Automatic, 3 ], + { _String, _String, _String }, + SameTest -> MatchQ, + TestID -> "RelatedDocumentation-URIs-Count@@Tests/RelatedDocumentation.wlt:68,1-73,2" +] + +VerificationTest[ + AllTrue[ uris, StringStartsQ[ "paclet:ref/" ] ], + True, + SameTest -> MatchQ, + TestID -> "RelatedDocumentation-URIs-Match@@Tests/RelatedDocumentation.wlt:75,1-80,2" +] + +VerificationTest[ + RelatedDocumentation[ "What's the biggest pokemon?", "Snippets", 3 ], + { _String, _String, _String }, + SameTest -> MatchQ, + TestID -> "RelatedDocumentation-Snippets-Count@@Tests/RelatedDocumentation.wlt:82,1-87,2" +] + +(* ::**************************************************************************************************************:: *) +(* ::Subsection::Closed:: *) +(*Prompt*) +VerificationTest[ + prompt = RelatedDocumentation[ + "What's the 123456789th prime?", + "Prompt", + "FilterResults" -> False, + "MaxItems" -> 20 + ], + _String, + SameTest -> MatchQ, + TestID -> "RelatedDocumentation-Prompt@@Tests/RelatedDocumentation.wlt:92,1-102,2" +] + +VerificationTest[ + StringCount[ prompt, "paclet:ref/Prime#" ], + _Integer? (GreaterThan[ 3 ]), + SameTest -> MatchQ, + TestID -> "RelatedDocumentation-Prompt-Count@@Tests/RelatedDocumentation.wlt:104,1-109,2" +] + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*Message Input*) +VerificationTest[ + prompt = RelatedDocumentation[ + { + <| "Role" -> "User" , "Content" -> "What's the 123456789th prime?" |>, + <| "Role" -> "Assistant", "Content" -> "```wl\nPrime[123456789]\n```" |>, + <| "Role" -> "User" , "Content" -> "What about the one after that?" |> + }, + "Prompt", + "FilterResults" -> False, + "MaxItems" -> 20 + ], + _String, + SameTest -> MatchQ, + TestID -> "RelatedDocumentation-Prompt-Messages@@Tests/RelatedDocumentation.wlt:114,1-128,2" +] + +VerificationTest[ + StringCount[ prompt, { "paclet:ref/Prime#", "paclet:ref/NextPrime#" } ], + _Integer? (GreaterEqualThan[ 8 ]), + SameTest -> MatchQ, + TestID -> "RelatedDocumentation-Prompt-Messages-Count@@Tests/RelatedDocumentation.wlt:130,1-135,2" +] + +(* ::**************************************************************************************************************:: *) +(* ::Subsubsection::Closed:: *) +(*Selection Prompt*) +VerificationTest[ + prompt = Block[ + { Wolfram`Chatbook`Common`$contextPrompt = "```wl\nIn[1]:= Prime[123456789]\nOut[1]= 2543568463\n```" }, + RelatedDocumentation[ + { <| "Role" -> "User", "Content" -> "What does this do?" |> }, + "Prompt", + "FilterResults" -> False, + "MaxItems" -> 20 + ] + ], + _String, + SameTest -> MatchQ, + TestID -> "RelatedDocumentation-Prompt-Selection@@Tests/RelatedDocumentation.wlt:140,1-153,2" +] + +VerificationTest[ + StringCount[ prompt, "paclet:ref/Prime#" ], + _Integer? (GreaterEqualThan[ 2 ]), + SameTest -> MatchQ, + TestID -> "RelatedDocumentation-Prompt-Selection-Count@@Tests/RelatedDocumentation.wlt:155,1-160,2" +]