-
-
Save johnowhitaker/0ca99714b500c3d0afe30cd1424ca428 to your computer and use it in GitHub Desktop.
My Dialog
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "id": "c1788d14", | |
| "metadata": { | |
| "input_tokens": 7 | |
| }, | |
| "source": [ | |
| "## Welcome to Solveit" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "1625ea5c", | |
| "metadata": { | |
| "input_tokens": 33 | |
| }, | |
| "source": [ | |
| "This is solveit. Think of it like a chat window between you, a computer, and an AI." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "de36ae8c", | |
| "metadata": { | |
| "input_tokens": 34 | |
| }, | |
| "source": [ | |
| "Type code in the box at the bottom and then click 'Submit' or use the keyboard shortcut: Ctrl-Enter" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "e4a0bcaf", | |
| "metadata": { | |
| "input_tokens": 4, | |
| "output_tokens": 19 | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "2" | |
| ] | |
| }, | |
| "execution_count": 4, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "1+1" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "dd2a0deb", | |
| "metadata": { | |
| "input_tokens": 91 | |
| }, | |
| "source": [ | |
| "It's a REPL - the computer read your code, executed it and gave you back the result. Behind the scenes is something similar to Jupyter - variables persist between messages, so you're in a live, dynamic environment that you can interact with. Let's try making a variable and using it in another cell." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "2aaa049e", | |
| "metadata": { | |
| "input_tokens": 15, | |
| "output_tokens": 24 | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "0.12\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "a = 0.12\n", | |
| "print(a)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "9d2edc3d", | |
| "metadata": { | |
| "input_tokens": 4, | |
| "output_tokens": 22 | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "10.12" | |
| ] | |
| }, | |
| "execution_count": 6, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "a+10" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "e80388b5", | |
| "metadata": { | |
| "input_tokens": 55 | |
| }, | |
| "source": [ | |
| "You don't have to print things to see them - just like Jupyter, the result of evaluating the last line is shown in the output (unless you end it with a `;`)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "0cbb1e95", | |
| "metadata": { | |
| "input_tokens": 60 | |
| }, | |
| "source": [ | |
| "Click the 'Contents' button (📖) or use the shortcut Ctrl-Shift-V - in the 'variables' section you'll see our variable a. Let's see what happens when we change it:" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "ee758830", | |
| "metadata": { | |
| "input_tokens": 6 | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "a += 2" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "851ce698", | |
| "metadata": { | |
| "input_tokens": 49 | |
| }, | |
| "source": [ | |
| "NB: It doesn't live update any more, you have to dismiss and re-show it to see changes to variables. (This may change in the future - TODO))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "a4b7faf6", | |
| "metadata": { | |
| "input_tokens": 90 | |
| }, | |
| "source": [ | |
| "To re-run a code message, you can also click the little 'Run Cell' play icon (TODO: Cell language in tooltip OK?). You can also click anywhere on the top (tooltip: 'Click to Edit') to edit the code, and then use 'Submit' to re-run it." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "899e022f", | |
| "metadata": { | |
| "input_tokens": 85 | |
| }, | |
| "source": [ | |
| "If for some reason you want to edit but NOT run a message, click to edit, make the edit, then use the 'X' button (shortcut: Shift-Escape) to save your changes without re-running. This is more useful for prompts (we'll get to those)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "5e8b36c5", | |
| "metadata": { | |
| "input_tokens": 85 | |
| }, | |
| "source": [ | |
| "Note: If you have some text in the bottom editor, and you click another message to edit it instead, whatever text is in the editor will be cleared. This is another reason you might want Shift-Esc - to dump your in-progress code into a message without running it yet." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "4f84e8a7", | |
| "metadata": { | |
| "input_tokens": 7 | |
| }, | |
| "source": [ | |
| "## Notes and Prompts" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "c62ef4ca", | |
| "metadata": { | |
| "input_tokens": 112 | |
| }, | |
| "source": [ | |
| "We don't just have to write code. At the top left of the editor section are options for solveit's different message types: Code, Note, Prompt and Raw. Switch between them by clicking or by using the keyboard shortcuts: Ctrl-Shift-J for code, Ctrl-Shift-K for note, Ctrl-Shift-L for prompt and Ctrl-Shift-; for raw messages.\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "a68d9d72", | |
| "metadata": { | |
| "input_tokens": 147 | |
| }, | |
| "source": [ | |
| "A note is simple - just some markdown you can use to make notes for yourself, or to dump in useful content. Note messages do have some tricks though. Using markdown headers (`# My heading...`) let's you navigate a dialog quickly in the contents pane, and also allows you to collapse whole sections.Try it - use the arrow toggle thingee to the left of where it says 'Note: 4' above the heading 'Message Types' TODO: tooltips for collapse/expand." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "bb6b3368", | |
| "metadata": { | |
| "input_tokens": 27 | |
| }, | |
| "source": [ | |
| "TODOs:\n", | |
| "- Split messages, what is the number after note, all the buttons..." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "6e88bdd4", | |
| "metadata": { | |
| "input_tokens": 72 | |
| }, | |
| "source": [ | |
| "Prompt messages are messages to solveit's helpful AI. It can see everything* you can see in the dialog up to the message where you ask it something. This makes it great at helping you write code that builds on what you already have:" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "4bf27f61", | |
| "metadata": { | |
| "input_tokens": 40, | |
| "output_tokens": 135, | |
| "solveit_ai": true | |
| }, | |
| "source": [ | |
| "Hey solveit :) Can you give me a short function that prints out the value of that variable we made earlier in a fun way?\n", | |
| "\n", | |
| "##### 🤖Reply🤖<!-- SOLVEIT_SEPARATOR_7f3a9b2c -->\n", | |
| "\n", | |
| "Hey there! I can see you've got the variable `a` with a value of 2.12. Here's a short, fun function for you:\n", | |
| "\n", | |
| "```python\n", | |
| "def fun_print():\n", | |
| " print(f\"🎉 The magical value of 'a' is: {a} ✨\")\n", | |
| "```\n", | |
| "\n", | |
| "This will print your variable with some fun emojis! Would you like to try running it, or would you prefer a different style of fun output?" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "e00d448e", | |
| "metadata": { | |
| "input_tokens": 48, | |
| "output_tokens": 52 | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "🎉 The magical value of 'a' is: 2.12 ✨\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "def fun_print():\n", | |
| " print(f\"🎉 The magical value of 'a' is: {a} ✨\")\n", | |
| "\n", | |
| "fun_print() # < My edit" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "09c34e8f", | |
| "metadata": { | |
| "input_tokens": 157 | |
| }, | |
| "source": [ | |
| "You can see it suggested some code - but that doesn't run or anything. We encourage you to review code from the AI to understand it for yourself. If you hover over the code block, a 'copy' option appears at the top right. There's also an option to copy the whole AI response ('Copy'), copy just the code ('Copy code') and a very useful one 'Add fenced block messages' that will add a new code message for each snippet of code the AI showed. Let's click that and see what happens:" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "d68238d2", | |
| "metadata": { | |
| "input_tokens": 78 | |
| }, | |
| "source": [ | |
| "A code message with that function appeared below the prompt. We can run it (the little play icon) or edit it first if there's something we don't like. In this case, let's edit it to actually call the function too, and see how it goes!" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "5b3871c3", | |
| "metadata": { | |
| "input_tokens": 94 | |
| }, | |
| "source": [ | |
| "The 'Default Code' toggle sets all new messages to code by default. Useful when you're primarily coding (most of us keep it on) but if you're chatting to the AI or planning things in notes you might prefer to leave it off, in which case new messages are of the same type as the previous message." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "6d033ebf", | |
| "metadata": { | |
| "input_tokens": 81 | |
| }, | |
| "source": [ | |
| "Raw messages are just like notes, but stored as `raw` cells in the exported jupyter notebook - useful when working with systems like nbdev or quarto that use raw cells to set metadata/frontmatter. You probably won't use them much unless you're working on existing projects." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "653e4eda", | |
| "metadata": { | |
| "input_tokens": 7 | |
| }, | |
| "source": [ | |
| "## AI/Prompt Tricks" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "f186b8a9", | |
| "metadata": { | |
| "input_tokens": 291 | |
| }, | |
| "source": [ | |
| "You can edit prompts without re-running them (Use Shift-Esc or the X button). And you can edit prompt **outputs** too. Together, these affordances give you control over how the conversation history appears to the AI, and are a powerful way to steer the style of future AI responses.\n", | |
| "\n", | |
| "We also have three 'modes' (learning, concise or standard) - changing mode in the dropdown changes the overall prompt for the model, as well as adding some hidden extra fake 'chat history' to steer the answer style.\n", | |
| "\n", | |
| "Learning mode (the default) is great for exploring a new topic - the AI acts a bit like a socratic teacher, helping you past difficult bits but trying to lead *you* to a solution rather than giving you tons of code directly. Standard mode has it act more like a regular helpful AI chatbot, and concise mode encourages a fastai style of coding with shorter, more condensed code that suits the interactive solveit style." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "c32a8582", | |
| "metadata": { | |
| "input_tokens": 115 | |
| }, | |
| "source": [ | |
| "We also have 'big brain mode' - activated when you hit the brain button instead of 'Submit' on a prompt. This has the model do some 'thinking' before starting it's response, and often uses an even better model than the default. Use it when you really need some extra brain power! (NB: requires MAX_THINKTOK=1024 to work atm TODO)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "7d7eb021", | |
| "metadata": { | |
| "input_tokens": 165 | |
| }, | |
| "source": [ | |
| "### Giving Context\n", | |
| "\n", | |
| "You can give the AI extra useful context in a few ways:\n", | |
| "\n", | |
| "- Paste the content in as a note (you can collapse long notes so they don't clutter up the dialog too much)\n", | |
| "- Ask the AI to search for information (more on that next)\n", | |
| "- Provide the contents of variables as additional context using a special syntax: a '$' sign followed by the name of the variable in backticks `like_this`.\n", | |
| "\n", | |
| "Here's the third one in action, pulling the text contents of a website in and feeding them to the AI directly:" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "8ffbe0ac", | |
| "metadata": { | |
| "input_tokens": 64, | |
| "output_tokens": 99 | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "# Live Reloading\n", | |
| "\n", | |
| "\n", | |
| "<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->\n", | |
| "\n", | |
| "When building your app it can be useful to view your changes in a web\n", | |
| "browser as you make them. FastHTML supports live r\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "from httpx import get as xget\n", | |
| "page_cts = xget('https://fastht.ml/docs/ref/live_reload.html.md', follow_redirects=True).text\n", | |
| "print(page_cts[:200])" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "fbbc86cd", | |
| "metadata": { | |
| "input_tokens": 37, | |
| "output_tokens": 219, | |
| "solveit_ai": true | |
| }, | |
| "source": [ | |
| "How do I set up live reloading in FastHTML? You can refer to the docs in $`page_cts`.\n", | |
| "\n", | |
| "##### 🤖Reply🤖<!-- SOLVEIT_SEPARATOR_7f3a9b2c -->\n", | |
| "\n", | |
| "Looking at the FastHTML documentation, there are two main ways to set up live reloading:\n", | |
| "\n", | |
| "**Method 1: Using FastHTMLWithLiveReload**\n", | |
| "```python\n", | |
| "from fasthtml.common import *\n", | |
| "app = FastHTMLWithLiveReload()\n", | |
| "```\n", | |
| "\n", | |
| "Then run with: `uvicorn main:app --reload`\n", | |
| "\n", | |
| "**Method 2: Using fast_app with live=True**\n", | |
| "```python\n", | |
| "from fasthtml.common import *\n", | |
| "app, rt = fast_app(live=True)\n", | |
| "serve()\n", | |
| "```\n", | |
| "\n", | |
| "Then just run: `python main.py`\n", | |
| "\n", | |
| "The second method is simpler since `serve()` handles the uvicorn setup for you. Which approach sounds more appealing to you, or would you like me to explain any of the details?" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "17081fda", | |
| "metadata": { | |
| "input_tokens": 108 | |
| }, | |
| "source": [ | |
| "You can also paste images directly in notes - AI can see images in notes and also output images like matplotlib plots. If you want to include a screenshot of the exact output of the previous cell as it appears on your screen, you can use the shortcut `Ctrl-Shift-,` as a convenience (or use your native os screenshot tool and paste it in)." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "d0464118", | |
| "metadata": { | |
| "input_tokens": 4 | |
| }, | |
| "source": [ | |
| "### Tool Use" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "c5d329a7", | |
| "metadata": { | |
| "input_tokens": 181 | |
| }, | |
| "source": [ | |
| "Solveit can also use tools - python functions that it can call to do things. The code runs in the same environment as your code. To give it a tool, we write a function with some extra documentation and pass it in with an ampersand ('&') then the tool name in backticks. For a function to work as a tool, it needs:\n", | |
| "- Types on the arguments\n", | |
| "- A docstring\n", | |
| "- Optionally, docments-style comments explaining the arguments.\n", | |
| "\n", | |
| "Here's an example: we'll define a tool that modified our variable `a` and then ask the AI to use it:" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "e8a4e343", | |
| "metadata": { | |
| "input_tokens": 52 | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def add_to_a(n:int = 100):\n", | |
| " \"adds n to the variable a and returns the result\"\n", | |
| " global a\n", | |
| " a += n\n", | |
| " return a" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "9ba66537", | |
| "metadata": { | |
| "input_tokens": 24, | |
| "output_tokens": 160, | |
| "solveit_ai": true | |
| }, | |
| "source": [ | |
| "Please use &`add_to_a` to add 1000 to it!\n", | |
| "\n", | |
| "##### 🤖Reply🤖<!-- SOLVEIT_SEPARATOR_7f3a9b2c -->\n", | |
| "\n", | |
| "\n", | |
| "<details class='tool-usage-details'>\n", | |
| "\n", | |
| "- `add_to_a({'n': 1000})`\n", | |
| " - `1003.12`\n", | |
| "\n", | |
| "</details>\n", | |
| "\n", | |
| "Perfect! I've added 1000 to your variable `a` using the tool. The variable `a` is now 1003.12 (it was 3.12 before, so 3.12 + 1000 = 1003.12).\n", | |
| "\n", | |
| "The tool worked exactly as expected - it added the specified amount and returned the new value!" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "63859af2", | |
| "metadata": { | |
| "input_tokens": 114 | |
| }, | |
| "source": [ | |
| "You can expand the details section there to see the tool call and the result. Long results are truncated and not included in the dialog context for future AI calls. This means the AI can go and do things like read a few big files, figure out the answer to a question and then provide a summary without polluting the rest of the conversation with unhelpful tool outputs. " | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "8ff57236", | |
| "metadata": { | |
| "input_tokens": 123 | |
| }, | |
| "source": [ | |
| "Solveit has a couple of built-in tools - search and read_url, which let it find information on the web. It can do more than one tool call at a time, letting it do 'agenty' multi-step workflows for you. For example, you could say \"Read http://my-library.com/llms.txt and then any links that look relevant, then tell me how to do X\"." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "53be7942", | |
| "metadata": { | |
| "input_tokens": 9 | |
| }, | |
| "source": [ | |
| "## Keyboard Shortcuts and Navigation" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "3ec7283b", | |
| "metadata": { | |
| "input_tokens": 388 | |
| }, | |
| "source": [ | |
| "You can navigate a dialog by scrolling, but to quickly find a section it's a good idea to use the 'Headings' section of the contents pane. Click on a heading to jump to that section. You can also move up and down with arrow keys if selection mode is turned on.\n", | |
| "\n", | |
| "To see a list of available shortcuts, click the (i) info button in the top right of the app. You can also hover over most buttons to see the corresponding shortcuts. We recommend turning on selection mode (currently USE_SELECTION_MODE secret set to any value, but default soon) and getting familiar with them - they save so much time!\n", | |
| "\n", | |
| "Most shortcuts use Ctrl-Shift-BLA on Windows/Linux or Cmd-Shift-BLA on mac, with the following exceptions: \n", | |
| "\n", | |
| "- All the submit and cancel shortcuts \n", | |
| "- Split is ctrl-shift-hyphen on all operating systems \n", | |
| "- Edit previous message is ctrl-shift-up on all operating systems \n", | |
| "- Force ghost text completion request is opt/alt+period\n", | |
| "\n", | |
| "A few useful ones not mentioned elsewhere:\n", | |
| "- Opt/Alt-. to trigger ghost text (even if you're in learning mode). Add Shift to trigger a smarter multi-line ghost text suggestion.\n", | |
| "- Ctrl-Shift-'-'to split a cell\n", | |
| "- TODO a few more faves?\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "7c0fc01d", | |
| "metadata": { | |
| "input_tokens": 43 | |
| }, | |
| "source": [ | |
| "## Secrets\r\n", | |
| "\r\n", | |
| "On the homepage, you can store secrets. These are inserted as environment variables, and can be accessed from your code like so:" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "9e133723", | |
| "metadata": { | |
| "input_tokens": 13, | |
| "output_tokens": 22 | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "1024\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "print(os.environ['MAX_THINKTOK'])" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "641883c8", | |
| "metadata": { | |
| "input_tokens": 172 | |
| }, | |
| "source": [ | |
| "We also use these to turn on beta features - for example, setting 'MAX_THINKTOK' to 1024 or 2048 enables thinking mode, accessed via the 'big brain' button for when you really need the AI to try a little harder! Some are important for other things too - for example, set `GITHUB_TOKEN` to your github token to enable export-to-gist functionality.\n", | |
| "\n", | |
| "NB! These secrets are visible to anyone with access to your solveit app - so keep your URL secret, and re-start if you suspect you've accidentally shared it." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "9c9d681b", | |
| "metadata": { | |
| "input_tokens": 4 | |
| }, | |
| "source": [ | |
| "## Exporting" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "2102fbee", | |
| "metadata": { | |
| "input_tokens": 328 | |
| }, | |
| "source": [ | |
| "You can export dialogs via the settings (cog icon) button in the upper right. Options are:\n", | |
| "\n", | |
| "- Notebook (.ipynb) - the full dialog serialized to a Jupyter Notebook, with prompts included in markdown cells with a special separator.\n", | |
| "- Markdown (.md) - a markdown version, with code in fenced code blocks. (TODO check)\n", | |
| "- Full script - all the code with all the text as comments\n", | |
| "- Exported code - Just the exported code messages\n", | |
| "\n", | |
| "By default, code messages aren't exported in the fourth option. But you can click the 'Will be exported?' button to toggle that. This is especially useful if the bulk of your dialog is exploration, but you also want to keep some functions you've developed for use elsewhere. In addition to getting the exported code via the export menu in settings, any dialog with exported code messages also automatically creates a .py file with the same name containing the exported code. This means you can very easily import it as a module into other dialogs. Any time you change an exported message, the .py file on disk is updated immediately." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "9e6699d0", | |
| "metadata": { | |
| "input_tokens": 28 | |
| }, | |
| "source": [ | |
| "To enable exporting to gist for easy sharing, set GITHUB_TOKEN in Secrets (see above)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "5f14abe6", | |
| "metadata": { | |
| "input_tokens": 9 | |
| }, | |
| "source": [ | |
| "## Fun with FastHTML apps" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "af8b71be", | |
| "metadata": { | |
| "input_tokens": 30 | |
| }, | |
| "source": [ | |
| "We have some extra tricks for working on FastHTML apps in solveit, with more to come." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "7578eb9f", | |
| "metadata": { | |
| "input_tokens": 31 | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "from fasthtml.common import *\r\n", | |
| "from fasthtml.jupyter import *\r\n", | |
| "from monsterui.all import *" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "974a1b1c", | |
| "metadata": { | |
| "input_tokens": 24, | |
| "output_tokens": 42 | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/markdown": [ | |
| "```html\n", | |
| "<i class=\"italic \">Hi</i>\n", | |
| "```" | |
| ], | |
| "text/plain": [ | |
| "i(('Hi',),{'class': 'italic '})" | |
| ] | |
| }, | |
| "execution_count": 13, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "# We can make and view fasttags to build HTML:\r\n", | |
| "I(\"Hi\")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "e277a1aa", | |
| "metadata": { | |
| "input_tokens": 22 | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "# TO make them render by default, we can use\r\n", | |
| "render_ft()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "175bf726", | |
| "metadata": { | |
| "input_tokens": 9, | |
| "output_tokens": 48 | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/markdown": [ | |
| "<div>\n", | |
| "<i class=\"italic \">Hi - rendered</i><script>if (window.htmx) htmx.process(document.body)</script></div>\n" | |
| ], | |
| "text/plain": [ | |
| "i(('Hi - rendered',),{'class': 'italic '})" | |
| ] | |
| }, | |
| "execution_count": 15, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "I(\"Hi - rendered\")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "c81fcd70", | |
| "metadata": { | |
| "input_tokens": 21, | |
| "output_tokens": 63 | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/markdown": [ | |
| "<div>\n", | |
| " <div style=\"color:red\">\n", | |
| "<a href=\"/foo\">Hi</a> </div>\n", | |
| "<script>if (window.htmx) htmx.process(document.body)</script></div>\n" | |
| ], | |
| "text/plain": [ | |
| "div((a(('Hi',),{'href': '/foo'}),),{'style': 'color:red'})" | |
| ] | |
| }, | |
| "execution_count": 16, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "Div(A(\"Hi\", href=\"/foo\"), style='color:red')" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "6eceb548", | |
| "metadata": { | |
| "input_tokens": 85 | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "# We can start a server:\n", | |
| "if 'srv' not in globals() or not srv: # Checking it doesn't already exists for if we 'run all' - not always needed\n", | |
| " app = FastHTML()\n", | |
| " rt = app.route\n", | |
| " srv = nb_serve(app)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "432927af", | |
| "metadata": { | |
| "input_tokens": 7, | |
| "output_tokens": 138 | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "Help on function nb_serve in module fasthtml.jupyter:\n", | |
| "\n", | |
| "nb_serve(app, log_level='error', port=8000, host='0.0.0.0', **kwargs)\n", | |
| " Start a Jupyter compatible uvicorn server with ASGI `app` on `port` with `log_level`\n", | |
| "\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "help(nb_serve)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "8f2bcbd0", | |
| "metadata": { | |
| "input_tokens": 18 | |
| }, | |
| "source": [ | |
| "Now we can add routes, complete with HTMX functionality!" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "b2831089", | |
| "metadata": { | |
| "input_tokens": 91, | |
| "output_tokens": 79 | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/markdown": [ | |
| "<div>\n", | |
| " <h1 hx-get=\"/bar\" hx-swap=\"outerHTML\" class=\"uk-h1 \" style=\"color:red\">Hello</h1>\n", | |
| "<script>if (window.htmx) htmx.process(document.body)</script></div>\n" | |
| ], | |
| "text/plain": [ | |
| "h1(('Hello',),{'hx-get': <fasthtml.core._mk_locfunc.<locals>._lf object at 0x7f032a93d220>, 'hx-swap': 'outerHTML', 'class': 'uk-h1 ', 'style': 'color:red'})" | |
| ] | |
| }, | |
| "execution_count": 21, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "@rt\n", | |
| "def foo():\n", | |
| " return H1(\"Hello\", hx_get=bar, hx_swap='outerHTML', style='color:red')\n", | |
| "@rt\n", | |
| "def bar():\n", | |
| " return H1(\"World\", hx_get=foo, hx_swap='outerHTML', style='color:blue')\n", | |
| "\n", | |
| "foo()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "7259352e", | |
| "metadata": { | |
| "input_tokens": 261 | |
| }, | |
| "source": [ | |
| "How does this work?!?! Any route solveit doesn't recognize gets routed to port 8000 on localhost, which is where nb_serve runs it's server. You can open your-solveit-url.com/foo and see your app there too! Or pop out the output with 'Open in new tab' and see it in a new window, where it will update any time you edit the code. \n", | |
| "\n", | |
| "We have monsterui styles in solveit - so those are on by default when viewing things with render_ft(). If you want your app to look the same when you open the routes directly, include the monsterui headers with a theme (TODO show how). The only constraint is that you can't write your `index()` route on `/` - but for all the other prototyping etc you can develop right in solveit! More tutorials on this hopefully out at some point :)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "97e70d96", | |
| "metadata": { | |
| "input_tokens": 4 | |
| }, | |
| "source": [ | |
| "## Dialoghelper" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "3b01ee44", | |
| "metadata": { | |
| "input_tokens": 7 | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "from dialoghelper import *" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "5bfc4d42", | |
| "metadata": { | |
| "input_tokens": 67 | |
| }, | |
| "source": [ | |
| "The dialoghelper module has some useful functions that both we and solveit can utilize to modify the current dialog. For convenience, it has a method to print these tools in a note, giving solveit access to them too:" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "622a8d6e", | |
| "metadata": { | |
| "input_tokens": 24 | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "# tool_info() # Uncomment and run to add a message like the one below" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "9b65ddbd", | |
| "metadata": { | |
| "input_tokens": 270 | |
| }, | |
| "source": [ | |
| "Tools available from `dialoghelper`:\n", | |
| "\n", | |
| "- &`curr_dialog`: Get the current dialog info.\n", | |
| "- &`msg_idx`: Get absolute index of message in dialog.\n", | |
| "- &`add_html`: Send HTML to the browser to be swapped into the DOM using hx-swap-oob.\n", | |
| "- &`find_msg_id`: Get the current message id.\n", | |
| "- &`find_msgs`: Find messages in current specific dialog that contain the given information.\n", | |
| " - (solveit can often get this id directly from its context, and will not need to use this if the required information is already available to it.)\n", | |
| "- &`read_msg`: Get the message indexed in the current dialog.\n", | |
| "- &`del_msg`: Delete a message from the dialog.\n", | |
| "- &`add_msg`: Add/update a message to the queue to show after code execution completes.\n", | |
| "- &`update_msg`: Update an existing message." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "123775fa", | |
| "metadata": { | |
| "input_tokens": 25, | |
| "output_tokens": 190, | |
| "solveit_ai": true | |
| }, | |
| "source": [ | |
| "Can you use some of the tools above to add a friendly message below this one?\n", | |
| "\n", | |
| "##### 🤖Reply🤖<!-- SOLVEIT_SEPARATOR_7f3a9b2c -->\n", | |
| "\n", | |
| "\n", | |
| "<details class='tool-usage-details'>\n", | |
| "\n", | |
| "- `add_msg({'content': \"Hello there! 👋 This is a friendly message that was added using the `add_msg` tool from dialoghelper. Hope you're enjoying exploring solveit!\", 'msg_type': 'note'})`\n", | |
| " - `'_2fd735b4'`\n", | |
| "\n", | |
| "</details>\n", | |
| "\n", | |
| "Perfect! I've added a friendly note message right below your prompt using the `add_msg` tool. The message will appear once this code execution completes. The tool returned the message ID `_2fd735b4` for the new message." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "2fd735b4", | |
| "metadata": { | |
| "input_tokens": 46 | |
| }, | |
| "source": [ | |
| "Hello there! 👋 This is a friendly message that was added using the `add_msg` tool from dialoghelper. Hope you're enjoying exploring solveit!" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "f9e49666", | |
| "metadata": { | |
| "input_tokens": 37 | |
| }, | |
| "source": [ | |
| "If programatically modifying your dialogs is interesting, spend a bit of time experimenting with those functions and see what you can do :)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "b153dfe3", | |
| "metadata": { | |
| "input_tokens": 45 | |
| }, | |
| "source": [ | |
| "There's also dialoghelper.experimental, where we're trying out things like enabling screen sharing so that solveit can see other applications and help you with those too." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "0f181c73", | |
| "metadata": { | |
| "input_tokens": 15 | |
| }, | |
| "source": [ | |
| "## Coding Productively in Solveit (TODO)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "849a7928", | |
| "metadata": { | |
| "input_tokens": 118 | |
| }, | |
| "source": [ | |
| "Solveit works best when you thoughtfully work through problems one small piece at a time - as taught in the solveit course. Use the AI to help when you're stuck, but try to understand all the code. When in doubt, break it down, ask more questions and dig in further! We find that in general this feels slower in the short term and makes you faster in the long run :)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "d54a0848", | |
| "metadata": { | |
| "input_tokens": 216 | |
| }, | |
| "source": [ | |
| "You can execute code messages in any order - we love this for exploring ideas, but if it's tripping you up or you want to make sure your dialog will run consistently, use 'restart' then 'run all' frequently to make sure you're in a clean state. If you've got long-running operations (like scraping, or sending lots of things off to AI) it's useful to try them out on one sample first, then tidy them into a function and run them across all your examples. For re-running, I'll sometimes ask solveit to store any hard-earned data and check if it exists before re-running expensive code - this kind of simple edit is right up it's alley, and can save a bunch of time. " | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "a4fbb2c9", | |
| "metadata": { | |
| "input_tokens": 145 | |
| }, | |
| "source": [ | |
| "Using ghost text (the AI autocomplete) can be helpful, but we find it can also be distracting or let you write bad code. That's why it's off in learning mode even if you have 'USE_GHOST' set. One tip though: you *can* summon it explicitly with the keyboard shortcut `Opt/Alt+.` - using it thoughfully to get quick completions for APIs you don't know well or boilerplate you're happy to skim is sometimes the best of both worlds." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "e0473b9f", | |
| "metadata": { | |
| "input_tokens": 379 | |
| }, | |
| "source": [ | |
| "## Managing Dialogs\n", | |
| "\n", | |
| "As mentioned, dialogs serialize to .ipynb files. You can re-name them by clicking on the name at the top of the screen, including to add a folder (e.g. rename this to `my_dialogs/wos` to save it in a `my_dialogs` folder). This makes it easy to share or save your work. Apart from exporting to gists, you can now directly store your dialogs in git. You can use the terminal to clone existing repositories from GitHub or create a new one for your work.\n", | |
| "\n", | |
| "Each time you open a dialog from the main screen, the 'kernel' is reset.\n", | |
| "\n", | |
| "Multiple people can open a given dialog - you'll notice that messages added in any open tab show up in all copies of solveit pointing at that URL. This is great for collaborating with someone (as long as you trust them not to abuse your secrets etc!)\n", | |
| "\n", | |
| "At the moment, this also means that opening multiple dialogs is a recipe for disaster, as changes from any that aren't the currently active 'current dialog' might easily be lost, and messages showing up in all open tabs appear confusing. We hope to fix this soon, but for now **do not keep more than one dialog open at a time**." | |
| ] | |
| } | |
| ], | |
| "metadata": { | |
| "solveit_dialog_mode": "learning", | |
| "solveit_ver": 2 | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 5 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment