{ "cells": [ { "metadata": {}, "cell_type": "markdown", "source": [ "# Attachments\n", "\n", "## Setting Up the Environment\n", "\n", "Before diving into the code, we make sure our Kotlin Notebook is ready.\n", "Here we load the latest descriptors and enable the **Koog** library,\n", "which provides a clean API for working with AI model providers.\n" ] }, { "metadata": { "collapsed": true, "ExecuteTime": { "end_time": "2025-08-15T10:27:17.953537Z", "start_time": "2025-08-15T10:27:17.766921Z" } }, "cell_type": "code", "source": [ "// Loads the latest descriptors and activates Koog integration for Kotlin Notebook.\n", "// This makes Koog DSL types and executors available in further cells.\n", "%useLatestDescriptors\n", "%use koog" ], "outputs": [], "execution_count": 9 }, { "metadata": {}, "cell_type": "markdown", "source": [ "## Configuring API Keys\n", "\n", "We read the API key from an environment variable. This keeps secrets out of the notebook file and lets you\n", "switch providers. You can set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY`." ] }, { "metadata": { "ExecuteTime": { "end_time": "2025-08-15T08:59:12.987077Z", "start_time": "2025-08-15T08:59:12.940253Z" } }, "cell_type": "code", "source": "val apiKey = System.getenv(\"OPENAI_API_KEY\") // or ANTHROPIC_API_KEY, or GEMINI_API_KEY", "outputs": [], "execution_count": 2 }, { "metadata": {}, "cell_type": "markdown", "source": [ "## Creating a Simple OpenAI Executor\n", "\n", "The executor encapsulates authentication, base URLs, and correct defaults. Here we use a simple OpenAI executor,\n", "but you can swap it for Anthropic or Gemini without changing the rest of the code." ] }, { "metadata": { "ExecuteTime": { "end_time": "2025-08-15T09:00:40.093638Z", "start_time": "2025-08-15T09:00:40.061716Z" } }, "cell_type": "code", "source": [ "// --- Provider selection ---\n", "// For OpenAI-compatible models. Alternatives include:\n", "// val executor = simpleAnthropicExecutor(System.getenv(\"ANTHROPIC_API_KEY\"))\n", "// val executor = simpleGeminiExecutor(System.getenv(\"GEMINI_API_KEY\"))\n", "// All executors expose the same high‑level API.\n", "val executor = simpleOpenAIExecutor(apiKey)" ], "outputs": [], "execution_count": 5 }, { "metadata": {}, "cell_type": "markdown", "source": [ "Koog’s prompt DSL lets you add **structured Markdown** and **attachments**.\n", "In this cell we build a prompt that asks the model to generate a short, blog‑style \"content card\" and\n", "we attach two images from the local `images/` directory." ] }, { "metadata": { "ExecuteTime": { "end_time": "2025-08-15T09:00:08.711759Z", "start_time": "2025-08-15T09:00:08.574211Z" } }, "cell_type": "code", "source": [ "import ai.koog.prompt.markdown.markdown\n", "import kotlinx.io.files.Path\n", "\n", "val prompt = prompt(\"images-prompt\") {\n", " system(\"You are professional assistant that can write cool and funny descriptions for Instagram posts.\")\n", "\n", " user {\n", " markdown {\n", " +\"I want to create a new post on Instagram.\"\n", " br()\n", " +\"Can you write something creative under my instagram post with the following photos?\"\n", " br()\n", " h2(\"Requirements\")\n", " bulleted {\n", " item(\"It must be very funny and creative\")\n", " item(\"It must increase my chance of becoming an ultra-famous blogger!!!!\")\n", " item(\"It not contain explicit content, harassment or bullying\")\n", " item(\"It must be a short catching phrase\")\n", " item(\"You must include relevant hashtags that would increase the visibility of my post\")\n", " }\n", " }\n", "\n", " attachments {\n", " image(Path(\"images/kodee-loving.png\"))\n", " image(Path(\"images/kodee-electrified.png\"))\n", " }\n", " }\n", "}" ], "outputs": [], "execution_count": 4 }, { "metadata": {}, "cell_type": "markdown", "source": [ "## Execute and Inspect the Response\n", "\n", "We run the prompt against `gpt-4.1`, collect the first message, and print its content.\n", "If you want streaming, swap to a streaming API in Koog; for tool use, pass your tool list instead of `emptyList()`.\n", "\n", "> Troubleshooting:\n", "> * **401/403** — check your API key/environment variable.\n", "> * **File not found** — verify the `images/` paths.\n", "> * **Rate limits** — add minimal retry/backoff around the call if needed." ] }, { "metadata": { "ExecuteTime": { "end_time": "2025-08-15T10:17:41.707125Z", "start_time": "2025-08-15T10:17:38.033937Z" } }, "cell_type": "code", "source": [ "import kotlinx.coroutines.runBlocking\n", "\n", "runBlocking {\n", " val response = executor.execute(prompt = prompt, model = OpenAIModels.Chat.GPT4_1, tools = emptyList()).first()\n", " println(response.content)\n", "}" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Caption:\n", "Running on cuteness and extra giggle power! Warning: Side effects may include heart-thief vibes and spontaneous dance parties. 💜🤖💃\n", "\n", "Hashtags: \n", "#ViralVibes #UltraFamousBlogger #CutieAlert #QuirkyContent #InstaFun #SpreadTheLove #DancingIntoFame #RobotLife #InstaFamous #FeedGoals\n" ] } ], "execution_count": 8 }, { "metadata": { "ExecuteTime": { "end_time": "2025-08-15T11:05:16.999242Z", "start_time": "2025-08-15T11:05:13.073152Z" } }, "cell_type": "code", "source": [ "runBlocking {\n", " val response = executor.executeStreaming(prompt = prompt, model = OpenAIModels.Chat.GPT4_1)\n", " response.collect { print(it) }\n", "}" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Caption: \n", "Running on good vibes & wi-fi only! 🤖💜 Drop a like if you feel the circuit-joy! #BlogBotInTheWild #HeartDeliveryService #DancingWithWiFi #UltraFamousBlogger #MoreFunThanYourAICat #ViralVibes #InstaFun #BeepBoopFamous" ] } ], "execution_count": 10 } ], "metadata": { "kernelspec": { "display_name": "Kotlin", "language": "kotlin", "name": "kotlin" }, "language_info": { "name": "kotlin", "version": "2.2.20-Beta2", "mimetype": "text/x-kotlin", "file_extension": ".kt", "pygments_lexer": "kotlin", "codemirror_mode": "text/x-kotlin", "nbconvert_exporter": "" } }, "nbformat": 4, "nbformat_minor": 0 }